Mercurial > libavformat.hg
annotate avidec.c @ 584:4e3bab6555ae libavformat
When playing
ftp://ftp.mplayerhq.hu/MPlayer/samples/V-codecs/QPEG/VWbig6.avi with my
decoder (should appear soon) it hadn't changed palette even there are
palette change chunks in that AVI.
Here is small patch to make it work (zero number of colors to change in
that chunk actually means to change ALL colors).
patch by (Kostya <cannonball>at<bw-team>dot<com>)
author | michael |
---|---|
date | Fri, 12 Nov 2004 01:32:35 +0000 |
parents | aca10aa7686f |
children | fe24632a577b |
rev | line source |
---|---|
0 | 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avformat.h" | |
20 #include "avi.h" | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
21 #include "dv.h" |
0 | 22 |
23 //#define DEBUG | |
311 | 24 //#define DEBUG_SEEK |
0 | 25 |
311 | 26 typedef struct AVIIndexEntry { |
27 unsigned int flags; | |
28 unsigned int pos; | |
29 unsigned int cum_len; /* sum of all lengths before this packet */ | |
30 } AVIIndexEntry; | |
31 | |
32 typedef struct AVIStream { | |
33 AVIIndexEntry *index_entries; | |
34 int nb_index_entries; | |
35 int index_entries_allocated_size; | |
36 int frame_offset; /* current frame (video) or byte (audio) counter | |
37 (used to compute the pts) */ | |
38 int scale; | |
39 int rate; | |
40 int sample_size; /* audio only data */ | |
457 | 41 int start; |
311 | 42 |
43 int new_frame_offset; /* temporary storage (used during seek) */ | |
44 int cum_len; /* temporary storage (used during seek) */ | |
519 | 45 |
46 int prefix; ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b' | |
47 int prefix_count; | |
311 | 48 } AVIStream; |
0 | 49 |
50 typedef struct { | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
51 int64_t riff_end; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
52 int64_t movi_end; |
0 | 53 offset_t movi_list; |
311 | 54 int index_loaded; |
510 | 55 int is_odml; |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
56 DVDemuxContext* dv_demux; |
0 | 57 } AVIContext; |
58 | |
469
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
59 static int avi_load_index(AVFormatContext *s); |
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
60 |
0 | 61 #ifdef DEBUG |
62 static void print_tag(const char *str, unsigned int tag, int size) | |
63 { | |
64 printf("%s: tag=%c%c%c%c size=0x%x\n", | |
65 str, tag & 0xff, | |
66 (tag >> 8) & 0xff, | |
67 (tag >> 16) & 0xff, | |
68 (tag >> 24) & 0xff, | |
69 size); | |
70 } | |
71 #endif | |
72 | |
92
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
73 static int get_riff(AVIContext *avi, ByteIOContext *pb) |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
74 { |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
75 uint32_t tag; |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
76 /* check RIFF header */ |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
77 tag = get_le32(pb); |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
78 |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
79 if (tag != MKTAG('R', 'I', 'F', 'F')) |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
80 return -1; |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
81 avi->riff_end = get_le32(pb); /* RIFF chunk size */ |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
82 avi->riff_end += url_ftell(pb); /* RIFF chunk end */ |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
83 tag = get_le32(pb); |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
84 if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X')) |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
85 return -1; |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
86 |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
87 return 0; |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
88 } |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
89 |
0 | 90 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
91 { | |
92 AVIContext *avi = s->priv_data; | |
93 ByteIOContext *pb = &s->pb; | |
98
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
94 uint32_t tag, tag1, handler; |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
95 int codec_type, stream_index, frame_period, bit_rate, scale, rate; |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
96 unsigned int size, nb_frames; |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
97 int i, n; |
0 | 98 AVStream *st; |
311 | 99 AVIStream *ast; |
227 | 100 int xan_video = 0; /* hack to support Xan A/V */ |
0 | 101 |
92
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
102 if (get_riff(avi, pb) < 0) |
0 | 103 return -1; |
104 | |
105 /* first list tag */ | |
106 stream_index = -1; | |
107 codec_type = -1; | |
108 frame_period = 0; | |
109 for(;;) { | |
110 if (url_feof(pb)) | |
111 goto fail; | |
112 tag = get_le32(pb); | |
113 size = get_le32(pb); | |
114 #ifdef DEBUG | |
115 print_tag("tag", tag, size); | |
116 #endif | |
117 | |
118 switch(tag) { | |
119 case MKTAG('L', 'I', 'S', 'T'): | |
120 /* ignored, except when start of video packets */ | |
121 tag1 = get_le32(pb); | |
122 #ifdef DEBUG | |
123 print_tag("list", tag1, 0); | |
124 #endif | |
125 if (tag1 == MKTAG('m', 'o', 'v', 'i')) { | |
311 | 126 avi->movi_list = url_ftell(pb) - 4; |
495 | 127 if(size) avi->movi_end = avi->movi_list + size; |
128 else avi->movi_end = url_filesize(url_fileno(pb)); | |
0 | 129 #ifdef DEBUG |
130 printf("movi end=%Lx\n", avi->movi_end); | |
131 #endif | |
132 goto end_of_header; | |
133 } | |
134 break; | |
510 | 135 case MKTAG('d', 'm', 'l', 'h'): |
136 avi->is_odml = 1; | |
137 url_fskip(pb, size + (size & 1)); | |
138 break; | |
0 | 139 case MKTAG('a', 'v', 'i', 'h'): |
140 /* avi header */ | |
141 /* using frame_period is bad idea */ | |
142 frame_period = get_le32(pb); | |
143 bit_rate = get_le32(pb) * 8; | |
144 url_fskip(pb, 4 * 4); | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
145 n = get_le32(pb); |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
146 for(i=0;i<n;i++) { |
311 | 147 AVIStream *ast; |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
148 st = av_new_stream(s, i); |
0 | 149 if (!st) |
150 goto fail; | |
462
b69898ffc92a
move time_base (pts_num/pts_den) from AVFormatContext -> AVStream
michael
parents:
457
diff
changeset
|
151 |
311 | 152 ast = av_mallocz(sizeof(AVIStream)); |
153 if (!ast) | |
154 goto fail; | |
155 st->priv_data = ast; | |
0 | 156 } |
157 url_fskip(pb, size - 7 * 4); | |
158 break; | |
159 case MKTAG('s', 't', 'r', 'h'): | |
160 /* stream header */ | |
161 stream_index++; | |
162 tag1 = get_le32(pb); | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
163 handler = get_le32(pb); /* codec tag */ |
471 | 164 #ifdef DEBUG |
165 print_tag("strh", tag1, -1); | |
166 #endif | |
0 | 167 switch(tag1) { |
98
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
168 case MKTAG('i', 'a', 'v', 's'): |
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
169 case MKTAG('i', 'v', 'a', 's'): |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
170 /* |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
171 * After some consideration -- I don't think we |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
172 * have to support anything but DV in a type1 AVIs. |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
173 */ |
98
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
174 if (s->nb_streams != 1) |
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
175 goto fail; |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
176 |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
177 if (handler != MKTAG('d', 'v', 's', 'd') && |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
178 handler != MKTAG('d', 'v', 'h', 'd') && |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
179 handler != MKTAG('d', 'v', 's', 'l')) |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
180 goto fail; |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
181 |
526
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
182 ast = s->streams[0]->priv_data; |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
183 av_freep(&s->streams[0]->codec.extradata); |
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
184 av_freep(&s->streams[0]); |
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
185 s->nb_streams = 0; |
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
186 avi->dv_demux = dv_init_demux(s); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
187 if (!avi->dv_demux) |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
188 goto fail; |
526
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
189 s->streams[0]->priv_data = ast; |
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
190 url_fskip(pb, 3 * 4); |
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
191 ast->scale = get_le32(pb); |
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
192 ast->rate = get_le32(pb); |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
193 stream_index = s->nb_streams - 1; |
526
c5743d66c5ca
* fix for a DV regression introduced with the last round of avi_read_packet
romansh
parents:
520
diff
changeset
|
194 url_fskip(pb, size - 7*4); |
296
252946de6d3f
* DV demuxer is now capable of decoding auxilary audio stream. So,
romansh
parents:
262
diff
changeset
|
195 break; |
98
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
196 case MKTAG('v', 'i', 'd', 's'): |
0 | 197 codec_type = CODEC_TYPE_VIDEO; |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
198 |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
199 if (stream_index >= s->nb_streams) { |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
200 url_fskip(pb, size - 8); |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
201 break; |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
202 } |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
203 |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
204 st = s->streams[stream_index]; |
311 | 205 ast = st->priv_data; |
339 | 206 st->codec.stream_codec_tag= handler; |
311 | 207 |
0 | 208 get_le32(pb); /* flags */ |
209 get_le16(pb); /* priority */ | |
210 get_le16(pb); /* language */ | |
211 get_le32(pb); /* XXX: initial frame ? */ | |
98
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
212 scale = get_le32(pb); /* scale */ |
cae6ddfadf51
AVI type 1 support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
92
diff
changeset
|
213 rate = get_le32(pb); /* rate */ |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
214 |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
84
diff
changeset
|
215 if(scale && rate){ |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
84
diff
changeset
|
216 }else if(frame_period){ |
311 | 217 rate = 1000000; |
218 scale = frame_period; | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
84
diff
changeset
|
219 }else{ |
311 | 220 rate = 25; |
221 scale = 1; | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
84
diff
changeset
|
222 } |
311 | 223 ast->rate = rate; |
224 ast->scale = scale; | |
463
696f41bc8784
store index for seeking in the native timebase of each stream
michael
parents:
462
diff
changeset
|
225 av_set_pts_info(st, 64, scale, rate); |
311 | 226 st->codec.frame_rate = rate; |
227 st->codec.frame_rate_base = scale; | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
228 get_le32(pb); /* start */ |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
229 nb_frames = get_le32(pb); |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
230 st->start_time = 0; |
465 | 231 st->duration = av_rescale(nb_frames, |
232 st->codec.frame_rate_base * AV_TIME_BASE, | |
233 st->codec.frame_rate); | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
234 url_fskip(pb, size - 9 * 4); |
0 | 235 break; |
236 case MKTAG('a', 'u', 'd', 's'): | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
237 { |
311 | 238 unsigned int length; |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
239 |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
240 codec_type = CODEC_TYPE_AUDIO; |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
241 |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
242 if (stream_index >= s->nb_streams) { |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
243 url_fskip(pb, size - 8); |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
244 break; |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
245 } |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
246 st = s->streams[stream_index]; |
311 | 247 ast = st->priv_data; |
248 | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
249 get_le32(pb); /* flags */ |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
250 get_le16(pb); /* priority */ |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
251 get_le16(pb); /* language */ |
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
252 get_le32(pb); /* initial frame */ |
311 | 253 ast->scale = get_le32(pb); /* scale */ |
254 ast->rate = get_le32(pb); | |
463
696f41bc8784
store index for seeking in the native timebase of each stream
michael
parents:
462
diff
changeset
|
255 av_set_pts_info(st, 64, ast->scale, ast->rate); |
457 | 256 ast->start= get_le32(pb); /* start */ |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
257 length = get_le32(pb); /* length, in samples or bytes */ |
311 | 258 get_le32(pb); /* buffer size */ |
259 get_le32(pb); /* quality */ | |
260 ast->sample_size = get_le32(pb); /* sample ssize */ | |
457 | 261 //av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d\n", ast->scale, ast->rate, ast->sample_size, ast->start); |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
262 st->start_time = 0; |
465 | 263 if (ast->rate != 0) |
264 st->duration = (int64_t)length * AV_TIME_BASE / ast->rate; | |
311 | 265 url_fskip(pb, size - 12 * 4); |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
149
diff
changeset
|
266 } |
73
d40ddc73858a
reversing not yet reversed changes from r1.7 -> r1.8 except the static/const stuff
michaelni
parents:
65
diff
changeset
|
267 break; |
471 | 268 case MKTAG('t', 'x', 't', 's'): |
269 //FIXME | |
270 codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ? FIXME | |
271 url_fskip(pb, size - 8); | |
272 break; | |
534 | 273 case MKTAG('p', 'a', 'd', 's'): |
274 codec_type = CODEC_TYPE_UNKNOWN; | |
275 url_fskip(pb, size - 8); | |
276 stream_index--; | |
277 break; | |
73
d40ddc73858a
reversing not yet reversed changes from r1.7 -> r1.8 except the static/const stuff
michaelni
parents:
65
diff
changeset
|
278 default: |
534 | 279 av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1); |
73
d40ddc73858a
reversing not yet reversed changes from r1.7 -> r1.8 except the static/const stuff
michaelni
parents:
65
diff
changeset
|
280 goto fail; |
0 | 281 } |
282 break; | |
283 case MKTAG('s', 't', 'r', 'f'): | |
284 /* stream header */ | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
285 if (stream_index >= s->nb_streams || avi->dv_demux) { |
0 | 286 url_fskip(pb, size); |
287 } else { | |
288 st = s->streams[stream_index]; | |
289 switch(codec_type) { | |
290 case CODEC_TYPE_VIDEO: | |
291 get_le32(pb); /* size */ | |
292 st->codec.width = get_le32(pb); | |
293 st->codec.height = get_le32(pb); | |
294 get_le16(pb); /* panes */ | |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
295 st->codec.bits_per_sample= get_le16(pb); /* depth */ |
0 | 296 tag1 = get_le32(pb); |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
297 get_le32(pb); /* ImageSize */ |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
298 get_le32(pb); /* XPelsPerMeter */ |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
299 get_le32(pb); /* YPelsPerMeter */ |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
300 get_le32(pb); /* ClrUsed */ |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
301 get_le32(pb); /* ClrImportant */ |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
302 |
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
303 st->codec.extradata_size= size - 10*4; |
110 | 304 st->codec.extradata= av_malloc(st->codec.extradata_size); |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
305 get_buffer(pb, st->codec.extradata, st->codec.extradata_size); |
76 | 306 |
307 if(st->codec.extradata_size & 1) //FIXME check if the encoder really did this correctly | |
308 get_byte(pb); | |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
309 |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
310 /* Extract palette from extradata if bpp <= 8 */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
311 /* This code assumes that extradata contains only palette */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
312 /* This is true for all paletted codecs implemented in ffmpeg */ |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
313 if (st->codec.extradata_size && (st->codec.bits_per_sample <= 8)) { |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
314 st->codec.palctrl = av_mallocz(sizeof(AVPaletteControl)); |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
315 #ifdef WORDS_BIGENDIAN |
300
6ee1b02f9b2a
* fixes for broken builds on Solaris, OS2 and all bingendian
romansh
parents:
297
diff
changeset
|
316 for (i = 0; i < FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)/4; i++) |
6ee1b02f9b2a
* fixes for broken builds on Solaris, OS2 and all bingendian
romansh
parents:
297
diff
changeset
|
317 st->codec.palctrl->palette[i] = bswap_32(((uint32_t*)st->codec.extradata)[i]); |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
318 #else |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
319 memcpy(st->codec.palctrl->palette, st->codec.extradata, |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
320 FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)); |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
321 #endif |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
322 st->codec.palctrl->palette_changed = 1; |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
323 } |
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
324 |
0 | 325 #ifdef DEBUG |
326 print_tag("video", tag1, 0); | |
327 #endif | |
328 st->codec.codec_type = CODEC_TYPE_VIDEO; | |
329 st->codec.codec_tag = tag1; | |
330 st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1); | |
227 | 331 if (st->codec.codec_id == CODEC_ID_XAN_WC4) |
332 xan_video = 1; | |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
73
diff
changeset
|
333 // url_fskip(pb, size - 5 * 4); |
0 | 334 break; |
73
d40ddc73858a
reversing not yet reversed changes from r1.7 -> r1.8 except the static/const stuff
michaelni
parents:
65
diff
changeset
|
335 case CODEC_TYPE_AUDIO: |
84
0068a6902911
correct AUDIO strf parsing patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
82
diff
changeset
|
336 get_wav_header(pb, &st->codec, size); |
13
8a5285a0ca2f
Fix for odd strf tag in Stargate SG-1 - 3x18 - Shades of Grey.avi
mmu_man
parents:
5
diff
changeset
|
337 if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ |
8a5285a0ca2f
Fix for odd strf tag in Stargate SG-1 - 3x18 - Shades of Grey.avi
mmu_man
parents:
5
diff
changeset
|
338 url_fskip(pb, 1); |
227 | 339 /* special case time: To support Xan DPCM, hardcode |
340 * the format if Xxan is the video codec */ | |
311 | 341 st->need_parsing = 1; |
342 /* force parsing as several audio frames can be in | |
343 one packet */ | |
227 | 344 if (xan_video) |
345 st->codec.codec_id = CODEC_ID_XAN_DPCM; | |
0 | 346 break; |
347 default: | |
472 | 348 st->codec.codec_type = CODEC_TYPE_DATA; |
349 st->codec.codec_id= CODEC_ID_NONE; | |
350 st->codec.codec_tag= 0; | |
0 | 351 url_fskip(pb, size); |
352 break; | |
353 } | |
354 } | |
355 break; | |
356 default: | |
357 /* skip tag */ | |
358 size += (size & 1); | |
359 url_fskip(pb, size); | |
360 break; | |
361 } | |
362 } | |
363 end_of_header: | |
364 /* check stream number */ | |
365 if (stream_index != s->nb_streams - 1) { | |
366 fail: | |
367 for(i=0;i<s->nb_streams;i++) { | |
80 | 368 av_freep(&s->streams[i]->codec.extradata); |
0 | 369 av_freep(&s->streams[i]); |
370 } | |
371 return -1; | |
372 } | |
373 | |
469
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
374 assert(!avi->index_loaded); |
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
375 avi_load_index(s); |
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
376 avi->index_loaded = 1; |
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
377 |
0 | 378 return 0; |
379 } | |
380 | |
381 static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) | |
382 { | |
383 AVIContext *avi = s->priv_data; | |
384 ByteIOContext *pb = &s->pb; | |
510 | 385 int n, d[8], size; |
569 | 386 offset_t i, sync; |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
387 void* dstr; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
388 |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
389 if (avi->dv_demux) { |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
390 size = dv_get_packet(avi->dv_demux, pkt); |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
391 if (size >= 0) |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
392 return size; |
149 | 393 } |
569 | 394 |
395 resync: | |
396 memset(d, -1, sizeof(int)*8); | |
397 for(i=sync=url_ftell(pb); !url_feof(pb); i++) { | |
82 | 398 int j; |
399 | |
510 | 400 if (i >= avi->movi_end) { |
401 if (avi->is_odml) { | |
402 url_fskip(pb, avi->riff_end - i); | |
403 avi->riff_end = avi->movi_end = url_filesize(url_fileno(pb)); | |
404 } else | |
405 break; | |
92
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
406 } |
5a4b5f03d13e
OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
91
diff
changeset
|
407 |
82 | 408 for(j=0; j<7; j++) |
409 d[j]= d[j+1]; | |
410 d[7]= get_byte(pb); | |
411 | |
412 size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24); | |
413 | |
519 | 414 if( d[2] >= '0' && d[2] <= '9' |
415 && d[3] >= '0' && d[3] <= '9'){ | |
416 n= (d[2] - '0') * 10 + (d[3] - '0'); | |
417 }else{ | |
418 n= 100; //invalid stream id | |
419 } | |
420 //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); | |
421 if(i + size > avi->movi_end || d[0]<0) | |
422 continue; | |
423 | |
82 | 424 //parse ix## |
519 | 425 if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) |
426 //parse JUNK | |
427 ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')){ | |
82 | 428 url_fskip(pb, size); |
519 | 429 //av_log(NULL, AV_LOG_DEBUG, "SKIP\n"); |
569 | 430 goto resync; |
82 | 431 } |
510 | 432 |
519 | 433 if( d[0] >= '0' && d[0] <= '9' |
434 && d[1] >= '0' && d[1] <= '9'){ | |
435 n= (d[0] - '0') * 10 + (d[1] - '0'); | |
436 }else{ | |
437 n= 100; //invalid stream id | |
510 | 438 } |
82 | 439 |
440 //parse ##dc/##wb | |
519 | 441 if(n < s->nb_streams){ |
442 AVStream *st; | |
443 AVIStream *ast; | |
444 st = s->streams[n]; | |
445 ast = st->priv_data; | |
446 | |
569 | 447 if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) || |
519 | 448 d[2]*256+d[3] == ast->prefix /*|| |
449 (d[2] == 'd' && d[3] == 'c') || | |
450 (d[2] == 'w' && d[3] == 'b')*/) { | |
451 | |
452 //av_log(NULL, AV_LOG_DEBUG, "OK\n"); | |
453 if(d[2]*256+d[3] == ast->prefix) | |
454 ast->prefix_count++; | |
455 else{ | |
456 ast->prefix= d[2]*256+d[3]; | |
457 ast->prefix_count= 0; | |
458 } | |
459 | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
460 av_new_packet(pkt, size); |
149 | 461 get_buffer(pb, pkt->data, size); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
462 if (size & 1) { |
149 | 463 get_byte(pb); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
464 size++; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
465 } |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
466 |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
467 if (avi->dv_demux) { |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
468 dstr = pkt->destruct; |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
469 size = dv_produce_packet(avi->dv_demux, pkt, |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
470 pkt->data, pkt->size); |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
471 pkt->destruct = dstr; |
311 | 472 pkt->flags |= PKT_FLAG_KEY; |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
473 } else { |
311 | 474 /* XXX: how to handle B frames in avi ? */ |
469
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
475 pkt->dts = ast->frame_offset; |
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
476 // pkt->dts += ast->start; |
457 | 477 if(ast->sample_size) |
469
6a4cc19e8d9b
exporting keyframe flags, fixes keyframe stuff with streamcopy
michael
parents:
466
diff
changeset
|
478 pkt->dts /= ast->sample_size; |
495 | 479 //av_log(NULL, AV_LOG_DEBUG, "dts:%Ld offset:%d %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, n, size); |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
480 pkt->stream_index = n; |
311 | 481 /* FIXME: We really should read index for that */ |
482 if (st->codec.codec_type == CODEC_TYPE_VIDEO) { | |
483 if (ast->frame_offset < ast->nb_index_entries) { | |
484 if (ast->index_entries[ast->frame_offset].flags & AVIIF_INDEX) | |
485 pkt->flags |= PKT_FLAG_KEY; | |
486 } else { | |
487 /* if no index, better to say that all frames | |
488 are key frames */ | |
489 pkt->flags |= PKT_FLAG_KEY; | |
490 } | |
491 } else { | |
492 pkt->flags |= PKT_FLAG_KEY; | |
493 } | |
457 | 494 if(ast->sample_size) |
495 ast->frame_offset += pkt->size; | |
496 else | |
497 ast->frame_offset++; | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
498 } |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
499 return size; |
519 | 500 } |
82 | 501 } |
520
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
502 /* palette changed chunk */ |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
503 if ( d[0] >= '0' && d[0] <= '9' |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
504 && d[1] >= '0' && d[1] <= '9' |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
505 && ((d[2] == 'p' && d[3] == 'c')) |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
506 && n < s->nb_streams && i + size <= avi->movi_end) { |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
507 |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
508 AVStream *st; |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
509 int first, clr, flags, k, p; |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
510 |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
511 st = s->streams[n]; |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
512 |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
513 first = get_byte(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
514 clr = get_byte(pb); |
584 | 515 if(!clr) /* all 256 colors used */ |
516 clr = 256; | |
520
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
517 flags = get_le16(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
518 p = 4; |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
519 for (k = first; k < clr + first; k++) { |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
520 int r, g, b; |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
521 r = get_byte(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
522 g = get_byte(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
523 b = get_byte(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
524 get_byte(pb); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
525 st->codec.palctrl->palette[k] = b + (g << 8) + (r << 16); |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
526 } |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
527 st->codec.palctrl->palette_changed = 1; |
569 | 528 goto resync; |
520
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
529 } |
5d96fe8f6560
added support for the elusive AVI palette change chunk, courtesy of
melanson
parents:
519
diff
changeset
|
530 |
82 | 531 } |
519 | 532 |
82 | 533 return -1; |
0 | 534 } |
535 | |
311 | 536 /* XXX: we make the implicit supposition that the position are sorted |
537 for each stream */ | |
538 static int avi_read_idx1(AVFormatContext *s, int size) | |
539 { | |
540 ByteIOContext *pb = &s->pb; | |
541 int nb_index_entries, i; | |
542 AVStream *st; | |
543 AVIStream *ast; | |
544 AVIIndexEntry *ie, *entries; | |
545 unsigned int index, tag, flags, pos, len; | |
546 | |
547 nb_index_entries = size / 16; | |
548 if (nb_index_entries <= 0) | |
549 return -1; | |
550 | |
551 /* read the entries and sort them in each stream component */ | |
552 for(i = 0; i < nb_index_entries; i++) { | |
553 tag = get_le32(pb); | |
554 flags = get_le32(pb); | |
555 pos = get_le32(pb); | |
556 len = get_le32(pb); | |
557 #if defined(DEBUG_SEEK) && 0 | |
558 printf("%d: tag=0x%x flags=0x%x pos=0x%x len=%d\n", | |
559 i, tag, flags, pos, len); | |
560 #endif | |
561 index = ((tag & 0xff) - '0') * 10; | |
562 index += ((tag >> 8) & 0xff) - '0'; | |
563 if (index >= s->nb_streams) | |
564 continue; | |
565 st = s->streams[index]; | |
566 ast = st->priv_data; | |
567 | |
568 entries = av_fast_realloc(ast->index_entries, | |
569 &ast->index_entries_allocated_size, | |
570 (ast->nb_index_entries + 1) * | |
571 sizeof(AVIIndexEntry)); | |
572 if (entries) { | |
573 ast->index_entries = entries; | |
574 ie = &entries[ast->nb_index_entries++]; | |
575 ie->flags = flags; | |
576 ie->pos = pos; | |
577 ie->cum_len = ast->cum_len; | |
578 ast->cum_len += len; | |
579 } | |
580 } | |
581 return 0; | |
582 } | |
583 | |
584 static int avi_load_index(AVFormatContext *s) | |
585 { | |
586 AVIContext *avi = s->priv_data; | |
587 ByteIOContext *pb = &s->pb; | |
588 uint32_t tag, size; | |
343 | 589 offset_t pos= url_ftell(pb); |
590 | |
311 | 591 url_fseek(pb, avi->movi_end, SEEK_SET); |
592 #ifdef DEBUG_SEEK | |
593 printf("movi_end=0x%llx\n", avi->movi_end); | |
594 #endif | |
595 for(;;) { | |
596 if (url_feof(pb)) | |
597 break; | |
598 tag = get_le32(pb); | |
599 size = get_le32(pb); | |
600 #ifdef DEBUG_SEEK | |
601 printf("tag=%c%c%c%c size=0x%x\n", | |
602 tag & 0xff, | |
603 (tag >> 8) & 0xff, | |
604 (tag >> 16) & 0xff, | |
605 (tag >> 24) & 0xff, | |
606 size); | |
607 #endif | |
608 switch(tag) { | |
609 case MKTAG('i', 'd', 'x', '1'): | |
610 if (avi_read_idx1(s, size) < 0) | |
611 goto skip; | |
612 else | |
613 goto the_end; | |
614 break; | |
615 default: | |
616 skip: | |
617 size += (size & 1); | |
618 url_fskip(pb, size); | |
619 break; | |
620 } | |
621 } | |
622 the_end: | |
343 | 623 url_fseek(pb, pos, SEEK_SET); |
311 | 624 return 0; |
625 } | |
626 | |
627 /* return the index entry whose position is immediately >= 'wanted_pos' */ | |
628 static int locate_frame_in_index(AVIIndexEntry *entries, | |
629 int nb_entries, int wanted_pos) | |
630 { | |
631 int a, b, m, pos; | |
632 | |
633 a = 0; | |
634 b = nb_entries - 1; | |
635 while (a <= b) { | |
636 m = (a + b) >> 1; | |
637 pos = entries[m].pos; | |
638 if (pos == wanted_pos) | |
639 goto found; | |
640 else if (pos > wanted_pos) { | |
641 b = m - 1; | |
642 } else { | |
643 a = m + 1; | |
644 } | |
645 } | |
646 m = a; | |
647 if (m > 0) | |
648 m--; | |
649 found: | |
650 return m; | |
651 } | |
652 | |
558 | 653 static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
311 | 654 { |
655 AVIContext *avi = s->priv_data; | |
656 AVStream *st; | |
657 AVIStream *ast; | |
658 int frame_number, i; | |
659 int64_t pos; | |
660 | |
661 if (!avi->index_loaded) { | |
662 /* we only load the index on demand */ | |
663 avi_load_index(s); | |
664 avi->index_loaded = 1; | |
665 } | |
666 if (stream_index < 0) { | |
667 for(i = 0; i < s->nb_streams; i++) { | |
668 st = s->streams[i]; | |
669 if (st->codec.codec_type == CODEC_TYPE_VIDEO) | |
670 goto found; | |
671 } | |
672 return -1; | |
673 found: | |
674 stream_index = i; | |
675 } | |
676 | |
677 st = s->streams[stream_index]; | |
678 if (st->codec.codec_type != CODEC_TYPE_VIDEO) | |
679 return -1; | |
680 ast = st->priv_data; | |
681 /* compute the frame number */ | |
466 | 682 frame_number = timestamp; |
311 | 683 #ifdef DEBUG_SEEK |
684 printf("timestamp=%0.3f nb_indexes=%d frame_number=%d\n", | |
685 (double)timestamp / AV_TIME_BASE, | |
686 ast->nb_index_entries, frame_number); | |
687 #endif | |
688 /* find a closest key frame before */ | |
689 if (frame_number >= ast->nb_index_entries) | |
690 return -1; | |
691 while (frame_number >= 0 && | |
692 !(ast->index_entries[frame_number].flags & AVIIF_INDEX)) | |
693 frame_number--; | |
694 if (frame_number < 0) | |
695 return -1; | |
696 ast->new_frame_offset = frame_number; | |
697 | |
698 /* find the position */ | |
699 pos = ast->index_entries[frame_number].pos; | |
700 | |
701 #ifdef DEBUG_SEEK | |
702 printf("key_frame_number=%d pos=0x%llx\n", | |
703 frame_number, pos); | |
704 #endif | |
705 | |
706 /* update the frame counters for all the other stream by looking | |
707 at the positions just after the one found */ | |
708 for(i = 0; i < s->nb_streams; i++) { | |
709 int j; | |
710 if (i != stream_index) { | |
711 st = s->streams[i]; | |
712 ast = st->priv_data; | |
713 if (ast->nb_index_entries <= 0) | |
714 return -1; | |
715 j = locate_frame_in_index(ast->index_entries, | |
716 ast->nb_index_entries, | |
717 pos); | |
718 /* get next frame */ | |
719 if ((j + 1) < ast->nb_index_entries) | |
720 j++; | |
721 /* extract the current frame number */ | |
457 | 722 if (ast->sample_size==0) |
311 | 723 ast->new_frame_offset = j; |
724 else | |
725 ast->new_frame_offset = ast->index_entries[j].cum_len; | |
726 } | |
727 } | |
728 | |
729 /* everything is OK now. We can update the frame offsets */ | |
730 for(i = 0; i < s->nb_streams; i++) { | |
731 st = s->streams[i]; | |
732 ast = st->priv_data; | |
733 ast->frame_offset = ast->new_frame_offset; | |
734 #ifdef DEBUG_SEEK | |
735 printf("%d: frame_offset=%d\n", i, | |
736 ast->frame_offset); | |
737 #endif | |
738 } | |
562
bf3231dd1d7c
* static allocation for audio packets. This will make it a little bit
romansh
parents:
558
diff
changeset
|
739 if (avi->dv_demux) |
bf3231dd1d7c
* static allocation for audio packets. This will make it a little bit
romansh
parents:
558
diff
changeset
|
740 dv_flush_audio_packets(avi->dv_demux); |
311 | 741 /* do the seek */ |
742 pos += avi->movi_list; | |
743 url_fseek(&s->pb, pos, SEEK_SET); | |
744 return 0; | |
745 } | |
746 | |
0 | 747 static int avi_read_close(AVFormatContext *s) |
748 { | |
110 | 749 int i; |
750 AVIContext *avi = s->priv_data; | |
751 | |
752 for(i=0;i<s->nb_streams;i++) { | |
753 AVStream *st = s->streams[i]; | |
311 | 754 AVIStream *ast = st->priv_data; |
340 | 755 if(ast){ |
756 av_free(ast->index_entries); | |
757 av_free(ast); | |
758 } | |
110 | 759 av_free(st->codec.extradata); |
297
85d558a18134
Make avi and asf demuxer export palette in palctrl
rtognimp
parents:
296
diff
changeset
|
760 av_free(st->codec.palctrl); |
110 | 761 } |
762 | |
262
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
763 if (avi->dv_demux) |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
764 av_free(avi->dv_demux); |
f174d9c00bce
* DV handling was streamlined for both muxing/demuxing and
romansh
parents:
227
diff
changeset
|
765 |
0 | 766 return 0; |
767 } | |
768 | |
769 static int avi_probe(AVProbeData *p) | |
770 { | |
771 /* check file header */ | |
772 if (p->buf_size <= 32) | |
773 return 0; | |
774 if (p->buf[0] == 'R' && p->buf[1] == 'I' && | |
775 p->buf[2] == 'F' && p->buf[3] == 'F' && | |
776 p->buf[8] == 'A' && p->buf[9] == 'V' && | |
777 p->buf[10] == 'I' && p->buf[11] == ' ') | |
778 return AVPROBE_SCORE_MAX; | |
779 else | |
780 return 0; | |
781 } | |
782 | |
783 static AVInputFormat avi_iformat = { | |
784 "avi", | |
785 "avi format", | |
786 sizeof(AVIContext), | |
787 avi_probe, | |
788 avi_read_header, | |
789 avi_read_packet, | |
790 avi_read_close, | |
311 | 791 avi_read_seek, |
0 | 792 }; |
793 | |
794 int avidec_init(void) | |
795 { | |
796 av_register_input_format(&avi_iformat); | |
797 return 0; | |
798 } |