OpenDML AVI > 2Gb support patch by (Roman Shaposhnick <rvs at sun dot com>)
[ffmpeg.git] / libavformat / avidec.c
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"
21
22 //#define DEBUG
23
24 typedef struct AVIIndex {
25     unsigned char tag[4];
26     unsigned int flags, pos, len;
27     struct AVIIndex *next;
28 } AVIIndex;
29
30 typedef struct {
31     int64_t riff_end;
32     int64_t movi_end;
33     offset_t movi_list;
34     AVIIndex *first, *last;
35 } AVIContext;
36
37 #ifdef DEBUG
38 static void print_tag(const char *str, unsigned int tag, int size)
39 {
40     printf("%s: tag=%c%c%c%c size=0x%x\n",
41            str, tag & 0xff,
42            (tag >> 8) & 0xff,
43            (tag >> 16) & 0xff,
44            (tag >> 24) & 0xff,
45            size);
46 }
47 #endif
48
49 static int get_riff(AVIContext *avi, ByteIOContext *pb)
50 {
51     uint32_t tag; 
52     /* check RIFF header */
53     tag = get_le32(pb);
54
55     if (tag != MKTAG('R', 'I', 'F', 'F'))
56         return -1;
57     avi->riff_end = get_le32(pb);   /* RIFF chunk size */
58     avi->riff_end += url_ftell(pb); /* RIFF chunk end */
59     tag = get_le32(pb);
60     if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X'))
61         return -1;
62     
63     return 0;
64 }
65
66 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
67 {
68     AVIContext *avi = s->priv_data;
69     ByteIOContext *pb = &s->pb;
70     uint32_t tag, tag1;
71     int codec_type, stream_index, frame_period, bit_rate, scale, rate;
72     unsigned int size;
73     int i;
74     AVStream *st;
75
76     if (get_riff(avi, pb) < 0)
77         return -1;
78
79     /* first list tag */
80     stream_index = -1;
81     codec_type = -1;
82     frame_period = 0;
83     for(;;) {
84         if (url_feof(pb))
85             goto fail;
86         tag = get_le32(pb);
87         size = get_le32(pb);
88 #ifdef DEBUG
89         print_tag("tag", tag, size);
90 #endif
91
92         switch(tag) {
93         case MKTAG('L', 'I', 'S', 'T'):
94             /* ignored, except when start of video packets */
95             tag1 = get_le32(pb);
96 #ifdef DEBUG
97             print_tag("list", tag1, 0);
98 #endif
99             if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
100                 avi->movi_end = url_ftell(pb) + size - 4;
101 #ifdef DEBUG
102                 printf("movi end=%Lx\n", avi->movi_end);
103 #endif
104                 goto end_of_header;
105             }
106             break;
107         case MKTAG('a', 'v', 'i', 'h'):
108             /* avi header */
109             /* using frame_period is bad idea */
110             frame_period = get_le32(pb);
111             bit_rate = get_le32(pb) * 8;
112             url_fskip(pb, 4 * 4);
113             s->nb_streams = get_le32(pb);
114             for(i=0;i<s->nb_streams;i++) {
115                 AVStream *st = av_mallocz(sizeof(AVStream));
116                 if (!st)
117                     goto fail;
118                 avcodec_get_context_defaults(&st->codec);
119
120                 s->streams[i] = st;
121             }
122             url_fskip(pb, size - 7 * 4);
123             break;
124         case MKTAG('s', 't', 'r', 'h'):
125             /* stream header */
126             stream_index++;
127             tag1 = get_le32(pb);
128             switch(tag1) {
129             case MKTAG('v', 'i', 'd', 's'):
130                 codec_type = CODEC_TYPE_VIDEO;
131
132                 if (stream_index >= s->nb_streams) {
133                     url_fskip(pb, size - 4);
134                     break;
135                 } 
136
137                 st = s->streams[stream_index];
138
139                 get_le32(pb); /* codec tag */
140                 get_le32(pb); /* flags */
141                 get_le16(pb); /* priority */
142                 get_le16(pb); /* language */
143                 get_le32(pb); /* XXX: initial frame ? */
144                 scale= get_le32(pb); /* scale */
145                 rate= get_le32(pb); /* rate */
146
147                 if(scale && rate){
148                     st->codec.frame_rate = rate;
149                     st->codec.frame_rate_base= scale;
150                 }else if(frame_period){
151                     st->codec.frame_rate = 1000000;
152                     st->codec.frame_rate_base= frame_period;
153                 }else{
154                     st->codec.frame_rate = 25;
155                     st->codec.frame_rate_base = 1;
156                 }
157                 
158                 url_fskip(pb, size - 7 * 4);
159                 break;
160             case MKTAG('a', 'u', 'd', 's'):
161                 codec_type = CODEC_TYPE_AUDIO;
162                 /* nothing really useful */
163                 url_fskip(pb, size - 4);
164                 break;
165             default:
166                 goto fail;
167             }
168             break;
169         case MKTAG('s', 't', 'r', 'f'):
170             /* stream header */
171             if (stream_index >= s->nb_streams) {
172                 url_fskip(pb, size);
173             } else {
174                 st = s->streams[stream_index];
175                 switch(codec_type) {
176                 case CODEC_TYPE_VIDEO:
177                     get_le32(pb); /* size */
178                     st->codec.width = get_le32(pb);
179                     st->codec.height = get_le32(pb);
180                     get_le16(pb); /* panes */
181                     st->codec.bits_per_sample= get_le16(pb); /* depth */
182                     tag1 = get_le32(pb);
183                     get_le32(pb); /* ImageSize */
184                     get_le32(pb); /* XPelsPerMeter */
185                     get_le32(pb); /* YPelsPerMeter */
186                     get_le32(pb); /* ClrUsed */
187                     get_le32(pb); /* ClrImportant */
188
189                     st->codec.extradata_size= size - 10*4;
190                     st->codec.extradata= av_malloc(st->codec.extradata_size); //FIXME where should we free this?
191                     get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
192                     
193                     if(st->codec.extradata_size & 1) //FIXME check if the encoder really did this correctly
194                         get_byte(pb);
195
196 #ifdef DEBUG
197                     print_tag("video", tag1, 0);
198 #endif
199                     st->codec.codec_type = CODEC_TYPE_VIDEO;
200                     st->codec.codec_tag = tag1;
201                     st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
202 //                    url_fskip(pb, size - 5 * 4);
203                     break;
204                 case CODEC_TYPE_AUDIO:
205                     get_wav_header(pb, &st->codec, size);
206                     if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
207                         url_fskip(pb, 1);
208                     break;
209                 default:
210                     url_fskip(pb, size);
211                     break;
212                 }
213             }
214             break;
215         default:
216             /* skip tag */
217             size += (size & 1);
218             url_fskip(pb, size);
219             break;
220         }
221     }
222  end_of_header:
223     /* check stream number */
224     if (stream_index != s->nb_streams - 1) {
225     fail:
226         for(i=0;i<s->nb_streams;i++) {
227             av_freep(&s->streams[i]->codec.extradata);
228             av_freep(&s->streams[i]);
229         }
230         return -1;
231     }
232
233     return 0;
234 }
235
236 static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
237 {
238     AVIContext *avi = s->priv_data;
239     ByteIOContext *pb = &s->pb;
240     int n, d[8], size, i;
241     
242     memset(d, -1, sizeof(int)*8);
243
244     for(i=url_ftell(pb); !url_feof(pb); i++) {
245         int j;
246
247         if (i >= avi->movi_end) { /* Let's see if it's an OpenDML AVI */
248             uint32_t tag, size, tag2;
249             url_fskip(pb, avi->riff_end - url_ftell(pb));
250             if (get_riff(avi, pb) < 0)
251                 return -1;
252             
253             tag = get_le32(pb);
254             size = get_le32(pb);
255             tag2 = get_le32(pb);
256             if (tag == MKTAG('L','I','S','T') && tag2 == MKTAG('m','o','v','i'))
257                 avi->movi_end = url_ftell(pb) + size - 4; 
258             else
259                 return -1;
260         }
261
262         for(j=0; j<7; j++)
263             d[j]= d[j+1];
264         d[7]= get_byte(pb);
265         
266         size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
267         
268         //parse ix##
269         n= (d[2] - '0') * 10 + (d[3] - '0');
270         if(    d[2] >= '0' && d[2] <= '9'
271             && d[3] >= '0' && d[3] <= '9'
272             && d[0] == 'i' && d[1] == 'x'
273             && n < s->nb_streams
274             && i + size <= avi->movi_end){
275             
276             url_fskip(pb, size);
277         }
278         
279         //parse ##dc/##wb
280         n= (d[0] - '0') * 10 + (d[1] - '0');
281         if(    d[0] >= '0' && d[0] <= '9'
282             && d[1] >= '0' && d[1] <= '9'
283             &&((d[2] == 'd' && d[3] == 'c') || (d[2] == 'w' && d[3] == 'b') || (d[2] == 'd' && d[3] == 'b') )
284
285             && n < s->nb_streams
286             && i + size <= avi->movi_end){
287         
288             av_new_packet(pkt, size);
289             pkt->stream_index = n;
290
291             get_buffer(pb, pkt->data, pkt->size);
292
293             if (size & 1)
294                 get_byte(pb);
295  
296             return 0;
297         }
298     }
299     
300     return -1;
301 }
302
303 static int avi_read_close(AVFormatContext *s)
304 {
305     return 0;
306 }
307
308 static int avi_probe(AVProbeData *p)
309 {
310     /* check file header */
311     if (p->buf_size <= 32)
312         return 0;
313     if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
314         p->buf[2] == 'F' && p->buf[3] == 'F' &&
315         p->buf[8] == 'A' && p->buf[9] == 'V' &&
316         p->buf[10] == 'I' && p->buf[11] == ' ')
317         return AVPROBE_SCORE_MAX;
318     else
319         return 0;
320 }
321
322 static AVInputFormat avi_iformat = {
323     "avi",
324     "avi format",
325     sizeof(AVIContext),
326     avi_probe,
327     avi_read_header,
328     avi_read_packet,
329     avi_read_close,
330 };
331
332 int avidec_init(void)
333 {
334     av_register_input_format(&avi_iformat);
335     return 0;
336 }