3 * Copyright (c) 2000, 2001 Fabrice Bellard
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/dict.h"
24 #include "avio_internal.h"
33 #define ASF_INDEXED_INTERVAL 10000000
34 #define ASF_INDEX_BLOCK 600
36 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
37 #define ASF_PACKET_ERROR_CORRECTION_FLAGS \
38 (ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
39 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE)
41 #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
42 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
44 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
47 #define ASF_PPI_PROPERTY_FLAGS \
48 (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
49 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
50 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
51 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE)
53 #define ASF_PPI_LENGTH_TYPE_FLAGS 0
55 #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
57 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
58 # define ASF_PPI_SEQUENCE_FIELD_SIZE 1
60 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
61 # define ASF_PPI_SEQUENCE_FIELD_SIZE 2
63 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
64 # define ASF_PPI_SEQUENCE_FIELD_SIZE 4
66 #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
67 # 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 */
156 // Replicated Data shall be at least 8 bytes long.
157 #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
159 #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
160 (1 + /* Stream Number */ \
161 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
162 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
163 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
164 ASF_PAYLOAD_REPLICATED_DATA_LENGTH)
166 #define PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \
167 (1 + /* Stream Number */ \
168 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
169 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
170 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
171 ASF_PAYLOAD_REPLICATED_DATA_LENGTH + \
172 ASF_PAYLOAD_LENGTH_FIELD_SIZE)
174 #define SINGLE_PAYLOAD_DATA_LENGTH \
176 PACKET_HEADER_MIN_SIZE - \
177 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD)
179 #define MULTI_PAYLOAD_CONSTANT \
181 PACKET_HEADER_MIN_SIZE - \
182 1 - /* Payload Flags */ \
183 2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS)
188 ASFStream streams
[128]; ///< it's max number and it's not that big
189 /* non streamed additonnal info */
190 uint64_t nb_packets
; ///< how many packets are there in the file, invalid if broadcasting
191 int64_t duration
; ///< in 100ns units
193 unsigned char multi_payloads_present
;
194 int packet_size_left
;
195 int packet_timestamp_start
;
196 int packet_timestamp_end
;
197 unsigned int packet_nb_payloads
;
198 uint8_t packet_buf
[PACKET_SIZE
];
200 /* only for reading */
201 uint64_t data_offset
; ///< beginning of the first data packet
203 int64_t last_indexed_pts
;
205 uint32_t nb_index_count
;
206 uint32_t nb_index_memory_alloc
;
207 uint16_t maximum_packet
;
210 static const AVCodecTag codec_asf_bmp_tags
[] = {
211 { AV_CODEC_ID_MPEG4
, MKTAG('M', 'P', '4', 'S') },
212 { AV_CODEC_ID_MPEG4
, MKTAG('M', '4', 'S', '2') },
213 { AV_CODEC_ID_MSMPEG4V3
, MKTAG('M', 'P', '4', '3') },
214 { AV_CODEC_ID_NONE
, 0 },
217 #define PREROLL_TIME 3100
219 static void put_guid(AVIOContext
*s
, const ff_asf_guid
*g
)
221 assert(sizeof(*g
) == 16);
222 avio_write(s
, *g
, sizeof(*g
));
225 static void put_str16(AVIOContext
*s
, const char *tag
)
229 AVIOContext
*dyn_buf
;
230 if (avio_open_dyn_buf(&dyn_buf
) < 0)
233 avio_put_str16le(dyn_buf
, tag
);
234 len
= avio_close_dyn_buf(dyn_buf
, &pb
);
236 avio_write(s
, pb
, len
);
240 static int64_t put_header(AVIOContext
*pb
, const ff_asf_guid
*g
)
250 /* update header size */
251 static void end_header(AVIOContext
*pb
, int64_t pos
)
255 pos1
= avio_tell(pb
);
256 avio_seek(pb
, pos
+ 16, SEEK_SET
);
257 avio_wl64(pb
, pos1
- pos
);
258 avio_seek(pb
, pos1
, SEEK_SET
);
261 /* write an asf chunk (only used in streaming case) */
262 static void put_chunk(AVFormatContext
*s
, int type
,
263 int payload_length
, int flags
)
265 ASFContext
*asf
= s
->priv_data
;
266 AVIOContext
*pb
= s
->pb
;
269 length
= payload_length
+ 8;
271 avio_wl16(pb
, length
); // size
272 avio_wl32(pb
, asf
->seqno
); // sequence number
273 avio_wl16(pb
, flags
); // unknown bytes
274 avio_wl16(pb
, length
); // size_confirm
278 /* convert from unix to windows time */
279 static int64_t unix_to_file_time(int ti
)
283 t
= ti
* INT64_C(10000000);
284 t
+= INT64_C(116444736000000000);
288 /* write the header (used two times if non streamed) */
289 static int asf_write_header1(AVFormatContext
*s
, int64_t file_size
,
290 int64_t data_chunk_size
)
292 ASFContext
*asf
= s
->priv_data
;
293 AVIOContext
*pb
= s
->pb
;
294 AVDictionaryEntry
*tags
[5];
295 int header_size
, n
, extra_size
, extra_size2
, wav_extra_size
, file_time
;
299 int64_t header_offset
, cur_pos
, hpos
;
303 ff_metadata_conv(&s
->metadata
, ff_asf_metadata_conv
, NULL
);
305 tags
[0] = av_dict_get(s
->metadata
, "title", NULL
, 0);
306 tags
[1] = av_dict_get(s
->metadata
, "author", NULL
, 0);
307 tags
[2] = av_dict_get(s
->metadata
, "copyright", NULL
, 0);
308 tags
[3] = av_dict_get(s
->metadata
, "comment", NULL
, 0);
309 tags
[4] = av_dict_get(s
->metadata
, "rating", NULL
, 0);
311 duration
= asf
->duration
+ PREROLL_TIME
* 10000;
312 has_title
= tags
[0] || tags
[1] || tags
[2] || tags
[3] || tags
[4];
313 metadata_count
= av_dict_count(s
->metadata
);
316 for (n
= 0; n
< s
->nb_streams
; n
++) {
317 enc
= s
->streams
[n
]->codec
;
319 avpriv_set_pts_info(s
->streams
[n
], 32, 1, 1000); /* 32 bit pts in ms */
321 bit_rate
+= enc
->bit_rate
;
324 if (asf
->is_streamed
) {
325 put_chunk(s
, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
328 put_guid(pb
, &ff_asf_header
);
329 avio_wl64(pb
, -1); /* header length, will be patched after */
330 avio_wl32(pb
, 3 + has_title
+ !!metadata_count
+ s
->nb_streams
); /* number of chunks in header */
331 avio_w8(pb
, 1); /* ??? */
332 avio_w8(pb
, 2); /* ??? */
335 header_offset
= avio_tell(pb
);
336 hpos
= put_header(pb
, &ff_asf_file_header
);
337 put_guid(pb
, &ff_asf_my_guid
);
338 avio_wl64(pb
, file_size
);
340 avio_wl64(pb
, unix_to_file_time(file_time
));
341 avio_wl64(pb
, asf
->nb_packets
); /* number of packets */
342 avio_wl64(pb
, duration
); /* end time stamp (in 100ns units) */
343 avio_wl64(pb
, asf
->duration
); /* duration (in 100ns units) */
344 avio_wl64(pb
, PREROLL_TIME
); /* start time stamp */
345 avio_wl32(pb
, (asf
->is_streamed
|| !pb
->seekable
) ? 3 : 2); /* ??? */
346 avio_wl32(pb
, s
->packet_size
); /* packet size */
347 avio_wl32(pb
, s
->packet_size
); /* packet size */
348 avio_wl32(pb
, bit_rate
); /* Nominal data rate in bps */
349 end_header(pb
, hpos
);
351 /* unknown headers */
352 hpos
= put_header(pb
, &ff_asf_head1_guid
);
353 put_guid(pb
, &ff_asf_head2_guid
);
356 end_header(pb
, hpos
);
358 /* title and other infos */
362 AVIOContext
*dyn_buf
;
364 if (avio_open_dyn_buf(&dyn_buf
) < 0)
365 return AVERROR(ENOMEM
);
367 hpos
= put_header(pb
, &ff_asf_comment_header
);
369 for (n
= 0; n
< FF_ARRAY_ELEMS(tags
); n
++) {
370 len
= tags
[n
] ? avio_put_str16le(dyn_buf
, tags
[n
]->value
) : 0;
373 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
374 avio_write(pb
, buf
, len
);
376 end_header(pb
, hpos
);
378 if (metadata_count
) {
379 AVDictionaryEntry
*tag
= NULL
;
380 hpos
= put_header(pb
, &ff_asf_extended_content_header
);
381 avio_wl16(pb
, metadata_count
);
382 while ((tag
= av_dict_get(s
->metadata
, "", tag
, AV_DICT_IGNORE_SUFFIX
))) {
383 put_str16(pb
, tag
->key
);
385 put_str16(pb
, tag
->value
);
387 end_header(pb
, hpos
);
391 for (n
= 0; n
< s
->nb_streams
; n
++) {
393 // ASFStream *stream = &asf->streams[n];
395 enc
= s
->streams
[n
]->codec
;
396 asf
->streams
[n
].num
= n
+ 1;
397 asf
->streams
[n
].seq
= 0;
399 switch (enc
->codec_type
) {
400 case AVMEDIA_TYPE_AUDIO
:
402 extra_size
= 18 + wav_extra_size
;
406 case AVMEDIA_TYPE_VIDEO
:
407 wav_extra_size
= enc
->extradata_size
;
408 extra_size
= 0x33 + wav_extra_size
;
413 hpos
= put_header(pb
, &ff_asf_stream_header
);
414 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
415 put_guid(pb
, &ff_asf_audio_stream
);
416 put_guid(pb
, &ff_asf_audio_conceal_spread
);
418 put_guid(pb
, &ff_asf_video_stream
);
419 put_guid(pb
, &ff_asf_video_conceal_none
);
421 avio_wl64(pb
, 0); /* ??? */
422 es_pos
= avio_tell(pb
);
423 avio_wl32(pb
, extra_size
); /* wav header len */
424 avio_wl32(pb
, extra_size2
); /* additional data len */
425 avio_wl16(pb
, n
+ 1); /* stream number */
426 avio_wl32(pb
, 0); /* ??? */
428 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
429 /* WAVEFORMATEX header */
430 int wavsize
= ff_put_wav_header(pb
, enc
);
434 if (wavsize
!= extra_size
) {
435 cur_pos
= avio_tell(pb
);
436 avio_seek(pb
, es_pos
, SEEK_SET
);
437 avio_wl32(pb
, wavsize
); /* wav header len */
438 avio_seek(pb
, cur_pos
, SEEK_SET
);
440 /* ERROR Correction */
442 if (enc
->codec_id
== AV_CODEC_ID_ADPCM_G726
|| !enc
->block_align
) {
443 avio_wl16(pb
, 0x0190);
444 avio_wl16(pb
, 0x0190);
446 avio_wl16(pb
, enc
->block_align
);
447 avio_wl16(pb
, enc
->block_align
);
452 avio_wl32(pb
, enc
->width
);
453 avio_wl32(pb
, enc
->height
);
454 avio_w8(pb
, 2); /* ??? */
455 avio_wl16(pb
, 40 + enc
->extradata_size
); /* size */
457 /* BITMAPINFOHEADER header */
458 ff_put_bmp_header(pb
, enc
, ff_codec_bmp_tags
, 1);
460 end_header(pb
, hpos
);
465 hpos
= put_header(pb
, &ff_asf_codec_comment_header
);
466 put_guid(pb
, &ff_asf_codec_comment1_header
);
467 avio_wl32(pb
, s
->nb_streams
);
468 for (n
= 0; n
< s
->nb_streams
; n
++) {
473 AVIOContext
*dyn_buf
;
475 enc
= s
->streams
[n
]->codec
;
476 p
= avcodec_find_encoder(enc
->codec_id
);
478 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
480 else if (enc
->codec_type
== AVMEDIA_TYPE_VIDEO
)
485 if (enc
->codec_id
== AV_CODEC_ID_WMAV2
)
486 desc
= "Windows Media Audio V8";
488 desc
= p
? p
->name
: enc
->codec_name
;
490 if (avio_open_dyn_buf(&dyn_buf
) < 0)
491 return AVERROR(ENOMEM
);
493 avio_put_str16le(dyn_buf
, desc
);
494 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
495 avio_wl16(pb
, len
/ 2); // "number of characters" = length in bytes / 2
497 avio_write(pb
, buf
, len
);
500 avio_wl16(pb
, 0); /* no parameters */
503 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
505 avio_wl16(pb
, enc
->codec_tag
);
508 avio_wl32(pb
, enc
->codec_tag
);
513 end_header(pb
, hpos
);
515 /* patch the header size fields */
517 cur_pos
= avio_tell(pb
);
518 header_size
= cur_pos
- header_offset
;
519 if (asf
->is_streamed
) {
520 header_size
+= 8 + 30 + 50;
522 avio_seek(pb
, header_offset
- 10 - 30, SEEK_SET
);
523 avio_wl16(pb
, header_size
);
524 avio_seek(pb
, header_offset
- 2 - 30, SEEK_SET
);
525 avio_wl16(pb
, header_size
);
527 header_size
-= 8 + 30 + 50;
529 header_size
+= 24 + 6;
530 avio_seek(pb
, header_offset
- 14, SEEK_SET
);
531 avio_wl64(pb
, header_size
);
532 avio_seek(pb
, cur_pos
, SEEK_SET
);
534 /* movie chunk, followed by packets of packet_size */
535 asf
->data_offset
= cur_pos
;
536 put_guid(pb
, &ff_asf_data_header
);
537 avio_wl64(pb
, data_chunk_size
);
538 put_guid(pb
, &ff_asf_my_guid
);
539 avio_wl64(pb
, asf
->nb_packets
); /* nb packets */
540 avio_w8(pb
, 1); /* ??? */
541 avio_w8(pb
, 1); /* ??? */
545 static int asf_write_header(AVFormatContext
*s
)
547 ASFContext
*asf
= s
->priv_data
;
549 s
->packet_size
= PACKET_SIZE
;
552 asf
->last_indexed_pts
= 0;
553 asf
->index_ptr
= av_malloc(sizeof(ASFIndex
) * ASF_INDEX_BLOCK
);
554 asf
->nb_index_memory_alloc
= ASF_INDEX_BLOCK
;
555 asf
->nb_index_count
= 0;
556 asf
->maximum_packet
= 0;
558 /* the data-chunk-size has to be 50, which is data_size - asf->data_offset
559 * at the moment this function is done. It is needed to use asf as
560 * streamable format. */
561 if (asf_write_header1(s
, 0, 50) < 0) {
568 asf
->packet_nb_payloads
= 0;
569 asf
->packet_timestamp_start
= -1;
570 asf
->packet_timestamp_end
= -1;
571 ffio_init_context(&asf
->pb
, asf
->packet_buf
, s
->packet_size
, 1,
572 NULL
, NULL
, NULL
, NULL
);
577 static int asf_write_stream_header(AVFormatContext
*s
)
579 ASFContext
*asf
= s
->priv_data
;
581 asf
->is_streamed
= 1;
583 return asf_write_header(s
);
586 static int put_payload_parsing_info(AVFormatContext
*s
,
587 unsigned sendtime
, unsigned duration
,
588 int nb_payloads
, int padsize
)
590 ASFContext
*asf
= s
->priv_data
;
591 AVIOContext
*pb
= s
->pb
;
593 int64_t start
= avio_tell(pb
);
595 int iLengthTypeFlags
= ASF_PPI_LENGTH_TYPE_FLAGS
;
597 padsize
-= PACKET_HEADER_MIN_SIZE
;
598 if (asf
->multi_payloads_present
)
600 assert(padsize
>= 0);
602 avio_w8(pb
, ASF_PACKET_ERROR_CORRECTION_FLAGS
);
603 for (i
= 0; i
< ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
; i
++)
606 if (asf
->multi_payloads_present
)
607 iLengthTypeFlags
|= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
;
611 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
;
613 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
;
615 avio_w8(pb
, iLengthTypeFlags
);
617 avio_w8(pb
, ASF_PPI_PROPERTY_FLAGS
);
619 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
)
620 avio_wl16(pb
, padsize
- 2);
621 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
)
622 avio_w8(pb
, padsize
- 1);
624 avio_wl32(pb
, sendtime
);
625 avio_wl16(pb
, duration
);
626 if (asf
->multi_payloads_present
)
627 avio_w8(pb
, nb_payloads
| ASF_PAYLOAD_FLAGS
);
629 ppi_size
= avio_tell(pb
) - start
;
634 static void flush_packet(AVFormatContext
*s
)
636 ASFContext
*asf
= s
->priv_data
;
637 int packet_hdr_size
, packet_filled_size
;
639 assert(asf
->packet_timestamp_end
>= asf
->packet_timestamp_start
);
641 if (asf
->is_streamed
)
642 put_chunk(s
, 0x4424, s
->packet_size
, 0);
644 packet_hdr_size
= put_payload_parsing_info(s
,
645 asf
->packet_timestamp_start
,
646 asf
->packet_timestamp_end
-
647 asf
->packet_timestamp_start
,
648 asf
->packet_nb_payloads
,
649 asf
->packet_size_left
);
651 packet_filled_size
= PACKET_SIZE
- asf
->packet_size_left
;
652 assert(packet_hdr_size
<= asf
->packet_size_left
);
653 memset(asf
->packet_buf
+ packet_filled_size
, 0, asf
->packet_size_left
);
655 avio_write(s
->pb
, asf
->packet_buf
, s
->packet_size
- packet_hdr_size
);
659 asf
->packet_nb_payloads
= 0;
660 asf
->packet_timestamp_start
= -1;
661 asf
->packet_timestamp_end
= -1;
662 ffio_init_context(&asf
->pb
, asf
->packet_buf
, s
->packet_size
, 1,
663 NULL
, NULL
, NULL
, NULL
);
666 static void put_payload_header(AVFormatContext
*s
, ASFStream
*stream
,
667 int presentation_time
, int m_obj_size
,
668 int m_obj_offset
, int payload_len
, int flags
)
670 ASFContext
*asf
= s
->priv_data
;
671 AVIOContext
*pb
= &asf
->pb
;
675 if (flags
& AV_PKT_FLAG_KEY
)
676 val
|= ASF_PL_FLAG_KEY_FRAME
;
679 avio_w8(pb
, stream
->seq
); // Media object number
680 avio_wl32(pb
, m_obj_offset
); // Offset Into Media Object
682 // Replicated Data shall be at least 8 bytes long.
683 // The first 4 bytes of data shall contain the
684 // Size of the Media Object that the payload belongs to.
685 // The next 4 bytes of data shall contain the
686 // Presentation Time for the media object that the payload belongs to.
687 avio_w8(pb
, ASF_PAYLOAD_REPLICATED_DATA_LENGTH
);
689 avio_wl32(pb
, m_obj_size
); // Replicated Data - Media Object Size
690 avio_wl32(pb
, presentation_time
); // Replicated Data - Presentation Time
692 if (asf
->multi_payloads_present
) {
693 avio_wl16(pb
, payload_len
); // payload length
697 static void put_frame(AVFormatContext
*s
, ASFStream
*stream
, AVStream
*avst
,
698 int timestamp
, const uint8_t *buf
,
699 int m_obj_size
, int flags
)
701 ASFContext
*asf
= s
->priv_data
;
702 int m_obj_offset
, payload_len
, frag_len1
;
705 while (m_obj_offset
< m_obj_size
) {
706 payload_len
= m_obj_size
- m_obj_offset
;
707 if (asf
->packet_timestamp_start
== -1) {
708 asf
->multi_payloads_present
= (payload_len
< MULTI_PAYLOAD_CONSTANT
);
710 asf
->packet_size_left
= PACKET_SIZE
;
711 if (asf
->multi_payloads_present
) {
712 frag_len1
= MULTI_PAYLOAD_CONSTANT
- 1;
714 frag_len1
= SINGLE_PAYLOAD_DATA_LENGTH
;
716 asf
->packet_timestamp_start
= timestamp
;
719 frag_len1
= asf
->packet_size_left
-
720 PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
-
721 PACKET_HEADER_MIN_SIZE
- 1;
723 if (frag_len1
< payload_len
&&
724 avst
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
730 if (payload_len
> frag_len1
)
731 payload_len
= frag_len1
;
732 else if (payload_len
== (frag_len1
- 1))
733 payload_len
= frag_len1
- 2; // additional byte need to put padding length
735 put_payload_header(s
, stream
, timestamp
+ PREROLL_TIME
,
736 m_obj_size
, m_obj_offset
, payload_len
, flags
);
737 avio_write(&asf
->pb
, buf
, payload_len
);
739 if (asf
->multi_payloads_present
)
740 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
);
742 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD
);
743 asf
->packet_timestamp_end
= timestamp
;
745 asf
->packet_nb_payloads
++;
749 m_obj_offset
+= payload_len
;
752 if (!asf
->multi_payloads_present
)
754 else if (asf
->packet_size_left
<= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
+ PACKET_HEADER_MIN_SIZE
+ 1))
760 static int asf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
762 ASFContext
*asf
= s
->priv_data
;
765 AVCodecContext
*codec
;
766 int64_t packet_st
, pts
;
768 int flags
= pkt
->flags
;
770 codec
= s
->streams
[pkt
->stream_index
]->codec
;
771 stream
= &asf
->streams
[pkt
->stream_index
];
773 if (codec
->codec_type
== AVMEDIA_TYPE_AUDIO
)
774 flags
&= ~AV_PKT_FLAG_KEY
;
776 pts
= (pkt
->pts
!= AV_NOPTS_VALUE
) ? pkt
->pts
: pkt
->dts
;
777 assert(pts
!= AV_NOPTS_VALUE
);
778 duration
= pts
* 10000;
779 asf
->duration
= FFMAX(asf
->duration
, duration
+ pkt
->duration
* 10000);
781 packet_st
= asf
->nb_packets
;
782 put_frame(s
, stream
, s
->streams
[pkt
->stream_index
],
783 pkt
->dts
, pkt
->data
, pkt
->size
, flags
);
786 if ((!asf
->is_streamed
) && (flags
& AV_PKT_FLAG_KEY
)) {
787 start_sec
= (int)(duration
/ INT64_C(10000000));
788 if (start_sec
!= (int)(asf
->last_indexed_pts
/ INT64_C(10000000))) {
789 for (i
= asf
->nb_index_count
; i
< start_sec
; i
++) {
790 if (i
>= asf
->nb_index_memory_alloc
) {
791 asf
->nb_index_memory_alloc
+= ASF_INDEX_BLOCK
;
792 asf
->index_ptr
= (ASFIndex
*)av_realloc(asf
->index_ptr
,
794 asf
->nb_index_memory_alloc
);
797 asf
->index_ptr
[i
].packet_number
= (uint32_t)packet_st
;
798 asf
->index_ptr
[i
].packet_count
= (uint16_t)(asf
->nb_packets
- packet_st
);
799 asf
->maximum_packet
= FFMAX(asf
->maximum_packet
,
800 (uint16_t)(asf
->nb_packets
- packet_st
));
802 asf
->nb_index_count
= start_sec
;
803 asf
->last_indexed_pts
= duration
;
809 static int asf_write_index(AVFormatContext
*s
, ASFIndex
*index
,
810 uint16_t max
, uint32_t count
)
812 AVIOContext
*pb
= s
->pb
;
815 put_guid(pb
, &ff_asf_simple_index_header
);
816 avio_wl64(pb
, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count
);
817 put_guid(pb
, &ff_asf_my_guid
);
818 avio_wl64(pb
, ASF_INDEXED_INTERVAL
);
820 avio_wl32(pb
, count
);
821 for (i
= 0; i
< count
; i
++) {
822 avio_wl32(pb
, index
[i
].packet_number
);
823 avio_wl16(pb
, index
[i
].packet_count
);
829 static int asf_write_trailer(AVFormatContext
*s
)
831 ASFContext
*asf
= s
->priv_data
;
832 int64_t file_size
, data_size
;
834 /* flush the current packet */
835 if (asf
->pb
.buf_ptr
> asf
->pb
.buffer
)
839 data_size
= avio_tell(s
->pb
);
840 if ((!asf
->is_streamed
) && (asf
->nb_index_count
!= 0))
841 asf_write_index(s
, asf
->index_ptr
, asf
->maximum_packet
, asf
->nb_index_count
);
844 if (asf
->is_streamed
|| !s
->pb
->seekable
) {
845 put_chunk(s
, 0x4524, 0, 0); /* end of stream */
847 /* rewrite an updated header */
848 file_size
= avio_tell(s
->pb
);
849 avio_seek(s
->pb
, 0, SEEK_SET
);
850 asf_write_header1(s
, file_size
, data_size
- asf
->data_offset
);
853 av_free(asf
->index_ptr
);
858 AVOutputFormat ff_asf_muxer
= {
860 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
861 .mime_type
= "video/x-ms-asf",
862 .extensions
= "asf,wmv,wma",
863 .priv_data_size
= sizeof(ASFContext
),
864 .audio_codec
= CONFIG_LIBMP3LAME
? AV_CODEC_ID_MP3
: AV_CODEC_ID_MP2
,
865 .video_codec
= AV_CODEC_ID_MSMPEG4V3
,
866 .write_header
= asf_write_header
,
867 .write_packet
= asf_write_packet
,
868 .write_trailer
= asf_write_trailer
,
869 .flags
= AVFMT_GLOBALHEADER
,
870 .codec_tag
= (const AVCodecTag
* const []) {
871 codec_asf_bmp_tags
, ff_codec_bmp_tags
, ff_codec_wav_tags
, 0
874 #endif /* CONFIG_ASF_MUXER */
876 #if CONFIG_ASF_STREAM_MUXER
877 AVOutputFormat ff_asf_stream_muxer
= {
878 .name
= "asf_stream",
879 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
880 .mime_type
= "video/x-ms-asf",
881 .extensions
= "asf,wmv,wma",
882 .priv_data_size
= sizeof(ASFContext
),
883 .audio_codec
= CONFIG_LIBMP3LAME
? AV_CODEC_ID_MP3
: AV_CODEC_ID_MP2
,
884 .video_codec
= AV_CODEC_ID_MSMPEG4V3
,
885 .write_header
= asf_write_stream_header
,
886 .write_packet
= asf_write_packet
,
887 .write_trailer
= asf_write_trailer
,
888 .flags
= AVFMT_GLOBALHEADER
,
889 .codec_tag
= (const AVCodecTag
* const []) {
890 codec_asf_bmp_tags
, ff_codec_bmp_tags
, ff_codec_wav_tags
, 0
893 #endif /* CONFIG_ASF_STREAM_MUXER */