2 * Adaptive stream format muxer
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
29 #define ASF_INDEXED_INTERVAL 10000000
30 #define ASF_INDEX_BLOCK 600
32 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
33 #define ASF_PACKET_ERROR_CORRECTION_FLAGS (\
34 ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
35 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE\
38 #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
39 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
41 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
44 #define ASF_PPI_PROPERTY_FLAGS (\
45 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
46 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
47 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
48 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE \
51 #define ASF_PPI_LENGTH_TYPE_FLAGS 0
53 #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
55 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
56 # define ASF_PPI_SEQUENCE_FIELD_SIZE 1
58 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
59 # define ASF_PPI_SEQUENCE_FIELD_SIZE 2
61 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
62 # define ASF_PPI_SEQUENCE_FIELD_SIZE 4
64 #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
65 # define ASF_PPI_SEQUENCE_FIELD_SIZE 0
69 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
70 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
72 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
73 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
75 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
76 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
78 #ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
79 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
82 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
83 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
85 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
86 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
88 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
89 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
91 #ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
92 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
95 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
96 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
98 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
99 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
101 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
102 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
104 #ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
105 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
108 #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))
109 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
111 #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))
112 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
114 #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))
115 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
117 #ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
118 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
121 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
122 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
124 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
125 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
127 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
128 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
130 #ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
131 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
134 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
135 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
137 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
138 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
140 #ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
141 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
144 #define PACKET_HEADER_MIN_SIZE (\
145 ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
146 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
147 1 + /*Length Type Flags*/ \
148 1 + /*Property Flags*/ \
149 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
150 ASF_PPI_SEQUENCE_FIELD_SIZE + \
151 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
152 4 + /*Send Time Field*/ \
153 2 /*Duration Field*/ \
157 // Replicated Data shall be at least 8 bytes long.
158 #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
160 #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD (\
161 1 + /*Stream Number*/ \
162 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
163 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
164 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
165 ASF_PAYLOAD_REPLICATED_DATA_LENGTH \
168 #define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS (\
169 1 + /*Stream Number*/ \
170 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
171 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
172 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
173 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
174 ASF_PAYLOAD_LENGTH_FIELD_SIZE \
177 #define SINGLE_PAYLOAD_DATA_LENGTH (\
179 PACKET_HEADER_MIN_SIZE - \
180 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
183 #define MULTI_PAYLOAD_CONSTANT (\
185 PACKET_HEADER_MIN_SIZE - \
186 1 - /*Payload Flags*/ \
187 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
190 static const AVCodecTag codec_asf_bmp_tags
[] = {
191 { CODEC_ID_MPEG4
, MKTAG('M', 'P', '4', 'S') },
192 { CODEC_ID_MPEG4
, MKTAG('M', '4', 'S', '2') },
193 { CODEC_ID_MSMPEG4V3
, MKTAG('M', 'P', '4', '3') },
194 { CODEC_ID_NONE
, 0 },
197 #define PREROLL_TIME 3100
199 static void put_guid(ByteIOContext
*s
, const GUID
*g
)
201 assert(sizeof(*g
) == 16);
202 put_buffer(s
, *g
, sizeof(*g
));
205 static void put_str16_nolen(ByteIOContext
*s
, const char *tag
);
206 static void put_str16(ByteIOContext
*s
, const char *tag
)
208 put_le16(s
,strlen(tag
) + 1);
209 put_str16_nolen(s
, tag
);
212 static void put_str16_nolen(ByteIOContext
*s
, const char *tag
)
222 static int64_t put_header(ByteIOContext
*pb
, const GUID
*g
)
232 /* update header size */
233 static void end_header(ByteIOContext
*pb
, int64_t pos
)
237 pos1
= url_ftell(pb
);
238 url_fseek(pb
, pos
+ 16, SEEK_SET
);
239 put_le64(pb
, pos1
- pos
);
240 url_fseek(pb
, pos1
, SEEK_SET
);
243 /* write an asf chunk (only used in streaming case) */
244 static void put_chunk(AVFormatContext
*s
, int type
, int payload_length
, int flags
)
246 ASFContext
*asf
= s
->priv_data
;
247 ByteIOContext
*pb
= s
->pb
;
250 length
= payload_length
+ 8;
252 put_le16(pb
, length
); //size
253 put_le32(pb
, asf
->seqno
);//sequence number
254 put_le16(pb
, flags
); /* unknown bytes */
255 put_le16(pb
, length
); //size_confirm
259 /* convert from unix to windows time */
260 static int64_t unix_to_file_time(int ti
)
264 t
= ti
* INT64_C(10000000);
265 t
+= INT64_C(116444736000000000);
269 /* write the header (used two times if non streamed) */
270 static int asf_write_header1(AVFormatContext
*s
, int64_t file_size
, int64_t data_chunk_size
)
272 ASFContext
*asf
= s
->priv_data
;
273 ByteIOContext
*pb
= s
->pb
;
274 int header_size
, n
, extra_size
, extra_size2
, wav_extra_size
, file_time
;
277 int64_t header_offset
, cur_pos
, hpos
;
281 duration
= asf
->duration
+ PREROLL_TIME
* 10000;
282 has_title
= (s
->title
[0] || s
->author
[0] || s
->copyright
[0] || s
->comment
[0]);
285 for(n
=0;n
<s
->nb_streams
;n
++) {
286 enc
= s
->streams
[n
]->codec
;
288 av_set_pts_info(s
->streams
[n
], 32, 1, 1000); /* 32 bit pts in ms */
290 bit_rate
+= enc
->bit_rate
;
293 if (asf
->is_streamed
) {
294 put_chunk(s
, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
297 put_guid(pb
, &asf_header
);
298 put_le64(pb
, -1); /* header length, will be patched after */
299 put_le32(pb
, 3 + has_title
+ s
->nb_streams
); /* number of chunks in header */
300 put_byte(pb
, 1); /* ??? */
301 put_byte(pb
, 2); /* ??? */
304 header_offset
= url_ftell(pb
);
305 hpos
= put_header(pb
, &file_header
);
306 put_guid(pb
, &my_guid
);
307 put_le64(pb
, file_size
);
309 put_le64(pb
, unix_to_file_time(file_time
));
310 put_le64(pb
, asf
->nb_packets
); /* number of packets */
311 put_le64(pb
, duration
); /* end time stamp (in 100ns units) */
312 put_le64(pb
, asf
->duration
); /* duration (in 100ns units) */
313 put_le64(pb
, PREROLL_TIME
); /* start time stamp */
314 put_le32(pb
, (asf
->is_streamed
|| url_is_streamed(pb
)) ? 3 : 2); /* ??? */
315 put_le32(pb
, asf
->packet_size
); /* packet size */
316 put_le32(pb
, asf
->packet_size
); /* packet size */
317 put_le32(pb
, bit_rate
); /* Nominal data rate in bps */
318 end_header(pb
, hpos
);
320 /* unknown headers */
321 hpos
= put_header(pb
, &head1_guid
);
322 put_guid(pb
, &head2_guid
);
325 end_header(pb
, hpos
);
327 /* title and other infos */
329 hpos
= put_header(pb
, &comment_header
);
330 if ( s
->title
[0] ) { put_le16(pb
, 2 * (strlen(s
->title
) + 1)); } else { put_le16(pb
, 0); }
331 if ( s
->author
[0] ) { put_le16(pb
, 2 * (strlen(s
->author
) + 1)); } else { put_le16(pb
, 0); }
332 if ( s
->copyright
[0] ) { put_le16(pb
, 2 * (strlen(s
->copyright
) + 1)); } else { put_le16(pb
, 0); }
333 if ( s
->comment
[0] ) { put_le16(pb
, 2 * (strlen(s
->comment
) + 1)); } else { put_le16(pb
, 0); }
335 if ( s
->title
[0] ) put_str16_nolen(pb
, s
->title
);
336 if ( s
->author
[0] ) put_str16_nolen(pb
, s
->author
);
337 if ( s
->copyright
[0] ) put_str16_nolen(pb
, s
->copyright
);
338 if ( s
->comment
[0] ) put_str16_nolen(pb
, s
->comment
);
339 end_header(pb
, hpos
);
343 for(n
=0;n
<s
->nb_streams
;n
++) {
345 // ASFStream *stream = &asf->streams[n];
347 enc
= s
->streams
[n
]->codec
;
348 asf
->streams
[n
].num
= n
+ 1;
349 asf
->streams
[n
].seq
= 0;
352 switch(enc
->codec_type
) {
353 case CODEC_TYPE_AUDIO
:
355 extra_size
= 18 + wav_extra_size
;
359 case CODEC_TYPE_VIDEO
:
360 wav_extra_size
= enc
->extradata_size
;
361 extra_size
= 0x33 + wav_extra_size
;
366 hpos
= put_header(pb
, &stream_header
);
367 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
368 put_guid(pb
, &audio_stream
);
369 put_guid(pb
, &audio_conceal_spread
);
371 put_guid(pb
, &video_stream
);
372 put_guid(pb
, &video_conceal_none
);
374 put_le64(pb
, 0); /* ??? */
375 es_pos
= url_ftell(pb
);
376 put_le32(pb
, extra_size
); /* wav header len */
377 put_le32(pb
, extra_size2
); /* additional data len */
378 put_le16(pb
, n
+ 1); /* stream number */
379 put_le32(pb
, 0); /* ??? */
381 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
382 /* WAVEFORMATEX header */
383 int wavsize
= put_wav_header(pb
, enc
);
384 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)) {
391 if (wavsize
!= extra_size
) {
392 cur_pos
= url_ftell(pb
);
393 url_fseek(pb
, es_pos
, SEEK_SET
);
394 put_le32(pb
, wavsize
); /* wav header len */
395 url_fseek(pb
, cur_pos
, SEEK_SET
);
397 /* ERROR Correction */
399 if(enc
->codec_id
== CODEC_ID_ADPCM_G726
|| !enc
->block_align
){
400 put_le16(pb
, 0x0190);
401 put_le16(pb
, 0x0190);
403 put_le16(pb
, enc
->block_align
);
404 put_le16(pb
, enc
->block_align
);
409 put_le32(pb
, enc
->width
);
410 put_le32(pb
, enc
->height
);
411 put_byte(pb
, 2); /* ??? */
412 put_le16(pb
, 40 + enc
->extradata_size
); /* size */
414 /* BITMAPINFOHEADER header */
415 put_bmp_header(pb
, enc
, codec_bmp_tags
, 1);
417 end_header(pb
, hpos
);
422 hpos
= put_header(pb
, &codec_comment_header
);
423 put_guid(pb
, &codec_comment1_header
);
424 put_le32(pb
, s
->nb_streams
);
425 for(n
=0;n
<s
->nb_streams
;n
++) {
428 enc
= s
->streams
[n
]->codec
;
429 p
= avcodec_find_encoder(enc
->codec_id
);
431 if(enc
->codec_type
== CODEC_TYPE_AUDIO
)
433 else if(enc
->codec_type
== CODEC_TYPE_VIDEO
)
438 if(enc
->codec_id
== CODEC_ID_WMAV2
)
439 put_str16(pb
, "Windows Media Audio V8");
441 put_str16(pb
, p
? p
->name
: enc
->codec_name
);
442 put_le16(pb
, 0); /* no parameters */
446 if (enc
->codec_type
== CODEC_TYPE_AUDIO
) {
448 put_le16(pb
, enc
->codec_tag
);
451 put_le32(pb
, enc
->codec_tag
);
456 end_header(pb
, hpos
);
458 /* patch the header size fields */
460 cur_pos
= url_ftell(pb
);
461 header_size
= cur_pos
- header_offset
;
462 if (asf
->is_streamed
) {
463 header_size
+= 8 + 30 + 50;
465 url_fseek(pb
, header_offset
- 10 - 30, SEEK_SET
);
466 put_le16(pb
, header_size
);
467 url_fseek(pb
, header_offset
- 2 - 30, SEEK_SET
);
468 put_le16(pb
, header_size
);
470 header_size
-= 8 + 30 + 50;
472 header_size
+= 24 + 6;
473 url_fseek(pb
, header_offset
- 14, SEEK_SET
);
474 put_le64(pb
, header_size
);
475 url_fseek(pb
, cur_pos
, SEEK_SET
);
477 /* movie chunk, followed by packets of packet_size */
478 asf
->data_offset
= cur_pos
;
479 put_guid(pb
, &data_header
);
480 put_le64(pb
, data_chunk_size
);
481 put_guid(pb
, &my_guid
);
482 put_le64(pb
, asf
->nb_packets
); /* nb packets */
483 put_byte(pb
, 1); /* ??? */
484 put_byte(pb
, 1); /* ??? */
488 static int asf_write_header(AVFormatContext
*s
)
490 ASFContext
*asf
= s
->priv_data
;
492 asf
->packet_size
= PACKET_SIZE
;
495 asf
->last_indexed_pts
= 0;
496 asf
->index_ptr
= av_malloc( sizeof(ASFIndex
) * ASF_INDEX_BLOCK
);
497 asf
->nb_index_memory_alloc
= ASF_INDEX_BLOCK
;
498 asf
->nb_index_count
= 0;
499 asf
->maximum_packet
= 0;
501 /* the data-chunk-size has to be 50, which is data_size - asf->data_offset
502 * at the moment this function is done. It is needed to use asf as
503 * streamable format. */
504 if (asf_write_header1(s
, 0, 50) < 0) {
509 put_flush_packet(s
->pb
);
511 asf
->packet_nb_payloads
= 0;
512 asf
->packet_timestamp_start
= -1;
513 asf
->packet_timestamp_end
= -1;
514 init_put_byte(&asf
->pb
, asf
->packet_buf
, asf
->packet_size
, 1,
515 NULL
, NULL
, NULL
, NULL
);
520 static int asf_write_stream_header(AVFormatContext
*s
)
522 ASFContext
*asf
= s
->priv_data
;
524 asf
->is_streamed
= 1;
526 return asf_write_header(s
);
529 static int put_payload_parsing_info(
531 unsigned int sendtime
,
532 unsigned int duration
,
537 ASFContext
*asf
= s
->priv_data
;
538 ByteIOContext
*pb
= s
->pb
;
540 int64_t start
= url_ftell(pb
);
542 int iLengthTypeFlags
= ASF_PPI_LENGTH_TYPE_FLAGS
;
544 padsize
-= PACKET_HEADER_MIN_SIZE
;
545 if(asf
->multi_payloads_present
)
549 put_byte(pb
, ASF_PACKET_ERROR_CORRECTION_FLAGS
);
550 for (i
= 0; i
< ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
; i
++){
554 if (asf
->multi_payloads_present
)
555 iLengthTypeFlags
|= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
;
559 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
;
561 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
;
563 put_byte(pb
, iLengthTypeFlags
);
565 put_byte(pb
, ASF_PPI_PROPERTY_FLAGS
);
567 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
)
568 put_le16(pb
, padsize
- 2);
569 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
)
570 put_byte(pb
, padsize
- 1);
572 put_le32(pb
, sendtime
);
573 put_le16(pb
, duration
);
574 if (asf
->multi_payloads_present
)
575 put_byte(pb
, nb_payloads
| ASF_PAYLOAD_FLAGS
);
577 ppi_size
= url_ftell(pb
) - start
;
582 static void flush_packet(AVFormatContext
*s
)
584 ASFContext
*asf
= s
->priv_data
;
585 int packet_hdr_size
, packet_filled_size
;
587 assert(asf
->packet_timestamp_end
>= asf
->packet_timestamp_start
);
589 if (asf
->is_streamed
) {
590 put_chunk(s
, 0x4424, asf
->packet_size
, 0);
593 packet_hdr_size
= put_payload_parsing_info(
595 asf
->packet_timestamp_start
,
596 asf
->packet_timestamp_end
- asf
->packet_timestamp_start
,
597 asf
->packet_nb_payloads
,
598 asf
->packet_size_left
601 packet_filled_size
= PACKET_SIZE
- asf
->packet_size_left
;
602 assert(packet_hdr_size
<= asf
->packet_size_left
);
603 memset(asf
->packet_buf
+ packet_filled_size
, 0, asf
->packet_size_left
);
605 put_buffer(s
->pb
, asf
->packet_buf
, asf
->packet_size
- packet_hdr_size
);
607 put_flush_packet(s
->pb
);
609 asf
->packet_nb_payloads
= 0;
610 asf
->packet_timestamp_start
= -1;
611 asf
->packet_timestamp_end
= -1;
612 init_put_byte(&asf
->pb
, asf
->packet_buf
, asf
->packet_size
, 1,
613 NULL
, NULL
, NULL
, NULL
);
616 static void put_payload_header(
619 int presentation_time
,
626 ASFContext
*asf
= s
->priv_data
;
627 ByteIOContext
*pb
= &asf
->pb
;
631 if (flags
& PKT_FLAG_KEY
)
632 val
|= ASF_PL_FLAG_KEY_FRAME
;
635 put_byte(pb
, stream
->seq
); //Media object number
636 put_le32(pb
, m_obj_offset
); //Offset Into Media Object
638 // Replicated Data shall be at least 8 bytes long.
639 // The first 4 bytes of data shall contain the
640 // Size of the Media Object that the payload belongs to.
641 // The next 4 bytes of data shall contain the
642 // Presentation Time for the media object that the payload belongs to.
643 put_byte(pb
, ASF_PAYLOAD_REPLICATED_DATA_LENGTH
);
645 put_le32(pb
, m_obj_size
); //Replicated Data - Media Object Size
646 put_le32(pb
, presentation_time
);//Replicated Data - Presentation Time
648 if (asf
->multi_payloads_present
){
649 put_le16(pb
, payload_len
); //payload length
653 static void put_frame(
663 ASFContext
*asf
= s
->priv_data
;
664 int m_obj_offset
, payload_len
, frag_len1
;
667 while (m_obj_offset
< m_obj_size
) {
668 payload_len
= m_obj_size
- m_obj_offset
;
669 if (asf
->packet_timestamp_start
== -1) {
670 asf
->multi_payloads_present
= (payload_len
< MULTI_PAYLOAD_CONSTANT
);
672 asf
->packet_size_left
= PACKET_SIZE
;
673 if (asf
->multi_payloads_present
){
674 frag_len1
= MULTI_PAYLOAD_CONSTANT
- 1;
677 frag_len1
= SINGLE_PAYLOAD_DATA_LENGTH
;
679 asf
->packet_timestamp_start
= timestamp
;
683 frag_len1
= asf
->packet_size_left
- PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
- PACKET_HEADER_MIN_SIZE
- 1;
685 if(frag_len1
< payload_len
&& avst
->codec
->codec_type
== CODEC_TYPE_AUDIO
){
691 if (payload_len
> frag_len1
)
692 payload_len
= frag_len1
;
693 else if (payload_len
== (frag_len1
- 1))
694 payload_len
= frag_len1
- 2; //additional byte need to put padding length
696 put_payload_header(s
, stream
, timestamp
+PREROLL_TIME
, m_obj_size
, m_obj_offset
, payload_len
, flags
);
697 put_buffer(&asf
->pb
, buf
, payload_len
);
699 if (asf
->multi_payloads_present
)
700 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
);
702 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD
);
703 asf
->packet_timestamp_end
= timestamp
;
705 asf
->packet_nb_payloads
++;
709 m_obj_offset
+= payload_len
;
712 if (!asf
->multi_payloads_present
)
714 else if (asf
->packet_size_left
<= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
+ PACKET_HEADER_MIN_SIZE
+ 1))
720 static int asf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
722 ASFContext
*asf
= s
->priv_data
;
725 AVCodecContext
*codec
;
726 int64_t packet_st
,pts
;
728 int flags
= pkt
->flags
;
730 codec
= s
->streams
[pkt
->stream_index
]->codec
;
731 stream
= &asf
->streams
[pkt
->stream_index
];
733 if(codec
->codec_type
== CODEC_TYPE_AUDIO
)
734 flags
&= ~PKT_FLAG_KEY
;
736 pts
= (pkt
->pts
!= AV_NOPTS_VALUE
) ? pkt
->pts
: pkt
->dts
;
737 assert(pts
!= AV_NOPTS_VALUE
);
738 duration
= pts
* 10000;
739 asf
->duration
= FFMAX(asf
->duration
, duration
+ pkt
->duration
* 10000);
741 packet_st
= asf
->nb_packets
;
742 put_frame(s
, stream
, s
->streams
[pkt
->stream_index
], pkt
->dts
, pkt
->data
, pkt
->size
, flags
);
745 if ((!asf
->is_streamed
) && (flags
& PKT_FLAG_KEY
)) {
746 start_sec
= (int)(duration
/ INT64_C(10000000));
747 if (start_sec
!= (int)(asf
->last_indexed_pts
/ INT64_C(10000000))) {
748 for(i
=asf
->nb_index_count
;i
<start_sec
;i
++) {
749 if (i
>=asf
->nb_index_memory_alloc
) {
750 asf
->nb_index_memory_alloc
+= ASF_INDEX_BLOCK
;
751 asf
->index_ptr
= (ASFIndex
*)av_realloc( asf
->index_ptr
, sizeof(ASFIndex
) * asf
->nb_index_memory_alloc
);
754 asf
->index_ptr
[i
].packet_number
= (uint32_t)packet_st
;
755 asf
->index_ptr
[i
].packet_count
= (uint16_t)(asf
->nb_packets
-packet_st
);
756 asf
->maximum_packet
= FFMAX(asf
->maximum_packet
, (uint16_t)(asf
->nb_packets
-packet_st
));
758 asf
->nb_index_count
= start_sec
;
759 asf
->last_indexed_pts
= duration
;
766 static int asf_write_index(AVFormatContext
*s
, ASFIndex
*index
, uint16_t max
, uint32_t count
)
768 ByteIOContext
*pb
= s
->pb
;
771 put_guid(pb
, &simple_index_header
);
772 put_le64(pb
, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count
);
773 put_guid(pb
, &my_guid
);
774 put_le64(pb
, ASF_INDEXED_INTERVAL
);
777 for(i
=0; i
<count
; i
++) {
778 put_le32(pb
, index
[i
].packet_number
);
779 put_le16(pb
, index
[i
].packet_count
);
785 static int asf_write_trailer(AVFormatContext
*s
)
787 ASFContext
*asf
= s
->priv_data
;
788 int64_t file_size
,data_size
;
790 /* flush the current packet */
791 if (asf
->pb
.buf_ptr
> asf
->pb
.buffer
)
795 data_size
= url_ftell(s
->pb
);
796 if ((!asf
->is_streamed
) && (asf
->nb_index_count
!= 0)) {
797 asf_write_index(s
, asf
->index_ptr
, asf
->maximum_packet
, asf
->nb_index_count
);
799 put_flush_packet(s
->pb
);
801 if (asf
->is_streamed
|| url_is_streamed(s
->pb
)) {
802 put_chunk(s
, 0x4524, 0, 0); /* end of stream */
804 /* rewrite an updated header */
805 file_size
= url_ftell(s
->pb
);
806 url_fseek(s
->pb
, 0, SEEK_SET
);
807 asf_write_header1(s
, file_size
, data_size
- asf
->data_offset
);
810 put_flush_packet(s
->pb
);
811 av_free(asf
->index_ptr
);
815 #ifdef CONFIG_ASF_MUXER
816 AVOutputFormat asf_muxer
= {
818 NULL_IF_CONFIG_SMALL("ASF format"),
822 #ifdef CONFIG_LIBMP3LAME
831 .flags
= AVFMT_GLOBALHEADER
,
832 .codec_tag
= (const AVCodecTag
*[]){codec_asf_bmp_tags
, codec_bmp_tags
, codec_wav_tags
, 0},
836 #ifdef CONFIG_ASF_STREAM_MUXER
837 AVOutputFormat asf_stream_muxer
= {
839 NULL_IF_CONFIG_SMALL("ASF format"),
843 #ifdef CONFIG_LIBMP3LAME
849 asf_write_stream_header
,
852 .flags
= AVFMT_GLOBALHEADER
,
853 .codec_tag
= (const AVCodecTag
*[]){codec_asf_bmp_tags
, codec_bmp_tags
, codec_wav_tags
, 0},
855 #endif //CONFIG_ASF_STREAM_MUXER