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)
580 align_position(pb
, asf
->offset
, size
);
584 static int asf_read_content_desc(AVFormatContext
*s
, const GUIDParseTable
*g
)
586 ASFContext
*asf
= s
->priv_data
;
587 AVIOContext
*pb
= s
->pb
;
589 static const char *const titles
[] =
590 { "Title", "Author", "Copyright", "Description", "Rate" };
591 uint16_t len
[5], buflen
[5] = { 0 };
593 uint64_t size
= avio_rl64(pb
);
595 for (i
= 0; i
< 5; i
++) {
596 len
[i
] = avio_rl16(pb
);
597 // utf8 string should be <= 2 * utf16 string, extra byte for the terminator
598 buflen
[i
] = 2 * len
[i
] + 1;
601 for (i
= 0; i
< 5; i
++) {
602 ch
= av_malloc(buflen
[i
]);
604 return(AVERROR(ENOMEM
));
605 asf_read_metadata(s
, titles
[i
], len
[i
], ch
, buflen
[i
]);
608 align_position(pb
, asf
->offset
, size
);
613 static int asf_read_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
615 ASFContext
*asf
= s
->priv_data
;
616 AVIOContext
*pb
= s
->pb
;
617 uint64_t creation_time
;
619 avio_rl64(pb
); // read object size
620 avio_skip(pb
, 16); // skip File ID
621 avio_skip(pb
, 8); // skip File size
622 creation_time
= avio_rl64(pb
);
623 if (!(asf
->b_flags
& ASF_FLAG_BROADCAST
)) {
628 // creation date is in 100 ns units from 1 Jan 1601, conversion to s
629 creation_time
/= 10000000;
630 // there are 11644473600 seconds between 1 Jan 1601 and 1 Jan 1970
631 creation_time
-= 11644473600;
632 tm
= gmtime_r(&creation_time
, &tmbuf
);
634 if (!strftime(buf
, sizeof(buf
), "%Y-%m-%d %H:%M:%S", tm
))
639 if (av_dict_set(&s
->metadata
, "creation_time", buf
, 0) < 0)
640 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
643 asf
->nb_packets
= avio_rl64(pb
);
644 asf
->duration
= avio_rl64(pb
) / 10000; // stream duration
645 avio_skip(pb
, 8); // skip send duration
646 asf
->preroll
= avio_rl64(pb
);
647 asf
->duration
-= asf
->preroll
;
648 asf
->b_flags
= avio_rl32(pb
);
649 avio_skip(pb
, 4); // skip minimal packet size
650 asf
->packet_size
= avio_rl32(pb
);
651 avio_skip(pb
, 4); // skip max_bitrate
656 static int parse_video_info(AVIOContext
*pb
, AVStream
*st
)
661 st
->codec
->width
= avio_rl32(pb
);
662 st
->codec
->height
= avio_rl32(pb
);
663 avio_skip(pb
, 1); // skip reserved flags
664 size
= avio_rl16(pb
); // size of the Format Data
665 tag
= ff_get_bmp_header(pb
, st
);
666 st
->codec
->codec_tag
= tag
;
667 st
->codec
->codec_id
= ff_codec_get_id(ff_codec_bmp_tags
, tag
);
669 if (size
> BMP_HEADER_SIZE
) {
671 st
->codec
->extradata_size
= size
- BMP_HEADER_SIZE
;
672 if (!(st
->codec
->extradata
= av_malloc(st
->codec
->extradata_size
+
673 FF_INPUT_BUFFER_PADDING_SIZE
))) {
674 st
->codec
->extradata_size
= 0;
675 return AVERROR(ENOMEM
);
677 memset(st
->codec
->extradata
+ st
->codec
->extradata_size
, 0,
678 FF_INPUT_BUFFER_PADDING_SIZE
);
679 if ((ret
= avio_read(pb
, st
->codec
->extradata
,
680 st
->codec
->extradata_size
)) < 0)
686 static int asf_read_stream_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
688 ASFContext
*asf
= s
->priv_data
;
689 AVIOContext
*pb
= s
->pb
;
691 uint32_t err_data_len
, ts_data_len
; // type specific data length
693 ff_asf_guid stream_type
;
694 enum AVMediaType type
;
696 uint8_t stream_index
;
700 // ASF file must not contain more than 128 streams according to the specification
701 if (asf
->nb_streams
>= ASF_MAX_STREAMS
)
702 return AVERROR_INVALIDDATA
;
704 size
= avio_rl64(pb
);
705 ff_get_guid(pb
, &stream_type
);
706 if (!ff_guidcmp(&stream_type
, &ff_asf_audio_stream
))
707 type
= AVMEDIA_TYPE_AUDIO
;
708 else if (!ff_guidcmp(&stream_type
, &ff_asf_video_stream
))
709 type
= AVMEDIA_TYPE_VIDEO
;
710 else if (!ff_guidcmp(&stream_type
, &ff_asf_jfif_media
))
711 type
= AVMEDIA_TYPE_VIDEO
;
712 else if (!ff_guidcmp(&stream_type
, &ff_asf_command_stream
))
713 type
= AVMEDIA_TYPE_DATA
;
714 else if (!ff_guidcmp(&stream_type
,
715 &ff_asf_ext_stream_embed_stream_header
))
716 type
= AVMEDIA_TYPE_UNKNOWN
;
718 return AVERROR_INVALIDDATA
;
720 ff_get_guid(pb
, &stream_type
); // error correction type
721 avio_skip(pb
, 8); // skip the time offset
722 ts_data_len
= avio_rl32(pb
);
723 err_data_len
= avio_rl32(pb
);
724 flags
= avio_rl16(pb
); // bit 15 - Encrypted Content
726 stream_index
= flags
& ASF_STREAM_NUM
;
727 for (i
= 0; i
< asf
->nb_streams
; i
++)
728 if (stream_index
== asf
->asf_st
[i
]->stream_index
) {
729 av_log(s
, AV_LOG_WARNING
,
730 "Duplicate stream found, this stream will be ignored.\n");
731 align_position(pb
, asf
->offset
, size
);
735 st
= avformat_new_stream(s
, NULL
);
737 return AVERROR(ENOMEM
);
738 avpriv_set_pts_info(st
, 32, 1, 1000); // pts should be dword, in milliseconds
739 st
->codec
->codec_type
= type
;
740 asf
->asf_st
[asf
->nb_streams
] = av_mallocz(sizeof(*asf_st
));
741 if (!asf
->asf_st
[asf
->nb_streams
])
742 return AVERROR(ENOMEM
);
743 asf_st
= asf
->asf_st
[asf
->nb_streams
];
744 asf_st
->stream_index
= stream_index
;
745 asf_st
->index
= st
->index
;
747 st
->id
= flags
& ASF_STREAM_NUM
;
748 av_init_packet(&asf_st
->pkt
.avpkt
);
749 asf_st
->pkt
.data_size
= 0;
750 avio_skip(pb
, 4); // skip reserved field
753 case AVMEDIA_TYPE_AUDIO
:
754 asf_st
->type
= AVMEDIA_TYPE_AUDIO
;
755 if ((ret
= ff_get_wav_header(pb
, st
->codec
, ts_data_len
)) < 0)
758 case AVMEDIA_TYPE_VIDEO
:
759 asf_st
->type
= AVMEDIA_TYPE_VIDEO
;
760 if ((ret
= parse_video_info(pb
, st
)) < 0)
764 avio_skip(pb
, ts_data_len
);
769 if (type
== AVMEDIA_TYPE_AUDIO
) {
770 uint8_t span
= avio_r8(pb
);
773 asf_st
->virtual_pkt_len
= avio_rl16(pb
);
774 asf_st
->virtual_chunk_len
= avio_rl16(pb
);
775 avio_skip(pb
, err_data_len
- 5);
777 avio_skip(pb
, err_data_len
- 1);
779 avio_skip(pb
, err_data_len
);
783 align_position(pb
, asf
->offset
, size
);
788 static void set_language(AVFormatContext
*s
, const char *rfc1766
, AVDictionary
**met
)
790 // language abbr should contain at least 2 chars
791 if (rfc1766
&& strlen(rfc1766
) > 1) {
792 const char primary_tag
[3] = { rfc1766
[0], rfc1766
[1], '\0' }; // ignore country code if any
793 const char *iso6392
= av_convert_lang_to(primary_tag
,
794 AV_LANG_ISO639_2_BIBL
);
796 if (av_dict_set(met
, "language", iso6392
, 0) < 0)
797 av_log(s
, AV_LOG_WARNING
, "av_dict_set failed.\n");
801 static int asf_read_ext_stream_properties(AVFormatContext
*s
, const GUIDParseTable
*g
)
803 ASFContext
*asf
= s
->priv_data
;
804 AVIOContext
*pb
= s
->pb
;
807 uint16_t nb_st_name
, nb_pay_exts
, st_num
, lang_idx
;
810 uint64_t start_time
, end_time
, time_per_frame
;
811 uint64_t size
= avio_rl64(pb
);
813 start_time
= avio_rl64(pb
);
814 end_time
= avio_rl64(pb
);
815 bitrate
= avio_rl32(pb
);
816 avio_skip(pb
, 28); // skip some unused values
817 st_num
= avio_rl16(pb
);
818 st_num
&= ASF_STREAM_NUM
;
819 lang_idx
= avio_rl16(pb
); // Stream Language ID Index
820 for (i
= 0; i
< asf
->nb_streams
; i
++) {
821 if (st_num
== asf
->asf_st
[i
]->stream_index
) {
822 st
= s
->streams
[asf
->asf_st
[i
]->index
];
823 asf
->asf_st
[i
]->lang_idx
= lang_idx
;
827 time_per_frame
= avio_rl64(pb
); // average time per frame
829 st
->start_time
= start_time
;
830 st
->duration
= end_time
- start_time
;
831 st
->codec
->bit_rate
= bitrate
;
832 st
->avg_frame_rate
.num
= 10000000;
833 st
->avg_frame_rate
.den
= time_per_frame
;
835 nb_st_name
= avio_rl16(pb
);
836 nb_pay_exts
= avio_rl16(pb
);
837 for (i
= 0; i
< nb_st_name
; i
++) {
840 avio_rl16(pb
); // Language ID Index
845 for (i
= 0; i
< nb_pay_exts
; i
++) {
847 avio_skip(pb
, 16); // Extension System ID
848 avio_skip(pb
, 2); // Extension Data Size
853 if ((ret
= ff_get_guid(pb
, &guid
)) < 0) {
854 align_position(pb
, asf
->offset
, size
);
860 if (g
&& !(strcmp(g
->name
, "Stream Properties"))) {
861 if ((ret
= g
->read_object(s
, g
)) < 0)
865 align_position(pb
, asf
->offset
, size
);
869 static int asf_read_language_list(AVFormatContext
*s
, const GUIDParseTable
*g
)
871 ASFContext
*asf
= s
->priv_data
;
872 AVIOContext
*pb
= s
->pb
;
874 uint64_t size
= avio_rl64(pb
);
875 uint16_t nb_langs
= avio_rl16(pb
);
877 if (nb_langs
< ASF_MAX_STREAMS
) {
878 for (i
= 0; i
< nb_langs
; i
++) {
883 if ((ret
= get_asf_string(pb
, len
, asf
->asf_sd
[i
].langs
,
884 sizeof(asf
->asf_sd
[i
].langs
))) < 0) {
890 align_position(pb
, asf
->offset
, size
);
894 // returns data object offset when reading this object for the first time
895 static int asf_read_data(AVFormatContext
*s
, const GUIDParseTable
*g
)
897 ASFContext
*asf
= s
->priv_data
;
898 AVIOContext
*pb
= s
->pb
;
899 uint64_t size
= asf
->data_size
= avio_rl64(pb
);
902 if (!asf
->data_reached
&& pb
->seekable
) {
903 asf
->data_reached
= 1;
904 asf
->data_offset
= asf
->offset
;
907 for (i
= 0; i
< asf
->nb_streams
; i
++) {
908 if (!(asf
->b_flags
& ASF_FLAG_BROADCAST
))
909 s
->streams
[i
]->duration
= asf
->duration
;
911 asf
->nb_mult_left
= 0;
913 asf
->state
= PARSE_PACKET_HEADER
;
914 asf
->return_subpayload
= 0;
915 asf
->packet_size_internal
= 0;
916 avio_skip(pb
, 16); // skip File ID
917 size
= avio_rl64(pb
); // Total Data Packets
918 if (size
!= asf
->nb_packets
)
919 av_log(s
, AV_LOG_WARNING
,
920 "Number of Packets from File Properties Object is not equal to Total"
921 "Datapackets value! num of packets %"PRIu64
" total num %"PRIu64
".\n",
922 size
, asf
->nb_packets
);
923 avio_skip(pb
, 2); // skip reserved field
924 asf
->first_packet_offset
= avio_tell(pb
);
925 align_position(pb
, asf
->offset
, asf
->data_size
);
930 static int asf_read_simple_index(AVFormatContext
*s
, const GUIDParseTable
*g
)
932 ASFContext
*asf
= s
->priv_data
;
933 AVIOContext
*pb
= s
->pb
;
935 uint64_t interval
; // index entry time interval in 100 ns units, usually it's 1s
936 uint32_t pkt_num
, nb_entries
;
937 int32_t prev_pkt_num
= -1;
939 uint64_t size
= avio_rl64(pb
);
941 // simple index objects should be ordered by stream number, this loop tries to find
942 // the first not indexed video stream
943 for (i
= 0; i
< asf
->nb_streams
; i
++) {
944 if ((asf
->asf_st
[i
]->type
== AVMEDIA_TYPE_VIDEO
) && !asf
->asf_st
[i
]->indexed
) {
945 asf
->asf_st
[i
]->indexed
= 1;
946 st
= s
->streams
[asf
->asf_st
[i
]->index
];
951 avio_skip(pb
, size
- 24); // if there's no video stream, skip index object
954 avio_skip(pb
, 16); // skip File ID
955 interval
= avio_rl64(pb
);
957 nb_entries
= avio_rl32(pb
);
958 for (i
= 0; i
< nb_entries
; i
++) {
959 pkt_num
= avio_rl32(pb
);
961 if (prev_pkt_num
!= pkt_num
) {
962 av_add_index_entry(st
, asf
->first_packet_offset
+ asf
->packet_size
*
963 pkt_num
, av_rescale(interval
, i
, 10000),
964 asf
->packet_size
, 0, AVINDEX_KEYFRAME
);
965 prev_pkt_num
= pkt_num
;
968 asf
->is_simple_index
= 1;
969 align_position(pb
, asf
->offset
, size
);
974 static const GUIDParseTable gdef
[] = {
975 { "Data", { 0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_data
, 1 },
976 { "Simple Index", { 0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB }, asf_read_simple_index
, 1 },
977 { "Content Description", { 0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_content_desc
, 1 },
978 { "Extended Content Description", { 0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50 }, asf_read_ext_content
, 1 },
979 { "Stream Bitrate Properties", { 0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2 }, asf_read_unknown
, 1 },
980 { "File Properties", { 0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_properties
, 1 },
981 { "Header Extension", { 0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_unknown
, 0 },
982 { "Stream Properties", { 0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_stream_properties
, 1 },
983 { "Codec List", { 0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown
, 1 },
984 { "Marker", { 0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_marker
, 1 },
985 { "Script Command", { 0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown
, 1 },
986 { "Language List", { 0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 }, asf_read_language_list
, 1},
987 { "Padding", { 0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8 }, asf_read_unknown
, 1 },
988 { "DRMv1 Header", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
989 { "DRMv2 Header", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c }, asf_read_unknown
, 1 },
990 { "Index", { 0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
991 { "Media Object Index", { 0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C }, asf_read_unknown
, 1 },
992 { "Timecode Index", { 0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C }, asf_read_unknown
, 0 },
993 { "Bitrate_Mutual_Exclusion", { 0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
994 { "Error Correction", { 0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_unknown
, 1 },
995 { "Content Branding", { 0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
996 { "Content Encryption", { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
997 { "Extended Content Encryption", { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C }, asf_read_unknown
, 1 },
998 { "Digital Signature", { 0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown
, 1 },
999 { "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 },
1000 { "Advanced Mutual Exclusion", { 0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD }, asf_read_unknown
, 1 },
1001 { "Group Mutual Exclusion", { 0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49 }, asf_read_unknown
, 1},
1002 { "Stream Prioritization", { 0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24 }, asf_read_unknown
, 1 },
1003 { "Bandwidth Sharing Object", { 0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1004 { "Metadata", { 0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA }, asf_read_metadata_obj
, 1 },
1005 { "Metadata Library", { 0x44, 0x23, 0x1C, 0x94, 0x94, 0x98, 0x49, 0xD1, 0xA1, 0x41, 0x1D, 0x13, 0x4E, 0x45, 0x70, 0x54 }, asf_read_metadata_obj
, 1 },
1006 { "Audio Spread", { 0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }, asf_read_unknown
, 1 },
1007 { "Index Parameters", { 0xD6, 0xE2, 0x29, 0xDF, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1008 { "Content Encryption System Windows Media DRM Network Devices",
1009 { 0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D }, asf_read_unknown
, 1 },
1010 { "Mutex Language", { 0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1011 { "Mutex Bitrate", { 0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1012 { "Mutex Unknown", { 0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown
, 1 },
1013 { "Bandwith Sharing Exclusive", { 0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1014 { "Bandwith Sharing Partial", { 0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown
, 1 },
1015 { "Payload Extension System Timecode", { 0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E }, asf_read_unknown
, 1 },
1016 { "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 },
1017 { "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 },
1018 { "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 },
1019 { "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 },
1020 { "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 },
1021 { "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 },
1024 #define READ_LEN(flag, name, len) \
1026 if ((flag) == name ## IS_BYTE) \
1027 len = avio_r8(pb); \
1028 else if ((flag) == name ## IS_WORD) \
1029 len = avio_rl16(pb); \
1030 else if ((flag) == name ## IS_DWORD) \
1031 len = avio_rl32(pb); \
1036 static int asf_read_subpayload(AVFormatContext
*s
, AVPacket
*pkt
, int is_header
)
1038 ASFContext
*asf
= s
->priv_data
;
1039 AVIOContext
*pb
= s
->pb
;
1044 asf
->dts_delta
= avio_r8(pb
);
1045 if (asf
->nb_mult_left
) {
1046 asf
->mult_sub_len
= avio_rl16(pb
); // total
1048 asf
->sub_header_offset
= avio_tell(pb
);
1052 sub_len
= avio_r8(pb
);
1053 if ((ret
= av_get_packet(pb
, pkt
, sub_len
)) < 0) // each subpayload is entire frame
1055 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1056 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1057 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1061 asf
->return_subpayload
= 1;
1063 asf
->return_subpayload
= 0;
1067 pkt
->dts
= asf
->sub_dts
+ (asf
->nb_sub
- 1) * asf
->dts_delta
- asf
->preroll
;
1068 if (asf
->nb_mult_left
&& (avio_tell(pb
) >=
1069 (asf
->sub_header_offset
+ asf
->mult_sub_len
))) {
1071 asf
->nb_mult_left
--;
1073 if (avio_tell(pb
) >= asf
->packet_offset
+ asf
->packet_size
- asf
->pad_len
) {
1075 if (!asf
->nb_mult_left
) {
1076 avio_skip(pb
, asf
->pad_len
);
1077 if (avio_tell(pb
) != asf
->packet_offset
+ asf
->packet_size
) {
1078 if (!asf
->packet_size
)
1079 return AVERROR_INVALIDDATA
;
1080 av_log(s
, AV_LOG_WARNING
,
1081 "Position %"PRId64
" wrong, should be %"PRId64
"\n",
1082 avio_tell(pb
), asf
->packet_offset
+ asf
->packet_size
);
1083 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1091 static void reset_packet(ASFPacket
*asf_pkt
)
1093 asf_pkt
->size_left
= 0;
1094 asf_pkt
->data_size
= 0;
1095 asf_pkt
->duration
= 0;
1098 asf_pkt
->duration
= 0;
1099 av_free_packet(&asf_pkt
->avpkt
);
1100 av_init_packet(&asf_pkt
->avpkt
);
1103 static int asf_read_multiple_payload(AVFormatContext
*s
, AVPacket
*pkt
,
1106 ASFContext
*asf
= s
->priv_data
;
1107 AVIOContext
*pb
= s
->pb
;
1113 // if replicated lenght is 1, subpayloads are present
1114 if (asf
->rep_data_len
== 1) {
1116 asf
->state
= READ_MULTI_SUB
;
1117 pkt
->flags
= asf_pkt
->flags
;
1118 if ((ret
= asf_read_subpayload(s
, pkt
, 1)) < 0)
1121 if (!asf_pkt
->data_size
) {
1122 asf_pkt
->data_size
= asf_pkt
->size_left
= avio_rl32(pb
); // read media object size
1123 if (asf_pkt
->data_size
<= 0)
1125 if ((ret
= av_new_packet(&asf_pkt
->avpkt
, asf_pkt
->data_size
)) < 0)
1128 avio_skip(pb
, 4); // reading of media object size is already done
1129 asf_pkt
->dts
= avio_rl32(pb
); // read presentation time
1130 if ((asf
->rep_data_len
- 8) > 0)
1131 avio_skip(pb
, asf
->rep_data_len
- 8); // skip replicated data
1132 pay_len
= avio_rl16(pb
); // payload length should be WORD
1133 if (pay_len
> asf
->packet_size
) {
1134 av_log(s
, AV_LOG_ERROR
,
1135 "Error: invalid data packet size, pay_len %"PRIu16
", "
1136 "asf->packet_size %"PRIu32
", offset %"PRId64
".\n",
1137 pay_len
, asf
->packet_size
, avio_tell(pb
));
1138 return AVERROR_INVALIDDATA
;
1140 p
= asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
- asf_pkt
->size_left
;
1141 if (pay_len
> asf_pkt
->size_left
) {
1142 av_log(s
, AV_LOG_ERROR
,
1143 "Error: invalid buffer size, pay_len %d, data size left %d.\n",
1144 pay_len
, asf_pkt
->size_left
);
1145 skip
= pay_len
- asf_pkt
->size_left
;
1146 pay_len
= asf_pkt
->size_left
;
1148 if ((ret
= avio_read(pb
, p
, pay_len
)) < 0)
1150 if (s
->key
&& s
->keylen
== 20)
1151 ff_asfcrypt_dec(s
->key
, p
, ret
);
1152 avio_skip(pb
, skip
);
1153 asf_pkt
->size_left
-= pay_len
;
1154 asf
->nb_mult_left
--;
1160 static int asf_read_single_payload(AVFormatContext
*s
, AVPacket
*pkt
,
1163 ASFContext
*asf
= s
->priv_data
;
1164 AVIOContext
*pb
= s
->pb
;
1170 if (!asf_pkt
->data_size
) {
1171 asf_pkt
->data_size
= asf_pkt
->size_left
= avio_rl32(pb
); // read media object size
1172 if (asf_pkt
->data_size
<= 0)
1174 if ((ret
= av_new_packet(&asf_pkt
->avpkt
, asf_pkt
->data_size
)) < 0)
1177 avio_skip(pb
, 4); // skip media object size
1178 asf_pkt
->dts
= avio_rl32(pb
); // read presentation time
1179 if ((asf
->rep_data_len
- 8) > 0)
1180 avio_skip(pb
, asf
->rep_data_len
- 8); // skip replicated data
1181 offset
= avio_tell(pb
);
1183 // size of the payload - size of the packet without header and padding
1184 if (asf
->packet_size_internal
)
1185 size
= asf
->packet_size_internal
- offset
+ asf
->packet_offset
- asf
->pad_len
;
1187 size
= asf
->packet_size
- offset
+ asf
->packet_offset
- asf
->pad_len
;
1188 if (size
> asf
->packet_size
) {
1189 av_log(s
, AV_LOG_ERROR
,
1190 "Error: invalid data packet size, offset %"PRId64
".\n",
1192 return AVERROR_INVALIDDATA
;
1194 p
= asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
- asf_pkt
->size_left
;
1195 if (size
> asf_pkt
->size_left
)
1196 return AVERROR_INVALIDDATA
;
1197 if (asf_pkt
->size_left
> size
)
1198 asf_pkt
->size_left
-= size
;
1200 asf_pkt
->size_left
= 0;
1201 if ((ret
= avio_read(pb
, p
, size
)) < 0)
1203 if (s
->key
&& s
->keylen
== 20)
1204 ff_asfcrypt_dec(s
->key
, p
, ret
);
1205 if (asf
->packet_size_internal
)
1206 avio_skip(pb
, asf
->packet_size
- asf
->packet_size_internal
);
1207 avio_skip(pb
, asf
->pad_len
); // skip padding
1212 static int asf_read_payload(AVFormatContext
*s
, AVPacket
*pkt
)
1214 ASFContext
*asf
= s
->priv_data
;
1215 AVIOContext
*pb
= s
->pb
;
1217 ASFPacket
*asf_pkt
= NULL
;
1219 if (!asf
->sub_left
) {
1220 uint32_t off_len
, media_len
;
1223 stream_num
= avio_r8(pb
);
1224 asf
->stream_index
= stream_num
& ASF_STREAM_NUM
;
1225 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1226 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1227 asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1228 asf_pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1229 asf_pkt
->dts
= asf
->dts
;
1234 return AVERROR_INVALIDDATA
;
1235 if (stream_num
>> 7)
1236 asf_pkt
->flags
|= AV_PKT_FLAG_KEY
;
1237 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE
,
1238 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_
, media_len
);
1239 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE
,
1240 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_
, off_len
);
1241 READ_LEN(asf
->prop_flags
& ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE
,
1242 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_
, asf
->rep_data_len
);
1243 if (asf_pkt
->size_left
&& (asf_pkt
->frame_num
!= media_len
)) {
1244 av_log(s
, AV_LOG_WARNING
, "Unfinished frame will be ignored\n");
1245 reset_packet(asf_pkt
);
1247 asf_pkt
->frame_num
= media_len
;
1248 asf
->sub_dts
= off_len
;
1249 if (asf
->nb_mult_left
) {
1250 if ((ret
= asf_read_multiple_payload(s
, pkt
, asf_pkt
)) < 0)
1252 } else if (asf
->rep_data_len
== 1) {
1254 asf
->state
= READ_SINGLE
;
1255 pkt
->flags
= asf_pkt
->flags
;
1256 if ((ret
= asf_read_subpayload(s
, pkt
, 1)) < 0)
1259 if ((ret
= asf_read_single_payload(s
, pkt
, asf_pkt
)) < 0)
1263 for (i
= 0; i
<= asf
->nb_streams
; i
++) {
1264 if (asf
->stream_index
== asf
->asf_st
[i
]->stream_index
) {
1265 asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1270 return AVERROR_INVALIDDATA
;
1271 pkt
->flags
= asf_pkt
->flags
;
1272 pkt
->dts
= asf_pkt
->dts
;
1273 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1274 if ((ret
= asf_read_subpayload(s
, pkt
, 0)) < 0) // read subpayload without its header
1281 static int asf_read_packet_header(AVFormatContext
*s
)
1283 ASFContext
*asf
= s
->priv_data
;
1284 AVIOContext
*pb
= s
->pb
;
1286 uint32_t av_unused seq
;
1287 unsigned char error_flags
, len_flags
, pay_flags
;
1289 asf
->packet_offset
= avio_tell(pb
);
1290 error_flags
= avio_r8(pb
); // read Error Correction Flags
1291 if (error_flags
& ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT
)
1292 if (!(error_flags
& ASF_ERROR_CORRECTION_LENGTH_TYPE
)) {
1293 size
= error_flags
& ASF_PACKET_ERROR_CORRECTION_DATA_SIZE
;
1294 avio_skip(pb
, size
);
1296 len_flags
= avio_r8(pb
);
1297 asf
->prop_flags
= avio_r8(pb
);
1298 READ_LEN(len_flags
& ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE
,
1299 ASF_PPI_FLAG_PACKET_LENGTH_FIELD_
, asf
->packet_size_internal
);
1300 READ_LEN(len_flags
& ASF_PPI_MASK_SEQUENCE_FIELD_SIZE
,
1301 ASF_PPI_FLAG_SEQUENCE_FIELD_
, seq
);
1302 READ_LEN(len_flags
& ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE
,
1303 ASF_PPI_FLAG_PADDING_LENGTH_FIELD_
, asf
->pad_len
);
1304 asf
->send_time
= avio_rl32(pb
); // send time
1305 avio_skip(pb
, 2); // skip duration
1306 if (len_flags
& ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT
) { // Multiple Payloads present
1307 pay_flags
= avio_r8(pb
);
1308 asf
->nb_mult_left
= (pay_flags
& ASF_NUM_OF_PAYLOADS
);
1314 static int asf_deinterleave(AVFormatContext
*s
, ASFPacket
*asf_pkt
, int st_num
)
1316 ASFContext
*asf
= s
->priv_data
;
1317 ASFStream
*asf_st
= asf
->asf_st
[st_num
];
1318 unsigned char *p
= asf_pkt
->avpkt
.data
;
1319 uint16_t pkt_len
= asf
->asf_st
[st_num
]->virtual_pkt_len
;
1320 uint16_t chunk_len
= asf
->asf_st
[st_num
]->virtual_chunk_len
;
1321 int nchunks
= pkt_len
/ chunk_len
;
1323 int pos
= 0, j
, l
, ret
;
1326 if ((ret
= av_new_packet(&pkt
, asf_pkt
->data_size
)) < 0)
1329 while (asf_pkt
->data_size
>= asf_st
->span
* pkt_len
+ pos
) {
1330 if (pos
>= asf_pkt
->data_size
) {
1333 for (l
= 0; l
< pkt_len
; l
++) {
1334 if (pos
>= asf_pkt
->data_size
) {
1337 for (j
= 0; j
< asf_st
->span
; j
++) {
1338 if ((pos
+ chunk_len
) >= asf_pkt
->data_size
)
1340 memcpy(pkt
.data
+ pos
,
1341 p
+ (j
* nchunks
+ l
) * chunk_len
,
1346 p
+= asf_st
->span
* pkt_len
;
1347 if (p
> asf_pkt
->avpkt
.data
+ asf_pkt
->data_size
)
1350 av_free_packet(&asf_pkt
->avpkt
);
1351 asf_pkt
->avpkt
= pkt
;
1356 static int asf_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
1358 ASFContext
*asf
= s
->priv_data
;
1359 AVIOContext
*pb
= s
->pb
;
1362 if ((avio_tell(pb
) >= asf
->data_offset
+ asf
->data_size
) &&
1363 !(asf
->b_flags
& ASF_FLAG_BROADCAST
))
1365 while (!pb
->eof_reached
) {
1366 if (asf
->state
== PARSE_PACKET_HEADER
) {
1367 asf_read_packet_header(s
);
1368 if (!asf
->nb_mult_left
)
1369 asf
->state
= READ_SINGLE
;
1371 asf
->state
= READ_MULTI
;
1373 if ((ret
= asf_read_payload(s
, pkt
)) < 0)
1375 switch (asf
->state
) {
1378 asf
->state
= PARSE_PACKET_HEADER
;
1380 case READ_MULTI_SUB
:
1381 if (!asf
->sub_left
&& !asf
->nb_mult_left
) {
1382 asf
->state
= PARSE_PACKET_HEADER
;
1383 if (!asf
->return_subpayload
)
1384 avio_skip(pb
, asf
->pad_len
); // skip padding
1385 if (asf
->packet_offset
+ asf
->packet_size
> avio_tell(pb
))
1386 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1387 } else if (!asf
->sub_left
)
1388 asf
->state
= READ_MULTI
;
1391 if (!asf
->nb_mult_left
) {
1392 asf
->state
= PARSE_PACKET_HEADER
;
1393 if (!asf
->return_subpayload
) {
1394 avio_skip(pb
, asf
->pad_len
); // skip padding
1396 if (asf
->packet_offset
+ asf
->packet_size
> avio_tell(pb
))
1397 avio_seek(pb
, asf
->packet_offset
+ asf
->packet_size
, SEEK_SET
);
1401 if (asf
->return_subpayload
) {
1402 asf
->return_subpayload
= 0;
1405 for (i
= 0; i
< s
->nb_streams
; i
++) {
1406 ASFPacket
*asf_pkt
= &asf
->asf_st
[i
]->pkt
;
1407 if (asf_pkt
&& !asf_pkt
->size_left
&& asf_pkt
->data_size
) {
1408 if (asf
->asf_st
[i
]->span
> 1 &&
1409 asf
->asf_st
[i
]->type
== AVMEDIA_TYPE_AUDIO
)
1410 if ((ret
= asf_deinterleave(s
, asf_pkt
, i
)) < 0)
1412 av_packet_move_ref(pkt
, &asf_pkt
->avpkt
);
1413 pkt
->stream_index
= asf
->asf_st
[i
]->index
;
1414 pkt
->flags
= asf_pkt
->flags
;
1415 pkt
->dts
= asf_pkt
->dts
- asf
->preroll
;
1416 asf_pkt
->data_size
= 0;
1417 asf_pkt
->frame_num
= 0;
1423 if (pb
->eof_reached
)
1429 static int asf_read_close(AVFormatContext
*s
)
1431 ASFContext
*asf
= s
->priv_data
;
1434 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1435 av_free_packet(&asf
->asf_st
[i
]->pkt
.avpkt
);
1436 av_freep(&asf
->asf_st
[i
]);
1437 av_dict_free(&asf
->asf_sd
[i
].asf_met
);
1443 static void reset_packet_state(AVFormatContext
*s
)
1445 ASFContext
*asf
= s
->priv_data
;
1448 asf
->state
= PARSE_PACKET_HEADER
;
1450 asf
->return_subpayload
= 0;
1452 asf
->sub_header_offset
= 0;
1453 asf
->packet_offset
= asf
->first_packet_offset
;
1455 asf
->rep_data_len
= 0;
1457 asf
->mult_sub_len
= 0;
1458 asf
->nb_mult_left
= 0;
1460 asf
->prop_flags
= 0;
1463 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1464 ASFPacket
*pkt
= &asf
->asf_st
[i
]->pkt
;
1471 av_free_packet(&pkt
->avpkt
);
1472 av_init_packet(&pkt
->avpkt
);
1477 * Find a timestamp for the requested position within the payload
1478 * where the pos (position) is the offset inside the Data Object.
1479 * When position is not on the packet boundary, asf_read_timestamp tries
1480 * to find the closest packet offset after this position. If this packet
1481 * is a key frame, this packet timestamp is read and an index entry is created
1482 * for the packet. If this packet belongs to the requested stream,
1483 * asf_read_timestamp upgrades pos to the packet beginning offset and
1484 * returns this packet's dts. So returned dts is the dts of the first key frame with
1485 * matching stream number after given position.
1487 static int64_t asf_read_timestamp(AVFormatContext
*s
, int stream_index
,
1488 int64_t *pos
, int64_t pos_limit
)
1490 ASFContext
*asf
= s
->priv_data
;
1491 int64_t pkt_pos
= *pos
, pkt_offset
, dts
= AV_NOPTS_VALUE
, data_end
;
1495 data_end
= asf
->data_offset
+ asf
->data_size
;
1497 n
= (pkt_pos
- asf
->first_packet_offset
+ asf
->packet_size
- 1) /
1499 n
= av_clip(n
, 0, ((data_end
- asf
->first_packet_offset
) / asf
->packet_size
- 1));
1500 pkt_pos
= asf
->first_packet_offset
+ n
* asf
->packet_size
;
1502 avio_seek(s
->pb
, pkt_pos
, SEEK_SET
);
1503 pkt_offset
= pkt_pos
;
1505 reset_packet_state(s
);
1506 while (avio_tell(s
->pb
) < data_end
) {
1508 int i
, ret
, st_found
;
1510 av_init_packet(&pkt
);
1511 pkt_offset
= avio_tell(s
->pb
);
1512 if ((ret
= asf_read_packet(s
, &pkt
)) < 0) {
1513 dts
= AV_NOPTS_VALUE
;
1516 // ASFPacket may contain fragments of packets belonging to different streams,
1517 // pkt_offset is the offset of the first fragment within it.
1518 if ((pkt_offset
>= (pkt_pos
+ asf
->packet_size
)))
1519 pkt_pos
+= asf
->packet_size
;
1520 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1521 ASFStream
*st
= asf
->asf_st
[i
];
1524 if (pkt
.flags
& AV_PKT_FLAG_KEY
) {
1527 av_add_index_entry(s
->streams
[pkt
.stream_index
], pkt_pos
,
1528 dts
, pkt
.size
, 0, AVINDEX_KEYFRAME
);
1529 if (stream_index
== st
->index
) {
1538 av_free_packet(&pkt
);
1542 av_free_packet(&pkt
);
1546 static int asf_read_seek(AVFormatContext
*s
, int stream_index
,
1547 int64_t timestamp
, int flags
)
1549 ASFContext
*asf
= s
->priv_data
;
1552 if (s
->streams
[stream_index
]->nb_index_entries
&& asf
->is_simple_index
) {
1553 idx
= av_index_search_timestamp(s
->streams
[stream_index
], timestamp
, flags
);
1554 if (idx
< 0 || idx
>= s
->streams
[stream_index
]->nb_index_entries
)
1555 return AVERROR_INVALIDDATA
;
1556 avio_seek(s
->pb
, s
->streams
[stream_index
]->index_entries
[idx
].pos
, SEEK_SET
);
1558 if ((ret
= ff_seek_frame_binary(s
, stream_index
, timestamp
, flags
)) < 0)
1561 // asf_read_timestamp is called inside ff_seek_frame_binary and leaves state dirty,
1562 // so reset_packet_state have to be called after it.
1563 reset_packet_state(s
);
1569 static const GUIDParseTable
*find_guid(ff_asf_guid guid
)
1572 const GUIDParseTable
*g
;
1576 for (j
= 0; j
< FF_ARRAY_ELEMS(gdef
); j
++) {
1577 if (!(ret
= memcmp(guid
, g
->guid
, sizeof(g
->guid
))))
1585 static int detect_unknown_subobject(AVFormatContext
*s
, int64_t offset
, int64_t size
)
1587 ASFContext
*asf
= s
->priv_data
;
1588 AVIOContext
*pb
= s
->pb
;
1589 const GUIDParseTable
*g
= NULL
;
1593 while (avio_tell(pb
) <= offset
+ size
) {
1594 asf
->offset
= avio_tell(pb
);
1595 if ((ret
= ff_get_guid(pb
, &guid
)) < 0)
1597 g
= find_guid(guid
);
1599 if ((ret
= g
->read_object(s
, g
)) < 0)
1604 g2
.name
= "Unknown";
1605 g2
.is_subobject
= 1;
1606 asf_read_unknown(s
, &g2
);
1613 static int asf_read_header(AVFormatContext
*s
)
1615 ASFContext
*asf
= s
->priv_data
;
1616 AVIOContext
*pb
= s
->pb
;
1617 const GUIDParseTable
*g
= NULL
;
1623 asf
->is_simple_index
= 0;
1624 ff_get_guid(pb
, &guid
);
1625 if (ff_guidcmp(&guid
, &ff_asf_header
))
1626 return AVERROR_INVALIDDATA
;
1627 avio_skip(pb
, 8); // skip header object size
1628 avio_skip(pb
, 6); // skip number of header objects and 2 reserved bytes
1629 asf
->data_reached
= 0;
1631 /* 1 is here instead of pb->eof_reached because (when not streaming), Data are skipped
1632 * for the first time,
1633 * Index object is processed and got eof and then seeking back to the Data is performed.
1636 // for the cases when object size is invalid
1637 if (avio_tell(pb
) == asf
->offset
) {
1638 if (asf
->data_reached
)
1639 avio_seek(pb
, asf
->first_packet_offset
, SEEK_SET
);
1642 asf
->offset
= avio_tell(pb
);
1643 if ((ret
= ff_get_guid(pb
, &guid
)) < 0) {
1644 if (ret
== AVERROR_EOF
&& asf
->data_reached
) {
1645 avio_seek(pb
, asf
->first_packet_offset
, SEEK_SET
);
1650 g
= find_guid(guid
);
1652 asf
->unknown_offset
= asf
->offset
;
1654 if ((ret
= g
->read_object(s
, g
)) < 0)
1657 size
= avio_rl64(pb
);
1658 align_position(pb
, asf
->offset
, size
);
1660 if (asf
->data_reached
&& !pb
->seekable
)
1664 for (i
= 0; i
< asf
->nb_streams
; i
++) {
1665 const char *rfc1766
= asf
->asf_sd
[asf
->asf_st
[i
]->lang_idx
].langs
;
1666 AVStream
*st
= s
->streams
[asf
->asf_st
[i
]->index
];
1667 set_language(s
, rfc1766
, &st
->metadata
);
1670 for (i
= 0; i
< ASF_MAX_STREAMS
; i
++) {
1671 AVStream
*st
= NULL
;
1673 st
= find_stream(s
, i
);
1675 av_dict_copy(&st
->metadata
, asf
->asf_sd
[i
].asf_met
, AV_DICT_IGNORE_SUFFIX
);
1676 if (asf
->asf_sd
[i
].aspect_ratio
.num
> 0 && asf
->asf_sd
[i
].aspect_ratio
.den
> 0) {
1677 st
->sample_aspect_ratio
.num
= asf
->asf_sd
[i
].aspect_ratio
.num
;
1678 st
->sample_aspect_ratio
.den
= asf
->asf_sd
[i
].aspect_ratio
.den
;
1686 AVInputFormat ff_asf_demuxer
= {
1688 .long_name
= NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1689 .priv_data_size
= sizeof(ASFContext
),
1690 .read_probe
= asf_probe
,
1691 .read_header
= asf_read_header
,
1692 .read_packet
= asf_read_packet
,
1693 .read_close
= asf_read_close
,
1694 .read_timestamp
= asf_read_timestamp
,
1695 .read_seek
= asf_read_seek
,
1696 .flags
= AVFMT_NOBINSEARCH
| AVFMT_NOGENSEARCH
,