Mercurial > libavformat.hg
annotate rm.c @ 879:1f093ae472d8 libavformat
Cook compatibe decoder, patch by Benjamin Larsson
Add cook demucing, change rm demuxer so that it reorders audio packets
before sending them to the decoder, and send minimum decodeable sized
packets; pass only real codec extradata fo the decoder
Fix 28_8 decoder for the new demuxer strategy
author | rtognimp |
---|---|
date | Fri, 09 Dec 2005 16:08:18 +0000 |
parents | 66cc656ea404 |
children | 2ece9c9dd94c |
rev | line source |
---|---|
0 | 1 /* |
2 * "Real" compatible mux and demux. | |
3 * Copyright (c) 2000, 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 | |
21 /* in ms */ | |
22 #define BUFFER_DURATION 0 | |
23 | |
24 typedef struct { | |
25 int nb_packets; | |
26 int packet_total_size; | |
27 int packet_max_size; | |
28 /* codec related output */ | |
29 int bit_rate; | |
30 float frame_rate; | |
31 int nb_frames; /* current frame number */ | |
32 int total_frames; /* total number of frames */ | |
33 int num; | |
34 AVCodecContext *enc; | |
35 } StreamInfo; | |
36 | |
37 typedef struct { | |
38 StreamInfo streams[2]; | |
39 StreamInfo *audio_stream, *video_stream; | |
40 int data_pos; /* position of the data after the header */ | |
41 int nb_packets; | |
194 | 42 int old_format; |
609 | 43 int current_stream; |
44 int remaining_len; | |
879 | 45 /// Audio descrambling matrix parameters |
46 uint8_t *audiobuf; ///< place to store reordered audio data | |
47 int64_t audiotimestamp; ///< Audio packet timestamp | |
48 int sub_packet_cnt; // Subpacket counter, used while reading | |
49 int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container | |
50 int audio_stream_num; ///< Stream number for audio packets | |
51 int audio_pkt_cnt; ///< Output packet counter | |
52 int audio_framesize; /// Audio frame size from container | |
0 | 53 } RMContext; |
54 | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
55 #ifdef CONFIG_MUXERS |
0 | 56 static void put_str(ByteIOContext *s, const char *tag) |
57 { | |
58 put_be16(s,strlen(tag)); | |
59 while (*tag) { | |
60 put_byte(s, *tag++); | |
61 } | |
62 } | |
63 | |
64 static void put_str8(ByteIOContext *s, const char *tag) | |
65 { | |
66 put_byte(s, strlen(tag)); | |
67 while (*tag) { | |
68 put_byte(s, *tag++); | |
69 } | |
70 } | |
71 | |
72 static void rv10_write_header(AVFormatContext *ctx, | |
73 int data_size, int index_pos) | |
74 { | |
75 RMContext *rm = ctx->priv_data; | |
76 ByteIOContext *s = &ctx->pb; | |
77 StreamInfo *stream; | |
78 unsigned char *data_offset_ptr, *start_ptr; | |
79 const char *desc, *mimetype; | |
80 int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; | |
81 int bit_rate, v, duration, flags, data_pos; | |
82 | |
83 start_ptr = s->buf_ptr; | |
84 | |
85 put_tag(s, ".RMF"); | |
86 put_be32(s,18); /* header size */ | |
87 put_be16(s,0); | |
88 put_be32(s,0); | |
89 put_be32(s,4 + ctx->nb_streams); /* num headers */ | |
90 | |
91 put_tag(s,"PROP"); | |
92 put_be32(s, 50); | |
93 put_be16(s, 0); | |
94 packet_max_size = 0; | |
95 packet_total_size = 0; | |
96 nb_packets = 0; | |
97 bit_rate = 0; | |
98 duration = 0; | |
99 for(i=0;i<ctx->nb_streams;i++) { | |
100 StreamInfo *stream = &rm->streams[i]; | |
101 bit_rate += stream->bit_rate; | |
102 if (stream->packet_max_size > packet_max_size) | |
103 packet_max_size = stream->packet_max_size; | |
104 nb_packets += stream->nb_packets; | |
105 packet_total_size += stream->packet_total_size; | |
106 /* select maximum duration */ | |
107 v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate); | |
108 if (v > duration) | |
109 duration = v; | |
110 } | |
111 put_be32(s, bit_rate); /* max bit rate */ | |
112 put_be32(s, bit_rate); /* avg bit rate */ | |
113 put_be32(s, packet_max_size); /* max packet size */ | |
114 if (nb_packets > 0) | |
115 packet_avg_size = packet_total_size / nb_packets; | |
116 else | |
117 packet_avg_size = 0; | |
118 put_be32(s, packet_avg_size); /* avg packet size */ | |
119 put_be32(s, nb_packets); /* num packets */ | |
120 put_be32(s, duration); /* duration */ | |
121 put_be32(s, BUFFER_DURATION); /* preroll */ | |
122 put_be32(s, index_pos); /* index offset */ | |
123 /* computation of data the data offset */ | |
124 data_offset_ptr = s->buf_ptr; | |
125 put_be32(s, 0); /* data offset : will be patched after */ | |
126 put_be16(s, ctx->nb_streams); /* num streams */ | |
127 flags = 1 | 2; /* save allowed & perfect play */ | |
128 if (url_is_streamed(s)) | |
129 flags |= 4; /* live broadcast */ | |
130 put_be16(s, flags); | |
131 | |
132 /* comments */ | |
133 | |
134 put_tag(s,"CONT"); | |
135 size = strlen(ctx->title) + strlen(ctx->author) + strlen(ctx->copyright) + | |
136 strlen(ctx->comment) + 4 * 2 + 10; | |
137 put_be32(s,size); | |
138 put_be16(s,0); | |
139 put_str(s, ctx->title); | |
140 put_str(s, ctx->author); | |
141 put_str(s, ctx->copyright); | |
142 put_str(s, ctx->comment); | |
143 | |
144 for(i=0;i<ctx->nb_streams;i++) { | |
145 int codec_data_size; | |
146 | |
147 stream = &rm->streams[i]; | |
148 | |
149 if (stream->enc->codec_type == CODEC_TYPE_AUDIO) { | |
150 desc = "The Audio Stream"; | |
151 mimetype = "audio/x-pn-realaudio"; | |
152 codec_data_size = 73; | |
153 } else { | |
154 desc = "The Video Stream"; | |
155 mimetype = "video/x-pn-realvideo"; | |
156 codec_data_size = 34; | |
157 } | |
158 | |
159 put_tag(s,"MDPR"); | |
160 size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; | |
161 put_be32(s, size); | |
162 put_be16(s, 0); | |
163 | |
164 put_be16(s, i); /* stream number */ | |
165 put_be32(s, stream->bit_rate); /* max bit rate */ | |
166 put_be32(s, stream->bit_rate); /* avg bit rate */ | |
167 put_be32(s, stream->packet_max_size); /* max packet size */ | |
168 if (stream->nb_packets > 0) | |
169 packet_avg_size = stream->packet_total_size / | |
170 stream->nb_packets; | |
171 else | |
172 packet_avg_size = 0; | |
173 put_be32(s, packet_avg_size); /* avg packet size */ | |
174 put_be32(s, 0); /* start time */ | |
175 put_be32(s, BUFFER_DURATION); /* preroll */ | |
176 /* duration */ | |
177 if (url_is_streamed(s) || !stream->total_frames) | |
178 put_be32(s, (int)(3600 * 1000)); | |
179 else | |
180 put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate)); | |
181 put_str8(s, desc); | |
182 put_str8(s, mimetype); | |
183 put_be32(s, codec_data_size); | |
184 | |
185 if (stream->enc->codec_type == CODEC_TYPE_AUDIO) { | |
186 int coded_frame_size, fscode, sample_rate; | |
187 sample_rate = stream->enc->sample_rate; | |
188 coded_frame_size = (stream->enc->bit_rate * | |
189 stream->enc->frame_size) / (8 * sample_rate); | |
190 /* audio codec info */ | |
191 put_tag(s, ".ra"); | |
192 put_byte(s, 0xfd); | |
193 put_be32(s, 0x00040000); /* version */ | |
194 put_tag(s, ".ra4"); | |
195 put_be32(s, 0x01b53530); /* stream length */ | |
196 put_be16(s, 4); /* unknown */ | |
197 put_be32(s, 0x39); /* header size */ | |
198 | |
199 switch(sample_rate) { | |
200 case 48000: | |
201 case 24000: | |
202 case 12000: | |
203 fscode = 1; | |
204 break; | |
205 default: | |
206 case 44100: | |
207 case 22050: | |
208 case 11025: | |
209 fscode = 2; | |
210 break; | |
211 case 32000: | |
212 case 16000: | |
213 case 8000: | |
214 fscode = 3; | |
215 } | |
216 put_be16(s, fscode); /* codec additional info, for AC3, seems | |
217 to be a frequency code */ | |
218 /* special hack to compensate rounding errors... */ | |
219 if (coded_frame_size == 557) | |
220 coded_frame_size--; | |
221 put_be32(s, coded_frame_size); /* frame length */ | |
222 put_be32(s, 0x51540); /* unknown */ | |
223 put_be32(s, 0x249f0); /* unknown */ | |
224 put_be32(s, 0x249f0); /* unknown */ | |
225 put_be16(s, 0x01); | |
226 /* frame length : seems to be very important */ | |
227 put_be16(s, coded_frame_size); | |
228 put_be32(s, 0); /* unknown */ | |
229 put_be16(s, stream->enc->sample_rate); /* sample rate */ | |
230 put_be32(s, 0x10); /* unknown */ | |
231 put_be16(s, stream->enc->channels); | |
232 put_str8(s, "Int0"); /* codec name */ | |
233 put_str8(s, "dnet"); /* codec name */ | |
234 put_be16(s, 0); /* title length */ | |
235 put_be16(s, 0); /* author length */ | |
236 put_be16(s, 0); /* copyright length */ | |
237 put_byte(s, 0); /* end of header */ | |
238 } else { | |
239 /* video codec info */ | |
240 put_be32(s,34); /* size */ | |
614 | 241 if(stream->enc->codec_id == CODEC_ID_RV10) |
242 put_tag(s,"VIDORV10"); | |
243 else | |
244 put_tag(s,"VIDORV20"); | |
0 | 245 put_be16(s, stream->enc->width); |
246 put_be16(s, stream->enc->height); | |
247 put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */ | |
248 put_be32(s,0); /* unknown meaning */ | |
249 put_be16(s, (int) stream->frame_rate); /* unknown meaning */ | |
250 put_be32(s,0); /* unknown meaning */ | |
251 put_be16(s, 8); /* unknown meaning */ | |
252 /* Seems to be the codec version: only use basic H263. The next | |
253 versions seems to add a diffential DC coding as in | |
254 MPEG... nothing new under the sun */ | |
614 | 255 if(stream->enc->codec_id == CODEC_ID_RV10) |
256 put_be32(s,0x10000000); | |
257 else | |
258 put_be32(s,0x20103001); | |
0 | 259 //put_be32(s,0x10003000); |
260 } | |
261 } | |
262 | |
263 /* patch data offset field */ | |
264 data_pos = s->buf_ptr - start_ptr; | |
265 rm->data_pos = data_pos; | |
266 data_offset_ptr[0] = data_pos >> 24; | |
267 data_offset_ptr[1] = data_pos >> 16; | |
268 data_offset_ptr[2] = data_pos >> 8; | |
269 data_offset_ptr[3] = data_pos; | |
270 | |
271 /* data stream */ | |
272 put_tag(s,"DATA"); | |
273 put_be32(s,data_size + 10 + 8); | |
274 put_be16(s,0); | |
275 | |
276 put_be32(s, nb_packets); /* number of packets */ | |
277 put_be32(s,0); /* next data header */ | |
278 } | |
279 | |
280 static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, | |
281 int length, int key_frame) | |
282 { | |
283 int timestamp; | |
284 ByteIOContext *s = &ctx->pb; | |
285 | |
286 stream->nb_packets++; | |
287 stream->packet_total_size += length; | |
288 if (length > stream->packet_max_size) | |
289 stream->packet_max_size = length; | |
290 | |
291 put_be16(s,0); /* version */ | |
292 put_be16(s,length + 12); | |
293 put_be16(s, stream->num); /* stream number */ | |
294 timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate; | |
295 put_be32(s, timestamp); /* timestamp */ | |
296 put_byte(s, 0); /* reserved */ | |
297 put_byte(s, key_frame ? 2 : 0); /* flags */ | |
298 } | |
299 | |
300 static int rm_write_header(AVFormatContext *s) | |
301 { | |
302 RMContext *rm = s->priv_data; | |
303 StreamInfo *stream; | |
304 int n; | |
305 AVCodecContext *codec; | |
306 | |
307 for(n=0;n<s->nb_streams;n++) { | |
308 s->streams[n]->id = n; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
309 codec = s->streams[n]->codec; |
0 | 310 stream = &rm->streams[n]; |
311 memset(stream, 0, sizeof(StreamInfo)); | |
312 stream->num = n; | |
313 stream->bit_rate = codec->bit_rate; | |
314 stream->enc = codec; | |
315 | |
316 switch(codec->codec_type) { | |
317 case CODEC_TYPE_AUDIO: | |
318 rm->audio_stream = stream; | |
319 stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size; | |
320 /* XXX: dummy values */ | |
321 stream->packet_max_size = 1024; | |
322 stream->nb_packets = 0; | |
323 stream->total_frames = stream->nb_packets; | |
324 break; | |
325 case CODEC_TYPE_VIDEO: | |
326 rm->video_stream = stream; | |
743 | 327 stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num; |
0 | 328 /* XXX: dummy values */ |
329 stream->packet_max_size = 4096; | |
330 stream->nb_packets = 0; | |
331 stream->total_frames = stream->nb_packets; | |
332 break; | |
333 default: | |
537 | 334 return -1; |
0 | 335 } |
336 } | |
337 | |
338 rv10_write_header(s, 0, 0); | |
339 put_flush_packet(&s->pb); | |
340 return 0; | |
341 } | |
342 | |
470 | 343 static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 344 { |
65 | 345 uint8_t *buf1; |
0 | 346 RMContext *rm = s->priv_data; |
347 ByteIOContext *pb = &s->pb; | |
348 StreamInfo *stream = rm->audio_stream; | |
349 int i; | |
350 | |
351 /* XXX: suppress this malloc */ | |
65 | 352 buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) ); |
0 | 353 |
470 | 354 write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY)); |
0 | 355 |
356 /* for AC3, the words seems to be reversed */ | |
357 for(i=0;i<size;i+=2) { | |
358 buf1[i] = buf[i+1]; | |
359 buf1[i+1] = buf[i]; | |
360 } | |
361 put_buffer(pb, buf1, size); | |
362 put_flush_packet(pb); | |
363 stream->nb_frames++; | |
364 av_free(buf1); | |
365 return 0; | |
366 } | |
367 | |
470 | 368 static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 369 { |
370 RMContext *rm = s->priv_data; | |
371 ByteIOContext *pb = &s->pb; | |
372 StreamInfo *stream = rm->video_stream; | |
470 | 373 int key_frame = !!(flags & PKT_FLAG_KEY); |
0 | 374 |
375 /* XXX: this is incorrect: should be a parameter */ | |
376 | |
377 /* Well, I spent some time finding the meaning of these bits. I am | |
378 not sure I understood everything, but it works !! */ | |
379 #if 1 | |
380 write_packet_header(s, stream, size + 7, key_frame); | |
381 /* bit 7: '1' if final packet of a frame converted in several packets */ | |
382 put_byte(pb, 0x81); | |
383 /* bit 7: '1' if I frame. bits 6..0 : sequence number in current | |
384 frame starting from 1 */ | |
385 if (key_frame) { | |
386 put_byte(pb, 0x81); | |
387 } else { | |
388 put_byte(pb, 0x01); | |
389 } | |
611 | 390 put_be16(pb, 0x4000 + (size)); /* total frame size */ |
391 put_be16(pb, 0x4000 + (size)); /* offset from the start or the end */ | |
0 | 392 #else |
393 /* full frame */ | |
394 write_packet_header(s, size + 6); | |
395 put_byte(pb, 0xc0); | |
611 | 396 put_be16(pb, 0x4000 + size); /* total frame size */ |
0 | 397 put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */ |
398 #endif | |
399 put_byte(pb, stream->nb_frames & 0xff); | |
400 | |
401 put_buffer(pb, buf, size); | |
402 put_flush_packet(pb); | |
403 | |
404 stream->nb_frames++; | |
405 return 0; | |
406 } | |
407 | |
468 | 408 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 409 { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
410 if (s->streams[pkt->stream_index]->codec->codec_type == |
0 | 411 CODEC_TYPE_AUDIO) |
470 | 412 return rm_write_audio(s, pkt->data, pkt->size, pkt->flags); |
0 | 413 else |
470 | 414 return rm_write_video(s, pkt->data, pkt->size, pkt->flags); |
0 | 415 } |
416 | |
417 static int rm_write_trailer(AVFormatContext *s) | |
418 { | |
419 RMContext *rm = s->priv_data; | |
420 int data_size, index_pos, i; | |
421 ByteIOContext *pb = &s->pb; | |
422 | |
423 if (!url_is_streamed(&s->pb)) { | |
424 /* end of file: finish to write header */ | |
425 index_pos = url_fseek(pb, 0, SEEK_CUR); | |
426 data_size = index_pos - rm->data_pos; | |
427 | |
428 /* index */ | |
429 put_tag(pb, "INDX"); | |
430 put_be32(pb, 10 + 10 * s->nb_streams); | |
431 put_be16(pb, 0); | |
432 | |
433 for(i=0;i<s->nb_streams;i++) { | |
434 put_be32(pb, 0); /* zero indices */ | |
435 put_be16(pb, i); /* stream number */ | |
436 put_be32(pb, 0); /* next index */ | |
437 } | |
438 /* undocumented end header */ | |
439 put_be32(pb, 0); | |
440 put_be32(pb, 0); | |
441 | |
442 url_fseek(pb, 0, SEEK_SET); | |
443 for(i=0;i<s->nb_streams;i++) | |
444 rm->streams[i].total_frames = rm->streams[i].nb_frames; | |
445 rv10_write_header(s, data_size, index_pos); | |
446 } else { | |
447 /* undocumented end header */ | |
448 put_be32(pb, 0); | |
449 put_be32(pb, 0); | |
450 } | |
451 put_flush_packet(pb); | |
452 return 0; | |
453 } | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
454 #endif //CONFIG_MUXERS |
0 | 455 |
456 /***************************************************/ | |
457 | |
458 static void get_str(ByteIOContext *pb, char *buf, int buf_size) | |
459 { | |
460 int len, i; | |
461 char *q; | |
462 | |
463 len = get_be16(pb); | |
464 q = buf; | |
465 for(i=0;i<len;i++) { | |
466 if (i < buf_size - 1) | |
467 *q++ = get_byte(pb); | |
468 } | |
469 *q = '\0'; | |
470 } | |
471 | |
472 static void get_str8(ByteIOContext *pb, char *buf, int buf_size) | |
473 { | |
474 int len, i; | |
475 char *q; | |
476 | |
477 len = get_byte(pb); | |
478 q = buf; | |
479 for(i=0;i<len;i++) { | |
480 if (i < buf_size - 1) | |
481 *q++ = get_byte(pb); | |
482 } | |
483 *q = '\0'; | |
484 } | |
485 | |
194 | 486 static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, |
487 int read_all) | |
488 { | |
879 | 489 RMContext *rm = s->priv_data; |
194 | 490 ByteIOContext *pb = &s->pb; |
491 char buf[128]; | |
492 uint32_t version; | |
493 int i; | |
494 | |
495 /* ra type header */ | |
496 version = get_be32(pb); /* version */ | |
497 if (((version >> 16) & 0xff) == 3) { | |
498 /* very old version */ | |
499 for(i = 0; i < 14; i++) | |
500 get_byte(pb); | |
501 get_str8(pb, s->title, sizeof(s->title)); | |
502 get_str8(pb, s->author, sizeof(s->author)); | |
503 get_str8(pb, s->copyright, sizeof(s->copyright)); | |
504 get_str8(pb, s->comment, sizeof(s->comment)); | |
505 get_byte(pb); | |
506 get_str8(pb, buf, sizeof(buf)); | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
507 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
|
508 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
|
509 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
|
510 st->codec->codec_id = CODEC_ID_RA_144; |
194 | 511 } else { |
879 | 512 int flavor, sub_packet_h, coded_framesize, sub_packet_size; |
194 | 513 /* old version (4) */ |
514 get_be32(pb); /* .ra4 */ | |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
515 get_be32(pb); /* data size */ |
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
516 get_be16(pb); /* version2 */ |
194 | 517 get_be32(pb); /* header size */ |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
518 flavor= get_be16(pb); /* add codec info / flavor */ |
879 | 519 rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */ |
194 | 520 get_be32(pb); /* ??? */ |
521 get_be32(pb); /* ??? */ | |
522 get_be32(pb); /* ??? */ | |
879 | 523 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
|
524 st->codec->block_align= get_be16(pb); /* frame size */ |
879 | 525 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
|
526 get_be16(pb); /* ??? */ |
879 | 527 if (((version >> 16) & 0xff) == 5) { |
528 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
|
529 st->codec->sample_rate = get_be16(pb); |
194 | 530 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
|
531 st->codec->channels = get_be16(pb); |
879 | 532 if (((version >> 16) & 0xff) == 5) { |
533 get_be32(pb); | |
534 buf[0] = get_byte(pb); | |
535 buf[1] = get_byte(pb); | |
536 buf[2] = get_byte(pb); | |
537 buf[3] = get_byte(pb); | |
538 buf[4] = 0; | |
539 } else { | |
194 | 540 get_str8(pb, buf, sizeof(buf)); /* desc */ |
541 get_str8(pb, buf, sizeof(buf)); /* desc */ | |
879 | 542 } |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
543 st->codec->codec_type = CODEC_TYPE_AUDIO; |
194 | 544 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
|
545 st->codec->codec_id = CODEC_ID_AC3; |
687
561f27e36bc4
ra288 demuxing support (doesnt really work, might be demuxer or decoder bug)
michael
parents:
652
diff
changeset
|
546 } 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
|
547 st->codec->codec_id = CODEC_ID_RA_288; |
879 | 548 st->codec->extradata_size= 0; |
549 rm->audio_framesize = st->codec->block_align; | |
550 st->codec->block_align = coded_framesize; | |
551 rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); | |
552 } else if (!strcmp(buf, "cook")) { | |
553 int codecdata_length, i; | |
554 get_be16(pb); get_byte(pb); | |
555 if (((version >> 16) & 0xff) == 5) | |
556 get_byte(pb); | |
557 codecdata_length = get_be32(pb); | |
558 st->codec->codec_id = CODEC_ID_COOK; | |
559 st->codec->extradata_size= codecdata_length; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
560 st->codec->extradata= av_mallocz(st->codec->extradata_size); |
879 | 561 for(i = 0; i < codecdata_length; i++) |
562 ((uint8_t*)st->codec->extradata)[i] = get_byte(pb); | |
563 rm->audio_framesize = st->codec->block_align; | |
564 st->codec->block_align = rm->sub_packet_size; | |
565 rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); | |
194 | 566 } 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
|
567 st->codec->codec_id = CODEC_ID_NONE; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
568 pstrcpy(st->codec->codec_name, sizeof(st->codec->codec_name), |
194 | 569 buf); |
570 } | |
571 if (read_all) { | |
572 get_byte(pb); | |
573 get_byte(pb); | |
574 get_byte(pb); | |
575 | |
576 get_str8(pb, s->title, sizeof(s->title)); | |
577 get_str8(pb, s->author, sizeof(s->author)); | |
578 get_str8(pb, s->copyright, sizeof(s->copyright)); | |
579 get_str8(pb, s->comment, sizeof(s->comment)); | |
580 } | |
581 } | |
582 } | |
583 | |
584 static int rm_read_header_old(AVFormatContext *s, AVFormatParameters *ap) | |
585 { | |
586 RMContext *rm = s->priv_data; | |
587 AVStream *st; | |
588 | |
589 rm->old_format = 1; | |
590 st = av_new_stream(s, 0); | |
591 if (!st) | |
592 goto fail; | |
593 rm_read_audio_stream_info(s, st, 1); | |
594 return 0; | |
595 fail: | |
596 return -1; | |
597 } | |
598 | |
0 | 599 static int rm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
600 { | |
601 RMContext *rm = s->priv_data; | |
602 AVStream *st; | |
603 ByteIOContext *pb = &s->pb; | |
604 unsigned int tag, v; | |
605 int tag_size, size, codec_data_size, i; | |
65 | 606 int64_t codec_pos; |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
607 unsigned int h263_hack_version, start_time, duration; |
0 | 608 char buf[128]; |
609 int flags = 0; | |
610 | |
194 | 611 tag = get_le32(pb); |
612 if (tag == MKTAG('.', 'r', 'a', 0xfd)) { | |
613 /* very old .ra format */ | |
614 return rm_read_header_old(s, ap); | |
615 } else if (tag != MKTAG('.', 'R', 'M', 'F')) { | |
482 | 616 return AVERROR_IO; |
194 | 617 } |
0 | 618 |
619 get_be32(pb); /* header size */ | |
620 get_be16(pb); | |
621 get_be32(pb); | |
622 get_be32(pb); /* number of headers */ | |
623 | |
624 for(;;) { | |
625 if (url_feof(pb)) | |
626 goto fail; | |
627 tag = get_le32(pb); | |
628 tag_size = get_be32(pb); | |
629 get_be16(pb); | |
630 #if 0 | |
631 printf("tag=%c%c%c%c (%08x) size=%d\n", | |
632 (tag) & 0xff, | |
633 (tag >> 8) & 0xff, | |
634 (tag >> 16) & 0xff, | |
635 (tag >> 24) & 0xff, | |
636 tag, | |
637 tag_size); | |
638 #endif | |
736 | 639 if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A')) |
0 | 640 goto fail; |
641 switch(tag) { | |
642 case MKTAG('P', 'R', 'O', 'P'): | |
643 /* file header */ | |
644 get_be32(pb); /* max bit rate */ | |
645 get_be32(pb); /* avg bit rate */ | |
646 get_be32(pb); /* max packet size */ | |
647 get_be32(pb); /* avg packet size */ | |
648 get_be32(pb); /* nb packets */ | |
649 get_be32(pb); /* duration */ | |
650 get_be32(pb); /* preroll */ | |
651 get_be32(pb); /* index offset */ | |
652 get_be32(pb); /* data offset */ | |
653 get_be16(pb); /* nb streams */ | |
654 flags = get_be16(pb); /* flags */ | |
655 break; | |
656 case MKTAG('C', 'O', 'N', 'T'): | |
657 get_str(pb, s->title, sizeof(s->title)); | |
658 get_str(pb, s->author, sizeof(s->author)); | |
659 get_str(pb, s->copyright, sizeof(s->copyright)); | |
660 get_str(pb, s->comment, sizeof(s->comment)); | |
661 break; | |
662 case MKTAG('M', 'D', 'P', 'R'): | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
663 st = av_new_stream(s, 0); |
0 | 664 if (!st) |
665 goto fail; | |
666 st->id = get_be16(pb); | |
667 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
|
668 st->codec->bit_rate = get_be32(pb); /* bit rate */ |
0 | 669 get_be32(pb); /* max packet size */ |
670 get_be32(pb); /* avg packet size */ | |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
671 start_time = get_be32(pb); /* start time */ |
0 | 672 get_be32(pb); /* preroll */ |
188
6c9d6422a2f6
update duration and start_time - add av_new_stream() usage
bellard
parents:
85
diff
changeset
|
673 duration = get_be32(pb); /* duration */ |
743 | 674 st->start_time = start_time; |
675 st->duration = duration; | |
0 | 676 get_str8(pb, buf, sizeof(buf)); /* desc */ |
677 get_str8(pb, buf, sizeof(buf)); /* mimetype */ | |
678 codec_data_size = get_be32(pb); | |
679 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
|
680 st->codec->codec_type = CODEC_TYPE_DATA; |
607 | 681 av_set_pts_info(st, 64, 1, 1000); |
0 | 682 |
683 v = get_be32(pb); | |
684 if (v == MKTAG(0xfd, 'a', 'r', '.')) { | |
685 /* ra type header */ | |
194 | 686 rm_read_audio_stream_info(s, st, 0); |
0 | 687 } else { |
604 | 688 int fps, fps2; |
0 | 689 if (get_le32(pb) != MKTAG('V', 'I', 'D', 'O')) { |
690 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
|
691 av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); |
593 | 692 goto skip; |
0 | 693 } |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
694 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
|
695 // 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
|
696 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
|
697 && 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
|
698 && 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
|
699 && st->codec->codec_tag != MKTAG('R', 'V', '4', '0')) |
0 | 700 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
|
701 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
|
702 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
|
703 st->codec->time_base.num= 1; |
604 | 704 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
|
705 st->codec->codec_type = CODEC_TYPE_VIDEO; |
0 | 706 get_be32(pb); |
604 | 707 fps2= get_be16(pb); |
0 | 708 get_be16(pb); |
604 | 709 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
710 st->codec->extradata_size= codec_data_size - (url_ftell(pb) - codec_pos); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
711 st->codec->extradata= av_malloc(st->codec->extradata_size); |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
712 get_buffer(pb, st->codec->extradata, st->codec->extradata_size); |
604 | 713 |
714 // 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
|
715 st->codec->time_base.den = fps * st->codec->time_base.num; |
0 | 716 /* modification of h263 codec version (!) */ |
604 | 717 #ifdef WORDS_BIGENDIAN |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
718 h263_hack_version = ((uint32_t*)st->codec->extradata)[1]; |
604 | 719 #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
|
720 h263_hack_version = bswap_32(((uint32_t*)st->codec->extradata)[1]); |
604 | 721 #endif |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
722 st->codec->sub_id = h263_hack_version; |
638 | 723 switch((h263_hack_version>>28)){ |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
724 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
|
725 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
|
726 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
|
727 case 4: st->codec->codec_id = CODEC_ID_RV40; break; |
638 | 728 default: goto fail1; |
729 } | |
0 | 730 } |
593 | 731 skip: |
0 | 732 /* skip codec info */ |
733 size = url_ftell(pb) - codec_pos; | |
734 url_fskip(pb, codec_data_size - size); | |
735 break; | |
736 case MKTAG('D', 'A', 'T', 'A'): | |
737 goto header_end; | |
738 default: | |
739 /* unknown tag: skip it */ | |
740 url_fskip(pb, tag_size - 10); | |
741 break; | |
742 } | |
743 } | |
744 header_end: | |
745 rm->nb_packets = get_be32(pb); /* number of packets */ | |
746 if (!rm->nb_packets && (flags & 4)) | |
747 rm->nb_packets = 3600 * 25; | |
748 get_be32(pb); /* next data header */ | |
749 return 0; | |
750 | |
751 fail: | |
752 for(i=0;i<s->nb_streams;i++) { | |
753 av_free(s->streams[i]); | |
754 } | |
482 | 755 return AVERROR_IO; |
0 | 756 } |
757 | |
758 static int get_num(ByteIOContext *pb, int *len) | |
759 { | |
760 int n, n1; | |
761 | |
762 n = get_be16(pb); | |
763 (*len)-=2; | |
764 if (n >= 0x4000) { | |
765 return n - 0x4000; | |
766 } else { | |
767 n1 = get_be16(pb); | |
768 (*len)-=2; | |
769 return (n << 16) | n1; | |
770 } | |
771 } | |
772 | |
194 | 773 /* multiple of 20 bytes for ra144 (ugly) */ |
774 #define RAW_PACKET_SIZE 1000 | |
775 | |
613 | 776 static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){ |
612 | 777 RMContext *rm = s->priv_data; |
778 ByteIOContext *pb = &s->pb; | |
779 int len, num, res, i; | |
780 AVStream *st; | |
632 | 781 uint32_t state=0xFFFFFFFF; |
612 | 782 |
783 while(!url_feof(pb)){ | |
613 | 784 *pos= url_ftell(pb); |
612 | 785 if(rm->remaining_len > 0){ |
786 num= rm->current_stream; | |
787 len= rm->remaining_len; | |
788 *timestamp = AV_NOPTS_VALUE; | |
789 *flags= 0; | |
790 }else{ | |
632 | 791 state= (state<<8) + get_byte(pb); |
792 | |
793 if(state == MKBETAG('I', 'N', 'D', 'X')){ | |
794 len = get_be16(pb) - 6; | |
795 if(len<0) | |
796 continue; | |
797 goto skip; | |
798 } | |
799 | |
800 if(state > (unsigned)0xFFFF || state < 12) | |
612 | 801 continue; |
632 | 802 len=state; |
803 state= 0xFFFFFFFF; | |
804 | |
612 | 805 num = get_be16(pb); |
806 *timestamp = get_be32(pb); | |
807 res= get_byte(pb); /* reserved */ | |
808 *flags = get_byte(pb); /* flags */ | |
613 | 809 |
612 | 810 |
811 len -= 12; | |
812 } | |
813 for(i=0;i<s->nb_streams;i++) { | |
814 st = s->streams[i]; | |
815 if (num == st->id) | |
816 break; | |
817 } | |
818 if (i == s->nb_streams) { | |
632 | 819 skip: |
612 | 820 /* skip packet if unknown number */ |
821 url_fskip(pb, len); | |
822 rm->remaining_len -= len; | |
823 continue; | |
824 } | |
825 *stream_index= i; | |
826 | |
827 return len; | |
828 } | |
829 return -1; | |
830 } | |
831 | |
0 | 832 static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) |
833 { | |
834 RMContext *rm = s->priv_data; | |
835 ByteIOContext *pb = &s->pb; | |
836 AVStream *st; | |
612 | 837 int i, len, tmp, j; |
613 | 838 int64_t timestamp, pos; |
65 | 839 uint8_t *ptr; |
612 | 840 int flags; |
0 | 841 |
194 | 842 if (rm->old_format) { |
843 /* just read raw bytes */ | |
844 len = RAW_PACKET_SIZE; | |
775 | 845 len= av_get_packet(pb, pkt, len); |
194 | 846 pkt->stream_index = 0; |
847 if (len <= 0) { | |
482 | 848 return AVERROR_IO; |
194 | 849 } |
850 pkt->size = len; | |
851 st = s->streams[0]; | |
879 | 852 } else if (rm->audio_pkt_cnt) { |
853 // If there are queued audio packet return them first | |
854 st = s->streams[rm->audio_stream_num]; | |
855 av_new_packet(pkt, st->codec->block_align); | |
856 memcpy(pkt->data, rm->audiobuf + st->codec->block_align * | |
857 (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), | |
858 st->codec->block_align); | |
859 rm->audio_pkt_cnt--; | |
860 pkt->flags = 0; | |
861 pkt->stream_index = rm->audio_stream_num; | |
194 | 862 } else { |
613 | 863 int seq=1; |
652 | 864 resync: |
613 | 865 len=sync(s, ×tamp, &flags, &i, &pos); |
612 | 866 if(len<0) |
610
1ab7b989f475
try to recover from errors instead of failing fataly
michael
parents:
609
diff
changeset
|
867 return AVERROR_IO; |
612 | 868 st = s->streams[i]; |
869 | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
870 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
609 | 871 int h, pic_num, len2, pos; |
872 | |
873 h= get_byte(pb); len--; | |
874 if(!(h & 0x40)){ | |
613 | 875 seq = get_byte(pb); len--; |
609 | 876 } |
877 | |
878 if((h & 0xc0) == 0x40){ | |
879 len2= pos= 0; | |
880 }else{ | |
881 len2 = get_num(pb, &len); | |
194 | 882 pos = get_num(pb, &len); |
883 } | |
884 /* picture number */ | |
609 | 885 pic_num= get_byte(pb); len--; |
886 rm->remaining_len= len; | |
887 rm->current_stream= st->id; | |
888 | |
889 // av_log(NULL, AV_LOG_DEBUG, "%X len:%d pos:%d len2:%d pic_num:%d\n",h, len, pos, len2, pic_num); | |
890 if(len2 && len2<len) | |
891 len=len2; | |
892 rm->remaining_len-= len; | |
879 | 893 av_get_packet(pb, pkt, len); |
894 } | |
895 | |
896 if (st->codec->codec_type == CODEC_TYPE_AUDIO) { | |
897 if ((st->codec->codec_id == CODEC_ID_RA_288) || | |
898 (st->codec->codec_id == CODEC_ID_COOK)) { | |
899 int x; | |
900 int sps = rm->sub_packet_size; | |
901 int cfs = rm->coded_framesize; | |
902 int h = rm->sub_packet_h; | |
903 int y = rm->sub_packet_cnt; | |
904 int w = rm->audio_framesize; | |
905 | |
906 if (flags & 2) | |
907 y = rm->sub_packet_cnt = 0; | |
908 if (!y) | |
909 rm->audiotimestamp = timestamp; | |
910 | |
911 switch(st->codec->codec_id) { | |
912 case CODEC_ID_RA_288: | |
913 for (x = 0; x < h/2; x++) | |
914 get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs); | |
915 break; | |
916 case CODEC_ID_COOK: | |
917 for (x = 0; x < w/sps; x++) | |
918 get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps); | |
919 break; | |
920 } | |
921 | |
922 if (++(rm->sub_packet_cnt) < h) | |
923 goto resync; | |
924 else { | |
925 rm->sub_packet_cnt = 0; | |
926 rm->audio_stream_num = i; | |
927 rm->audio_pkt_cnt = h * w / st->codec->block_align - 1; | |
928 // Release first audio packet | |
929 av_new_packet(pkt, st->codec->block_align); | |
930 memcpy(pkt->data, rm->audiobuf, st->codec->block_align); | |
931 timestamp = rm->audiotimestamp; | |
932 flags = 2; // Mark first packet as keyframe | |
933 } | |
934 } else | |
935 av_get_packet(pb, pkt, len); | |
194 | 936 } |
652 | 937 |
708 | 938 if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) |
939 || st->discard >= AVDISCARD_ALL){ | |
879 | 940 av_free_packet(pkt); |
652 | 941 goto resync; |
942 } | |
194 | 943 |
944 pkt->stream_index = i; | |
607 | 945 |
946 #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
|
947 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
|
948 if(st->codec->codec_id == CODEC_ID_RV20){ |
607 | 949 int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1); |
950 av_log(NULL, AV_LOG_DEBUG, "%d %Ld %d\n", timestamp, timestamp*512LL/25, seq); | |
951 | |
952 seq |= (timestamp&~0x3FFF); | |
953 if(seq - timestamp > 0x2000) seq -= 0x4000; | |
954 if(seq - timestamp < -0x2000) seq += 0x4000; | |
955 } | |
956 } | |
957 #endif | |
958 pkt->pts= timestamp; | |
613 | 959 if(flags&2){ |
607 | 960 pkt->flags |= PKT_FLAG_KEY; |
613 | 961 if((seq&0x7F) == 1) |
962 av_add_index_entry(st, pos, timestamp, 0, AVINDEX_KEYFRAME); | |
963 } | |
0 | 964 } |
965 | |
966 /* 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
|
967 if (st->codec->codec_id == CODEC_ID_AC3) { |
0 | 968 ptr = pkt->data; |
969 for(j=0;j<len;j+=2) { | |
970 tmp = ptr[0]; | |
971 ptr[0] = ptr[1]; | |
972 ptr[1] = tmp; | |
973 ptr += 2; | |
974 } | |
975 } | |
976 return 0; | |
977 } | |
978 | |
979 static int rm_read_close(AVFormatContext *s) | |
980 { | |
879 | 981 RMContext *rm = s->priv_data; |
982 | |
983 av_free(rm->audiobuf); | |
0 | 984 return 0; |
985 } | |
986 | |
987 static int rm_probe(AVProbeData *p) | |
988 { | |
989 /* check file header */ | |
990 if (p->buf_size <= 32) | |
991 return 0; | |
194 | 992 if ((p->buf[0] == '.' && p->buf[1] == 'R' && |
993 p->buf[2] == 'M' && p->buf[3] == 'F' && | |
994 p->buf[4] == 0 && p->buf[5] == 0) || | |
995 (p->buf[0] == '.' && p->buf[1] == 'r' && | |
996 p->buf[2] == 'a' && p->buf[3] == 0xfd)) | |
0 | 997 return AVPROBE_SCORE_MAX; |
998 else | |
999 return 0; | |
1000 } | |
1001 | |
612 | 1002 static int64_t rm_read_dts(AVFormatContext *s, int stream_index, |
1003 int64_t *ppos, int64_t pos_limit) | |
1004 { | |
1005 RMContext *rm = s->priv_data; | |
1006 int64_t pos, dts; | |
613 | 1007 int stream_index2, flags, len, h; |
612 | 1008 |
1009 pos = *ppos; | |
1010 | |
1011 if(rm->old_format) | |
1012 return AV_NOPTS_VALUE; | |
1013 | |
1014 url_fseek(&s->pb, pos, SEEK_SET); | |
1015 rm->remaining_len=0; | |
1016 for(;;){ | |
613 | 1017 int seq=1; |
1018 AVStream *st; | |
1019 | |
1020 len=sync(s, &dts, &flags, &stream_index2, &pos); | |
612 | 1021 if(len<0) |
1022 return AV_NOPTS_VALUE; | |
613 | 1023 |
1024 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
|
1025 if (st->codec->codec_type == CODEC_TYPE_VIDEO) { |
613 | 1026 h= get_byte(&s->pb); len--; |
1027 if(!(h & 0x40)){ | |
1028 seq = get_byte(&s->pb); len--; | |
612 | 1029 } |
1030 } | |
613 | 1031 |
1032 if((flags&2) && (seq&0x7F) == 1){ | |
1033 // av_log(s, AV_LOG_DEBUG, "%d %d-%d %Ld %d\n", flags, stream_index2, stream_index, dts, seq); | |
1034 av_add_index_entry(st, pos, dts, 0, AVINDEX_KEYFRAME); | |
1035 if(stream_index2 == stream_index) | |
1036 break; | |
1037 } | |
1038 | |
612 | 1039 url_fskip(&s->pb, len); |
1040 } | |
1041 *ppos = pos; | |
1042 return dts; | |
1043 } | |
1044 | |
0 | 1045 static AVInputFormat rm_iformat = { |
1046 "rm", | |
1047 "rm format", | |
1048 sizeof(RMContext), | |
1049 rm_probe, | |
1050 rm_read_header, | |
1051 rm_read_packet, | |
1052 rm_read_close, | |
612 | 1053 NULL, |
1054 rm_read_dts, | |
0 | 1055 }; |
1056 | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
1057 #ifdef CONFIG_MUXERS |
0 | 1058 static AVOutputFormat rm_oformat = { |
1059 "rm", | |
1060 "rm format", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
7
diff
changeset
|
1061 "application/vnd.rn-realmedia", |
0 | 1062 "rm,ra", |
1063 sizeof(RMContext), | |
1064 CODEC_ID_AC3, | |
1065 CODEC_ID_RV10, | |
1066 rm_write_header, | |
1067 rm_write_packet, | |
1068 rm_write_trailer, | |
1069 }; | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
1070 #endif //CONFIG_MUXERS |
0 | 1071 |
1072 int rm_init(void) | |
1073 { | |
1074 av_register_input_format(&rm_iformat); | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
1075 #ifdef CONFIG_MUXERS |
0 | 1076 av_register_output_format(&rm_oformat); |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
1077 #endif //CONFIG_MUXERS |
0 | 1078 return 0; |
1079 } |