2 * Microsoft Advanced Streaming Format demuxer
3 * Copyright (c) 2014 Alexandra Hájková
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/attributes.h"
23 #include "libavutil/avassert.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/bswap.h"
26 #include "libavutil/common.h"
27 #include "libavutil/dict.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/mathematics.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/time_internal.h"
34 #include "avio_internal.h"
35 #include "avlanguage.h"
47 #define ASF_UNICODE 0x0
48 #define ASF_FLAG_BROADCAST 0x1
49 #define ASF_BYTE_ARRAY 0x1
50 #define ASF_TYPE_AUDIO 0x2
51 #define ASF_TYPE_VIDEO 0x1
52 #define ASF_STREAM_NUM 0x7F
53 #define ASF_MAX_STREAMS 128
54 #define BMP_HEADER_SIZE 40
55 #define ASF_NUM_OF_PAYLOADS 0x3F
56 #define ASF_ERROR_CORRECTION_LENGTH_TYPE 0x60
57 #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
59 typedef struct GUIDParseTable
{
62 int (*read_object
)(AVFormatContext
*, const struct GUIDParseTable
*);
66 typedef struct ASFPacket
{
69 uint32_t frame_num
; // ASF payloads with the same number are parts of the same frame
77 typedef struct ASFStream
{
78 uint8_t stream_index
; // from packet header
79 int index
; // stream index in AVFormatContext, set in asf_read_stream_properties
81 int indexed
; // added index entries from the Simple Index Object or not
82 int8_t span
; // for deinterleaving
83 uint16_t virtual_pkt_len
;
84 uint16_t virtual_chunk_len
;
89 typedef struct ASFStreamData
{
91 AVDictionary
*asf_met
; // for storing per-stream metadata
92 AVRational aspect_ratio
;
95 typedef struct ASFContext
{
97 int is_simple_index
; // is simple index present or not 1/0
101 uint64_t nb_packets
; // ASF packets
102 uint32_t packet_size
;
106 uint32_t b_flags
; // flags with broadcast flag
107 uint32_t prop_flags
; // file properties object flags
109 uint64_t data_size
; // data object size
110 uint64_t unknown_size
; // size of the unknown object
112 int64_t offset
; // offset of the current object
115 int64_t first_packet_offset
; // packet offset
116 int64_t unknown_offset
; // for top level header objects or subobjects without specified behavior
118 // ASF file must not contain more than 128 streams according to the specification
119 ASFStream
*asf_st
[ASF_MAX_STREAMS
];
120 ASFStreamData asf_sd
[ASF_MAX_STREAMS
];
123 int stream_index
; // from packet header, for the subpayload case
125 // packet parameteres
126 uint64_t sub_header_offset
; // offset of subplayload header
128 uint8_t dts_delta
; // for subpayloads
129 uint32_t packet_size_internal
; // packet size stored inside ASFPacket, can be 0
131 int64_t packet_offset
; // offset of the current packet inside Data Object
132 uint32_t pad_len
; // padding after payload
133 uint32_t rep_data_len
;
136 uint64_t sub_left
; // subpayloads left or not
137 int nb_sub
; // number of subpayloads read so far from the current ASF packet
138 uint16_t mult_sub_len
; // total length of subpayloads array inside multiple payload
139 uint64_t nb_mult_left
; // multiple payloads left
140 int return_subpayload
;
149 static int detect_unknown_subobject(AVFormatContext
*s
, int64_t offset
, int64_t size
);
150 static const GUIDParseTable
*find_guid(ff_asf_guid guid
);
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 static void swap_guid(ff_asf_guid guid
)
163 FFSWAP(unsigned char, guid
[0], guid
[3]);
164 FFSWAP(unsigned char, guid
[1], guid
[2]);
165 FFSWAP(unsigned char, guid
[4], guid
[5]);
166 FFSWAP(unsigned char, guid
[6], guid
[7]);
169 static void align_position(AVIOContext
*pb
, int64_t offset
, uint64_t size
)
171 if (avio_tell(pb
) != offset
+ size
)
172 avio_seek(pb
, offset
+ size
, SEEK_SET
);
175 static int asf_read_unknown(AVFormatContext
*s
, const GUIDParseTable
*g
)
177 ASFContext
*asf
= s
->priv_data
;
178 AVIOContext
*pb
= s
->pb
;
179 uint64_t size
= avio_rl64(pb
);
183 asf
->unknown_size
= size
;
185 if (!g
->is_subobject
) {
186 if (!(ret
= strcmp(g
->name
, "Header Extension")))
187 avio_skip(pb
, 22); // skip reserved fields and Data Size
188 if ((ret
= detect_unknown_subobject(s
, asf
->unknown_offset
,
189 asf
->unknown_size
)) < 0)
192 avio_skip(pb
, size
- 24);
197 static int get_asf_string(AVIOContext
*pb
, int maxlen
, char *buf
, int buflen
)
202 return AVERROR(EINVAL
);
203 while (ret
+ 1 < maxlen
) {
206 GET_UTF16(ch
, (ret
+= 2) <= maxlen ?
avio_rl16(pb
) : 0, break;);
207 PUT_UTF8(ch
, tmp
, if (q
- buf
< buflen
- 1) *q
++ = tmp
;)
214 static int asf_read_marker(AVFormatContext
*s
, const GUIDParseTable
*g
)
216 ASFContext
*asf
= s
->priv_data
;
217 AVIOContext
*pb
= s
->pb
;
218 uint64_t size
= avio_rl64(pb
);
219 int i
, nb_markers
, ret
;
224 avio_skip(pb
, 8); // skip reserved GUID
225 nb_markers
= avio_rl32(pb
);
226 avio_skip(pb
, 2); // skip reserved field
228 for (i
= 0; i
< len
; i
++)
231 for (i
= 0; i
< nb_markers
; i
++) {
236 pts
-= asf
->preroll
* 10000;
237 avio_skip(pb
, 2); // entry length
238 avio_skip(pb
, 4); // send time
239 avio_skip(pb
, 4); // flags
242 if ((ret
= avio_get_str16le(pb
, len
, name
,
243 sizeof(name
))) < len
)
244 avio_skip(pb
, len
- ret
);
245 avpriv_new_chapter(s
, i
, (AVRational
) { 1, 10000000 }, pts
,
246 AV_NOPTS_VALUE
, name
);
248 align_position(pb
, asf
->offset
, size
);
253 static int asf_read_metadata(AVFormatContext
*s
, const char *title
, uint16_t len
,
254 unsigned char *ch
, uint16_t buflen
)
256 AVIOContext
*pb
= s
->pb
;
258 avio_get_str16le(pb
, len
, ch
, buflen
);
259 if (av_dict_set(&s
->metadata
, title
, ch
, 0) < 0)
260 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
265 static int asf_read_value(AVFormatContext
*s
, uint8_t *name
, uint16_t name_len
,
266 uint16_t val_len
, int type
, AVDictionary
**met
)
270 uint16_t buflen
= 2 * val_len
+ 1;
271 AVIOContext
*pb
= s
->pb
;
273 value
= av_malloc(buflen
);
275 return AVERROR(ENOMEM
);
276 if (type
== ASF_UNICODE
) {
277 // get_asf_string reads UTF-16 and converts it to UTF-8 which needs longer buffer
278 if ((ret
= get_asf_string(pb
, val_len
, value
, buflen
)) < 0)
280 if (av_dict_set(met
, name
, value
, 0) < 0)
281 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
284 if (val_len
> sizeof(buf
))
285 return AVERROR_INVALIDDATA
;
286 if ((ret
= avio_read(pb
, value
, val_len
)) < 0)
288 if (ret
< 2 * val_len
)
291 value
[2 * val_len
- 1] = '\0';
292 snprintf(buf
, sizeof(buf
), "%s", value
);
293 if (av_dict_set(met
, name
, buf
, 0) < 0)
294 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
305 static int asf_read_generic_value(AVFormatContext
*s
, uint8_t *name
, uint16_t name_len
,
306 int type
, AVDictionary
**met
)
308 AVIOContext
*pb
= s
->pb
;
314 value
= avio_rl32(pb
);
317 value
= avio_rl32(pb
);
320 value
= avio_rl64(pb
);
323 value
= avio_rl16(pb
);
327 return AVERROR_INVALIDDATA
;
329 snprintf(buf
, sizeof(buf
), "%"PRIu64
, value
);
330 if (av_dict_set(met
, name
, buf
, 0) < 0)
331 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
336 /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
337 * but in reality this is only loosely similar */
338 static int asf_read_picture(AVFormatContext
*s
, int len
)
340 ASFContext
*asf
= s
->priv_data
;
341 AVPacket pkt
= { 0 };
342 const CodecMime
*mime
= ff_id3v2_mime_tags
;
343 enum AVCodecID id
= AV_CODEC_ID_NONE
;
345 uint8_t *desc
= NULL
;
347 int ret
, type
, picsize
, desc_len
;
350 /* type + picsize + mime + desc */
351 if (len
< 1 + 4 + 2 + 2) {
352 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture size: %d.\n", len
);
353 return AVERROR_INVALIDDATA
;
357 type
= avio_r8(s
->pb
);
359 if (type
>= FF_ARRAY_ELEMS(ff_id3v2_picture_types
) || type
< 0) {
360 av_log(s
, AV_LOG_WARNING
, "Unknown attached picture type: %d.\n", type
);
364 /* picture data size */
365 picsize
= avio_rl32(s
->pb
);
368 /* picture MIME type */
369 len
-= avio_get_str16le(s
->pb
, len
, mimetype
, sizeof(mimetype
));
370 while (mime
->id
!= AV_CODEC_ID_NONE
) {
371 if (!strncmp(mime
->str
, mimetype
, sizeof(mimetype
))) {
377 if (id
== AV_CODEC_ID_NONE
) {
378 av_log(s
, AV_LOG_ERROR
, "Unknown attached picture mimetype: %s.\n",
383 if (picsize
>= len
) {
384 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture data size: %d >= %d.\n",
386 return AVERROR_INVALIDDATA
;
389 /* picture description */
390 desc_len
= (len
- picsize
) * 2 + 1;
391 desc
= av_malloc(desc_len
);
393 return AVERROR(ENOMEM
);
394 len
-= avio_get_str16le(s
->pb
, len
- picsize
, desc
, desc_len
);
396 ret
= av_get_packet(s
->pb
, &pkt
, picsize
);
400 st
= avformat_new_stream(s
, NULL
);
402 ret
= AVERROR(ENOMEM
);
405 asf
->asf_st
[asf
->nb_streams
] = av_mallocz(sizeof(*asf_st
));
406 asf_st
= asf
->asf_st
[asf
->nb_streams
];
408 return AVERROR(ENOMEM
);
410 st
->disposition
|= AV_DISPOSITION_ATTACHED_PIC
;
411 st
->codec
->codec_type
= asf_st
->type
= AVMEDIA_TYPE_VIDEO
;
412 st
->codec
->codec_id
= id
;
413 st
->attached_pic
= pkt
;
414 st
->attached_pic
.stream_index
= asf_st
->index
= st
->index
;
415 st
->attached_pic
.flags
|= AV_PKT_FLAG_KEY
;
420 if (av_dict_set(&st
->metadata
, "title", desc
, AV_DICT_DONT_STRDUP_VAL
) < 0)
421 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
425 if (av_dict_set(&st
->metadata
, "comment", ff_id3v2_picture_types
[type
], 0) < 0)
426 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
432 av_free_packet(&pkt
);
436 static void get_id3_tag(AVFormatContext
*s
, int len
)
438 ID3v2ExtraMeta
*id3v2_extra_meta
= NULL
;
440 ff_id3v2_read(s
, ID3v2_DEFAULT_MAGIC
, &id3v2_extra_meta
);
441 if (id3v2_extra_meta
)
442 ff_id3v2_parse_apic(s
, &id3v2_extra_meta
);
443 ff_id3v2_free_extra_meta(&id3v2_extra_meta
);
446 static int process_metadata(AVFormatContext
*s
, uint8_t *name
, uint16_t name_len
,
447 uint16_t val_len
, uint16_t type
, AVDictionary
**met
)
455 asf_read_value(s
, name
, name_len
, val_len
, type
, met
);
458 if (!strcmp(name
, "WM/Picture")) // handle cover art
459 asf_read_picture(s
, val_len
);
460 else if (!strcmp(name
, "ID3")) // handle ID3 tag
461 get_id3_tag(s
, val_len
);
463 asf_read_value(s
, name
, name_len
, val_len
, type
, met
);
466 ff_get_guid(s
->pb
, &guid
);
469 if ((ret
= asf_read_generic_value(s
, name
, name_len
, type
, met
)) < 0)
479 static int asf_read_ext_content(AVFormatContext
*s
, const GUIDParseTable
*g
)
481 ASFContext
*asf
= s
->priv_data
;
482 AVIOContext
*pb
= s
->pb
;
483 uint64_t size
= avio_rl64(pb
);
484 uint16_t nb_desc
= avio_rl16(pb
);
487 for (i
= 0; i
< nb_desc
; i
++) {
488 uint16_t name_len
, type
, val_len
;
489 uint8_t *name
= NULL
;
491 name_len
= avio_rl16(pb
);
493 return AVERROR_INVALIDDATA
;
494 name
= av_malloc(name_len
);
496 return AVERROR(ENOMEM
);
497 avio_get_str16le(pb
, name_len
, name
,
499 type
= avio_rl16(pb
);
500 val_len
= avio_rl16(pb
);
502 if ((ret
= process_metadata(s
, name
, name_len
, val_len
, type
, &s
->metadata
)) < 0)
506 align_position(pb
, asf
->offset
, size
);
510 static AVStream
*find_stream(AVFormatContext
*s
, uint16_t st_num
)
513 ASFContext
*asf
= s
->priv_data
;
516 for (i
= 0; i
< asf
->nb_streams
; i
++) {
517 if (asf
->asf_st
[i
]->stream_index
== st_num
) {
518 st
= s
->streams
[asf
->asf_st
[i
]->index
];
526 static void asf_store_aspect_ratio(AVFormatContext
*s
, uint8_t st_num
, uint8_t *name
)
528 ASFContext
*asf
= s
->priv_data
;
529 AVIOContext
*pb
= s
->pb
;
532 value
= avio_rl16(pb
);
534 if (st_num
< ASF_MAX_STREAMS
) {
535 if (!strcmp(name
, "AspectRatioX"))
536 asf
->asf_sd
[st_num
].aspect_ratio
.num
= value
;
538 asf
->asf_sd
[st_num
].aspect_ratio
.den
= value
;
542 static int asf_read_metadata_obj(AVFormatContext
*s
, const GUIDParseTable
*g
)
544 ASFContext
*asf
= s
->priv_data
;
545 AVIOContext
*pb
= s
->pb
;
546 uint64_t size
= avio_rl64(pb
);
547 uint16_t nb_recs
= avio_rl16(pb
); // number of records in the Description Records list
550 for (i
= 0; i
< nb_recs
; i
++) {
551 uint16_t name_len
, buflen
, type
, val_len
, st_num
;
552 uint8_t *name
= NULL
;
554 avio_skip(pb
, 2); // skip reserved field
555 st_num
= avio_rl16(pb
);
556 name_len
= avio_rl16(pb
);
557 buflen
= 2 * name_len
+ 1;
560 type
= avio_rl16(pb
);
561 val_len
= avio_rl32(pb
);
562 name
= av_malloc(name_len
);
564 return AVERROR(ENOMEM
);
565 avio_get_str16le(pb
, name_len
, name
,
568 if (!strcmp(name
, "AspectRatioX") || !strcmp(name
, "AspectRatioY")) {
569 asf_store_aspect_ratio(s
, st_num
, name
);
571 if (st_num
< ASF_MAX_STREAMS
) {
572 if ((ret
= process_metadata(s
, name
, name_len
, val_len
, type
,
573 &asf
->asf_sd
[st_num
].asf_met
)) < 0)
579 align_position(pb
, asf
->offset
, size
);
583 static int asf_read_content_desc(AVFormatContext
*s
, const GUIDParseTable
*g
)
585 ASFContext
*asf
= s
->priv_data
;
586 AVIOContext
*pb
= s
->pb
;
588 static const char *const titles
[] =
589 { "Title", "Author", "Copyright", "Description", "Rate" };
590 uint16_t len
[5], buflen
[5] = { 0 };
592 uint64_t size
= avio_rl64(pb
);
594 for (i
= 0; i
< 5; i
++) {
595 len
[i
] = avio_rl16(pb
);
596 // utf8 string should be <= 2 * utf16 string, extra byte for the terminator
597 buflen
[i
] = 2 * len
[i
] + 1;
600 for (i
= 0; i
< 5; i
++) {
601 ch
= av_malloc(buflen
[i
]);
603 return(AVERROR(ENOMEM
));
604 asf_read_metadata(s
, titles
[i
], len
[i
], ch
, buflen
[i
]);
607 align_position(pb
, asf
->offset
, size
);
612 static int asf_read_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
614 ASFContext
*asf
= s
->priv_data
;
615 AVIOContext
*pb
= s
->pb
;
616 uint64_t creation_time
;
618 avio_rl64(pb
); // read object size
619 avio_skip(pb
, 16); // skip File ID
620 avio_skip(pb
, 8); // skip File size
621 creation_time
= avio_rl64(pb
);
622 if (!(asf
->b_flags
& ASF_FLAG_BROADCAST
)) {
627 // creation date is in 100 ns units from 1 Jan 1601, conversion to s
628 creation_time
/= 10000000;
629 // there are 11644473600 seconds between 1 Jan 1601 and 1 Jan 1970
630 creation_time
-= 11644473600;
631 tm
= gmtime_r(&creation_time
, &tmbuf
);
633 if (!strftime(buf
, sizeof(buf
), "%Y-%m-%d %H:%M:%S", tm
))
638 if (av_dict_set(&s
->metadata
, "creation_time", buf
, 0) < 0)
639 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
642 asf
->nb_packets
= avio_rl64(pb
);
643 asf
->duration
= avio_rl64(pb
) / 10000; // stream duration
644 avio_skip(pb
, 8); // skip send duration
645 asf
->preroll
= avio_rl64(pb
);
646 asf
->duration
-= asf
->preroll
;
647 asf
->b_flags
= avio_rl32(pb
);
648 avio_skip(pb
, 4); // skip minimal packet size
649 asf
->packet_size
= avio_rl32(pb
);
650 avio_skip(pb
, 4); // skip max_bitrate
655 static int parse_video_info(AVIOContext
*pb
, AVStream
*st
)
660 st
->codec
->width
= avio_rl32(pb
);
661 st
->codec
->height
= avio_rl32(pb
);
662 avio_skip(pb
, 1); // skip reserved flags
663 size
= avio_rl16(pb
); // size of the Format Data
664 tag
= ff_get_bmp_header(pb
, st
);
665 st
->codec
->codec_tag
= tag
;
666 st
->codec
->codec_id
= ff_codec_get_id(ff_codec_bmp_tags
, tag
);
668 if (size
> BMP_HEADER_SIZE
) {
670 st
->codec
->extradata_size
= size
- BMP_HEADER_SIZE
;
671 if (!(st
->codec
->extradata
= av_malloc(st
->codec
->extradata_size
+
672 FF_INPUT_BUFFER_PADDING_SIZE
))) {
673 st
->codec
->extradata_size
= 0;
674 return AVERROR(ENOMEM
);
676 memset(st
->codec
->extradata
+ st
->codec
->extradata_size
, 0,
677 FF_INPUT_BUFFER_PADDING_SIZE
);
678 if ((ret
= avio_read(pb
, st
->codec
->extradata
,
679 st
->codec
->extradata_size
)) < 0)
685 static int asf_read_stream_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
687 ASFContext
*asf
= s
->priv_data
;
688 AVIOContext
*pb
= s
->pb
;
690 uint32_t err_data_len
, ts_data_len
; // type specific data length
692 ff_asf_guid stream_type
;
693 enum AVMediaType type
;
695 uint8_t stream_index
;
699 // ASF file must not contain more than 128 streams according to the specification
700 if (asf
->nb_streams
>= ASF_MAX_STREAMS
)
701 return AVERROR_INVALIDDATA
;
703 size
= avio_rl64(pb
);
704 ff_get_guid(pb
, &stream_type
);
705 if (!ff_guidcmp(&stream_type
, &ff_asf_audio_stream
))
706 type
= AVMEDIA_TYPE_AUDIO
;
707 else if (!ff_guidcmp(&stream_type
, &ff_asf_video_stream
))
708 type
= AVMEDIA_TYPE_VIDEO
;
709 else if (!ff_guidcmp(&stream_type
, &ff_asf_jfif_media
))
710 type
= AVMEDIA_TYPE_VIDEO
;
711 else if (!ff_guidcmp(&stream_type
, &ff_asf_command_stream
))
712 type
= AVMEDIA_TYPE_DATA
;
713 else if (!ff_guidcmp(&stream_type
,
714 &ff_asf_ext_stream_embed_stream_header
))
715 type
= AVMEDIA_TYPE_UNKNOWN
;
717 return AVERROR_INVALIDDATA
;
719 ff_get_guid(pb
, &stream_type
); // error correction type
720 avio_skip(pb
, 8); // skip the time offset
721 ts_data_len
= avio_rl32(pb
);
722 err_data_len
= avio_rl32(pb
);
723 flags
= avio_rl16(pb
); // bit 15 - Encrypted Content
725 stream_index
= flags
& ASF_STREAM_NUM
;
726 for (i
= 0; i
< asf
->nb_streams
; i
++)
727 if (stream_index
== asf
->asf_st
[i
]->stream_index
) {
728 av_log(s
, AV_LOG_WARNING
,
729 "Duplicate stream found, this stream will be ignored.\n");
730 align_position(pb
, asf
->offset
, size
);
734 st
= avformat_new_stream(s
, NULL
);
736 return AVERROR(ENOMEM
);
737 avpriv_set_pts_info(st
, 32, 1, 1000); // pts should be dword, in milliseconds
738 st
->codec
->codec_type
= type
;
739 asf
->asf_st
[asf
->nb_streams
] = av_mallocz(sizeof(*asf_st
));
740 if (!asf
->asf_st
[asf
->nb_streams
])
741 return AVERROR(ENOMEM
);
742 asf_st
= asf
->asf_st
[asf
->nb_streams
];
743 asf_st
->stream_index
= stream_index
;
744 asf_st
->index
= st
->index
;
746 st
->id
= flags
& ASF_STREAM_NUM
;
747 av_init_packet(&asf_st
->pkt
.avpkt
);
748 asf_st
->pkt
.data_size
= 0;
749 avio_skip(pb
, 4); // skip reserved field
752 case AVMEDIA_TYPE_AUDIO
:
753 asf_st
->type
= AVMEDIA_TYPE_AUDIO
;
754 if ((ret
= ff_get_wav_header(pb
, st
->codec
, ts_data_len
)) < 0)
757 case AVMEDIA_TYPE_VIDEO
:
758 asf_st
->type
= AVMEDIA_TYPE_VIDEO
;
759 if ((ret
= parse_video_info(pb
, st
)) < 0)
763 avio_skip(pb
, ts_data_len
);
768 if (type
== AVMEDIA_TYPE_AUDIO
) {
769 uint8_t span
= avio_r8(pb
);
772 asf_st
->virtual_pkt_len
= avio_rl16(pb
);
773 asf_st
->virtual_chunk_len
= avio_rl16(pb
);
774 avio_skip(pb
, err_data_len
- 5);
776 avio_skip(pb
, err_data_len
- 1);
778 avio_skip(pb
, err_data_len
);
782 align_position(pb
, asf
->offset
, size
);
787 static void set_language(AVFormatContext
*s
, const char *rfc1766
, AVDictionary
**met
)
789 // language abbr should contain at least 2 chars
790 if (rfc1766
&& strlen(rfc1766
) > 1) {
791 const char primary_tag
[3] = { rfc1766
[0], rfc1766
[1], '\0' }; // ignore country code if any
792 const char *iso6392
= av_convert_lang_to(primary_tag
,
793 AV_LANG_ISO639_2_BIBL
);
795 if (av_dict_set(met
, "language", iso6392
, 0) < 0)
796 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
800 static int asf_read_ext_stream_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
802 ASFContext
*asf
= s
->priv_data
;
803 AVIOContext
*pb
= s
->pb
;
806 uint16_t nb_st_name
, nb_pay_exts
, st_num
, lang_idx
;
809 uint64_t start_time
, end_time
, time_per_frame
;
810 uint64_t size
= avio_rl64(pb
);
812 start_time
= avio_rl64(pb
);
813 end_time
= avio_rl64(pb
);
814 bitrate
= avio_rl32(pb
);
815 avio_skip(pb
, 28); // skip some unused values
816 st_num
= avio_rl16(pb
);
817 st_num
&= ASF_STREAM_NUM
;
818 lang_idx
= avio_rl16(pb
); // Stream Language ID Index
819 for (i
= 0; i
< asf
->nb_streams
; i
++) {
820 if (st_num
== asf
->asf_st
[i
]->stream_index
) {
821 st
= s
->streams
[asf
->asf_st
[i
]->index
];
822 asf
->asf_st
[i
]->lang_idx
= lang_idx
;
826 time_per_frame
= avio_rl64(pb
); // average time per frame
828 st
->start_time
= start_time
;
829 st
->duration
= end_time
- start_time
;
830 st
->codec
->bit_rate
= bitrate
;
831 st
->avg_frame_rate
.num
= 10000000;
832 st
->avg_frame_rate
.den
= time_per_frame
;
834 nb_st_name
= avio_rl16(pb
);
835 nb_pay_exts
= avio_rl16(pb
);
836 for (i
= 0; i
< nb_st_name
; i
++) {
839 avio_rl16(pb
); // Language ID Index
844 for (i
= 0; i
< nb_pay_exts
; i
++) {
846 avio_skip(pb
, 16); // Extension System ID
847 avio_skip(pb
, 2); // Extension Data Size
852 if ((ret
= ff_get_guid(pb
, &guid
)) < 0) {
853 align_position(pb
, asf
->offset
, size
);
859 if (g
&& !(strcmp(g
->name
, "Stream Properties"))) {
860 if ((ret
= g
->read_object(s
, g
)) < 0)
864 align_position(pb
, asf
->offset
, size
);
868 static int asf_read_language_list(AVFormatContext
*s
, const GUIDParseTable
*g
)
870 ASFContext
*asf
= s
->priv_data
;
871 AVIOContext
*pb
= s
->pb
;
873 uint64_t size
= avio_rl64(pb
);
874 uint16_t nb_langs
= avio_rl16(pb
);
876 if (nb_langs
< ASF_MAX_STREAMS
) {
877 for (i
= 0; i
< nb_langs
; i
++) {
882 if ((ret
= get_asf_string(pb
, len
, asf
->asf_sd
[i
].langs
,
883 sizeof(asf
->asf_sd
[i
].langs
))) < 0) {
889 align_position(pb
, asf
->offset
, size
);
893 // returns data object offset when reading this object for the first time
894 static int asf_read_data(AVFormatContext
*s
, const GUIDParseTable
*g
)
896 ASFContext
*asf
= s
->priv_data
;
897 AVIOContext
*pb
= s
->pb
;
898 uint64_t size
= asf
->data_size
= avio_rl64(pb
);
901 if (!asf
->data_reached
&& pb
->seekable
) {
902 asf
->data_reached
= 1;
903 asf
->data_offset
= asf
->offset
;
906 for (i
= 0; i
< asf
->nb_streams
; i
++) {
907 if (!(asf
->b_flags
& ASF_FLAG_BROADCAST
))
908 s
->streams
[i
]->duration
= asf
->duration
;
910 asf
->nb_mult_left
= 0;
912 asf
->state
= PARSE_PACKET_HEADER
;
913 asf
->return_subpayload
= 0;
914 asf
->packet_size_internal
= 0;
915 avio_skip(pb
, 16); // skip File ID
916 size
= avio_rl64(pb
); // Total Data Packets
917 if (size
!= asf
->nb_packets
)
918 av_log(s
, AV_LOG_WARNING
,
919 "Number of Packets from File Properties Object is not equal to Total"
920 "Datapackets value! num of packets %"PRIu64
" total num %"PRIu64
".\n",
921 size
, asf
->nb_packets
);
922 avio_skip(pb
, 2); // skip reserved field
923 asf
->first_packet_offset
= avio_tell(pb
);
924 align_position(pb
, asf
->offset
, asf
->data_size
);
929 static int asf_read_simple_index(AVFormatContext
*s
, const GUIDParseTable
*g
)
931 ASFContext
*asf
= s
->priv_data
;
932 AVIOContext
*pb
= s
->pb
;
934 uint64_t interval
; // index entry time interval in 100 ns units, usually it's 1s
935 uint32_t pkt_num
, nb_entries
;
936 int32_t prev_pkt_num
= -1;
938 uint64_t size
= avio_rl64(pb
);
940 // simple index objects should be ordered by stream number, this loop tries to find
941 // the first not indexed video stream
942 for (i
= 0; i
< asf
->nb_streams
; i
++) {
943 if ((asf
->asf_st
[i
]->type
== AVMEDIA_TYPE_VIDEO
) && !asf
->asf_st
[i
]->indexed
) {
944 asf
->asf_st
[i
]->indexed
= 1;
945 st
= s
->streams
[asf
->asf_st
[i
]->index
];
950 avio_skip(pb
, size
- 24); // if there's no video stream, skip index object
953 avio_skip(pb
, 16); // skip File ID
954 interval
= avio_rl64(pb
);
956 nb_entries
= avio_rl32(pb
);
957 for (i
= 0; i
< nb_entries
; i
++) {
958 pkt_num
= avio_rl32(pb
);
960 if (prev_pkt_num
!= pkt_num
) {
961 av_add_index_entry(st
, asf
->first_packet_offset
+ asf
->packet_size
*
962 pkt_num
, av_rescale(interval
, i
, 10000),
963 asf
->packet_size
, 0, AVINDEX_KEYFRAME
);
964 prev_pkt_num
= pkt_num
;
967 asf
->is_simple_index
= 1;
968 align_position(pb
, asf
->offset
, size
);
973 static const GUIDParseTable gdef
[] = {
974 { "Data", { 0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_data
, 1 },
975 { "Simple Index", { 0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB }, asf_read_simple_index
, 1 },
976 { "Content Description", { 0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_content_desc
, 1 },
977 { "Extended Content Description", { 0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50 }, asf_read_ext_content
, 1 },
978 { "Stream Bitrate Properties", { 0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2 }, asf_read_unknown
, 1 },
979 { "File Properties", { 0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_properties
, 1 },
980 { "Header Extension", { 0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_unknown
, 0 },
981 { "Stream Properties", { 0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_stream_properties
, 1 },
982 { "Codec List", { 0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown
, 1 },
983 { "Marker", { 0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_marker
, 1 },
984 { "Script Command", { 0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown
, 1 },
985 { "Language List", { 0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 }, asf_read_language_list
, 1},
986 { "Padding", { 0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8 }, asf_read_unknown
, 1 },
987 { "DRMv1 Header", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
988 { "DRMv2 Header", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c }, asf_read_unknown
, 1 },
989 { "Index", { 0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
990 { "Media Object Index", { 0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C }, asf_read_unknown
, 1 },
991 { "Timecode Index", { 0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C }, asf_read_unknown
, 0 },
992 { "Bitrate_Mutual_Exclusion", { 0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
993 { "Error Correction", { 0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_unknown
, 1 },
994 { "Content Branding", { 0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
995 { "Content Encryption", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
996 { "Extended Content Encryption", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C }, asf_read_unknown
, 1 },
997 { "Digital Signature", { 0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
998 { "Extended Stream Properties", { 0x14, 0xE6, 0xA5, 0xCB, 0xC6, 0x72, 0x43, 0x32, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A }, asf_read_ext_stream_properties
, 1 },
999 { "Advanced Mutual Exclusion", { 0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD }, asf_read_unknown
, 1 },
1000 { "Group Mutual Exclusion", { 0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49 }, asf_read_unknown
, 1},
1001 { "Stream Prioritization", { 0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24 }, asf_read_unknown
, 1 },
1002 { "Bandwidth Sharing Object", { 0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1003 { "Metadata", { 0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA }, asf_read_metadata_obj
, 1 },
1004 { "Metadata Library", { 0x44, 0x23, 0x1C, 0x94, 0x94, 0x98, 0x49, 0xD1, 0xA1, 0x41, 0x1D, 0x13, 0x4E, 0x45, 0x70, 0x54 }, asf_read_metadata_obj
, 1 },
1005 { "Audio Spread", { 0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }, asf_read_unknown
, 1 },
1006 { "Index Parameters", { 0xD6, 0xE2, 0x29, 0xDF, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1007 { "Content Encryption System Windows Media DRM Network Devices",
1008 { 0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D }, asf_read_unknown
, 1 },
1009 { "Mutex Language", { 0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1010 { "Mutex Bitrate", { 0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1011 { "Mutex Unknown", { 0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1012 { "Bandwith Sharing Exclusive", { 0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1013 { "Bandwith Sharing Partial", { 0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1014 { "Payload Extension System Timecode", { 0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E }, asf_read_unknown
, 1 },
1015 { "Payload Extension System File Name", { 0xE1, 0x65, 0xEC, 0x0E, 0x19, 0xED, 0x45, 0xD7, 0xB4, 0xA7, 0x25, 0xCB, 0xD1, 0xE2, 0x8E, 0x9B }, asf_read_unknown
, 1 },
1016 { "Payload Extension System Content Type", { 0xD5, 0x90, 0xDC, 0x20, 0x07, 0xBC, 0x43, 0x6C, 0x9C, 0xF7, 0xF3, 0xBB, 0xFB, 0xF1, 0xA4, 0xDC }, asf_read_unknown
, 1 },
1017 { "Payload Extension System Pixel Aspect Ratio", { 0x1, 0x1E, 0xE5, 0x54, 0xF9, 0xEA, 0x4B, 0xC8, 0x82, 0x1A, 0x37, 0x6B, 0x74, 0xE4, 0xC4, 0xB8 }, asf_read_unknown
, 1 },
1018 { "Payload Extension System Sample Duration", { 0xC6, 0xBD, 0x94, 0x50, 0x86, 0x7F, 0x49, 0x07, 0x83, 0xA3, 0xC7, 0x79, 0x21, 0xB7, 0x33, 0xAD }, asf_read_unknown
, 1 },
1019 { "Payload Extension System Encryption Sample ID", { 0x66, 0x98, 0xB8, 0x4E, 0x0A, 0xFA, 0x43, 0x30, 0xAE, 0xB2, 0x1C, 0x0A, 0x98, 0xD7, 0xA4, 0x4D }, asf_read_unknown
, 1 },
1020 { "Payload Extension System Degradable JPEG", { 0x00, 0xE1, 0xAF, 0x06, 0x7B, 0xEC, 0x11, 0xD1, 0xA5, 0x82, 0x00, 0xC0, 0x4F, 0xC2, 0x9C, 0xFB }, asf_read_unknown
, 1 },
1023 #define READ_LEN(flag, name, len) \
1025 if ((flag) == name ## IS_BYTE) \
1026 len = avio_r8(pb); \
1027 else if ((flag) == name ## IS_WORD) \
1028 len = avio_rl16(pb); \
1029 else if ((flag) == name ## IS_DWORD) \
1030 len = avio_rl32(pb); \
1035 static int asf_read_subpayload(AVFormatContext
*s
, AVPacket
*pkt
, int is_header
)
1037 ASFContext
*asf
= s
->priv_data
;
1038 AVIOContext
*pb
= s
->pb
;
1043 asf
->dts_delta
= avio_r8(pb
);
1044 if (asf
->nb_mult_left
) {
1045 asf
->mult_sub_len
= avio_rl16(pb
); // total
1047 asf
->sub_header_offset
= avio_tell(pb
);
1051 sub_len
= avio_r8(pb
);
1052 if ((ret
= av_get_packet(pb
, pkt
, sub_len
)) < 0) // each subpayload is entire frame
1054 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1055 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1056 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1060 asf
->return_subpayload
= 1;
1062 asf
->return_subpayload
= 0;
1066 pkt
->dts
= asf
->sub_dts
+ (asf
->nb_sub
- 1) * asf
->dts_delta
- asf
->preroll
;
1067 if (asf
->nb_mult_left
&& (avio_tell(pb
) >=
1068 (asf
->sub_header_offset
+ asf
->mult_sub_len
))) {
1070 asf
->nb_mult_left
--;
1072 if (avio_tell(pb
) >= asf
->packet_offset
+ asf
->packet_size
- asf
->pad_len
) {
1074 if (!asf
->nb_mult_left
) {
1075 avio_skip(pb
, asf
->pad_len
);
1076 if (avio_tell(pb
) != asf
->packet_offset
+ asf
->packet_size
) {
1077 if (!asf
->packet_size
)
1078 return AVERROR_INVALIDDATA
;
1079 av_log(s
, AV_LOG_WARNING
,
1080 "Position %"PRId64
" wrong, should be %"PRId64
"\n",
1081 avio_tell(pb
), asf
->packet_offset
+ asf
->packet_size
);
1082 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1090 static void reset_packet(ASFPacket
*asf_pkt
)
1092 asf_pkt
->size_left
= 0;
1093 asf_pkt
->data_size
= 0;
1094 asf_pkt
->duration
= 0;
1097 asf_pkt
->duration
= 0;
1098 av_free_packet(&asf_pkt
->avpkt
);
1099 av_init_packet(&asf_pkt
->avpkt
);
1102 static int asf_read_multiple_payload(AVFormatContext
*s
, AVPacket
*pkt
,
1105 ASFContext
*asf
= s
->priv_data
;
1106 AVIOContext
*pb
= s
->pb
;
1112 // if replicated lenght is 1, subpayloads are present
1113 if (asf
->rep_data_len
== 1) {
1115 asf
->state
= READ_MULTI_SUB
;
1116 pkt
->flags
= asf_pkt
->flags
;
1117 if ((ret
= asf_read_subpayload(s
, pkt
, 1)) < 0)
1120 if (!asf_pkt
->data_size
) {
1121 asf_pkt
->data_size
= asf_pkt
->size_left
= avio_rl32(pb
); // read media object size
1122 if (asf_pkt
->data_size
<= 0)
1124 if ((ret
= av_new_packet(&asf_pkt
->avpkt
, asf_pkt
->data_size
)) < 0)
1127 avio_skip(pb
, 4); // reading of media object size is already done
1128 asf_pkt
->dts
= avio_rl32(pb
); // read presentation time
1129 if ((asf
->rep_data_len
- 8) > 0)
1130 avio_skip(pb
, asf
->rep_data_len
- 8); // skip replicated data
1131 pay_len
= avio_rl16(pb
); // payload length should be WORD
1132 if (pay_len
> asf
->packet_size
) {
1133 av_log(s
, AV_LOG_ERROR
,
1134 "Error: invalid data packet size, pay_len %"PRIu16
", "
1135 "asf->packet_size %"PRIu32
", offset %"PRId64
".\n",
1136 pay_len
, asf
->packet_size
, avio_tell(pb
));
1137 return AVERROR_INVALIDDATA
;
1139 p
= asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
- asf_pkt
->size_left
;
1140 if (pay_len
> asf_pkt
->size_left
) {
1141 av_log(s
, AV_LOG_ERROR
,
1142 "Error: invalid buffer size, pay_len %d, data size left %d.\n",
1143 pay_len
, asf_pkt
->size_left
);
1144 skip
= pay_len
- asf_pkt
->size_left
;
1145 pay_len
= asf_pkt
->size_left
;
1147 if ((ret
= avio_read(pb
, p
, pay_len
)) < 0)
1149 if (s
->key
&& s
->keylen
== 20)
1150 ff_asfcrypt_dec(s
->key
, p
, ret
);
1151 avio_skip(pb
, skip
);
1152 asf_pkt
->size_left
-= pay_len
;
1153 asf
->nb_mult_left
--;
1159 static int asf_read_single_payload(AVFormatContext
*s
, AVPacket
*pkt
,
1162 ASFContext
*asf
= s
->priv_data
;
1163 AVIOContext
*pb
= s
->pb
;
1169 if (!asf_pkt
->data_size
) {
1170 asf_pkt
->data_size
= asf_pkt
->size_left
= avio_rl32(pb
); // read media object size
1171 if (asf_pkt
->data_size
<= 0)
1173 if ((ret
= av_new_packet(&asf_pkt
->avpkt
, asf_pkt
->data_size
)) < 0)
1176 avio_skip(pb
, 4); // skip media object size
1177 asf_pkt
->dts
= avio_rl32(pb
); // read presentation time
1178 if ((asf
->rep_data_len
- 8) > 0)
1179 avio_skip(pb
, asf
->rep_data_len
- 8); // skip replicated data
1180 offset
= avio_tell(pb
);
1182 // size of the payload - size of the packet without header and padding
1183 if (asf
->packet_size_internal
)
1184 size
= asf
->packet_size_internal
- offset
+ asf
->packet_offset
- asf
->pad_len
;
1186 size
= asf
->packet_size
- offset
+ asf
->packet_offset
- asf
->pad_len
;
1187 if (size
> asf
->packet_size
) {
1188 av_log(s
, AV_LOG_ERROR
,
1189 "Error: invalid data packet size, offset %"PRId64
".\n",
1191 return AVERROR_INVALIDDATA
;
1193 p
= asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
- asf_pkt
->size_left
;
1194 if (size
> asf_pkt
->size_left
)
1195 return AVERROR_INVALIDDATA
;
1196 if (asf_pkt
->size_left
> size
)
1197 asf_pkt
->size_left
-= size
;
1199 asf_pkt
->size_left
= 0;
1200 if ((ret
= avio_read(pb
, p
, size
)) < 0)
1202 if (s
->key
&& s
->keylen
== 20)
1203 ff_asfcrypt_dec(s
->key
, p
, ret
);
1204 if (asf
->packet_size_internal
)
1205 avio_skip(pb
, asf
->packet_size
- asf
->packet_size_internal
);
1206 avio_skip(pb
, asf
->pad_len
); // skip padding
1211 static int asf_read_payload(AVFormatContext
*s
, AVPacket
*pkt
)
1213 ASFContext
*asf
= s
->priv_data
;
1214 AVIOContext
*pb
= s
->pb
;
1216 ASFPacket
*asf_pkt
= NULL
;
1218 if (!asf
->sub_left
) {
1219 uint32_t off_len
, media_len
;
1222 stream_num
= avio_r8(pb
);
1223 asf
->stream_index
= stream_num
& ASF_STREAM_NUM
;
1224 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1225 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1226 asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1227 asf_pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1228 asf_pkt
->dts
= asf
->dts
;
1233 return AVERROR_INVALIDDATA
;
1234 if (stream_num
>> 7)
1235 asf_pkt
->flags
|= AV_PKT_FLAG_KEY
;
1236 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE
,
1237 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_
, media_len
);
1238 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE
,
1239 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_
, off_len
);
1240 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE
,
1241 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_
, asf
->rep_data_len
);
1242 if (asf_pkt
->size_left
&& (asf_pkt
->frame_num
!= media_len
)) {
1243 av_log(s
, AV_LOG_WARNING
, "Unfinished frame will be ignored\n");
1244 reset_packet(asf_pkt
);
1246 asf_pkt
->frame_num
= media_len
;
1247 asf
->sub_dts
= off_len
;
1248 if (asf
->nb_mult_left
) {
1249 if ((ret
= asf_read_multiple_payload(s
, pkt
, asf_pkt
)) < 0)
1251 } else if (asf
->rep_data_len
== 1) {
1253 asf
->state
= READ_SINGLE
;
1254 pkt
->flags
= asf_pkt
->flags
;
1255 if ((ret
= asf_read_subpayload(s
, pkt
, 1)) < 0)
1258 if ((ret
= asf_read_single_payload(s
, pkt
, asf_pkt
)) < 0)
1262 for (i
= 0; i
<= asf
->nb_streams
; i
++) {
1263 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1264 asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1269 return AVERROR_INVALIDDATA
;
1270 pkt
->flags
= asf_pkt
->flags
;
1271 pkt
->dts
= asf_pkt
->dts
;
1272 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1273 if ((ret
= asf_read_subpayload(s
, pkt
, 0)) < 0) // read subpayload without its header
1280 static int asf_read_packet_header(AVFormatContext
*s
)
1282 ASFContext
*asf
= s
->priv_data
;
1283 AVIOContext
*pb
= s
->pb
;
1285 uint32_t av_unused seq
;
1286 unsigned char error_flags
, len_flags
, pay_flags
;
1288 asf
->packet_offset
= avio_tell(pb
);
1289 error_flags
= avio_r8(pb
); // read Error Correction Flags
1290 if (error_flags
& ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT
)
1291 if (!(error_flags
& ASF_ERROR_CORRECTION_LENGTH_TYPE
)) {
1292 size
= error_flags
& ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
;
1293 avio_skip(pb
, size
);
1295 len_flags
= avio_r8(pb
);
1296 asf
->prop_flags
= avio_r8(pb
);
1297 READ_LEN(len_flags
& ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE
,
1298 ASF_PPI_FLAG_PACKET_LENGTH_FIELD_
, asf
->packet_size_internal
);
1299 READ_LEN(len_flags
& ASF_PPI_MASK_SEQUENCE_FIELD_SIZE
,
1300 ASF_PPI_FLAG_SEQUENCE_FIELD_
, seq
);
1301 READ_LEN(len_flags
& ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE
,
1302 ASF_PPI_FLAG_PADDING_LENGTH_FIELD_
, asf
->pad_len
);
1303 asf
->send_time
= avio_rl32(pb
); // send time
1304 avio_skip(pb
, 2); // skip duration
1305 if (len_flags
& ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
) { // Multiple Payloads present
1306 pay_flags
= avio_r8(pb
);
1307 asf
->nb_mult_left
= (pay_flags
& ASF_NUM_OF_PAYLOADS
);
1313 static int asf_deinterleave(AVFormatContext
*s
, ASFPacket
*asf_pkt
, int st_num
)
1315 ASFContext
*asf
= s
->priv_data
;
1316 ASFStream
*asf_st
= asf
->asf_st
[st_num
];
1317 unsigned char *p
= asf_pkt
->avpkt
.data
;
1318 uint16_t pkt_len
= asf
->asf_st
[st_num
]->virtual_pkt_len
;
1319 uint16_t chunk_len
= asf
->asf_st
[st_num
]->virtual_chunk_len
;
1320 int nchunks
= pkt_len
/ chunk_len
;
1322 int pos
= 0, j
, l
, ret
;
1325 if ((ret
= av_new_packet(&pkt
, asf_pkt
->data_size
)) < 0)
1328 while (asf_pkt
->data_size
>= asf_st
->span
* pkt_len
+ pos
) {
1329 if (pos
>= asf_pkt
->data_size
) {
1332 for (l
= 0; l
< pkt_len
; l
++) {
1333 if (pos
>= asf_pkt
->data_size
) {
1336 for (j
= 0; j
< asf_st
->span
; j
++) {
1337 if ((pos
+ chunk_len
) >= asf_pkt
->data_size
)
1339 memcpy(pkt
.data
+ pos
,
1340 p
+ (j
* nchunks
+ l
) * chunk_len
,
1345 p
+= asf_st
->span
* pkt_len
;
1346 if (p
> asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
)
1349 av_free_packet(&asf_pkt
->avpkt
);
1350 asf_pkt
->avpkt
= pkt
;
1355 static int asf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
1357 ASFContext
*asf
= s
->priv_data
;
1358 AVIOContext
*pb
= s
->pb
;
1361 if ((avio_tell(pb
) >= asf
->data_offset
+ asf
->data_size
) &&
1362 !(asf
->b_flags
& ASF_FLAG_BROADCAST
))
1364 while (!pb
->eof_reached
) {
1365 if (asf
->state
== PARSE_PACKET_HEADER
) {
1366 asf_read_packet_header(s
);
1367 if (!asf
->nb_mult_left
)
1368 asf
->state
= READ_SINGLE
;
1370 asf
->state
= READ_MULTI
;
1372 if ((ret
= asf_read_payload(s
, pkt
)) < 0)
1374 switch (asf
->state
) {
1377 asf
->state
= PARSE_PACKET_HEADER
;
1379 case READ_MULTI_SUB
:
1380 if (!asf
->sub_left
&& !asf
->nb_mult_left
) {
1381 asf
->state
= PARSE_PACKET_HEADER
;
1382 if (!asf
->return_subpayload
)
1383 avio_skip(pb
, asf
->pad_len
); // skip padding
1384 if (asf
->packet_offset
+ asf
->packet_size
> avio_tell(pb
))
1385 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1386 } else if (!asf
->sub_left
)
1387 asf
->state
= READ_MULTI
;
1390 if (!asf
->nb_mult_left
) {
1391 asf
->state
= PARSE_PACKET_HEADER
;
1392 if (!asf
->return_subpayload
) {
1393 avio_skip(pb
, asf
->pad_len
); // skip padding
1395 if (asf
->packet_offset
+ asf
->packet_size
> avio_tell(pb
))
1396 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1400 if (asf
->return_subpayload
) {
1401 asf
->return_subpayload
= 0;
1404 for (i
= 0; i
< s
->nb_streams
; i
++) {
1405 ASFPacket
*asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1406 if (asf_pkt
&& !asf_pkt
->size_left
&& asf_pkt
->data_size
) {
1407 if (asf
->asf_st
[i
]->span
> 1 &&
1408 asf
->asf_st
[i
]->type
== AVMEDIA_TYPE_AUDIO
)
1409 if ((ret
= asf_deinterleave(s
, asf_pkt
, i
)) < 0)
1411 av_packet_move_ref(pkt
, &asf_pkt
->avpkt
);
1412 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1413 pkt
->flags
= asf_pkt
->flags
;
1414 pkt
->dts
= asf_pkt
->dts
- asf
->preroll
;
1415 asf_pkt
->data_size
= 0;
1416 asf_pkt
->frame_num
= 0;
1422 if (pb
->eof_reached
)
1428 static int asf_read_close(AVFormatContext
*s
)
1430 ASFContext
*asf
= s
->priv_data
;
1433 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1434 av_free_packet(&asf
->asf_st
[i
]->pkt
.avpkt
);
1435 av_freep(&asf
->asf_st
[i
]);
1436 av_dict_free(&asf
->asf_sd
[i
].asf_met
);
1442 static void reset_packet_state(AVFormatContext
*s
)
1444 ASFContext
*asf
= s
->priv_data
;
1447 asf
->state
= PARSE_PACKET_HEADER
;
1449 asf
->return_subpayload
= 0;
1451 asf
->sub_header_offset
= 0;
1452 asf
->packet_offset
= asf
->first_packet_offset
;
1454 asf
->rep_data_len
= 0;
1456 asf
->mult_sub_len
= 0;
1457 asf
->nb_mult_left
= 0;
1459 asf
->prop_flags
= 0;
1462 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1463 ASFPacket
*pkt
= &asf
->asf_st
[i
]->pkt
;
1470 av_free_packet(&pkt
->avpkt
);
1471 av_init_packet(&pkt
->avpkt
);
1476 * Find a timestamp for the requested position within the payload
1477 * where the pos (position) is the offset inside the Data Object.
1478 * When position is not on the packet boundary, asf_read_timestamp tries
1479 * to find the closest packet offset after this position. If this packet
1480 * is a key frame, this packet timestamp is read and an index entry is created
1481 * for the packet. If this packet belongs to the requested stream,
1482 * asf_read_timestamp upgrades pos to the packet beginning offset and
1483 * returns this packet's dts. So returned dts is the dts of the first key frame with
1484 * matching stream number after given position.
1486 static int64_t asf_read_timestamp(AVFormatContext
*s
, int stream_index
,
1487 int64_t *pos
, int64_t pos_limit
)
1489 ASFContext
*asf
= s
->priv_data
;
1490 int64_t pkt_pos
= *pos
, pkt_offset
, dts
= AV_NOPTS_VALUE
, data_end
;
1494 data_end
= asf
->data_offset
+ asf
->data_size
;
1496 n
= (pkt_pos
- asf
->first_packet_offset
+ asf
->packet_size
- 1) /
1498 n
= av_clip(n
, 0, ((data_end
- asf
->first_packet_offset
) / asf
->packet_size
- 1));
1499 pkt_pos
= asf
->first_packet_offset
+ n
* asf
->packet_size
;
1501 avio_seek(s
->pb
, pkt_pos
, SEEK_SET
);
1502 pkt_offset
= pkt_pos
;
1504 reset_packet_state(s
);
1505 while (avio_tell(s
->pb
) < data_end
) {
1507 int i
, ret
, st_found
;
1509 av_init_packet(&pkt
);
1510 pkt_offset
= avio_tell(s
->pb
);
1511 if ((ret
= asf_read_packet(s
, &pkt
)) < 0) {
1512 dts
= AV_NOPTS_VALUE
;
1515 // ASFPacket may contain fragments of packets belonging to different streams,
1516 // pkt_offset is the offset of the first fragment within it.
1517 if ((pkt_offset
>= (pkt_pos
+ asf
->packet_size
)))
1518 pkt_pos
+= asf
->packet_size
;
1519 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1520 ASFStream
*st
= asf
->asf_st
[i
];
1523 if (pkt
.flags
& AV_PKT_FLAG_KEY
) {
1526 av_add_index_entry(s
->streams
[pkt
.stream_index
], pkt_pos
,
1527 dts
, pkt
.size
, 0, AVINDEX_KEYFRAME
);
1528 if (stream_index
== st
->index
) {
1537 av_free_packet(&pkt
);
1541 av_free_packet(&pkt
);
1545 static int asf_read_seek(AVFormatContext
*s
, int stream_index
,
1546 int64_t timestamp
, int flags
)
1548 ASFContext
*asf
= s
->priv_data
;
1551 if (s
->streams
[stream_index
]->nb_index_entries
&& asf
->is_simple_index
) {
1552 idx
= av_index_search_timestamp(s
->streams
[stream_index
], timestamp
, flags
);
1553 if (idx
< 0 || idx
>= s
->streams
[stream_index
]->nb_index_entries
)
1554 return AVERROR_INVALIDDATA
;
1555 avio_seek(s
->pb
, s
->streams
[stream_index
]->index_entries
[idx
].pos
, SEEK_SET
);
1557 if ((ret
= ff_seek_frame_binary(s
, stream_index
, timestamp
, flags
)) < 0)
1560 // asf_read_timestamp is called inside ff_seek_frame_binary and leaves state dirty,
1561 // so reset_packet_state have to be called after it.
1562 reset_packet_state(s
);
1568 static const GUIDParseTable
*find_guid(ff_asf_guid guid
)
1571 const GUIDParseTable
*g
;
1575 for (j
= 0; j
< FF_ARRAY_ELEMS(gdef
); j
++) {
1576 if (!(ret
= memcmp(guid
, g
->guid
, sizeof(g
->guid
))))
1584 static int detect_unknown_subobject(AVFormatContext
*s
, int64_t offset
, int64_t size
)
1586 ASFContext
*asf
= s
->priv_data
;
1587 AVIOContext
*pb
= s
->pb
;
1588 const GUIDParseTable
*g
= NULL
;
1592 while (avio_tell(pb
) <= offset
+ size
) {
1593 asf
->offset
= avio_tell(pb
);
1594 if ((ret
= ff_get_guid(pb
, &guid
)) < 0)
1596 g
= find_guid(guid
);
1598 if ((ret
= g
->read_object(s
, g
)) < 0)
1603 g2
.name
= "Unknown";
1604 g2
.is_subobject
= 1;
1605 asf_read_unknown(s
, &g2
);
1612 static int asf_read_header(AVFormatContext
*s
)
1614 ASFContext
*asf
= s
->priv_data
;
1615 AVIOContext
*pb
= s
->pb
;
1616 const GUIDParseTable
*g
= NULL
;
1622 asf
->is_simple_index
= 0;
1623 ff_get_guid(pb
, &guid
);
1624 if (ff_guidcmp(&guid
, &ff_asf_header
))
1625 return AVERROR_INVALIDDATA
;
1626 avio_skip(pb
, 8); // skip header object size
1627 avio_skip(pb
, 6); // skip number of header objects and 2 reserved bytes
1628 asf
->data_reached
= 0;
1630 /* 1 is here instead of pb->eof_reached because (when not streaming), Data are skipped
1631 * for the first time,
1632 * Index object is processed and got eof and then seeking back to the Data is performed.
1635 // for the cases when object size is invalid
1636 if (avio_tell(pb
) == asf
->offset
) {
1637 if (asf
->data_reached
)
1638 avio_seek(pb
, asf
->first_packet_offset
, SEEK_SET
);
1641 asf
->offset
= avio_tell(pb
);
1642 if ((ret
= ff_get_guid(pb
, &guid
)) < 0) {
1643 if (ret
== AVERROR_EOF
&& asf
->data_reached
) {
1644 avio_seek(pb
, asf
->first_packet_offset
, SEEK_SET
);
1649 g
= find_guid(guid
);
1651 asf
->unknown_offset
= asf
->offset
;
1653 if ((ret
= g
->read_object(s
, g
)) < 0)
1656 size
= avio_rl64(pb
);
1657 align_position(pb
, asf
->offset
, size
);
1659 if (asf
->data_reached
&& !pb
->seekable
)
1663 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1664 const char *rfc1766
= asf
->asf_sd
[asf
->asf_st
[i
]->lang_idx
].langs
;
1665 AVStream
*st
= s
->streams
[asf
->asf_st
[i
]->index
];
1666 set_language(s
, rfc1766
, &st
->metadata
);
1669 for (i
= 0; i
< ASF_MAX_STREAMS
; i
++) {
1670 AVStream
*st
= NULL
;
1672 st
= find_stream(s
, i
);
1674 av_dict_copy(&st
->metadata
, asf
->asf_sd
[i
].asf_met
, AV_DICT_IGNORE_SUFFIX
);
1675 if (asf
->asf_sd
[i
].aspect_ratio
.num
> 0 && asf
->asf_sd
[i
].aspect_ratio
.den
> 0) {
1676 st
->sample_aspect_ratio
.num
= asf
->asf_sd
[i
].aspect_ratio
.num
;
1677 st
->sample_aspect_ratio
.den
= asf
->asf_sd
[i
].aspect_ratio
.den
;
1685 AVInputFormat ff_asf_demuxer
= {
1687 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1688 .priv_data_size
= sizeof(ASFContext
),
1689 .read_probe
= asf_probe
,
1690 .read_header
= asf_read_header
,
1691 .read_packet
= asf_read_packet
,
1692 .read_close
= asf_read_close
,
1693 .read_timestamp
= asf_read_timestamp
,
1694 .read_seek
= asf_read_seek
,
1695 .flags
= AVFMT_NOBINSEARCH
| AVFMT_NOGENSEARCH
,