av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
[libav.git] / libavformat / asf.c
CommitLineData
de6d9b64
FB
1/*
2 * ASF compatible encoder and decoder.
19720f15 3 * Copyright (c) 2000, 2001 Fabrice Bellard.
de6d9b64 4 *
19720f15
FB
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.
de6d9b64 9 *
19720f15 10 * This library is distributed in the hope that it will be useful,
de6d9b64 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19720f15
FB
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
de6d9b64 14 *
19720f15
FB
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
de6d9b64 18 */
de6d9b64
FB
19#include "avformat.h"
20#include "avi.h"
f80c1ac0 21#include "mpegaudio.h"
de6d9b64 22
580fb5e7
MN
23#undef NDEBUG
24#include <assert.h>
25
de6d9b64
FB
26#define PACKET_SIZE 3200
27#define PACKET_HEADER_SIZE 12
28#define FRAME_HEADER_SIZE 17
29
30typedef struct {
31 int num;
32 int seq;
33 /* use for reading */
34 AVPacket pkt;
35 int frag_offset;
2a10020b 36 int timestamp;
0c1a9eda 37 int64_t duration;
2a10020b
ZK
38
39 int ds_span; /* descrambling */
40 int ds_packet_size;
41 int ds_chunk_size;
42 int ds_data_size;
43 int ds_silence_data;
82b9e4a2
MN
44
45 int packet_pos;
2a10020b 46
de6d9b64
FB
47} ASFStream;
48
49typedef struct {
0c1a9eda
ZK
50 uint32_t v1;
51 uint16_t v2;
52 uint16_t v3;
53 uint8_t v4[8];
2a10020b
ZK
54} GUID;
55
247eadca 56typedef struct {
2a10020b
ZK
57 GUID guid; // generated by client computer
58 uint64_t file_size; // in bytes
59 // invalid if broadcasting
60 uint64_t create_time; // time of creation, in 100-nanosecond units since 1.1.1601
61 // invalid if broadcasting
62 uint64_t packets_count; // how many packets are there in the file
63 // invalid if broadcasting
64 uint64_t play_time; // play time, in 100-nanosecond units
65 // invalid if broadcasting
66 uint64_t send_time; // time to send file, in 100-nanosecond units
67 // invalid if broadcasting (could be ignored)
68 uint32_t preroll; // timestamp of the first packet, in milliseconds
69 // if nonzero - substract from time
70 uint32_t ignore; // preroll is 64bit - but let's just ignore it
71 uint32_t flags; // 0x01 - broadcast
72 // 0x02 - seekable
73 // rest is reserved should be 0
74 uint32_t min_pktsize; // size of a data packet
75 // invalid if broadcasting
76 uint32_t max_pktsize; // shall be the same as for min_pktsize
77 // invalid if broadcasting
78 uint32_t max_bitrate; // bandwith of stream in bps
79 // should be the sum of bitrates of the
80 // individual media streams
81} ASFMainHeader;
82
83
84typedef struct {
de6d9b64
FB
85 int seqno;
86 int packet_size;
8b3c13f9 87 int is_streamed;
2141dc37
ZK
88 int asfid2avid[128]; /* conversion table from asf ID 2 AVStream ID */
89 ASFStream streams[128]; /* it's max number and it's not that big */
de6d9b64 90 /* non streamed additonnal info */
0c1a9eda
ZK
91 int64_t nb_packets;
92 int64_t duration; /* in 100ns units */
de6d9b64
FB
93 /* packet filling */
94 int packet_size_left;
95 int packet_timestamp_start;
96 int packet_timestamp_end;
97 int packet_nb_frames;
0c1a9eda 98 uint8_t packet_buf[PACKET_SIZE];
de6d9b64
FB
99 ByteIOContext pb;
100 /* only for reading */
2a10020b
ZK
101 uint64_t data_offset; /* begining of the first data packet */
102
103 ASFMainHeader hdr;
104
105 int packet_flags;
106 int packet_property;
107 int packet_timestamp;
108 int packet_segsizetype;
109 int packet_segments;
110 int packet_seq;
111 int packet_replic_size;
112 int packet_key_frame;
de6d9b64 113 int packet_padsize;
2a10020b
ZK
114 int packet_frag_offset;
115 int packet_frag_size;
116 int packet_frag_timestamp;
2141dc37 117 int packet_multi_size;
2a10020b
ZK
118 int packet_obj_size;
119 int packet_time_delta;
120 int packet_time_start;
82b9e4a2 121 int packet_pos;
2a10020b
ZK
122
123 int stream_index;
124 ASFStream* asf_st; /* currently decoded stream */
de6d9b64
FB
125} ASFContext;
126
de6d9b64
FB
127static const GUID asf_header = {
128 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
129};
130
131static const GUID file_header = {
132 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
133};
134
135static const GUID stream_header = {
136 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
137};
138
139static const GUID audio_stream = {
140 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
141};
142
143static const GUID audio_conceal_none = {
f80c1ac0
PG
144 // 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
145 // New value lifted from avifile
146 0x20fb5700, 0x5b55, 0x11cf, { 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b },
de6d9b64
FB
147};
148
149static const GUID video_stream = {
150 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
151};
152
153static const GUID video_conceal_none = {
154 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
155};
156
157
158static const GUID comment_header = {
159 0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
160};
161
162static const GUID codec_comment_header = {
163 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
164};
165static const GUID codec_comment1_header = {
166 0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
167};
168
169static const GUID data_header = {
170 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
171};
172
173static const GUID index_guid = {
174 0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },
175};
176
177static const GUID head1_guid = {
178 0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
179};
180
181static const GUID head2_guid = {
182 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
183};
2a10020b 184
d13431cd
KK
185static const GUID extended_content_header = {
186 0xD2D0A440, 0xE307, 0x11D2, { 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 },
187};
188
de6d9b64
FB
189/* I am not a number !!! This GUID is the one found on the PC used to
190 generate the stream */
191static const GUID my_guid = {
192 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 },
193};
194
764ef400 195#ifdef CONFIG_ENCODERS
de6d9b64
FB
196static void put_guid(ByteIOContext *s, const GUID *g)
197{
198 int i;
199
200 put_le32(s, g->v1);
201 put_le16(s, g->v2);
202 put_le16(s, g->v3);
203 for(i=0;i<8;i++)
204 put_byte(s, g->v4[i]);
205}
206
207static void put_str16(ByteIOContext *s, const char *tag)
208{
209 int c;
210
211 put_le16(s,strlen(tag) + 1);
212 for(;;) {
0c1a9eda 213 c = (uint8_t)*tag++;
de6d9b64 214 put_le16(s, c);
2a10020b 215 if (c == '\0')
de6d9b64
FB
216 break;
217 }
218}
219
220static void put_str16_nolen(ByteIOContext *s, const char *tag)
221{
222 int c;
223
224 for(;;) {
0c1a9eda 225 c = (uint8_t)*tag++;
de6d9b64 226 put_le16(s, c);
2a10020b 227 if (c == '\0')
de6d9b64
FB
228 break;
229 }
230}
231
0c1a9eda 232static int64_t put_header(ByteIOContext *pb, const GUID *g)
de6d9b64 233{
0c1a9eda 234 int64_t pos;
de6d9b64
FB
235
236 pos = url_ftell(pb);
237 put_guid(pb, g);
238 put_le64(pb, 24);
239 return pos;
240}
241
242/* update header size */
0c1a9eda 243static void end_header(ByteIOContext *pb, int64_t pos)
de6d9b64 244{
0c1a9eda 245 int64_t pos1;
de6d9b64
FB
246
247 pos1 = url_ftell(pb);
248 url_fseek(pb, pos + 16, SEEK_SET);
249 put_le64(pb, pos1 - pos);
250 url_fseek(pb, pos1, SEEK_SET);
251}
252
253/* write an asf chunk (only used in streaming case) */
f80c1ac0 254static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
de6d9b64
FB
255{
256 ASFContext *asf = s->priv_data;
257 ByteIOContext *pb = &s->pb;
258 int length;
259
260 length = payload_length + 8;
2a10020b
ZK
261 put_le16(pb, type);
262 put_le16(pb, length);
de6d9b64 263 put_le32(pb, asf->seqno);
f80c1ac0 264 put_le16(pb, flags); /* unknown bytes */
de6d9b64
FB
265 put_le16(pb, length);
266 asf->seqno++;
267}
268
269/* convert from unix to windows time */
0c1a9eda 270static int64_t unix_to_file_time(int ti)
de6d9b64 271{
0c1a9eda 272 int64_t t;
2a10020b 273
0c1a9eda
ZK
274 t = ti * int64_t_C(10000000);
275 t += int64_t_C(116444736000000000);
de6d9b64
FB
276 return t;
277}
278
279/* write the header (used two times if non streamed) */
0c1a9eda 280static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size)
de6d9b64
FB
281{
282 ASFContext *asf = s->priv_data;
283 ByteIOContext *pb = &s->pb;
284 int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
285 int has_title;
286 AVCodecContext *enc;
0c1a9eda 287 int64_t header_offset, cur_pos, hpos;
f80c1ac0 288 int bit_rate;
de6d9b64 289
084fada8 290 has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]);
de6d9b64 291
f80c1ac0
PG
292 bit_rate = 0;
293 for(n=0;n<s->nb_streams;n++) {
294 enc = &s->streams[n]->codec;
295
296 bit_rate += enc->bit_rate;
297 }
298
8b3c13f9 299 if (asf->is_streamed) {
f80c1ac0 300 put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
de6d9b64 301 }
f80c1ac0
PG
302
303 put_guid(pb, &asf_header);
2a10020b 304 put_le64(pb, -1); /* header length, will be patched after */
f80c1ac0
PG
305 put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */
306 put_byte(pb, 1); /* ??? */
307 put_byte(pb, 2); /* ??? */
2a10020b 308
de6d9b64
FB
309 /* file header */
310 header_offset = url_ftell(pb);
311 hpos = put_header(pb, &file_header);
312 put_guid(pb, &my_guid);
313 put_le64(pb, file_size);
314 file_time = 0;
315 put_le64(pb, unix_to_file_time(file_time));
316 put_le64(pb, asf->nb_packets); /* number of packets */
317 put_le64(pb, asf->duration); /* end time stamp (in 100ns units) */
318 put_le64(pb, asf->duration); /* duration (in 100ns units) */
2a10020b
ZK
319 put_le32(pb, 0); /* start time stamp */
320 put_le32(pb, 0); /* ??? */
321 put_le32(pb, asf->is_streamed ? 1 : 0); /* ??? */
de6d9b64
FB
322 put_le32(pb, asf->packet_size); /* packet size */
323 put_le32(pb, asf->packet_size); /* packet size */
f80c1ac0 324 put_le32(pb, bit_rate); /* Nominal data rate in bps */
de6d9b64
FB
325 end_header(pb, hpos);
326
327 /* unknown headers */
328 hpos = put_header(pb, &head1_guid);
329 put_guid(pb, &head2_guid);
330 put_le32(pb, 6);
331 put_le16(pb, 0);
332 end_header(pb, hpos);
333
334 /* title and other infos */
335 if (has_title) {
336 hpos = put_header(pb, &comment_header);
337 put_le16(pb, 2 * (strlen(s->title) + 1));
338 put_le16(pb, 2 * (strlen(s->author) + 1));
339 put_le16(pb, 2 * (strlen(s->copyright) + 1));
340 put_le16(pb, 2 * (strlen(s->comment) + 1));
341 put_le16(pb, 0);
342 put_str16_nolen(pb, s->title);
343 put_str16_nolen(pb, s->author);
344 put_str16_nolen(pb, s->copyright);
345 put_str16_nolen(pb, s->comment);
346 end_header(pb, hpos);
347 }
348
349 /* stream headers */
350 for(n=0;n<s->nb_streams;n++) {
0c1a9eda 351 int64_t es_pos;
17a241dd 352 // ASFStream *stream = &asf->streams[n];
f80c1ac0 353
de6d9b64
FB
354 enc = &s->streams[n]->codec;
355 asf->streams[n].num = n + 1;
356 asf->streams[n].seq = 0;
2a10020b 357
de6d9b64
FB
358 switch(enc->codec_type) {
359 case CODEC_TYPE_AUDIO:
360 wav_extra_size = 0;
361 extra_size = 18 + wav_extra_size;
362 extra_size2 = 0;
363 break;
364 default:
365 case CODEC_TYPE_VIDEO:
366 wav_extra_size = 0;
367 extra_size = 0x33;
368 extra_size2 = 0;
369 break;
370 }
371
372 hpos = put_header(pb, &stream_header);
373 if (enc->codec_type == CODEC_TYPE_AUDIO) {
374 put_guid(pb, &audio_stream);
375 put_guid(pb, &audio_conceal_none);
376 } else {
377 put_guid(pb, &video_stream);
378 put_guid(pb, &video_conceal_none);
379 }
380 put_le64(pb, 0); /* ??? */
f80c1ac0 381 es_pos = url_ftell(pb);
de6d9b64
FB
382 put_le32(pb, extra_size); /* wav header len */
383 put_le32(pb, extra_size2); /* additional data len */
384 put_le16(pb, n + 1); /* stream number */
385 put_le32(pb, 0); /* ??? */
2a10020b 386
de6d9b64
FB
387 if (enc->codec_type == CODEC_TYPE_AUDIO) {
388 /* WAVEFORMATEX header */
f80c1ac0
PG
389 int wavsize = put_wav_header(pb, enc);
390
391 if (wavsize < 0)
46a3d068 392 return -1;
f80c1ac0
PG
393 if (wavsize != extra_size) {
394 cur_pos = url_ftell(pb);
395 url_fseek(pb, es_pos, SEEK_SET);
396 put_le32(pb, wavsize); /* wav header len */
397 url_fseek(pb, cur_pos, SEEK_SET);
398 }
de6d9b64
FB
399 } else {
400 put_le32(pb, enc->width);
401 put_le32(pb, enc->height);
402 put_byte(pb, 2); /* ??? */
403 put_le16(pb, 40); /* size */
404
405 /* BITMAPINFOHEADER header */
2727c35e 406 put_bmp_header(pb, enc, codec_bmp_tags, 1);
de6d9b64
FB
407 }
408 end_header(pb, hpos);
409 }
410
411 /* media comments */
412
413 hpos = put_header(pb, &codec_comment_header);
414 put_guid(pb, &codec_comment1_header);
415 put_le32(pb, s->nb_streams);
416 for(n=0;n<s->nb_streams;n++) {
084fada8
PG
417 AVCodec *p;
418
de6d9b64 419 enc = &s->streams[n]->codec;
084fada8 420 p = avcodec_find_encoder(enc->codec_id);
de6d9b64
FB
421
422 put_le16(pb, asf->streams[n].num);
084fada8 423 put_str16(pb, p ? p->name : enc->codec_name);
de6d9b64 424 put_le16(pb, 0); /* no parameters */
bd5a6020
MN
425
426
de6d9b64
FB
427 /* id */
428 if (enc->codec_type == CODEC_TYPE_AUDIO) {
429 put_le16(pb, 2);
bd5a6020
MN
430 if(!enc->codec_tag)
431 enc->codec_tag = codec_get_tag(codec_wav_tags, enc->codec_id);
432 if(!enc->codec_tag)
433 return -1;
434 put_le16(pb, enc->codec_tag);
de6d9b64
FB
435 } else {
436 put_le16(pb, 4);
bd5a6020
MN
437 if(!enc->codec_tag)
438 enc->codec_tag = codec_get_tag(codec_bmp_tags, enc->codec_id);
439 if(!enc->codec_tag)
440 return -1;
441 put_le32(pb, enc->codec_tag);
de6d9b64
FB
442 }
443 }
444 end_header(pb, hpos);
445
446 /* patch the header size fields */
447
448 cur_pos = url_ftell(pb);
449 header_size = cur_pos - header_offset;
8b3c13f9 450 if (asf->is_streamed) {
f80c1ac0
PG
451 header_size += 8 + 30 + 50;
452
453 url_fseek(pb, header_offset - 10 - 30, SEEK_SET);
de6d9b64 454 put_le16(pb, header_size);
f80c1ac0 455 url_fseek(pb, header_offset - 2 - 30, SEEK_SET);
de6d9b64 456 put_le16(pb, header_size);
f80c1ac0
PG
457
458 header_size -= 8 + 30 + 50;
de6d9b64 459 }
f80c1ac0
PG
460 header_size += 24 + 6;
461 url_fseek(pb, header_offset - 14, SEEK_SET);
462 put_le64(pb, header_size);
de6d9b64
FB
463 url_fseek(pb, cur_pos, SEEK_SET);
464
465 /* movie chunk, followed by packets of packet_size */
466 asf->data_offset = cur_pos;
467 put_guid(pb, &data_header);
468 put_le64(pb, data_chunk_size);
469 put_guid(pb, &my_guid);
470 put_le64(pb, asf->nb_packets); /* nb packets */
471 put_byte(pb, 1); /* ??? */
472 put_byte(pb, 1); /* ??? */
473 return 0;
474}
475
476static int asf_write_header(AVFormatContext *s)
477{
c9a65ca8 478 ASFContext *asf = s->priv_data;
de6d9b64 479
17a241dd
FB
480 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */
481
de6d9b64
FB
482 asf->packet_size = PACKET_SIZE;
483 asf->nb_packets = 0;
484
f80c1ac0 485 if (asf_write_header1(s, 0, 50) < 0) {
2824c473 486 //av_free(asf);
46a3d068
FB
487 return -1;
488 }
de6d9b64
FB
489
490 put_flush_packet(&s->pb);
491
492 asf->packet_nb_frames = 0;
493 asf->packet_timestamp_start = -1;
494 asf->packet_timestamp_end = -1;
495 asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
496 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
497 NULL, NULL, NULL, NULL);
498
499 return 0;
500}
501
8b3c13f9
PG
502static int asf_write_stream_header(AVFormatContext *s)
503{
504 ASFContext *asf = s->priv_data;
505
506 asf->is_streamed = 1;
507
508 return asf_write_header(s);
509}
510
de6d9b64 511/* write a fixed size packet */
2a10020b
ZK
512static int put_packet(AVFormatContext *s,
513 unsigned int timestamp, unsigned int duration,
de6d9b64
FB
514 int nb_frames, int padsize)
515{
516 ASFContext *asf = s->priv_data;
517 ByteIOContext *pb = &s->pb;
518 int flags;
519
8b3c13f9 520 if (asf->is_streamed) {
f80c1ac0 521 put_chunk(s, 0x4424, asf->packet_size, 0);
de6d9b64
FB
522 }
523
524 put_byte(pb, 0x82);
525 put_le16(pb, 0);
2a10020b 526
de6d9b64
FB
527 flags = 0x01; /* nb segments present */
528 if (padsize > 0) {
529 if (padsize < 256)
530 flags |= 0x08;
531 else
532 flags |= 0x10;
533 }
534 put_byte(pb, flags); /* flags */
535 put_byte(pb, 0x5d);
536 if (flags & 0x10)
f80c1ac0 537 put_le16(pb, padsize - 2);
de6d9b64 538 if (flags & 0x08)
f80c1ac0 539 put_byte(pb, padsize - 1);
de6d9b64
FB
540 put_le32(pb, timestamp);
541 put_le16(pb, duration);
542 put_byte(pb, nb_frames | 0x80);
f80c1ac0
PG
543
544 return PACKET_HEADER_SIZE + ((flags & 0x18) >> 3);
de6d9b64
FB
545}
546
547static void flush_packet(AVFormatContext *s)
548{
549 ASFContext *asf = s->priv_data;
550 int hdr_size, ptr;
2a10020b
ZK
551
552 hdr_size = put_packet(s, asf->packet_timestamp_start,
553 asf->packet_timestamp_end - asf->packet_timestamp_start,
de6d9b64 554 asf->packet_nb_frames, asf->packet_size_left);
2a10020b 555
f80c1ac0
PG
556 /* Clear out the padding bytes */
557 ptr = asf->packet_size - hdr_size - asf->packet_size_left;
de6d9b64 558 memset(asf->packet_buf + ptr, 0, asf->packet_size_left);
2a10020b 559
de6d9b64 560 put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size);
2a10020b 561
de6d9b64
FB
562 put_flush_packet(&s->pb);
563 asf->nb_packets++;
564 asf->packet_nb_frames = 0;
565 asf->packet_timestamp_start = -1;
566 asf->packet_timestamp_end = -1;
567 asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
568 init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
569 NULL, NULL, NULL, NULL);
570}
571
572static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp,
573 int payload_size, int frag_offset, int frag_len)
574{
575 ASFContext *asf = s->priv_data;
576 ByteIOContext *pb = &asf->pb;
577 int val;
578
579 val = stream->num;
492cd3a9 580 if (s->streams[val - 1]->codec.coded_frame->key_frame /* && frag_offset == 0 */)
de6d9b64
FB
581 val |= 0x80;
582 put_byte(pb, val);
583 put_byte(pb, stream->seq);
584 put_le32(pb, frag_offset); /* fragment offset */
585 put_byte(pb, 0x08); /* flags */
586 put_le32(pb, payload_size);
587 put_le32(pb, timestamp);
588 put_le16(pb, frag_len);
589}
590
591
592/* Output a frame. We suppose that payload_size <= PACKET_SIZE.
593
594 It is there that you understand that the ASF format is really
2a10020b 595 crap. They have misread the MPEG Systems spec !
de6d9b64
FB
596 */
597static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp,
49057904 598 const uint8_t *buf, int payload_size)
de6d9b64
FB
599{
600 ASFContext *asf = s->priv_data;
601 int frag_pos, frag_len, frag_len1;
2a10020b 602
de6d9b64
FB
603 frag_pos = 0;
604 while (frag_pos < payload_size) {
605 frag_len = payload_size - frag_pos;
606 frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE;
607 if (frag_len1 > 0) {
608 if (frag_len > frag_len1)
609 frag_len = frag_len1;
b13a517f 610 put_frame_header(s, stream, timestamp+1, payload_size, frag_pos, frag_len);
de6d9b64
FB
611 put_buffer(&asf->pb, buf, frag_len);
612 asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE);
613 asf->packet_timestamp_end = timestamp;
614 if (asf->packet_timestamp_start == -1)
615 asf->packet_timestamp_start = timestamp;
616 asf->packet_nb_frames++;
617 } else {
618 frag_len = 0;
619 }
620 frag_pos += frag_len;
621 buf += frag_len;
622 /* output the frame if filled */
623 if (asf->packet_size_left <= FRAME_HEADER_SIZE)
624 flush_packet(s);
625 }
626 stream->seq++;
627}
628
629
630static int asf_write_packet(AVFormatContext *s, int stream_index,
49057904 631 const uint8_t *buf, int size, int64_t timestamp)
de6d9b64
FB
632{
633 ASFContext *asf = s->priv_data;
e0d2714a 634 ASFStream *stream;
0c1a9eda 635 int64_t duration;
de6d9b64
FB
636 AVCodecContext *codec;
637
638 codec = &s->streams[stream_index]->codec;
e0d2714a 639 stream = &asf->streams[stream_index];
2a10020b 640
de6d9b64 641 if (codec->codec_type == CODEC_TYPE_AUDIO) {
0c1a9eda 642 duration = (codec->frame_number * codec->frame_size * int64_t_C(10000000)) /
de6d9b64
FB
643 codec->sample_rate;
644 } else {
14bea432 645 duration = av_rescale(codec->frame_number * codec->frame_rate_base, 10000000, codec->frame_rate);
de6d9b64
FB
646 }
647 if (duration > asf->duration)
648 asf->duration = duration;
2a10020b 649
e0d2714a 650 put_frame(s, stream, timestamp, buf, size);
de6d9b64
FB
651 return 0;
652}
2a10020b 653
de6d9b64
FB
654static int asf_write_trailer(AVFormatContext *s)
655{
656 ASFContext *asf = s->priv_data;
0c1a9eda 657 int64_t file_size;
de6d9b64
FB
658
659 /* flush the current packet */
660 if (asf->pb.buf_ptr > asf->pb.buffer)
661 flush_packet(s);
662
8b3c13f9 663 if (asf->is_streamed) {
f80c1ac0 664 put_chunk(s, 0x4524, 0, 0); /* end of stream */
de6d9b64
FB
665 } else {
666 /* rewrite an updated header */
667 file_size = url_ftell(&s->pb);
668 url_fseek(&s->pb, 0, SEEK_SET);
669 asf_write_header1(s, file_size, file_size - asf->data_offset);
670 }
671
672 put_flush_packet(&s->pb);
de6d9b64
FB
673 return 0;
674}
764ef400 675#endif //CONFIG_ENCODERS
de6d9b64
FB
676
677/**********************************/
678/* decoding */
679
680//#define DEBUG
681
682#ifdef DEBUG
5082f759
FR
683#define PRINT_IF_GUID(g,cmp) \
684if (!memcmp(g, &cmp, sizeof(GUID))) \
685 printf("(GUID: %s) ", #cmp)
686
de6d9b64
FB
687static void print_guid(const GUID *g)
688{
689 int i;
5082f759
FR
690 PRINT_IF_GUID(g, asf_header);
691 else PRINT_IF_GUID(g, file_header);
692 else PRINT_IF_GUID(g, stream_header);
693 else PRINT_IF_GUID(g, audio_stream);
694 else PRINT_IF_GUID(g, audio_conceal_none);
695 else PRINT_IF_GUID(g, video_stream);
696 else PRINT_IF_GUID(g, video_conceal_none);
697 else PRINT_IF_GUID(g, comment_header);
698 else PRINT_IF_GUID(g, codec_comment_header);
699 else PRINT_IF_GUID(g, codec_comment1_header);
700 else PRINT_IF_GUID(g, data_header);
701 else PRINT_IF_GUID(g, index_guid);
702 else PRINT_IF_GUID(g, head1_guid);
703 else PRINT_IF_GUID(g, head2_guid);
704 else PRINT_IF_GUID(g, my_guid);
705 else
706 printf("(GUID: unknown) ");
de6d9b64 707 printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3);
2a10020b 708 for(i=0;i<8;i++)
de6d9b64
FB
709 printf(" 0x%02x,", g->v4[i]);
710 printf("}\n");
711}
5082f759 712#undef PRINT_IF_GUID(g,cmp)
de6d9b64
FB
713#endif
714
715static void get_guid(ByteIOContext *s, GUID *g)
716{
717 int i;
718
719 g->v1 = get_le32(s);
720 g->v2 = get_le16(s);
721 g->v3 = get_le16(s);
722 for(i=0;i<8;i++)
723 g->v4[i] = get_byte(s);
724}
725
726#if 0
727static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
728{
729 int len, c;
730 char *q;
731
732 len = get_le16(pb);
733 q = buf;
734 while (len > 0) {
735 c = get_le16(pb);
736 if ((q - buf) < buf_size - 1)
737 *q++ = c;
738 len--;
739 }
740 *q = '\0';
741}
742#endif
743
744static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
745{
746 int c;
747 char *q;
748
749 q = buf;
750 while (len > 0) {
751 c = get_le16(pb);
752 if ((q - buf) < buf_size - 1)
753 *q++ = c;
754 len-=2;
755 }
756 *q = '\0';
757}
758
c9a65ca8
FB
759static int asf_probe(AVProbeData *pd)
760{
761 GUID g;
762 const unsigned char *p;
763 int i;
764
765 /* check file header */
766 if (pd->buf_size <= 32)
767 return 0;
768 p = pd->buf;
769 g.v1 = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
770 p += 4;
771 g.v2 = p[0] | (p[1] << 8);
772 p += 2;
773 g.v3 = p[0] | (p[1] << 8);
774 p += 2;
775 for(i=0;i<8;i++)
776 g.v4[i] = *p++;
777
778 if (!memcmp(&g, &asf_header, sizeof(GUID)))
779 return AVPROBE_SCORE_MAX;
780 else
781 return 0;
782}
783
de6d9b64
FB
784static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
785{
c9a65ca8 786 ASFContext *asf = s->priv_data;
de6d9b64
FB
787 GUID g;
788 ByteIOContext *pb = &s->pb;
789 AVStream *st;
790 ASFStream *asf_st;
e095026a 791 int size, i;
0c1a9eda 792 int64_t gsize;
de6d9b64 793
17a241dd
FB
794 av_set_pts_info(s, 32, 1, 1000); /* 32 bit pts in ms */
795
de6d9b64
FB
796 get_guid(pb, &g);
797 if (memcmp(&g, &asf_header, sizeof(GUID)))
798 goto fail;
799 get_le64(pb);
800 get_le32(pb);
801 get_byte(pb);
802 get_byte(pb);
2141dc37 803 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
de6d9b64
FB
804 for(;;) {
805 get_guid(pb, &g);
806 gsize = get_le64(pb);
807#ifdef DEBUG
808 printf("%08Lx: ", url_ftell(pb) - 24);
809 print_guid(&g);
810 printf(" size=0x%Lx\n", gsize);
811#endif
812 if (gsize < 24)
813 goto fail;
814 if (!memcmp(&g, &file_header, sizeof(GUID))) {
2a10020b
ZK
815 get_guid(pb, &asf->hdr.guid);
816 asf->hdr.file_size = get_le64(pb);
817 asf->hdr.create_time = get_le64(pb);
818 asf->hdr.packets_count = get_le64(pb);
819 asf->hdr.play_time = get_le64(pb);
820 asf->hdr.send_time = get_le64(pb);
821 asf->hdr.preroll = get_le32(pb);
822 asf->hdr.ignore = get_le32(pb);
823 asf->hdr.flags = get_le32(pb);
824 asf->hdr.min_pktsize = get_le32(pb);
825 asf->hdr.max_pktsize = get_le32(pb);
826 asf->hdr.max_bitrate = get_le32(pb);
2141dc37
ZK
827 asf->packet_size = asf->hdr.max_pktsize;
828 asf->nb_packets = asf->hdr.packets_count;
de6d9b64 829 } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
2e7973bb 830 int type, total_size, type_specific_size;
de6d9b64 831 unsigned int tag1;
0c1a9eda 832 int64_t pos1, pos2;
2a10020b 833
de6d9b64
FB
834 pos1 = url_ftell(pb);
835
247eadca 836 st = av_new_stream(s, 0);
de6d9b64
FB
837 if (!st)
838 goto fail;
de6d9b64
FB
839 asf_st = av_mallocz(sizeof(ASFStream));
840 if (!asf_st)
841 goto fail;
842 st->priv_data = asf_st;
247eadca
FB
843 st->start_time = asf->hdr.preroll / (10000000 / AV_TIME_BASE);
844 st->duration = (asf->hdr.send_time - asf->hdr.preroll) /
845 (10000000 / AV_TIME_BASE);
de6d9b64
FB
846 get_guid(pb, &g);
847 if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
848 type = CODEC_TYPE_AUDIO;
849 } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
850 type = CODEC_TYPE_VIDEO;
851 } else {
852 goto fail;
853 }
854 get_guid(pb, &g);
855 total_size = get_le64(pb);
2e7973bb 856 type_specific_size = get_le32(pb);
de6d9b64 857 get_le32(pb);
2a10020b
ZK
858 st->id = get_le16(pb) & 0x7f; /* stream id */
859 // mapping of asf ID to AV stream ID;
247eadca 860 asf->asfid2avid[st->id] = s->nb_streams - 1;
2a10020b 861
de6d9b64 862 get_le32(pb);
2141dc37 863 st->codec.codec_type = type;
afda223c
FB
864 /* 1 fps default (XXX: put 0 fps instead) */
865 st->codec.frame_rate = 1;
866 st->codec.frame_rate_base = 1;
de6d9b64 867 if (type == CODEC_TYPE_AUDIO) {
2e7973bb 868 get_wav_header(pb, &st->codec, type_specific_size);
afda223c 869 st->need_parsing = 1;
2a10020b
ZK
870 /* We have to init the frame size at some point .... */
871 pos2 = url_ftell(pb);
2141dc37 872 if (gsize > (pos2 + 8 - pos1 + 24)) {
2a10020b
ZK
873 asf_st->ds_span = get_byte(pb);
874 asf_st->ds_packet_size = get_le16(pb);
875 asf_st->ds_chunk_size = get_le16(pb);
876 asf_st->ds_data_size = get_le16(pb);
877 asf_st->ds_silence_data = get_byte(pb);
878 }
879 //printf("Descrambling: ps:%d cs:%d ds:%d s:%d sd:%d\n",
880 // asf_st->ds_packet_size, asf_st->ds_chunk_size,
881 // asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
2141dc37 882 if (asf_st->ds_span > 1) {
2a10020b
ZK
883 if (!asf_st->ds_chunk_size
884 || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1))
885 asf_st->ds_span = 0; // disable descrambling
886 }
f80c1ac0 887 switch (st->codec.codec_id) {
80783dc2 888 case CODEC_ID_MP3:
f80c1ac0
PG
889 st->codec.frame_size = MPA_FRAME_SIZE;
890 break;
891 case CODEC_ID_PCM_S16LE:
892 case CODEC_ID_PCM_S16BE:
893 case CODEC_ID_PCM_U16LE:
894 case CODEC_ID_PCM_U16BE:
895 case CODEC_ID_PCM_S8:
896 case CODEC_ID_PCM_U8:
897 case CODEC_ID_PCM_ALAW:
898 case CODEC_ID_PCM_MULAW:
899 st->codec.frame_size = 1;
900 break;
901 default:
902 /* This is probably wrong, but it prevents a crash later */
903 st->codec.frame_size = 1;
904 break;
905 }
de6d9b64 906 } else {
2141dc37 907 get_le32(pb);
de6d9b64
FB
908 get_le32(pb);
909 get_byte(pb);
910 size = get_le16(pb); /* size */
911 get_le32(pb); /* size */
912 st->codec.width = get_le32(pb);
2a10020b
ZK
913 st->codec.height = get_le32(pb);
914 /* not available for asf */
de6d9b64 915 get_le16(pb); /* panes */
693feac5 916 st->codec.bits_per_sample = get_le16(pb); /* depth */
de6d9b64 917 tag1 = get_le32(pb);
2141dc37
ZK
918 url_fskip(pb, 20);
919 if (size > 40) {
e40fed0b
ZK
920 st->codec.extradata_size = size - 40;
921 st->codec.extradata = av_mallocz(st->codec.extradata_size);
922 get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
2141dc37 923 }
5e29abf8
RT
924
925 /* Extract palette from extradata if bpp <= 8 */
926 /* This code assumes that extradata contains only palette */
927 /* This is true for all paletted codecs implemented in ffmpeg */
928 if (st->codec.extradata_size && (st->codec.bits_per_sample <= 8)) {
929 st->codec.palctrl = av_mallocz(sizeof(AVPaletteControl));
930#ifdef WORDS_BIGENDIAN
19d053c5
RS
931 for (i = 0; i < FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)/4; i++)
932 st->codec.palctrl->palette[i] = bswap_32(((uint32_t*)st->codec.extradata)[i]);
5e29abf8
RT
933#else
934 memcpy(st->codec.palctrl->palette, st->codec.extradata,
935 FFMIN(st->codec.extradata_size, AVPALETTE_SIZE));
936#endif
937 st->codec.palctrl->palette_changed = 1;
938 }
939
7004ffb3 940 st->codec.codec_tag = tag1;
17a241dd 941 st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
de6d9b64
FB
942 }
943 pos2 = url_ftell(pb);
944 url_fskip(pb, gsize - (pos2 - pos1 + 24));
945 } else if (!memcmp(&g, &data_header, sizeof(GUID))) {
946 break;
947 } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
948 int len1, len2, len3, len4, len5;
949
950 len1 = get_le16(pb);
951 len2 = get_le16(pb);
952 len3 = get_le16(pb);
953 len4 = get_le16(pb);
954 len5 = get_le16(pb);
955 get_str16_nolen(pb, len1, s->title, sizeof(s->title));
956 get_str16_nolen(pb, len2, s->author, sizeof(s->author));
957 get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
958 get_str16_nolen(pb, len4, s->comment, sizeof(s->comment));
2141dc37 959 url_fskip(pb, len5);
d13431cd
KK
960 } else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
961 int desc_count, i;
962
963 desc_count = get_le16(pb);
964 for(i=0;i<desc_count;i++)
965 {
966 int name_len,value_type,value_len,value_num = 0;
967 char *name, *value;
968
969 name_len = get_le16(pb);
970 name = (char *)av_mallocz(name_len);
971 get_str16_nolen(pb, name_len, name, name_len);
972 value_type = get_le16(pb);
973 value_len = get_le16(pb);
974 if ((value_type == 0) || (value_type == 1)) // unicode or byte
975 {
976 value = (char *)av_mallocz(value_len);
977 get_str16_nolen(pb, value_len, value, value_len);
978 if (strcmp(name,"WM/AlbumTitle")==0) { strcpy(s->album, value); }
979 av_free(value);
980 }
981 if ((value_type >= 2) || (value_type <= 5)) // boolean or DWORD or QWORD or WORD
982 {
983 if (value_type==2) value_num = get_le32(pb);
984 if (value_type==3) value_num = get_le32(pb);
985 if (value_type==4) value_num = get_le64(pb);
986 if (value_type==5) value_num = get_le16(pb);
987 if (strcmp(name,"WM/Track")==0) s->track = value_num + 1;
988 if (strcmp(name,"WM/TrackNumber")==0) s->track = value_num;
989 }
990 av_free(name);
991 }
de6d9b64
FB
992#if 0
993 } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
994 int v1, v2;
995 get_guid(pb, &g);
996 v1 = get_le32(pb);
997 v2 = get_le16(pb);
998 } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
999 int len, v1, n, num;
1000 char str[256], *q;
1001 char tag[16];
1002
1003 get_guid(pb, &g);
1004 print_guid(&g);
2a10020b 1005
de6d9b64
FB
1006 n = get_le32(pb);
1007 for(i=0;i<n;i++) {
1008 num = get_le16(pb); /* stream number */
1009 get_str16(pb, str, sizeof(str));
1010 get_str16(pb, str, sizeof(str));
1011 len = get_le16(pb);
1012 q = tag;
1013 while (len > 0) {
1014 v1 = get_byte(pb);
1015 if ((q - tag) < sizeof(tag) - 1)
1016 *q++ = v1;
1017 len--;
1018 }
1019 *q = '\0';
1020 }
1021#endif
1022 } else if (url_feof(pb)) {
1023 goto fail;
1024 } else {
1025 url_fseek(pb, gsize - 24, SEEK_CUR);
1026 }
1027 }
1028 get_guid(pb, &g);
1029 get_le64(pb);
1030 get_byte(pb);
1031 get_byte(pb);
2141dc37
ZK
1032 if (url_feof(pb))
1033 goto fail;
1034 asf->data_offset = url_ftell(pb);
de6d9b64
FB
1035 asf->packet_size_left = 0;
1036
1037 return 0;
1038
1039 fail:
4c3dff6d 1040 for(i=0;i<s->nb_streams;i++) {
de6d9b64 1041 AVStream *st = s->streams[i];
4c3dff6d 1042 if (st) {
2141dc37 1043 av_free(st->priv_data);
4c3dff6d
ZK
1044 av_free(st->codec.extradata);
1045 }
1ea4f593 1046 av_free(st);
de6d9b64 1047 }
de6d9b64
FB
1048 return -1;
1049}
1050
2a10020b
ZK
1051#define DO_2BITS(bits, var, defval) \
1052 switch (bits & 3) \
1053 { \
1054 case 3: var = get_le32(pb); rsize += 4; break; \
1055 case 2: var = get_le16(pb); rsize += 2; break; \
1056 case 1: var = get_byte(pb); rsize++; break; \
1057 default: var = defval; break; \
1058 }
1059
de6d9b64
FB
1060static int asf_get_packet(AVFormatContext *s)
1061{
1062 ASFContext *asf = s->priv_data;
1063 ByteIOContext *pb = &s->pb;
2a10020b 1064 uint32_t packet_length, padsize;
29962fea
MN
1065 int rsize = 9;
1066 int c;
1067
1068 assert((url_ftell(&s->pb) - s->data_offset) % asf->packet_size == 0);
1069
1070 c = get_byte(pb);
1359c2d4 1071 if (c != 0x82) {
5acdd6e6 1072 if (!url_feof(pb))
bc874dae 1073 av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%lld\n", c, url_ftell(pb));
2a10020b
ZK
1074 }
1075 if ((c & 0x0f) == 2) { // always true for now
1359c2d4 1076 if (get_le16(pb) != 0) {
5acdd6e6 1077 if (!url_feof(pb))
bc874dae 1078 av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
2a10020b
ZK
1079 return -EIO;
1080 }
29962fea
MN
1081 rsize+=2;
1082/* }else{
1083 if (!url_feof(pb))
1084 printf("ff asf bad header %x at:%lld\n", c, url_ftell(pb));
1085 return -EIO;*/
de6d9b64 1086 }
2a10020b
ZK
1087
1088 asf->packet_flags = get_byte(pb);
1089 asf->packet_property = get_byte(pb);
1090
1091 DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
1092 DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
1093 DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
1094
1095 asf->packet_timestamp = get_le32(pb);
de6d9b64 1096 get_le16(pb); /* duration */
2141dc37 1097 // rsize has at least 11 bytes which have to be present
2a10020b
ZK
1098
1099 if (asf->packet_flags & 0x01) {
1100 asf->packet_segsizetype = get_byte(pb); rsize++;
1101 asf->packet_segments = asf->packet_segsizetype & 0x3f;
1102 } else {
1103 asf->packet_segments = 1;
1104 asf->packet_segsizetype = 0x80;
1105 }
1106 asf->packet_size_left = packet_length - padsize - rsize;
acbe6cfa
ZK
1107 if (packet_length < asf->hdr.min_pktsize)
1108 padsize += asf->hdr.min_pktsize - packet_length;
2a10020b 1109 asf->packet_padsize = padsize;
de6d9b64 1110#ifdef DEBUG
2a10020b 1111 printf("packet: size=%d padsize=%d left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
de6d9b64 1112#endif
de6d9b64
FB
1113 return 0;
1114}
1115
1116static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
1117{
1118 ASFContext *asf = s->priv_data;
2a10020b 1119 ASFStream *asf_st = 0;
de6d9b64 1120 ByteIOContext *pb = &s->pb;
1359c2d4 1121 //static int pc = 0;
2a10020b
ZK
1122 for (;;) {
1123 int rsize = 0;
2141dc37 1124 if (asf->packet_size_left < FRAME_HEADER_SIZE
1359c2d4 1125 || asf->packet_segments < 1) {
2a10020b 1126 //asf->packet_size_left <= asf->packet_padsize) {
1359c2d4
ZK
1127 int ret = asf->packet_size_left + asf->packet_padsize;
1128 //printf("PacketLeftSize:%d Pad:%d Pos:%Ld\n", asf->packet_size_left, asf->packet_padsize, url_ftell(pb));
1129 /* fail safe */
1130 url_fskip(pb, ret);
82b9e4a2 1131 asf->packet_pos= url_ftell(&s->pb);
2a10020b
ZK
1132 ret = asf_get_packet(s);
1133 //printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++);
5acdd6e6 1134 if (ret < 0 || url_feof(pb))
2a10020b 1135 return -EIO;
2141dc37 1136 asf->packet_time_start = 0;
2a10020b
ZK
1137 continue;
1138 }
2141dc37 1139 if (asf->packet_time_start == 0) {
2a10020b 1140 /* read frame header */
1359c2d4
ZK
1141 int num = get_byte(pb);
1142 asf->packet_segments--;
2a10020b
ZK
1143 rsize++;
1144 asf->packet_key_frame = (num & 0x80) >> 7;
1145 asf->stream_index = asf->asfid2avid[num & 0x7f];
2a10020b
ZK
1146 // sequence should be ignored!
1147 DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
1148 DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
1149 DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
82b9e4a2 1150//printf("key:%d stream:%d seq:%d offset:%d replic_size:%d\n", asf->packet_key_frame, asf->stream_index, asf->packet_seq, //asf->packet_frag_offset, asf->packet_replic_size);
2a10020b 1151 if (asf->packet_replic_size > 1) {
1305a9d5 1152 assert(asf->packet_replic_size >= 8);
2a10020b
ZK
1153 // it should be always at least 8 bytes - FIXME validate
1154 asf->packet_obj_size = get_le32(pb);
1155 asf->packet_frag_timestamp = get_le32(pb); // timestamp
acbe6cfa
ZK
1156 if (asf->packet_replic_size > 8)
1157 url_fskip(pb, asf->packet_replic_size - 8);
2a10020b 1158 rsize += asf->packet_replic_size; // FIXME - check validity
1305a9d5 1159 } else if (asf->packet_replic_size==1){
acbe6cfa 1160 // multipacket - frag_offset is begining timestamp
2a10020b
ZK
1161 asf->packet_time_start = asf->packet_frag_offset;
1162 asf->packet_frag_offset = 0;
1163 asf->packet_frag_timestamp = asf->packet_timestamp;
2141dc37 1164
1305a9d5
MN
1165 asf->packet_time_delta = get_byte(pb);
1166 rsize++;
1167 }else{
1168 assert(asf->packet_replic_size==0);
1169 }
2a10020b
ZK
1170 if (asf->packet_flags & 0x01) {
1171 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
acbe6cfa 1172#undef DO_2BITS
2a10020b
ZK
1173 //printf("Fragsize %d\n", asf->packet_frag_size);
1174 } else {
1175 asf->packet_frag_size = asf->packet_size_left - rsize;
1176 //printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
1177 }
1359c2d4 1178 if (asf->packet_replic_size == 1) {
2141dc37 1179 asf->packet_multi_size = asf->packet_frag_size;
1359c2d4 1180 if (asf->packet_multi_size > asf->packet_size_left) {
2141dc37
ZK
1181 asf->packet_segments = 0;
1182 continue;
1183 }
1184 }
2a10020b
ZK
1185 asf->packet_size_left -= rsize;
1186 //printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
1359c2d4
ZK
1187
1188 if (asf->stream_index < 0) {
1189 asf->packet_time_start = 0;
1190 /* unhandled packet (should not happen) */
1191 url_fskip(pb, asf->packet_frag_size);
1192 asf->packet_size_left -= asf->packet_frag_size;
bc874dae 1193 av_log(s, AV_LOG_ERROR, "ff asf skip %d %d\n", asf->packet_frag_size, num & 0x7f);
1359c2d4
ZK
1194 continue;
1195 }
1196 asf->asf_st = s->streams[asf->stream_index]->priv_data;
2a10020b
ZK
1197 }
1198 asf_st = asf->asf_st;
1199
1200 if ((asf->packet_frag_offset != asf_st->frag_offset
1201 || (asf->packet_frag_offset
1202 && asf->packet_seq != asf_st->seq)) // seq should be ignored
1203 ) {
1204 /* cannot continue current packet: free it */
1205 // FIXME better check if packet was already allocated
bc874dae 1206 av_log(s, AV_LOG_INFO, "ff asf parser skips: %d - %d o:%d - %d %d %d fl:%d\n",
2a10020b 1207 asf_st->pkt.size,
2141dc37 1208 asf->packet_obj_size,
2a10020b
ZK
1209 asf->packet_frag_offset, asf_st->frag_offset,
1210 asf->packet_seq, asf_st->seq, asf->packet_frag_size);
2141dc37 1211 if (asf_st->pkt.size)
2a10020b
ZK
1212 av_free_packet(&asf_st->pkt);
1213 asf_st->frag_offset = 0;
1214 if (asf->packet_frag_offset != 0) {
2a10020b 1215 url_fskip(pb, asf->packet_frag_size);
bc874dae 1216 av_log(s, AV_LOG_INFO, "ff asf parser skiping %db\n", asf->packet_frag_size);
2141dc37 1217 asf->packet_size_left -= asf->packet_frag_size;
2a10020b
ZK
1218 continue;
1219 }
1220 }
2141dc37
ZK
1221 if (asf->packet_replic_size == 1) {
1222 // frag_offset is here used as the begining timestamp
2a10020b 1223 asf->packet_frag_timestamp = asf->packet_time_start;
2141dc37 1224 asf->packet_time_start += asf->packet_time_delta;
2a10020b 1225 asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
2141dc37
ZK
1226 asf->packet_size_left--;
1227 asf->packet_multi_size--;
1228 if (asf->packet_multi_size < asf->packet_obj_size)
1229 {
1230 asf->packet_time_start = 0;
1231 url_fskip(pb, asf->packet_multi_size);
1232 asf->packet_size_left -= asf->packet_multi_size;
1233 continue;
1234 }
1235 asf->packet_multi_size -= asf->packet_obj_size;
1236 //printf("COMPRESS size %d %d %d ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size);
2a10020b 1237 }
2a10020b
ZK
1238 if (asf_st->frag_offset == 0) {
1239 /* new packet */
1240 av_new_packet(&asf_st->pkt, asf->packet_obj_size);
1241 asf_st->seq = asf->packet_seq;
1242 asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll;
1243 asf_st->pkt.stream_index = asf->stream_index;
1305a9d5
MN
1244 asf_st->packet_pos= asf->packet_pos;
1245//printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
82b9e4a2 1246//asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY,
1305a9d5 1247//s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO, asf->packet_obj_size);
38376f00
KK
1248 if (s->streams[asf->stream_index]->codec.codec_type == CODEC_TYPE_AUDIO)
1249 asf->packet_key_frame = 1;
2a10020b
ZK
1250 if (asf->packet_key_frame)
1251 asf_st->pkt.flags |= PKT_FLAG_KEY;
1252 }
1253
1254 /* read data */
1255 //printf("READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
1256 // asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
1257 // asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
2141dc37
ZK
1258 asf->packet_size_left -= asf->packet_frag_size;
1259 if (asf->packet_size_left < 0)
1260 continue;
2a10020b
ZK
1261 get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
1262 asf->packet_frag_size);
1263 asf_st->frag_offset += asf->packet_frag_size;
2a10020b
ZK
1264 /* test if whole packet is read */
1265 if (asf_st->frag_offset == asf_st->pkt.size) {
1266 /* return packet */
1267 if (asf_st->ds_span > 1) {
2141dc37 1268 /* packet descrambling */
2a10020b
ZK
1269 char* newdata = av_malloc(asf_st->pkt.size);
1270 if (newdata) {
1271 int offset = 0;
1272 while (offset < asf_st->pkt.size) {
1273 int off = offset / asf_st->ds_chunk_size;
1274 int row = off / asf_st->ds_span;
1275 int col = off % asf_st->ds_span;
1276 int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
1277 //printf("off:%d row:%d col:%d idx:%d\n", off, row, col, idx);
1278 memcpy(newdata + offset,
1279 asf_st->pkt.data + idx * asf_st->ds_chunk_size,
1280 asf_st->ds_chunk_size);
1281 offset += asf_st->ds_chunk_size;
1282 }
1283 av_free(asf_st->pkt.data);
1284 asf_st->pkt.data = newdata;
1285 }
1286 }
2a10020b
ZK
1287 asf_st->frag_offset = 0;
1288 memcpy(pkt, &asf_st->pkt, sizeof(AVPacket));
1289 //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size);
1290 asf_st->pkt.size = 0;
1291 asf_st->pkt.data = 0;
2a10020b
ZK
1292 break; // packet completed
1293 }
de6d9b64 1294 }
de6d9b64
FB
1295 return 0;
1296}
1297
1298static int asf_read_close(AVFormatContext *s)
1299{
de6d9b64
FB
1300 int i;
1301
1302 for(i=0;i<s->nb_streams;i++) {
4c3dff6d
ZK
1303 AVStream *st = s->streams[i];
1304 av_free(st->priv_data);
1305 av_free(st->codec.extradata);
5e29abf8 1306 av_free(st->codec.palctrl);
de6d9b64 1307 }
de6d9b64
FB
1308 return 0;
1309}
1310
38376f00
KK
1311// Added to support seeking after packets have been read
1312// If information is not reset, read_packet fails due to
1313// leftover information from previous reads
1314static void asf_reset_header(AVFormatContext *s)
1315{
1316 ASFContext *asf = s->priv_data;
82b9e4a2
MN
1317 ASFStream *asf_st;
1318 int i;
38376f00
KK
1319
1320 asf->packet_nb_frames = 0;
1321 asf->packet_timestamp_start = -1;
1322 asf->packet_timestamp_end = -1;
1323 asf->packet_size_left = 0;
1324 asf->packet_segments = 0;
1325 asf->packet_flags = 0;
1326 asf->packet_property = 0;
1327 asf->packet_timestamp = 0;
1328 asf->packet_segsizetype = 0;
1329 asf->packet_segments = 0;
1330 asf->packet_seq = 0;
1331 asf->packet_replic_size = 0;
1332 asf->packet_key_frame = 0;
1333 asf->packet_padsize = 0;
1334 asf->packet_frag_offset = 0;
1335 asf->packet_frag_size = 0;
1336 asf->packet_frag_timestamp = 0;
1337 asf->packet_multi_size = 0;
1338 asf->packet_obj_size = 0;
1339 asf->packet_time_delta = 0;
1340 asf->packet_time_start = 0;
82b9e4a2
MN
1341
1342 for(i=0; i<s->nb_streams; i++){
1343 asf_st= s->streams[i]->priv_data;
1344 av_free_packet(&asf_st->pkt);
1345 asf_st->frag_offset=0;
1346 asf_st->seq=0;
1347 }
1348 asf->asf_st= NULL;
38376f00
KK
1349}
1350
580fb5e7 1351static int64_t asf_read_pts(AVFormatContext *s, int64_t *ppos, int stream_index)
38376f00
KK
1352{
1353 ASFContext *asf = s->priv_data;
1354 AVPacket pkt1, *pkt = &pkt1;
82b9e4a2 1355 ASFStream *asf_st;
580fb5e7 1356 int64_t pts;
82b9e4a2 1357 int64_t pos= *ppos;
3e9245a9
MN
1358 int i;
1359 int64_t start_pos[s->nb_streams];
1360
1361 for(i=0; i<s->nb_streams; i++){
1362 start_pos[i]= pos;
1363 }
580fb5e7 1364
82b9e4a2 1365//printf("asf_read_pts\n");
09646bab 1366 url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET);
82b9e4a2 1367 asf_reset_header(s);
3e9245a9 1368 for(;;){
82b9e4a2 1369 if (av_read_frame(s, pkt) < 0){
bc874dae 1370 av_log(s, AV_LOG_INFO, "seek failed\n");
580fb5e7 1371 return AV_NOPTS_VALUE;
82b9e4a2 1372 }
580fb5e7
MN
1373 pts= pkt->pts;
1374
1375 av_free_packet(pkt);
3e9245a9
MN
1376 if(pkt->flags&PKT_FLAG_KEY){
1377 i= pkt->stream_index;
1378
1379 asf_st= s->streams[i]->priv_data;
1380
1381 assert((asf_st->packet_pos - s->data_offset) % asf->packet_size == 0);
1382 pos= (asf_st->packet_pos - s->data_offset) / asf->packet_size;
09646bab 1383
3e9245a9
MN
1384 av_add_index_entry(s->streams[i], pos, pts, pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
1385 start_pos[i]= pos + 1;
1386
1387 if(pkt->stream_index == stream_index)
1388 break;
1389 }
1390 }
1391
1392 *ppos= pos;
82b9e4a2 1393//printf("found keyframe at %Ld stream %d stamp:%Ld\n", *ppos, stream_index, pts);
580fb5e7
MN
1394
1395 return pts;
38376f00
KK
1396}
1397
afda223c 1398static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts)
2a10020b 1399{
afda223c 1400 ASFContext *asf = s->priv_data;
3e9245a9 1401 AVStream *st;
38376f00 1402 int64_t pos;
82b9e4a2 1403 int64_t pos_min, pos_max, pts_min, pts_max, cur_pts, pos_limit;
0888ac4f 1404 int no_change;
3e9245a9 1405
38376f00 1406 if (stream_index == -1)
580fb5e7
MN
1407 stream_index= av_find_default_stream_index(s);
1408
a602556e 1409 if (asf->packet_size <= 0)
38376f00
KK
1410 return -1;
1411
3e9245a9
MN
1412 pts_max=
1413 pts_min= AV_NOPTS_VALUE;
1414 pos_max= pos_limit= -1; // gcc thinks its uninitalized
1415
1416 st= s->streams[stream_index];
1417 if(st->index_entries){
1418 AVIndexEntry *e;
1419 int index;
1420
1421 index= av_index_search_timestamp(st, pts);
1422 e= &st->index_entries[index];
1423 if(e->timestamp <= pts){
1424 pos_min= e->pos;
1425 pts_min= e->timestamp;
1426#ifdef DEBUG_SEEK
1427 printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n",
1428 pos_min,pts_min / 90000.0);
1429#endif
1430 }else{
1431 assert(index==0);
1432 }
1433 index++;
1434 if(index < st->nb_index_entries){
1435 e= &st->index_entries[index];
1436 assert(e->timestamp >= pts);
1437 pos_max= e->pos;
1438 pts_max= e->timestamp;
1439 pos_limit= pos_max - e->min_distance;
1440#ifdef DEBUG_SEEK
1441 printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n",
1442 pos_max,pts_max / 90000.0);
1443#endif
1444 }
1445 }
1446
1447 if(pts_min == AV_NOPTS_VALUE){
1448 pos_min = 0;
1449 pts_min = asf_read_pts(s, &pos_min, stream_index);
1450 if (pts_min == AV_NOPTS_VALUE) return -1;
1451 }
1452 if(pts_max == AV_NOPTS_VALUE){
1453 pos_max = (url_filesize(url_fileno(&s->pb)) - 1 - s->data_offset) / asf->packet_size; //FIXME wrong
1454 pts_max = s->duration; //FIXME wrong
1455 pos_limit= pos_max;
1456 }
38376f00 1457
0888ac4f 1458 no_change=0;
82b9e4a2
MN
1459 while (pos_min < pos_limit) {
1460 int64_t start_pos;
82b9e4a2
MN
1461 assert(pos_limit <= pos_max);
1462
0888ac4f
MN
1463 if(no_change==0){
1464 int64_t approximate_keyframe_distance= pos_max - pos_limit;
1465 // interpolate position (better than dichotomy)
1466 pos = (int64_t)((double)(pos_max - pos_min) *
1467 (double)(pts - pts_min) /
1468 (double)(pts_max - pts_min)) + pos_min - approximate_keyframe_distance;
1469 }else if(no_change==1){
1470 // bisection, if interpolation failed to change min or max pos last time
1471 pos = (pos_min + pos_limit)>>1;
1472 }else{
1473 // linear search if bisection failed, can only happen if there are very few or no keyframes between min/max
1474 pos=pos_min;
1475 }
82b9e4a2 1476 if(pos <= pos_min)
09646bab 1477 pos= pos_min + 1;
82b9e4a2
MN
1478 else if(pos > pos_limit)
1479 pos= pos_limit;
1480 start_pos= pos;
38376f00
KK
1481
1482 // read the next timestamp
580fb5e7 1483 cur_pts = asf_read_pts(s, &pos, stream_index);
0888ac4f
MN
1484 if(pos == pos_max)
1485 no_change++;
1486 else
1487 no_change=0;
1488
3e9245a9
MN
1489#ifdef DEBUG_SEEK
1490printf("%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld\n", pos_min, pos, pos_max, pts_min, cur_pts, pts_max, pts, pos_limit, start_pos);
1491#endif
0888ac4f
MN
1492 assert (cur_pts != AV_NOPTS_VALUE);
1493 if (pts < cur_pts) {
09646bab 1494 pos_limit = start_pos - 1;
38376f00 1495 pos_max = pos;
82b9e4a2 1496 pts_max = cur_pts;
38376f00 1497 } else {
82b9e4a2
MN
1498 pos_min = pos;
1499 pts_min = cur_pts;
1500 /* check if we are lucky */
1501 if (pts == cur_pts)
1502 break;
38376f00 1503 }
afda223c 1504 }
38376f00 1505 pos = pos_min;
09646bab 1506 url_fseek(&s->pb, pos*asf->packet_size + s->data_offset, SEEK_SET);
38376f00
KK
1507 asf_reset_header(s);
1508 return 0;
2a10020b
ZK
1509}
1510
0570bf06 1511static AVInputFormat asf_iformat = {
c9a65ca8
FB
1512 "asf",
1513 "asf format",
1514 sizeof(ASFContext),
1515 asf_probe,
1516 asf_read_header,
1517 asf_read_packet,
1518 asf_read_close,
2a10020b 1519 asf_read_seek,
c9a65ca8
FB
1520};
1521
764ef400 1522#ifdef CONFIG_ENCODERS
0570bf06 1523static AVOutputFormat asf_oformat = {
de6d9b64
FB
1524 "asf",
1525 "asf format",
c6c11cb6 1526 "video/x-ms-asf",
a56c66a7 1527 "asf,wmv",
c9a65ca8 1528 sizeof(ASFContext),
4606ac8d 1529#ifdef CONFIG_MP3LAME
80783dc2 1530 CODEC_ID_MP3,
4606ac8d 1531#else
de6d9b64 1532 CODEC_ID_MP2,
4606ac8d 1533#endif
d7425f59 1534 CODEC_ID_MSMPEG4V3,
de6d9b64
FB
1535 asf_write_header,
1536 asf_write_packet,
1537 asf_write_trailer,
de6d9b64 1538};
c9a65ca8 1539
0570bf06 1540static AVOutputFormat asf_stream_oformat = {
8b3c13f9
PG
1541 "asf_stream",
1542 "asf format",
c6c11cb6 1543 "video/x-ms-asf",
8b3c13f9
PG
1544 "asf,wmv",
1545 sizeof(ASFContext),
1546#ifdef CONFIG_MP3LAME
80783dc2 1547 CODEC_ID_MP3,
8b3c13f9
PG
1548#else
1549 CODEC_ID_MP2,
1550#endif
d7425f59 1551 CODEC_ID_MSMPEG4V3,
8b3c13f9
PG
1552 asf_write_stream_header,
1553 asf_write_packet,
1554 asf_write_trailer,
1555};
764ef400 1556#endif //CONFIG_ENCODERS
8b3c13f9 1557
c9a65ca8
FB
1558int asf_init(void)
1559{
1560 av_register_input_format(&asf_iformat);
764ef400 1561#ifdef CONFIG_ENCODERS
c9a65ca8 1562 av_register_output_format(&asf_oformat);
8b3c13f9 1563 av_register_output_format(&asf_stream_oformat);
764ef400 1564#endif //CONFIG_ENCODERS
c9a65ca8
FB
1565 return 0;
1566}