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
22 #include "libavutil/avassert.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/mathematics.h"
26 #include "avio_internal.h"
35 #define ASF_INDEXED_INTERVAL 10000000
36 #define ASF_INDEX_BLOCK (1<<9)
37 #define ASF_PAYLOADS_PER_PACKET 63
39 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
40 #define ASF_PACKET_ERROR_CORRECTION_FLAGS \
41 (ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT | \
42 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE)
44 #if (ASF_PACKET_ERROR_CORRECTION_FLAGS != 0)
45 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 1
47 # define ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE 0
50 #define ASF_PPI_PROPERTY_FLAGS \
51 (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE | \
52 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_IS_DWORD | \
53 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE | \
54 ASF_PL_FLAG_STREAM_NUMBER_LENGTH_FIELD_IS_BYTE)
56 #define ASF_PPI_LENGTH_TYPE_FLAGS 0
58 #define ASF_PAYLOAD_FLAGS ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD
60 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
61 # define ASF_PPI_SEQUENCE_FIELD_SIZE 1
63 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
64 # define ASF_PPI_SEQUENCE_FIELD_SIZE 2
66 #if (ASF_PPI_FLAG_SEQUENCE_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE))
67 # define ASF_PPI_SEQUENCE_FIELD_SIZE 4
69 #ifndef ASF_PPI_SEQUENCE_FIELD_SIZE
70 # define ASF_PPI_SEQUENCE_FIELD_SIZE 0
73 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
74 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 1
76 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
77 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 2
79 #if (ASF_PPI_FLAG_PACKET_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE))
80 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 4
82 #ifndef ASF_PPI_PACKET_LENGTH_FIELD_SIZE
83 # define ASF_PPI_PACKET_LENGTH_FIELD_SIZE 0
86 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
87 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 1
89 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
90 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 2
92 #if (ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_DWORD == (ASF_PPI_LENGTH_TYPE_FLAGS & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE))
93 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 4
95 #ifndef ASF_PPI_PADDING_LENGTH_FIELD_SIZE
96 # define ASF_PPI_PADDING_LENGTH_FIELD_SIZE 0
99 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
100 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 1
102 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
103 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 2
105 #if (ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE))
106 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 4
108 #ifndef ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE
109 # define ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE 0
112 #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))
113 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 1
115 #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))
116 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 2
118 #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))
119 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 4
121 #ifndef ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE
122 # define ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE 0
125 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_BYTE == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
126 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 1
128 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_WORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
129 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 2
131 #if (ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_IS_DWORD == (ASF_PPI_PROPERTY_FLAGS & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE))
132 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 4
134 #ifndef ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE
135 # define ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE 0
138 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_BYTE == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
139 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 1
141 #if (ASF_PL_FLAG_PAYLOAD_LENGTH_FIELD_IS_WORD == (ASF_PAYLOAD_FLAGS & ASF_PL_MASK_PAYLOAD_LENGTH_FIELD_SIZE))
142 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 2
144 #ifndef ASF_PAYLOAD_LENGTH_FIELD_SIZE
145 # define ASF_PAYLOAD_LENGTH_FIELD_SIZE 0
148 #define PACKET_HEADER_MIN_SIZE \
149 (ASF_PACKET_ERROR_CORRECTION_FLAGS_FIELD_SIZE + \
150 ASF_PACKET_ERROR_CORRECTION_DATA_SIZE + \
151 1 + /* Length Type Flags */ \
152 1 + /* Property Flags */ \
153 ASF_PPI_PACKET_LENGTH_FIELD_SIZE + \
154 ASF_PPI_SEQUENCE_FIELD_SIZE + \
155 ASF_PPI_PADDING_LENGTH_FIELD_SIZE + \
156 4 + /* Send Time Field */ \
157 2) /* Duration Field */
159 // Replicated Data shall be at least 8 bytes long.
160 #define ASF_PAYLOAD_REPLICATED_DATA_LENGTH 0x08
162 #define PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \
163 (1 + /* Stream Number */ \
164 ASF_PAYLOAD_MEDIA_OBJECT_NUMBER_FIELD_SIZE + \
165 ASF_PAYLOAD_OFFSET_INTO_MEDIA_OBJECT_FIELD_SIZE + \
166 ASF_PAYLOAD_REPLICATED_DATA_LENGTH_FIELD_SIZE + \
167 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)
177 #define SINGLE_PAYLOAD_DATA_LENGTH \
179 PACKET_HEADER_MIN_SIZE - \
180 PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD)
182 #define MULTI_PAYLOAD_CONSTANT \
184 PACKET_HEADER_MIN_SIZE - \
185 1 - /* Payload Flags */ \
186 2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS)
188 #define DATA_HEADER_SIZE 50
193 ASFStream streams
[128]; ///< it's max number and it's not that big
194 /* non streamed additonnal info */
195 uint64_t nb_packets
; ///< how many packets are there in the file, invalid if broadcasting
196 int64_t duration
; ///< in 100ns units
198 unsigned char multi_payloads_present
;
199 int packet_size_left
;
200 int64_t packet_timestamp_start
;
201 int64_t packet_timestamp_end
;
202 unsigned int packet_nb_payloads
;
203 uint8_t packet_buf
[PACKET_SIZE
];
205 /* only for reading */
206 uint64_t data_offset
; ///< beginning of the first data packet
209 uint32_t nb_index_memory_alloc
;
210 uint16_t maximum_packet
;
211 uint32_t next_packet_number
;
212 uint16_t next_packet_count
;
213 uint64_t next_packet_offset
;
218 static const AVCodecTag codec_asf_bmp_tags
[] = {
219 { AV_CODEC_ID_MPEG4
, MKTAG('M', '4', 'S', '2') },
220 { AV_CODEC_ID_MPEG4
, MKTAG('M', 'P', '4', 'S') },
221 { AV_CODEC_ID_MSMPEG4V3
, MKTAG('M', 'P', '4', '3') },
222 { AV_CODEC_ID_NONE
, 0 },
225 #define PREROLL_TIME 3100
227 static void put_str16(AVIOContext
*s
, const char *tag
)
231 AVIOContext
*dyn_buf
;
232 if (avio_open_dyn_buf(&dyn_buf
) < 0)
235 avio_put_str16le(dyn_buf
, tag
);
236 len
= avio_close_dyn_buf(dyn_buf
, &pb
);
238 avio_write(s
, pb
, len
);
242 static int64_t put_header(AVIOContext
*pb
, const ff_asf_guid
*g
)
252 /* update header size */
253 static void end_header(AVIOContext
*pb
, int64_t pos
)
257 pos1
= avio_tell(pb
);
258 avio_seek(pb
, pos
+ 16, SEEK_SET
);
259 avio_wl64(pb
, pos1
- pos
);
260 avio_seek(pb
, pos1
, SEEK_SET
);
263 /* write an asf chunk (only used in streaming case) */
264 static void put_chunk(AVFormatContext
*s
, int type
,
265 int payload_length
, int flags
)
267 ASFContext
*asf
= s
->priv_data
;
268 AVIOContext
*pb
= s
->pb
;
271 length
= payload_length
+ 8;
273 avio_wl16(pb
, length
); // size
274 avio_wl32(pb
, asf
->seqno
); // sequence number
275 avio_wl16(pb
, flags
); // unknown bytes
276 avio_wl16(pb
, length
); // size_confirm
280 /* convert from unix to windows time */
281 static int64_t unix_to_file_time(int ti
)
285 t
= ti
* INT64_C(10000000);
286 t
+= INT64_C(116444736000000000);
290 static int32_t get_send_time(ASFContext
*asf
, int64_t pres_time
, uint64_t *offset
)
293 int32_t send_time
= 0;
294 *offset
= asf
->data_offset
+ DATA_HEADER_SIZE
;
295 for (i
= 0; i
< asf
->next_start_sec
; i
++) {
296 if (pres_time
<= asf
->index_ptr
[i
].send_time
)
298 send_time
= asf
->index_ptr
[i
].send_time
;
299 *offset
= asf
->index_ptr
[i
].offset
;
302 return send_time
/ 10000;
305 static int asf_write_markers(AVFormatContext
*s
)
307 ASFContext
*asf
= s
->priv_data
;
308 AVIOContext
*pb
= s
->pb
;
310 AVRational scale
= {1, 10000000};
311 int64_t hpos
= put_header(pb
, &ff_asf_marker_header
);
313 ff_put_guid(pb
, &ff_asf_reserved_4
);// ASF spec mandates this reserved value
314 avio_wl32(pb
, s
->nb_chapters
); // markers count
315 avio_wl16(pb
, 0); // ASF spec mandates 0 for this
316 avio_wl16(pb
, 0); // name length 0, no name given
318 for (i
= 0; i
< s
->nb_chapters
; i
++) {
319 AVChapter
*c
= s
->chapters
[i
];
320 AVDictionaryEntry
*t
= av_dict_get(c
->metadata
, "title", NULL
, 0);
321 int64_t pres_time
= av_rescale_q(c
->start
, c
->time_base
, scale
);
323 int32_t send_time
= get_send_time(asf
, pres_time
, &offset
);
326 AVIOContext
*dyn_buf
;
328 if (avio_open_dyn_buf(&dyn_buf
) < 0)
329 return AVERROR(ENOMEM
);
330 avio_put_str16le(dyn_buf
, t
->value
);
331 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
333 avio_wl64(pb
, offset
); // offset of the packet with send_time
334 avio_wl64(pb
, pres_time
+ PREROLL_TIME
* 10000); // presentation time
335 avio_wl16(pb
, 12 + len
); // entry length
336 avio_wl32(pb
, send_time
); // send time
337 avio_wl32(pb
, 0); // flags, should be 0
338 avio_wl32(pb
, len
/ 2); // marker desc length in WCHARS!
340 avio_write(pb
, buf
, len
); // marker desc
344 end_header(pb
, hpos
);
348 /* write the header (used two times if non streamed) */
349 static int asf_write_header1(AVFormatContext
*s
, int64_t file_size
,
350 int64_t data_chunk_size
)
352 ASFContext
*asf
= s
->priv_data
;
353 AVIOContext
*pb
= s
->pb
;
354 AVDictionaryEntry
*tags
[5];
355 int header_size
, n
, extra_size
, extra_size2
, wav_extra_size
, file_time
;
356 int has_title
, has_aspect_ratio
= 0;
359 int64_t header_offset
, cur_pos
, hpos
;
363 ff_metadata_conv(&s
->metadata
, ff_asf_metadata_conv
, NULL
);
365 tags
[0] = av_dict_get(s
->metadata
, "title", NULL
, 0);
366 tags
[1] = av_dict_get(s
->metadata
, "author", NULL
, 0);
367 tags
[2] = av_dict_get(s
->metadata
, "copyright", NULL
, 0);
368 tags
[3] = av_dict_get(s
->metadata
, "comment", NULL
, 0);
369 tags
[4] = av_dict_get(s
->metadata
, "rating", NULL
, 0);
371 duration
= asf
->duration
+ PREROLL_TIME
* 10000;
372 has_title
= tags
[0] || tags
[1] || tags
[2] || tags
[3] || tags
[4];
373 metadata_count
= av_dict_count(s
->metadata
);
376 for (n
= 0; n
< s
->nb_streams
; n
++) {
377 enc
= s
->streams
[n
]->codec
;
379 avpriv_set_pts_info(s
->streams
[n
], 32, 1, 1000); /* 32 bit pts in ms */
381 bit_rate
+= enc
->bit_rate
;
382 if ( enc
->codec_type
== AVMEDIA_TYPE_VIDEO
383 && enc
->sample_aspect_ratio
.num
> 0
384 && enc
->sample_aspect_ratio
.den
> 0)
388 if (asf
->is_streamed
) {
389 put_chunk(s
, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
392 ff_put_guid(pb
, &ff_asf_header
);
393 avio_wl64(pb
, -1); /* header length, will be patched after */
394 avio_wl32(pb
, 3 + has_title
+ !!metadata_count
+ s
->nb_streams
); /* number of chunks in header */
395 avio_w8(pb
, 1); /* ??? */
396 avio_w8(pb
, 2); /* ??? */
399 header_offset
= avio_tell(pb
);
400 hpos
= put_header(pb
, &ff_asf_file_header
);
401 ff_put_guid(pb
, &ff_asf_my_guid
);
402 avio_wl64(pb
, file_size
);
404 avio_wl64(pb
, unix_to_file_time(file_time
));
405 avio_wl64(pb
, asf
->nb_packets
); /* number of packets */
406 avio_wl64(pb
, duration
); /* end time stamp (in 100ns units) */
407 avio_wl64(pb
, asf
->duration
); /* duration (in 100ns units) */
408 avio_wl64(pb
, PREROLL_TIME
); /* start time stamp */
409 avio_wl32(pb
, (asf
->is_streamed
|| !pb
->seekable
) ? 3 : 2); /* ??? */
410 avio_wl32(pb
, s
->packet_size
); /* packet size */
411 avio_wl32(pb
, s
->packet_size
); /* packet size */
412 avio_wl32(pb
, bit_rate
? bit_rate
: -1); /* Maximum data rate in bps */
413 end_header(pb
, hpos
);
415 /* unknown headers */
416 hpos
= put_header(pb
, &ff_asf_head1_guid
);
417 ff_put_guid(pb
, &ff_asf_head2_guid
);
419 if (has_aspect_ratio
) {
421 avio_wl32(pb
, 26 + has_aspect_ratio
* 84);
422 hpos2
= put_header(pb
, &ff_asf_metadata_header
);
423 avio_wl16(pb
, 2 * has_aspect_ratio
);
424 for (n
= 0; n
< s
->nb_streams
; n
++) {
425 enc
= s
->streams
[n
]->codec
;
426 if ( enc
->codec_type
== AVMEDIA_TYPE_VIDEO
427 && enc
->sample_aspect_ratio
.num
> 0
428 && enc
->sample_aspect_ratio
.den
> 0) {
429 AVRational sar
= enc
->sample_aspect_ratio
;
431 // the stream number is set like this below
432 avio_wl16(pb
, n
+ 1);
433 avio_wl16(pb
, 26); // name_len
434 avio_wl16(pb
, 3); // value_type
435 avio_wl32(pb
, 4); // value_len
436 avio_put_str16le(pb
, "AspectRatioX");
437 avio_wl32(pb
, sar
.num
);
439 // the stream number is set like this below
440 avio_wl16(pb
, n
+ 1);
441 avio_wl16(pb
, 26); // name_len
442 avio_wl16(pb
, 3); // value_type
443 avio_wl32(pb
, 4); // value_len
444 avio_put_str16le(pb
, "AspectRatioY");
445 avio_wl32(pb
, sar
.den
);
448 end_header(pb
, hpos2
);
452 end_header(pb
, hpos
);
454 /* title and other infos */
458 AVIOContext
*dyn_buf
;
460 if (avio_open_dyn_buf(&dyn_buf
) < 0)
461 return AVERROR(ENOMEM
);
463 hpos
= put_header(pb
, &ff_asf_comment_header
);
465 for (n
= 0; n
< FF_ARRAY_ELEMS(tags
); n
++) {
466 len
= tags
[n
] ? avio_put_str16le(dyn_buf
, tags
[n
]->value
) : 0;
469 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
470 avio_write(pb
, buf
, len
);
472 end_header(pb
, hpos
);
474 if (metadata_count
) {
475 AVDictionaryEntry
*tag
= NULL
;
476 hpos
= put_header(pb
, &ff_asf_extended_content_header
);
477 avio_wl16(pb
, metadata_count
);
478 while ((tag
= av_dict_get(s
->metadata
, "", tag
, AV_DICT_IGNORE_SUFFIX
))) {
479 put_str16(pb
, tag
->key
);
481 put_str16(pb
, tag
->value
);
483 end_header(pb
, hpos
);
485 /* chapters using ASF markers */
486 if (!asf
->is_streamed
&& s
->nb_chapters
) {
488 if (ret
= asf_write_markers(s
))
492 for (n
= 0; n
< s
->nb_streams
; n
++) {
494 // ASFStream *stream = &asf->streams[n];
496 enc
= s
->streams
[n
]->codec
;
497 asf
->streams
[n
].num
= n
+ 1;
498 asf
->streams
[n
].seq
= 1;
500 switch (enc
->codec_type
) {
501 case AVMEDIA_TYPE_AUDIO
:
503 extra_size
= 18 + wav_extra_size
;
507 case AVMEDIA_TYPE_VIDEO
:
508 wav_extra_size
= enc
->extradata_size
;
509 extra_size
= 0x33 + wav_extra_size
;
514 hpos
= put_header(pb
, &ff_asf_stream_header
);
515 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
516 ff_put_guid(pb
, &ff_asf_audio_stream
);
517 ff_put_guid(pb
, &ff_asf_audio_conceal_spread
);
519 ff_put_guid(pb
, &ff_asf_video_stream
);
520 ff_put_guid(pb
, &ff_asf_video_conceal_none
);
522 avio_wl64(pb
, 0); /* ??? */
523 es_pos
= avio_tell(pb
);
524 avio_wl32(pb
, extra_size
); /* wav header len */
525 avio_wl32(pb
, extra_size2
); /* additional data len */
526 avio_wl16(pb
, n
+ 1); /* stream number */
527 avio_wl32(pb
, 0); /* ??? */
529 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
530 /* WAVEFORMATEX header */
531 int wavsize
= ff_put_wav_header(pb
, enc
, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX
);
535 if (wavsize
!= extra_size
) {
536 cur_pos
= avio_tell(pb
);
537 avio_seek(pb
, es_pos
, SEEK_SET
);
538 avio_wl32(pb
, wavsize
); /* wav header len */
539 avio_seek(pb
, cur_pos
, SEEK_SET
);
541 /* ERROR Correction */
543 if (enc
->codec_id
== AV_CODEC_ID_ADPCM_G726
|| !enc
->block_align
) {
544 avio_wl16(pb
, 0x0190);
545 avio_wl16(pb
, 0x0190);
547 avio_wl16(pb
, enc
->block_align
);
548 avio_wl16(pb
, enc
->block_align
);
553 avio_wl32(pb
, enc
->width
);
554 avio_wl32(pb
, enc
->height
);
555 avio_w8(pb
, 2); /* ??? */
556 avio_wl16(pb
, 40 + enc
->extradata_size
); /* size */
558 /* BITMAPINFOHEADER header */
559 ff_put_bmp_header(pb
, enc
, ff_codec_bmp_tags
, 1, 0);
561 end_header(pb
, hpos
);
566 hpos
= put_header(pb
, &ff_asf_codec_comment_header
);
567 ff_put_guid(pb
, &ff_asf_codec_comment1_header
);
568 avio_wl32(pb
, s
->nb_streams
);
569 for (n
= 0; n
< s
->nb_streams
; n
++) {
570 const AVCodecDescriptor
*codec_desc
;
573 enc
= s
->streams
[n
]->codec
;
574 codec_desc
= avcodec_descriptor_get(enc
->codec_id
);
576 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
578 else if (enc
->codec_type
== AVMEDIA_TYPE_VIDEO
)
583 if (enc
->codec_id
== AV_CODEC_ID_WMAV2
)
584 desc
= "Windows Media Audio V8";
586 desc
= codec_desc
? codec_desc
->name
: NULL
;
589 AVIOContext
*dyn_buf
;
593 if (avio_open_dyn_buf(&dyn_buf
) < 0)
594 return AVERROR(ENOMEM
);
596 avio_put_str16le(dyn_buf
, desc
);
597 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
598 avio_wl16(pb
, len
/ 2); // "number of characters" = length in bytes / 2
600 avio_write(pb
, buf
, len
);
605 avio_wl16(pb
, 0); /* no parameters */
608 if (enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
610 avio_wl16(pb
, enc
->codec_tag
);
613 avio_wl32(pb
, enc
->codec_tag
);
618 end_header(pb
, hpos
);
620 /* patch the header size fields */
622 cur_pos
= avio_tell(pb
);
623 header_size
= cur_pos
- header_offset
;
624 if (asf
->is_streamed
) {
625 header_size
+= 8 + 30 + DATA_HEADER_SIZE
;
627 avio_seek(pb
, header_offset
- 10 - 30, SEEK_SET
);
628 avio_wl16(pb
, header_size
);
629 avio_seek(pb
, header_offset
- 2 - 30, SEEK_SET
);
630 avio_wl16(pb
, header_size
);
632 header_size
-= 8 + 30 + DATA_HEADER_SIZE
;
634 header_size
+= 24 + 6;
635 avio_seek(pb
, header_offset
- 14, SEEK_SET
);
636 avio_wl64(pb
, header_size
);
637 avio_seek(pb
, cur_pos
, SEEK_SET
);
639 /* movie chunk, followed by packets of packet_size */
640 asf
->data_offset
= cur_pos
;
641 ff_put_guid(pb
, &ff_asf_data_header
);
642 avio_wl64(pb
, data_chunk_size
);
643 ff_put_guid(pb
, &ff_asf_my_guid
);
644 avio_wl64(pb
, asf
->nb_packets
); /* nb packets */
645 avio_w8(pb
, 1); /* ??? */
646 avio_w8(pb
, 1); /* ??? */
650 static int asf_write_header(AVFormatContext
*s
)
652 ASFContext
*asf
= s
->priv_data
;
654 s
->packet_size
= PACKET_SIZE
;
655 s
->max_interleave_delta
= 0;
658 asf
->index_ptr
= av_malloc(sizeof(ASFIndex
) * ASF_INDEX_BLOCK
);
659 asf
->nb_index_memory_alloc
= ASF_INDEX_BLOCK
;
660 asf
->maximum_packet
= 0;
662 /* the data-chunk-size has to be 50 (DATA_HEADER_SIZE), which is
663 * data_size - asf->data_offset at the moment this function is done.
664 * It is needed to use asf as a streamable format. */
665 if (asf_write_header1(s
, 0, DATA_HEADER_SIZE
) < 0) {
672 asf
->packet_nb_payloads
= 0;
673 asf
->packet_timestamp_start
= -1;
674 asf
->packet_timestamp_end
= -1;
675 ffio_init_context(&asf
->pb
, asf
->packet_buf
, s
->packet_size
, 1,
676 NULL
, NULL
, NULL
, NULL
);
678 if (s
->avoid_negative_ts
< 0)
679 s
->avoid_negative_ts
= 1;
684 static int asf_write_stream_header(AVFormatContext
*s
)
686 ASFContext
*asf
= s
->priv_data
;
688 asf
->is_streamed
= 1;
690 return asf_write_header(s
);
693 static int put_payload_parsing_info(AVFormatContext
*s
,
694 unsigned sendtime
, unsigned duration
,
695 int nb_payloads
, int padsize
)
697 ASFContext
*asf
= s
->priv_data
;
698 AVIOContext
*pb
= s
->pb
;
700 int64_t start
= avio_tell(pb
);
702 int iLengthTypeFlags
= ASF_PPI_LENGTH_TYPE_FLAGS
;
704 padsize
-= PACKET_HEADER_MIN_SIZE
;
705 if (asf
->multi_payloads_present
)
707 av_assert0(padsize
>= 0);
709 avio_w8(pb
, ASF_PACKET_ERROR_CORRECTION_FLAGS
);
710 for (i
= 0; i
< ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
; i
++)
713 if (asf
->multi_payloads_present
)
714 iLengthTypeFlags
|= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
;
718 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
;
720 iLengthTypeFlags
|= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
;
722 avio_w8(pb
, iLengthTypeFlags
);
724 avio_w8(pb
, ASF_PPI_PROPERTY_FLAGS
);
726 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD
)
727 avio_wl16(pb
, padsize
- 2);
728 if (iLengthTypeFlags
& ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE
)
729 avio_w8(pb
, padsize
- 1);
731 avio_wl32(pb
, sendtime
);
732 avio_wl16(pb
, duration
);
733 if (asf
->multi_payloads_present
)
734 avio_w8(pb
, nb_payloads
| ASF_PAYLOAD_FLAGS
);
736 ppi_size
= avio_tell(pb
) - start
;
741 static void flush_packet(AVFormatContext
*s
)
743 ASFContext
*asf
= s
->priv_data
;
744 int packet_hdr_size
, packet_filled_size
;
746 av_assert0(asf
->packet_timestamp_end
>= asf
->packet_timestamp_start
);
748 if (asf
->is_streamed
)
749 put_chunk(s
, 0x4424, s
->packet_size
, 0);
751 packet_hdr_size
= put_payload_parsing_info(s
,
752 asf
->packet_timestamp_start
,
753 asf
->packet_timestamp_end
- asf
->packet_timestamp_start
,
754 asf
->packet_nb_payloads
,
755 asf
->packet_size_left
);
757 packet_filled_size
= PACKET_SIZE
- asf
->packet_size_left
;
758 av_assert0(packet_hdr_size
<= asf
->packet_size_left
);
759 memset(asf
->packet_buf
+ packet_filled_size
, 0, asf
->packet_size_left
);
761 avio_write(s
->pb
, asf
->packet_buf
, s
->packet_size
- packet_hdr_size
);
765 asf
->packet_nb_payloads
= 0;
766 asf
->packet_timestamp_start
= -1;
767 asf
->packet_timestamp_end
= -1;
768 ffio_init_context(&asf
->pb
, asf
->packet_buf
, s
->packet_size
, 1,
769 NULL
, NULL
, NULL
, NULL
);
772 static void put_payload_header(AVFormatContext
*s
, ASFStream
*stream
,
773 int64_t presentation_time
, int m_obj_size
,
774 int m_obj_offset
, int payload_len
, int flags
)
776 ASFContext
*asf
= s
->priv_data
;
777 AVIOContext
*pb
= &asf
->pb
;
781 if (flags
& AV_PKT_FLAG_KEY
)
782 val
|= ASF_PL_FLAG_KEY_FRAME
;
785 avio_w8(pb
, stream
->seq
); // Media object number
786 avio_wl32(pb
, m_obj_offset
); // Offset Into Media Object
788 // Replicated Data shall be at least 8 bytes long.
789 // The first 4 bytes of data shall contain the
790 // Size of the Media Object that the payload belongs to.
791 // The next 4 bytes of data shall contain the
792 // Presentation Time for the media object that the payload belongs to.
793 avio_w8(pb
, ASF_PAYLOAD_REPLICATED_DATA_LENGTH
);
795 avio_wl32(pb
, m_obj_size
); // Replicated Data - Media Object Size
796 avio_wl32(pb
, (uint32_t) presentation_time
); // Replicated Data - Presentation Time
798 if (asf
->multi_payloads_present
) {
799 avio_wl16(pb
, payload_len
); // payload length
803 static void put_frame(AVFormatContext
*s
, ASFStream
*stream
, AVStream
*avst
,
804 int64_t timestamp
, const uint8_t *buf
,
805 int m_obj_size
, int flags
)
807 ASFContext
*asf
= s
->priv_data
;
808 int m_obj_offset
, payload_len
, frag_len1
;
811 while (m_obj_offset
< m_obj_size
) {
812 payload_len
= m_obj_size
- m_obj_offset
;
813 if (asf
->packet_timestamp_start
== -1) {
814 asf
->multi_payloads_present
= (payload_len
< MULTI_PAYLOAD_CONSTANT
);
816 asf
->packet_size_left
= PACKET_SIZE
;
817 if (asf
->multi_payloads_present
) {
818 frag_len1
= MULTI_PAYLOAD_CONSTANT
- 1;
820 frag_len1
= SINGLE_PAYLOAD_DATA_LENGTH
;
822 asf
->packet_timestamp_start
= timestamp
;
825 frag_len1
= asf
->packet_size_left
-
826 PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
-
827 PACKET_HEADER_MIN_SIZE
- 1;
829 if (frag_len1
< payload_len
&&
830 avst
->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
836 if (payload_len
> frag_len1
)
837 payload_len
= frag_len1
;
838 else if (payload_len
== (frag_len1
- 1))
839 payload_len
= frag_len1
- 2; // additional byte need to put padding length
841 put_payload_header(s
, stream
, timestamp
+ PREROLL_TIME
,
842 m_obj_size
, m_obj_offset
, payload_len
, flags
);
843 avio_write(&asf
->pb
, buf
, payload_len
);
845 if (asf
->multi_payloads_present
)
846 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
);
848 asf
->packet_size_left
-= (payload_len
+ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD
);
849 asf
->packet_timestamp_end
= timestamp
;
851 asf
->packet_nb_payloads
++;
855 m_obj_offset
+= payload_len
;
858 if (!asf
->multi_payloads_present
)
860 else if (asf
->packet_size_left
<= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS
+ PACKET_HEADER_MIN_SIZE
+ 1))
862 else if (asf
->packet_nb_payloads
== ASF_PAYLOADS_PER_PACKET
)
868 static int update_index(AVFormatContext
*s
, int start_sec
,
869 uint32_t packet_number
, uint16_t packet_count
,
870 uint64_t packet_offset
)
872 ASFContext
*asf
= s
->priv_data
;
874 if (start_sec
> asf
->next_start_sec
) {
877 if (!asf
->next_start_sec
) {
878 asf
->next_packet_number
= packet_number
;
879 asf
->next_packet_count
= packet_count
;
880 asf
->next_packet_offset
= packet_offset
;
883 if (start_sec
> asf
->nb_index_memory_alloc
) {
885 asf
->nb_index_memory_alloc
= (start_sec
+ ASF_INDEX_BLOCK
) & ~(ASF_INDEX_BLOCK
- 1);
886 if ((err
= av_reallocp_array(&asf
->index_ptr
,
887 asf
->nb_index_memory_alloc
,
888 sizeof(*asf
->index_ptr
))) < 0) {
889 asf
->nb_index_memory_alloc
= 0;
893 for (i
= asf
->next_start_sec
; i
< start_sec
; i
++) {
894 asf
->index_ptr
[i
].packet_number
= asf
->next_packet_number
;
895 asf
->index_ptr
[i
].packet_count
= asf
->next_packet_count
;
896 asf
->index_ptr
[i
].send_time
= asf
->next_start_sec
* INT64_C(10000000);
897 asf
->index_ptr
[i
].offset
= asf
->next_packet_offset
;
901 asf
->maximum_packet
= FFMAX(asf
->maximum_packet
, packet_count
);
902 asf
->next_packet_number
= packet_number
;
903 asf
->next_packet_count
= packet_count
;
904 asf
->next_packet_offset
= packet_offset
;
905 asf
->next_start_sec
= start_sec
;
910 static int asf_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
912 ASFContext
*asf
= s
->priv_data
;
913 AVIOContext
*pb
= s
->pb
;
915 AVCodecContext
*codec
;
916 uint32_t packet_number
;
919 int flags
= pkt
->flags
;
921 uint64_t offset
= avio_tell(pb
);
923 codec
= s
->streams
[pkt
->stream_index
]->codec
;
924 stream
= &asf
->streams
[pkt
->stream_index
];
926 if (codec
->codec_type
== AVMEDIA_TYPE_AUDIO
)
927 flags
&= ~AV_PKT_FLAG_KEY
;
929 pts
= (pkt
->pts
!= AV_NOPTS_VALUE
) ? pkt
->pts
: pkt
->dts
;
930 av_assert0(pts
!= AV_NOPTS_VALUE
);
932 asf
->duration
= FFMAX(asf
->duration
, pts
+ pkt
->duration
* 10000);
934 packet_number
= asf
->nb_packets
;
935 put_frame(s
, stream
, s
->streams
[pkt
->stream_index
],
936 pkt
->dts
, pkt
->data
, pkt
->size
, flags
);
938 start_sec
= (int)((PREROLL_TIME
* 10000 + pts
+ ASF_INDEXED_INTERVAL
- 1)
939 / ASF_INDEXED_INTERVAL
);
942 if ((!asf
->is_streamed
) && (flags
& AV_PKT_FLAG_KEY
)) {
943 uint16_t packet_count
= asf
->nb_packets
- packet_number
;
944 ret
= update_index(s
, start_sec
, packet_number
, packet_count
, offset
);
948 asf
->end_sec
= start_sec
;
953 static int asf_write_index(AVFormatContext
*s
, const ASFIndex
*index
,
954 uint16_t max
, uint32_t count
)
956 AVIOContext
*pb
= s
->pb
;
959 ff_put_guid(pb
, &ff_asf_simple_index_header
);
960 avio_wl64(pb
, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count
);
961 ff_put_guid(pb
, &ff_asf_my_guid
);
962 avio_wl64(pb
, ASF_INDEXED_INTERVAL
);
964 avio_wl32(pb
, count
);
965 for (i
= 0; i
< count
; i
++) {
966 avio_wl32(pb
, index
[i
].packet_number
);
967 avio_wl16(pb
, index
[i
].packet_count
);
973 static int asf_write_trailer(AVFormatContext
*s
)
975 ASFContext
*asf
= s
->priv_data
;
976 int64_t file_size
, data_size
;
979 /* flush the current packet */
980 if (asf
->pb
.buf_ptr
> asf
->pb
.buffer
)
984 data_size
= avio_tell(s
->pb
);
985 if (!asf
->is_streamed
&& asf
->next_start_sec
) {
986 if ((ret
= update_index(s
, asf
->end_sec
+ 1, 0, 0, 0)) < 0)
988 asf_write_index(s
, asf
->index_ptr
, asf
->maximum_packet
, asf
->next_start_sec
);
992 if (asf
->is_streamed
|| !s
->pb
->seekable
) {
993 put_chunk(s
, 0x4524, 0, 0); /* end of stream */
995 /* rewrite an updated header */
996 file_size
= avio_tell(s
->pb
);
997 avio_seek(s
->pb
, 0, SEEK_SET
);
998 asf_write_header1(s
, file_size
, data_size
- asf
->data_offset
);
1001 av_freep(&asf
->index_ptr
);
1005 #if CONFIG_ASF_MUXER
1006 AVOutputFormat ff_asf_muxer
= {
1008 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1009 .mime_type
= "video/x-ms-asf",
1010 .extensions
= "asf,wmv,wma",
1011 .priv_data_size
= sizeof(ASFContext
),
1012 .audio_codec
= AV_CODEC_ID_WMAV2
,
1013 .video_codec
= AV_CODEC_ID_MSMPEG4V3
,
1014 .write_header
= asf_write_header
,
1015 .write_packet
= asf_write_packet
,
1016 .write_trailer
= asf_write_trailer
,
1017 .flags
= AVFMT_GLOBALHEADER
,
1018 .codec_tag
= (const AVCodecTag
* const []) {
1019 codec_asf_bmp_tags
, ff_codec_bmp_tags
, ff_codec_wav_tags
, 0
1022 #endif /* CONFIG_ASF_MUXER */
1024 #if CONFIG_ASF_STREAM_MUXER
1025 AVOutputFormat ff_asf_stream_muxer
= {
1026 .name
= "asf_stream",
1027 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1028 .mime_type
= "video/x-ms-asf",
1029 .extensions
= "asf,wmv,wma",
1030 .priv_data_size
= sizeof(ASFContext
),
1031 .audio_codec
= AV_CODEC_ID_WMAV2
,
1032 .video_codec
= AV_CODEC_ID_MSMPEG4V3
,
1033 .write_header
= asf_write_stream_header
,
1034 .write_packet
= asf_write_packet
,
1035 .write_trailer
= asf_write_trailer
,
1036 .flags
= AVFMT_GLOBALHEADER
,
1037 .codec_tag
= (const AVCodecTag
* const []) {
1038 codec_asf_bmp_tags
, ff_codec_bmp_tags
, ff_codec_wav_tags
, 0
1041 #endif /* CONFIG_ASF_STREAM_MUXER */