Commit | Line | Data |
---|---|---|
de6d9b64 | 1 | /* |
7b2a2ce5 | 2 | * "Real" compatible demuxer. |
19720f15 | 3 | * Copyright (c) 2000, 2001 Fabrice Bellard. |
de6d9b64 | 4 | * |
b78e7197 DB |
5 | * This file is part of FFmpeg. |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
19720f15 FB |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
de6d9b64 | 11 | * |
b78e7197 | 12 | * FFmpeg is distributed in the hope that it will be useful, |
de6d9b64 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 FB |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. | |
de6d9b64 | 16 | * |
19720f15 | 17 | * You should have received a copy of the GNU Lesser General Public |
b78e7197 | 18 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
de6d9b64 | 20 | */ |
245976da DB |
21 | |
22 | #include "libavutil/avstring.h" | |
de6d9b64 | 23 | #include "avformat.h" |
ba614729 | 24 | #include "rm.h" |
1edddc99 | 25 | |
ba614729 | 26 | struct RMStream { |
0b4ff0c9 | 27 | AVPacket pkt; ///< place to store merged video frame / reordered audio data |
1edddc99 RB |
28 | int videobufsize; ///< current assembled frame size |
29 | int videobufpos; ///< position for the next slice in the video buffer | |
30 | int curpic_num; ///< picture number of current frame | |
31 | int cur_slice, slices; | |
32 | int64_t pktpos; ///< first slice position in file | |
33 | /// Audio descrambling matrix parameters | |
1edddc99 RB |
34 | int64_t audiotimestamp; ///< Audio packet timestamp |
35 | int sub_packet_cnt; // Subpacket counter, used while reading | |
36 | int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container | |
ba614729 RB |
37 | int audio_framesize; /// Audio frame size from container |
38 | int sub_packet_lengths[16]; /// Length of each subpacket | |
39 | }; | |
40 | ||
41 | typedef struct { | |
42 | int nb_packets; | |
43 | int old_format; | |
44 | int current_stream; | |
45 | int remaining_len; | |
1edddc99 RB |
46 | int audio_stream_num; ///< Stream number for audio packets |
47 | int audio_pkt_cnt; ///< Output packet counter | |
1edddc99 | 48 | } RMDemuxContext; |
de6d9b64 | 49 | |
36cf20f5 | 50 | static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len) |
de6d9b64 | 51 | { |
36cf20f5 | 52 | int i; |
28263f5f | 53 | char *q, r; |
de6d9b64 | 54 | |
de6d9b64 FB |
55 | q = buf; |
56 | for(i=0;i<len;i++) { | |
28263f5f | 57 | r = get_byte(pb); |
de6d9b64 | 58 | if (i < buf_size - 1) |
28263f5f | 59 | *q++ = r; |
de6d9b64 | 60 | } |
28263f5f | 61 | if (buf_size > 0) *q = '\0'; |
de6d9b64 FB |
62 | } |
63 | ||
36cf20f5 | 64 | static void get_str16(ByteIOContext *pb, char *buf, int buf_size) |
de6d9b64 | 65 | { |
36cf20f5 RB |
66 | get_strl(pb, buf, buf_size, get_be16(pb)); |
67 | } | |
de6d9b64 | 68 | |
36cf20f5 RB |
69 | static void get_str8(ByteIOContext *pb, char *buf, int buf_size) |
70 | { | |
71 | get_strl(pb, buf, buf_size, get_byte(pb)); | |
de6d9b64 FB |
72 | } |
73 | ||
ba614729 RB |
74 | RMStream *ff_rm_alloc_rmstream (void) |
75 | { | |
76 | RMStream *rms = av_mallocz(sizeof(RMStream)); | |
77 | rms->curpic_num = -1; | |
78 | return rms; | |
79 | } | |
80 | ||
81 | void ff_rm_free_rmstream (RMStream *rms) | |
82 | { | |
0b4ff0c9 | 83 | av_free_packet(&rms->pkt); |
ba614729 RB |
84 | } |
85 | ||
fcc995a5 | 86 | static int rm_read_audio_stream_info(AVFormatContext *s, ByteIOContext *pb, |
886e89d0 | 87 | AVStream *st, RMStream *ast, int read_all) |
c9510803 | 88 | { |
1e4668d1 | 89 | char buf[256]; |
c9510803 | 90 | uint32_t version; |
c9510803 FB |
91 | |
92 | /* ra type header */ | |
93 | version = get_be32(pb); /* version */ | |
94 | if (((version >> 16) & 0xff) == 3) { | |
1e4668d1 | 95 | int64_t startpos = url_ftell(pb); |
b9b2b8c9 | 96 | url_fskip(pb, 14); |
c9510803 FB |
97 | get_str8(pb, s->title, sizeof(s->title)); |
98 | get_str8(pb, s->author, sizeof(s->author)); | |
99 | get_str8(pb, s->copyright, sizeof(s->copyright)); | |
100 | get_str8(pb, s->comment, sizeof(s->comment)); | |
1e4668d1 | 101 | if ((startpos + (version & 0xffff)) >= url_ftell(pb) + 2) { |
76f940b2 RB |
102 | // fourcc (should always be "lpcJ") |
103 | get_byte(pb); | |
104 | get_str8(pb, buf, sizeof(buf)); | |
1e4668d1 RT |
105 | } |
106 | // Skip extra header crap (this should never happen) | |
107 | if ((startpos + (version & 0xffff)) > url_ftell(pb)) | |
108 | url_fskip(pb, (version & 0xffff) + startpos - url_ftell(pb)); | |
01f4895c MN |
109 | st->codec->sample_rate = 8000; |
110 | st->codec->channels = 1; | |
111 | st->codec->codec_type = CODEC_TYPE_AUDIO; | |
112 | st->codec->codec_id = CODEC_ID_RA_144; | |
c9510803 | 113 | } else { |
e0f7e329 | 114 | int flavor, sub_packet_h, coded_framesize, sub_packet_size; |
c9510803 FB |
115 | /* old version (4) */ |
116 | get_be32(pb); /* .ra4 */ | |
72aef198 MN |
117 | get_be32(pb); /* data size */ |
118 | get_be16(pb); /* version2 */ | |
c9510803 | 119 | get_be32(pb); /* header size */ |
72aef198 | 120 | flavor= get_be16(pb); /* add codec info / flavor */ |
ba614729 | 121 | ast->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */ |
c9510803 FB |
122 | get_be32(pb); /* ??? */ |
123 | get_be32(pb); /* ??? */ | |
124 | get_be32(pb); /* ??? */ | |
ba614729 | 125 | ast->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */ |
01f4895c | 126 | st->codec->block_align= get_be16(pb); /* frame size */ |
ba614729 | 127 | ast->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */ |
72aef198 | 128 | get_be16(pb); /* ??? */ |
e0f7e329 | 129 | if (((version >> 16) & 0xff) == 5) { |
127ed7b0 RB |
130 | get_be16(pb); get_be16(pb); get_be16(pb); |
131 | } | |
01f4895c | 132 | st->codec->sample_rate = get_be16(pb); |
c9510803 | 133 | get_be32(pb); |
01f4895c | 134 | st->codec->channels = get_be16(pb); |
e0f7e329 BL |
135 | if (((version >> 16) & 0xff) == 5) { |
136 | get_be32(pb); | |
b9b2b8c9 | 137 | get_buffer(pb, buf, 4); |
bb270c08 DB |
138 | buf[4] = 0; |
139 | } else { | |
e344c1ea SH |
140 | get_str8(pb, buf, sizeof(buf)); /* desc */ |
141 | get_str8(pb, buf, sizeof(buf)); /* desc */ | |
bb270c08 | 142 | } |
01f4895c | 143 | st->codec->codec_type = CODEC_TYPE_AUDIO; |
c9510803 | 144 | if (!strcmp(buf, "dnet")) { |
01f4895c | 145 | st->codec->codec_id = CODEC_ID_AC3; |
bf415121 | 146 | st->need_parsing = AVSTREAM_PARSE_FULL; |
72aef198 | 147 | } else if (!strcmp(buf, "28_8")) { |
01f4895c | 148 | st->codec->codec_id = CODEC_ID_RA_288; |
e0f7e329 | 149 | st->codec->extradata_size= 0; |
ba614729 | 150 | ast->audio_framesize = st->codec->block_align; |
e0f7e329 | 151 | st->codec->block_align = coded_framesize; |
a443a253 | 152 | |
ba614729 RB |
153 | if(ast->audio_framesize >= UINT_MAX / sub_packet_h){ |
154 | av_log(s, AV_LOG_ERROR, "ast->audio_framesize * sub_packet_h too large\n"); | |
a443a253 MN |
155 | return -1; |
156 | } | |
157 | ||
0b4ff0c9 | 158 | av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h); |
2426bb96 | 159 | } else if ((!strcmp(buf, "cook")) || (!strcmp(buf, "atrc")) || (!strcmp(buf, "sipr"))) { |
b9b2b8c9 | 160 | int codecdata_length; |
e0f7e329 BL |
161 | get_be16(pb); get_byte(pb); |
162 | if (((version >> 16) & 0xff) == 5) | |
163 | get_byte(pb); | |
164 | codecdata_length = get_be32(pb); | |
a443a253 MN |
165 | if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ |
166 | av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); | |
167 | return -1; | |
168 | } | |
169 | ||
f23938f5 MN |
170 | if(sub_packet_size <= 0){ |
171 | av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n"); | |
172 | return -1; | |
173 | } | |
174 | ||
10e26bc7 | 175 | if (!strcmp(buf, "cook")) st->codec->codec_id = CODEC_ID_COOK; |
2426bb96 | 176 | else if (!strcmp(buf, "sipr")) st->codec->codec_id = CODEC_ID_SIPR; |
10e26bc7 | 177 | else st->codec->codec_id = CODEC_ID_ATRAC3; |
e0f7e329 | 178 | st->codec->extradata_size= codecdata_length; |
d76319b1 | 179 | st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); |
b9b2b8c9 | 180 | get_buffer(pb, st->codec->extradata, st->codec->extradata_size); |
ba614729 RB |
181 | ast->audio_framesize = st->codec->block_align; |
182 | st->codec->block_align = ast->sub_packet_size; | |
a443a253 | 183 | |
ba614729 | 184 | if(ast->audio_framesize >= UINT_MAX / sub_packet_h){ |
a443a253 MN |
185 | av_log(s, AV_LOG_ERROR, "rm->audio_framesize * sub_packet_h too large\n"); |
186 | return -1; | |
187 | } | |
188 | ||
0b4ff0c9 | 189 | av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h); |
a194f595 | 190 | } else if (!strcmp(buf, "raac") || !strcmp(buf, "racp")) { |
b9b2b8c9 | 191 | int codecdata_length; |
a194f595 RT |
192 | get_be16(pb); get_byte(pb); |
193 | if (((version >> 16) & 0xff) == 5) | |
194 | get_byte(pb); | |
195 | st->codec->codec_id = CODEC_ID_AAC; | |
196 | codecdata_length = get_be32(pb); | |
a9d4a6ef RT |
197 | if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ |
198 | av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); | |
199 | return -1; | |
200 | } | |
a194f595 RT |
201 | if (codecdata_length >= 1) { |
202 | st->codec->extradata_size = codecdata_length - 1; | |
203 | st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
204 | get_byte(pb); | |
b9b2b8c9 | 205 | get_buffer(pb, st->codec->extradata, st->codec->extradata_size); |
a194f595 | 206 | } |
c9510803 | 207 | } else { |
01f4895c | 208 | st->codec->codec_id = CODEC_ID_NONE; |
75e61b0e | 209 | av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name)); |
c9510803 FB |
210 | } |
211 | if (read_all) { | |
212 | get_byte(pb); | |
213 | get_byte(pb); | |
214 | get_byte(pb); | |
115329f1 | 215 | |
c9510803 FB |
216 | get_str8(pb, s->title, sizeof(s->title)); |
217 | get_str8(pb, s->author, sizeof(s->author)); | |
218 | get_str8(pb, s->copyright, sizeof(s->copyright)); | |
219 | get_str8(pb, s->comment, sizeof(s->comment)); | |
220 | } | |
221 | } | |
a9d4a6ef | 222 | return 0; |
c9510803 FB |
223 | } |
224 | ||
0fd36362 | 225 | int |
fcc995a5 | 226 | ff_rm_read_mdpr_codecdata (AVFormatContext *s, ByteIOContext *pb, |
886e89d0 | 227 | AVStream *st, RMStream *rst, int codec_data_size) |
ff1463dc | 228 | { |
ff1463dc | 229 | unsigned int v; |
79d5045d | 230 | int size; |
ff1463dc RB |
231 | int64_t codec_pos; |
232 | ||
15995030 | 233 | av_set_pts_info(st, 64, 1, 1000); |
ff1463dc RB |
234 | codec_pos = url_ftell(pb); |
235 | v = get_be32(pb); | |
236 | if (v == MKTAG(0xfd, 'a', 'r', '.')) { | |
237 | /* ra type header */ | |
886e89d0 | 238 | if (rm_read_audio_stream_info(s, pb, st, rst, 0)) |
ff1463dc RB |
239 | return -1; |
240 | } else { | |
241 | int fps, fps2; | |
242 | if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) { | |
243 | fail1: | |
244 | av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); | |
245 | goto skip; | |
246 | } | |
247 | st->codec->codec_tag = get_le32(pb); | |
248 | // av_log(NULL, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); | |
249 | if ( st->codec->codec_tag != MKTAG('R', 'V', '1', '0') | |
250 | && st->codec->codec_tag != MKTAG('R', 'V', '2', '0') | |
251 | && st->codec->codec_tag != MKTAG('R', 'V', '3', '0') | |
b93dd838 VS |
252 | && st->codec->codec_tag != MKTAG('R', 'V', '4', '0') |
253 | && st->codec->codec_tag != MKTAG('R', 'V', 'T', 'R')) | |
ff1463dc RB |
254 | goto fail1; |
255 | st->codec->width = get_be16(pb); | |
256 | st->codec->height = get_be16(pb); | |
257 | st->codec->time_base.num= 1; | |
258 | fps= get_be16(pb); | |
259 | st->codec->codec_type = CODEC_TYPE_VIDEO; | |
260 | get_be32(pb); | |
261 | fps2= get_be16(pb); | |
262 | get_be16(pb); | |
263 | ||
264 | st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos); | |
265 | ||
266 | if(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ | |
267 | //check is redundant as get_buffer() will catch this | |
268 | av_log(s, AV_LOG_ERROR, "st->codec->extradata_size too large\n"); | |
269 | return -1; | |
270 | } | |
271 | st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
437fd77b PI |
272 | if (!st->codec->extradata) |
273 | return AVERROR(ENOMEM); | |
ff1463dc RB |
274 | get_buffer(pb, st->codec->extradata, st->codec->extradata_size); |
275 | ||
276 | // av_log(NULL, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2); | |
277 | st->codec->time_base.den = fps * st->codec->time_base.num; | |
278 | switch(((uint8_t*)st->codec->extradata)[4]>>4){ | |
279 | case 1: st->codec->codec_id = CODEC_ID_RV10; break; | |
280 | case 2: st->codec->codec_id = CODEC_ID_RV20; break; | |
281 | case 3: st->codec->codec_id = CODEC_ID_RV30; break; | |
282 | case 4: st->codec->codec_id = CODEC_ID_RV40; break; | |
283 | default: goto fail1; | |
284 | } | |
285 | } | |
286 | ||
ff1463dc RB |
287 | skip: |
288 | /* skip codec info */ | |
289 | size = url_ftell(pb) - codec_pos; | |
290 | url_fskip(pb, codec_data_size - size); | |
291 | ||
36c9e40a | 292 | return 0; |
ff1463dc RB |
293 | } |
294 | ||
295 | ||
c9510803 FB |
296 | static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap) |
297 | { | |
1edddc99 | 298 | RMDemuxContext *rm = s->priv_data; |
c9510803 FB |
299 | AVStream *st; |
300 | ||
301 | rm->old_format = 1; | |
302 | st = av_new_stream(s, 0); | |
303 | if (!st) | |
a9d4a6ef | 304 | return -1; |
886e89d0 RB |
305 | st->priv_data = ff_rm_alloc_rmstream(); |
306 | return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1); | |
c9510803 FB |
307 | } |
308 | ||
de6d9b64 FB |
309 | static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
310 | { | |
1edddc99 | 311 | RMDemuxContext *rm = s->priv_data; |
de6d9b64 | 312 | AVStream *st; |
899681cd | 313 | ByteIOContext *pb = s->pb; |
ff1463dc | 314 | unsigned int tag; |
07cb073b | 315 | int tag_size; |
36c32bdd | 316 | unsigned int start_time, duration; |
de6d9b64 | 317 | char buf[128]; |
5d6ef63f | 318 | int flags = 0; |
de6d9b64 | 319 | |
c9510803 FB |
320 | tag = get_le32(pb); |
321 | if (tag == MKTAG('.', 'r', 'a', 0xfd)) { | |
322 | /* very old .ra format */ | |
323 | return rm_read_header_old(s, ap); | |
324 | } else if (tag != MKTAG('.', 'R', 'M', 'F')) { | |
6f3e0b21 | 325 | return AVERROR(EIO); |
c9510803 | 326 | } |
de6d9b64 FB |
327 | |
328 | get_be32(pb); /* header size */ | |
329 | get_be16(pb); | |
330 | get_be32(pb); | |
331 | get_be32(pb); /* number of headers */ | |
115329f1 | 332 | |
de6d9b64 FB |
333 | for(;;) { |
334 | if (url_feof(pb)) | |
ccafd472 | 335 | return -1; |
de6d9b64 FB |
336 | tag = get_le32(pb); |
337 | tag_size = get_be32(pb); | |
338 | get_be16(pb); | |
339 | #if 0 | |
115329f1 | 340 | printf("tag=%c%c%c%c (%08x) size=%d\n", |
de6d9b64 FB |
341 | (tag) & 0xff, |
342 | (tag >> 8) & 0xff, | |
343 | (tag >> 16) & 0xff, | |
344 | (tag >> 24) & 0xff, | |
345 | tag, | |
346 | tag_size); | |
347 | #endif | |
9786bd4d | 348 | if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A')) |
ccafd472 | 349 | return -1; |
de6d9b64 FB |
350 | switch(tag) { |
351 | case MKTAG('P', 'R', 'O', 'P'): | |
352 | /* file header */ | |
353 | get_be32(pb); /* max bit rate */ | |
354 | get_be32(pb); /* avg bit rate */ | |
355 | get_be32(pb); /* max packet size */ | |
356 | get_be32(pb); /* avg packet size */ | |
357 | get_be32(pb); /* nb packets */ | |
358 | get_be32(pb); /* duration */ | |
359 | get_be32(pb); /* preroll */ | |
360 | get_be32(pb); /* index offset */ | |
361 | get_be32(pb); /* data offset */ | |
362 | get_be16(pb); /* nb streams */ | |
5d6ef63f | 363 | flags = get_be16(pb); /* flags */ |
de6d9b64 FB |
364 | break; |
365 | case MKTAG('C', 'O', 'N', 'T'): | |
36cf20f5 RB |
366 | get_str16(pb, s->title, sizeof(s->title)); |
367 | get_str16(pb, s->author, sizeof(s->author)); | |
368 | get_str16(pb, s->copyright, sizeof(s->copyright)); | |
369 | get_str16(pb, s->comment, sizeof(s->comment)); | |
de6d9b64 FB |
370 | break; |
371 | case MKTAG('M', 'D', 'P', 'R'): | |
247eadca | 372 | st = av_new_stream(s, 0); |
de6d9b64 | 373 | if (!st) |
ccafd472 | 374 | return AVERROR(ENOMEM); |
de6d9b64 FB |
375 | st->id = get_be16(pb); |
376 | get_be32(pb); /* max bit rate */ | |
01f4895c | 377 | st->codec->bit_rate = get_be32(pb); /* bit rate */ |
de6d9b64 FB |
378 | get_be32(pb); /* max packet size */ |
379 | get_be32(pb); /* avg packet size */ | |
247eadca | 380 | start_time = get_be32(pb); /* start time */ |
de6d9b64 | 381 | get_be32(pb); /* preroll */ |
247eadca | 382 | duration = get_be32(pb); /* duration */ |
c0df9d75 MN |
383 | st->start_time = start_time; |
384 | st->duration = duration; | |
de6d9b64 FB |
385 | get_str8(pb, buf, sizeof(buf)); /* desc */ |
386 | get_str8(pb, buf, sizeof(buf)); /* mimetype */ | |
01f4895c | 387 | st->codec->codec_type = CODEC_TYPE_DATA; |
886e89d0 RB |
388 | st->priv_data = ff_rm_alloc_rmstream(); |
389 | if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, | |
390 | get_be32(pb)) < 0) | |
ff1463dc | 391 | return -1; |
de6d9b64 FB |
392 | break; |
393 | case MKTAG('D', 'A', 'T', 'A'): | |
394 | goto header_end; | |
395 | default: | |
396 | /* unknown tag: skip it */ | |
397 | url_fskip(pb, tag_size - 10); | |
398 | break; | |
399 | } | |
400 | } | |
401 | header_end: | |
402 | rm->nb_packets = get_be32(pb); /* number of packets */ | |
5d6ef63f PG |
403 | if (!rm->nb_packets && (flags & 4)) |
404 | rm->nb_packets = 3600 * 25; | |
de6d9b64 FB |
405 | get_be32(pb); /* next data header */ |
406 | return 0; | |
de6d9b64 FB |
407 | } |
408 | ||
4c2bc159 MN |
409 | static int get_num(ByteIOContext *pb, int *len) |
410 | { | |
411 | int n, n1; | |
412 | ||
413 | n = get_be16(pb); | |
414 | (*len)-=2; | |
e3052ce7 | 415 | n &= 0x7FFF; |
4c2bc159 MN |
416 | if (n >= 0x4000) { |
417 | return n - 0x4000; | |
418 | } else { | |
419 | n1 = get_be16(pb); | |
420 | (*len)-=2; | |
421 | return (n << 16) | n1; | |
422 | } | |
423 | } | |
424 | ||
c9510803 FB |
425 | /* multiple of 20 bytes for ra144 (ugly) */ |
426 | #define RAW_PACKET_SIZE 1000 | |
427 | ||
37e85dac | 428 | static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){ |
1edddc99 | 429 | RMDemuxContext *rm = s->priv_data; |
899681cd | 430 | ByteIOContext *pb = s->pb; |
bc17df09 MN |
431 | int len, num, res, i; |
432 | AVStream *st; | |
119cebf4 | 433 | uint32_t state=0xFFFFFFFF; |
bc17df09 MN |
434 | |
435 | while(!url_feof(pb)){ | |
fd31550d | 436 | *pos= url_ftell(pb) - 3; |
bc17df09 MN |
437 | if(rm->remaining_len > 0){ |
438 | num= rm->current_stream; | |
439 | len= rm->remaining_len; | |
440 | *timestamp = AV_NOPTS_VALUE; | |
441 | *flags= 0; | |
442 | }else{ | |
119cebf4 | 443 | state= (state<<8) + get_byte(pb); |
115329f1 | 444 | |
119cebf4 MN |
445 | if(state == MKBETAG('I', 'N', 'D', 'X')){ |
446 | len = get_be16(pb) - 6; | |
447 | if(len<0) | |
448 | continue; | |
449 | goto skip; | |
450 | } | |
115329f1 | 451 | |
119cebf4 | 452 | if(state > (unsigned)0xFFFF || state < 12) |
bc17df09 | 453 | continue; |
119cebf4 MN |
454 | len=state; |
455 | state= 0xFFFFFFFF; | |
456 | ||
bc17df09 MN |
457 | num = get_be16(pb); |
458 | *timestamp = get_be32(pb); | |
459 | res= get_byte(pb); /* reserved */ | |
460 | *flags = get_byte(pb); /* flags */ | |
37e85dac | 461 | |
115329f1 | 462 | |
bc17df09 MN |
463 | len -= 12; |
464 | } | |
465 | for(i=0;i<s->nb_streams;i++) { | |
466 | st = s->streams[i]; | |
467 | if (num == st->id) | |
468 | break; | |
469 | } | |
470 | if (i == s->nb_streams) { | |
119cebf4 | 471 | skip: |
bc17df09 MN |
472 | /* skip packet if unknown number */ |
473 | url_fskip(pb, len); | |
474 | rm->remaining_len -= len; | |
475 | continue; | |
476 | } | |
477 | *stream_index= i; | |
115329f1 | 478 | |
bc17df09 MN |
479 | return len; |
480 | } | |
481 | return -1; | |
482 | } | |
483 | ||
fcc995a5 | 484 | static int rm_assemble_video_frame(AVFormatContext *s, ByteIOContext *pb, |
ba614729 RB |
485 | RMDemuxContext *rm, RMStream *vst, |
486 | AVPacket *pkt, int len) | |
383b123e | 487 | { |
383b123e KS |
488 | int hdr, seq, pic_num, len2, pos; |
489 | int type; | |
383b123e KS |
490 | |
491 | hdr = get_byte(pb); len--; | |
492 | type = hdr >> 6; | |
f48d5457 MN |
493 | |
494 | if(type != 3){ // not frame as a part of packet | |
383b123e | 495 | seq = get_byte(pb); len--; |
f48d5457 MN |
496 | } |
497 | if(type != 1){ // not whole frame | |
383b123e | 498 | len2 = get_num(pb, &len); |
f48d5457 | 499 | pos = get_num(pb, &len); |
383b123e | 500 | pic_num = get_byte(pb); len--; |
f48d5457 MN |
501 | } |
502 | if(len<0) | |
503 | return -1; | |
504 | rm->remaining_len = len; | |
505 | if(type&1){ // frame, not slice | |
506 | if(type == 3) // frame as a part of packet | |
507 | len= len2; | |
508 | if(rm->remaining_len < len) | |
e45673cb | 509 | return -1; |
f48d5457 | 510 | rm->remaining_len -= len; |
383b123e KS |
511 | if(av_new_packet(pkt, len + 9) < 0) |
512 | return AVERROR(EIO); | |
513 | pkt->data[0] = 0; | |
514 | AV_WL32(pkt->data + 1, 1); | |
515 | AV_WL32(pkt->data + 5, 0); | |
516 | get_buffer(pb, pkt->data + 9, len); | |
383b123e KS |
517 | return 0; |
518 | } | |
519 | //now we have to deal with single slice | |
520 | ||
ba614729 RB |
521 | if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){ |
522 | vst->slices = ((hdr & 0x3F) << 1) + 1; | |
523 | vst->videobufsize = len2 + 8*vst->slices + 1; | |
0b4ff0c9 MN |
524 | av_free_packet(&vst->pkt); //FIXME this should be output. |
525 | if(av_new_packet(&vst->pkt, vst->videobufsize) < 0) | |
52537534 | 526 | return AVERROR(ENOMEM); |
ba614729 RB |
527 | vst->videobufpos = 8*vst->slices + 1; |
528 | vst->cur_slice = 0; | |
529 | vst->curpic_num = pic_num; | |
530 | vst->pktpos = url_ftell(pb); | |
383b123e | 531 | } |
e35033e6 | 532 | if(type == 2) |
383b123e | 533 | len = FFMIN(len, pos); |
383b123e | 534 | |
ba614729 | 535 | if(++vst->cur_slice > vst->slices) |
383b123e | 536 | return 1; |
0b4ff0c9 MN |
537 | AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1); |
538 | AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1); | |
ba614729 | 539 | if(vst->videobufpos + len > vst->videobufsize) |
383b123e | 540 | return 1; |
0b4ff0c9 | 541 | if (get_buffer(pb, vst->pkt.data + vst->videobufpos, len) != len) |
383b123e | 542 | return AVERROR(EIO); |
ba614729 | 543 | vst->videobufpos += len; |
383b123e KS |
544 | rm->remaining_len-= len; |
545 | ||
ba614729 | 546 | if(type == 2 || (vst->videobufpos) == vst->videobufsize){ |
188e67ea MN |
547 | vst->pkt.data[0] = vst->cur_slice-1; |
548 | *pkt= vst->pkt; | |
549 | vst->pkt.data= | |
550 | vst->pkt.size= 0; | |
551 | if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin | |
0b4ff0c9 | 552 | memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, |
ba614729 | 553 | vst->videobufpos - 1 - 8*vst->slices); |
ce0453aa | 554 | pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices); |
188e67ea MN |
555 | pkt->pts = AV_NOPTS_VALUE; |
556 | pkt->pos = vst->pktpos; | |
557 | return 0; | |
383b123e KS |
558 | } |
559 | ||
560 | return 1; | |
561 | } | |
562 | ||
5c470b91 RB |
563 | static inline void |
564 | rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt) | |
565 | { | |
566 | uint8_t *ptr; | |
567 | int j; | |
568 | ||
569 | if (st->codec->codec_id == CODEC_ID_AC3) { | |
570 | ptr = pkt->data; | |
571 | for (j=0;j<pkt->size;j+=2) { | |
572 | FFSWAP(int, ptr[0], ptr[1]); | |
573 | ptr += 2; | |
574 | } | |
575 | } | |
576 | } | |
577 | ||
0fd36362 | 578 | int |
fcc995a5 | 579 | ff_rm_parse_packet (AVFormatContext *s, ByteIOContext *pb, |
886e89d0 | 580 | AVStream *st, RMStream *ast, int len, AVPacket *pkt, |
afd302fa RB |
581 | int *seq, int *flags, int64_t *timestamp) |
582 | { | |
1edddc99 | 583 | RMDemuxContext *rm = s->priv_data; |
afd302fa RB |
584 | |
585 | if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | |
586 | rm->current_stream= st->id; | |
51d6852f | 587 | if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len)) |
afd302fa RB |
588 | return -1; //got partial frame |
589 | } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
590 | if ((st->codec->codec_id == CODEC_ID_RA_288) || | |
591 | (st->codec->codec_id == CODEC_ID_COOK) || | |
2426bb96 BL |
592 | (st->codec->codec_id == CODEC_ID_ATRAC3) || |
593 | (st->codec->codec_id == CODEC_ID_SIPR)) { | |
afd302fa | 594 | int x; |
ba614729 RB |
595 | int sps = ast->sub_packet_size; |
596 | int cfs = ast->coded_framesize; | |
597 | int h = ast->sub_packet_h; | |
598 | int y = ast->sub_packet_cnt; | |
599 | int w = ast->audio_framesize; | |
afd302fa RB |
600 | |
601 | if (*flags & 2) | |
ba614729 | 602 | y = ast->sub_packet_cnt = 0; |
afd302fa | 603 | if (!y) |
ba614729 | 604 | ast->audiotimestamp = *timestamp; |
afd302fa RB |
605 | |
606 | switch(st->codec->codec_id) { | |
607 | case CODEC_ID_RA_288: | |
608 | for (x = 0; x < h/2; x++) | |
0b4ff0c9 | 609 | get_buffer(pb, ast->pkt.data+x*2*w+y*cfs, cfs); |
afd302fa RB |
610 | break; |
611 | case CODEC_ID_ATRAC3: | |
612 | case CODEC_ID_COOK: | |
613 | for (x = 0; x < w/sps; x++) | |
0b4ff0c9 | 614 | get_buffer(pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps); |
afd302fa RB |
615 | break; |
616 | } | |
617 | ||
ba614729 | 618 | if (++(ast->sub_packet_cnt) < h) |
afd302fa RB |
619 | return -1; |
620 | else { | |
ba614729 | 621 | ast->sub_packet_cnt = 0; |
afd302fa RB |
622 | rm->audio_stream_num = st->index; |
623 | rm->audio_pkt_cnt = h * w / st->codec->block_align - 1; | |
624 | // Release first audio packet | |
625 | av_new_packet(pkt, st->codec->block_align); | |
0b4ff0c9 | 626 | memcpy(pkt->data, ast->pkt.data, st->codec->block_align); //FIXME avoid this |
ba614729 | 627 | *timestamp = ast->audiotimestamp; |
afd302fa RB |
628 | *flags = 2; // Mark first packet as keyframe |
629 | } | |
630 | } else if (st->codec->codec_id == CODEC_ID_AAC) { | |
631 | int x; | |
632 | rm->audio_stream_num = st->index; | |
ba614729 RB |
633 | ast->sub_packet_cnt = (get_be16(pb) & 0xf0) >> 4; |
634 | if (ast->sub_packet_cnt) { | |
635 | for (x = 0; x < ast->sub_packet_cnt; x++) | |
636 | ast->sub_packet_lengths[x] = get_be16(pb); | |
afd302fa | 637 | // Release first audio packet |
ba614729 RB |
638 | rm->audio_pkt_cnt = ast->sub_packet_cnt - 1; |
639 | av_get_packet(pb, pkt, ast->sub_packet_lengths[0]); | |
afd302fa RB |
640 | *flags = 2; // Mark first packet as keyframe |
641 | } | |
badbe09a | 642 | } else { |
afd302fa | 643 | av_get_packet(pb, pkt, len); |
e29378ff | 644 | rm_ac3_swap_bytes(st, pkt); |
badbe09a | 645 | } |
afd302fa RB |
646 | } else |
647 | av_get_packet(pb, pkt, len); | |
648 | ||
649 | if( (st->discard >= AVDISCARD_NONKEY && !(*flags&2)) | |
650 | || st->discard >= AVDISCARD_ALL){ | |
651 | av_free_packet(pkt); | |
652 | return -1; | |
653 | } | |
654 | ||
655 | pkt->stream_index = st->index; | |
656 | ||
657 | #if 0 | |
658 | if (st->codec->codec_type == CODEC_TYPE_VIDEO) { | |
659 | if(st->codec->codec_id == CODEC_ID_RV20){ | |
660 | int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1); | |
661 | av_log(NULL, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq); | |
662 | ||
663 | seq |= (*timestamp&~0x3FFF); | |
664 | if(seq - *timestamp > 0x2000) seq -= 0x4000; | |
665 | if(seq - *timestamp < -0x2000) seq += 0x4000; | |
666 | } | |
667 | } | |
668 | #endif | |
669 | ||
670 | pkt->pts= *timestamp; | |
671 | if (*flags & 2) | |
672 | pkt->flags |= PKT_FLAG_KEY; | |
673 | ||
a15ebf34 | 674 | return st->codec->codec_type == CODEC_TYPE_AUDIO ? rm->audio_pkt_cnt : 0; |
afd302fa RB |
675 | } |
676 | ||
a9f84821 | 677 | int |
fcc995a5 | 678 | ff_rm_retrieve_cache (AVFormatContext *s, ByteIOContext *pb, |
886e89d0 | 679 | AVStream *st, RMStream *ast, AVPacket *pkt) |
d4d1b5fb | 680 | { |
1edddc99 | 681 | RMDemuxContext *rm = s->priv_data; |
d4d1b5fb RB |
682 | |
683 | assert (rm->audio_pkt_cnt > 0); | |
684 | ||
685 | if (st->codec->codec_id == CODEC_ID_AAC) | |
ba614729 | 686 | av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); |
d4d1b5fb RB |
687 | else { |
688 | av_new_packet(pkt, st->codec->block_align); | |
0b4ff0c9 | 689 | memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this |
ba614729 | 690 | (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), |
d4d1b5fb RB |
691 | st->codec->block_align); |
692 | } | |
693 | rm->audio_pkt_cnt--; | |
694 | pkt->flags = 0; | |
695 | pkt->stream_index = st->index; | |
a9f84821 RB |
696 | |
697 | return rm->audio_pkt_cnt; | |
d4d1b5fb RB |
698 | } |
699 | ||
de6d9b64 FB |
700 | static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) |
701 | { | |
1edddc99 | 702 | RMDemuxContext *rm = s->priv_data; |
899681cd | 703 | ByteIOContext *pb = s->pb; |
de6d9b64 | 704 | AVStream *st; |
5c470b91 | 705 | int i, len; |
37e85dac | 706 | int64_t timestamp, pos; |
bc17df09 | 707 | int flags; |
de6d9b64 | 708 | |
c69e7914 | 709 | if (rm->audio_pkt_cnt) { |
e0f7e329 BL |
710 | // If there are queued audio packet return them first |
711 | st = s->streams[rm->audio_stream_num]; | |
886e89d0 | 712 | ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt); |
c69e7914 | 713 | } else if (rm->old_format) { |
ba614729 RB |
714 | RMStream *ast; |
715 | ||
c69e7914 | 716 | st = s->streams[0]; |
ba614729 | 717 | ast = st->priv_data; |
c69e7914 RT |
718 | if (st->codec->codec_id == CODEC_ID_RA_288) { |
719 | int x, y; | |
720 | ||
ba614729 RB |
721 | for (y = 0; y < ast->sub_packet_h; y++) |
722 | for (x = 0; x < ast->sub_packet_h/2; x++) | |
0b4ff0c9 | 723 | if (get_buffer(pb, ast->pkt.data+x*2*ast->audio_framesize+y*ast->coded_framesize, ast->coded_framesize) <= 0) |
6f3e0b21 | 724 | return AVERROR(EIO); |
c69e7914 | 725 | rm->audio_stream_num = 0; |
ba614729 | 726 | rm->audio_pkt_cnt = ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - 1; |
c69e7914 RT |
727 | // Release first audio packet |
728 | av_new_packet(pkt, st->codec->block_align); | |
0b4ff0c9 | 729 | memcpy(pkt->data, ast->pkt.data, st->codec->block_align); //FIXME avoid this |
c69e7914 RT |
730 | pkt->flags |= PKT_FLAG_KEY; // Mark first packet as keyframe |
731 | pkt->stream_index = 0; | |
732 | } else { | |
733 | /* just read raw bytes */ | |
734 | len = RAW_PACKET_SIZE; | |
735 | len= av_get_packet(pb, pkt, len); | |
736 | pkt->stream_index = 0; | |
737 | if (len <= 0) { | |
6f3e0b21 | 738 | return AVERROR(EIO); |
c69e7914 RT |
739 | } |
740 | pkt->size = len; | |
741 | } | |
e29378ff | 742 | rm_ac3_swap_bytes(st, pkt); |
c9510803 | 743 | } else { |
37e85dac | 744 | int seq=1; |
b9866ebc | 745 | resync: |
37e85dac | 746 | len=sync(s, ×tamp, &flags, &i, &pos); |
bc17df09 | 747 | if(len<0) |
6f3e0b21 | 748 | return AVERROR(EIO); |
bc17df09 MN |
749 | st = s->streams[i]; |
750 | ||
886e89d0 RB |
751 | if (ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt, |
752 | &seq, &flags, ×tamp) < 0) | |
b9866ebc | 753 | goto resync; |
d880240e | 754 | |
9b41eb37 | 755 | if((flags&2) && (seq&0x7F) == 1) |
8f8fae80 | 756 | av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME); |
5d6ef63f PG |
757 | } |
758 | ||
de6d9b64 FB |
759 | return 0; |
760 | } | |
761 | ||
762 | static int rm_read_close(AVFormatContext *s) | |
763 | { | |
ba614729 RB |
764 | int i; |
765 | ||
766 | for (i=0;i<s->nb_streams;i++) | |
767 | ff_rm_free_rmstream(s->streams[i]->priv_data); | |
e0f7e329 | 768 | |
de6d9b64 FB |
769 | return 0; |
770 | } | |
771 | ||
c9a65ca8 FB |
772 | static int rm_probe(AVProbeData *p) |
773 | { | |
774 | /* check file header */ | |
c9510803 FB |
775 | if ((p->buf[0] == '.' && p->buf[1] == 'R' && |
776 | p->buf[2] == 'M' && p->buf[3] == 'F' && | |
777 | p->buf[4] == 0 && p->buf[5] == 0) || | |
778 | (p->buf[0] == '.' && p->buf[1] == 'r' && | |
779 | p->buf[2] == 'a' && p->buf[3] == 0xfd)) | |
c9a65ca8 FB |
780 | return AVPROBE_SCORE_MAX; |
781 | else | |
782 | return 0; | |
783 | } | |
784 | ||
115329f1 | 785 | static int64_t rm_read_dts(AVFormatContext *s, int stream_index, |
bc17df09 MN |
786 | int64_t *ppos, int64_t pos_limit) |
787 | { | |
1edddc99 | 788 | RMDemuxContext *rm = s->priv_data; |
bc17df09 | 789 | int64_t pos, dts; |
37e85dac | 790 | int stream_index2, flags, len, h; |
bc17df09 MN |
791 | |
792 | pos = *ppos; | |
115329f1 | 793 | |
bc17df09 MN |
794 | if(rm->old_format) |
795 | return AV_NOPTS_VALUE; | |
796 | ||
899681cd | 797 | url_fseek(s->pb, pos, SEEK_SET); |
bc17df09 MN |
798 | rm->remaining_len=0; |
799 | for(;;){ | |
37e85dac MN |
800 | int seq=1; |
801 | AVStream *st; | |
802 | ||
803 | len=sync(s, &dts, &flags, &stream_index2, &pos); | |
bc17df09 MN |
804 | if(len<0) |
805 | return AV_NOPTS_VALUE; | |
37e85dac MN |
806 | |
807 | st = s->streams[stream_index2]; | |
01f4895c | 808 | if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
899681cd | 809 | h= get_byte(s->pb); len--; |
37e85dac | 810 | if(!(h & 0x40)){ |
899681cd | 811 | seq = get_byte(s->pb); len--; |
bc17df09 MN |
812 | } |
813 | } | |
115329f1 | 814 | |
37e85dac | 815 | if((flags&2) && (seq&0x7F) == 1){ |
949b1a13 | 816 | // av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq); |
30a43f2d | 817 | av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME); |
37e85dac MN |
818 | if(stream_index2 == stream_index) |
819 | break; | |
820 | } | |
821 | ||
899681cd | 822 | url_fskip(s->pb, len); |
bc17df09 MN |
823 | } |
824 | *ppos = pos; | |
825 | return dts; | |
826 | } | |
827 | ||
ff70e601 | 828 | AVInputFormat rm_demuxer = { |
c9a65ca8 | 829 | "rm", |
bde15e74 | 830 | NULL_IF_CONFIG_SMALL("RM format"), |
1edddc99 | 831 | sizeof(RMDemuxContext), |
c9a65ca8 FB |
832 | rm_probe, |
833 | rm_read_header, | |
834 | rm_read_packet, | |
835 | rm_read_close, | |
bc17df09 MN |
836 | NULL, |
837 | rm_read_dts, | |
c9a65ca8 | 838 | }; |
ff13ba92 RB |
839 | |
840 | AVInputFormat rdt_demuxer = { | |
841 | "rdt", | |
842 | NULL_IF_CONFIG_SMALL("RDT demuxer"), | |
1edddc99 | 843 | sizeof(RMDemuxContext), |
ff13ba92 RB |
844 | NULL, NULL, NULL, rm_read_close, NULL, NULL |
845 | }; |