Mercurial > libavformat.hg
annotate rmdec.c @ 2660:022174d849d5 libavformat
fix issue 225, instead of stoping when wrong atom size is found,
limit atom size to what is left, assuming container atom has correct size..
cricket4.3g2 has incorrect moov atom size which indicates that file size should be
2 bytes bigger than it is and quicktime reads it correctly though.
author | bcoudurier |
---|---|
date | Mon, 22 Oct 2007 14:36:14 +0000 |
parents | 67667d13bab5 |
children | 997fb1ac4783 |
rev | line source |
---|---|
0 | 1 /* |
2103 | 2 * "Real" compatible demuxer. |
0 | 3 * Copyright (c) 2000, 2001 Fabrice Bellard. |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
888
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
21 #include "avformat.h" | |
2103 | 22 #include "rm.h" |
2189 | 23 #include "avstring.h" |
0 | 24 |
2291 | 25 static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len) |
0 | 26 { |
2291 | 27 int i; |
2290
572f7077ba40
Fix get_str/get_str8() to also work if the target string is not long enough to
diego
parents:
2274
diff
changeset
|
28 char *q, r; |
0 | 29 |
30 q = buf; | |
31 for(i=0;i<len;i++) { | |
2290
572f7077ba40
Fix get_str/get_str8() to also work if the target string is not long enough to
diego
parents:
2274
diff
changeset
|
32 r = get_byte(pb); |
0 | 33 if (i < buf_size - 1) |
2290
572f7077ba40
Fix get_str/get_str8() to also work if the target string is not long enough to
diego
parents:
2274
diff
changeset
|
34 *q++ = r; |
0 | 35 } |
2290
572f7077ba40
Fix get_str/get_str8() to also work if the target string is not long enough to
diego
parents:
2274
diff
changeset
|
36 if (buf_size > 0) *q = '\0'; |
0 | 37 } |
38 | |
2291 | 39 static void get_str16(ByteIOContext *pb, char *buf, int buf_size) |
40 { | |
41 get_strl(pb, buf, buf_size, get_be16(pb)); | |
42 } | |
43 | |
0 | 44 static void get_str8(ByteIOContext *pb, char *buf, int buf_size) |
45 { | |
2291 | 46 get_strl(pb, buf, buf_size, get_byte(pb)); |
0 | 47 } |
48 | |
1106 | 49 static int rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, |
194 | 50 int read_all) |
51 { | |
879 | 52 RMContext *rm = s->priv_data; |
194 | 53 ByteIOContext *pb = &s->pb; |
886
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
54 char buf[256]; |
194 | 55 uint32_t version; |
56 int i; | |
57 | |
58 /* ra type header */ | |
59 version = get_be32(pb); /* version */ | |
60 if (((version >> 16) & 0xff) == 3) { | |
886
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
61 int64_t startpos = url_ftell(pb); |
194 | 62 /* very old version */ |
63 for(i = 0; i < 14; i++) | |
64 get_byte(pb); | |
65 get_str8(pb, s->title, sizeof(s->title)); | |
66 get_str8(pb, s->author, sizeof(s->author)); | |
67 get_str8(pb, s->copyright, sizeof(s->copyright)); | |
68 get_str8(pb, s->comment, sizeof(s->comment)); | |
886
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
69 if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) { |
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
70 // fourcc (should always be "lpcJ") |
194 | 71 get_byte(pb); |
72 get_str8(pb, buf, sizeof(buf)); | |
886
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
73 } |
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
74 // Skip extra header crap (this should never happen) |
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
75 if ((startpos + (version & 0xffff)) > url_ftell(pb)) |
7ed1351f8c7e
Fix for Real "old" files version 3 with no 4cc. Fixes thankyou144.ra
rtognimp
parents:
885
diff
changeset
|
76 url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb)); |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
77 st->codec->sample_rate = 8000; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
78 st->codec->channels = 1; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
79 st->codec->codec_type = CODEC_TYPE_AUDIO; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
80 st->codec->codec_id = CODEC_ID_RA_144; |
194 | 81 } else { |
879 | 82 int flavor, sub_packet_h, coded_framesize, sub_packet_size; |
194 | 83 /* old version (4) */ |
84 get_be32(pb); /* .ra4 */ | |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
85 get_be32(pb); /* data size */ |
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
86 get_be16(pb); /* version2 */ |
194 | 87 get_be32(pb); /* header size */ |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
88 flavor= get_be16(pb); /* add codec info / flavor */ |
879 | 89 rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */ |
194 | 90 get_be32(pb); /* ??? */ |
91 get_be32(pb); /* ??? */ | |
92 get_be32(pb); /* ??? */ | |
885 | 93 rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */ |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
94 st->codec->block_align= get_be16(pb); /* frame size */ |
879 | 95 rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */ |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
96 get_be16(pb); /* ??? */ |
879 | 97 if (((version >> 16) & 0xff) == 5) { |
98 get_be16(pb); get_be16(pb); get_be16(pb); } | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
99 st->codec->sample_rate = get_be16(pb); |
194 | 100 get_be32(pb); |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
101 st->codec->channels = get_be16(pb); |
879 | 102 if (((version >> 16) & 0xff) == 5) { |
103 get_be32(pb); | |
887 | 104 buf[0] = get_byte(pb); |
105 buf[1] = get_byte(pb); | |
106 buf[2] = get_byte(pb); | |
107 buf[3] = get_byte(pb); | |
108 buf[4] = 0; | |
109 } else { | |
1441
ad3b03b7b142
reindentation, patch by From: Steve Lhomme, slhomme divxcorp com
diego
parents:
1415
diff
changeset
|
110 get_str8(pb, buf, sizeof(buf)); /* desc */ |
ad3b03b7b142
reindentation, patch by From: Steve Lhomme, slhomme divxcorp com
diego
parents:
1415
diff
changeset
|
111 get_str8(pb, buf, sizeof(buf)); /* desc */ |
887 | 112 } |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
113 st->codec->codec_type = CODEC_TYPE_AUDIO; |
194 | 114 if (!strcmp(buf, "dnet")) { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
115 st->codec->codec_id = CODEC_ID_AC3; |
2585
ecd8a9aa182d
dnet audio needs avparser to work with the lavc ac3 decoder.
rtogni
parents:
2532
diff
changeset
|
116 st->need_parsing = AVSTREAM_PARSE_FULL; |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
117 } else if (!strcmp(buf, "28_8")) { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
118 st->codec->codec_id = CODEC_ID_RA_288; |
879 | 119 st->codec->extradata_size= 0; |
120 rm->audio_framesize = st->codec->block_align; | |
121 st->codec->block_align = coded_framesize; | |
1079 | 122 |
123 if(rm->audio_framesize >= UINT_MAX / sub_packet_h){ | |
124 av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n"); | |
125 return -1; | |
126 } | |
127 | |
879 | 128 rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); |
2024 | 129 } else if ((!strcmp(buf, "cook")) || (!strcmp(buf, "atrc"))) { |
879 | 130 int codecdata_length, i; |
131 get_be16(pb); get_byte(pb); | |
132 if (((version >> 16) & 0xff) == 5) | |
133 get_byte(pb); | |
134 codecdata_length = get_be32(pb); | |
1079 | 135 if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ |
136 av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); | |
137 return -1; | |
138 } | |
139 | |
2024 | 140 if (!strcmp(buf, "cook")) st->codec->codec_id = CODEC_ID_COOK; |
141 else st->codec->codec_id = CODEC_ID_ATRAC3; | |
879 | 142 st->codec->extradata_size= codecdata_length; |
884
2ece9c9dd94c
malloc padding to avoid reading past the malloc()ed area.
henry
parents:
879
diff
changeset
|
143 st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); |
879 | 144 for(i = 0; i < codecdata_length; i++) |
145 ((uint8_t*)st->codec->extradata)[i] = get_byte(pb); | |
146 rm->audio_framesize = st->codec->block_align; | |
147 st->codec->block_align = rm->sub_packet_size; | |
1079 | 148 |
149 if(rm->audio_framesize >= UINT_MAX / sub_packet_h){ | |
150 av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n"); | |
151 return -1; | |
152 } | |
153 | |
879 | 154 rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); |
1105 | 155 } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) { |
156 int codecdata_length, i; | |
157 get_be16(pb); get_byte(pb); | |
158 if (((version >> 16) & 0xff) == 5) | |
159 get_byte(pb); | |
160 st->codec->codec_id = CODEC_ID_AAC; | |
161 codecdata_length = get_be32(pb); | |
1106 | 162 if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ |
163 av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); | |
164 return -1; | |
165 } | |
1105 | 166 if (codecdata_length >= 1) { |
167 st->codec->extradata_size = codecdata_length - 1; | |
168 st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
169 get_byte(pb); | |
170 for(i = 0; i < st->codec->extradata_size; i++) | |
171 ((uint8_t*)st->codec->extradata)[i] = get_byte(pb); | |
172 } | |
194 | 173 } else { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
174 st->codec->codec_id = CODEC_ID_NONE; |
2189 | 175 av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name)); |
194 | 176 } |
177 if (read_all) { | |
178 get_byte(pb); | |
179 get_byte(pb); | |
180 get_byte(pb); | |
885 | 181 |
194 | 182 get_str8(pb, s->title, sizeof(s->title)); |
183 get_str8(pb, s->author, sizeof(s->author)); | |
184 get_str8(pb, s->copyright, sizeof(s->copyright)); | |
185 get_str8(pb, s->comment, sizeof(s->comment)); | |
186 } | |
187 } | |
1106 | 188 return 0; |
194 | 189 } |
190 | |
191 static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap) | |
192 { | |
193 RMContext *rm = s->priv_data; | |
194 AVStream *st; | |
195 | |
196 rm->old_format = 1; | |
197 st = av_new_stream(s, 0); | |
198 if (!st) | |
1106 | 199 return -1; |
200 return rm_read_audio_stream_info(s, st, 1); | |
194 | 201 } |
202 | |
0 | 203 static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
204 { | |
205 RMContext *rm = s->priv_data; | |
206 AVStream *st; | |
207 ByteIOContext *pb = &s->pb; | |
208 unsigned int tag, v; | |
209 int tag_size, size, codec_data_size, i; | |
65 | 210 int64_t codec_pos; |
1350
f77cf5a063a8
Remove unused variables and the corresponding warnings along with them.
diego
parents:
1344
diff
changeset
|
211 unsigned int start_time, duration; |
0 | 212 char buf[128]; |
213 int flags = 0; | |
214 | |
194 | 215 tag = get_le32(pb); |
216 if (tag == MKTAG('.', 'r', 'a', 0xfd)) { | |
217 /* very old .ra format */ | |
218 return rm_read_header_old(s, ap); | |
219 } else if (tag != MKTAG('.', 'R', 'M', 'F')) { | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2237
diff
changeset
|
220 return AVERROR(EIO); |
194 | 221 } |
0 | 222 |
223 get_be32(pb); /* header size */ | |
224 get_be16(pb); | |
225 get_be32(pb); | |
226 get_be32(pb); /* number of headers */ | |
885 | 227 |
0 | 228 for(;;) { |
229 if (url_feof(pb)) | |
230 goto fail; | |
231 tag = get_le32(pb); | |
232 tag_size = get_be32(pb); | |
233 get_be16(pb); | |
234 #if 0 | |
885 | 235 printf("tag=%c%c%c%c (%08x) size=%d\n", |
0 | 236 (tag) & 0xff, |
237 (tag >> 8) & 0xff, | |
238 (tag >> 16) & 0xff, | |
239 (tag >> 24) & 0xff, | |
240 tag, | |
241 tag_size); | |
242 #endif | |
736 | 243 if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A')) |
0 | 244 goto fail; |
245 switch(tag) { | |
246 case MKTAG('P', 'R', 'O', 'P'): | |
247 /* file header */ | |
248 get_be32(pb); /* max bit rate */ | |
249 get_be32(pb); /* avg bit rate */ | |
250 get_be32(pb); /* max packet size */ | |
251 get_be32(pb); /* avg packet size */ | |
252 get_be32(pb); /* nb packets */ | |
253 get_be32(pb); /* duration */ | |
254 get_be32(pb); /* preroll */ | |
255 get_be32(pb); /* index offset */ | |
256 get_be32(pb); /* data offset */ | |
257 get_be16(pb); /* nb streams */ | |
258 flags = get_be16(pb); /* flags */ | |
259 break; | |
260 case MKTAG('C', 'O', 'N', 'T'): | |
2291 | 261 get_str16(pb, s->title, sizeof(s->title)); |
262 get_str16(pb, s->author, sizeof(s->author)); | |
263 get_str16(pb, s->copyright, sizeof(s->copyright)); | |
264 get_str16(pb, s->comment, sizeof(s->comment)); | |
0 | 265 break; |
266 case MKTAG('M', 'D', 'P', 'R'): | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
267 st = av_new_stream(s, 0); |
0 | 268 if (!st) |
269 goto fail; | |
270 st->id = get_be16(pb); | |
271 get_be32(pb); /* max bit rate */ | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
272 st->codec->bit_rate = get_be32(pb); /* bit rate */ |
0 | 273 get_be32(pb); /* max packet size */ |
274 get_be32(pb); /* avg packet size */ | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
275 start_time = get_be32(pb); /* start time */ |
0 | 276 get_be32(pb); /* preroll */ |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
277 duration = get_be32(pb); /* duration */ |
743 | 278 st->start_time = start_time; |
279 st->duration = duration; | |
0 | 280 get_str8(pb, buf, sizeof(buf)); /* desc */ |
281 get_str8(pb, buf, sizeof(buf)); /* mimetype */ | |
282 codec_data_size = get_be32(pb); | |
283 codec_pos = url_ftell(pb); | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
284 st->codec->codec_type = CODEC_TYPE_DATA; |
607 | 285 av_set_pts_info(st, 64, 1, 1000); |
0 | 286 |
287 v = get_be32(pb); | |
288 if (v == MKTAG(0xfd, 'a', 'r', '.')) { | |
289 /* ra type header */ | |
1106 | 290 if (rm_read_audio_stream_info(s, st, 0)) |
291 return -1; | |
0 | 292 } else { |
604 | 293 int fps, fps2; |
0 | 294 if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) { |
295 fail1: | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
296 av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); |
593 | 297 goto skip; |
0 | 298 } |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
299 st->codec->codec_tag = get_le32(pb); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
300 // av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
301 if ( st->codec->codec_tag != MKTAG('R', 'V', '1', '0') |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
302 && st->codec->codec_tag != MKTAG('R', 'V', '2', '0') |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
303 && st->codec->codec_tag != MKTAG('R', 'V', '3', '0') |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
304 && st->codec->codec_tag != MKTAG('R', 'V', '4', '0')) |
0 | 305 goto fail1; |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
306 st->codec->width = get_be16(pb); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
307 st->codec->height = get_be16(pb); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
308 st->codec->time_base.num= 1; |
604 | 309 fps= get_be16(pb); |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
310 st->codec->codec_type = CODEC_TYPE_VIDEO; |
0 | 311 get_be32(pb); |
604 | 312 fps2= get_be16(pb); |
0 | 313 get_be16(pb); |
885 | 314 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
315 st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos); |
1079 | 316 |
317 if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ | |
318 //check is redundant as get_buffer() will catch this | |
319 av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n"); | |
320 return -1; | |
321 } | |
884
2ece9c9dd94c
malloc padding to avoid reading past the malloc()ed area.
henry
parents:
879
diff
changeset
|
322 st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
323 get_buffer(pb, st->codec->extradata, st->codec->extradata_size); |
885 | 324 |
604 | 325 // av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2); |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
326 st->codec->time_base.den = fps * st->codec->time_base.num; |
1344
770363b669aa
dont set sub_id as its completly redundant and silly
michael
parents:
1169
diff
changeset
|
327 switch(((uint8_t*)st->codec->extradata)[4]>>4){ |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
328 case 1: st->codec->codec_id = CODEC_ID_RV10; break; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
329 case 2: st->codec->codec_id = CODEC_ID_RV20; break; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
330 case 3: st->codec->codec_id = CODEC_ID_RV30; break; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
331 case 4: st->codec->codec_id = CODEC_ID_RV40; break; |
638 | 332 default: goto fail1; |
333 } | |
0 | 334 } |
593 | 335 skip: |
0 | 336 /* skip codec info */ |
337 size = url_ftell(pb) - codec_pos; | |
338 url_fskip(pb, codec_data_size - size); | |
339 break; | |
340 case MKTAG('D', 'A', 'T', 'A'): | |
341 goto header_end; | |
342 default: | |
343 /* unknown tag: skip it */ | |
344 url_fskip(pb, tag_size - 10); | |
345 break; | |
346 } | |
347 } | |
348 header_end: | |
349 rm->nb_packets = get_be32(pb); /* number of packets */ | |
350 if (!rm->nb_packets && (flags & 4)) | |
351 rm->nb_packets = 3600 * 25; | |
352 get_be32(pb); /* next data header */ | |
2653 | 353 rm->curpic_num = -1; |
0 | 354 return 0; |
355 | |
356 fail: | |
357 for(i=0;i<s->nb_streams;i++) { | |
358 av_free(s->streams[i]); | |
359 } | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2237
diff
changeset
|
360 return AVERROR(EIO); |
0 | 361 } |
362 | |
363 static int get_num(ByteIOContext *pb, int *len) | |
364 { | |
365 int n, n1; | |
366 | |
367 n = get_be16(pb); | |
368 (*len)-=2; | |
2653 | 369 n &= 0x7FFF; |
0 | 370 if (n >= 0x4000) { |
371 return n - 0x4000; | |
372 } else { | |
373 n1 = get_be16(pb); | |
374 (*len)-=2; | |
375 return (n << 16) | n1; | |
376 } | |
377 } | |
378 | |
194 | 379 /* multiple of 20 bytes for ra144 (ugly) */ |
380 #define RAW_PACKET_SIZE 1000 | |
381 | |
613 | 382 static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){ |
612 | 383 RMContext *rm = s->priv_data; |
384 ByteIOContext *pb = &s->pb; | |
385 int len, num, res, i; | |
386 AVStream *st; | |
632 | 387 uint32_t state=0xFFFFFFFF; |
612 | 388 |
389 while(!url_feof(pb)){ | |
613 | 390 *pos= url_ftell(pb); |
612 | 391 if(rm->remaining_len > 0){ |
392 num= rm->current_stream; | |
393 len= rm->remaining_len; | |
394 *timestamp = AV_NOPTS_VALUE; | |
395 *flags= 0; | |
396 }else{ | |
632 | 397 state= (state<<8) + get_byte(pb); |
885 | 398 |
632 | 399 if(state == MKBETAG('I', 'N', 'D', 'X')){ |
400 len = get_be16(pb) - 6; | |
401 if(len<0) | |
402 continue; | |
403 goto skip; | |
404 } | |
885 | 405 |
632 | 406 if(state > (unsigned)0xFFFF || state < 12) |
612 | 407 continue; |
632 | 408 len=state; |
409 state= 0xFFFFFFFF; | |
410 | |
612 | 411 num = get_be16(pb); |
412 *timestamp = get_be32(pb); | |
413 res= get_byte(pb); /* reserved */ | |
414 *flags = get_byte(pb); /* flags */ | |
613 | 415 |
885 | 416 |
612 | 417 len -= 12; |
418 } | |
419 for(i=0;i<s->nb_streams;i++) { | |
420 st = s->streams[i]; | |
421 if (num == st->id) | |
422 break; | |
423 } | |
424 if (i == s->nb_streams) { | |
632 | 425 skip: |
612 | 426 /* skip packet if unknown number */ |
427 url_fskip(pb, len); | |
428 rm->remaining_len -= len; | |
429 continue; | |
430 } | |
431 *stream_index= i; | |
885 | 432 |
612 | 433 return len; |
434 } | |
435 return -1; | |
436 } | |
437 | |
2653 | 438 static int rm_assemble_video_frame(AVFormatContext *s, RMContext *rm, AVPacket *pkt, int len) |
439 { | |
440 ByteIOContext *pb = &s->pb; | |
441 int hdr, seq, pic_num, len2, pos; | |
442 int type; | |
443 int ssize; | |
444 | |
445 hdr = get_byte(pb); len--; | |
446 type = hdr >> 6; | |
447 switch(type){ | |
448 case 0: // slice | |
449 case 2: // last slice | |
450 seq = get_byte(pb); len--; | |
451 len2 = get_num(pb, &len); | |
452 pos = get_num(pb, &len); | |
453 pic_num = get_byte(pb); len--; | |
454 rm->remaining_len = len; | |
455 break; | |
456 case 1: //whole frame | |
457 seq = get_byte(pb); len--; | |
458 if(av_new_packet(pkt, len + 9) < 0) | |
459 return AVERROR(EIO); | |
460 pkt->data[0] = 0; | |
461 AV_WL32(pkt->data + 1, 1); | |
462 AV_WL32(pkt->data + 5, 0); | |
463 get_buffer(pb, pkt->data + 9, len); | |
464 rm->remaining_len = 0; | |
465 return 0; | |
466 case 3: //frame as a part of packet | |
467 len2 = get_num(pb, &len); | |
468 pos = get_num(pb, &len); | |
469 pic_num = get_byte(pb); len--; | |
470 rm->remaining_len = len - len2; | |
471 if(av_new_packet(pkt, len2 + 9) < 0) | |
472 return AVERROR(EIO); | |
473 pkt->data[0] = 0; | |
474 AV_WL32(pkt->data + 1, 1); | |
475 AV_WL32(pkt->data + 5, 0); | |
476 get_buffer(pb, pkt->data + 9, len2); | |
477 return 0; | |
478 } | |
479 //now we have to deal with single slice | |
480 | |
481 if((seq & 0x7F) == 1 || rm->curpic_num != pic_num){ | |
482 rm->slices = ((hdr & 0x3F) << 1) + 1; | |
483 ssize = len2 + 8*rm->slices + 1; | |
484 rm->videobuf = av_realloc(rm->videobuf, ssize); | |
485 rm->videobufsize = ssize; | |
486 rm->videobufpos = 8*rm->slices + 1; | |
487 rm->cur_slice = 0; | |
488 rm->curpic_num = pic_num; | |
489 } | |
490 if(type == 2){ | |
491 len = FFMIN(len, pos); | |
492 pos = len2 - pos; | |
493 } | |
494 | |
495 if(++rm->cur_slice > rm->cur_slice) | |
496 return 1; | |
497 AV_WL32(rm->videobuf - 7 + 8*rm->cur_slice, 1); | |
498 AV_WL32(rm->videobuf - 3 + 8*rm->cur_slice, rm->videobufpos - 8*rm->slices - 1); | |
499 if(rm->videobufpos + len > rm->videobufsize) | |
500 return 1; | |
501 if (get_buffer(pb, rm->videobuf + rm->videobufpos, len) != len) | |
502 return AVERROR(EIO); | |
503 rm->videobufpos += len, | |
504 rm->remaining_len-= len; | |
505 | |
506 if(type == 2 || (rm->videobufpos) == rm->videobufsize){ | |
507 //adjust slice headers | |
508 memmove(rm->videobuf + 1 + 8*rm->cur_slice, rm->videobuf + 1 + 8*rm->slices, rm->videobufsize - 1 - 8*rm->slices); | |
509 ssize = rm->videobufsize - 8*(rm->slices - rm->cur_slice); | |
510 | |
511 rm->videobuf[0] = rm->cur_slice-1; | |
512 if(av_new_packet(pkt, ssize) < 0) | |
513 return AVERROR(ENOMEM); | |
514 memcpy(pkt->data, rm->videobuf, ssize); | |
515 return 0; | |
516 } | |
517 | |
518 return 1; | |
519 } | |
520 | |
0 | 521 static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) |
522 { | |
523 RMContext *rm = s->priv_data; | |
524 ByteIOContext *pb = &s->pb; | |
525 AVStream *st; | |
2105 | 526 int i, len, j; |
613 | 527 int64_t timestamp, pos; |
65 | 528 uint8_t *ptr; |
612 | 529 int flags; |
0 | 530 |
888 | 531 if (rm->audio_pkt_cnt) { |
879 | 532 // If there are queued audio packet return them first |
533 st = s->streams[rm->audio_stream_num]; | |
1105 | 534 if (st->codec->codec_id == CODEC_ID_AAC) |
535 av_get_packet(pb, pkt, rm->sub_packet_lengths[rm->sub_packet_cnt - rm->audio_pkt_cnt]); | |
536 else { | |
879 | 537 av_new_packet(pkt, st->codec->block_align); |
538 memcpy(pkt->data, rm->audiobuf + st->codec->block_align * | |
539 (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), | |
540 st->codec->block_align); | |
1105 | 541 } |
879 | 542 rm->audio_pkt_cnt--; |
543 pkt->flags = 0; | |
544 pkt->stream_index = rm->audio_stream_num; | |
888 | 545 } else if (rm->old_format) { |
546 st = s->streams[0]; | |
547 if (st->codec->codec_id == CODEC_ID_RA_288) { | |
548 int x, y; | |
549 | |
550 for (y = 0; y < rm->sub_packet_h; y++) | |
551 for (x = 0; x < rm->sub_packet_h/2; x++) | |
552 if (get_buffer(pb, rm->audiobuf+x*2*rm->audio_framesize+y*rm->coded_framesize, rm->coded_framesize) <= 0) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2237
diff
changeset
|
553 return AVERROR(EIO); |
888 | 554 rm->audio_stream_num = 0; |
555 rm->audio_pkt_cnt = rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - 1; | |
556 // Release first audio packet | |
557 av_new_packet(pkt, st->codec->block_align); | |
558 memcpy(pkt->data, rm->audiobuf, st->codec->block_align); | |
559 pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe | |
560 pkt->stream_index = 0; | |
561 } else { | |
562 /* just read raw bytes */ | |
563 len = RAW_PACKET_SIZE; | |
564 len= av_get_packet(pb, pkt, len); | |
565 pkt->stream_index = 0; | |
566 if (len <= 0) { | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2237
diff
changeset
|
567 return AVERROR(EIO); |
888 | 568 } |
569 pkt->size = len; | |
570 } | |
194 | 571 } else { |
613 | 572 int seq=1; |
652 | 573 resync: |
613 | 574 len=sync(s, ×tamp, &flags, &i, &pos); |
612 | 575 if(len<0) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2237
diff
changeset
|
576 return AVERROR(EIO); |
612 | 577 st = s->streams[i]; |
578 | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
579 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
609 | 580 rm->current_stream= st->id; |
2653 | 581 if(rm_assemble_video_frame(s, rm, pkt, len) == 1) |
582 goto resync;//got partial frame | |
1970
a27976be3394
Do not return invalid pointer for non-audio or video streams.
rtogni
parents:
1443
diff
changeset
|
583 } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { |
879 | 584 if ((st->codec->codec_id == CODEC_ID_RA_288) || |
2024 | 585 (st->codec->codec_id == CODEC_ID_COOK) || |
586 (st->codec->codec_id == CODEC_ID_ATRAC3)) { | |
879 | 587 int x; |
588 int sps = rm->sub_packet_size; | |
589 int cfs = rm->coded_framesize; | |
590 int h = rm->sub_packet_h; | |
591 int y = rm->sub_packet_cnt; | |
592 int w = rm->audio_framesize; | |
593 | |
594 if (flags & 2) | |
595 y = rm->sub_packet_cnt = 0; | |
596 if (!y) | |
597 rm->audiotimestamp = timestamp; | |
598 | |
599 switch(st->codec->codec_id) { | |
600 case CODEC_ID_RA_288: | |
601 for (x = 0; x < h/2; x++) | |
602 get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs); | |
603 break; | |
2024 | 604 case CODEC_ID_ATRAC3: |
879 | 605 case CODEC_ID_COOK: |
606 for (x = 0; x < w/sps; x++) | |
607 get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps); | |
608 break; | |
609 } | |
610 | |
611 if (++(rm->sub_packet_cnt) < h) | |
612 goto resync; | |
613 else { | |
614 rm->sub_packet_cnt = 0; | |
615 rm->audio_stream_num = i; | |
616 rm->audio_pkt_cnt = h * w / st->codec->block_align - 1; | |
617 // Release first audio packet | |
618 av_new_packet(pkt, st->codec->block_align); | |
619 memcpy(pkt->data, rm->audiobuf, st->codec->block_align); | |
620 timestamp = rm->audiotimestamp; | |
621 flags = 2; // Mark first packet as keyframe | |
622 } | |
1105 | 623 } else if (st->codec->codec_id == CODEC_ID_AAC) { |
624 int x; | |
625 rm->audio_stream_num = i; | |
626 rm->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4; | |
627 if (rm->sub_packet_cnt) { | |
628 for (x = 0; x < rm->sub_packet_cnt; x++) | |
629 rm->sub_packet_lengths[x] = get_be16(pb); | |
630 // Release first audio packet | |
631 rm->audio_pkt_cnt = rm->sub_packet_cnt - 1; | |
632 av_get_packet(pb, pkt, rm->sub_packet_lengths[0]); | |
633 flags = 2; // Mark first packet as keyframe | |
634 } | |
879 | 635 } else |
636 av_get_packet(pb, pkt, len); | |
1970
a27976be3394
Do not return invalid pointer for non-audio or video streams.
rtogni
parents:
1443
diff
changeset
|
637 |
a27976be3394
Do not return invalid pointer for non-audio or video streams.
rtogni
parents:
1443
diff
changeset
|
638 } else |
a27976be3394
Do not return invalid pointer for non-audio or video streams.
rtogni
parents:
1443
diff
changeset
|
639 av_get_packet(pb, pkt, len); |
652 | 640 |
708 | 641 if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) |
642 || st->discard >= AVDISCARD_ALL){ | |
879 | 643 av_free_packet(pkt); |
652 | 644 goto resync; |
645 } | |
885 | 646 |
194 | 647 pkt->stream_index = i; |
607 | 648 |
649 #if 0 | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
650 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
651 if(st->codec->codec_id == CODEC_ID_RV20){ |
607 | 652 int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1); |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1441
diff
changeset
|
653 av_log(NULL, AV_LOG_DEBUG, "%d %"PRId64" %d\n", timestamp, timestamp*512LL/25, seq); |
607 | 654 |
655 seq |= (timestamp&~0x3FFF); | |
656 if(seq - timestamp > 0x2000) seq -= 0x4000; | |
657 if(seq - timestamp < -0x2000) seq += 0x4000; | |
658 } | |
659 } | |
660 #endif | |
661 pkt->pts= timestamp; | |
613 | 662 if(flags&2){ |
607 | 663 pkt->flags |= PKT_FLAG_KEY; |
613 | 664 if((seq&0x7F) == 1) |
979 | 665 av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME); |
613 | 666 } |
0 | 667 } |
668 | |
669 /* for AC3, needs to swap bytes */ | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
670 if (st->codec->codec_id == CODEC_ID_AC3) { |
0 | 671 ptr = pkt->data; |
2237 | 672 for(j=0;j<pkt->size;j+=2) { |
2105 | 673 FFSWAP(int, ptr[0], ptr[1]); |
2104 | 674 ptr += 2; |
0 | 675 } |
676 } | |
677 return 0; | |
678 } | |
679 | |
680 static int rm_read_close(AVFormatContext *s) | |
681 { | |
879 | 682 RMContext *rm = s->priv_data; |
683 | |
684 av_free(rm->audiobuf); | |
2653 | 685 av_free(rm->videobuf); |
0 | 686 return 0; |
687 } | |
688 | |
689 static int rm_probe(AVProbeData *p) | |
690 { | |
691 /* check file header */ | |
194 | 692 if ((p->buf[0] == '.' && p->buf[1] == 'R' && |
693 p->buf[2] == 'M' && p->buf[3] == 'F' && | |
694 p->buf[4] == 0 && p->buf[5] == 0) || | |
695 (p->buf[0] == '.' && p->buf[1] == 'r' && | |
696 p->buf[2] == 'a' && p->buf[3] == 0xfd)) | |
0 | 697 return AVPROBE_SCORE_MAX; |
698 else | |
699 return 0; | |
700 } | |
701 | |
885 | 702 static int64_t rm_read_dts(AVFormatContext *s, int stream_index, |
612 | 703 int64_t *ppos, int64_t pos_limit) |
704 { | |
705 RMContext *rm = s->priv_data; | |
706 int64_t pos, dts; | |
613 | 707 int stream_index2, flags, len, h; |
612 | 708 |
709 pos = *ppos; | |
885 | 710 |
612 | 711 if(rm->old_format) |
712 return AV_NOPTS_VALUE; | |
713 | |
714 url_fseek(&s->pb, pos, SEEK_SET); | |
715 rm->remaining_len=0; | |
716 for(;;){ | |
613 | 717 int seq=1; |
718 AVStream *st; | |
719 | |
720 len=sync(s, &dts, &flags, &stream_index2, &pos); | |
612 | 721 if(len<0) |
722 return AV_NOPTS_VALUE; | |
613 | 723 |
724 st = s->streams[stream_index2]; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
725 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
613 | 726 h= get_byte(&s->pb); len--; |
727 if(!(h & 0x40)){ | |
728 seq = get_byte(&s->pb); len--; | |
612 | 729 } |
730 } | |
885 | 731 |
613 | 732 if((flags&2) && (seq&0x7F) == 1){ |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1441
diff
changeset
|
733 // av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq); |
979 | 734 av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME); |
613 | 735 if(stream_index2 == stream_index) |
736 break; | |
737 } | |
738 | |
612 | 739 url_fskip(&s->pb, len); |
740 } | |
741 *ppos = pos; | |
742 return dts; | |
743 } | |
744 | |
1169 | 745 AVInputFormat rm_demuxer = { |
0 | 746 "rm", |
747 "rm format", | |
748 sizeof(RMContext), | |
749 rm_probe, | |
750 rm_read_header, | |
751 rm_read_packet, | |
752 rm_read_close, | |
612 | 753 NULL, |
754 rm_read_dts, | |
0 | 755 }; |