]> git.sesse.net Git - ffmpeg/blob - libav/asf.c
7574fff4df4b02c645bafb38843e6633938b13c9
[ffmpeg] / libav / asf.c
1 /*
2  * ASF compatible encoder and decoder.
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 #include "avi.h"
21 #include "tick.h"
22 #include "mpegaudio.h"
23
24 #define PACKET_SIZE 3200
25 #define PACKET_HEADER_SIZE 12
26 #define FRAME_HEADER_SIZE 17
27
28 typedef struct {
29     int num;
30     int seq;
31     Ticker pts_ticker;
32     /* use for reading */
33     AVPacket pkt;
34     int frag_offset;
35     int timestamp;
36     INT64 duration;
37
38     int ds_span;                /* descrambling  */
39     int ds_packet_size;
40     int ds_chunk_size;
41     int ds_data_size;
42     int ds_silence_data;
43
44 } ASFStream;
45
46 typedef struct {
47     UINT32 v1;
48     UINT16 v2;
49     UINT16 v3;
50     UINT8 v4[8];
51 } GUID;
52
53 typedef struct __attribute__((packed)) {
54     GUID guid;                  // generated by client computer
55     uint64_t file_size;         // in bytes
56                                 // invalid if broadcasting
57     uint64_t create_time;       // time of creation, in 100-nanosecond units since 1.1.1601
58                                 // invalid if broadcasting
59     uint64_t packets_count;     // how many packets are there in the file
60                                 // invalid if broadcasting
61     uint64_t play_time;         // play time, in 100-nanosecond units
62                                 // invalid if broadcasting
63     uint64_t send_time;         // time to send file, in 100-nanosecond units
64                                 // invalid if broadcasting (could be ignored)
65     uint32_t preroll;           // timestamp of the first packet, in milliseconds
66                                 // if nonzero - substract from time
67     uint32_t ignore;            // preroll is 64bit - but let's just ignore it
68     uint32_t flags;             // 0x01 - broadcast
69                                 // 0x02 - seekable
70                                 // rest is reserved should be 0
71     uint32_t min_pktsize;       // size of a data packet
72                                 // invalid if broadcasting
73     uint32_t max_pktsize;       // shall be the same as for min_pktsize
74                                 // invalid if broadcasting
75     uint32_t max_bitrate;       // bandwith of stream in bps
76                                 // should be the sum of bitrates of the
77                                 // individual media streams
78 } ASFMainHeader;
79
80
81 typedef struct {
82     int seqno;
83     int packet_size;
84     int is_streamed;
85     int asfid2avid[128];
86     ASFStream streams[128]; // it's max number
87     /* non streamed additonnal info */
88     INT64 nb_packets;
89     INT64 duration; /* in 100ns units */
90     /* packet filling */
91     int packet_size_left;
92     int packet_timestamp_start;
93     int packet_timestamp_end;
94     int packet_nb_frames;
95     UINT8 packet_buf[PACKET_SIZE];
96     ByteIOContext pb;
97     /* only for reading */
98     uint64_t data_offset; /* begining of the first data packet */
99
100     ASFMainHeader hdr;
101
102     int packet_flags;
103     int packet_property;
104     int packet_timestamp;
105     int packet_segsizetype;
106     int packet_segments;
107     int packet_seq;
108     int packet_replic_size;
109     int packet_key_frame;
110     int packet_padsize;
111     int packet_frag_offset;
112     int packet_frag_size;
113     int packet_frag_timestamp;
114     int packet_obj_size;
115     int packet_time_delta;
116     int packet_time_start;
117
118     int stream_index;
119     ASFStream* asf_st; /* currently decoded stream */
120 } ASFContext;
121
122 static const GUID asf_header = {
123     0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
124 };
125
126 static const GUID file_header = {
127     0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
128 };
129
130 static const GUID stream_header = {
131     0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
132 };
133
134 static const GUID audio_stream = {
135     0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
136 };
137
138 static const GUID audio_conceal_none = {
139     // 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
140     // New value lifted from avifile
141     0x20fb5700, 0x5b55, 0x11cf, { 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b },
142 };
143
144 static const GUID video_stream = {
145     0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
146 };
147
148 static const GUID video_conceal_none = {
149     0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
150 };
151
152
153 static const GUID comment_header = {
154     0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
155 };
156
157 static const GUID codec_comment_header = {
158     0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
159 };
160 static const GUID codec_comment1_header = {
161     0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
162 };
163
164 static const GUID data_header = {
165     0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
166 };
167
168 static const GUID index_guid = {
169     0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },
170 };
171
172 static const GUID head1_guid = {
173     0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
174 };
175
176 static const GUID head2_guid = {
177     0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },
178 };
179
180 /* I am not a number !!! This GUID is the one found on the PC used to
181    generate the stream */
182 static const GUID my_guid = {
183     0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 },
184 };
185
186 CodecTag codec_asf_bmp_tags[] = {
187     { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
188     { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
189     { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
190     { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
191     { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') },
192     { CODEC_ID_MPEG4, MKTAG('d', 'i', 'v', 'x') },
193     { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') },
194     { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
195     { CODEC_ID_MPEG4, MKTAG('x', 'v', 'i', 'd') },
196     { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 's') },
197     { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
198     { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
199     { CODEC_ID_MPEG4, MKTAG('m', '4', 's', '2') },
200     { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
201     { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, /* default signature when using MSMPEG4 */
202     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') },
203     { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') },
204     { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') },
205     { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') },
206     { 0, 0 },
207 };
208
209
210
211 static void put_guid(ByteIOContext *s, const GUID *g)
212 {
213     int i;
214
215     put_le32(s, g->v1);
216     put_le16(s, g->v2);
217     put_le16(s, g->v3);
218     for(i=0;i<8;i++)
219         put_byte(s, g->v4[i]);
220 }
221
222 static void put_str16(ByteIOContext *s, const char *tag)
223 {
224     int c;
225
226     put_le16(s,strlen(tag) + 1);
227     for(;;) {
228         c = (UINT8)*tag++;
229         put_le16(s, c);
230         if (c == '\0')
231             break;
232     }
233 }
234
235 static void put_str16_nolen(ByteIOContext *s, const char *tag)
236 {
237     int c;
238
239     for(;;) {
240         c = (UINT8)*tag++;
241         put_le16(s, c);
242         if (c == '\0')
243             break;
244     }
245 }
246
247 static INT64 put_header(ByteIOContext *pb, const GUID *g)
248 {
249     INT64 pos;
250
251     pos = url_ftell(pb);
252     put_guid(pb, g);
253     put_le64(pb, 24);
254     return pos;
255 }
256
257 /* update header size */
258 static void end_header(ByteIOContext *pb, INT64 pos)
259 {
260     INT64 pos1;
261
262     pos1 = url_ftell(pb);
263     url_fseek(pb, pos + 16, SEEK_SET);
264     put_le64(pb, pos1 - pos);
265     url_fseek(pb, pos1, SEEK_SET);
266 }
267
268 /* write an asf chunk (only used in streaming case) */
269 static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags)
270 {
271     ASFContext *asf = s->priv_data;
272     ByteIOContext *pb = &s->pb;
273     int length;
274
275     length = payload_length + 8;
276     put_le16(pb, type);
277     put_le16(pb, length);
278     put_le32(pb, asf->seqno);
279     put_le16(pb, flags); /* unknown bytes */
280     put_le16(pb, length);
281     asf->seqno++;
282 }
283
284 /* convert from unix to windows time */
285 static INT64 unix_to_file_time(int ti)
286 {
287     INT64 t;
288
289     t = ti * INT64_C(10000000);
290     t += INT64_C(116444736000000000);
291     return t;
292 }
293
294 /* write the header (used two times if non streamed) */
295 static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chunk_size)
296 {
297     ASFContext *asf = s->priv_data;
298     ByteIOContext *pb = &s->pb;
299     int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
300     int has_title;
301     AVCodecContext *enc;
302     INT64 header_offset, cur_pos, hpos;
303     int bit_rate;
304
305     has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]);
306
307     bit_rate = 0;
308     for(n=0;n<s->nb_streams;n++) {
309         enc = &s->streams[n]->codec;
310
311         bit_rate += enc->bit_rate;
312     }
313
314     if (asf->is_streamed) {
315         put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
316     }
317
318     put_guid(pb, &asf_header);
319     put_le64(pb, -1); /* header length, will be patched after */
320     put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */
321     put_byte(pb, 1); /* ??? */
322     put_byte(pb, 2); /* ??? */
323
324     /* file header */
325     header_offset = url_ftell(pb);
326     hpos = put_header(pb, &file_header);
327     put_guid(pb, &my_guid);
328     put_le64(pb, file_size);
329     file_time = 0;
330     put_le64(pb, unix_to_file_time(file_time));
331     put_le64(pb, asf->nb_packets); /* number of packets */
332     put_le64(pb, asf->duration); /* end time stamp (in 100ns units) */
333     put_le64(pb, asf->duration); /* duration (in 100ns units) */
334     put_le32(pb, 0); /* start time stamp */
335     put_le32(pb, 0); /* ??? */
336     put_le32(pb, asf->is_streamed ? 1 : 0); /* ??? */
337     put_le32(pb, asf->packet_size); /* packet size */
338     put_le32(pb, asf->packet_size); /* packet size */
339     put_le32(pb, bit_rate); /* Nominal data rate in bps */
340     end_header(pb, hpos);
341
342     /* unknown headers */
343     hpos = put_header(pb, &head1_guid);
344     put_guid(pb, &head2_guid);
345     put_le32(pb, 6);
346     put_le16(pb, 0);
347     end_header(pb, hpos);
348
349     /* title and other infos */
350     if (has_title) {
351         hpos = put_header(pb, &comment_header);
352         put_le16(pb, 2 * (strlen(s->title) + 1));
353         put_le16(pb, 2 * (strlen(s->author) + 1));
354         put_le16(pb, 2 * (strlen(s->copyright) + 1));
355         put_le16(pb, 2 * (strlen(s->comment) + 1));
356         put_le16(pb, 0);
357         put_str16_nolen(pb, s->title);
358         put_str16_nolen(pb, s->author);
359         put_str16_nolen(pb, s->copyright);
360         put_str16_nolen(pb, s->comment);
361         end_header(pb, hpos);
362     }
363
364     /* stream headers */
365     for(n=0;n<s->nb_streams;n++) {
366         INT64 es_pos;
367         ASFStream *stream = &asf->streams[n];
368
369         enc = &s->streams[n]->codec;
370         asf->streams[n].num = n + 1;
371         asf->streams[n].seq = 0;
372
373         switch(enc->codec_type) {
374         case CODEC_TYPE_AUDIO:
375             wav_extra_size = 0;
376             extra_size = 18 + wav_extra_size;
377             extra_size2 = 0;
378             /* Init the ticker */
379             ticker_init(&stream->pts_ticker,
380                         enc->sample_rate,
381                         1000 * enc->frame_size);
382             break;
383         default:
384         case CODEC_TYPE_VIDEO:
385             wav_extra_size = 0;
386             extra_size = 0x33;
387             extra_size2 = 0;
388             /* Init the ticker */
389             ticker_init(&stream->pts_ticker,
390                         enc->frame_rate,
391                         1000 * FRAME_RATE_BASE);
392             break;
393         }
394
395         hpos = put_header(pb, &stream_header);
396         if (enc->codec_type == CODEC_TYPE_AUDIO) {
397             put_guid(pb, &audio_stream);
398             put_guid(pb, &audio_conceal_none);
399         } else {
400             put_guid(pb, &video_stream);
401             put_guid(pb, &video_conceal_none);
402         }
403         put_le64(pb, 0); /* ??? */
404         es_pos = url_ftell(pb);
405         put_le32(pb, extra_size); /* wav header len */
406         put_le32(pb, extra_size2); /* additional data len */
407         put_le16(pb, n + 1); /* stream number */
408         put_le32(pb, 0); /* ??? */
409
410         if (enc->codec_type == CODEC_TYPE_AUDIO) {
411             /* WAVEFORMATEX header */
412             int wavsize = put_wav_header(pb, enc);
413
414             if (wavsize < 0)
415                 return -1;
416             if (wavsize != extra_size) {
417                 cur_pos = url_ftell(pb);
418                 url_fseek(pb, es_pos, SEEK_SET);
419                 put_le32(pb, wavsize); /* wav header len */
420                 url_fseek(pb, cur_pos, SEEK_SET);
421             }
422         } else {
423             put_le32(pb, enc->width);
424             put_le32(pb, enc->height);
425             put_byte(pb, 2); /* ??? */
426             put_le16(pb, 40); /* size */
427
428             /* BITMAPINFOHEADER header */
429             put_bmp_header(pb, enc, codec_asf_bmp_tags);
430         }
431         end_header(pb, hpos);
432     }
433
434     /* media comments */
435
436     hpos = put_header(pb, &codec_comment_header);
437     put_guid(pb, &codec_comment1_header);
438     put_le32(pb, s->nb_streams);
439     for(n=0;n<s->nb_streams;n++) {
440         AVCodec *p;
441
442         enc = &s->streams[n]->codec;
443         p = avcodec_find_encoder(enc->codec_id);
444
445         put_le16(pb, asf->streams[n].num);
446         put_str16(pb, p ? p->name : enc->codec_name);
447         put_le16(pb, 0); /* no parameters */
448         /* id */
449         if (enc->codec_type == CODEC_TYPE_AUDIO) {
450             put_le16(pb, 2);
451             put_le16(pb, codec_get_tag(codec_wav_tags, enc->codec_id));
452         } else {
453             put_le16(pb, 4);
454             put_le32(pb, codec_get_tag(codec_asf_bmp_tags, enc->codec_id));
455         }
456     }
457     end_header(pb, hpos);
458
459     /* patch the header size fields */
460
461     cur_pos = url_ftell(pb);
462     header_size = cur_pos - header_offset;
463     if (asf->is_streamed) {
464         header_size += 8 + 30 + 50;
465
466         url_fseek(pb, header_offset - 10 - 30, SEEK_SET);
467         put_le16(pb, header_size);
468         url_fseek(pb, header_offset - 2 - 30, SEEK_SET);
469         put_le16(pb, header_size);
470
471         header_size -= 8 + 30 + 50;
472     }
473     header_size += 24 + 6;
474     url_fseek(pb, header_offset - 14, SEEK_SET);
475     put_le64(pb, header_size);
476     url_fseek(pb, cur_pos, SEEK_SET);
477
478     /* movie chunk, followed by packets of packet_size */
479     asf->data_offset = cur_pos;
480     put_guid(pb, &data_header);
481     put_le64(pb, data_chunk_size);
482     put_guid(pb, &my_guid);
483     put_le64(pb, asf->nb_packets); /* nb packets */
484     put_byte(pb, 1); /* ??? */
485     put_byte(pb, 1); /* ??? */
486     return 0;
487 }
488
489 static int asf_write_header(AVFormatContext *s)
490 {
491     ASFContext *asf = s->priv_data;
492
493     asf->packet_size = PACKET_SIZE;
494     asf->nb_packets = 0;
495
496     if (asf_write_header1(s, 0, 50) < 0) {
497         //av_free(asf);
498         return -1;
499     }
500
501     put_flush_packet(&s->pb);
502
503     asf->packet_nb_frames = 0;
504     asf->packet_timestamp_start = -1;
505     asf->packet_timestamp_end = -1;
506     asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
507     init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
508                   NULL, NULL, NULL, NULL);
509
510     return 0;
511 }
512
513 static int asf_write_stream_header(AVFormatContext *s)
514 {
515     ASFContext *asf = s->priv_data;
516
517     asf->is_streamed = 1;
518
519     return asf_write_header(s);
520 }
521
522 /* write a fixed size packet */
523 static int put_packet(AVFormatContext *s,
524                        unsigned int timestamp, unsigned int duration,
525                        int nb_frames, int padsize)
526 {
527     ASFContext *asf = s->priv_data;
528     ByteIOContext *pb = &s->pb;
529     int flags;
530
531     if (asf->is_streamed) {
532         put_chunk(s, 0x4424, asf->packet_size, 0);
533     }
534
535     put_byte(pb, 0x82);
536     put_le16(pb, 0);
537
538     flags = 0x01; /* nb segments present */
539     if (padsize > 0) {
540         if (padsize < 256)
541             flags |= 0x08;
542         else
543             flags |= 0x10;
544     }
545     put_byte(pb, flags); /* flags */
546     put_byte(pb, 0x5d);
547     if (flags & 0x10)
548         put_le16(pb, padsize - 2);
549     if (flags & 0x08)
550         put_byte(pb, padsize - 1);
551     put_le32(pb, timestamp);
552     put_le16(pb, duration);
553     put_byte(pb, nb_frames | 0x80);
554
555     return PACKET_HEADER_SIZE + ((flags & 0x18) >> 3);
556 }
557
558 static void flush_packet(AVFormatContext *s)
559 {
560     ASFContext *asf = s->priv_data;
561     int hdr_size, ptr;
562
563     hdr_size = put_packet(s, asf->packet_timestamp_start,
564                asf->packet_timestamp_end - asf->packet_timestamp_start,
565                asf->packet_nb_frames, asf->packet_size_left);
566
567     /* Clear out the padding bytes */
568     ptr = asf->packet_size - hdr_size - asf->packet_size_left;
569     memset(asf->packet_buf + ptr, 0, asf->packet_size_left);
570
571     put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size);
572
573     put_flush_packet(&s->pb);
574     asf->nb_packets++;
575     asf->packet_nb_frames = 0;
576     asf->packet_timestamp_start = -1;
577     asf->packet_timestamp_end = -1;
578     asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
579     init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
580                   NULL, NULL, NULL, NULL);
581 }
582
583 static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp,
584                              int payload_size, int frag_offset, int frag_len)
585 {
586     ASFContext *asf = s->priv_data;
587     ByteIOContext *pb = &asf->pb;
588     int val;
589
590     val = stream->num;
591     if (s->streams[val - 1]->codec.key_frame /* && frag_offset == 0 */)
592         val |= 0x80;
593     put_byte(pb, val);
594     put_byte(pb, stream->seq);
595     put_le32(pb, frag_offset); /* fragment offset */
596     put_byte(pb, 0x08); /* flags */
597     put_le32(pb, payload_size);
598     put_le32(pb, timestamp);
599     put_le16(pb, frag_len);
600 }
601
602
603 /* Output a frame. We suppose that payload_size <= PACKET_SIZE.
604
605    It is there that you understand that the ASF format is really
606    crap. They have misread the MPEG Systems spec !
607  */
608 static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp,
609                       UINT8 *buf, int payload_size)
610 {
611     ASFContext *asf = s->priv_data;
612     int frag_pos, frag_len, frag_len1;
613
614     frag_pos = 0;
615     while (frag_pos < payload_size) {
616         frag_len = payload_size - frag_pos;
617         frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE;
618         if (frag_len1 > 0) {
619             if (frag_len > frag_len1)
620                 frag_len = frag_len1;
621             put_frame_header(s, stream, timestamp, payload_size, frag_pos, frag_len);
622             put_buffer(&asf->pb, buf, frag_len);
623             asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE);
624             asf->packet_timestamp_end = timestamp;
625             if (asf->packet_timestamp_start == -1)
626                 asf->packet_timestamp_start = timestamp;
627             asf->packet_nb_frames++;
628         } else {
629             frag_len = 0;
630         }
631         frag_pos += frag_len;
632         buf += frag_len;
633         /* output the frame if filled */
634         if (asf->packet_size_left <= FRAME_HEADER_SIZE)
635             flush_packet(s);
636     }
637     stream->seq++;
638 }
639
640
641 static int asf_write_packet(AVFormatContext *s, int stream_index,
642                             UINT8 *buf, int size, int force_pts)
643 {
644     ASFContext *asf = s->priv_data;
645     ASFStream *stream;
646     int timestamp;
647     INT64 duration;
648     AVCodecContext *codec;
649
650     stream = &asf->streams[stream_index];
651     codec = &s->streams[stream_index]->codec;
652     stream = &asf->streams[stream_index];
653
654     if (codec->codec_type == CODEC_TYPE_AUDIO) {
655         timestamp = (int)ticker_abs(&stream->pts_ticker, codec->frame_number);
656         duration = (codec->frame_number * codec->frame_size * INT64_C(10000000)) /
657             codec->sample_rate;
658     } else {
659         timestamp = (int)ticker_abs(&stream->pts_ticker, codec->frame_number);
660         duration = codec->frame_number *
661             ((INT64_C(10000000) * FRAME_RATE_BASE) / codec->frame_rate);
662     }
663     if (duration > asf->duration)
664         asf->duration = duration;
665
666     put_frame(s, stream, timestamp, buf, size);
667     return 0;
668 }
669
670 static int asf_write_trailer(AVFormatContext *s)
671 {
672     ASFContext *asf = s->priv_data;
673     INT64 file_size;
674
675     /* flush the current packet */
676     if (asf->pb.buf_ptr > asf->pb.buffer)
677         flush_packet(s);
678
679     if (asf->is_streamed) {
680         put_chunk(s, 0x4524, 0, 0); /* end of stream */
681     } else {
682         /* rewrite an updated header */
683         file_size = url_ftell(&s->pb);
684         url_fseek(&s->pb, 0, SEEK_SET);
685         asf_write_header1(s, file_size, file_size - asf->data_offset);
686     }
687
688     put_flush_packet(&s->pb);
689     return 0;
690 }
691
692 /**********************************/
693 /* decoding */
694
695 //#define DEBUG
696
697 #ifdef DEBUG
698 static void print_guid(const GUID *g)
699 {
700     int i;
701     printf("0x%08x, 0x%04x, 0x%04x, {", g->v1, g->v2, g->v3);
702     for(i=0;i<8;i++)
703         printf(" 0x%02x,", g->v4[i]);
704     printf("}\n");
705 }
706 #endif
707
708 static void get_guid(ByteIOContext *s, GUID *g)
709 {
710     int i;
711
712     g->v1 = get_le32(s);
713     g->v2 = get_le16(s);
714     g->v3 = get_le16(s);
715     for(i=0;i<8;i++)
716         g->v4[i] = get_byte(s);
717 }
718
719 #if 0
720 static void get_str16(ByteIOContext *pb, char *buf, int buf_size)
721 {
722     int len, c;
723     char *q;
724
725     len = get_le16(pb);
726     q = buf;
727     while (len > 0) {
728         c = get_le16(pb);
729         if ((q - buf) < buf_size - 1)
730             *q++ = c;
731         len--;
732     }
733     *q = '\0';
734 }
735 #endif
736
737 static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
738 {
739     int c;
740     char *q;
741
742     q = buf;
743     while (len > 0) {
744         c = get_le16(pb);
745         if ((q - buf) < buf_size - 1)
746             *q++ = c;
747         len-=2;
748     }
749     *q = '\0';
750 }
751
752 static int asf_probe(AVProbeData *pd)
753 {
754     GUID g;
755     const unsigned char *p;
756     int i;
757
758     /* check file header */
759     if (pd->buf_size <= 32)
760         return 0;
761     p = pd->buf;
762     g.v1 = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
763     p += 4;
764     g.v2 = p[0] | (p[1] << 8);
765     p += 2;
766     g.v3 = p[0] | (p[1] << 8);
767     p += 2;
768     for(i=0;i<8;i++)
769         g.v4[i] = *p++;
770
771     if (!memcmp(&g, &asf_header, sizeof(GUID)))
772         return AVPROBE_SCORE_MAX;
773     else
774         return 0;
775 }
776
777 static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
778 {
779     ASFContext *asf = s->priv_data;
780     GUID g;
781     ByteIOContext *pb = &s->pb;
782     AVStream *st;
783     ASFStream *asf_st;
784     int size, i, bps;
785     INT64 gsize;
786
787     get_guid(pb, &g);
788     if (memcmp(&g, &asf_header, sizeof(GUID)))
789         goto fail;
790     get_le64(pb);
791     get_le32(pb);
792     get_byte(pb);
793     get_byte(pb);
794
795     for(;;) {
796         get_guid(pb, &g);
797         gsize = get_le64(pb);
798 #ifdef DEBUG
799         printf("%08Lx: ", url_ftell(pb) - 24);
800         print_guid(&g);
801         printf("  size=0x%Lx\n", gsize);
802 #endif
803         if (gsize < 24)
804             goto fail;
805         if (!memcmp(&g, &file_header, sizeof(GUID))) {
806             get_guid(pb, &asf->hdr.guid);
807             asf->hdr.file_size          = get_le64(pb);
808             asf->hdr.create_time        = get_le64(pb);
809             asf->hdr.packets_count      = get_le64(pb);
810             asf->hdr.play_time          = get_le64(pb);
811             asf->hdr.send_time          = get_le64(pb);
812             asf->hdr.preroll            = get_le32(pb);
813             asf->hdr.ignore             = get_le32(pb);
814             asf->hdr.flags              = get_le32(pb);
815             asf->hdr.min_pktsize        = get_le32(pb);
816             asf->hdr.max_pktsize        = get_le32(pb);
817             asf->hdr.max_bitrate        = get_le32(pb);
818             asf->packet_size = asf->hdr.max_pktsize;
819         } else if (!memcmp(&g, &stream_header, sizeof(GUID))) {
820             int type, id, total_size;
821             unsigned int tag1;
822             INT64 pos1, pos2;
823
824             pos1 = url_ftell(pb);
825
826             st = av_mallocz(sizeof(AVStream));
827             if (!st)
828                 goto fail;
829             s->streams[s->nb_streams] = st;
830             asf_st = av_mallocz(sizeof(ASFStream));
831             if (!asf_st)
832                 goto fail;
833             st->priv_data = asf_st;
834             st->time_length = (asf->hdr.send_time - asf->hdr.preroll) / 10000;
835             get_guid(pb, &g);
836             if (!memcmp(&g, &audio_stream, sizeof(GUID))) {
837                 type = CODEC_TYPE_AUDIO;
838             } else if (!memcmp(&g, &video_stream, sizeof(GUID))) {
839                 type = CODEC_TYPE_VIDEO;
840             } else {
841                 goto fail;
842             }
843             get_guid(pb, &g);
844             total_size = get_le64(pb);
845             get_le32(pb);
846             get_le32(pb);
847             st->id = get_le16(pb) & 0x7f; /* stream id */
848             // mapping of asf ID to AV stream ID;
849             asf->asfid2avid[st->id] = s->nb_streams++;
850
851             get_le32(pb);
852             st->codec.codec_type = type;
853             if (type == CODEC_TYPE_AUDIO) {
854                 id = get_le16(pb);
855                 st->codec.codec_tag = id;
856                 st->codec.channels = get_le16(pb);
857                 st->codec.sample_rate = get_le32(pb);
858                 st->codec.bit_rate = get_le32(pb) * 8;
859                 st->codec.block_align = get_le16(pb); /* block align */
860                 bps = get_le16(pb); /* bits per sample */
861                 st->codec.codec_id = wav_codec_get_id(id, bps);
862                 size = get_le16(pb);
863                 st->extra_data = av_mallocz(size);
864                 get_buffer(pb, st->extra_data, size);
865                 st->extra_data_size =  size;
866                 /* We have to init the frame size at some point .... */
867                 pos2 = url_ftell(pb);
868                 if (gsize > (pos2 + 8 - pos1 + 24))
869                 {
870                     asf_st->ds_span = get_byte(pb);
871                     asf_st->ds_packet_size = get_le16(pb);
872                     asf_st->ds_chunk_size = get_le16(pb);
873                     asf_st->ds_data_size = get_le16(pb);
874                     asf_st->ds_silence_data = get_byte(pb);
875                 }
876                 //printf("Descrambling: ps:%d cs:%d ds:%d s:%d  sd:%d\n",
877                 //       asf_st->ds_packet_size, asf_st->ds_chunk_size,
878                 //       asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
879                 if (asf_st->ds_span > 1)
880                 {
881                     if (!asf_st->ds_chunk_size
882                         || (asf_st->ds_packet_size/asf_st->ds_chunk_size <= 1))
883                         asf_st->ds_span = 0; // disable descrambling
884                 }
885                 switch (st->codec.codec_id) {
886                 case CODEC_ID_MP3LAME:
887                     st->codec.frame_size = MPA_FRAME_SIZE;
888                     break;
889                 case CODEC_ID_PCM_S16LE:
890                 case CODEC_ID_PCM_S16BE:
891                 case CODEC_ID_PCM_U16LE:
892                 case CODEC_ID_PCM_U16BE:
893                 case CODEC_ID_PCM_S8:
894                 case CODEC_ID_PCM_U8:
895                 case CODEC_ID_PCM_ALAW:
896                 case CODEC_ID_PCM_MULAW:
897                     st->codec.frame_size = 1;
898                     break;
899                 default:
900                     /* This is probably wrong, but it prevents a crash later */
901                     st->codec.frame_size = 1;
902                     break;
903                 }
904             } else {
905                 get_le32(pb);
906                 get_le32(pb);
907                 get_byte(pb);
908                 size = get_le16(pb); /* size */
909                 get_le32(pb); /* size */
910                 st->codec.width = get_le32(pb);
911                 st->codec.height = get_le32(pb);
912                 /* not available for asf */
913                 st->codec.frame_rate = 25 * FRAME_RATE_BASE; /* XXX: find it */
914                 get_le16(pb); /* panes */
915                 get_le16(pb); /* depth */
916                 tag1 = get_le32(pb);
917                 st->codec.codec_tag = tag1;
918                 st->codec.codec_id = codec_get_id(codec_asf_bmp_tags, tag1);
919                 url_fskip(pb, size - 5 * 4);
920             }
921             pos2 = url_ftell(pb);
922             url_fskip(pb, gsize - (pos2 - pos1 + 24));
923         } else if (!memcmp(&g, &data_header, sizeof(GUID))) {
924             break;
925         } else if (!memcmp(&g, &comment_header, sizeof(GUID))) {
926             int len1, len2, len3, len4, len5;
927
928             len1 = get_le16(pb);
929             len2 = get_le16(pb);
930             len3 = get_le16(pb);
931             len4 = get_le16(pb);
932             len5 = get_le16(pb);
933             get_str16_nolen(pb, len1, s->title, sizeof(s->title));
934             get_str16_nolen(pb, len2, s->author, sizeof(s->author));
935             get_str16_nolen(pb, len3, s->copyright, sizeof(s->copyright));
936             get_str16_nolen(pb, len4, s->comment, sizeof(s->comment));
937             url_fskip(pb, len5);
938 #if 0
939         } else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
940             int v1, v2;
941             get_guid(pb, &g);
942             v1 = get_le32(pb);
943             v2 = get_le16(pb);
944         } else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
945             int len, v1, n, num;
946             char str[256], *q;
947             char tag[16];
948
949             get_guid(pb, &g);
950             print_guid(&g);
951
952             n = get_le32(pb);
953             for(i=0;i<n;i++) {
954                 num = get_le16(pb); /* stream number */
955                 get_str16(pb, str, sizeof(str));
956                 get_str16(pb, str, sizeof(str));
957                 len = get_le16(pb);
958                 q = tag;
959                 while (len > 0) {
960                     v1 = get_byte(pb);
961                     if ((q - tag) < sizeof(tag) - 1)
962                         *q++ = v1;
963                     len--;
964                 }
965                 *q = '\0';
966             }
967 #endif
968         } else if (url_feof(pb)) {
969             goto fail;
970         } else {
971             url_fseek(pb, gsize - 24, SEEK_CUR);
972         }
973     }
974     get_guid(pb, &g);
975     get_le64(pb);
976     get_byte(pb);
977     get_byte(pb);
978
979     asf->packet_size_left = 0;
980
981     return 0;
982
983  fail:
984     for(i=0;i<s->nb_streams;i++) {
985         AVStream *st = s->streams[i];
986         if (st)
987             av_free(st->priv_data);
988         av_free(st);
989     }
990     //av_free(asf);
991     return -1;
992 }
993
994 #define DO_2BITS(bits, var, defval) \
995     switch (bits & 3) \
996     { \
997     case 3: var = get_le32(pb); rsize += 4; break; \
998     case 2: var = get_le16(pb); rsize += 2; break; \
999     case 1: var = get_byte(pb); rsize++; break; \
1000     default: var = defval; break; \
1001     }
1002
1003 static int asf_get_packet(AVFormatContext *s)
1004 {
1005     ASFContext *asf = s->priv_data;
1006     ByteIOContext *pb = &s->pb;
1007     uint32_t packet_length, padsize;
1008     int rsize = 11;
1009     int c = get_byte(pb);
1010     if (c != 0x82)
1011     {
1012         printf("BAD HRD %x  at:%Ld\n", c, url_ftell(pb));
1013         return -EIO;
1014     }
1015     if ((c & 0x0f) == 2) { // always true for now
1016         if (get_le16(pb) != 0)
1017         {
1018             printf("BAD NO ZERO\n");
1019             return -EIO;
1020         }
1021     }
1022
1023     asf->packet_flags = get_byte(pb);
1024     asf->packet_property = get_byte(pb);
1025
1026     DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
1027     DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
1028     DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
1029
1030     asf->packet_timestamp = get_le32(pb);
1031     get_le16(pb); /* duration */
1032     // rsize has 11 bytes static bytes which have to be present
1033
1034     if (asf->packet_flags & 0x01) {
1035         asf->packet_segsizetype = get_byte(pb); rsize++;
1036         asf->packet_segments = asf->packet_segsizetype & 0x3f;
1037     } else {
1038         asf->packet_segments = 1;
1039         asf->packet_segsizetype = 0x80;
1040     }
1041     asf->packet_size_left = packet_length - padsize - rsize;
1042     asf->packet_padsize = padsize;
1043 #ifdef DEBUG
1044     printf("packet: size=%d padsize=%d  left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
1045 #endif
1046     return 0;
1047 }
1048
1049 static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
1050 {
1051     ASFContext *asf = s->priv_data;
1052     ASFStream *asf_st = 0;
1053     ByteIOContext *pb = &s->pb;
1054     static int pc = 0;
1055     for (;;) {
1056         int rsize = 0;
1057         if (asf->packet_size_left < FRAME_HEADER_SIZE) {
1058             //asf->packet_size_left <= asf->packet_padsize) {
1059             int ret;
1060             //printf("PACKETLEFTSIZE  %d\n", asf->packet_size_left);
1061             /* fail safe */
1062             if (asf->packet_size_left)
1063                 url_fskip(pb, asf->packet_size_left);
1064             if (asf->packet_padsize)
1065                 url_fskip(pb, asf->packet_padsize);
1066             ret = asf_get_packet(s);
1067             //printf("READ ASF PACKET  %d   r:%d   c:%d\n", ret, asf->packet_size_left, pc++);
1068             if (ret < 0)
1069                 return -EIO;
1070             continue;
1071         }
1072         if (1) { // FIXME - handle replicated multi packets
1073             /* read frame header */
1074             int num = get_byte(pb);
1075             rsize++;
1076             asf->packet_key_frame = (num & 0x80) >> 7;
1077             asf->stream_index = asf->asfid2avid[num & 0x7f];
1078             if (asf->stream_index < 0)
1079             {
1080                 /* unhandled packet (should not happen) */
1081                 url_fskip(pb, asf->packet_frag_size);
1082                 asf->packet_size_left -= asf->packet_frag_size;
1083                 //printf("#####xxxxxx###### skip %d\n", asf->packet_frag_size);
1084                 continue;
1085                 // FIXME
1086             }
1087             asf->asf_st = s->streams[asf->stream_index]->priv_data;
1088             //printf("ASFST  %p    %d <> %d\n", asf->asf_st, asf->stream_index, num & 0x7f);
1089             // sequence should be ignored!
1090             DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
1091             DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
1092             DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
1093
1094             if (asf->packet_replic_size > 1) {
1095                 // it should be always at least 8 bytes - FIXME validate
1096                 asf->packet_obj_size = get_le32(pb);
1097                 asf->packet_frag_timestamp = get_le32(pb); // timestamp
1098                 rsize += asf->packet_replic_size; // FIXME - check validity
1099             } else {
1100                 // multipacket - frag_offset is beginig timestamp
1101                 asf->packet_time_start = asf->packet_frag_offset;
1102                 asf->packet_frag_offset = 0;
1103                 asf->packet_frag_timestamp = asf->packet_timestamp;
1104                 if (asf->packet_replic_size == 1) {
1105                     asf->packet_time_delta = get_byte(pb);
1106                     rsize++;
1107                 }
1108             }
1109
1110             if (asf->packet_flags & 0x01) {
1111                 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
1112                 //printf("Fragsize %d\n", asf->packet_frag_size);
1113             } else {
1114                 asf->packet_frag_size = asf->packet_size_left - rsize;
1115                 //printf("Using rest  %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
1116             }
1117 #undef DO_2BITS
1118             asf->packet_size_left -= rsize;
1119             //printf("___objsize____  %d   %d    rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
1120         }
1121         asf_st = asf->asf_st;
1122
1123         if ((asf->packet_frag_offset != asf_st->frag_offset
1124              || (asf->packet_frag_offset
1125                  && asf->packet_seq != asf_st->seq)) // seq should be ignored
1126            ) {
1127             /* cannot continue current packet: free it */
1128             // FIXME better check if packet was already allocated
1129             printf("asf parser skips: %d - %d     o:%d - %d    %d %d   fl:%d\n",
1130                    asf_st->pkt.size,
1131                    asf->packet_obj_size,
1132                    asf->packet_frag_offset, asf_st->frag_offset,
1133                    asf->packet_seq, asf_st->seq, asf->packet_frag_size);
1134             if (asf_st->pkt.size)
1135                 av_free_packet(&asf_st->pkt);
1136             asf_st->frag_offset = 0;
1137             if (asf->packet_frag_offset != 0) {
1138                 /* cannot create new packet */
1139                 url_fskip(pb, asf->packet_frag_size);
1140                 printf("asf parser skiping %db\n", asf->packet_frag_size);
1141                 asf->packet_size_left -= asf->packet_frag_size;
1142                 continue;
1143             }
1144         }
1145         if (asf->packet_replic_size == 1)
1146         {
1147             // frag_size is now begining timestamp
1148             asf->packet_frag_timestamp = asf->packet_time_start;
1149             asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
1150             asf->packet_size_left--;
1151             //printf("COMPRESS size  %d  %d\n", asf->packet_obj_size, asf->packet_frag_timestamp);
1152         }
1153
1154         //printf("PACKET OFFSET   %d\n", asf_st->frag_offset);
1155         if (asf_st->frag_offset == 0) {
1156             /* new packet */
1157             av_new_packet(&asf_st->pkt, asf->packet_obj_size);
1158             asf_st->seq = asf->packet_seq;
1159             asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll;
1160             asf_st->pkt.stream_index = asf->stream_index;
1161             if (asf->packet_key_frame)
1162                 asf_st->pkt.flags |= PKT_FLAG_KEY;
1163         }
1164
1165         /* read data */
1166         //printf("READ PACKET s:%d  os:%d  o:%d,%d  l:%d   DATA:%p\n",
1167         //       asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
1168         //       asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
1169         get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
1170                    asf->packet_frag_size);
1171         asf_st->frag_offset += asf->packet_frag_size;
1172         asf->packet_size_left -= asf->packet_frag_size;
1173         /* test if whole packet is read */
1174         if (asf_st->frag_offset == asf_st->pkt.size) {
1175             /* return packet */
1176             if (asf_st->ds_span > 1) {
1177                 // descramble packet
1178                 char* newdata = av_malloc(asf_st->pkt.size);
1179                 if (newdata) {
1180                     int offset = 0;
1181                     while (offset < asf_st->pkt.size) {
1182                         int off = offset / asf_st->ds_chunk_size;
1183                         int row = off / asf_st->ds_span;
1184                         int col = off % asf_st->ds_span;
1185                         int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
1186                         //printf("off:%d  row:%d  col:%d  idx:%d\n", off, row, col, idx);
1187                         memcpy(newdata + offset,
1188                                asf_st->pkt.data + idx * asf_st->ds_chunk_size,
1189                                asf_st->ds_chunk_size);
1190                         offset += asf_st->ds_chunk_size;
1191                     }
1192                     av_free(asf_st->pkt.data);
1193                     asf_st->pkt.data = newdata;
1194                 }
1195             }
1196
1197             asf_st->frag_offset = 0;
1198             memcpy(pkt, &asf_st->pkt, sizeof(AVPacket));
1199             //printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size);
1200             asf_st->pkt.size = 0;
1201             asf_st->pkt.data = 0;
1202             // FIXME descrambling
1203             break; // packet completed
1204         }
1205     }
1206     return 0;
1207 }
1208
1209 static int asf_read_close(AVFormatContext *s)
1210 {
1211     //ASFContext *asf = s->priv_data;
1212     int i;
1213
1214     for(i=0;i<s->nb_streams;i++) {
1215         AVStream *st = s->streams[i];
1216         av_free(st->priv_data);
1217     }
1218     //av_free(asf);
1219     return 0;
1220 }
1221
1222 static int asf_read_seek(AVFormatContext *s, int64_t pts)
1223 {
1224     printf("SEEK TO %Ld", pts);
1225     return -1;
1226 }
1227
1228 AVInputFormat asf_iformat = {
1229     "asf",
1230     "asf format",
1231     sizeof(ASFContext),
1232     asf_probe,
1233     asf_read_header,
1234     asf_read_packet,
1235     asf_read_close,
1236     asf_read_seek,
1237 };
1238
1239 AVOutputFormat asf_oformat = {
1240     "asf",
1241     "asf format",
1242     "application/octet-stream",
1243     "asf,wmv",
1244     sizeof(ASFContext),
1245 #ifdef CONFIG_MP3LAME
1246     CODEC_ID_MP3LAME,
1247 #else
1248     CODEC_ID_MP2,
1249 #endif
1250     CODEC_ID_MSMPEG4,
1251     asf_write_header,
1252     asf_write_packet,
1253     asf_write_trailer,
1254 };
1255
1256 AVOutputFormat asf_stream_oformat = {
1257     "asf_stream",
1258     "asf format",
1259     "application/octet-stream",
1260     "asf,wmv",
1261     sizeof(ASFContext),
1262 #ifdef CONFIG_MP3LAME
1263     CODEC_ID_MP3LAME,
1264 #else
1265     CODEC_ID_MP2,
1266 #endif
1267     CODEC_ID_MSMPEG4,
1268     asf_write_stream_header,
1269     asf_write_packet,
1270     asf_write_trailer,
1271 };
1272
1273 int asf_init(void)
1274 {
1275     av_register_input_format(&asf_iformat);
1276     av_register_output_format(&asf_oformat);
1277     av_register_output_format(&asf_stream_oformat);
1278     return 0;
1279 }