3 * Copyright (c) 2000, 2001 Fabrice Bellard
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #define ASF_INDEXED_INTERVAL 10000000
31 #define ASF_INDEX_BLOCK 600
33 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
34 #define ASF_PACKET_ERROR_CORRECTION_FLAGS (\
35 ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
36 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE\
39 #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
40 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
42 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
45 #define ASF_PPI_PROPERTY_FLAGS (\
46 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
47 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
48 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
49 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE \
52 #define ASF_PPI_LENGTH_TYPE_FLAGS 0
54 #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
56 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
57 # define ASF_PPI_SEQUENCE_FIELD_SIZE 1
59 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
60 # define ASF_PPI_SEQUENCE_FIELD_SIZE 2
62 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
63 # define ASF_PPI_SEQUENCE_FIELD_SIZE 4
65 #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
66 # define ASF_PPI_SEQUENCE_FIELD_SIZE 0
70 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
71 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
73 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
74 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
76 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
77 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
79 #ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
80 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
83 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
84 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
86 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
87 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
89 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
90 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
92 #ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
93 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
96 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
97 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
99 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
100 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
102 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
103 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
105 #ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
106 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
109 #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
110 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
112 #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
113 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
115 #if (ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE))
116 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
118 #ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
119 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
122 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
123 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
125 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
126 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
128 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
129 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
131 #ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
132 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
135 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
136 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
138 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
139 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
141 #ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
142 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
145 #define PACKET_HEADER_MIN_SIZE (\
146 ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
147 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
148 1 + /*Length Type Flags*/ \
149 1 + /*Property Flags*/ \
150 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
151 ASF_PPI_SEQUENCE_FIELD_SIZE + \
152 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
153 4 + /*Send Time Field*/ \
154 2 /*Duration Field*/ \
158 // Replicated Data shall be at least 8 bytes long.
159 #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
161 #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\
162 1 + /*Stream Number*/ \
163 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
164 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
165 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
166 ASF_PAYLOAD_REPLICATED_DATA_LENGTH \
169 #define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\
170 1 + /*Stream Number*/ \
171 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
172 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
173 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
174 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
175 ASF_PAYLOAD_LENGTH_FIELD_SIZE \
178 #define SINGLE_PAYLOAD_DATA_LENGTH (\
180 PACKET_HEADER_MIN_SIZE - \
181 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
184 #define MULTI_PAYLOAD_CONSTANT (\
186 PACKET_HEADER_MIN_SIZE - \
187 1 - /*Payload Flags*/ \
188 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
191 static const AVCodecTag codec_asf_bmp_tags
[] = {
192 { CODEC_ID_MPEG4
, MKTAG('M', 'P', '4', 'S') },
193 { CODEC_ID_MPEG4
, MKTAG('M', '4', 'S', '2') },
194 { CODEC_ID_MSMPEG4V3
, MKTAG('M', 'P', '4', '3') },
195 { CODEC_ID_NONE
, 0 },
198 #define PREROLL_TIME 3100
200 static void put_guid(ByteIOContext
*s
, const GUID
*g
)
202 assert(sizeof(*g
) == 16);
203 put_buffer(s
, *g
, sizeof(*g
));
206 static void put_str16_nolen(ByteIOContext
*s
, const char *tag
);
207 static void put_str16(ByteIOContext
*s
, const char *tag
)
209 put_le16(s
,strlen(tag
) + 1);
210 put_str16_nolen(s
, tag
);
213 static void put_str16_nolen(ByteIOContext
*s
, const char *tag
)
223 static int64_t put_header(ByteIOContext
*pb
, const GUID
*g
)
233 /* update header size */
234 static void end_header(ByteIOContext
*pb
, int64_t pos
)
238 pos1
= url_ftell(pb
);
239 url_fseek(pb
, pos
+ 16, SEEK_SET
);
240 put_le64(pb
, pos1
- pos
);
241 url_fseek(pb
, pos1
, SEEK_SET
);
244 /* write an asf chunk (only used in streaming case) */
245 static void put_chunk(AVFormatContext
*s
, int type
, int payload_length
, int flags
)
247 ASFContext
*asf
= s
->priv_data
;
248 ByteIOContext
*pb
= s
->pb
;
251 length
= payload_length
+ 8;
253 put_le16(pb
, length
); //size
254 put_le32(pb
, asf
->seqno
);//sequence number
255 put_le16(pb
, flags
); /* unknown bytes */
256 put_le16(pb
, length
); //size_confirm
260 /* convert from unix to windows time */
261 static int64_t unix_to_file_time(int ti
)
265 t
= ti
* INT64_C(10000000);
266 t
+= INT64_C(116444736000000000);
270 /* write the header (used two times if non streamed) */
271 static int asf_write_header1(AVFormatContext
*s
, int64_t file_size
, int64_t data_chunk_size
)
273 ASFContext
*asf
= s
->priv_data
;
274 ByteIOContext
*pb
= s
->pb
;
275 AVMetadataTag
*title
, *author
, *copyright
, *comment
;
276 int header_size
, n
, extra_size
, extra_size2
, wav_extra_size
, file_time
;
280 int64_t header_offset
, cur_pos
, hpos
;
284 title
= av_metadata_get(s
->metadata
, "title" , NULL
, 0);
285 author
= av_metadata_get(s
->metadata
, "author" , NULL
, 0);
286 copyright
= av_metadata_get(s
->metadata
, "copyright", NULL
, 0);
287 comment
= av_metadata_get(s
->metadata
, "comment" , NULL
, 0);
289 duration
= asf
->duration
+ PREROLL_TIME
* 10000;
290 has_title
= title
|| author
|| copyright
|| comment
;
291 metadata_count
= s
->metadata
? s
->metadata
->count
: 0;
294 for(n
=0;n
<s
->nb_streams
;n
++) {
295 enc
= s
->streams
[n
]->codec
;
297 av_set_pts_info(s
->streams
[n
], 32, 1, 1000); /* 32 bit pts in ms */
299 bit_rate
+= enc
->bit_rate
;
302 if (asf
->is_streamed
) {
303 put_chunk(s
, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
306 put_guid(pb
, &ff_asf_header
);
307 put_le64(pb
, -1); /* header length, will be patched after */
308 put_le32(pb
, 3 + has_title
+ !!metadata_count
+ s
->nb_streams
); /* number of chunks in header */
309 put_byte(pb
, 1); /* ??? */
310 put_byte(pb
, 2); /* ??? */
313 header_offset
= url_ftell(pb
);
314 hpos
= put_header(pb
, &ff_asf_file_header
);
315 put_guid(pb
, &ff_asf_my_guid
);
316 put_le64(pb
, file_size
);
318 put_le64(pb
, unix_to_file_time(file_time
));
319 put_le64(pb
, asf
->nb_packets
); /* number of packets */
320 put_le64(pb
, duration
); /* end time stamp (in 100ns units) */
321 put_le64(pb
, asf
->duration
); /* duration (in 100ns units) */
322 put_le64(pb
, PREROLL_TIME
); /* start time stamp */
323 put_le32(pb
, (asf
->is_streamed
|| url_is_streamed(pb
)) ? 3 : 2); /* ??? */
324 put_le32(pb
, asf
->packet_size
); /* packet size */
325 put_le32(pb
, asf
->packet_size
); /* packet size */
326 put_le32(pb
, bit_rate
); /* Nominal data rate in bps */
327 end_header(pb
, hpos
);
329 /* unknown headers */
330 hpos
= put_header(pb
, &ff_asf_head1_guid
);
331 put_guid(pb
, &ff_asf_head2_guid
);
334 end_header(pb
, hpos
);
336 /* title and other infos */
338 hpos
= put_header(pb
, &ff_asf_comment_header
);
339 put_le16(pb
, title
? 2 * (strlen(title
->value
) + 1) : 0);
340 put_le16(pb
, author
? 2 * (strlen(author
->value
) + 1) : 0);
341 put_le16(pb
, copyright
? 2 * (strlen(copyright
->value
) + 1) : 0);
342 put_le16(pb
, comment
? 2 * (strlen(comment
->value
) + 1) : 0);
344 if (title
) put_str16_nolen(pb
, title
->value
);
345 if (author
) put_str16_nolen(pb
, author
->value
);
346 if (copyright
) put_str16_nolen(pb
, copyright
->value
);
347 if (comment
) put_str16_nolen(pb
, comment
->value
);
348 end_header(pb
, hpos
);
350 if (metadata_count
) {
351 AVMetadataTag
*tag
= NULL
;
352 hpos
= put_header(pb
, &ff_asf_extended_content_header
);
353 put_le16(pb
, metadata_count
);
354 while ((tag
= av_metadata_get(s
->metadata
, "", tag
, AV_METADATA_IGNORE_SUFFIX
))) {
355 put_le16(pb
, 2*(strlen(tag
->key
) + 3) + 1);
359 put_str16_nolen(pb
, tag
->key
);
361 put_le16(pb
, 2*strlen(tag
->value
) + 1);
362 put_str16_nolen(pb
, tag
->value
);
364 end_header(pb
, hpos
);
368 for(n
=0;n
<s
->nb_streams
;n
++) {
370 // ASFStream *stream = &asf->streams[n];
372 enc
= s
->streams
[n
]->codec
;
373 asf
->streams
[n
].num
= n
+ 1;
374 asf
->streams
[n
].seq
= 0;
377 switch(enc
->codec_type
) {
378 case CODEC_TYPE_AUDIO
:
380 extra_size
= 18 + wav_extra_size
;
384 case CODEC_TYPE_VIDEO
:
385 wav_extra_size
= enc
->extradata_size
;
386 extra_size
= 0x33 + wav_extra_size
;
391 hpos
= put_header(pb
, &ff_asf_stream_header
);
392 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
393 put_guid(pb
, &ff_asf_audio_stream
);
394 put_guid(pb
, &ff_asf_audio_conceal_spread
);
396 put_guid(pb
, &ff_asf_video_stream
);
397 put_guid(pb
, &ff_asf_video_conceal_none
);
399 put_le64(pb
, 0); /* ??? */
400 es_pos
= url_ftell(pb
);
401 put_le32(pb
, extra_size
); /* wav header len */
402 put_le32(pb
, extra_size2
); /* additional data len */
403 put_le16(pb
, n
+ 1); /* stream number */
404 put_le32(pb
, 0); /* ??? */
406 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
407 /* WAVEFORMATEX header */
408 int wavsize
= put_wav_header(pb
, enc
);
409 if ((enc
->codec_id
!= CODEC_ID_MP3
) && (enc
->codec_id
!= CODEC_ID_MP2
) && (enc
->codec_id
!= CODEC_ID_ADPCM_IMA_WAV
) && (enc
->extradata_size
==0)) {
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
);
422 /* ERROR Correction */
424 if(enc
->codec_id
== CODEC_ID_ADPCM_G726
|| !enc
->block_align
){
425 put_le16(pb
, 0x0190);
426 put_le16(pb
, 0x0190);
428 put_le16(pb
, enc
->block_align
);
429 put_le16(pb
, enc
->block_align
);
434 put_le32(pb
, enc
->width
);
435 put_le32(pb
, enc
->height
);
436 put_byte(pb
, 2); /* ??? */
437 put_le16(pb
, 40 + enc
->extradata_size
); /* size */
439 /* BITMAPINFOHEADER header */
440 put_bmp_header(pb
, enc
, codec_bmp_tags
, 1);
442 end_header(pb
, hpos
);
447 hpos
= put_header(pb
, &ff_asf_codec_comment_header
);
448 put_guid(pb
, &ff_asf_codec_comment1_header
);
449 put_le32(pb
, s
->nb_streams
);
450 for(n
=0;n
<s
->nb_streams
;n
++) {
453 enc
= s
->streams
[n
]->codec
;
454 p
= avcodec_find_encoder(enc
->codec_id
);
456 if(enc
->codec_type
== CODEC_TYPE_AUDIO
)
458 else if(enc
->codec_type
== CODEC_TYPE_VIDEO
)
463 if(enc
->codec_id
== CODEC_ID_WMAV2
)
464 put_str16(pb
, "Windows Media Audio V8");
466 put_str16(pb
, p
? p
->name
: enc
->codec_name
);
467 put_le16(pb
, 0); /* no parameters */
471 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
473 put_le16(pb
, enc
->codec_tag
);
476 put_le32(pb
, enc
->codec_tag
);
481 end_header(pb
, hpos
);
483 /* patch the header size fields */
485 cur_pos
= url_ftell(pb
);
486 header_size
= cur_pos
- header_offset
;
487 if (asf
->is_streamed
) {
488 header_size
+= 8 + 30 + 50;
490 url_fseek(pb
, header_offset
- 10 - 30, SEEK_SET
);
491 put_le16(pb
, header_size
);
492 url_fseek(pb
, header_offset
- 2 - 30, SEEK_SET
);
493 put_le16(pb
, header_size
);
495 header_size
-= 8 + 30 + 50;
497 header_size
+= 24 + 6;
498 url_fseek(pb
, header_offset
- 14, SEEK_SET
);
499 put_le64(pb
, header_size
);
500 url_fseek(pb
, cur_pos
, SEEK_SET
);
502 /* movie chunk, followed by packets of packet_size */
503 asf
->data_offset
= cur_pos
;
504 put_guid(pb
, &ff_asf_data_header
);
505 put_le64(pb
, data_chunk_size
);
506 put_guid(pb
, &ff_asf_my_guid
);
507 put_le64(pb
, asf
->nb_packets
); /* nb packets */
508 put_byte(pb
, 1); /* ??? */
509 put_byte(pb
, 1); /* ??? */
513 static int asf_write_header(AVFormatContext
*s
)
515 ASFContext
*asf
= s
->priv_data
;
517 asf
->packet_size
= PACKET_SIZE
;
520 asf
->last_indexed_pts
= 0;
521 asf
->index_ptr
= av_malloc( sizeof(ASFIndex
) * ASF_INDEX_BLOCK
);
522 asf
->nb_index_memory_alloc
= ASF_INDEX_BLOCK
;
523 asf
->nb_index_count
= 0;
524 asf
->maximum_packet
= 0;
526 /* the data-chunk-size has to be 50, which is data_size - asf->data_offset
527 * at the moment this function is done. It is needed to use asf as
528 * streamable format. */
529 if (asf_write_header1(s
, 0, 50) < 0) {
534 put_flush_packet(s
->pb
);
536 asf
->packet_nb_payloads
= 0;
537 asf
->packet_timestamp_start
= -1;
538 asf
->packet_timestamp_end
= -1;
539 init_put_byte(&asf
->pb
, asf
->packet_buf
, asf
->packet_size
, 1,
540 NULL
, NULL
, NULL
, NULL
);
545 static int asf_write_stream_header(AVFormatContext
*s
)
547 ASFContext
*asf
= s
->priv_data
;
549 asf
->is_streamed
= 1;
551 return asf_write_header(s
);
554 static int put_payload_parsing_info(
556 unsigned int sendtime
,
557 unsigned int duration
,
562 ASFContext
*asf
= s
->priv_data
;
563 ByteIOContext
*pb
= s
->pb
;
565 int64_t start
= url_ftell(pb
);
567 int iLengthTypeFlags
= ASF_PPI_LENGTH_TYPE_FLAGS
;
569 padsize
-= PACKET_HEADER_MIN_SIZE
;
570 if(asf
->multi_payloads_present
)
574 put_byte(pb
, ASF_PACKET_ERROR_CORRECTION_FLAGS
);
575 for (i
= 0; i
< ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
; i
++){
579 if (asf
->multi_payloads_present
)
580 iLengthTypeFlags
|= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
;
584 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
;
586 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
;
588 put_byte(pb
, iLengthTypeFlags
);
590 put_byte(pb
, ASF_PPI_PROPERTY_FLAGS
);
592 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
)
593 put_le16(pb
, padsize
- 2);
594 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
)
595 put_byte(pb
, padsize
- 1);
597 put_le32(pb
, sendtime
);
598 put_le16(pb
, duration
);
599 if (asf
->multi_payloads_present
)
600 put_byte(pb
, nb_payloads
| ASF_PAYLOAD_FLAGS
);
602 ppi_size
= url_ftell(pb
) - start
;
607 static void flush_packet(AVFormatContext
*s
)
609 ASFContext
*asf
= s
->priv_data
;
610 int packet_hdr_size
, packet_filled_size
;
612 assert(asf
->packet_timestamp_end
>= asf
->packet_timestamp_start
);
614 if (asf
->is_streamed
) {
615 put_chunk(s
, 0x4424, asf
->packet_size
, 0);
618 packet_hdr_size
= put_payload_parsing_info(
620 asf
->packet_timestamp_start
,
621 asf
->packet_timestamp_end
- asf
->packet_timestamp_start
,
622 asf
->packet_nb_payloads
,
623 asf
->packet_size_left
626 packet_filled_size
= PACKET_SIZE
- asf
->packet_size_left
;
627 assert(packet_hdr_size
<= asf
->packet_size_left
);
628 memset(asf
->packet_buf
+ packet_filled_size
, 0, asf
->packet_size_left
);
630 put_buffer(s
->pb
, asf
->packet_buf
, asf
->packet_size
- packet_hdr_size
);
632 put_flush_packet(s
->pb
);
634 asf
->packet_nb_payloads
= 0;
635 asf
->packet_timestamp_start
= -1;
636 asf
->packet_timestamp_end
= -1;
637 init_put_byte(&asf
->pb
, asf
->packet_buf
, asf
->packet_size
, 1,
638 NULL
, NULL
, NULL
, NULL
);
641 static void put_payload_header(
644 int presentation_time
,
651 ASFContext
*asf
= s
->priv_data
;
652 ByteIOContext
*pb
= &asf
->pb
;
656 if (flags
& PKT_FLAG_KEY
)
657 val
|= ASF_PL_FLAG_KEY_FRAME
;
660 put_byte(pb
, stream
->seq
); //Media object number
661 put_le32(pb
, m_obj_offset
); //Offset Into Media Object
663 // Replicated Data shall be at least 8 bytes long.
664 // The first 4 bytes of data shall contain the
665 // Size of the Media Object that the payload belongs to.
666 // The next 4 bytes of data shall contain the
667 // Presentation Time for the media object that the payload belongs to.
668 put_byte(pb
, ASF_PAYLOAD_REPLICATED_DATA_LENGTH
);
670 put_le32(pb
, m_obj_size
); //Replicated Data - Media Object Size
671 put_le32(pb
, presentation_time
);//Replicated Data - Presentation Time
673 if (asf
->multi_payloads_present
){
674 put_le16(pb
, payload_len
); //payload length
678 static void put_frame(
688 ASFContext
*asf
= s
->priv_data
;
689 int m_obj_offset
, payload_len
, frag_len1
;
692 while (m_obj_offset
< m_obj_size
) {
693 payload_len
= m_obj_size
- m_obj_offset
;
694 if (asf
->packet_timestamp_start
== -1) {
695 asf
->multi_payloads_present
= (payload_len
< MULTI_PAYLOAD_CONSTANT
);
697 asf
->packet_size_left
= PACKET_SIZE
;
698 if (asf
->multi_payloads_present
){
699 frag_len1
= MULTI_PAYLOAD_CONSTANT
- 1;
702 frag_len1
= SINGLE_PAYLOAD_DATA_LENGTH
;
704 asf
->packet_timestamp_start
= timestamp
;
708 frag_len1
= asf
->packet_size_left
- PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
- PACKET_HEADER_MIN_SIZE
- 1;
710 if(frag_len1
< payload_len
&& avst
->codec
->codec_type
== CODEC_TYPE_AUDIO
){
716 if (payload_len
> frag_len1
)
717 payload_len
= frag_len1
;
718 else if (payload_len
== (frag_len1
- 1))
719 payload_len
= frag_len1
- 2; //additional byte need to put padding length
721 put_payload_header(s
, stream
, timestamp
+PREROLL_TIME
, m_obj_size
, m_obj_offset
, payload_len
, flags
);
722 put_buffer(&asf
->pb
, buf
, payload_len
);
724 if (asf
->multi_payloads_present
)
725 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
);
727 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD
);
728 asf
->packet_timestamp_end
= timestamp
;
730 asf
->packet_nb_payloads
++;
734 m_obj_offset
+= payload_len
;
737 if (!asf
->multi_payloads_present
)
739 else if (asf
->packet_size_left
<= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
+ PACKET_HEADER_MIN_SIZE
+ 1))
745 static int asf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
747 ASFContext
*asf
= s
->priv_data
;
750 AVCodecContext
*codec
;
751 int64_t packet_st
,pts
;
753 int flags
= pkt
->flags
;
755 codec
= s
->streams
[pkt
->stream_index
]->codec
;
756 stream
= &asf
->streams
[pkt
->stream_index
];
758 if(codec
->codec_type
== CODEC_TYPE_AUDIO
)
759 flags
&= ~PKT_FLAG_KEY
;
761 pts
= (pkt
->pts
!= AV_NOPTS_VALUE
) ? pkt
->pts
: pkt
->dts
;
762 assert(pts
!= AV_NOPTS_VALUE
);
763 duration
= pts
* 10000;
764 asf
->duration
= FFMAX(asf
->duration
, duration
+ pkt
->duration
* 10000);
766 packet_st
= asf
->nb_packets
;
767 put_frame(s
, stream
, s
->streams
[pkt
->stream_index
], pkt
->dts
, pkt
->data
, pkt
->size
, flags
);
770 if ((!asf
->is_streamed
) && (flags
& PKT_FLAG_KEY
)) {
771 start_sec
= (int)(duration
/ INT64_C(10000000));
772 if (start_sec
!= (int)(asf
->last_indexed_pts
/ INT64_C(10000000))) {
773 for(i
=asf
->nb_index_count
;i
<start_sec
;i
++) {
774 if (i
>=asf
->nb_index_memory_alloc
) {
775 asf
->nb_index_memory_alloc
+= ASF_INDEX_BLOCK
;
776 asf
->index_ptr
= (ASFIndex
*)av_realloc( asf
->index_ptr
, sizeof(ASFIndex
) * asf
->nb_index_memory_alloc
);
779 asf
->index_ptr
[i
].packet_number
= (uint32_t)packet_st
;
780 asf
->index_ptr
[i
].packet_count
= (uint16_t)(asf
->nb_packets
-packet_st
);
781 asf
->maximum_packet
= FFMAX(asf
->maximum_packet
, (uint16_t)(asf
->nb_packets
-packet_st
));
783 asf
->nb_index_count
= start_sec
;
784 asf
->last_indexed_pts
= duration
;
791 static int asf_write_index(AVFormatContext
*s
, ASFIndex
*index
, uint16_t max
, uint32_t count
)
793 ByteIOContext
*pb
= s
->pb
;
796 put_guid(pb
, &ff_asf_simple_index_header
);
797 put_le64(pb
, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count
);
798 put_guid(pb
, &ff_asf_my_guid
);
799 put_le64(pb
, ASF_INDEXED_INTERVAL
);
802 for(i
=0; i
<count
; i
++) {
803 put_le32(pb
, index
[i
].packet_number
);
804 put_le16(pb
, index
[i
].packet_count
);
810 static int asf_write_trailer(AVFormatContext
*s
)
812 ASFContext
*asf
= s
->priv_data
;
813 int64_t file_size
,data_size
;
815 /* flush the current packet */
816 if (asf
->pb
.buf_ptr
> asf
->pb
.buffer
)
820 data_size
= url_ftell(s
->pb
);
821 if ((!asf
->is_streamed
) && (asf
->nb_index_count
!= 0)) {
822 asf_write_index(s
, asf
->index_ptr
, asf
->maximum_packet
, asf
->nb_index_count
);
824 put_flush_packet(s
->pb
);
826 if (asf
->is_streamed
|| url_is_streamed(s
->pb
)) {
827 put_chunk(s
, 0x4524, 0, 0); /* end of stream */
829 /* rewrite an updated header */
830 file_size
= url_ftell(s
->pb
);
831 url_fseek(s
->pb
, 0, SEEK_SET
);
832 asf_write_header1(s
, file_size
, data_size
- asf
->data_offset
);
835 put_flush_packet(s
->pb
);
836 av_free(asf
->index_ptr
);
841 AVOutputFormat asf_muxer
= {
843 NULL_IF_CONFIG_SMALL("ASF format"),
847 #if CONFIG_LIBMP3LAME
856 .flags
= AVFMT_GLOBALHEADER
,
857 .codec_tag
= (const AVCodecTag
* const []){codec_asf_bmp_tags
, codec_bmp_tags
, codec_wav_tags
, 0},
858 .metadata_conv
= ff_asf_metadata_conv
,
862 #if CONFIG_ASF_STREAM_MUXER
863 AVOutputFormat asf_stream_muxer
= {
865 NULL_IF_CONFIG_SMALL("ASF format"),
869 #if CONFIG_LIBMP3LAME
875 asf_write_stream_header
,
878 .flags
= AVFMT_GLOBALHEADER
,
879 .codec_tag
= (const AVCodecTag
* const []){codec_asf_bmp_tags
, codec_bmp_tags
, codec_wav_tags
, 0},
880 .metadata_conv
= ff_asf_metadata_conv
,
882 #endif //CONFIG_ASF_STREAM_MUXER