3 * Copyright (c) 2008 Sascha Sommer (saschasommer@freenet.de)
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * @author Sascha Sommer (saschasommer@freenet.de)
26 * For more information regarding the RL2 file format, visit:
27 * http://wiki.multimedia.cx/index.php?title=RL2
30 * 2 byte le initial drawing offset within 320x200 viewport
31 * 4 byte le number of used colors
32 * 256 * 3 bytes rgb palette
33 * optional background_frame
38 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr, palette
40 #define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
41 #define RLV2_TAG MKBETAG('R', 'L', 'V', '2')
42 #define RLV3_TAG MKBETAG('R', 'L', 'V', '3')
44 typedef struct Rl2DemuxContext
{
45 unsigned int index_pos
[2]; ///< indices in the sample tables
50 * check if the file is in rl2 format
51 * @param p probe buffer
52 * @return 0 when the probe buffer does not contain rl2 data, > 0 otherwise
54 static int rl2_probe(AVProbeData
*p
)
57 if(AV_RB32(&p
->buf
[0]) != FORM_TAG
)
60 if(AV_RB32(&p
->buf
[8]) != RLV2_TAG
&&
61 AV_RB32(&p
->buf
[8]) != RLV3_TAG
)
64 return AVPROBE_SCORE_MAX
;
68 * read rl2 header data and setup the avstreams
69 * @param s demuxer context
70 * @param ap format parameters
71 * @return 0 on success, AVERROR otherwise
73 static av_cold
int rl2_read_header(AVFormatContext
*s
,
74 AVFormatParameters
*ap
)
76 ByteIOContext
*pb
= s
->pb
;
78 unsigned int frame_count
;
79 unsigned int audio_frame_counter
= 0;
80 unsigned int video_frame_counter
= 0;
81 unsigned int back_size
;
83 unsigned short encoding_method
;
84 unsigned short sound_rate
;
86 unsigned short channels
;
87 unsigned short def_sound_size
;
88 unsigned int signature
;
89 unsigned int pts_den
= 11025; /* video only case */
90 unsigned int pts_num
= 1103;
91 unsigned int* chunk_offset
= NULL
;
92 int* chunk_size
= NULL
;
93 int* audio_size
= NULL
;
97 url_fskip(pb
,4); /* skip FORM tag */
98 back_size
= get_le32(pb
); /** get size of the background frame */
99 signature
= get_be32(pb
);
100 data_size
= get_be32(pb
);
101 frame_count
= get_le32(pb
);
103 /* disallow back_sizes and frame_counts that may lead to overflows later */
104 if(back_size
> INT_MAX
/2 || frame_count
> INT_MAX
/ sizeof(uint32_t))
105 return AVERROR_INVALIDDATA
;
107 encoding_method
= get_le16(pb
);
108 sound_rate
= get_le16(pb
);
110 channels
= get_le16(pb
);
111 def_sound_size
= get_le16(pb
);
113 /** setup video stream */
114 st
= av_new_stream(s
, 0);
116 return AVERROR(ENOMEM
);
118 st
->codec
->codec_type
= CODEC_TYPE_VIDEO
;
119 st
->codec
->codec_id
= CODEC_ID_RL2
;
120 st
->codec
->codec_tag
= 0; /* no fourcc */
121 st
->codec
->width
= 320;
122 st
->codec
->height
= 200;
124 /** allocate and fill extradata */
125 st
->codec
->extradata_size
= EXTRADATA1_SIZE
;
127 if(signature
== RLV3_TAG
&& back_size
> 0)
128 st
->codec
->extradata_size
+= back_size
;
130 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+
131 FF_INPUT_BUFFER_PADDING_SIZE
);
132 if(!st
->codec
->extradata
)
133 return AVERROR(ENOMEM
);
135 if(get_buffer(pb
,st
->codec
->extradata
,st
->codec
->extradata_size
) !=
136 st
->codec
->extradata_size
)
139 /** setup audio stream if present */
141 pts_num
= def_sound_size
;
144 st
= av_new_stream(s
, 0);
146 return AVERROR(ENOMEM
);
147 st
->codec
->codec_type
= CODEC_TYPE_AUDIO
;
148 st
->codec
->codec_id
= CODEC_ID_PCM_U8
;
149 st
->codec
->codec_tag
= 1;
150 st
->codec
->channels
= channels
;
151 st
->codec
->bits_per_sample
= 8;
152 st
->codec
->sample_rate
= rate
;
153 st
->codec
->bit_rate
= st
->codec
->channels
* st
->codec
->sample_rate
*
154 st
->codec
->bits_per_sample
;
155 st
->codec
->block_align
= st
->codec
->channels
*
156 st
->codec
->bits_per_sample
/ 8;
157 av_set_pts_info(st
,32,1,rate
);
160 av_set_pts_info(s
->streams
[0], 32, pts_num
, pts_den
);
162 chunk_size
= av_malloc(frame_count
* sizeof(uint32_t));
163 audio_size
= av_malloc(frame_count
* sizeof(uint32_t));
164 chunk_offset
= av_malloc(frame_count
* sizeof(uint32_t));
166 if(!chunk_size
|| !audio_size
|| !chunk_offset
){
169 av_free(chunk_offset
);
170 return AVERROR(ENOMEM
);
173 /** read offset and size tables */
174 for(i
=0; i
< frame_count
;i
++)
175 chunk_size
[i
] = get_le32(pb
);
176 for(i
=0; i
< frame_count
;i
++)
177 chunk_offset
[i
] = get_le32(pb
);
178 for(i
=0; i
< frame_count
;i
++)
179 audio_size
[i
] = get_le32(pb
) & 0xFFFF;
181 /** build the sample index */
182 for(i
=0;i
<frame_count
;i
++){
183 if(chunk_size
[i
] < 0 || audio_size
[i
] > chunk_size
[i
]){
184 ret
= AVERROR_INVALIDDATA
;
188 if(sound_rate
&& audio_size
[i
]){
189 av_add_index_entry(s
->streams
[1], chunk_offset
[i
],
190 audio_frame_counter
,audio_size
[i
], 0, AVINDEX_KEYFRAME
);
191 audio_frame_counter
+= audio_size
[i
] / channels
;
193 av_add_index_entry(s
->streams
[0], chunk_offset
[i
] + audio_size
[i
],
194 video_frame_counter
,chunk_size
[i
]-audio_size
[i
],0,AVINDEX_KEYFRAME
);
195 ++video_frame_counter
;
201 av_free(chunk_offset
);
207 * read a single audio or video packet
208 * @param s demuxer context
209 * @param pkt the packet to be filled
210 * @return 0 on success, AVERROR otherwise
212 static int rl2_read_packet(AVFormatContext
*s
,
215 Rl2DemuxContext
*rl2
= s
->priv_data
;
216 ByteIOContext
*pb
= s
->pb
;
217 AVIndexEntry
*sample
= NULL
;
221 int64_t pos
= INT64_MAX
;
223 /** check if there is a valid video or audio entry that can be used */
224 for(i
=0; i
<s
->nb_streams
; i
++){
225 if(rl2
->index_pos
[i
] < s
->streams
[i
]->nb_index_entries
226 && s
->streams
[i
]->index_entries
[ rl2
->index_pos
[i
] ].pos
< pos
){
227 sample
= &s
->streams
[i
]->index_entries
[ rl2
->index_pos
[i
] ];
236 ++rl2
->index_pos
[stream_id
];
238 /** position the stream (will probably be there anyway) */
239 url_fseek(pb
, sample
->pos
, SEEK_SET
);
241 /** fill the packet */
242 ret
= av_get_packet(pb
, pkt
, sample
->size
);
243 if(ret
!= sample
->size
){
248 pkt
->stream_index
= stream_id
;
249 pkt
->pts
= sample
->timestamp
;
255 * seek to a new timestamp
256 * @param s demuxer context
257 * @param stream_index index of the stream that should be seeked
258 * @param timestamp wanted timestamp
259 * @param flags direction and seeking mode
260 * @return 0 on success, -1 otherwise
262 static int rl2_read_seek(AVFormatContext
*s
, int stream_index
, int64_t timestamp
, int flags
)
264 AVStream
*st
= s
->streams
[stream_index
];
265 Rl2DemuxContext
*rl2
= s
->priv_data
;
267 int index
= av_index_search_timestamp(st
, timestamp
, flags
);
271 rl2
->index_pos
[stream_index
] = index
;
272 timestamp
= st
->index_entries
[index
].timestamp
;
274 for(i
=0; i
< s
->nb_streams
; i
++){
275 AVStream
*st2
= s
->streams
[i
];
276 index
= av_index_search_timestamp(st2
,
277 av_rescale_q(timestamp
, st
->time_base
, st2
->time_base
),
278 flags
| AVSEEK_FLAG_BACKWARD
);
283 rl2
->index_pos
[i
] = index
;
289 AVInputFormat rl2_demuxer
= {
292 sizeof(Rl2DemuxContext
),