2 * ASF compatible demuxer
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
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/internal.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/opt.h"
34 #include "avio_internal.h"
35 #include "avlanguage.h"
44 int asfid2avid
[128]; ///< conversion table from asf ID 2 AVStream ID
45 ASFStream streams
[128]; ///< it's max number and it's not that big
46 uint32_t stream_bitrates
[128]; ///< max number of streams, bitrate for each (for streaming)
48 char stream_languages
[128][6]; ///< max number of streams, language for each (RFC1766, e.g. en-US)
49 /* non streamed additonnal info */
52 /* only for reading */
53 uint64_t data_offset
; ///< beginning of the first data packet
54 uint64_t data_object_offset
; ///< data object offset (excl. GUID & size)
55 uint64_t data_object_size
; ///< size of the data object
63 int packet_segsizetype
;
66 int packet_replic_size
;
69 unsigned int packet_frag_offset
;
70 unsigned int packet_frag_size
;
71 int64_t packet_frag_timestamp
;
73 int packet_multi_size
;
74 int packet_time_delta
;
75 int packet_time_start
;
80 ASFStream
*asf_st
; ///< currently decoded stream
85 static const AVOption options
[] = {
86 { "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
},
90 static const AVClass asf_class
= {
91 .class_name
= "asf demuxer",
92 .item_name
= av_default_item_name
,
94 .version
= LIBAVUTIL_VERSION_INT
,
100 #define ASF_MAX_STREAMS 127
101 #define FRAME_HEADER_SIZE 16
102 // Fix Me! FRAME_HEADER_SIZE may be different. (17 is known to be too large)
105 static const ff_asf_guid stream_bitrate_guid
= { /* (http://get.to/sdp) */
106 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
109 #define PRINT_IF_GUID(g, cmp) \
110 if (!ff_guidcmp(g, &cmp)) \
111 av_dlog(NULL, "(GUID: %s) ", # cmp)
113 static void print_guid(ff_asf_guid
*g
)
116 PRINT_IF_GUID(g
, ff_asf_header
);
117 else PRINT_IF_GUID(g
, ff_asf_file_header
);
118 else PRINT_IF_GUID(g
, ff_asf_stream_header
);
119 else PRINT_IF_GUID(g
, ff_asf_audio_stream
);
120 else PRINT_IF_GUID(g
, ff_asf_audio_conceal_none
);
121 else PRINT_IF_GUID(g
, ff_asf_video_stream
);
122 else PRINT_IF_GUID(g
, ff_asf_video_conceal_none
);
123 else PRINT_IF_GUID(g
, ff_asf_command_stream
);
124 else PRINT_IF_GUID(g
, ff_asf_comment_header
);
125 else PRINT_IF_GUID(g
, ff_asf_codec_comment_header
);
126 else PRINT_IF_GUID(g
, ff_asf_codec_comment1_header
);
127 else PRINT_IF_GUID(g
, ff_asf_data_header
);
128 else PRINT_IF_GUID(g
, ff_asf_simple_index_header
);
129 else PRINT_IF_GUID(g
, ff_asf_head1_guid
);
130 else PRINT_IF_GUID(g
, ff_asf_head2_guid
);
131 else PRINT_IF_GUID(g
, ff_asf_my_guid
);
132 else PRINT_IF_GUID(g
, ff_asf_ext_stream_header
);
133 else PRINT_IF_GUID(g
, ff_asf_extended_content_header
);
134 else PRINT_IF_GUID(g
, ff_asf_ext_stream_embed_stream_header
);
135 else PRINT_IF_GUID(g
, ff_asf_ext_stream_audio_stream
);
136 else PRINT_IF_GUID(g
, ff_asf_metadata_header
);
137 else PRINT_IF_GUID(g
, ff_asf_metadata_library_header
);
138 else PRINT_IF_GUID(g
, ff_asf_marker_header
);
139 else PRINT_IF_GUID(g
, stream_bitrate_guid
);
140 else PRINT_IF_GUID(g
, ff_asf_language_guid
);
142 av_dlog(NULL
, "(GUID: unknown) ");
143 for (i
= 0; i
< 16; i
++)
144 av_dlog(NULL
, " 0x%02x,", (*g
)[i
]);
145 av_dlog(NULL
, "}\n");
149 #define print_guid(g)
152 static int asf_probe(AVProbeData
*pd
)
154 /* check file header */
155 if (!ff_guidcmp(pd
->buf
, &ff_asf_header
))
156 return AVPROBE_SCORE_MAX
;
161 /* size of type 2 (BOOL) is 32bit for "Extended Content Description Object"
162 * but 16 bit for "Metadata Object" and "Metadata Library Object" */
163 static int get_value(AVIOContext
*pb
, int type
, int type2_size
)
167 return (type2_size
== 32) ? avio_rl32(pb
) : avio_rl16(pb
);
169 return avio_rl32(pb
);
171 return avio_rl64(pb
);
173 return avio_rl16(pb
);
179 /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
180 * but in reality this is only loosely similar */
181 static int asf_read_picture(AVFormatContext
*s
, int len
)
183 AVPacket pkt
= { 0 };
184 const CodecMime
*mime
= ff_id3v2_mime_tags
;
185 enum AVCodecID id
= AV_CODEC_ID_NONE
;
187 uint8_t *desc
= NULL
;
189 int ret
, type
, picsize
, desc_len
;
191 /* type + picsize + mime + desc */
192 if (len
< 1 + 4 + 2 + 2) {
193 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture size: %d.\n", len
);
194 return AVERROR_INVALIDDATA
;
198 type
= avio_r8(s
->pb
);
200 if (type
>= FF_ARRAY_ELEMS(ff_id3v2_picture_types
) || type
< 0) {
201 av_log(s
, AV_LOG_WARNING
, "Unknown attached picture type: %d.\n", type
);
205 /* picture data size */
206 picsize
= avio_rl32(s
->pb
);
209 /* picture MIME type */
210 len
-= avio_get_str16le(s
->pb
, len
, mimetype
, sizeof(mimetype
));
211 while (mime
->id
!= AV_CODEC_ID_NONE
) {
212 if (!strncmp(mime
->str
, mimetype
, sizeof(mimetype
))) {
218 if (id
== AV_CODEC_ID_NONE
) {
219 av_log(s
, AV_LOG_ERROR
, "Unknown attached picture mimetype: %s.\n",
224 if (picsize
>= len
) {
225 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture data size: %d >= %d.\n",
227 return AVERROR_INVALIDDATA
;
230 /* picture description */
231 desc_len
= (len
- picsize
) * 2 + 1;
232 desc
= av_malloc(desc_len
);
234 return AVERROR(ENOMEM
);
235 len
-= avio_get_str16le(s
->pb
, len
- picsize
, desc
, desc_len
);
237 ret
= av_get_packet(s
->pb
, &pkt
, picsize
);
241 st
= avformat_new_stream(s
, NULL
);
243 ret
= AVERROR(ENOMEM
);
246 st
->disposition
|= AV_DISPOSITION_ATTACHED_PIC
;
247 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
248 st
->codec
->codec_id
= id
;
249 st
->attached_pic
= pkt
;
250 st
->attached_pic
.stream_index
= st
->index
;
251 st
->attached_pic
.flags
|= AV_PKT_FLAG_KEY
;
254 av_dict_set(&st
->metadata
, "title", desc
, AV_DICT_DONT_STRDUP_VAL
);
258 av_dict_set(&st
->metadata
, "comment", ff_id3v2_picture_types
[type
], 0);
264 av_free_packet(&pkt
);
268 static void get_id3_tag(AVFormatContext
*s
, int len
)
270 ID3v2ExtraMeta
*id3v2_extra_meta
= NULL
;
272 ff_id3v2_read(s
, ID3v2_DEFAULT_MAGIC
, &id3v2_extra_meta
, len
);
273 if (id3v2_extra_meta
)
274 ff_id3v2_parse_apic(s
, &id3v2_extra_meta
);
275 ff_id3v2_free_extra_meta(&id3v2_extra_meta
);
278 static void get_tag(AVFormatContext
*s
, const char *key
, int type
, int len
, int type2_size
)
281 int64_t off
= avio_tell(s
->pb
);
284 if ((unsigned)len
>= (UINT_MAX
- LEN
) / 2)
287 value
= av_malloc(2 * len
+ LEN
);
291 if (type
== 0) { // UTF16-LE
292 avio_get_str16le(s
->pb
, len
, value
, 2 * len
+ 1);
293 } else if (type
== -1) { // ASCII
294 avio_read(s
->pb
, value
, len
);
296 } else if (type
== 1) { // byte array
297 if (!strcmp(key
, "WM/Picture")) { // handle cover art
298 asf_read_picture(s
, len
);
299 } else if (!strcmp(key
, "ID3")) { // handle ID3 tag
302 av_log(s
, AV_LOG_VERBOSE
, "Unsupported byte array in tag %s.\n", key
);
305 } else if (type
> 1 && type
<= 5) { // boolean or DWORD or QWORD or WORD
306 uint64_t num
= get_value(s
->pb
, type
, type2_size
);
307 snprintf(value
, LEN
, "%"PRIu64
, num
);
308 } else if (type
== 6) { // (don't) handle GUID
309 av_log(s
, AV_LOG_DEBUG
, "Unsupported GUID value in tag %s.\n", key
);
312 av_log(s
, AV_LOG_DEBUG
,
313 "Unsupported value type %d in tag %s.\n", type
, key
);
317 av_dict_set(&s
->metadata
, key
, value
, 0);
321 avio_seek(s
->pb
, off
+ len
, SEEK_SET
);
324 static int asf_read_file_properties(AVFormatContext
*s
, int64_t size
)
326 ASFContext
*asf
= s
->priv_data
;
327 AVIOContext
*pb
= s
->pb
;
329 ff_get_guid(pb
, &asf
->hdr
.guid
);
330 asf
->hdr
.file_size
= avio_rl64(pb
);
331 asf
->hdr
.create_time
= avio_rl64(pb
);
332 avio_rl64(pb
); /* number of packets */
333 asf
->hdr
.play_time
= avio_rl64(pb
);
334 asf
->hdr
.send_time
= avio_rl64(pb
);
335 asf
->hdr
.preroll
= avio_rl32(pb
);
336 asf
->hdr
.ignore
= avio_rl32(pb
);
337 asf
->hdr
.flags
= avio_rl32(pb
);
338 asf
->hdr
.min_pktsize
= avio_rl32(pb
);
339 asf
->hdr
.max_pktsize
= avio_rl32(pb
);
340 if (asf
->hdr
.min_pktsize
>= (1U << 29))
341 return AVERROR_INVALIDDATA
;
342 asf
->hdr
.max_bitrate
= avio_rl32(pb
);
343 s
->packet_size
= asf
->hdr
.max_pktsize
;
348 static int asf_read_stream_properties(AVFormatContext
*s
, int64_t size
)
350 ASFContext
*asf
= s
->priv_data
;
351 AVIOContext
*pb
= s
->pb
;
355 enum AVMediaType type
;
356 int type_specific_size
, sizeX
;
358 int64_t pos1
, pos2
, start_time
;
359 int test_for_ext_stream_audio
, is_dvr_ms_audio
= 0;
361 if (s
->nb_streams
== ASF_MAX_STREAMS
) {
362 av_log(s
, AV_LOG_ERROR
, "too many streams\n");
363 return AVERROR(EINVAL
);
366 pos1
= avio_tell(pb
);
368 st
= avformat_new_stream(s
, NULL
);
370 return AVERROR(ENOMEM
);
371 avpriv_set_pts_info(st
, 32, 1, 1000); /* 32 bit pts in ms */
372 start_time
= asf
->hdr
.preroll
;
374 if (!(asf
->hdr
.flags
& 0x01)) { // if we aren't streaming...
375 int64_t fsize
= avio_size(pb
);
376 if (fsize
<= 0 || (int64_t)asf
->hdr
.file_size
<= 0 ||
377 FFABS(fsize
- (int64_t)asf
->hdr
.file_size
) / (float)FFMIN(fsize
, asf
->hdr
.file_size
) < 0.05)
378 st
->duration
= asf
->hdr
.play_time
/
379 (10000000 / 1000) - start_time
;
383 test_for_ext_stream_audio
= 0;
384 if (!ff_guidcmp(&g
, &ff_asf_audio_stream
)) {
385 type
= AVMEDIA_TYPE_AUDIO
;
386 } else if (!ff_guidcmp(&g
, &ff_asf_video_stream
)) {
387 type
= AVMEDIA_TYPE_VIDEO
;
388 } else if (!ff_guidcmp(&g
, &ff_asf_jfif_media
)) {
389 type
= AVMEDIA_TYPE_VIDEO
;
390 st
->codec
->codec_id
= AV_CODEC_ID_MJPEG
;
391 } else if (!ff_guidcmp(&g
, &ff_asf_command_stream
)) {
392 type
= AVMEDIA_TYPE_DATA
;
393 } else if (!ff_guidcmp(&g
, &ff_asf_ext_stream_embed_stream_header
)) {
394 test_for_ext_stream_audio
= 1;
395 type
= AVMEDIA_TYPE_UNKNOWN
;
400 avio_skip(pb
, 8); /* total_size */
401 type_specific_size
= avio_rl32(pb
);
403 st
->id
= avio_rl16(pb
) & 0x7f; /* stream id */
404 // mapping of asf ID to AV stream ID;
405 asf
->asfid2avid
[st
->id
] = s
->nb_streams
- 1;
406 asf_st
= &asf
->streams
[st
->id
];
410 if (test_for_ext_stream_audio
) {
412 if (!ff_guidcmp(&g
, &ff_asf_ext_stream_audio_stream
)) {
413 type
= AVMEDIA_TYPE_AUDIO
;
424 st
->codec
->codec_type
= type
;
425 if (type
== AVMEDIA_TYPE_AUDIO
) {
426 int ret
= ff_get_wav_header(pb
, st
->codec
, type_specific_size
);
429 if (is_dvr_ms_audio
) {
430 // codec_id and codec_tag are unreliable in dvr_ms
431 // files. Set them later by probing stream.
432 st
->request_probe
= 1;
433 st
->codec
->codec_tag
= 0;
435 if (st
->codec
->codec_id
== AV_CODEC_ID_AAC
)
436 st
->need_parsing
= AVSTREAM_PARSE_NONE
;
438 st
->need_parsing
= AVSTREAM_PARSE_FULL
;
439 /* We have to init the frame size at some point .... */
440 pos2
= avio_tell(pb
);
441 if (size
>= (pos2
+ 8 - pos1
+ 24)) {
442 asf_st
->ds_span
= avio_r8(pb
);
443 asf_st
->ds_packet_size
= avio_rl16(pb
);
444 asf_st
->ds_chunk_size
= avio_rl16(pb
);
445 avio_rl16(pb
); // ds_data_size
446 avio_r8(pb
); // ds_silence_data
448 if (asf_st
->ds_span
> 1) {
449 if (!asf_st
->ds_chunk_size
||
450 (asf_st
->ds_packet_size
/ asf_st
->ds_chunk_size
<= 1) ||
451 asf_st
->ds_packet_size
% asf_st
->ds_chunk_size
)
452 asf_st
->ds_span
= 0; // disable descrambling
454 } else if (type
== AVMEDIA_TYPE_VIDEO
&&
455 size
- (avio_tell(pb
) - pos1
+ 24) >= 51) {
459 avio_rl16(pb
); /* size */
460 sizeX
= avio_rl32(pb
); /* size */
461 st
->codec
->width
= avio_rl32(pb
);
462 st
->codec
->height
= avio_rl32(pb
);
463 /* not available for asf */
464 avio_rl16(pb
); /* panes */
465 st
->codec
->bits_per_coded_sample
= avio_rl16(pb
); /* depth */
466 tag1
= avio_rl32(pb
);
469 st
->codec
->extradata_size
= ffio_limit(pb
, sizeX
- 40);
470 st
->codec
->extradata
= av_mallocz(st
->codec
->extradata_size
+
471 FF_INPUT_BUFFER_PADDING_SIZE
);
472 if (!st
->codec
->extradata
)
473 return AVERROR(ENOMEM
);
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
;
506 if (st
->codec
->codec_id
== AV_CODEC_ID_MPEG4
)
507 st
->need_parsing
= AVSTREAM_PARSE_FULL_ONCE
;
509 pos2
= avio_tell(pb
);
510 avio_skip(pb
, size
- (pos2
- pos1
+ 24));
515 static int asf_read_ext_stream_properties(AVFormatContext
*s
, int64_t size
)
517 ASFContext
*asf
= s
->priv_data
;
518 AVIOContext
*pb
= s
->pb
;
520 int ext_len
, payload_ext_ct
, stream_ct
, i
;
521 uint32_t leak_rate
, stream_num
;
522 unsigned int stream_languageid_index
;
524 avio_rl64(pb
); // starttime
525 avio_rl64(pb
); // endtime
526 leak_rate
= avio_rl32(pb
); // leak-datarate
527 avio_rl32(pb
); // bucket-datasize
528 avio_rl32(pb
); // init-bucket-fullness
529 avio_rl32(pb
); // alt-leak-datarate
530 avio_rl32(pb
); // alt-bucket-datasize
531 avio_rl32(pb
); // alt-init-bucket-fullness
532 avio_rl32(pb
); // max-object-size
533 avio_rl32(pb
); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
534 stream_num
= avio_rl16(pb
); // stream-num
536 stream_languageid_index
= avio_rl16(pb
); // stream-language-id-index
537 if (stream_num
< 128)
538 asf
->streams
[stream_num
].stream_language_index
= stream_languageid_index
;
540 avio_rl64(pb
); // avg frametime in 100ns units
541 stream_ct
= avio_rl16(pb
); // stream-name-count
542 payload_ext_ct
= avio_rl16(pb
); // payload-extension-system-count
544 if (stream_num
< 128) {
545 asf
->stream_bitrates
[stream_num
] = leak_rate
;
546 asf
->streams
[stream_num
].payload_ext_ct
= 0;
549 for (i
= 0; i
< stream_ct
; i
++) {
551 ext_len
= avio_rl16(pb
);
552 avio_skip(pb
, ext_len
);
555 for (i
= 0; i
< payload_ext_ct
; i
++) {
558 size
= avio_rl16(pb
);
559 ext_len
= avio_rl32(pb
);
560 avio_skip(pb
, ext_len
);
561 if (stream_num
< 128 && i
< FF_ARRAY_ELEMS(asf
->streams
[stream_num
].payload
)) {
562 ASFPayload
*p
= &asf
->streams
[stream_num
].payload
[i
];
565 av_log(s
, AV_LOG_DEBUG
, "Payload extension %x %d\n", g
[0], p
->size
);
566 asf
->streams
[stream_num
].payload_ext_ct
++;
573 static int asf_read_content_desc(AVFormatContext
*s
, int64_t size
)
575 AVIOContext
*pb
= s
->pb
;
576 int len1
, len2
, len3
, len4
, len5
;
578 len1
= avio_rl16(pb
);
579 len2
= avio_rl16(pb
);
580 len3
= avio_rl16(pb
);
581 len4
= avio_rl16(pb
);
582 len5
= avio_rl16(pb
);
583 get_tag(s
, "title", 0, len1
, 32);
584 get_tag(s
, "author", 0, len2
, 32);
585 get_tag(s
, "copyright", 0, len3
, 32);
586 get_tag(s
, "comment", 0, len4
, 32);
592 static int asf_read_ext_content_desc(AVFormatContext
*s
, int64_t size
)
594 AVIOContext
*pb
= s
->pb
;
595 ASFContext
*asf
= s
->priv_data
;
596 int desc_count
, i
, ret
;
598 desc_count
= avio_rl16(pb
);
599 for (i
= 0; i
< desc_count
; i
++) {
600 int name_len
, value_type
, value_len
;
603 name_len
= avio_rl16(pb
);
604 if (name_len
% 2) // must be even, broken lavf versions wrote len-1
606 if ((ret
= avio_get_str16le(pb
, name_len
, name
, sizeof(name
))) < name_len
)
607 avio_skip(pb
, name_len
- ret
);
608 value_type
= avio_rl16(pb
);
609 value_len
= avio_rl16(pb
);
610 if (!value_type
&& value_len
% 2)
612 /* My sample has that stream set to 0 maybe that mean the container.
613 * ASF stream count starts at 1. I am using 0 to the container value
614 * since it's unused. */
615 if (!strcmp(name
, "AspectRatioX"))
616 asf
->dar
[0].num
= get_value(s
->pb
, value_type
, 32);
617 else if (!strcmp(name
, "AspectRatioY"))
618 asf
->dar
[0].den
= get_value(s
->pb
, value_type
, 32);
620 get_tag(s
, name
, value_type
, value_len
, 32);
626 static int asf_read_language_list(AVFormatContext
*s
, int64_t size
)
628 AVIOContext
*pb
= s
->pb
;
629 ASFContext
*asf
= s
->priv_data
;
631 int stream_count
= avio_rl16(pb
);
632 for (j
= 0; j
< stream_count
; j
++) {
634 unsigned int lang_len
= avio_r8(pb
);
635 if ((ret
= avio_get_str16le(pb
, lang_len
, lang
,
636 sizeof(lang
))) < lang_len
)
637 avio_skip(pb
, lang_len
- ret
);
639 av_strlcpy(asf
->stream_languages
[j
], lang
,
640 sizeof(*asf
->stream_languages
));
646 static int asf_read_metadata(AVFormatContext
*s
, int64_t size
)
648 AVIOContext
*pb
= s
->pb
;
649 ASFContext
*asf
= s
->priv_data
;
650 int n
, stream_num
, name_len
, value_len
;
654 for (i
= 0; i
< n
; i
++) {
658 avio_rl16(pb
); // lang_list_index
659 stream_num
= avio_rl16(pb
);
660 name_len
= avio_rl16(pb
);
661 value_type
= avio_rl16(pb
); /* value_type */
662 value_len
= avio_rl32(pb
);
664 if ((ret
= avio_get_str16le(pb
, name_len
, name
, sizeof(name
))) < name_len
)
665 avio_skip(pb
, name_len
- ret
);
666 av_dlog(s
, "%d stream %d name_len %2d type %d len %4d <%s>\n",
667 i
, stream_num
, name_len
, value_type
, value_len
, name
);
669 if (!strcmp(name
, "AspectRatioX")){
670 int aspect_x
= get_value(s
->pb
, value_type
, 16);
672 asf
->dar
[stream_num
].num
= aspect_x
;
673 } else if(!strcmp(name
, "AspectRatioY")){
674 int aspect_y
= get_value(s
->pb
, value_type
, 16);
676 asf
->dar
[stream_num
].den
= aspect_y
;
678 get_tag(s
, name
, value_type
, value_len
, 16);
685 static int asf_read_marker(AVFormatContext
*s
, int64_t size
)
687 AVIOContext
*pb
= s
->pb
;
688 ASFContext
*asf
= s
->priv_data
;
689 int i
, count
, name_len
, ret
;
692 avio_rl64(pb
); // reserved 16 bytes
693 avio_rl64(pb
); // ...
694 count
= avio_rl32(pb
); // markers count
695 avio_rl16(pb
); // reserved 2 bytes
696 name_len
= avio_rl16(pb
); // name length
697 for (i
= 0; i
< name_len
; i
++)
698 avio_r8(pb
); // skip the name
700 for (i
= 0; i
< count
; i
++) {
704 avio_rl64(pb
); // offset, 8 bytes
705 pres_time
= avio_rl64(pb
); // presentation time
706 pres_time
-= asf
->hdr
.preroll
* 10000;
707 avio_rl16(pb
); // entry length
708 avio_rl32(pb
); // send time
709 avio_rl32(pb
); // flags
710 name_len
= avio_rl32(pb
); // name length
711 if ((ret
= avio_get_str16le(pb
, name_len
* 2, name
,
712 sizeof(name
))) < name_len
)
713 avio_skip(pb
, name_len
- ret
);
714 avpriv_new_chapter(s
, i
, (AVRational
) { 1, 10000000 }, pres_time
,
715 AV_NOPTS_VALUE
, name
);
721 static int asf_read_header(AVFormatContext
*s
)
723 ASFContext
*asf
= s
->priv_data
;
725 AVIOContext
*pb
= s
->pb
;
730 if (ff_guidcmp(&g
, &ff_asf_header
))
731 return AVERROR_INVALIDDATA
;
736 memset(&asf
->asfid2avid
, -1, sizeof(asf
->asfid2avid
));
738 for (i
= 0; i
<128; i
++)
739 asf
->streams
[i
].stream_language_index
= 128; // invalid stream index means no language info
742 uint64_t gpos
= avio_tell(pb
);
744 gsize
= avio_rl64(pb
);
746 if (!ff_guidcmp(&g
, &ff_asf_data_header
)) {
747 asf
->data_object_offset
= avio_tell(pb
);
748 /* If not streaming, gsize is not unlimited (how?),
749 * and there is enough space in the file.. */
750 if (!(asf
->hdr
.flags
& 0x01) && gsize
>= 100)
751 asf
->data_object_size
= gsize
- 24;
753 asf
->data_object_size
= (uint64_t)-1;
757 return AVERROR_INVALIDDATA
;
758 if (!ff_guidcmp(&g
, &ff_asf_file_header
)) {
759 int ret
= asf_read_file_properties(s
, gsize
);
762 } else if (!ff_guidcmp(&g
, &ff_asf_stream_header
)) {
763 int ret
= asf_read_stream_properties(s
, gsize
);
766 } else if (!ff_guidcmp(&g
, &ff_asf_comment_header
)) {
767 asf_read_content_desc(s
, gsize
);
768 } else if (!ff_guidcmp(&g
, &ff_asf_language_guid
)) {
769 asf_read_language_list(s
, gsize
);
770 } else if (!ff_guidcmp(&g
, &ff_asf_extended_content_header
)) {
771 asf_read_ext_content_desc(s
, gsize
);
772 } else if (!ff_guidcmp(&g
, &ff_asf_metadata_header
)) {
773 asf_read_metadata(s
, gsize
);
774 } else if (!ff_guidcmp(&g
, &ff_asf_metadata_library_header
)) {
775 asf_read_metadata(s
, gsize
);
776 } else if (!ff_guidcmp(&g
, &ff_asf_ext_stream_header
)) {
777 asf_read_ext_stream_properties(s
, gsize
);
779 // there could be a optional stream properties object to follow
780 // if so the next iteration will pick it up
782 } else if (!ff_guidcmp(&g
, &ff_asf_head1_guid
)) {
786 } else if (!ff_guidcmp(&g
, &ff_asf_marker_header
)) {
787 asf_read_marker(s
, gsize
);
788 } else if (avio_feof(pb
)) {
792 if (!ff_guidcmp(&g
, &ff_asf_content_encryption
)) {
795 av_log(s
, AV_LOG_WARNING
,
796 "DRM protected stream detected, decoding will likely fail!\n");
798 av_log(s
, AV_LOG_DEBUG
, "Secret data:\n");
799 av_get_packet(pb
, &pkt
, len
); av_hex_dump_log(s
, AV_LOG_DEBUG
, pkt
.data
, pkt
.size
); av_free_packet(&pkt
);
801 get_tag(s
, "ASF_Protection_Type", -1, len
, 32);
803 get_tag(s
, "ASF_Key_ID", -1, len
, 32);
805 get_tag(s
, "ASF_License_URL", -1, len
, 32);
806 } else if (!ff_guidcmp(&g
, &ff_asf_ext_content_encryption
)) {
807 av_log(s
, AV_LOG_WARNING
,
808 "Ext DRM protected stream detected, decoding will likely fail!\n");
809 av_dict_set(&s
->metadata
, "encryption", "ASF Extended Content Encryption", 0);
810 } else if (!ff_guidcmp(&g
, &ff_asf_digital_signature
)) {
811 av_log(s
, AV_LOG_INFO
, "Digital signature detected!\n");
815 if (avio_tell(pb
) != gpos
+ gsize
)
816 av_log(s
, AV_LOG_DEBUG
,
817 "gpos mismatch our pos=%"PRIu64
", end=%"PRId64
"\n",
818 avio_tell(pb
) - gpos
, gsize
);
819 avio_seek(pb
, gpos
+ gsize
, SEEK_SET
);
827 asf
->data_offset
= avio_tell(pb
);
828 asf
->packet_size_left
= 0;
830 for (i
= 0; i
< 128; i
++) {
831 int stream_num
= asf
->asfid2avid
[i
];
832 if (stream_num
>= 0) {
833 AVStream
*st
= s
->streams
[stream_num
];
834 if (!st
->codec
->bit_rate
)
835 st
->codec
->bit_rate
= asf
->stream_bitrates
[i
];
836 if (asf
->dar
[i
].num
> 0 && asf
->dar
[i
].den
> 0) {
837 av_reduce(&st
->sample_aspect_ratio
.num
,
838 &st
->sample_aspect_ratio
.den
,
839 asf
->dar
[i
].num
, asf
->dar
[i
].den
, INT_MAX
);
840 } else if ((asf
->dar
[0].num
> 0) && (asf
->dar
[0].den
> 0) &&
841 // Use ASF container value if the stream doesn't set AR.
842 (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
))
843 av_reduce(&st
->sample_aspect_ratio
.num
,
844 &st
->sample_aspect_ratio
.den
,
845 asf
->dar
[0].num
, asf
->dar
[0].den
, INT_MAX
);
847 av_dlog(s
, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
848 i
, st
->codec
->codec_type
, asf
->dar
[i
].num
, asf
->dar
[i
].den
,
849 st
->sample_aspect_ratio
.num
, st
->sample_aspect_ratio
.den
);
851 // copy and convert language codes to the frontend
852 if (asf
->streams
[i
].stream_language_index
< 128) {
853 const char *rfc1766
= asf
->stream_languages
[asf
->streams
[i
].stream_language_index
];
854 if (rfc1766
&& strlen(rfc1766
) > 1) {
855 const char primary_tag
[3] = { rfc1766
[0], rfc1766
[1], '\0' }; // ignore country code if any
856 const char *iso6392
= av_convert_lang_to(primary_tag
,
857 AV_LANG_ISO639_2_BIBL
);
859 av_dict_set(&st
->metadata
, "language", iso6392
, 0);
865 ff_metadata_conv(&s
->metadata
, NULL
, ff_asf_metadata_conv
);
870 #define DO_2BITS(bits, var, defval) \
871 switch (bits & 3) { \
873 var = avio_rl32(pb); \
877 var = avio_rl16(pb); \
890 * Load a single ASF packet into the demuxer.
891 * @param s demux context
892 * @param pb context to read data from
893 * @return 0 on success, <0 on error
895 static int asf_get_packet(AVFormatContext
*s
, AVIOContext
*pb
)
897 ASFContext
*asf
= s
->priv_data
;
898 uint32_t packet_length
, padsize
;
902 // if we do not know packet size, allow skipping up to 32 kB
904 if (asf
->no_resync_search
)
906 else if (s
->packet_size
> 0)
907 off
= (avio_tell(pb
) - s
->data_offset
) % s
->packet_size
+ 3;
914 if (c
== 0x82 && !d
&& !e
)
919 /* This code allows handling of -EAGAIN at packet boundaries (i.e.
920 * if the packet sync code above triggers -EAGAIN). This does not
921 * imply complete -EAGAIN handling support at random positions in
923 if (pb
->error
== AVERROR(EAGAIN
))
924 return AVERROR(EAGAIN
);
926 av_log(s
, AV_LOG_ERROR
,
927 "ff asf bad header %x at:%"PRId64
"\n", c
, avio_tell(pb
));
929 if ((c
& 0x8f) == 0x82) {
932 av_log(s
, AV_LOG_ERROR
, "ff asf bad non zero\n");
933 return AVERROR_INVALIDDATA
;
938 } else if(!avio_feof(pb
)) {
939 avio_seek(pb
, -1, SEEK_CUR
); // FIXME
942 asf
->packet_flags
= c
;
943 asf
->packet_property
= d
;
945 DO_2BITS(asf
->packet_flags
>> 5, packet_length
, s
->packet_size
);
946 DO_2BITS(asf
->packet_flags
>> 1, padsize
, 0); // sequence ignored
947 DO_2BITS(asf
->packet_flags
>> 3, padsize
, 0); // padding length
949 // the following checks prevent overflows and infinite loops
950 if (!packet_length
|| packet_length
>= (1U << 29)) {
951 av_log(s
, AV_LOG_ERROR
,
952 "invalid packet_length %"PRIu32
" at:%"PRId64
"\n",
953 packet_length
, avio_tell(pb
));
954 return AVERROR_INVALIDDATA
;
956 if (padsize
>= packet_length
) {
957 av_log(s
, AV_LOG_ERROR
,
958 "invalid padsize %"PRIu32
" at:%"PRId64
"\n", padsize
, avio_tell(pb
));
959 return AVERROR_INVALIDDATA
;
962 asf
->packet_timestamp
= avio_rl32(pb
);
963 avio_rl16(pb
); /* duration */
964 // rsize has at least 11 bytes which have to be present
966 if (asf
->packet_flags
& 0x01) {
967 asf
->packet_segsizetype
= avio_r8(pb
);
969 asf
->packet_segments
= asf
->packet_segsizetype
& 0x3f;
971 asf
->packet_segments
= 1;
972 asf
->packet_segsizetype
= 0x80;
974 if (rsize
> packet_length
- padsize
) {
975 asf
->packet_size_left
= 0;
976 av_log(s
, AV_LOG_ERROR
,
977 "invalid packet header length %d for pktlen %"PRIu32
"-%"PRIu32
" at %"PRId64
"\n",
978 rsize
, packet_length
, padsize
, avio_tell(pb
));
979 return AVERROR_INVALIDDATA
;
981 asf
->packet_size_left
= packet_length
- padsize
- rsize
;
982 if (packet_length
< asf
->hdr
.min_pktsize
)
983 padsize
+= asf
->hdr
.min_pktsize
- packet_length
;
984 asf
->packet_padsize
= padsize
;
985 av_dlog(s
, "packet: size=%d padsize=%d left=%d\n",
986 s
->packet_size
, asf
->packet_padsize
, asf
->packet_size_left
);
992 * @return <0 if error
994 static int asf_read_frame_header(AVFormatContext
*s
, AVIOContext
*pb
)
996 ASFContext
*asf
= s
->priv_data
;
999 int num
= avio_r8(pb
);
1001 int64_t ts0
, ts1 av_unused
;
1003 asf
->packet_segments
--;
1004 asf
->packet_key_frame
= num
>> 7;
1005 asf
->stream_index
= asf
->asfid2avid
[num
& 0x7f];
1006 asfst
= &asf
->streams
[num
& 0x7f];
1007 // sequence should be ignored!
1008 DO_2BITS(asf
->packet_property
>> 4, asf
->packet_seq
, 0);
1009 DO_2BITS(asf
->packet_property
>> 2, asf
->packet_frag_offset
, 0);
1010 DO_2BITS(asf
->packet_property
, asf
->packet_replic_size
, 0);
1011 av_dlog(asf
, "key:%d stream:%d seq:%d offset:%d replic_size:%d\n",
1012 asf
->packet_key_frame
, asf
->stream_index
, asf
->packet_seq
,
1013 asf
->packet_frag_offset
, asf
->packet_replic_size
);
1014 if (rsize
+(int64_t)asf
->packet_replic_size
> asf
->packet_size_left
) {
1015 av_log(s
, AV_LOG_ERROR
, "packet_replic_size %d is invalid\n", asf
->packet_replic_size
);
1016 return AVERROR_INVALIDDATA
;
1018 if (asf
->packet_replic_size
>= 8) {
1019 int64_t end
= avio_tell(pb
) + asf
->packet_replic_size
;
1021 asfst
->packet_obj_size
= avio_rl32(pb
);
1022 if (asfst
->packet_obj_size
>= (1 << 24) || asfst
->packet_obj_size
<= 0) {
1023 av_log(s
, AV_LOG_ERROR
, "packet_obj_size invalid\n");
1024 asfst
->packet_obj_size
= 0;
1025 return AVERROR_INVALIDDATA
;
1027 asf
->packet_frag_timestamp
= avio_rl32(pb
); // timestamp
1029 for (i
= 0; i
< asfst
->payload_ext_ct
; i
++) {
1030 ASFPayload
*p
= &asfst
->payload
[i
];
1034 size
= avio_rl16(pb
);
1035 payend
= avio_tell(pb
) + size
;
1037 av_log(s
, AV_LOG_ERROR
, "too long payload\n");
1042 // duration = avio_rl16(pb);
1045 aspect
.num
= avio_r8(pb
);
1046 aspect
.den
= avio_r8(pb
);
1047 if (aspect
.num
> 0 && aspect
.den
> 0 && asf
->stream_index
>= 0) {
1048 s
->streams
[asf
->stream_index
]->sample_aspect_ratio
= aspect
;
1053 ts0
= avio_rl64(pb
);
1054 ts1
= avio_rl64(pb
);
1055 if (ts0
!= -1) asf
->packet_frag_timestamp
= ts0
/10000;
1056 else asf
->packet_frag_timestamp
= AV_NOPTS_VALUE
;
1067 avio_seek(pb
, payend
, SEEK_SET
);
1070 avio_seek(pb
, end
, SEEK_SET
);
1071 rsize
+= asf
->packet_replic_size
; // FIXME - check validity
1072 } else if (asf
->packet_replic_size
== 1) {
1073 // multipacket - frag_offset is beginning timestamp
1074 asf
->packet_time_start
= asf
->packet_frag_offset
;
1075 asf
->packet_frag_offset
= 0;
1076 asf
->packet_frag_timestamp
= asf
->packet_timestamp
;
1078 asf
->packet_time_delta
= avio_r8(pb
);
1080 } else if (asf
->packet_replic_size
!= 0) {
1081 av_log(s
, AV_LOG_ERROR
, "unexpected packet_replic_size of %d\n",
1082 asf
->packet_replic_size
);
1083 return AVERROR_INVALIDDATA
;
1085 if (asf
->packet_flags
& 0x01) {
1086 DO_2BITS(asf
->packet_segsizetype
>> 6, asf
->packet_frag_size
, 0); // 0 is illegal
1087 if (rsize
> asf
->packet_size_left
) {
1088 av_log(s
, AV_LOG_ERROR
, "packet_replic_size is invalid\n");
1089 return AVERROR_INVALIDDATA
;
1090 } else if (asf
->packet_frag_size
> asf
->packet_size_left
- rsize
) {
1091 if (asf
->packet_frag_size
> asf
->packet_size_left
- rsize
+ asf
->packet_padsize
) {
1092 av_log(s
, AV_LOG_ERROR
, "packet_frag_size is invalid (%d-%d)\n",
1093 asf
->packet_size_left
, rsize
);
1094 return AVERROR_INVALIDDATA
;
1096 int diff
= asf
->packet_frag_size
- (asf
->packet_size_left
- rsize
);
1097 asf
->packet_size_left
+= diff
;
1098 asf
->packet_padsize
-= diff
;
1102 asf
->packet_frag_size
= asf
->packet_size_left
- rsize
;
1104 if (asf
->packet_replic_size
== 1) {
1105 asf
->packet_multi_size
= asf
->packet_frag_size
;
1106 if (asf
->packet_multi_size
> asf
->packet_size_left
)
1107 return AVERROR_INVALIDDATA
;
1109 asf
->packet_size_left
-= rsize
;
1115 * Parse data from individual ASF packets (which were previously loaded
1116 * with asf_get_packet()).
1117 * @param s demux context
1118 * @param pb context to read data from
1119 * @param pkt pointer to store packet data into
1120 * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
1121 * packets need to be loaded (through asf_get_packet())
1123 static int asf_parse_packet(AVFormatContext
*s
, AVIOContext
*pb
, AVPacket
*pkt
)
1125 ASFContext
*asf
= s
->priv_data
;
1126 ASFStream
*asf_st
= 0;
1131 if (asf
->packet_size_left
< FRAME_HEADER_SIZE
||
1132 asf
->packet_segments
< 1 && asf
->packet_time_start
== 0) {
1133 int ret
= asf
->packet_size_left
+ asf
->packet_padsize
;
1139 asf
->packet_pos
= avio_tell(pb
);
1140 if (asf
->data_object_size
!= (uint64_t)-1 &&
1141 (asf
->packet_pos
- asf
->data_object_offset
>= asf
->data_object_size
))
1142 return AVERROR_EOF
; /* Do not exceed the size of the data object */
1145 if (asf
->packet_time_start
== 0) {
1146 if (asf_read_frame_header(s
, pb
) < 0) {
1147 asf
->packet_time_start
= asf
->packet_segments
= 0;
1150 if (asf
->stream_index
< 0 ||
1151 s
->streams
[asf
->stream_index
]->discard
>= AVDISCARD_ALL
||
1152 (!asf
->packet_key_frame
&&
1153 (s
->streams
[asf
->stream_index
]->discard
>= AVDISCARD_NONKEY
|| asf
->streams
[s
->streams
[asf
->stream_index
]->id
].skip_to_key
))) {
1154 asf
->packet_time_start
= 0;
1155 /* unhandled packet (should not happen) */
1156 avio_skip(pb
, asf
->packet_frag_size
);
1157 asf
->packet_size_left
-= asf
->packet_frag_size
;
1158 if (asf
->stream_index
< 0)
1159 av_log(s
, AV_LOG_ERROR
, "ff asf skip %d (unknown stream)\n",
1160 asf
->packet_frag_size
);
1163 asf
->asf_st
= &asf
->streams
[s
->streams
[asf
->stream_index
]->id
];
1164 asf
->asf_st
->skip_to_key
= 0;
1166 asf_st
= asf
->asf_st
;
1169 if (!asf_st
->frag_offset
&& asf
->packet_frag_offset
) {
1170 av_dlog(s
, "skipping asf data pkt with fragment offset for "
1171 "stream:%d, expected:%d but got %d from pkt)\n",
1172 asf
->stream_index
, asf_st
->frag_offset
,
1173 asf
->packet_frag_offset
);
1174 avio_skip(pb
, asf
->packet_frag_size
);
1175 asf
->packet_size_left
-= asf
->packet_frag_size
;
1179 if (asf
->packet_replic_size
== 1) {
1180 // frag_offset is here used as the beginning timestamp
1181 asf
->packet_frag_timestamp
= asf
->packet_time_start
;
1182 asf
->packet_time_start
+= asf
->packet_time_delta
;
1183 asf_st
->packet_obj_size
= asf
->packet_frag_size
= avio_r8(pb
);
1184 asf
->packet_size_left
--;
1185 asf
->packet_multi_size
--;
1186 if (asf
->packet_multi_size
< asf_st
->packet_obj_size
) {
1187 asf
->packet_time_start
= 0;
1188 avio_skip(pb
, asf
->packet_multi_size
);
1189 asf
->packet_size_left
-= asf
->packet_multi_size
;
1192 asf
->packet_multi_size
-= asf_st
->packet_obj_size
;
1195 if (asf_st
->pkt
.size
!= asf_st
->packet_obj_size
||
1196 // FIXME is this condition sufficient?
1197 asf_st
->frag_offset
+ asf
->packet_frag_size
> asf_st
->pkt
.size
) {
1200 if (asf_st
->pkt
.data
) {
1201 av_log(s
, AV_LOG_INFO
,
1202 "freeing incomplete packet size %d, new %d\n",
1203 asf_st
->pkt
.size
, asf_st
->packet_obj_size
);
1204 asf_st
->frag_offset
= 0;
1205 av_free_packet(&asf_st
->pkt
);
1208 if ((ret
= av_new_packet(&asf_st
->pkt
, asf_st
->packet_obj_size
)) < 0)
1210 asf_st
->seq
= asf
->packet_seq
;
1211 if (asf
->ts_is_pts
) {
1212 asf_st
->pkt
.pts
= asf
->packet_frag_timestamp
- asf
->hdr
.preroll
;
1214 asf_st
->pkt
.dts
= asf
->packet_frag_timestamp
- asf
->hdr
.preroll
;
1215 asf_st
->pkt
.stream_index
= asf
->stream_index
;
1216 asf_st
->pkt
.pos
= asf_st
->packet_pos
= asf
->packet_pos
;
1217 asf_st
->pkt_clean
= 0;
1219 if (asf_st
->pkt
.data
&& asf_st
->palette_changed
) {
1221 pal
= av_packet_new_side_data(&asf_st
->pkt
, AV_PKT_DATA_PALETTE
,
1224 av_log(s
, AV_LOG_ERROR
, "Cannot append palette to packet\n");
1226 memcpy(pal
, asf_st
->palette
, AVPALETTE_SIZE
);
1227 asf_st
->palette_changed
= 0;
1230 av_dlog(asf
, "new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
1231 asf
->stream_index
, asf
->packet_key_frame
,
1232 asf_st
->pkt
.flags
& AV_PKT_FLAG_KEY
,
1233 s
->streams
[asf
->stream_index
]->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
,
1234 asf_st
->packet_obj_size
);
1235 if (s
->streams
[asf
->stream_index
]->codec
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1236 asf
->packet_key_frame
= 1;
1237 if (asf
->packet_key_frame
)
1238 asf_st
->pkt
.flags
|= AV_PKT_FLAG_KEY
;
1242 av_dlog(asf
, "READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
1243 s
->packet_size
, asf_st
->pkt
.size
, asf
->packet_frag_offset
,
1244 asf_st
->frag_offset
, asf
->packet_frag_size
, asf_st
->pkt
.data
);
1245 asf
->packet_size_left
-= asf
->packet_frag_size
;
1246 if (asf
->packet_size_left
< 0)
1249 if (asf
->packet_frag_offset
>= asf_st
->pkt
.size
||
1250 asf
->packet_frag_size
> asf_st
->pkt
.size
- asf
->packet_frag_offset
) {
1251 av_log(s
, AV_LOG_ERROR
,
1252 "packet fragment position invalid %u,%u not in %u\n",
1253 asf
->packet_frag_offset
, asf
->packet_frag_size
,
1258 if (asf
->packet_frag_offset
!= asf_st
->frag_offset
&& !asf_st
->pkt_clean
) {
1259 memset(asf_st
->pkt
.data
+ asf_st
->frag_offset
, 0, asf_st
->pkt
.size
- asf_st
->frag_offset
);
1260 asf_st
->pkt_clean
= 1;
1263 ret
= avio_read(pb
, asf_st
->pkt
.data
+ asf
->packet_frag_offset
,
1264 asf
->packet_frag_size
);
1265 if (ret
!= asf
->packet_frag_size
) {
1266 if (ret
< 0 || asf
->packet_frag_offset
+ ret
== 0)
1267 return ret
< 0 ? ret
: AVERROR_EOF
;
1269 if (asf_st
->ds_span
> 1) {
1270 // scrambling, we can either drop it completely or fill the remainder
1271 // TODO: should we fill the whole packet instead of just the current
1273 memset(asf_st
->pkt
.data
+ asf
->packet_frag_offset
+ ret
, 0,
1274 asf
->packet_frag_size
- ret
);
1275 ret
= asf
->packet_frag_size
;
1277 // no scrambling, so we can return partial packets
1278 av_shrink_packet(&asf_st
->pkt
, asf
->packet_frag_offset
+ ret
);
1281 if (s
->key
&& s
->keylen
== 20)
1282 ff_asfcrypt_dec(s
->key
, asf_st
->pkt
.data
+ asf
->packet_frag_offset
,
1284 asf_st
->frag_offset
+= ret
;
1285 /* test if whole packet is read */
1286 if (asf_st
->frag_offset
== asf_st
->pkt
.size
) {
1287 // workaround for macroshit radio DVR-MS files
1288 if (s
->streams
[asf
->stream_index
]->codec
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
&&
1289 asf_st
->pkt
.size
> 100) {
1291 for (i
= 0; i
< asf_st
->pkt
.size
&& !asf_st
->pkt
.data
[i
]; i
++)
1293 if (i
== asf_st
->pkt
.size
) {
1294 av_log(s
, AV_LOG_DEBUG
, "discarding ms fart\n");
1295 asf_st
->frag_offset
= 0;
1296 av_free_packet(&asf_st
->pkt
);
1302 if (asf_st
->ds_span
> 1) {
1303 if (asf_st
->pkt
.size
!= asf_st
->ds_packet_size
* asf_st
->ds_span
) {
1304 av_log(s
, AV_LOG_ERROR
,
1305 "pkt.size != ds_packet_size * ds_span (%d %d %d)\n",
1306 asf_st
->pkt
.size
, asf_st
->ds_packet_size
,
1309 /* packet descrambling */
1310 AVBufferRef
*buf
= av_buffer_alloc(asf_st
->pkt
.size
+
1311 FF_INPUT_BUFFER_PADDING_SIZE
);
1313 uint8_t *newdata
= buf
->data
;
1315 memset(newdata
+ asf_st
->pkt
.size
, 0,
1316 FF_INPUT_BUFFER_PADDING_SIZE
);
1317 while (offset
< asf_st
->pkt
.size
) {
1318 int off
= offset
/ asf_st
->ds_chunk_size
;
1319 int row
= off
/ asf_st
->ds_span
;
1320 int col
= off
% asf_st
->ds_span
;
1321 int idx
= row
+ col
* asf_st
->ds_packet_size
/ asf_st
->ds_chunk_size
;
1322 assert(offset
+ asf_st
->ds_chunk_size
<= asf_st
->pkt
.size
);
1323 assert(idx
+ 1 <= asf_st
->pkt
.size
/ asf_st
->ds_chunk_size
);
1324 memcpy(newdata
+ offset
,
1325 asf_st
->pkt
.data
+ idx
* asf_st
->ds_chunk_size
,
1326 asf_st
->ds_chunk_size
);
1327 offset
+= asf_st
->ds_chunk_size
;
1329 av_buffer_unref(&asf_st
->pkt
.buf
);
1330 asf_st
->pkt
.buf
= buf
;
1331 asf_st
->pkt
.data
= buf
->data
;
1335 asf_st
->frag_offset
= 0;
1337 #if FF_API_DESTRUCT_PACKET
1338 FF_DISABLE_DEPRECATION_WARNINGS
1339 asf_st
->pkt
.destruct
= NULL
;
1340 FF_ENABLE_DEPRECATION_WARNINGS
1342 asf_st
->pkt
.buf
= 0;
1343 asf_st
->pkt
.size
= 0;
1344 asf_st
->pkt
.data
= 0;
1345 asf_st
->pkt
.side_data_elems
= 0;
1346 asf_st
->pkt
.side_data
= NULL
;
1347 break; // packet completed
1353 static int asf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
1355 ASFContext
*asf
= s
->priv_data
;
1360 /* parse cached packets, if any */
1361 if ((ret
= asf_parse_packet(s
, s
->pb
, pkt
)) <= 0)
1363 if ((ret
= asf_get_packet(s
, s
->pb
)) < 0)
1364 assert(asf
->packet_size_left
< FRAME_HEADER_SIZE
||
1365 asf
->packet_segments
< 1);
1366 asf
->packet_time_start
= 0;
1370 // Added to support seeking after packets have been read
1371 // If information is not reset, read_packet fails due to
1372 // leftover information from previous reads
1373 static void asf_reset_header(AVFormatContext
*s
)
1375 ASFContext
*asf
= s
->priv_data
;
1379 asf
->packet_size_left
= 0;
1380 asf
->packet_flags
= 0;
1381 asf
->packet_property
= 0;
1382 asf
->packet_timestamp
= 0;
1383 asf
->packet_segsizetype
= 0;
1384 asf
->packet_segments
= 0;
1385 asf
->packet_seq
= 0;
1386 asf
->packet_replic_size
= 0;
1387 asf
->packet_key_frame
= 0;
1388 asf
->packet_padsize
= 0;
1389 asf
->packet_frag_offset
= 0;
1390 asf
->packet_frag_size
= 0;
1391 asf
->packet_frag_timestamp
= 0;
1392 asf
->packet_multi_size
= 0;
1393 asf
->packet_time_delta
= 0;
1394 asf
->packet_time_start
= 0;
1396 for (i
= 0; i
< 128; i
++) {
1397 asf_st
= &asf
->streams
[i
];
1398 av_free_packet(&asf_st
->pkt
);
1399 asf_st
->packet_obj_size
= 0;
1400 asf_st
->frag_offset
= 0;
1406 static void skip_to_key(AVFormatContext
*s
)
1408 ASFContext
*asf
= s
->priv_data
;
1411 for (i
= 0; i
< 128; i
++) {
1412 int j
= asf
->asfid2avid
[i
];
1413 ASFStream
*asf_st
= &asf
->streams
[i
];
1414 if (j
< 0 || s
->streams
[j
]->codec
->codec_type
!= AVMEDIA_TYPE_VIDEO
)
1417 asf_st
->skip_to_key
= 1;
1421 static int asf_read_close(AVFormatContext
*s
)
1423 asf_reset_header(s
);
1428 static int64_t asf_read_pts(AVFormatContext
*s
, int stream_index
,
1429 int64_t *ppos
, int64_t pos_limit
)
1431 ASFContext
*asf
= s
->priv_data
;
1432 AVPacket pkt1
, *pkt
= &pkt1
;
1435 int64_t pos
= *ppos
;
1437 int64_t start_pos
[ASF_MAX_STREAMS
];
1439 for (i
= 0; i
< s
->nb_streams
; i
++)
1442 if (s
->packet_size
> 0)
1443 pos
= (pos
+ s
->packet_size
- 1 - s
->data_offset
) /
1444 s
->packet_size
* s
->packet_size
+
1447 if (avio_seek(s
->pb
, pos
, SEEK_SET
) < 0)
1448 return AV_NOPTS_VALUE
;
1450 ff_read_frame_flush(s
);
1451 asf_reset_header(s
);
1453 if (av_read_frame(s
, pkt
) < 0) {
1454 av_log(s
, AV_LOG_INFO
, "asf_read_pts failed\n");
1455 return AV_NOPTS_VALUE
;
1460 av_free_packet(pkt
);
1461 if (pkt
->flags
& AV_PKT_FLAG_KEY
) {
1462 i
= pkt
->stream_index
;
1464 asf_st
= &asf
->streams
[s
->streams
[i
]->id
];
1466 // assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0);
1467 pos
= asf_st
->packet_pos
;
1469 av_add_index_entry(s
->streams
[i
], pos
, pts
, pkt
->size
,
1470 pos
- start_pos
[i
] + 1, AVINDEX_KEYFRAME
);
1471 start_pos
[i
] = asf_st
->packet_pos
+ 1;
1473 if (pkt
->stream_index
== stream_index
)
1482 static int asf_build_simple_index(AVFormatContext
*s
, int stream_index
)
1485 ASFContext
*asf
= s
->priv_data
;
1486 int64_t current_pos
= avio_tell(s
->pb
);
1489 if((ret
= avio_seek(s
->pb
, asf
->data_object_offset
+ asf
->data_object_size
, SEEK_SET
)) < 0) {
1493 if ((ret
= ff_get_guid(s
->pb
, &g
)) < 0)
1496 /* the data object can be followed by other top-level objects,
1497 * skip them until the simple index object is reached */
1498 while (ff_guidcmp(&g
, &ff_asf_simple_index_header
)) {
1499 int64_t gsize
= avio_rl64(s
->pb
);
1500 if (gsize
< 24 || avio_feof(s
->pb
)) {
1503 avio_skip(s
->pb
, gsize
- 24);
1504 if ((ret
= ff_get_guid(s
->pb
, &g
)) < 0)
1509 int64_t itime
, last_pos
= -1;
1512 int64_t av_unused gsize
= avio_rl64(s
->pb
);
1513 if ((ret
= ff_get_guid(s
->pb
, &g
)) < 0)
1515 itime
= avio_rl64(s
->pb
);
1516 pct
= avio_rl32(s
->pb
);
1517 ict
= avio_rl32(s
->pb
);
1518 av_log(s
, AV_LOG_DEBUG
,
1519 "itime:0x%"PRIx64
", pct:%d, ict:%d\n", itime
, pct
, ict
);
1521 for (i
= 0; i
< ict
; i
++) {
1522 int pktnum
= avio_rl32(s
->pb
);
1523 int pktct
= avio_rl16(s
->pb
);
1524 int64_t pos
= s
->data_offset
+ s
->packet_size
* (int64_t)pktnum
;
1525 int64_t index_pts
= FFMAX(av_rescale(itime
, i
, 10000) - asf
->hdr
.preroll
, 0);
1527 if (pos
!= last_pos
) {
1528 av_log(s
, AV_LOG_DEBUG
, "pktnum:%d, pktct:%d pts: %"PRId64
"\n",
1529 pktnum
, pktct
, index_pts
);
1530 av_add_index_entry(s
->streams
[stream_index
], pos
, index_pts
,
1531 s
->packet_size
, 0, AVINDEX_KEYFRAME
);
1535 asf
->index_read
= ict
> 1;
1538 // if (avio_feof(s->pb)) {
1541 avio_seek(s
->pb
, current_pos
, SEEK_SET
);
1545 static int asf_read_seek(AVFormatContext
*s
, int stream_index
,
1546 int64_t pts
, int flags
)
1548 ASFContext
*asf
= s
->priv_data
;
1549 AVStream
*st
= s
->streams
[stream_index
];
1552 if (s
->packet_size
<= 0)
1555 /* Try using the protocol's read_seek if available */
1557 int ret
= avio_seek_time(s
->pb
, stream_index
, pts
, flags
);
1559 asf_reset_header(s
);
1560 if (ret
!= AVERROR(ENOSYS
))
1564 /* explicitly handle the case of seeking to 0 */
1566 asf_reset_header(s
);
1567 avio_seek(s
->pb
, s
->data_offset
, SEEK_SET
);
1571 if (!asf
->index_read
) {
1572 ret
= asf_build_simple_index(s
, stream_index
);
1574 asf
->index_read
= -1;
1577 if (asf
->index_read
> 0 && st
->index_entries
) {
1578 int index
= av_index_search_timestamp(st
, pts
, flags
);
1580 /* find the position */
1581 uint64_t pos
= st
->index_entries
[index
].pos
;
1584 av_log(s
, AV_LOG_DEBUG
, "SEEKTO: %"PRId64
"\n", pos
);
1585 if(avio_seek(s
->pb
, pos
, SEEK_SET
) < 0)
1587 asf_reset_header(s
);
1592 /* no index or seeking by index failed */
1593 if (ff_seek_frame_binary(s
, stream_index
, pts
, flags
) < 0)
1595 asf_reset_header(s
);
1600 AVInputFormat ff_asf_demuxer
= {
1602 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1603 .priv_data_size
= sizeof(ASFContext
),
1604 .read_probe
= asf_probe
,
1605 .read_header
= asf_read_header
,
1606 .read_packet
= asf_read_packet
,
1607 .read_close
= asf_read_close
,
1608 .read_seek
= asf_read_seek
,
1609 .read_timestamp
= asf_read_pts
,
1610 .flags
= AVFMT_NOBINSEARCH
| AVFMT_NOGENSEARCH
,
1611 .priv_class
= &asf_class
,