2 * ASF compatible demuxer
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
24 #include "libavutil/attributes.h"
25 #include "libavutil/avassert.h"
26 #include "libavutil/avstring.h"
27 #include "libavutil/bswap.h"
28 #include "libavutil/common.h"
29 #include "libavutil/dict.h"
30 #include "libavutil/mathematics.h"
31 #include "libavutil/opt.h"
33 #include "avio_internal.h"
34 #include "avlanguage.h"
43 int asfid2avid
[128]; ///< conversion table from asf ID 2 AVStream ID
44 ASFStream streams
[128]; ///< it's max number and it's not that big
45 uint32_t stream_bitrates
[128]; ///< max number of streams, bitrate for each (for streaming)
47 char stream_languages
[128][6]; ///< max number of streams, language for each (RFC1766, e.g. en-US)
48 /* non streamed additonnal info */
51 /* only for reading */
52 uint64_t data_offset
; ///< beginning of the first data packet
53 uint64_t data_object_offset
; ///< data object offset (excl. GUID & size)
54 uint64_t data_object_size
; ///< size of the data object
62 int packet_segsizetype
;
65 int packet_replic_size
;
68 unsigned int packet_frag_offset
;
69 unsigned int packet_frag_size
;
70 int64_t packet_frag_timestamp
;
71 int packet_multi_size
;
73 int packet_time_delta
;
74 int packet_time_start
;
79 ASFStream
*asf_st
; ///< currently decoded stream
84 static const AVOption options
[] = {
85 { "no_resync_search", "Don't try to resynchronize by looking for a certain optional start code", offsetof(ASFContext
, no_resync_search
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM
},
89 static const AVClass asf_class
= {
90 .class_name
= "asf demuxer",
91 .item_name
= av_default_item_name
,
93 .version
= LIBAVUTIL_VERSION_INT
,
99 #define ASF_MAX_STREAMS 127
100 #define FRAME_HEADER_SIZE 17
101 // Fix Me! FRAME_HEADER_SIZE may be different.
103 static const ff_asf_guid index_guid
= {
104 0x90, 0x08, 0x00, 0x33, 0xb1, 0xe5, 0xcf, 0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb
108 static const ff_asf_guid stream_bitrate_guid
= { /* (http://get.to/sdp) */
109 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
112 #define PRINT_IF_GUID(g, cmp) \
113 if (!ff_guidcmp(g, &cmp)) \
114 av_dlog(NULL, "(GUID: %s) ", # cmp)
116 static void print_guid(ff_asf_guid
*g
)
119 PRINT_IF_GUID(g
, ff_asf_header
);
120 else PRINT_IF_GUID(g
, ff_asf_file_header
);
121 else PRINT_IF_GUID(g
, ff_asf_stream_header
);
122 else PRINT_IF_GUID(g
, ff_asf_audio_stream
);
123 else PRINT_IF_GUID(g
, ff_asf_audio_conceal_none
);
124 else PRINT_IF_GUID(g
, ff_asf_video_stream
);
125 else PRINT_IF_GUID(g
, ff_asf_video_conceal_none
);
126 else PRINT_IF_GUID(g
, ff_asf_command_stream
);
127 else PRINT_IF_GUID(g
, ff_asf_comment_header
);
128 else PRINT_IF_GUID(g
, ff_asf_codec_comment_header
);
129 else PRINT_IF_GUID(g
, ff_asf_codec_comment1_header
);
130 else PRINT_IF_GUID(g
, ff_asf_data_header
);
131 else PRINT_IF_GUID(g
, index_guid
);
132 else PRINT_IF_GUID(g
, ff_asf_head1_guid
);
133 else PRINT_IF_GUID(g
, ff_asf_head2_guid
);
134 else PRINT_IF_GUID(g
, ff_asf_my_guid
);
135 else PRINT_IF_GUID(g
, ff_asf_ext_stream_header
);
136 else PRINT_IF_GUID(g
, ff_asf_extended_content_header
);
137 else PRINT_IF_GUID(g
, ff_asf_ext_stream_embed_stream_header
);
138 else PRINT_IF_GUID(g
, ff_asf_ext_stream_audio_stream
);
139 else PRINT_IF_GUID(g
, ff_asf_metadata_header
);
140 else PRINT_IF_GUID(g
, ff_asf_metadata_library_header
);
141 else PRINT_IF_GUID(g
, ff_asf_marker_header
);
142 else PRINT_IF_GUID(g
, stream_bitrate_guid
);
143 else PRINT_IF_GUID(g
, ff_asf_language_guid
);
145 av_dlog(NULL
, "(GUID: unknown) ");
146 for (i
= 0; i
< 16; i
++)
147 av_dlog(NULL
, " 0x%02x,", (*g
)[i
]);
148 av_dlog(NULL
, "}\n");
152 #define print_guid(g)
155 static int asf_probe(AVProbeData
*pd
)
157 /* check file header */
158 if (!ff_guidcmp(pd
->buf
, &ff_asf_header
))
159 return AVPROBE_SCORE_MAX
;
164 /* size of type 2 (BOOL) is 32bit for "Extended Content Description Object"
165 * but 16 bit for "Metadata Object" and "Metadata Library Object" */
166 static int get_value(AVIOContext
*pb
, int type
, int type2_size
)
170 return (type2_size
== 32) ?
avio_rl32(pb
) : avio_rl16(pb
);
172 return avio_rl32(pb
);
174 return avio_rl64(pb
);
176 return avio_rl16(pb
);
182 /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
183 * but in reality this is only loosely similar */
184 static int asf_read_picture(AVFormatContext
*s
, int len
)
186 AVPacket pkt
= { 0 };
187 const CodecMime
*mime
= ff_id3v2_mime_tags
;
188 enum AVCodecID id
= AV_CODEC_ID_NONE
;
190 uint8_t *desc
= NULL
;
192 int ret
, type
, picsize
, desc_len
;
194 /* type + picsize + mime + desc */
195 if (len
< 1 + 4 + 2 + 2) {
196 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture size: %d.\n", len
);
197 return AVERROR_INVALIDDATA
;
201 type
= avio_r8(s
->pb
);
203 if (type
>= FF_ARRAY_ELEMS(ff_id3v2_picture_types
) || type
< 0) {
204 av_log(s
, AV_LOG_WARNING
, "Unknown attached picture type: %d.\n", type
);
208 /* picture data size */
209 picsize
= avio_rl32(s
->pb
);
212 /* picture MIME type */
213 len
-= avio_get_str16le(s
->pb
, len
, mimetype
, sizeof(mimetype
));
214 while (mime
->id
!= AV_CODEC_ID_NONE
) {
215 if (!strncmp(mime
->str
, mimetype
, sizeof(mimetype
))) {
221 if (id
== AV_CODEC_ID_NONE
) {
222 av_log(s
, AV_LOG_ERROR
, "Unknown attached picture mimetype: %s.\n",
227 if (picsize
>= len
) {
228 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture data size: %d >= %d.\n",
230 return AVERROR_INVALIDDATA
;
233 /* picture description */
234 desc_len
= (len
- picsize
) * 2 + 1;
235 desc
= av_malloc(desc_len
);
237 return AVERROR(ENOMEM
);
238 len
-= avio_get_str16le(s
->pb
, len
- picsize
, desc
, desc_len
);
240 ret
= av_get_packet(s
->pb
, &pkt
, picsize
);
244 st
= avformat_new_stream(s
, NULL
);
246 ret
= AVERROR(ENOMEM
);
249 st
->disposition
|= AV_DISPOSITION_ATTACHED_PIC
;
250 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
251 st
->codec
->codec_id
= id
;
252 st
->attached_pic
= pkt
;
253 st
->attached_pic
.stream_index
= st
->index
;
254 st
->attached_pic
.flags
|= AV_PKT_FLAG_KEY
;
257 av_dict_set(&st
->metadata
, "title", desc
, AV_DICT_DONT_STRDUP_VAL
);
261 av_dict_set(&st
->metadata
, "comment", ff_id3v2_picture_types
[type
], 0);
267 av_free_packet(&pkt
);
271 static void get_id3_tag(AVFormatContext
*s
, int len
)
273 ID3v2ExtraMeta
*id3v2_extra_meta
= NULL
;
275 ff_id3v2_read(s
, ID3v2_DEFAULT_MAGIC
, &id3v2_extra_meta
);
276 if (id3v2_extra_meta
)
277 ff_id3v2_parse_apic(s
, &id3v2_extra_meta
);
278 ff_id3v2_free_extra_meta(&id3v2_extra_meta
);
281 static void get_tag(AVFormatContext
*s
, const char *key
, int type
, int len
, int type2_size
)
284 int64_t off
= avio_tell(s
->pb
);
286 if ((unsigned)len
>= (UINT_MAX
- 1) / 2)
289 value
= av_malloc(2 * len
+ 1);
293 if (type
== 0) { // UTF16-LE
294 avio_get_str16le(s
->pb
, len
, value
, 2 * len
+ 1);
295 } else if (type
== 1) { // byte array
296 if (!strcmp(key
, "WM/Picture")) { // handle cover art
297 asf_read_picture(s
, len
);
298 } else if (!strcmp(key
, "ID3")) { // handle ID3 tag
301 av_log(s
, AV_LOG_VERBOSE
, "Unsupported byte array in tag %s.\n", key
);
304 } else if (type
> 1 && type
<= 5) { // boolean or DWORD or QWORD or WORD
305 uint64_t num
= get_value(s
->pb
, type
, type2_size
);
306 snprintf(value
, len
, "%"PRIu64
, num
);
307 } else if (type
== 6) { // (don't) handle GUID
308 av_log(s
, AV_LOG_DEBUG
, "Unsupported GUID value in tag %s.\n", key
);
311 av_log(s
, AV_LOG_DEBUG
,
312 "Unsupported value type %d in tag %s.\n", type
, key
);
316 av_dict_set(&s
->metadata
, key
, value
, 0);
320 avio_seek(s
->pb
, off
+ len
, SEEK_SET
);
323 static int asf_read_file_properties(AVFormatContext
*s
, int64_t size
)
325 ASFContext
*asf
= s
->priv_data
;
326 AVIOContext
*pb
= s
->pb
;
328 ff_get_guid(pb
, &asf
->hdr
.guid
);
329 asf
->hdr
.file_size
= avio_rl64(pb
);
330 asf
->hdr
.create_time
= avio_rl64(pb
);
331 avio_rl64(pb
); /* number of packets */
332 asf
->hdr
.play_time
= avio_rl64(pb
);
333 asf
->hdr
.send_time
= avio_rl64(pb
);
334 asf
->hdr
.preroll
= avio_rl32(pb
);
335 asf
->hdr
.ignore
= avio_rl32(pb
);
336 asf
->hdr
.flags
= avio_rl32(pb
);
337 asf
->hdr
.min_pktsize
= avio_rl32(pb
);
338 asf
->hdr
.max_pktsize
= avio_rl32(pb
);
339 if (asf
->hdr
.min_pktsize
>= (1U << 29))
340 return AVERROR_INVALIDDATA
;
341 asf
->hdr
.max_bitrate
= avio_rl32(pb
);
342 s
->packet_size
= asf
->hdr
.max_pktsize
;
347 static int asf_read_stream_properties(AVFormatContext
*s
, int64_t size
)
349 ASFContext
*asf
= s
->priv_data
;
350 AVIOContext
*pb
= s
->pb
;
354 enum AVMediaType type
;
355 int type_specific_size
, sizeX
;
357 int64_t pos1
, pos2
, start_time
;
358 int test_for_ext_stream_audio
, is_dvr_ms_audio
= 0;
360 if (s
->nb_streams
== ASF_MAX_STREAMS
) {
361 av_log(s
, AV_LOG_ERROR
, "too many streams\n");
362 return AVERROR(EINVAL
);
365 pos1
= avio_tell(pb
);
367 st
= avformat_new_stream(s
, NULL
);
369 return AVERROR(ENOMEM
);
370 avpriv_set_pts_info(st
, 32, 1, 1000); /* 32 bit pts in ms */
371 asf_st
= av_mallocz(sizeof(ASFStream
));
373 return AVERROR(ENOMEM
);
374 st
->priv_data
= asf_st
;
376 start_time
= asf
->hdr
.preroll
;
378 asf_st
->stream_language_index
= 128; // invalid stream index means no language info
380 if (!(asf
->hdr
.flags
& 0x01)) { // if we aren't streaming...
381 st
->duration
= asf
->hdr
.play_time
/
382 (10000000 / 1000) - start_time
;
386 test_for_ext_stream_audio
= 0;
387 if (!ff_guidcmp(&g
, &ff_asf_audio_stream
)) {
388 type
= AVMEDIA_TYPE_AUDIO
;
389 } else if (!ff_guidcmp(&g
, &ff_asf_video_stream
)) {
390 type
= AVMEDIA_TYPE_VIDEO
;
391 } else if (!ff_guidcmp(&g
, &ff_asf_jfif_media
)) {
392 type
= AVMEDIA_TYPE_VIDEO
;
393 st
->codec
->codec_id
= AV_CODEC_ID_MJPEG
;
394 } else if (!ff_guidcmp(&g
, &ff_asf_command_stream
)) {
395 type
= AVMEDIA_TYPE_DATA
;
396 } else if (!ff_guidcmp(&g
, &ff_asf_ext_stream_embed_stream_header
)) {
397 test_for_ext_stream_audio
= 1;
398 type
= AVMEDIA_TYPE_UNKNOWN
;
403 avio_skip(pb
, 8); /* total_size */
404 type_specific_size
= avio_rl32(pb
);
406 st
->id
= avio_rl16(pb
) & 0x7f; /* stream id */
407 // mapping of asf ID to AV stream ID;
408 asf
->asfid2avid
[st
->id
] = s
->nb_streams
- 1;
412 if (test_for_ext_stream_audio
) {
414 if (!ff_guidcmp(&g
, &ff_asf_ext_stream_audio_stream
)) {
415 type
= AVMEDIA_TYPE_AUDIO
;
426 st
->codec
->codec_type
= type
;
427 if (type
== AVMEDIA_TYPE_AUDIO
) {
428 int ret
= ff_get_wav_header(pb
, st
->codec
, type_specific_size
);
431 if (is_dvr_ms_audio
) {
432 // codec_id and codec_tag are unreliable in dvr_ms
433 // files. Set them later by probing stream.
434 st
->codec
->codec_id
= AV_CODEC_ID_PROBE
;
435 st
->codec
->codec_tag
= 0;
437 if (st
->codec
->codec_id
== AV_CODEC_ID_AAC
)
438 st
->need_parsing
= AVSTREAM_PARSE_NONE
;
440 st
->need_parsing
= AVSTREAM_PARSE_FULL
;
441 /* We have to init the frame size at some point .... */
442 pos2
= avio_tell(pb
);
443 if (size
>= (pos2
+ 8 - pos1
+ 24)) {
444 asf_st
->ds_span
= avio_r8(pb
);
445 asf_st
->ds_packet_size
= avio_rl16(pb
);
446 asf_st
->ds_chunk_size
= avio_rl16(pb
);
447 avio_rl16(pb
); // ds_data_size
448 avio_r8(pb
); // ds_silence_data
450 if (asf_st
->ds_span
> 1) {
451 if (!asf_st
->ds_chunk_size
||
452 (asf_st
->ds_packet_size
/ asf_st
->ds_chunk_size
<= 1) ||
453 asf_st
->ds_packet_size
% asf_st
->ds_chunk_size
)
454 asf_st
->ds_span
= 0; // disable descrambling
456 } else if (type
== AVMEDIA_TYPE_VIDEO
&&
457 size
- (avio_tell(pb
) - pos1
+ 24) >= 51) {
461 avio_rl16(pb
); /* size */
462 sizeX
= avio_rl32(pb
); /* size */
463 st
->codec
->width
= avio_rl32(pb
);
464 st
->codec
->height
= avio_rl32(pb
);
465 /* not available for asf */
466 avio_rl16(pb
); /* panes */
467 st
->codec
->bits_per_coded_sample
= avio_rl16(pb
); /* depth */
468 tag1
= avio_rl32(pb
);
471 st
->codec
->extradata_size
= sizeX
- 40;
472 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+
473 FF_INPUT_BUFFER_PADDING_SIZE
);
474 avio_read(pb
, st
->codec
->extradata
, st
->codec
->extradata_size
);
477 /* Extract palette from extradata if bpp <= 8 */
478 /* This code assumes that extradata contains only palette */
479 /* This is true for all paletted codecs implemented in libavcodec */
480 if (st
->codec
->extradata_size
&& (st
->codec
->bits_per_coded_sample
<= 8)) {
483 for (i
= 0; i
< FFMIN(st
->codec
->extradata_size
, AVPALETTE_SIZE
) / 4; i
++)
484 asf_st
->palette
[i
] = av_bswap32(((uint32_t *)st
->codec
->extradata
)[i
]);
486 memcpy(asf_st
->palette
, st
->codec
->extradata
,
487 FFMIN(st
->codec
->extradata_size
, AVPALETTE_SIZE
));
489 asf_st
->palette_changed
= 1;
492 st
->codec
->codec_tag
= tag1
;
493 st
->codec
->codec_id
= ff_codec_get_id(ff_codec_bmp_tags
, tag1
);
494 if (tag1
== MKTAG('D', 'V', 'R', ' ')) {
495 st
->need_parsing
= AVSTREAM_PARSE_FULL
;
496 /* issue658 contains wrong w/h and MS even puts a fake seq header
497 * with wrong w/h in extradata while a correct one is in the stream.
498 * maximum lameness */
500 st
->codec
->height
= 0;
501 av_freep(&st
->codec
->extradata
);
502 st
->codec
->extradata_size
= 0;
504 if (st
->codec
->codec_id
== AV_CODEC_ID_H264
)
505 st
->need_parsing
= AVSTREAM_PARSE_FULL_ONCE
;
507 pos2
= avio_tell(pb
);
508 avio_skip(pb
, size
- (pos2
- pos1
+ 24));
513 static int asf_read_ext_stream_properties(AVFormatContext
*s
, int64_t size
)
515 ASFContext
*asf
= s
->priv_data
;
516 AVIOContext
*pb
= s
->pb
;
518 int ext_len
, payload_ext_ct
, stream_ct
, i
;
519 uint32_t leak_rate
, stream_num
;
520 unsigned int stream_languageid_index
;
522 avio_rl64(pb
); // starttime
523 avio_rl64(pb
); // endtime
524 leak_rate
= avio_rl32(pb
); // leak-datarate
525 avio_rl32(pb
); // bucket-datasize
526 avio_rl32(pb
); // init-bucket-fullness
527 avio_rl32(pb
); // alt-leak-datarate
528 avio_rl32(pb
); // alt-bucket-datasize
529 avio_rl32(pb
); // alt-init-bucket-fullness
530 avio_rl32(pb
); // max-object-size
531 avio_rl32(pb
); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
532 stream_num
= avio_rl16(pb
); // stream-num
534 stream_languageid_index
= avio_rl16(pb
); // stream-language-id-index
535 if (stream_num
< 128)
536 asf
->streams
[stream_num
].stream_language_index
= stream_languageid_index
;
538 avio_rl64(pb
); // avg frametime in 100ns units
539 stream_ct
= avio_rl16(pb
); // stream-name-count
540 payload_ext_ct
= avio_rl16(pb
); // payload-extension-system-count
542 if (stream_num
< 128)
543 asf
->stream_bitrates
[stream_num
] = leak_rate
;
545 for (i
= 0; i
< stream_ct
; i
++) {
547 ext_len
= avio_rl16(pb
);
548 avio_skip(pb
, ext_len
);
551 for (i
= 0; i
< payload_ext_ct
; i
++) {
554 ext_len
= avio_rl32(pb
);
555 avio_skip(pb
, ext_len
);
561 static int asf_read_content_desc(AVFormatContext
*s
, int64_t size
)
563 AVIOContext
*pb
= s
->pb
;
564 int len1
, len2
, len3
, len4
, len5
;
566 len1
= avio_rl16(pb
);
567 len2
= avio_rl16(pb
);
568 len3
= avio_rl16(pb
);
569 len4
= avio_rl16(pb
);
570 len5
= avio_rl16(pb
);
571 get_tag(s
, "title", 0, len1
, 32);
572 get_tag(s
, "author", 0, len2
, 32);
573 get_tag(s
, "copyright", 0, len3
, 32);
574 get_tag(s
, "comment", 0, len4
, 32);
580 static int asf_read_ext_content_desc(AVFormatContext
*s
, int64_t size
)
582 AVIOContext
*pb
= s
->pb
;
583 ASFContext
*asf
= s
->priv_data
;
584 int desc_count
, i
, ret
;
586 desc_count
= avio_rl16(pb
);
587 for (i
= 0; i
< desc_count
; i
++) {
588 int name_len
, value_type
, value_len
;
591 name_len
= avio_rl16(pb
);
592 if (name_len
% 2) // must be even, broken lavf versions wrote len-1
594 if ((ret
= avio_get_str16le(pb
, name_len
, name
, sizeof(name
))) < name_len
)
595 avio_skip(pb
, name_len
- ret
);
596 value_type
= avio_rl16(pb
);
597 value_len
= avio_rl16(pb
);
598 if (!value_type
&& value_len
% 2)
600 /* My sample has that stream set to 0 maybe that mean the container.
601 * ASF stream count starts at 1. I am using 0 to the container value
602 * since it's unused. */
603 if (!strcmp(name
, "AspectRatioX"))
604 asf
->dar
[0].num
= get_value(s
->pb
, value_type
, 32);
605 else if (!strcmp(name
, "AspectRatioY"))
606 asf
->dar
[0].den
= get_value(s
->pb
, value_type
, 32);
608 get_tag(s
, name
, value_type
, value_len
, 32);
614 static int asf_read_language_list(AVFormatContext
*s
, int64_t size
)
616 AVIOContext
*pb
= s
->pb
;
617 ASFContext
*asf
= s
->priv_data
;
619 int stream_count
= avio_rl16(pb
);
620 for (j
= 0; j
< stream_count
; j
++) {
622 unsigned int lang_len
= avio_r8(pb
);
623 if ((ret
= avio_get_str16le(pb
, lang_len
, lang
,
624 sizeof(lang
))) < lang_len
)
625 avio_skip(pb
, lang_len
- ret
);
627 av_strlcpy(asf
->stream_languages
[j
], lang
,
628 sizeof(*asf
->stream_languages
));
634 static int asf_read_metadata(AVFormatContext
*s
, int64_t size
)
636 AVIOContext
*pb
= s
->pb
;
637 ASFContext
*asf
= s
->priv_data
;
638 int n
, stream_num
, name_len
, value_len
;
642 for (i
= 0; i
< n
; i
++) {
646 avio_rl16(pb
); // lang_list_index
647 stream_num
= avio_rl16(pb
);
648 name_len
= avio_rl16(pb
);
649 value_type
= avio_rl16(pb
); /* value_type */
650 value_len
= avio_rl32(pb
);
652 if ((ret
= avio_get_str16le(pb
, name_len
, name
, sizeof(name
))) < name_len
)
653 avio_skip(pb
, name_len
- ret
);
654 av_dlog(s
, "%d stream %d name_len %2d type %d len %4d <%s>\n",
655 i
, stream_num
, name_len
, value_type
, value_len
, name
);
657 if (!strcmp(name
, "AspectRatioX")){
658 int aspect_x
= get_value(s
->pb
, value_type
, 16);
660 asf
->dar
[stream_num
].num
= aspect_x
;
661 } else if(!strcmp(name
, "AspectRatioY")){
662 int aspect_y
= get_value(s
->pb
, value_type
, 16);
664 asf
->dar
[stream_num
].den
= aspect_y
;
666 get_tag(s
, name
, value_type
, value_len
, 16);
673 static int asf_read_marker(AVFormatContext
*s
, int64_t size
)
675 AVIOContext
*pb
= s
->pb
;
676 int i
, count
, name_len
, ret
;
679 avio_rl64(pb
); // reserved 16 bytes
680 avio_rl64(pb
); // ...
681 count
= avio_rl32(pb
); // markers count
682 avio_rl16(pb
); // reserved 2 bytes
683 name_len
= avio_rl16(pb
); // name length
684 for (i
= 0; i
< name_len
; i
++)
685 avio_r8(pb
); // skip the name
687 for (i
= 0; i
< count
; i
++) {
691 avio_rl64(pb
); // offset, 8 bytes
692 pres_time
= avio_rl64(pb
); // presentation time
693 avio_rl16(pb
); // entry length
694 avio_rl32(pb
); // send time
695 avio_rl32(pb
); // flags
696 name_len
= avio_rl32(pb
); // name length
697 if ((ret
= avio_get_str16le(pb
, name_len
* 2, name
,
698 sizeof(name
))) < name_len
)
699 avio_skip(pb
, name_len
- ret
);
700 avpriv_new_chapter(s
, i
, (AVRational
) { 1, 10000000 }, pres_time
,
701 AV_NOPTS_VALUE
, name
);
707 static int asf_read_header(AVFormatContext
*s
)
709 ASFContext
*asf
= s
->priv_data
;
711 AVIOContext
*pb
= s
->pb
;
716 if (ff_guidcmp(&g
, &ff_asf_header
))
722 memset(&asf
->asfid2avid
, -1, sizeof(asf
->asfid2avid
));
724 uint64_t gpos
= avio_tell(pb
);
726 gsize
= avio_rl64(pb
);
728 if (!ff_guidcmp(&g
, &ff_asf_data_header
)) {
729 asf
->data_object_offset
= avio_tell(pb
);
730 /* If not streaming, gsize is not unlimited (how?),
731 * and there is enough space in the file.. */
732 if (!(asf
->hdr
.flags
& 0x01) && gsize
>= 100)
733 asf
->data_object_size
= gsize
- 24;
735 asf
->data_object_size
= (uint64_t)-1;
740 if (!ff_guidcmp(&g
, &ff_asf_file_header
)) {
741 int ret
= asf_read_file_properties(s
, gsize
);
744 } else if (!ff_guidcmp(&g
, &ff_asf_stream_header
)) {
745 asf_read_stream_properties(s
, gsize
);
746 } else if (!ff_guidcmp(&g
, &ff_asf_comment_header
)) {
747 asf_read_content_desc(s
, gsize
);
748 } else if (!ff_guidcmp(&g
, &ff_asf_language_guid
)) {
749 asf_read_language_list(s
, gsize
);
750 } else if (!ff_guidcmp(&g
, &ff_asf_extended_content_header
)) {
751 asf_read_ext_content_desc(s
, gsize
);
752 } else if (!ff_guidcmp(&g
, &ff_asf_metadata_header
)) {
753 asf_read_metadata(s
, gsize
);
754 } else if (!ff_guidcmp(&g
, &ff_asf_metadata_library_header
)) {
755 asf_read_metadata(s
, gsize
);
756 } else if (!ff_guidcmp(&g
, &ff_asf_ext_stream_header
)) {
757 asf_read_ext_stream_properties(s
, gsize
);
759 // there could be a optional stream properties object to follow
760 // if so the next iteration will pick it up
762 } else if (!ff_guidcmp(&g
, &ff_asf_head1_guid
)) {
766 } else if (!ff_guidcmp(&g
, &ff_asf_marker_header
)) {
767 asf_read_marker(s
, gsize
);
768 } else if (pb
->eof_reached
) {
772 if (!ff_guidcmp(&g
, &ff_asf_content_encryption
)) {
773 av_log(s
, AV_LOG_WARNING
,
774 "DRM protected stream detected, decoding will likely fail!\n");
775 } else if (!ff_guidcmp(&g
, &ff_asf_ext_content_encryption
)) {
776 av_log(s
, AV_LOG_WARNING
,
777 "Ext DRM protected stream detected, decoding will likely fail!\n");
778 } else if (!ff_guidcmp(&g
, &ff_asf_digital_signature
)) {
779 av_log(s
, AV_LOG_WARNING
,
780 "Digital signature detected, decoding will likely fail!\n");
784 if (avio_tell(pb
) != gpos
+ gsize
)
785 av_log(s
, AV_LOG_DEBUG
,
786 "gpos mismatch our pos=%"PRIu64
", end=%"PRId64
"\n",
787 avio_tell(pb
) - gpos
, gsize
);
788 avio_seek(pb
, gpos
+ gsize
, SEEK_SET
);
796 asf
->data_offset
= avio_tell(pb
);
797 asf
->packet_size_left
= 0;
799 for (i
= 0; i
< 128; i
++) {
800 int stream_num
= asf
->asfid2avid
[i
];
801 if (stream_num
>= 0) {
802 AVStream
*st
= s
->streams
[stream_num
];
803 if (!st
->codec
->bit_rate
)
804 st
->codec
->bit_rate
= asf
->stream_bitrates
[i
];
805 if (asf
->dar
[i
].num
> 0 && asf
->dar
[i
].den
> 0) {
806 av_reduce(&st
->sample_aspect_ratio
.num
,
807 &st
->sample_aspect_ratio
.den
,
808 asf
->dar
[i
].num
, asf
->dar
[i
].den
, INT_MAX
);
809 } else if ((asf
->dar
[0].num
> 0) && (asf
->dar
[0].den
> 0) &&
810 // Use ASF container value if the stream doesn't set AR.
811 (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
))
812 av_reduce(&st
->sample_aspect_ratio
.num
,
813 &st
->sample_aspect_ratio
.den
,
814 asf
->dar
[0].num
, asf
->dar
[0].den
, INT_MAX
);
816 av_dlog(s
, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
817 i
, st
->codec
->codec_type
, asf
->dar
[i
].num
, asf
->dar
[i
].den
,
818 st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
);
820 // copy and convert language codes to the frontend
821 if (asf
->streams
[i
].stream_language_index
< 128) {
822 const char *rfc1766
= asf
->stream_languages
[asf
->streams
[i
].stream_language_index
];
823 if (rfc1766
&& strlen(rfc1766
) > 1) {
824 const char primary_tag
[3] = { rfc1766
[0], rfc1766
[1], '\0' }; // ignore country code if any
825 const char *iso6392
= av_convert_lang_to(primary_tag
,
826 AV_LANG_ISO639_2_BIBL
);
828 av_dict_set(&st
->metadata
, "language", iso6392
, 0);
834 ff_metadata_conv(&s
->metadata
, NULL
, ff_asf_metadata_conv
);
839 #define DO_2BITS(bits, var, defval) \
840 switch (bits & 3) { \
842 var = avio_rl32(pb); \
846 var = avio_rl16(pb); \
859 * Load a single ASF packet into the demuxer.
860 * @param s demux context
861 * @param pb context to read data from
862 * @return 0 on success, <0 on error
864 static int ff_asf_get_packet(AVFormatContext
*s
, AVIOContext
*pb
)
866 ASFContext
*asf
= s
->priv_data
;
867 uint32_t packet_length
, padsize
;
871 // if we do not know packet size, allow skipping up to 32 kB
873 if (asf
->no_resync_search
)
875 else if (s
->packet_size
> 0)
876 off
= (avio_tell(pb
) - s
->data_offset
) % s
->packet_size
+ 3;
883 if (c
== 0x82 && !d
&& !e
)
888 /* This code allows handling of -EAGAIN at packet boundaries (i.e.
889 * if the packet sync code above triggers -EAGAIN). This does not
890 * imply complete -EAGAIN handling support at random positions in
892 if (pb
->error
== AVERROR(EAGAIN
))
893 return AVERROR(EAGAIN
);
894 if (!pb
->eof_reached
)
895 av_log(s
, AV_LOG_ERROR
,
896 "ff asf bad header %x at:%"PRId64
"\n", c
, avio_tell(pb
));
898 if ((c
& 0x8f) == 0x82) {
900 if (!pb
->eof_reached
)
901 av_log(s
, AV_LOG_ERROR
, "ff asf bad non zero\n");
907 } else if (!pb
->eof_reached
) {
908 avio_seek(pb
, -1, SEEK_CUR
); // FIXME
911 asf
->packet_flags
= c
;
912 asf
->packet_property
= d
;
914 DO_2BITS(asf
->packet_flags
>> 5, packet_length
, s
->packet_size
);
915 DO_2BITS(asf
->packet_flags
>> 1, padsize
, 0); // sequence ignored
916 DO_2BITS(asf
->packet_flags
>> 3, padsize
, 0); // padding length
918 // the following checks prevent overflows and infinite loops
919 if (!packet_length
|| packet_length
>= (1U << 29)) {
920 av_log(s
, AV_LOG_ERROR
,
921 "invalid packet_length %d at:%"PRId64
"\n",
922 packet_length
, avio_tell(pb
));
925 if (padsize
>= packet_length
) {
926 av_log(s
, AV_LOG_ERROR
,
927 "invalid padsize %d at:%"PRId64
"\n", padsize
, avio_tell(pb
));
931 asf
->packet_timestamp
= avio_rl32(pb
);
932 avio_rl16(pb
); /* duration */
933 // rsize has at least 11 bytes which have to be present
935 if (asf
->packet_flags
& 0x01) {
936 asf
->packet_segsizetype
= avio_r8(pb
);
938 asf
->packet_segments
= asf
->packet_segsizetype
& 0x3f;
940 asf
->packet_segments
= 1;
941 asf
->packet_segsizetype
= 0x80;
943 if (rsize
> packet_length
- padsize
) {
944 asf
->packet_size_left
= 0;
945 av_log(s
, AV_LOG_ERROR
,
946 "invalid packet header length %d for pktlen %d-%d at %"PRId64
"\n",
947 rsize
, packet_length
, padsize
, avio_tell(pb
));
950 asf
->packet_size_left
= packet_length
- padsize
- rsize
;
951 if (packet_length
< asf
->hdr
.min_pktsize
)
952 padsize
+= asf
->hdr
.min_pktsize
- packet_length
;
953 asf
->packet_padsize
= padsize
;
954 av_dlog(s
, "packet: size=%d padsize=%d left=%d\n",
955 s
->packet_size
, asf
->packet_padsize
, asf
->packet_size_left
);
961 * @return <0 if error
963 static int asf_read_frame_header(AVFormatContext
*s
, AVIOContext
*pb
)
965 ASFContext
*asf
= s
->priv_data
;
967 int num
= avio_r8(pb
);
970 asf
->packet_segments
--;
971 asf
->packet_key_frame
= num
>> 7;
972 asf
->stream_index
= asf
->asfid2avid
[num
& 0x7f];
973 // sequence should be ignored!
974 DO_2BITS(asf
->packet_property
>> 4, asf
->packet_seq
, 0);
975 DO_2BITS(asf
->packet_property
>> 2, asf
->packet_frag_offset
, 0);
976 DO_2BITS(asf
->packet_property
, asf
->packet_replic_size
, 0);
977 av_dlog(asf
, "key:%d stream:%d seq:%d offset:%d replic_size:%d\n",
978 asf
->packet_key_frame
, asf
->stream_index
, asf
->packet_seq
,
979 asf
->packet_frag_offset
, asf
->packet_replic_size
);
980 if (asf
->packet_replic_size
>= 8) {
981 asf
->packet_obj_size
= avio_rl32(pb
);
982 if (asf
->packet_obj_size
>= (1 << 24) || asf
->packet_obj_size
<= 0) {
983 av_log(s
, AV_LOG_ERROR
, "packet_obj_size invalid\n");
986 asf
->packet_frag_timestamp
= avio_rl32(pb
); // timestamp
987 if (asf
->packet_replic_size
>= 8 + 38 + 4) {
993 avio_skip(pb
, asf
->packet_replic_size
- 8 - 38 - 4);
995 asf
->packet_frag_timestamp
= ts0
/ 10000;
997 asf
->packet_frag_timestamp
= AV_NOPTS_VALUE
;
999 avio_skip(pb
, asf
->packet_replic_size
- 8);
1000 rsize
+= asf
->packet_replic_size
; // FIXME - check validity
1001 } else if (asf
->packet_replic_size
== 1) {
1002 // multipacket - frag_offset is beginning timestamp
1003 asf
->packet_time_start
= asf
->packet_frag_offset
;
1004 asf
->packet_frag_offset
= 0;
1005 asf
->packet_frag_timestamp
= asf
->packet_timestamp
;
1007 asf
->packet_time_delta
= avio_r8(pb
);
1009 } else if (asf
->packet_replic_size
!= 0) {
1010 av_log(s
, AV_LOG_ERROR
, "unexpected packet_replic_size of %d\n",
1011 asf
->packet_replic_size
);
1014 if (asf
->packet_flags
& 0x01) {
1015 DO_2BITS(asf
->packet_segsizetype
>> 6, asf
->packet_frag_size
, 0); // 0 is illegal
1016 if (rsize
> asf
->packet_size_left
) {
1017 av_log(s
, AV_LOG_ERROR
, "packet_replic_size is invalid\n");
1019 } else if (asf
->packet_frag_size
> asf
->packet_size_left
- rsize
) {
1020 if (asf
->packet_frag_size
> asf
->packet_size_left
- rsize
+ asf
->packet_padsize
) {
1021 av_log(s
, AV_LOG_ERROR
, "packet_frag_size is invalid (%d-%d)\n",
1022 asf
->packet_size_left
, rsize
);
1025 int diff
= asf
->packet_frag_size
- (asf
->packet_size_left
- rsize
);
1026 asf
->packet_size_left
+= diff
;
1027 asf
->packet_padsize
-= diff
;
1031 if (rsize
> asf
->packet_size_left
) {
1032 av_log(s
, AV_LOG_ERROR
, "packet_replic_size is invalid\n");
1035 asf
->packet_frag_size
= asf
->packet_size_left
- rsize
;
1037 if (asf
->packet_replic_size
== 1) {
1038 asf
->packet_multi_size
= asf
->packet_frag_size
;
1039 if (asf
->packet_multi_size
> asf
->packet_size_left
)
1042 asf
->packet_size_left
-= rsize
;
1048 * Parse data from individual ASF packets (which were previously loaded
1049 * with asf_get_packet()).
1050 * @param s demux context
1051 * @param pb context to read data from
1052 * @param pkt pointer to store packet data into
1053 * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
1054 * packets need to be loaded (through asf_get_packet())
1056 static int ff_asf_parse_packet(AVFormatContext
*s
, AVIOContext
*pb
, AVPacket
*pkt
)
1058 ASFContext
*asf
= s
->priv_data
;
1059 ASFStream
*asf_st
= 0;
1063 if (pb
->eof_reached
)
1066 if (asf
->packet_size_left
< FRAME_HEADER_SIZE
||
1067 asf
->packet_segments
< 1) {
1068 int ret
= asf
->packet_size_left
+ asf
->packet_padsize
;
1074 asf
->packet_pos
= avio_tell(pb
);
1075 if (asf
->data_object_size
!= (uint64_t)-1 &&
1076 (asf
->packet_pos
- asf
->data_object_offset
>= asf
->data_object_size
))
1077 return AVERROR_EOF
; /* Do not exceed the size of the data object */
1080 if (asf
->packet_time_start
== 0) {
1081 if (asf_read_frame_header(s
, pb
) < 0) {
1082 asf
->packet_segments
= 0;
1085 if (asf
->stream_index
< 0 ||
1086 s
->streams
[asf
->stream_index
]->discard
>= AVDISCARD_ALL
||
1087 (!asf
->packet_key_frame
&&
1088 s
->streams
[asf
->stream_index
]->discard
>= AVDISCARD_NONKEY
)) {
1089 asf
->packet_time_start
= 0;
1090 /* unhandled packet (should not happen) */
1091 avio_skip(pb
, asf
->packet_frag_size
);
1092 asf
->packet_size_left
-= asf
->packet_frag_size
;
1093 if (asf
->stream_index
< 0)
1094 av_log(s
, AV_LOG_ERROR
, "ff asf skip %d (unknown stream)\n",
1095 asf
->packet_frag_size
);
1098 asf
->asf_st
= s
->streams
[asf
->stream_index
]->priv_data
;
1100 asf_st
= asf
->asf_st
;
1103 if (asf
->packet_replic_size
== 1) {
1104 // frag_offset is here used as the beginning timestamp
1105 asf
->packet_frag_timestamp
= asf
->packet_time_start
;
1106 asf
->packet_time_start
+= asf
->packet_time_delta
;
1107 asf
->packet_obj_size
= asf
->packet_frag_size
= avio_r8(pb
);
1108 asf
->packet_size_left
--;
1109 asf
->packet_multi_size
--;
1110 if (asf
->packet_multi_size
< asf
->packet_obj_size
) {
1111 asf
->packet_time_start
= 0;
1112 avio_skip(pb
, asf
->packet_multi_size
);
1113 asf
->packet_size_left
-= asf
->packet_multi_size
;
1116 asf
->packet_multi_size
-= asf
->packet_obj_size
;
1118 if (asf_st
->frag_offset
+ asf
->packet_frag_size
<= asf_st
->pkt
.size
&&
1119 asf_st
->frag_offset
+ asf
->packet_frag_size
> asf
->packet_obj_size
) {
1120 av_log(s
, AV_LOG_INFO
, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
1121 asf_st
->frag_offset
, asf
->packet_frag_size
,
1122 asf
->packet_obj_size
, asf_st
->pkt
.size
);
1123 asf
->packet_obj_size
= asf_st
->pkt
.size
;
1126 if (asf_st
->pkt
.size
!= asf
->packet_obj_size
||
1127 // FIXME is this condition sufficient?
1128 asf_st
->frag_offset
+ asf
->packet_frag_size
> asf_st
->pkt
.size
) {
1129 if (asf_st
->pkt
.data
) {
1130 av_log(s
, AV_LOG_INFO
,
1131 "freeing incomplete packet size %d, new %d\n",
1132 asf_st
->pkt
.size
, asf
->packet_obj_size
);
1133 asf_st
->frag_offset
= 0;
1134 av_free_packet(&asf_st
->pkt
);
1137 av_new_packet(&asf_st
->pkt
, asf
->packet_obj_size
);
1138 asf_st
->seq
= asf
->packet_seq
;
1139 asf_st
->pkt
.dts
= asf
->packet_frag_timestamp
- asf
->hdr
.preroll
;
1140 asf_st
->pkt
.stream_index
= asf
->stream_index
;
1141 asf_st
->pkt
.pos
= asf_st
->packet_pos
= asf
->packet_pos
;
1143 if (asf_st
->pkt
.data
&& asf_st
->palette_changed
) {
1145 pal
= av_packet_new_side_data(&asf_st
->pkt
, AV_PKT_DATA_PALETTE
,
1148 av_log(s
, AV_LOG_ERROR
, "Cannot append palette to packet\n");
1150 memcpy(pal
, asf_st
->palette
, AVPALETTE_SIZE
);
1151 asf_st
->palette_changed
= 0;
1154 av_dlog(asf
, "new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
1155 asf
->stream_index
, asf
->packet_key_frame
,
1156 asf_st
->pkt
.flags
& AV_PKT_FLAG_KEY
,
1157 s
->streams
[asf
->stream_index
]->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
,
1158 asf
->packet_obj_size
);
1159 if (s
->streams
[asf
->stream_index
]->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1160 asf
->packet_key_frame
= 1;
1161 if (asf
->packet_key_frame
)
1162 asf_st
->pkt
.flags
|= AV_PKT_FLAG_KEY
;
1166 av_dlog(asf
, "READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
1167 s
->packet_size
, asf_st
->pkt
.size
, asf
->packet_frag_offset
,
1168 asf_st
->frag_offset
, asf
->packet_frag_size
, asf_st
->pkt
.data
);
1169 asf
->packet_size_left
-= asf
->packet_frag_size
;
1170 if (asf
->packet_size_left
< 0)
1173 if (asf
->packet_frag_offset
>= asf_st
->pkt
.size
||
1174 asf
->packet_frag_size
> asf_st
->pkt
.size
- asf
->packet_frag_offset
) {
1175 av_log(s
, AV_LOG_ERROR
,
1176 "packet fragment position invalid %u,%u not in %u\n",
1177 asf
->packet_frag_offset
, asf
->packet_frag_size
,
1182 ret
= avio_read(pb
, asf_st
->pkt
.data
+ asf
->packet_frag_offset
,
1183 asf
->packet_frag_size
);
1184 if (ret
!= asf
->packet_frag_size
) {
1185 if (ret
< 0 || asf
->packet_frag_offset
+ ret
== 0)
1186 return ret
< 0 ? ret
: AVERROR_EOF
;
1188 if (asf_st
->ds_span
> 1) {
1189 // scrambling, we can either drop it completely or fill the remainder
1190 // TODO: should we fill the whole packet instead of just the current
1192 memset(asf_st
->pkt
.data
+ asf
->packet_frag_offset
+ ret
, 0,
1193 asf
->packet_frag_size
- ret
);
1194 ret
= asf
->packet_frag_size
;
1196 // no scrambling, so we can return partial packets
1197 av_shrink_packet(&asf_st
->pkt
, asf
->packet_frag_offset
+ ret
);
1200 if (s
->key
&& s
->keylen
== 20)
1201 ff_asfcrypt_dec(s
->key
, asf_st
->pkt
.data
+ asf
->packet_frag_offset
,
1203 asf_st
->frag_offset
+= ret
;
1204 /* test if whole packet is read */
1205 if (asf_st
->frag_offset
== asf_st
->pkt
.size
) {
1206 // workaround for macroshit radio DVR-MS files
1207 if (s
->streams
[asf
->stream_index
]->codec
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&&
1208 asf_st
->pkt
.size
> 100) {
1210 for (i
= 0; i
< asf_st
->pkt
.size
&& !asf_st
->pkt
.data
[i
]; i
++)
1212 if (i
== asf_st
->pkt
.size
) {
1213 av_log(s
, AV_LOG_DEBUG
, "discarding ms fart\n");
1214 asf_st
->frag_offset
= 0;
1215 av_free_packet(&asf_st
->pkt
);
1221 if (asf_st
->ds_span
> 1) {
1222 if (asf_st
->pkt
.size
!= asf_st
->ds_packet_size
* asf_st
->ds_span
) {
1223 av_log(s
, AV_LOG_ERROR
,
1224 "pkt.size != ds_packet_size * ds_span (%d %d %d)\n",
1225 asf_st
->pkt
.size
, asf_st
->ds_packet_size
,
1228 /* packet descrambling */
1229 AVBufferRef
*buf
= av_buffer_alloc(asf_st
->pkt
.size
+
1230 FF_INPUT_BUFFER_PADDING_SIZE
);
1232 uint8_t *newdata
= buf
->data
;
1234 memset(newdata
+ asf_st
->pkt
.size
, 0,
1235 FF_INPUT_BUFFER_PADDING_SIZE
);
1236 while (offset
< asf_st
->pkt
.size
) {
1237 int off
= offset
/ asf_st
->ds_chunk_size
;
1238 int row
= off
/ asf_st
->ds_span
;
1239 int col
= off
% asf_st
->ds_span
;
1240 int idx
= row
+ col
* asf_st
->ds_packet_size
/ asf_st
->ds_chunk_size
;
1241 assert(offset
+ asf_st
->ds_chunk_size
<= asf_st
->pkt
.size
);
1242 assert(idx
+ 1 <= asf_st
->pkt
.size
/ asf_st
->ds_chunk_size
);
1243 memcpy(newdata
+ offset
,
1244 asf_st
->pkt
.data
+ idx
* asf_st
->ds_chunk_size
,
1245 asf_st
->ds_chunk_size
);
1246 offset
+= asf_st
->ds_chunk_size
;
1248 av_buffer_unref(&asf_st
->pkt
.buf
);
1249 asf_st
->pkt
.buf
= buf
;
1250 asf_st
->pkt
.data
= buf
->data
;
1254 asf_st
->frag_offset
= 0;
1256 #if FF_API_DESTRUCT_PACKET
1257 asf_st
->pkt
.destruct
= NULL
;
1259 asf_st
->pkt
.buf
= 0;
1260 asf_st
->pkt
.size
= 0;
1261 asf_st
->pkt
.data
= 0;
1262 asf_st
->pkt
.side_data_elems
= 0;
1263 asf_st
->pkt
.side_data
= NULL
;
1264 break; // packet completed
1270 static int asf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
1272 ASFContext
*asf
= s
->priv_data
;
1277 /* parse cached packets, if any */
1278 if ((ret
= ff_asf_parse_packet(s
, s
->pb
, pkt
)) <= 0)
1280 if ((ret
= ff_asf_get_packet(s
, s
->pb
)) < 0)
1281 assert(asf
->packet_size_left
< FRAME_HEADER_SIZE
||
1282 asf
->packet_segments
< 1);
1283 asf
->packet_time_start
= 0;
1287 // Added to support seeking after packets have been read
1288 // If information is not reset, read_packet fails due to
1289 // leftover information from previous reads
1290 static void asf_reset_header(AVFormatContext
*s
)
1292 ASFContext
*asf
= s
->priv_data
;
1296 asf
->packet_size_left
= 0;
1297 asf
->packet_segments
= 0;
1298 asf
->packet_flags
= 0;
1299 asf
->packet_property
= 0;
1300 asf
->packet_timestamp
= 0;
1301 asf
->packet_segsizetype
= 0;
1302 asf
->packet_segments
= 0;
1303 asf
->packet_seq
= 0;
1304 asf
->packet_replic_size
= 0;
1305 asf
->packet_key_frame
= 0;
1306 asf
->packet_padsize
= 0;
1307 asf
->packet_frag_offset
= 0;
1308 asf
->packet_frag_size
= 0;
1309 asf
->packet_frag_timestamp
= 0;
1310 asf
->packet_multi_size
= 0;
1311 asf
->packet_obj_size
= 0;
1312 asf
->packet_time_delta
= 0;
1313 asf
->packet_time_start
= 0;
1315 for (i
= 0; i
< s
->nb_streams
; i
++) {
1316 asf_st
= s
->streams
[i
]->priv_data
;
1319 av_free_packet(&asf_st
->pkt
);
1320 asf_st
->frag_offset
= 0;
1326 static int asf_read_close(AVFormatContext
*s
)
1328 asf_reset_header(s
);
1333 static int64_t asf_read_pts(AVFormatContext
*s
, int stream_index
,
1334 int64_t *ppos
, int64_t pos_limit
)
1336 AVPacket pkt1
, *pkt
= &pkt1
;
1339 int64_t pos
= *ppos
;
1341 int64_t start_pos
[ASF_MAX_STREAMS
];
1343 for (i
= 0; i
< s
->nb_streams
; i
++)
1346 if (s
->packet_size
> 0)
1347 pos
= (pos
+ s
->packet_size
- 1 - s
->data_offset
) /
1348 s
->packet_size
* s
->packet_size
+
1351 avio_seek(s
->pb
, pos
, SEEK_SET
);
1353 asf_reset_header(s
);
1355 if (asf_read_packet(s
, pkt
) < 0) {
1356 av_log(s
, AV_LOG_INFO
, "asf_read_pts failed\n");
1357 return AV_NOPTS_VALUE
;
1362 av_free_packet(pkt
);
1363 if (pkt
->flags
& AV_PKT_FLAG_KEY
) {
1364 i
= pkt
->stream_index
;
1366 asf_st
= s
->streams
[i
]->priv_data
;
1369 // assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0);
1370 pos
= asf_st
->packet_pos
;
1372 av_add_index_entry(s
->streams
[i
], pos
, pts
, pkt
->size
,
1373 pos
- start_pos
[i
] + 1, AVINDEX_KEYFRAME
);
1374 start_pos
[i
] = asf_st
->packet_pos
+ 1;
1376 if (pkt
->stream_index
== stream_index
)
1385 static void asf_build_simple_index(AVFormatContext
*s
, int stream_index
)
1388 ASFContext
*asf
= s
->priv_data
;
1389 int64_t current_pos
= avio_tell(s
->pb
);
1392 avio_seek(s
->pb
, asf
->data_object_offset
+ asf
->data_object_size
, SEEK_SET
);
1393 ff_get_guid(s
->pb
, &g
);
1395 /* the data object can be followed by other top-level objects,
1396 * skip them until the simple index object is reached */
1397 while (ff_guidcmp(&g
, &index_guid
)) {
1398 int64_t gsize
= avio_rl64(s
->pb
);
1399 if (gsize
< 24 || s
->pb
->eof_reached
) {
1400 avio_seek(s
->pb
, current_pos
, SEEK_SET
);
1403 avio_skip(s
->pb
, gsize
- 24);
1404 ff_get_guid(s
->pb
, &g
);
1408 int64_t itime
, last_pos
= -1;
1410 int64_t av_unused gsize
= avio_rl64(s
->pb
);
1411 ff_get_guid(s
->pb
, &g
);
1412 itime
= avio_rl64(s
->pb
);
1413 pct
= avio_rl32(s
->pb
);
1414 ict
= avio_rl32(s
->pb
);
1415 av_log(s
, AV_LOG_DEBUG
,
1416 "itime:0x%"PRIx64
", pct:%d, ict:%d\n", itime
, pct
, ict
);
1418 for (i
= 0; i
< ict
; i
++) {
1419 int pktnum
= avio_rl32(s
->pb
);
1420 int pktct
= avio_rl16(s
->pb
);
1421 int64_t pos
= s
->data_offset
+ s
->packet_size
* (int64_t)pktnum
;
1422 int64_t index_pts
= FFMAX(av_rescale(itime
, i
, 10000) - asf
->hdr
.preroll
, 0);
1424 if (pos
!= last_pos
) {
1425 av_log(s
, AV_LOG_DEBUG
, "pktnum:%d, pktct:%d pts: %"PRId64
"\n",
1426 pktnum
, pktct
, index_pts
);
1427 av_add_index_entry(s
->streams
[stream_index
], pos
, index_pts
,
1428 s
->packet_size
, 0, AVINDEX_KEYFRAME
);
1432 asf
->index_read
= ict
> 0;
1434 avio_seek(s
->pb
, current_pos
, SEEK_SET
);
1437 static int asf_read_seek(AVFormatContext
*s
, int stream_index
,
1438 int64_t pts
, int flags
)
1440 ASFContext
*asf
= s
->priv_data
;
1441 AVStream
*st
= s
->streams
[stream_index
];
1445 if (s
->packet_size
<= 0)
1448 /* Try using the protocol's read_seek if available */
1450 int ret
= avio_seek_time(s
->pb
, stream_index
, pts
, flags
);
1452 asf_reset_header(s
);
1453 if (ret
!= AVERROR(ENOSYS
))
1457 if (!asf
->index_read
)
1458 asf_build_simple_index(s
, stream_index
);
1460 if ((asf
->index_read
&& st
->index_entries
)) {
1461 index
= av_index_search_timestamp(st
, pts
, flags
);
1463 /* find the position */
1464 pos
= st
->index_entries
[index
].pos
;
1467 av_log(s
, AV_LOG_DEBUG
, "SEEKTO: %"PRId64
"\n", pos
);
1468 avio_seek(s
->pb
, pos
, SEEK_SET
);
1469 asf_reset_header(s
);
1473 /* no index or seeking by index failed */
1474 if (ff_seek_frame_binary(s
, stream_index
, pts
, flags
) < 0)
1476 asf_reset_header(s
);
1480 AVInputFormat ff_asf_demuxer
= {
1482 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1483 .priv_data_size
= sizeof(ASFContext
),
1484 .read_probe
= asf_probe
,
1485 .read_header
= asf_read_header
,
1486 .read_packet
= asf_read_packet
,
1487 .read_close
= asf_read_close
,
1488 .read_seek
= asf_read_seek
,
1489 .read_timestamp
= asf_read_pts
,
1490 .flags
= AVFMT_NOBINSEARCH
| AVFMT_NOGENSEARCH
,
1491 .priv_class
= &asf_class
,