1 | /*
|
---|
2 | * AVI decoder.
|
---|
3 | * Copyright (c) 2001 Fabrice Bellard.
|
---|
4 | *
|
---|
5 | * This library is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU Lesser General Public
|
---|
7 | * License as published by the Free Software Foundation; either
|
---|
8 | * version 2 of the License, or (at your option) any later version.
|
---|
9 | *
|
---|
10 | * This library is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
13 | * Lesser General Public License for more details.
|
---|
14 | *
|
---|
15 | * You should have received a copy of the GNU Lesser General Public
|
---|
16 | * License along with this library; if not, write to the Free Software
|
---|
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
18 | */
|
---|
19 | #include "avformat.h"
|
---|
20 | #include "avi.h"
|
---|
21 | #include "dv.h"
|
---|
22 |
|
---|
23 | #undef NDEBUG
|
---|
24 | #include <assert.h>
|
---|
25 |
|
---|
26 | //#define DEBUG
|
---|
27 | //#define DEBUG_SEEK
|
---|
28 |
|
---|
29 | typedef struct AVIStream {
|
---|
30 | int64_t frame_offset; /* current frame (video) or byte (audio) counter
|
---|
31 | (used to compute the pts) */
|
---|
32 | int remaining;
|
---|
33 | int packet_size;
|
---|
34 |
|
---|
35 | int scale;
|
---|
36 | int rate;
|
---|
37 | int sample_size; /* size of one sample (or packet) (in the rate/scale sense) in bytes */
|
---|
38 |
|
---|
39 | int64_t cum_len; /* temporary storage (used during seek) */
|
---|
40 |
|
---|
41 | int prefix; ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b'
|
---|
42 | int prefix_count;
|
---|
43 | } AVIStream;
|
---|
44 |
|
---|
45 | typedef struct {
|
---|
46 | int64_t riff_end;
|
---|
47 | int64_t movi_end;
|
---|
48 | offset_t movi_list;
|
---|
49 | int index_loaded;
|
---|
50 | int is_odml;
|
---|
51 | int non_interleaved;
|
---|
52 | int stream_index;
|
---|
53 | DVDemuxContext* dv_demux;
|
---|
54 | } AVIContext;
|
---|
55 |
|
---|
56 | static int avi_load_index(AVFormatContext *s);
|
---|
57 | static int guess_ni_flag(AVFormatContext *s);
|
---|
58 |
|
---|
59 | #ifdef DEBUG
|
---|
60 | static void print_tag(const char *str, unsigned int tag, int size)
|
---|
61 | {
|
---|
62 | printf("%s: tag=%c%c%c%c size=0x%x\n",
|
---|
63 | str, tag & 0xff,
|
---|
64 | (tag >> 8) & 0xff,
|
---|
65 | (tag >> 16) & 0xff,
|
---|
66 | (tag >> 24) & 0xff,
|
---|
67 | size);
|
---|
68 | }
|
---|
69 | #endif
|
---|
70 |
|
---|
71 | static int get_riff(AVIContext *avi, ByteIOContext *pb)
|
---|
72 | {
|
---|
73 | uint32_t tag;
|
---|
74 | /* check RIFF header */
|
---|
75 | tag = get_le32(pb);
|
---|
76 |
|
---|
77 | if (tag != MKTAG('R', 'I', 'F', 'F'))
|
---|
78 | return -1;
|
---|
79 | avi->riff_end = get_le32(pb); /* RIFF chunk size */
|
---|
80 | avi->riff_end += url_ftell(pb); /* RIFF chunk end */
|
---|
81 | tag = get_le32(pb);
|
---|
82 | if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X'))
|
---|
83 | return -1;
|
---|
84 |
|
---|
85 | return 0;
|
---|
86 | }
|
---|
87 |
|
---|
88 | static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
|
---|
89 | AVIContext *avi = s->priv_data;
|
---|
90 | ByteIOContext *pb = &s->pb;
|
---|
91 | int longs_pre_entry= get_le16(pb);
|
---|
92 | int index_sub_type = get_byte(pb);
|
---|
93 | int index_type = get_byte(pb);
|
---|
94 | int entries_in_use = get_le32(pb);
|
---|
95 | int chunk_id = get_le32(pb);
|
---|
96 | int64_t base = get_le64(pb);
|
---|
97 | int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0');
|
---|
98 | AVStream *st;
|
---|
99 | AVIStream *ast;
|
---|
100 | int i;
|
---|
101 | int64_t last_pos= -1;
|
---|
102 |
|
---|
103 | // av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%Ld\n",
|
---|
104 | // longs_pre_entry,index_type, entries_in_use, chunk_id, base);
|
---|
105 |
|
---|
106 | if(stream_id > s->nb_streams || stream_id < 0)
|
---|
107 | return -1;
|
---|
108 | st= s->streams[stream_id];
|
---|
109 | ast = st->priv_data;
|
---|
110 |
|
---|
111 | if(index_sub_type)
|
---|
112 | return -1;
|
---|
113 |
|
---|
114 | get_le32(pb);
|
---|
115 |
|
---|
116 | if(index_type && longs_pre_entry != 2)
|
---|
117 | return -1;
|
---|
118 | if(index_type>1)
|
---|
119 | return -1;
|
---|
120 |
|
---|
121 | for(i=0; i<entries_in_use; i++){
|
---|
122 | if(index_type){
|
---|
123 | int64_t pos= get_le32(pb) + base - 8;
|
---|
124 | int len = get_le32(pb);
|
---|
125 | int key= len >= 0;
|
---|
126 | len &= 0x7FFFFFFF;
|
---|
127 |
|
---|
128 | //av_log(s, AV_LOG_ERROR, "pos:%Ld, len:%X\n", pos, len);
|
---|
129 | if(last_pos == pos || pos == base - 8)
|
---|
130 | avi->non_interleaved= 1;
|
---|
131 | else
|
---|
132 | av_add_index_entry(st, pos, ast->cum_len, len, 0, key ? AVINDEX_KEYFRAME : 0);
|
---|
133 |
|
---|
134 | if(ast->sample_size)
|
---|
135 | ast->cum_len += len / ast->sample_size;
|
---|
136 | else
|
---|
137 | ast->cum_len ++;
|
---|
138 | last_pos= pos;
|
---|
139 | }else{
|
---|
140 | int64_t offset, pos;
|
---|
141 | int duration;
|
---|
142 | offset = get_le64(pb);
|
---|
143 | get_le32(pb); /* size */
|
---|
144 | duration = get_le32(pb);
|
---|
145 | pos = url_ftell(pb);
|
---|
146 |
|
---|
147 | url_fseek(pb, offset+8, SEEK_SET);
|
---|
148 | read_braindead_odml_indx(s, frame_num);
|
---|
149 | frame_num += duration;
|
---|
150 |
|
---|
151 | url_fseek(pb, pos, SEEK_SET);
|
---|
152 | }
|
---|
153 | }
|
---|
154 | return 0;
|
---|
155 | }
|
---|
156 |
|
---|
157 | static void clean_index(AVFormatContext *s){
|
---|
158 | int i, j;
|
---|
159 |
|
---|
160 | for(i=0; i<s->nb_streams; i++){
|
---|
161 | AVStream *st = s->streams[i];
|
---|
162 | AVIStream *ast = st->priv_data;
|
---|
163 | int n= st->nb_index_entries;
|
---|
164 | int max= ast->sample_size;
|
---|
165 | int64_t pos, size, ts;
|
---|
166 |
|
---|
167 | if(n != 1 || ast->sample_size==0)
|
---|
168 | continue;
|
---|
169 |
|
---|
170 | while(max < 1024) max+=max;
|
---|
171 |
|
---|
172 | pos= st->index_entries[0].pos;
|
---|
173 | size= st->index_entries[0].size;
|
---|
174 | ts= st->index_entries[0].timestamp;
|
---|
175 |
|
---|
176 | for(j=0; j<size; j+=max){
|
---|
177 | av_add_index_entry(st, pos+j, ts + j/ast->sample_size, FFMIN(max, size-j), 0, AVINDEX_KEYFRAME);
|
---|
178 | }
|
---|
179 | }
|
---|
180 | }
|
---|
181 |
|
---|
182 | static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
---|
183 | {
|
---|
184 | AVIContext *avi = s->priv_data;
|
---|
185 | ByteIOContext *pb = &s->pb;
|
---|
186 | uint32_t tag, tag1, handler;
|
---|
187 | int codec_type, stream_index, frame_period, bit_rate;
|
---|
188 | unsigned int size, nb_frames;
|
---|
189 | int i, n;
|
---|
190 | AVStream *st;
|
---|
191 | AVIStream *ast = NULL;
|
---|
192 | int xan_video = 0; /* hack to support Xan A/V */
|
---|
193 |
|
---|
194 | avi->stream_index= -1;
|
---|
195 |
|
---|
196 | if (get_riff(avi, pb) < 0)
|
---|
197 | return -1;
|
---|
198 |
|
---|
199 | /* first list tag */
|
---|
200 | stream_index = -1;
|
---|
201 | codec_type = -1;
|
---|
202 | frame_period = 0;
|
---|
203 | for(;;) {
|
---|
204 | if (url_feof(pb))
|
---|
205 | goto fail;
|
---|
206 | tag = get_le32(pb);
|
---|
207 | size = get_le32(pb);
|
---|
208 | #ifdef DEBUG
|
---|
209 | print_tag("tag", tag, size);
|
---|
210 | #endif
|
---|
211 |
|
---|
212 | switch(tag) {
|
---|
213 | case MKTAG('L', 'I', 'S', 'T'):
|
---|
214 | /* ignored, except when start of video packets */
|
---|
215 | tag1 = get_le32(pb);
|
---|
216 | #ifdef DEBUG
|
---|
217 | print_tag("list", tag1, 0);
|
---|
218 | #endif
|
---|
219 | if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
|
---|
220 | avi->movi_list = url_ftell(pb) - 4;
|
---|
221 | if(size) avi->movi_end = avi->movi_list + size;
|
---|
222 | else avi->movi_end = url_fsize(pb);
|
---|
223 | #ifdef DEBUG
|
---|
224 | printf("movi end=%Lx\n", avi->movi_end);
|
---|
225 | #endif
|
---|
226 | goto end_of_header;
|
---|
227 | }
|
---|
228 | break;
|
---|
229 | case MKTAG('d', 'm', 'l', 'h'):
|
---|
230 | avi->is_odml = 1;
|
---|
231 | url_fskip(pb, size + (size & 1));
|
---|
232 | break;
|
---|
233 | case MKTAG('a', 'v', 'i', 'h'):
|
---|
234 | /* avi header */
|
---|
235 | /* using frame_period is bad idea */
|
---|
236 | frame_period = get_le32(pb);
|
---|
237 | bit_rate = get_le32(pb) * 8;
|
---|
238 | get_le32(pb);
|
---|
239 | avi->non_interleaved |= get_le32(pb) & AVIF_MUSTUSEINDEX;
|
---|
240 |
|
---|
241 | url_fskip(pb, 2 * 4);
|
---|
242 | n = get_le32(pb);
|
---|
243 | for(i=0;i<n;i++) {
|
---|
244 | AVIStream *ast;
|
---|
245 | st = av_new_stream(s, i);
|
---|
246 | if (!st)
|
---|
247 | goto fail;
|
---|
248 |
|
---|
249 | ast = av_mallocz(sizeof(AVIStream));
|
---|
250 | if (!ast)
|
---|
251 | goto fail;
|
---|
252 | st->priv_data = ast;
|
---|
253 | }
|
---|
254 | url_fskip(pb, size - 7 * 4);
|
---|
255 | break;
|
---|
256 | case MKTAG('s', 't', 'r', 'h'):
|
---|
257 | /* stream header */
|
---|
258 | stream_index++;
|
---|
259 | tag1 = get_le32(pb);
|
---|
260 | handler = get_le32(pb); /* codec tag */
|
---|
261 | #ifdef DEBUG
|
---|
262 | print_tag("strh", tag1, -1);
|
---|
263 | #endif
|
---|
264 | if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){
|
---|
265 | /*
|
---|
266 | * After some consideration -- I don't think we
|
---|
267 | * have to support anything but DV in a type1 AVIs.
|
---|
268 | */
|
---|
269 | if (s->nb_streams != 1)
|
---|
270 | goto fail;
|
---|
271 |
|
---|
272 | if (handler != MKTAG('d', 'v', 's', 'd') &&
|
---|
273 | handler != MKTAG('d', 'v', 'h', 'd') &&
|
---|
274 | handler != MKTAG('d', 'v', 's', 'l'))
|
---|
275 | goto fail;
|
---|
276 |
|
---|
277 | ast = s->streams[0]->priv_data;
|
---|
278 | av_freep(&s->streams[0]->codec->extradata);
|
---|
279 | av_freep(&s->streams[0]);
|
---|
280 | s->nb_streams = 0;
|
---|
281 | avi->dv_demux = dv_init_demux(s);
|
---|
282 | if (!avi->dv_demux)
|
---|
283 | goto fail;
|
---|
284 | s->streams[0]->priv_data = ast;
|
---|
285 | url_fskip(pb, 3 * 4);
|
---|
286 | ast->scale = get_le32(pb);
|
---|
287 | ast->rate = get_le32(pb);
|
---|
288 | stream_index = s->nb_streams - 1;
|
---|
289 | url_fskip(pb, size - 7*4);
|
---|
290 | break;
|
---|
291 | }
|
---|
292 |
|
---|
293 | if (stream_index >= s->nb_streams) {
|
---|
294 | url_fskip(pb, size - 8);
|
---|
295 | /* ignore padding stream */
|
---|
296 | if (tag1 == MKTAG('p', 'a', 'd', 's'))
|
---|
297 | stream_index--;
|
---|
298 | break;
|
---|
299 | }
|
---|
300 | st = s->streams[stream_index];
|
---|
301 | ast = st->priv_data;
|
---|
302 | st->codec->stream_codec_tag= handler;
|
---|
303 |
|
---|
304 | get_le32(pb); /* flags */
|
---|
305 | get_le16(pb); /* priority */
|
---|
306 | get_le16(pb); /* language */
|
---|
307 | get_le32(pb); /* initial frame */
|
---|
308 | ast->scale = get_le32(pb);
|
---|
309 | ast->rate = get_le32(pb);
|
---|
310 | if(ast->scale && ast->rate){
|
---|
311 | }else if(frame_period){
|
---|
312 | ast->rate = 1000000;
|
---|
313 | ast->scale = frame_period;
|
---|
314 | }else{
|
---|
315 | ast->rate = 25;
|
---|
316 | ast->scale = 1;
|
---|
317 | }
|
---|
318 | av_set_pts_info(st, 64, ast->scale, ast->rate);
|
---|
319 |
|
---|
320 | ast->cum_len=get_le32(pb); /* start */
|
---|
321 | nb_frames = get_le32(pb);
|
---|
322 |
|
---|
323 | st->start_time = 0;
|
---|
324 | st->duration = nb_frames;
|
---|
325 | get_le32(pb); /* buffer size */
|
---|
326 | get_le32(pb); /* quality */
|
---|
327 | ast->sample_size = get_le32(pb); /* sample ssize */
|
---|
328 | // av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d\n", ast->rate, ast->scale, ast->start, ast->sample_size);
|
---|
329 |
|
---|
330 | switch(tag1) {
|
---|
331 | case MKTAG('v', 'i', 'd', 's'):
|
---|
332 | codec_type = CODEC_TYPE_VIDEO;
|
---|
333 |
|
---|
334 | ast->sample_size = 0;
|
---|
335 | break;
|
---|
336 | case MKTAG('a', 'u', 'd', 's'):
|
---|
337 | codec_type = CODEC_TYPE_AUDIO;
|
---|
338 | break;
|
---|
339 | case MKTAG('t', 'x', 't', 's'):
|
---|
340 | //FIXME
|
---|
341 | codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ? FIXME
|
---|
342 | break;
|
---|
343 | case MKTAG('p', 'a', 'd', 's'):
|
---|
344 | codec_type = CODEC_TYPE_UNKNOWN;
|
---|
345 | stream_index--;
|
---|
346 | break;
|
---|
347 | default:
|
---|
348 | av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
|
---|
349 | goto fail;
|
---|
350 | }
|
---|
351 | ast->frame_offset= ast->cum_len * FFMAX(ast->sample_size, 1);
|
---|
352 | url_fskip(pb, size - 12 * 4);
|
---|
353 | break;
|
---|
354 | case MKTAG('s', 't', 'r', 'f'):
|
---|
355 | /* stream header */
|
---|
356 | if (stream_index >= s->nb_streams || avi->dv_demux) {
|
---|
357 | url_fskip(pb, size);
|
---|
358 | } else {
|
---|
359 | st = s->streams[stream_index];
|
---|
360 | switch(codec_type) {
|
---|
361 | case CODEC_TYPE_VIDEO:
|
---|
362 | get_le32(pb); /* size */
|
---|
363 | st->codec->width = get_le32(pb);
|
---|
364 | st->codec->height = get_le32(pb);
|
---|
365 | get_le16(pb); /* panes */
|
---|
366 | st->codec->bits_per_sample= get_le16(pb); /* depth */
|
---|
367 | tag1 = get_le32(pb);
|
---|
368 | get_le32(pb); /* ImageSize */
|
---|
369 | get_le32(pb); /* XPelsPerMeter */
|
---|
370 | get_le32(pb); /* YPelsPerMeter */
|
---|
371 | get_le32(pb); /* ClrUsed */
|
---|
372 | get_le32(pb); /* ClrImportant */
|
---|
373 |
|
---|
374 | if(size > 10*4 && size<(1<<30)){
|
---|
375 | st->codec->extradata_size= size - 10*4;
|
---|
376 | st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
|
---|
377 | get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
|
---|
378 | }
|
---|
379 |
|
---|
380 | if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
|
---|
381 | get_byte(pb);
|
---|
382 |
|
---|
383 | /* Extract palette from extradata if bpp <= 8 */
|
---|
384 | /* This code assumes that extradata contains only palette */
|
---|
385 | /* This is true for all paletted codecs implemented in ffmpeg */
|
---|
386 | if (st->codec->extradata_size && (st->codec->bits_per_sample <= 8)) {
|
---|
387 | st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
|
---|
388 | #ifdef WORDS_BIGENDIAN
|
---|
389 | for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
|
---|
390 | st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
|
---|
391 | #else
|
---|
392 | memcpy(st->codec->palctrl->palette, st->codec->extradata,
|
---|
393 | FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
|
---|
394 | #endif
|
---|
395 | st->codec->palctrl->palette_changed = 1;
|
---|
396 | }
|
---|
397 |
|
---|
398 | #ifdef DEBUG
|
---|
399 | print_tag("video", tag1, 0);
|
---|
400 | #endif
|
---|
401 | st->codec->codec_type = CODEC_TYPE_VIDEO;
|
---|
402 | st->codec->codec_tag = tag1;
|
---|
403 | st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
|
---|
404 | if (st->codec->codec_id == CODEC_ID_XAN_WC4)
|
---|
405 | xan_video = 1;
|
---|
406 | st->need_parsing = 2; //only parse headers dont do slower repacketization, this is needed to get the pict type which is needed for generating correct pts
|
---|
407 | // url_fskip(pb, size - 5 * 4);
|
---|
408 | break;
|
---|
409 | case CODEC_TYPE_AUDIO:
|
---|
410 | get_wav_header(pb, st->codec, size);
|
---|
411 | if(ast->sample_size && st->codec->block_align && ast->sample_size % st->codec->block_align)
|
---|
412 | av_log(s, AV_LOG_DEBUG, "invalid sample size or block align detected\n");
|
---|
413 | if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
|
---|
414 | url_fskip(pb, 1);
|
---|
415 | /* special case time: To support Xan DPCM, hardcode
|
---|
416 | * the format if Xxan is the video codec */
|
---|
417 | st->need_parsing = 1;
|
---|
418 | /* force parsing as several audio frames can be in
|
---|
419 | one packet */
|
---|
420 | if (xan_video)
|
---|
421 | st->codec->codec_id = CODEC_ID_XAN_DPCM;
|
---|
422 | break;
|
---|
423 | default:
|
---|
424 | st->codec->codec_type = CODEC_TYPE_DATA;
|
---|
425 | st->codec->codec_id= CODEC_ID_NONE;
|
---|
426 | st->codec->codec_tag= 0;
|
---|
427 | url_fskip(pb, size);
|
---|
428 | break;
|
---|
429 | }
|
---|
430 | }
|
---|
431 | break;
|
---|
432 | case MKTAG('i', 'n', 'd', 'x'):
|
---|
433 | i= url_ftell(pb);
|
---|
434 | if(!url_is_streamed(pb)){
|
---|
435 | read_braindead_odml_indx(s, 0);
|
---|
436 | avi->index_loaded=1;
|
---|
437 | }
|
---|
438 | url_fseek(pb, i+size, SEEK_SET);
|
---|
439 | break;
|
---|
440 | default:
|
---|
441 | /* skip tag */
|
---|
442 | size += (size & 1);
|
---|
443 | url_fskip(pb, size);
|
---|
444 | break;
|
---|
445 | }
|
---|
446 | }
|
---|
447 | end_of_header:
|
---|
448 | /* check stream number */
|
---|
449 | if (stream_index != s->nb_streams - 1) {
|
---|
450 | fail:
|
---|
451 | for(i=0;i<s->nb_streams;i++) {
|
---|
452 | av_freep(&s->streams[i]->codec->extradata);
|
---|
453 | av_freep(&s->streams[i]);
|
---|
454 | }
|
---|
455 | return -1;
|
---|
456 | }
|
---|
457 |
|
---|
458 | if(!avi->index_loaded && !url_is_streamed(pb))
|
---|
459 | avi_load_index(s);
|
---|
460 | avi->index_loaded = 1;
|
---|
461 | avi->non_interleaved |= guess_ni_flag(s);
|
---|
462 | if(avi->non_interleaved)
|
---|
463 | clean_index(s);
|
---|
464 |
|
---|
465 | return 0;
|
---|
466 | }
|
---|
467 |
|
---|
468 | static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
|
---|
469 | {
|
---|
470 | AVIContext *avi = s->priv_data;
|
---|
471 | ByteIOContext *pb = &s->pb;
|
---|
472 | int n, d[8], size;
|
---|
473 | offset_t i, sync;
|
---|
474 | void* dstr;
|
---|
475 |
|
---|
476 | if (avi->dv_demux) {
|
---|
477 | size = dv_get_packet(avi->dv_demux, pkt);
|
---|
478 | if (size >= 0)
|
---|
479 | return size;
|
---|
480 | }
|
---|
481 |
|
---|
482 | if(avi->non_interleaved){
|
---|
483 | int best_stream_index = 0;
|
---|
484 | AVStream *best_st= NULL;
|
---|
485 | AVIStream *best_ast;
|
---|
486 | int64_t best_ts= INT64_MAX;
|
---|
487 | int i;
|
---|
488 |
|
---|
489 | for(i=0; i<s->nb_streams; i++){
|
---|
490 | AVStream *st = s->streams[i];
|
---|
491 | AVIStream *ast = st->priv_data;
|
---|
492 | int64_t ts= ast->frame_offset;
|
---|
493 |
|
---|
494 | if(ast->sample_size)
|
---|
495 | ts /= ast->sample_size;
|
---|
496 | ts= av_rescale(ts, AV_TIME_BASE * (int64_t)st->time_base.num, st->time_base.den);
|
---|
497 |
|
---|
498 | // av_log(NULL, AV_LOG_DEBUG, "%Ld %d/%d %Ld\n", ts, st->time_base.num, st->time_base.den, ast->frame_offset);
|
---|
499 | if(ts < best_ts){
|
---|
500 | best_ts= ts;
|
---|
501 | best_st= st;
|
---|
502 | best_stream_index= i;
|
---|
503 | }
|
---|
504 | }
|
---|
505 | best_ast = best_st->priv_data;
|
---|
506 | best_ts= av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE * (int64_t)best_st->time_base.num); //FIXME a little ugly
|
---|
507 | if(best_ast->remaining)
|
---|
508 | i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
|
---|
509 | else
|
---|
510 | i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
|
---|
511 |
|
---|
512 | // av_log(NULL, AV_LOG_DEBUG, "%d\n", i);
|
---|
513 | if(i>=0){
|
---|
514 | int64_t pos= best_st->index_entries[i].pos;
|
---|
515 | pos += best_ast->packet_size - best_ast->remaining;
|
---|
516 | url_fseek(&s->pb, pos + 8, SEEK_SET);
|
---|
517 | // av_log(NULL, AV_LOG_DEBUG, "pos=%Ld\n", pos);
|
---|
518 |
|
---|
519 | assert(best_ast->remaining <= best_ast->packet_size);
|
---|
520 |
|
---|
521 | avi->stream_index= best_stream_index;
|
---|
522 | if(!best_ast->remaining)
|
---|
523 | best_ast->packet_size=
|
---|
524 | best_ast->remaining= best_st->index_entries[i].size;
|
---|
525 | }
|
---|
526 | }
|
---|
527 |
|
---|
528 | resync:
|
---|
529 | if(avi->stream_index >= 0){
|
---|
530 | AVStream *st= s->streams[ avi->stream_index ];
|
---|
531 | AVIStream *ast= st->priv_data;
|
---|
532 | int size;
|
---|
533 |
|
---|
534 | if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM
|
---|
535 | size= INT_MAX;
|
---|
536 | else if(ast->sample_size < 32)
|
---|
537 | size= 64*ast->sample_size;
|
---|
538 | else
|
---|
539 | size= ast->sample_size;
|
---|
540 |
|
---|
541 | if(size > ast->remaining)
|
---|
542 | size= ast->remaining;
|
---|
543 | av_get_packet(pb, pkt, size);
|
---|
544 |
|
---|
545 | if (avi->dv_demux) {
|
---|
546 | dstr = pkt->destruct;
|
---|
547 | size = dv_produce_packet(avi->dv_demux, pkt,
|
---|
548 | pkt->data, pkt->size);
|
---|
549 | pkt->destruct = dstr;
|
---|
550 | pkt->flags |= PKT_FLAG_KEY;
|
---|
551 | } else {
|
---|
552 | /* XXX: how to handle B frames in avi ? */
|
---|
553 | pkt->dts = ast->frame_offset;
|
---|
554 | // pkt->dts += ast->start;
|
---|
555 | if(ast->sample_size)
|
---|
556 | pkt->dts /= ast->sample_size;
|
---|
557 | //av_log(NULL, AV_LOG_DEBUG, "dts:%Ld offset:%Ld %d/%d smpl_siz:%d base:%d st:%d size:%d\n", pkt->dts, ast->frame_offset, ast->scale, ast->rate, ast->sample_size, AV_TIME_BASE, avi->stream_index, size);
|
---|
558 | pkt->stream_index = avi->stream_index;
|
---|
559 |
|
---|
560 | if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
|
---|
561 | if(st->index_entries){
|
---|
562 | AVIndexEntry *e;
|
---|
563 | int index;
|
---|
564 |
|
---|
565 | index= av_index_search_timestamp(st, pkt->dts, 0);
|
---|
566 | e= &st->index_entries[index];
|
---|
567 |
|
---|
568 | if(index >= 0 && e->timestamp == ast->frame_offset){
|
---|
569 | if (e->flags & AVINDEX_KEYFRAME)
|
---|
570 | pkt->flags |= PKT_FLAG_KEY;
|
---|
571 | }
|
---|
572 | } else {
|
---|
573 | /* if no index, better to say that all frames
|
---|
574 | are key frames */
|
---|
575 | pkt->flags |= PKT_FLAG_KEY;
|
---|
576 | }
|
---|
577 | } else {
|
---|
578 | pkt->flags |= PKT_FLAG_KEY;
|
---|
579 | }
|
---|
580 | if(ast->sample_size)
|
---|
581 | ast->frame_offset += pkt->size;
|
---|
582 | else
|
---|
583 | ast->frame_offset++;
|
---|
584 | }
|
---|
585 | ast->remaining -= size;
|
---|
586 | if(!ast->remaining){
|
---|
587 | avi->stream_index= -1;
|
---|
588 | ast->packet_size= 0;
|
---|
589 | if (size & 1) {
|
---|
590 | get_byte(pb);
|
---|
591 | size++;
|
---|
592 | }
|
---|
593 | }
|
---|
594 |
|
---|
595 | return size;
|
---|
596 | }
|
---|
597 |
|
---|
598 | memset(d, -1, sizeof(int)*8);
|
---|
599 | for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
|
---|
600 | int j;
|
---|
601 |
|
---|
602 | if (i >= avi->movi_end) {
|
---|
603 | if (avi->is_odml) {
|
---|
604 | url_fskip(pb, avi->riff_end - i);
|
---|
605 | avi->riff_end = avi->movi_end = url_fsize(pb);
|
---|
606 | } else
|
---|
607 | break;
|
---|
608 | }
|
---|
609 |
|
---|
610 | for(j=0; j<7; j++)
|
---|
611 | d[j]= d[j+1];
|
---|
612 | d[7]= get_byte(pb);
|
---|
613 |
|
---|
614 | size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
|
---|
615 |
|
---|
616 | if( d[2] >= '0' && d[2] <= '9'
|
---|
617 | && d[3] >= '0' && d[3] <= '9'){
|
---|
618 | n= (d[2] - '0') * 10 + (d[3] - '0');
|
---|
619 | }else{
|
---|
620 | n= 100; //invalid stream id
|
---|
621 | }
|
---|
622 | //av_log(NULL, AV_LOG_DEBUG, "%X %X %X %X %X %X %X %X %lld %d %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
|
---|
623 | if(i + size > avi->movi_end || d[0]<0)
|
---|
624 | continue;
|
---|
625 |
|
---|
626 | //parse ix##
|
---|
627 | if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
|
---|
628 | //parse JUNK
|
---|
629 | ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')){
|
---|
630 | url_fskip(pb, size);
|
---|
631 | //av_log(NULL, AV_LOG_DEBUG, "SKIP\n");
|
---|
632 | goto resync;
|
---|
633 | }
|
---|
634 |
|
---|
635 | if( d[0] >= '0' && d[0] <= '9'
|
---|
636 | && d[1] >= '0' && d[1] <= '9'){
|
---|
637 | n= (d[0] - '0') * 10 + (d[1] - '0');
|
---|
638 | }else{
|
---|
639 | n= 100; //invalid stream id
|
---|
640 | }
|
---|
641 |
|
---|
642 | //parse ##dc/##wb
|
---|
643 | if(n < s->nb_streams){
|
---|
644 | AVStream *st;
|
---|
645 | AVIStream *ast;
|
---|
646 | st = s->streams[n];
|
---|
647 | ast = st->priv_data;
|
---|
648 |
|
---|
649 | if( (st->discard >= AVDISCARD_DEFAULT && size==0)
|
---|
650 | /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & PKT_FLAG_KEY))*/ //FIXME needs a little reordering
|
---|
651 | || st->discard >= AVDISCARD_ALL){
|
---|
652 | if(ast->sample_size) ast->frame_offset += pkt->size;
|
---|
653 | else ast->frame_offset++;
|
---|
654 | url_fskip(pb, size);
|
---|
655 | goto resync;
|
---|
656 | }
|
---|
657 |
|
---|
658 | if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||
|
---|
659 | d[2]*256+d[3] == ast->prefix /*||
|
---|
660 | (d[2] == 'd' && d[3] == 'c') ||
|
---|
661 | (d[2] == 'w' && d[3] == 'b')*/) {
|
---|
662 |
|
---|
663 | //av_log(NULL, AV_LOG_DEBUG, "OK\n");
|
---|
664 | if(d[2]*256+d[3] == ast->prefix)
|
---|
665 | ast->prefix_count++;
|
---|
666 | else{
|
---|
667 | ast->prefix= d[2]*256+d[3];
|
---|
668 | ast->prefix_count= 0;
|
---|
669 | }
|
---|
670 |
|
---|
671 | avi->stream_index= n;
|
---|
672 | ast->packet_size= size + 8;
|
---|
673 | ast->remaining= size;
|
---|
674 | goto resync;
|
---|
675 | }
|
---|
676 | }
|
---|
677 | /* palette changed chunk */
|
---|
678 | if ( d[0] >= '0' && d[0] <= '9'
|
---|
679 | && d[1] >= '0' && d[1] <= '9'
|
---|
680 | && ((d[2] == 'p' && d[3] == 'c'))
|
---|
681 | && n < s->nb_streams && i + size <= avi->movi_end) {
|
---|
682 |
|
---|
683 | AVStream *st;
|
---|
684 | int first, clr, flags, k, p;
|
---|
685 |
|
---|
686 | st = s->streams[n];
|
---|
687 |
|
---|
688 | first = get_byte(pb);
|
---|
689 | clr = get_byte(pb);
|
---|
690 | if(!clr) /* all 256 colors used */
|
---|
691 | clr = 256;
|
---|
692 | flags = get_le16(pb);
|
---|
693 | p = 4;
|
---|
694 | for (k = first; k < clr + first; k++) {
|
---|
695 | int r, g, b;
|
---|
696 | r = get_byte(pb);
|
---|
697 | g = get_byte(pb);
|
---|
698 | b = get_byte(pb);
|
---|
699 | get_byte(pb);
|
---|
700 | st->codec->palctrl->palette[k] = b + (g << 8) + (r << 16);
|
---|
701 | }
|
---|
702 | st->codec->palctrl->palette_changed = 1;
|
---|
703 | goto resync;
|
---|
704 | }
|
---|
705 |
|
---|
706 | }
|
---|
707 |
|
---|
708 | return -1;
|
---|
709 | }
|
---|
710 |
|
---|
711 | /* XXX: we make the implicit supposition that the position are sorted
|
---|
712 | for each stream */
|
---|
713 | static int avi_read_idx1(AVFormatContext *s, int size)
|
---|
714 | {
|
---|
715 | AVIContext *avi = s->priv_data;
|
---|
716 | ByteIOContext *pb = &s->pb;
|
---|
717 | int nb_index_entries, i;
|
---|
718 | AVStream *st;
|
---|
719 | AVIStream *ast;
|
---|
720 | unsigned int index, tag, flags, pos, len;
|
---|
721 | unsigned last_pos= -1;
|
---|
722 |
|
---|
723 | nb_index_entries = size / 16;
|
---|
724 | if (nb_index_entries <= 0)
|
---|
725 | return -1;
|
---|
726 |
|
---|
727 | /* read the entries and sort them in each stream component */
|
---|
728 | for(i = 0; i < nb_index_entries; i++) {
|
---|
729 | tag = get_le32(pb);
|
---|
730 | flags = get_le32(pb);
|
---|
731 | pos = get_le32(pb);
|
---|
732 | len = get_le32(pb);
|
---|
733 | #if defined(DEBUG_SEEK)
|
---|
734 | av_log(NULL, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/",
|
---|
735 | i, tag, flags, pos, len);
|
---|
736 | #endif
|
---|
737 | if(i==0 && pos > avi->movi_list)
|
---|
738 | avi->movi_list= 0; //FIXME better check
|
---|
739 | pos += avi->movi_list;
|
---|
740 |
|
---|
741 | index = ((tag & 0xff) - '0') * 10;
|
---|
742 | index += ((tag >> 8) & 0xff) - '0';
|
---|
743 | if (index >= s->nb_streams)
|
---|
744 | continue;
|
---|
745 | st = s->streams[index];
|
---|
746 | ast = st->priv_data;
|
---|
747 |
|
---|
748 | #if defined(DEBUG_SEEK)
|
---|
749 | av_log(NULL, AV_LOG_DEBUG, "%d cum_len=%d\n", len, ast->cum_len);
|
---|
750 | #endif
|
---|
751 | if(last_pos == pos)
|
---|
752 | avi->non_interleaved= 1;
|
---|
753 | else
|
---|
754 | av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
|
---|
755 | if(ast->sample_size)
|
---|
756 | ast->cum_len += len / ast->sample_size;
|
---|
757 | else
|
---|
758 | ast->cum_len ++;
|
---|
759 | last_pos= pos;
|
---|
760 | }
|
---|
761 | return 0;
|
---|
762 | }
|
---|
763 |
|
---|
764 | static int guess_ni_flag(AVFormatContext *s){
|
---|
765 | int i;
|
---|
766 | int64_t last_start=0;
|
---|
767 | int64_t first_end= INT64_MAX;
|
---|
768 |
|
---|
769 | for(i=0; i<s->nb_streams; i++){
|
---|
770 | AVStream *st = s->streams[i];
|
---|
771 | int n= st->nb_index_entries;
|
---|
772 |
|
---|
773 | if(n <= 0)
|
---|
774 | continue;
|
---|
775 |
|
---|
776 | if(st->index_entries[0].pos > last_start)
|
---|
777 | last_start= st->index_entries[0].pos;
|
---|
778 | if(st->index_entries[n-1].pos < first_end)
|
---|
779 | first_end= st->index_entries[n-1].pos;
|
---|
780 | }
|
---|
781 | return last_start > first_end;
|
---|
782 | }
|
---|
783 |
|
---|
784 | static int avi_load_index(AVFormatContext *s)
|
---|
785 | {
|
---|
786 | AVIContext *avi = s->priv_data;
|
---|
787 | ByteIOContext *pb = &s->pb;
|
---|
788 | uint32_t tag, size;
|
---|
789 | offset_t pos= url_ftell(pb);
|
---|
790 |
|
---|
791 | url_fseek(pb, avi->movi_end, SEEK_SET);
|
---|
792 | #ifdef DEBUG_SEEK
|
---|
793 | printf("movi_end=0x%llx\n", avi->movi_end);
|
---|
794 | #endif
|
---|
795 | for(;;) {
|
---|
796 | if (url_feof(pb))
|
---|
797 | break;
|
---|
798 | tag = get_le32(pb);
|
---|
799 | size = get_le32(pb);
|
---|
800 | #ifdef DEBUG_SEEK
|
---|
801 | printf("tag=%c%c%c%c size=0x%x\n",
|
---|
802 | tag & 0xff,
|
---|
803 | (tag >> 8) & 0xff,
|
---|
804 | (tag >> 16) & 0xff,
|
---|
805 | (tag >> 24) & 0xff,
|
---|
806 | size);
|
---|
807 | #endif
|
---|
808 | switch(tag) {
|
---|
809 | case MKTAG('i', 'd', 'x', '1'):
|
---|
810 | if (avi_read_idx1(s, size) < 0)
|
---|
811 | goto skip;
|
---|
812 | else
|
---|
813 | goto the_end;
|
---|
814 | break;
|
---|
815 | default:
|
---|
816 | skip:
|
---|
817 | size += (size & 1);
|
---|
818 | url_fskip(pb, size);
|
---|
819 | break;
|
---|
820 | }
|
---|
821 | }
|
---|
822 | the_end:
|
---|
823 | url_fseek(pb, pos, SEEK_SET);
|
---|
824 | return 0;
|
---|
825 | }
|
---|
826 |
|
---|
827 | static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
|
---|
828 | {
|
---|
829 | AVIContext *avi = s->priv_data;
|
---|
830 | AVStream *st;
|
---|
831 | int i, index;
|
---|
832 | int64_t pos;
|
---|
833 |
|
---|
834 | if (!avi->index_loaded) {
|
---|
835 | /* we only load the index on demand */
|
---|
836 | avi_load_index(s);
|
---|
837 | avi->index_loaded = 1;
|
---|
838 | }
|
---|
839 | assert(stream_index>= 0);
|
---|
840 |
|
---|
841 | st = s->streams[stream_index];
|
---|
842 | index= av_index_search_timestamp(st, timestamp, flags);
|
---|
843 | if(index<0)
|
---|
844 | return -1;
|
---|
845 |
|
---|
846 | /* find the position */
|
---|
847 | pos = st->index_entries[index].pos;
|
---|
848 | timestamp = st->index_entries[index].timestamp;
|
---|
849 |
|
---|
850 | // av_log(NULL, AV_LOG_DEBUG, "XX %Ld %d %Ld\n", timestamp, index, st->index_entries[index].timestamp);
|
---|
851 |
|
---|
852 | for(i = 0; i < s->nb_streams; i++) {
|
---|
853 | AVStream *st2 = s->streams[i];
|
---|
854 | AVIStream *ast2 = st2->priv_data;
|
---|
855 |
|
---|
856 | ast2->packet_size=
|
---|
857 | ast2->remaining= 0;
|
---|
858 |
|
---|
859 | if (st2->nb_index_entries <= 0)
|
---|
860 | continue;
|
---|
861 |
|
---|
862 | // assert(st2->codec->block_align);
|
---|
863 | assert(st2->time_base.den == ast2->rate);
|
---|
864 | assert(st2->time_base.num == ast2->scale);
|
---|
865 | index = av_index_search_timestamp(
|
---|
866 | st2,
|
---|
867 | av_rescale(timestamp, st2->time_base.den*(int64_t)st->time_base.num, st->time_base.den * (int64_t)st2->time_base.num),
|
---|
868 | flags | AVSEEK_FLAG_BACKWARD);
|
---|
869 | if(index<0)
|
---|
870 | index=0;
|
---|
871 |
|
---|
872 | if(!avi->non_interleaved){
|
---|
873 | while(index>0 && st2->index_entries[index].pos > pos)
|
---|
874 | index--;
|
---|
875 | while(index+1 < st2->nb_index_entries && st2->index_entries[index].pos < pos)
|
---|
876 | index++;
|
---|
877 | }
|
---|
878 |
|
---|
879 | // av_log(NULL, AV_LOG_DEBUG, "%Ld %d %Ld\n", timestamp, index, st2->index_entries[index].timestamp);
|
---|
880 | /* extract the current frame number */
|
---|
881 | ast2->frame_offset = st2->index_entries[index].timestamp;
|
---|
882 | if(ast2->sample_size)
|
---|
883 | ast2->frame_offset *=ast2->sample_size;
|
---|
884 | }
|
---|
885 |
|
---|
886 | if (avi->dv_demux)
|
---|
887 | dv_flush_audio_packets(avi->dv_demux);
|
---|
888 | /* do the seek */
|
---|
889 | url_fseek(&s->pb, pos, SEEK_SET);
|
---|
890 | avi->stream_index= -1;
|
---|
891 | return 0;
|
---|
892 | }
|
---|
893 |
|
---|
894 | static int avi_read_close(AVFormatContext *s)
|
---|
895 | {
|
---|
896 | int i;
|
---|
897 | AVIContext *avi = s->priv_data;
|
---|
898 |
|
---|
899 | for(i=0;i<s->nb_streams;i++) {
|
---|
900 | AVStream *st = s->streams[i];
|
---|
901 | AVIStream *ast = st->priv_data;
|
---|
902 | av_free(ast);
|
---|
903 | av_free(st->codec->palctrl);
|
---|
904 | }
|
---|
905 |
|
---|
906 | if (avi->dv_demux)
|
---|
907 | av_free(avi->dv_demux);
|
---|
908 |
|
---|
909 | return 0;
|
---|
910 | }
|
---|
911 |
|
---|
912 | static int avi_probe(AVProbeData *p)
|
---|
913 | {
|
---|
914 | /* check file header */
|
---|
915 | if (p->buf_size <= 32)
|
---|
916 | return 0;
|
---|
917 | if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
|
---|
918 | p->buf[2] == 'F' && p->buf[3] == 'F' &&
|
---|
919 | p->buf[8] == 'A' && p->buf[9] == 'V' &&
|
---|
920 | p->buf[10] == 'I' && p->buf[11] == ' ')
|
---|
921 | return AVPROBE_SCORE_MAX;
|
---|
922 | else
|
---|
923 | return 0;
|
---|
924 | }
|
---|
925 |
|
---|
926 | static AVInputFormat avi_demuxer = {
|
---|
927 | "avi",
|
---|
928 | "avi format",
|
---|
929 | sizeof(AVIContext),
|
---|
930 | avi_probe,
|
---|
931 | avi_read_header,
|
---|
932 | avi_read_packet,
|
---|
933 | avi_read_close,
|
---|
934 | avi_read_seek,
|
---|
935 | };
|
---|
936 |
|
---|
937 | int avidec_init(void)
|
---|
938 | {
|
---|
939 | av_register_input_format(&avi_demuxer);
|
---|
940 | return 0;
|
---|
941 | }
|
---|