1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Microsoft Advanced Streaming Format demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2014 Alexandra Hájková
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
23cabdff1aSopenharmony_ci#include "libavutil/common.h"
24cabdff1aSopenharmony_ci#include "libavutil/dict.h"
25cabdff1aSopenharmony_ci#include "libavutil/internal.h"
26cabdff1aSopenharmony_ci#include "libavutil/mathematics.h"
27cabdff1aSopenharmony_ci#include "libavutil/time_internal.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "avformat.h"
30cabdff1aSopenharmony_ci#include "avlanguage.h"
31cabdff1aSopenharmony_ci#include "demux.h"
32cabdff1aSopenharmony_ci#include "internal.h"
33cabdff1aSopenharmony_ci#include "riff.h"
34cabdff1aSopenharmony_ci#include "asf.h"
35cabdff1aSopenharmony_ci#include "asfcrypt.h"
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci#define ASF_BOOL                              0x2
38cabdff1aSopenharmony_ci#define ASF_WORD                              0x5
39cabdff1aSopenharmony_ci#define ASF_GUID                              0x6
40cabdff1aSopenharmony_ci#define ASF_DWORD                             0x3
41cabdff1aSopenharmony_ci#define ASF_QWORD                             0x4
42cabdff1aSopenharmony_ci#define ASF_UNICODE                           0x0
43cabdff1aSopenharmony_ci#define ASF_FLAG_BROADCAST                    0x1
44cabdff1aSopenharmony_ci#define ASF_BYTE_ARRAY                        0x1
45cabdff1aSopenharmony_ci#define ASF_TYPE_AUDIO                        0x2
46cabdff1aSopenharmony_ci#define ASF_TYPE_VIDEO                        0x1
47cabdff1aSopenharmony_ci#define ASF_STREAM_NUM                        0x7F
48cabdff1aSopenharmony_ci#define ASF_MAX_STREAMS                       128
49cabdff1aSopenharmony_ci#define BMP_HEADER_SIZE                       40
50cabdff1aSopenharmony_ci#define ASF_NUM_OF_PAYLOADS                   0x3F
51cabdff1aSopenharmony_ci#define ASF_ERROR_CORRECTION_LENGTH_TYPE      0x60
52cabdff1aSopenharmony_ci#define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_citypedef struct GUIDParseTable {
55cabdff1aSopenharmony_ci    const char *name;
56cabdff1aSopenharmony_ci    ff_asf_guid guid;
57cabdff1aSopenharmony_ci    int (*read_object)(AVFormatContext *, const struct GUIDParseTable *);
58cabdff1aSopenharmony_ci    int is_subobject;
59cabdff1aSopenharmony_ci} GUIDParseTable;
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_citypedef struct ASFPacket {
62cabdff1aSopenharmony_ci    AVPacket *avpkt;
63cabdff1aSopenharmony_ci    int64_t dts;
64cabdff1aSopenharmony_ci    uint32_t frame_num; // ASF payloads with the same number are parts of the same frame
65cabdff1aSopenharmony_ci    int flags;
66cabdff1aSopenharmony_ci    int data_size;
67cabdff1aSopenharmony_ci    int duration;
68cabdff1aSopenharmony_ci    int size_left;
69cabdff1aSopenharmony_ci    uint8_t stream_index;
70cabdff1aSopenharmony_ci} ASFPacket;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_citypedef struct ASFStream {
73cabdff1aSopenharmony_ci    uint8_t stream_index; // from packet header
74cabdff1aSopenharmony_ci    int index;  // stream index in AVFormatContext, set in asf_read_stream_properties
75cabdff1aSopenharmony_ci    int type;
76cabdff1aSopenharmony_ci    int indexed; // added index entries from the Simple Index Object or not
77cabdff1aSopenharmony_ci    int8_t span;   // for deinterleaving
78cabdff1aSopenharmony_ci    uint16_t virtual_pkt_len;
79cabdff1aSopenharmony_ci    uint16_t virtual_chunk_len;
80cabdff1aSopenharmony_ci    int16_t lang_idx;
81cabdff1aSopenharmony_ci    ASFPacket pkt;
82cabdff1aSopenharmony_ci} ASFStream;
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_citypedef struct ASFStreamData{
85cabdff1aSopenharmony_ci    char langs[32];
86cabdff1aSopenharmony_ci    AVDictionary *asf_met; // for storing per-stream metadata
87cabdff1aSopenharmony_ci    AVRational aspect_ratio;
88cabdff1aSopenharmony_ci} ASFStreamData;
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_citypedef struct ASFContext {
91cabdff1aSopenharmony_ci    int data_reached;
92cabdff1aSopenharmony_ci    int is_simple_index; // is simple index present or not 1/0
93cabdff1aSopenharmony_ci    int is_header;
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_ci    uint64_t preroll;
96cabdff1aSopenharmony_ci    uint64_t nb_packets; // ASF packets
97cabdff1aSopenharmony_ci    uint32_t packet_size;
98cabdff1aSopenharmony_ci    int64_t send_time;
99cabdff1aSopenharmony_ci    int duration;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    uint32_t b_flags;    // flags with broadcast flag
102cabdff1aSopenharmony_ci    uint32_t prop_flags; // file properties object flags
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci    uint64_t data_size; // data object size
105cabdff1aSopenharmony_ci    uint64_t unknown_size; // size of the unknown object
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    int64_t offset; // offset of the current object
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci    int64_t data_offset;
110cabdff1aSopenharmony_ci    int64_t first_packet_offset; // packet offset
111cabdff1aSopenharmony_ci    int64_t unknown_offset;   // for top level header objects or subobjects without specified behavior
112cabdff1aSopenharmony_ci    int in_asf_read_unknown;
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    // ASF file must not contain more than 128 streams according to the specification
115cabdff1aSopenharmony_ci    ASFStream *asf_st[ASF_MAX_STREAMS];
116cabdff1aSopenharmony_ci    ASFStreamData asf_sd[ASF_MAX_STREAMS];
117cabdff1aSopenharmony_ci    int nb_streams;
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    int stream_index; // from packet header, for the subpayload case
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    // packet parameters
122cabdff1aSopenharmony_ci    uint64_t sub_header_offset; // offset of subpayload header
123cabdff1aSopenharmony_ci    int64_t sub_dts;
124cabdff1aSopenharmony_ci    uint8_t dts_delta; // for subpayloads
125cabdff1aSopenharmony_ci    uint32_t packet_size_internal; // packet size stored inside ASFPacket, can be 0
126cabdff1aSopenharmony_ci    int64_t packet_offset; // offset of the current packet inside Data Object
127cabdff1aSopenharmony_ci    uint32_t pad_len; // padding after payload
128cabdff1aSopenharmony_ci    uint32_t rep_data_len;
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci    // packet state
131cabdff1aSopenharmony_ci    uint64_t sub_left;  // subpayloads left or not
132cabdff1aSopenharmony_ci    unsigned int nb_sub; // number of subpayloads read so far from the current ASF packet
133cabdff1aSopenharmony_ci    uint16_t mult_sub_len; // total length of subpayloads array inside multiple payload
134cabdff1aSopenharmony_ci    uint64_t nb_mult_left; // multiple payloads left
135cabdff1aSopenharmony_ci    int return_subpayload;
136cabdff1aSopenharmony_ci    enum {
137cabdff1aSopenharmony_ci        PARSE_PACKET_HEADER,
138cabdff1aSopenharmony_ci        READ_SINGLE,
139cabdff1aSopenharmony_ci        READ_MULTI,
140cabdff1aSopenharmony_ci        READ_MULTI_SUB
141cabdff1aSopenharmony_ci    } state;
142cabdff1aSopenharmony_ci} ASFContext;
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_cistatic int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size);
145cabdff1aSopenharmony_cistatic const GUIDParseTable *find_guid(ff_asf_guid guid);
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_cistatic int asf_probe(const AVProbeData *pd)
148cabdff1aSopenharmony_ci{
149cabdff1aSopenharmony_ci    /* check file header */
150cabdff1aSopenharmony_ci    if (!ff_guidcmp(pd->buf, &ff_asf_header))
151cabdff1aSopenharmony_ci        return AVPROBE_SCORE_MAX/2;
152cabdff1aSopenharmony_ci    else
153cabdff1aSopenharmony_ci        return 0;
154cabdff1aSopenharmony_ci}
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_cistatic void swap_guid(ff_asf_guid guid)
157cabdff1aSopenharmony_ci{
158cabdff1aSopenharmony_ci    FFSWAP(unsigned char, guid[0], guid[3]);
159cabdff1aSopenharmony_ci    FFSWAP(unsigned char, guid[1], guid[2]);
160cabdff1aSopenharmony_ci    FFSWAP(unsigned char, guid[4], guid[5]);
161cabdff1aSopenharmony_ci    FFSWAP(unsigned char, guid[6], guid[7]);
162cabdff1aSopenharmony_ci}
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_cistatic void align_position(AVIOContext *pb,  int64_t offset, uint64_t size)
165cabdff1aSopenharmony_ci{
166cabdff1aSopenharmony_ci    if (size < INT64_MAX - offset && avio_tell(pb) != offset + size)
167cabdff1aSopenharmony_ci        avio_seek(pb, offset + size, SEEK_SET);
168cabdff1aSopenharmony_ci}
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_cistatic int asf_read_unknown(AVFormatContext *s, const GUIDParseTable *g)
171cabdff1aSopenharmony_ci{
172cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
173cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
174cabdff1aSopenharmony_ci    uint64_t size   = avio_rl64(pb);
175cabdff1aSopenharmony_ci    int ret;
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci    if (size > INT64_MAX || asf->in_asf_read_unknown > 5)
178cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    if (asf->is_header)
181cabdff1aSopenharmony_ci        asf->unknown_size = size;
182cabdff1aSopenharmony_ci    asf->is_header = 0;
183cabdff1aSopenharmony_ci    if (!g->is_subobject) {
184cabdff1aSopenharmony_ci        if (!(ret = strcmp(g->name, "Header Extension")))
185cabdff1aSopenharmony_ci            avio_skip(pb, 22); // skip reserved fields and Data Size
186cabdff1aSopenharmony_ci        asf->in_asf_read_unknown ++;
187cabdff1aSopenharmony_ci        ret = detect_unknown_subobject(s, asf->unknown_offset,
188cabdff1aSopenharmony_ci                                            asf->unknown_size);
189cabdff1aSopenharmony_ci        asf->in_asf_read_unknown --;
190cabdff1aSopenharmony_ci        if (ret < 0)
191cabdff1aSopenharmony_ci            return ret;
192cabdff1aSopenharmony_ci    } else {
193cabdff1aSopenharmony_ci        if (size < 24) {
194cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Too small size %"PRIu64" (< 24).\n", size);
195cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
196cabdff1aSopenharmony_ci        }
197cabdff1aSopenharmony_ci        avio_skip(pb, size - 24);
198cabdff1aSopenharmony_ci    }
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci    return 0;
201cabdff1aSopenharmony_ci}
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_cistatic int get_asf_string(AVIOContext *pb, int maxlen, char *buf, int buflen)
204cabdff1aSopenharmony_ci{
205cabdff1aSopenharmony_ci    char *q = buf;
206cabdff1aSopenharmony_ci    int ret = 0;
207cabdff1aSopenharmony_ci    if (buflen <= 0)
208cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
209cabdff1aSopenharmony_ci    while (ret + 1 < maxlen) {
210cabdff1aSopenharmony_ci        uint8_t tmp;
211cabdff1aSopenharmony_ci        uint32_t ch;
212cabdff1aSopenharmony_ci        GET_UTF16(ch, (ret += 2) <= maxlen ? avio_rl16(pb) : 0, break;);
213cabdff1aSopenharmony_ci        PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)
214cabdff1aSopenharmony_ci    }
215cabdff1aSopenharmony_ci    *q = 0;
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci    return ret;
218cabdff1aSopenharmony_ci}
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_cistatic int asf_read_marker(AVFormatContext *s, const GUIDParseTable *g)
221cabdff1aSopenharmony_ci{
222cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
223cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
224cabdff1aSopenharmony_ci    uint64_t size   = avio_rl64(pb);
225cabdff1aSopenharmony_ci    int i, nb_markers, ret;
226cabdff1aSopenharmony_ci    size_t len;
227cabdff1aSopenharmony_ci    char name[1024];
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ci    avio_skip(pb, 8);
230cabdff1aSopenharmony_ci    avio_skip(pb, 8); // skip reserved GUID
231cabdff1aSopenharmony_ci    nb_markers = avio_rl32(pb);
232cabdff1aSopenharmony_ci    avio_skip(pb, 2); // skip reserved field
233cabdff1aSopenharmony_ci    len = avio_rl16(pb);
234cabdff1aSopenharmony_ci    for (i = 0; i < len; i++)
235cabdff1aSopenharmony_ci        avio_skip(pb, 1);
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci    for (i = 0; i < nb_markers; i++) {
238cabdff1aSopenharmony_ci        int64_t pts;
239cabdff1aSopenharmony_ci
240cabdff1aSopenharmony_ci        avio_skip(pb, 8);
241cabdff1aSopenharmony_ci        pts = avio_rl64(pb);
242cabdff1aSopenharmony_ci        pts -= asf->preroll * 10000;
243cabdff1aSopenharmony_ci        avio_skip(pb, 2); // entry length
244cabdff1aSopenharmony_ci        avio_skip(pb, 4); // send time
245cabdff1aSopenharmony_ci        avio_skip(pb, 4); // flags
246cabdff1aSopenharmony_ci        len = avio_rl32(pb);
247cabdff1aSopenharmony_ci
248cabdff1aSopenharmony_ci        if (avio_feof(pb))
249cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_ci        if ((ret = avio_get_str16le(pb, len, name,
252cabdff1aSopenharmony_ci                                    sizeof(name))) < len)
253cabdff1aSopenharmony_ci            avio_skip(pb, len - ret);
254cabdff1aSopenharmony_ci        avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pts,
255cabdff1aSopenharmony_ci                           AV_NOPTS_VALUE, name);
256cabdff1aSopenharmony_ci    }
257cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci    return 0;
260cabdff1aSopenharmony_ci}
261cabdff1aSopenharmony_ci
262cabdff1aSopenharmony_cistatic int asf_read_metadata(AVFormatContext *s, const char *title, uint16_t len,
263cabdff1aSopenharmony_ci                             unsigned char *ch, uint16_t buflen)
264cabdff1aSopenharmony_ci{
265cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    avio_get_str16le(pb, len, ch, buflen);
268cabdff1aSopenharmony_ci    if (ch[0]) {
269cabdff1aSopenharmony_ci        if (av_dict_set(&s->metadata, title, ch, 0) < 0)
270cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
271cabdff1aSopenharmony_ci    }
272cabdff1aSopenharmony_ci
273cabdff1aSopenharmony_ci    return 0;
274cabdff1aSopenharmony_ci}
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_cistatic int asf_read_value(AVFormatContext *s, const uint8_t *name,
277cabdff1aSopenharmony_ci                          uint16_t val_len, int type, AVDictionary **met)
278cabdff1aSopenharmony_ci{
279cabdff1aSopenharmony_ci    int ret;
280cabdff1aSopenharmony_ci    uint8_t *value;
281cabdff1aSopenharmony_ci    uint16_t buflen = 2 * val_len + 1;
282cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci    value = av_malloc(buflen);
285cabdff1aSopenharmony_ci    if (!value)
286cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
287cabdff1aSopenharmony_ci    if (type == ASF_UNICODE) {
288cabdff1aSopenharmony_ci        // get_asf_string reads UTF-16 and converts it to UTF-8 which needs longer buffer
289cabdff1aSopenharmony_ci        if ((ret = get_asf_string(pb, val_len, value, buflen)) < 0)
290cabdff1aSopenharmony_ci            goto failed;
291cabdff1aSopenharmony_ci        if (av_dict_set(met, name, value, 0) < 0)
292cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
293cabdff1aSopenharmony_ci    } else {
294cabdff1aSopenharmony_ci        char buf[256];
295cabdff1aSopenharmony_ci        if (val_len > sizeof(buf)) {
296cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
297cabdff1aSopenharmony_ci            goto failed;
298cabdff1aSopenharmony_ci        }
299cabdff1aSopenharmony_ci        if ((ret = avio_read(pb, value, val_len)) < 0)
300cabdff1aSopenharmony_ci            goto failed;
301cabdff1aSopenharmony_ci        if (ret < 2 * val_len)
302cabdff1aSopenharmony_ci            value[ret] = '\0';
303cabdff1aSopenharmony_ci        else
304cabdff1aSopenharmony_ci            value[2 * val_len - 1] = '\0';
305cabdff1aSopenharmony_ci        snprintf(buf, sizeof(buf), "%s", value);
306cabdff1aSopenharmony_ci        if (av_dict_set(met, name, buf, 0) < 0)
307cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
308cabdff1aSopenharmony_ci    }
309cabdff1aSopenharmony_ci    av_freep(&value);
310cabdff1aSopenharmony_ci
311cabdff1aSopenharmony_ci    return 0;
312cabdff1aSopenharmony_ci
313cabdff1aSopenharmony_cifailed:
314cabdff1aSopenharmony_ci    av_freep(&value);
315cabdff1aSopenharmony_ci    return ret;
316cabdff1aSopenharmony_ci}
317cabdff1aSopenharmony_cistatic int asf_read_generic_value(AVIOContext *pb, int type, uint64_t *value)
318cabdff1aSopenharmony_ci{
319cabdff1aSopenharmony_ci
320cabdff1aSopenharmony_ci    switch (type) {
321cabdff1aSopenharmony_ci    case ASF_BOOL:
322cabdff1aSopenharmony_ci        *value = avio_rl16(pb);
323cabdff1aSopenharmony_ci        break;
324cabdff1aSopenharmony_ci    case ASF_DWORD:
325cabdff1aSopenharmony_ci        *value = avio_rl32(pb);
326cabdff1aSopenharmony_ci        break;
327cabdff1aSopenharmony_ci    case ASF_QWORD:
328cabdff1aSopenharmony_ci        *value = avio_rl64(pb);
329cabdff1aSopenharmony_ci        break;
330cabdff1aSopenharmony_ci    case ASF_WORD:
331cabdff1aSopenharmony_ci        *value = avio_rl16(pb);
332cabdff1aSopenharmony_ci        break;
333cabdff1aSopenharmony_ci    default:
334cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
335cabdff1aSopenharmony_ci    }
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci    return 0;
338cabdff1aSopenharmony_ci}
339cabdff1aSopenharmony_ci
340cabdff1aSopenharmony_cistatic int asf_set_metadata(AVFormatContext *s, const uint8_t *name,
341cabdff1aSopenharmony_ci                            int type, AVDictionary **met)
342cabdff1aSopenharmony_ci{
343cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
344cabdff1aSopenharmony_ci    uint64_t value;
345cabdff1aSopenharmony_ci    char buf[32];
346cabdff1aSopenharmony_ci    int ret;
347cabdff1aSopenharmony_ci
348cabdff1aSopenharmony_ci    ret = asf_read_generic_value(pb, type, &value);
349cabdff1aSopenharmony_ci    if (ret < 0)
350cabdff1aSopenharmony_ci        return ret;
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    snprintf(buf, sizeof(buf), "%"PRIu64, value);
353cabdff1aSopenharmony_ci    if (av_dict_set(met, name, buf, 0) < 0)
354cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    return 0;
357cabdff1aSopenharmony_ci}
358cabdff1aSopenharmony_ci
359cabdff1aSopenharmony_cistatic int process_metadata(AVFormatContext *s, const uint8_t *name, uint16_t name_len,
360cabdff1aSopenharmony_ci                            uint16_t val_len, uint16_t type, AVDictionary **met)
361cabdff1aSopenharmony_ci{
362cabdff1aSopenharmony_ci    int ret;
363cabdff1aSopenharmony_ci    ff_asf_guid guid;
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    if (val_len) {
366cabdff1aSopenharmony_ci        switch (type) {
367cabdff1aSopenharmony_ci        case ASF_UNICODE:
368cabdff1aSopenharmony_ci            asf_read_value(s, name, val_len, type, met);
369cabdff1aSopenharmony_ci            break;
370cabdff1aSopenharmony_ci        case ASF_BYTE_ARRAY:
371cabdff1aSopenharmony_ci            if (ff_asf_handle_byte_array(s, name, val_len) > 0)
372cabdff1aSopenharmony_ci                asf_read_value(s, name, val_len, type, met);
373cabdff1aSopenharmony_ci            break;
374cabdff1aSopenharmony_ci        case ASF_GUID:
375cabdff1aSopenharmony_ci            ff_get_guid(s->pb, &guid);
376cabdff1aSopenharmony_ci            break;
377cabdff1aSopenharmony_ci        default:
378cabdff1aSopenharmony_ci            if ((ret = asf_set_metadata(s, name, type, met)) < 0)
379cabdff1aSopenharmony_ci                return ret;
380cabdff1aSopenharmony_ci            break;
381cabdff1aSopenharmony_ci        }
382cabdff1aSopenharmony_ci    }
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ci    return 0;
385cabdff1aSopenharmony_ci}
386cabdff1aSopenharmony_ci
387cabdff1aSopenharmony_cistatic int asf_read_ext_content(AVFormatContext *s, const GUIDParseTable *g)
388cabdff1aSopenharmony_ci{
389cabdff1aSopenharmony_ci    ASFContext *asf  = s->priv_data;
390cabdff1aSopenharmony_ci    AVIOContext *pb  = s->pb;
391cabdff1aSopenharmony_ci    uint64_t size    = avio_rl64(pb);
392cabdff1aSopenharmony_ci    uint16_t nb_desc = avio_rl16(pb);
393cabdff1aSopenharmony_ci    int i, ret;
394cabdff1aSopenharmony_ci
395cabdff1aSopenharmony_ci    for (i = 0; i < nb_desc; i++) {
396cabdff1aSopenharmony_ci        uint16_t name_len, type, val_len;
397cabdff1aSopenharmony_ci        uint8_t *name = NULL;
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci        name_len = avio_rl16(pb);
400cabdff1aSopenharmony_ci        if (!name_len)
401cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
402cabdff1aSopenharmony_ci        name = av_malloc(name_len);
403cabdff1aSopenharmony_ci        if (!name)
404cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
405cabdff1aSopenharmony_ci        avio_get_str16le(pb, name_len, name,
406cabdff1aSopenharmony_ci                         name_len);
407cabdff1aSopenharmony_ci        type    = avio_rl16(pb);
408cabdff1aSopenharmony_ci        // BOOL values are 16 bits long in the Metadata Object
409cabdff1aSopenharmony_ci        // but 32 bits long in the Extended Content Description Object
410cabdff1aSopenharmony_ci        if (type == ASF_BOOL)
411cabdff1aSopenharmony_ci            type = ASF_DWORD;
412cabdff1aSopenharmony_ci        val_len = avio_rl16(pb);
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_ci        ret = process_metadata(s, name, name_len, val_len, type, &s->metadata);
415cabdff1aSopenharmony_ci        av_freep(&name);
416cabdff1aSopenharmony_ci        if (ret < 0)
417cabdff1aSopenharmony_ci            return ret;
418cabdff1aSopenharmony_ci    }
419cabdff1aSopenharmony_ci
420cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
421cabdff1aSopenharmony_ci    return 0;
422cabdff1aSopenharmony_ci}
423cabdff1aSopenharmony_ci
424cabdff1aSopenharmony_cistatic AVStream *find_stream(AVFormatContext *s, uint16_t st_num)
425cabdff1aSopenharmony_ci{
426cabdff1aSopenharmony_ci    AVStream *st = NULL;
427cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
428cabdff1aSopenharmony_ci    int i;
429cabdff1aSopenharmony_ci
430cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
431cabdff1aSopenharmony_ci        if (asf->asf_st[i]->stream_index == st_num) {
432cabdff1aSopenharmony_ci            st = s->streams[asf->asf_st[i]->index];
433cabdff1aSopenharmony_ci            break;
434cabdff1aSopenharmony_ci        }
435cabdff1aSopenharmony_ci    }
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    return st;
438cabdff1aSopenharmony_ci}
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_cistatic int asf_store_aspect_ratio(AVFormatContext *s, uint8_t st_num, uint8_t *name, int type)
441cabdff1aSopenharmony_ci{
442cabdff1aSopenharmony_ci    ASFContext *asf   = s->priv_data;
443cabdff1aSopenharmony_ci    AVIOContext *pb   = s->pb;
444cabdff1aSopenharmony_ci    uint64_t value = 0;
445cabdff1aSopenharmony_ci    int ret;
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_ci    ret = asf_read_generic_value(pb, type, &value);
448cabdff1aSopenharmony_ci    if (ret < 0)
449cabdff1aSopenharmony_ci        return ret;
450cabdff1aSopenharmony_ci
451cabdff1aSopenharmony_ci    if (st_num < ASF_MAX_STREAMS) {
452cabdff1aSopenharmony_ci        if (!strcmp(name, "AspectRatioX"))
453cabdff1aSopenharmony_ci            asf->asf_sd[st_num].aspect_ratio.num = value;
454cabdff1aSopenharmony_ci        else
455cabdff1aSopenharmony_ci            asf->asf_sd[st_num].aspect_ratio.den = value;
456cabdff1aSopenharmony_ci    }
457cabdff1aSopenharmony_ci    return 0;
458cabdff1aSopenharmony_ci}
459cabdff1aSopenharmony_ci
460cabdff1aSopenharmony_cistatic int asf_read_metadata_obj(AVFormatContext *s, const GUIDParseTable *g)
461cabdff1aSopenharmony_ci{
462cabdff1aSopenharmony_ci    ASFContext *asf   = s->priv_data;
463cabdff1aSopenharmony_ci    AVIOContext *pb   = s->pb;
464cabdff1aSopenharmony_ci    uint64_t size     = avio_rl64(pb);
465cabdff1aSopenharmony_ci    uint16_t nb_recs  = avio_rl16(pb); // number of records in the Description Records list
466cabdff1aSopenharmony_ci    int i, ret;
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci    for (i = 0; i < nb_recs; i++) {
469cabdff1aSopenharmony_ci        uint16_t name_len, buflen, type, val_len, st_num;
470cabdff1aSopenharmony_ci        uint8_t *name = NULL;
471cabdff1aSopenharmony_ci
472cabdff1aSopenharmony_ci        avio_skip(pb, 2); // skip reserved field
473cabdff1aSopenharmony_ci        st_num   = avio_rl16(pb);
474cabdff1aSopenharmony_ci        name_len = avio_rl16(pb);
475cabdff1aSopenharmony_ci        buflen   = 2 * name_len + 1;
476cabdff1aSopenharmony_ci        if (!name_len)
477cabdff1aSopenharmony_ci            break;
478cabdff1aSopenharmony_ci        type     = avio_rl16(pb);
479cabdff1aSopenharmony_ci        val_len  = avio_rl32(pb);
480cabdff1aSopenharmony_ci        name     = av_malloc(buflen);
481cabdff1aSopenharmony_ci        if (!name)
482cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
483cabdff1aSopenharmony_ci        avio_get_str16le(pb, name_len, name,
484cabdff1aSopenharmony_ci                         buflen);
485cabdff1aSopenharmony_ci        if (!strcmp(name, "AspectRatioX") || !strcmp(name, "AspectRatioY")) {
486cabdff1aSopenharmony_ci            ret = asf_store_aspect_ratio(s, st_num, name, type);
487cabdff1aSopenharmony_ci            if (ret < 0) {
488cabdff1aSopenharmony_ci                av_freep(&name);
489cabdff1aSopenharmony_ci                break;
490cabdff1aSopenharmony_ci            }
491cabdff1aSopenharmony_ci        } else {
492cabdff1aSopenharmony_ci            if (st_num < ASF_MAX_STREAMS) {
493cabdff1aSopenharmony_ci                if ((ret = process_metadata(s, name, name_len, val_len, type,
494cabdff1aSopenharmony_ci                                            st_num ? &asf->asf_sd[st_num].asf_met
495cabdff1aSopenharmony_ci                                                   : &s->metadata)) < 0) {
496cabdff1aSopenharmony_ci                    av_freep(&name);
497cabdff1aSopenharmony_ci                    break;
498cabdff1aSopenharmony_ci                }
499cabdff1aSopenharmony_ci            }
500cabdff1aSopenharmony_ci        }
501cabdff1aSopenharmony_ci        av_freep(&name);
502cabdff1aSopenharmony_ci    }
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
505cabdff1aSopenharmony_ci    return 0;
506cabdff1aSopenharmony_ci}
507cabdff1aSopenharmony_ci
508cabdff1aSopenharmony_cistatic int asf_read_content_desc(AVFormatContext *s, const GUIDParseTable *g)
509cabdff1aSopenharmony_ci{
510cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
511cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
512cabdff1aSopenharmony_ci    int i;
513cabdff1aSopenharmony_ci    static const char *const titles[] =
514cabdff1aSopenharmony_ci    { "Title", "Author", "Copyright", "Description", "Rate" };
515cabdff1aSopenharmony_ci    uint16_t len[5], buflen[5] = { 0 };
516cabdff1aSopenharmony_ci    uint8_t *ch;
517cabdff1aSopenharmony_ci    uint64_t size = avio_rl64(pb);
518cabdff1aSopenharmony_ci
519cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++) {
520cabdff1aSopenharmony_ci        len[i]  = avio_rl16(pb);
521cabdff1aSopenharmony_ci        // utf8 string should be <= 2 * utf16 string, extra byte for the terminator
522cabdff1aSopenharmony_ci        buflen[i]  = 2 * len[i] + 1;
523cabdff1aSopenharmony_ci    }
524cabdff1aSopenharmony_ci
525cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++) {
526cabdff1aSopenharmony_ci        ch = av_malloc(buflen[i]);
527cabdff1aSopenharmony_ci        if (!ch)
528cabdff1aSopenharmony_ci            return(AVERROR(ENOMEM));
529cabdff1aSopenharmony_ci        asf_read_metadata(s, titles[i], len[i], ch, buflen[i]);
530cabdff1aSopenharmony_ci        av_freep(&ch);
531cabdff1aSopenharmony_ci    }
532cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
533cabdff1aSopenharmony_ci
534cabdff1aSopenharmony_ci    return 0;
535cabdff1aSopenharmony_ci}
536cabdff1aSopenharmony_ci
537cabdff1aSopenharmony_cistatic int asf_read_properties(AVFormatContext *s, const GUIDParseTable *g)
538cabdff1aSopenharmony_ci{
539cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
540cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
541cabdff1aSopenharmony_ci    time_t creation_time;
542cabdff1aSopenharmony_ci
543cabdff1aSopenharmony_ci    avio_rl64(pb); // read object size
544cabdff1aSopenharmony_ci    avio_skip(pb, 16); // skip File ID
545cabdff1aSopenharmony_ci    avio_skip(pb, 8);  // skip File size
546cabdff1aSopenharmony_ci    creation_time = avio_rl64(pb);
547cabdff1aSopenharmony_ci    if (!(asf->b_flags & ASF_FLAG_BROADCAST)) {
548cabdff1aSopenharmony_ci        struct tm tmbuf;
549cabdff1aSopenharmony_ci        struct tm *tm;
550cabdff1aSopenharmony_ci        char buf[64];
551cabdff1aSopenharmony_ci
552cabdff1aSopenharmony_ci        // creation date is in 100 ns units from 1 Jan 1601, conversion to s
553cabdff1aSopenharmony_ci        creation_time /= 10000000;
554cabdff1aSopenharmony_ci        // there are 11644473600 seconds between 1 Jan 1601 and 1 Jan 1970
555cabdff1aSopenharmony_ci        creation_time -= 11644473600;
556cabdff1aSopenharmony_ci        tm = gmtime_r(&creation_time, &tmbuf);
557cabdff1aSopenharmony_ci        if (tm) {
558cabdff1aSopenharmony_ci            if (!strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm))
559cabdff1aSopenharmony_ci                buf[0] = '\0';
560cabdff1aSopenharmony_ci        } else
561cabdff1aSopenharmony_ci            buf[0] = '\0';
562cabdff1aSopenharmony_ci        if (buf[0]) {
563cabdff1aSopenharmony_ci            if (av_dict_set(&s->metadata, "creation_time", buf, 0) < 0)
564cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
565cabdff1aSopenharmony_ci        }
566cabdff1aSopenharmony_ci    }
567cabdff1aSopenharmony_ci    asf->nb_packets  = avio_rl64(pb);
568cabdff1aSopenharmony_ci    asf->duration    = avio_rl64(pb) / 10000; // stream duration
569cabdff1aSopenharmony_ci    avio_skip(pb, 8); // skip send duration
570cabdff1aSopenharmony_ci    asf->preroll     = avio_rl64(pb);
571cabdff1aSopenharmony_ci    asf->duration   -= asf->preroll;
572cabdff1aSopenharmony_ci    asf->b_flags     = avio_rl32(pb);
573cabdff1aSopenharmony_ci    avio_skip(pb, 4); // skip minimal packet size
574cabdff1aSopenharmony_ci    asf->packet_size  = avio_rl32(pb);
575cabdff1aSopenharmony_ci    avio_skip(pb, 4); // skip max_bitrate
576cabdff1aSopenharmony_ci
577cabdff1aSopenharmony_ci    return 0;
578cabdff1aSopenharmony_ci}
579cabdff1aSopenharmony_ci
580cabdff1aSopenharmony_cistatic int parse_video_info(AVFormatContext *avfmt, AVIOContext *pb, AVStream *st)
581cabdff1aSopenharmony_ci{
582cabdff1aSopenharmony_ci    uint16_t size_asf; // ASF-specific Format Data size
583cabdff1aSopenharmony_ci    uint32_t size_bmp; // BMP_HEADER-specific Format Data size
584cabdff1aSopenharmony_ci    unsigned int tag;
585cabdff1aSopenharmony_ci
586cabdff1aSopenharmony_ci    st->codecpar->width  = avio_rl32(pb);
587cabdff1aSopenharmony_ci    st->codecpar->height = avio_rl32(pb);
588cabdff1aSopenharmony_ci    avio_skip(pb, 1); // skip reserved flags
589cabdff1aSopenharmony_ci    size_asf = avio_rl16(pb);
590cabdff1aSopenharmony_ci    tag = ff_get_bmp_header(pb, st, &size_bmp);
591cabdff1aSopenharmony_ci    st->codecpar->codec_tag = tag;
592cabdff1aSopenharmony_ci    st->codecpar->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag);
593cabdff1aSopenharmony_ci    size_bmp = FFMAX(size_asf, size_bmp);
594cabdff1aSopenharmony_ci
595cabdff1aSopenharmony_ci    if (size_bmp > BMP_HEADER_SIZE) {
596cabdff1aSopenharmony_ci        int ret = ff_get_extradata(avfmt, st->codecpar, pb, size_bmp - BMP_HEADER_SIZE);
597cabdff1aSopenharmony_ci
598cabdff1aSopenharmony_ci        if (ret < 0)
599cabdff1aSopenharmony_ci            return ret;
600cabdff1aSopenharmony_ci    }
601cabdff1aSopenharmony_ci    return 0;
602cabdff1aSopenharmony_ci}
603cabdff1aSopenharmony_ci
604cabdff1aSopenharmony_cistatic int asf_read_stream_properties(AVFormatContext *s, const GUIDParseTable *g)
605cabdff1aSopenharmony_ci{
606cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
607cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
608cabdff1aSopenharmony_ci    uint64_t size;
609cabdff1aSopenharmony_ci    uint32_t err_data_len, ts_data_len; // type specific data length
610cabdff1aSopenharmony_ci    uint16_t flags;
611cabdff1aSopenharmony_ci    ff_asf_guid stream_type;
612cabdff1aSopenharmony_ci    enum AVMediaType type;
613cabdff1aSopenharmony_ci    int i, ret;
614cabdff1aSopenharmony_ci    uint8_t stream_index;
615cabdff1aSopenharmony_ci    AVStream *st;
616cabdff1aSopenharmony_ci    ASFStream *asf_st;
617cabdff1aSopenharmony_ci
618cabdff1aSopenharmony_ci    // ASF file must not contain more than 128 streams according to the specification
619cabdff1aSopenharmony_ci    if (asf->nb_streams >= ASF_MAX_STREAMS)
620cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
621cabdff1aSopenharmony_ci
622cabdff1aSopenharmony_ci    size = avio_rl64(pb);
623cabdff1aSopenharmony_ci    ff_get_guid(pb, &stream_type);
624cabdff1aSopenharmony_ci    if (!ff_guidcmp(&stream_type, &ff_asf_audio_stream))
625cabdff1aSopenharmony_ci        type = AVMEDIA_TYPE_AUDIO;
626cabdff1aSopenharmony_ci    else if (!ff_guidcmp(&stream_type, &ff_asf_video_stream))
627cabdff1aSopenharmony_ci        type = AVMEDIA_TYPE_VIDEO;
628cabdff1aSopenharmony_ci    else if (!ff_guidcmp(&stream_type, &ff_asf_jfif_media))
629cabdff1aSopenharmony_ci        type = AVMEDIA_TYPE_VIDEO;
630cabdff1aSopenharmony_ci    else if (!ff_guidcmp(&stream_type, &ff_asf_command_stream))
631cabdff1aSopenharmony_ci        type = AVMEDIA_TYPE_DATA;
632cabdff1aSopenharmony_ci    else if (!ff_guidcmp(&stream_type,
633cabdff1aSopenharmony_ci                         &ff_asf_ext_stream_embed_stream_header))
634cabdff1aSopenharmony_ci        type = AVMEDIA_TYPE_UNKNOWN;
635cabdff1aSopenharmony_ci    else
636cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
637cabdff1aSopenharmony_ci
638cabdff1aSopenharmony_ci    ff_get_guid(pb, &stream_type); // error correction type
639cabdff1aSopenharmony_ci    avio_skip(pb, 8); // skip the time offset
640cabdff1aSopenharmony_ci    ts_data_len      = avio_rl32(pb);
641cabdff1aSopenharmony_ci    err_data_len     = avio_rl32(pb);
642cabdff1aSopenharmony_ci    flags            = avio_rl16(pb); // bit 15 - Encrypted Content
643cabdff1aSopenharmony_ci
644cabdff1aSopenharmony_ci    stream_index = flags & ASF_STREAM_NUM;
645cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++)
646cabdff1aSopenharmony_ci        if (stream_index == asf->asf_st[i]->stream_index) {
647cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING,
648cabdff1aSopenharmony_ci                   "Duplicate stream found, this stream will be ignored.\n");
649cabdff1aSopenharmony_ci            align_position(pb, asf->offset, size);
650cabdff1aSopenharmony_ci            return 0;
651cabdff1aSopenharmony_ci        }
652cabdff1aSopenharmony_ci
653cabdff1aSopenharmony_ci    st = avformat_new_stream(s, NULL);
654cabdff1aSopenharmony_ci    if (!st)
655cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
656cabdff1aSopenharmony_ci    avpriv_set_pts_info(st, 32, 1, 1000); // pts should be dword, in milliseconds
657cabdff1aSopenharmony_ci    st->codecpar->codec_type = type;
658cabdff1aSopenharmony_ci    asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st));
659cabdff1aSopenharmony_ci    if (!asf->asf_st[asf->nb_streams])
660cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
661cabdff1aSopenharmony_ci    asf_st                       = asf->asf_st[asf->nb_streams];
662cabdff1aSopenharmony_ci    asf->nb_streams++;
663cabdff1aSopenharmony_ci    asf_st->stream_index         = stream_index;
664cabdff1aSopenharmony_ci    asf_st->index                = st->index;
665cabdff1aSopenharmony_ci    asf_st->indexed              = 0;
666cabdff1aSopenharmony_ci    st->id                       = flags & ASF_STREAM_NUM;
667cabdff1aSopenharmony_ci    asf_st->pkt.data_size        = 0;
668cabdff1aSopenharmony_ci    asf_st->pkt.avpkt = av_packet_alloc();
669cabdff1aSopenharmony_ci    if (!asf_st->pkt.avpkt)
670cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
671cabdff1aSopenharmony_ci    avio_skip(pb, 4); // skip reserved field
672cabdff1aSopenharmony_ci
673cabdff1aSopenharmony_ci    switch (type) {
674cabdff1aSopenharmony_ci    case AVMEDIA_TYPE_AUDIO:
675cabdff1aSopenharmony_ci        asf_st->type = AVMEDIA_TYPE_AUDIO;
676cabdff1aSopenharmony_ci        if ((ret = ff_get_wav_header(s, pb, st->codecpar, ts_data_len, 0)) < 0)
677cabdff1aSopenharmony_ci            return ret;
678cabdff1aSopenharmony_ci        break;
679cabdff1aSopenharmony_ci    case AVMEDIA_TYPE_VIDEO:
680cabdff1aSopenharmony_ci        asf_st->type = AVMEDIA_TYPE_VIDEO;
681cabdff1aSopenharmony_ci        if ((ret = parse_video_info(s, pb, st)) < 0)
682cabdff1aSopenharmony_ci            return ret;
683cabdff1aSopenharmony_ci        break;
684cabdff1aSopenharmony_ci    default:
685cabdff1aSopenharmony_ci        avio_skip(pb, ts_data_len);
686cabdff1aSopenharmony_ci        break;
687cabdff1aSopenharmony_ci    }
688cabdff1aSopenharmony_ci
689cabdff1aSopenharmony_ci    if (err_data_len) {
690cabdff1aSopenharmony_ci        if (type == AVMEDIA_TYPE_AUDIO) {
691cabdff1aSopenharmony_ci            uint8_t span = avio_r8(pb);
692cabdff1aSopenharmony_ci            if (span > 1) {
693cabdff1aSopenharmony_ci                asf_st->span              = span;
694cabdff1aSopenharmony_ci                asf_st->virtual_pkt_len   = avio_rl16(pb);
695cabdff1aSopenharmony_ci                asf_st->virtual_chunk_len = avio_rl16(pb);
696cabdff1aSopenharmony_ci                if (!asf_st->virtual_chunk_len || !asf_st->virtual_pkt_len)
697cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
698cabdff1aSopenharmony_ci                avio_skip(pb, err_data_len - 5);
699cabdff1aSopenharmony_ci            } else
700cabdff1aSopenharmony_ci                avio_skip(pb, err_data_len - 1);
701cabdff1aSopenharmony_ci        } else
702cabdff1aSopenharmony_ci            avio_skip(pb, err_data_len);
703cabdff1aSopenharmony_ci    }
704cabdff1aSopenharmony_ci
705cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
706cabdff1aSopenharmony_ci
707cabdff1aSopenharmony_ci    return 0;
708cabdff1aSopenharmony_ci}
709cabdff1aSopenharmony_ci
710cabdff1aSopenharmony_cistatic void set_language(AVFormatContext *s, const char *rfc1766, AVDictionary **met)
711cabdff1aSopenharmony_ci{
712cabdff1aSopenharmony_ci    // language abbr should contain at least 2 chars
713cabdff1aSopenharmony_ci    if (rfc1766 && strlen(rfc1766) > 1) {
714cabdff1aSopenharmony_ci        const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any
715cabdff1aSopenharmony_ci        const char *iso6392       = ff_convert_lang_to(primary_tag,
716cabdff1aSopenharmony_ci                                                       AV_LANG_ISO639_2_BIBL);
717cabdff1aSopenharmony_ci        if (iso6392)
718cabdff1aSopenharmony_ci            if (av_dict_set(met, "language", iso6392, 0) < 0)
719cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n");
720cabdff1aSopenharmony_ci    }
721cabdff1aSopenharmony_ci}
722cabdff1aSopenharmony_ci
723cabdff1aSopenharmony_cistatic int asf_read_ext_stream_properties(AVFormatContext *s, const GUIDParseTable *g)
724cabdff1aSopenharmony_ci{
725cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
726cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
727cabdff1aSopenharmony_ci    AVStream *st    = NULL;
728cabdff1aSopenharmony_ci    ff_asf_guid guid;
729cabdff1aSopenharmony_ci    uint16_t nb_st_name, nb_pay_exts, st_num, lang_idx;
730cabdff1aSopenharmony_ci    int i, ret;
731cabdff1aSopenharmony_ci    uint32_t bitrate;
732cabdff1aSopenharmony_ci    uint64_t start_time, end_time, time_per_frame;
733cabdff1aSopenharmony_ci    uint64_t size = avio_rl64(pb);
734cabdff1aSopenharmony_ci
735cabdff1aSopenharmony_ci    start_time = avio_rl64(pb);
736cabdff1aSopenharmony_ci    end_time   = avio_rl64(pb);
737cabdff1aSopenharmony_ci    bitrate    = avio_rl32(pb);
738cabdff1aSopenharmony_ci    avio_skip(pb, 28); // skip some unused values
739cabdff1aSopenharmony_ci    st_num     = avio_rl16(pb);
740cabdff1aSopenharmony_ci    st_num    &= ASF_STREAM_NUM;
741cabdff1aSopenharmony_ci    lang_idx   = avio_rl16(pb); // Stream Language ID Index
742cabdff1aSopenharmony_ci    if (lang_idx >= ASF_MAX_STREAMS)
743cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
744cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
745cabdff1aSopenharmony_ci        if (st_num == asf->asf_st[i]->stream_index) {
746cabdff1aSopenharmony_ci            st                       = s->streams[asf->asf_st[i]->index];
747cabdff1aSopenharmony_ci            asf->asf_st[i]->lang_idx = lang_idx;
748cabdff1aSopenharmony_ci            break;
749cabdff1aSopenharmony_ci        }
750cabdff1aSopenharmony_ci    }
751cabdff1aSopenharmony_ci    time_per_frame = avio_rl64(pb); // average time per frame
752cabdff1aSopenharmony_ci    if (st) {
753cabdff1aSopenharmony_ci        st->start_time           = start_time;
754cabdff1aSopenharmony_ci        st->duration             = end_time - start_time;
755cabdff1aSopenharmony_ci        st->codecpar->bit_rate   = bitrate;
756cabdff1aSopenharmony_ci        st->avg_frame_rate.num   = 10000000;
757cabdff1aSopenharmony_ci        st->avg_frame_rate.den   = time_per_frame;
758cabdff1aSopenharmony_ci    }
759cabdff1aSopenharmony_ci    nb_st_name = avio_rl16(pb);
760cabdff1aSopenharmony_ci    nb_pay_exts   = avio_rl16(pb);
761cabdff1aSopenharmony_ci    for (i = 0; i < nb_st_name; i++) {
762cabdff1aSopenharmony_ci        uint16_t len;
763cabdff1aSopenharmony_ci
764cabdff1aSopenharmony_ci        avio_rl16(pb); // Language ID Index
765cabdff1aSopenharmony_ci        len = avio_rl16(pb);
766cabdff1aSopenharmony_ci        avio_skip(pb, len);
767cabdff1aSopenharmony_ci    }
768cabdff1aSopenharmony_ci
769cabdff1aSopenharmony_ci    for (i = 0; i < nb_pay_exts; i++) {
770cabdff1aSopenharmony_ci        uint32_t len;
771cabdff1aSopenharmony_ci        avio_skip(pb, 16); // Extension System ID
772cabdff1aSopenharmony_ci        avio_skip(pb, 2);  // Extension Data Size
773cabdff1aSopenharmony_ci        len = avio_rl32(pb);
774cabdff1aSopenharmony_ci        avio_skip(pb, len);
775cabdff1aSopenharmony_ci    }
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci    if ((ret = ff_get_guid(pb, &guid)) < 0) {
778cabdff1aSopenharmony_ci        align_position(pb, asf->offset, size);
779cabdff1aSopenharmony_ci
780cabdff1aSopenharmony_ci        return 0;
781cabdff1aSopenharmony_ci    }
782cabdff1aSopenharmony_ci
783cabdff1aSopenharmony_ci    g = find_guid(guid);
784cabdff1aSopenharmony_ci    if (g && !(strcmp(g->name, "Stream Properties"))) {
785cabdff1aSopenharmony_ci        if ((ret = g->read_object(s, g)) < 0)
786cabdff1aSopenharmony_ci            return ret;
787cabdff1aSopenharmony_ci    }
788cabdff1aSopenharmony_ci
789cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
790cabdff1aSopenharmony_ci    return 0;
791cabdff1aSopenharmony_ci}
792cabdff1aSopenharmony_ci
793cabdff1aSopenharmony_cistatic int asf_read_language_list(AVFormatContext *s, const GUIDParseTable *g)
794cabdff1aSopenharmony_ci{
795cabdff1aSopenharmony_ci    ASFContext *asf   = s->priv_data;
796cabdff1aSopenharmony_ci    AVIOContext *pb   = s->pb;
797cabdff1aSopenharmony_ci    int i, ret;
798cabdff1aSopenharmony_ci    uint64_t size     = avio_rl64(pb);
799cabdff1aSopenharmony_ci    uint16_t nb_langs = avio_rl16(pb);
800cabdff1aSopenharmony_ci
801cabdff1aSopenharmony_ci    if (nb_langs < ASF_MAX_STREAMS) {
802cabdff1aSopenharmony_ci        for (i = 0; i < nb_langs; i++) {
803cabdff1aSopenharmony_ci            size_t len;
804cabdff1aSopenharmony_ci            len = avio_r8(pb);
805cabdff1aSopenharmony_ci            if (!len)
806cabdff1aSopenharmony_ci                len = 6;
807cabdff1aSopenharmony_ci            if ((ret = get_asf_string(pb, len, asf->asf_sd[i].langs,
808cabdff1aSopenharmony_ci                                      sizeof(asf->asf_sd[i].langs))) < 0) {
809cabdff1aSopenharmony_ci                return ret;
810cabdff1aSopenharmony_ci            }
811cabdff1aSopenharmony_ci        }
812cabdff1aSopenharmony_ci    }
813cabdff1aSopenharmony_ci
814cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
815cabdff1aSopenharmony_ci    return 0;
816cabdff1aSopenharmony_ci}
817cabdff1aSopenharmony_ci
818cabdff1aSopenharmony_ci// returns data object offset when reading this object for the first time
819cabdff1aSopenharmony_cistatic int asf_read_data(AVFormatContext *s, const GUIDParseTable *g)
820cabdff1aSopenharmony_ci{
821cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
822cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
823cabdff1aSopenharmony_ci    uint64_t size   = asf->data_size = avio_rl64(pb);
824cabdff1aSopenharmony_ci    int i;
825cabdff1aSopenharmony_ci
826cabdff1aSopenharmony_ci    if (!asf->data_reached) {
827cabdff1aSopenharmony_ci        asf->data_reached       = 1;
828cabdff1aSopenharmony_ci        asf->data_offset        = asf->offset;
829cabdff1aSopenharmony_ci    }
830cabdff1aSopenharmony_ci
831cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
832cabdff1aSopenharmony_ci        if (!(asf->b_flags & ASF_FLAG_BROADCAST))
833cabdff1aSopenharmony_ci            s->streams[i]->duration = asf->duration;
834cabdff1aSopenharmony_ci    }
835cabdff1aSopenharmony_ci    asf->nb_mult_left           = 0;
836cabdff1aSopenharmony_ci    asf->sub_left               = 0;
837cabdff1aSopenharmony_ci    asf->state                  = PARSE_PACKET_HEADER;
838cabdff1aSopenharmony_ci    asf->return_subpayload      = 0;
839cabdff1aSopenharmony_ci    asf->packet_size_internal   = 0;
840cabdff1aSopenharmony_ci    avio_skip(pb, 16); // skip File ID
841cabdff1aSopenharmony_ci    size = avio_rl64(pb); // Total Data Packets
842cabdff1aSopenharmony_ci    if (size != asf->nb_packets)
843cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING,
844cabdff1aSopenharmony_ci               "Number of Packets from File Properties Object is not equal to Total"
845cabdff1aSopenharmony_ci               "Datapackets value! num of packets %"PRIu64" total num %"PRIu64".\n",
846cabdff1aSopenharmony_ci               size, asf->nb_packets);
847cabdff1aSopenharmony_ci    avio_skip(pb, 2); // skip reserved field
848cabdff1aSopenharmony_ci    asf->first_packet_offset = avio_tell(pb);
849cabdff1aSopenharmony_ci    if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !(asf->b_flags & ASF_FLAG_BROADCAST))
850cabdff1aSopenharmony_ci        align_position(pb, asf->offset, asf->data_size);
851cabdff1aSopenharmony_ci
852cabdff1aSopenharmony_ci    return 0;
853cabdff1aSopenharmony_ci}
854cabdff1aSopenharmony_ci
855cabdff1aSopenharmony_cistatic int asf_read_simple_index(AVFormatContext *s, const GUIDParseTable *g)
856cabdff1aSopenharmony_ci{
857cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
858cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
859cabdff1aSopenharmony_ci    AVStream *st    = NULL;
860cabdff1aSopenharmony_ci    uint64_t interval; // index entry time interval in 100 ns units, usually it's 1s
861cabdff1aSopenharmony_ci    uint32_t pkt_num, nb_entries;
862cabdff1aSopenharmony_ci    int32_t prev_pkt_num = -1;
863cabdff1aSopenharmony_ci    int i;
864cabdff1aSopenharmony_ci    int64_t offset;
865cabdff1aSopenharmony_ci    uint64_t size = avio_rl64(pb);
866cabdff1aSopenharmony_ci
867cabdff1aSopenharmony_ci    // simple index objects should be ordered by stream number, this loop tries to find
868cabdff1aSopenharmony_ci    // the first not indexed video stream
869cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
870cabdff1aSopenharmony_ci        if ((asf->asf_st[i]->type == AVMEDIA_TYPE_VIDEO) && !asf->asf_st[i]->indexed) {
871cabdff1aSopenharmony_ci            asf->asf_st[i]->indexed = 1;
872cabdff1aSopenharmony_ci            st = s->streams[asf->asf_st[i]->index];
873cabdff1aSopenharmony_ci            break;
874cabdff1aSopenharmony_ci        }
875cabdff1aSopenharmony_ci    }
876cabdff1aSopenharmony_ci    if (!st) {
877cabdff1aSopenharmony_ci        avio_skip(pb, size - 24); // if there's no video stream, skip index object
878cabdff1aSopenharmony_ci        return 0;
879cabdff1aSopenharmony_ci    }
880cabdff1aSopenharmony_ci    avio_skip(pb, 16); // skip File ID
881cabdff1aSopenharmony_ci    interval = avio_rl64(pb);
882cabdff1aSopenharmony_ci    avio_skip(pb, 4);
883cabdff1aSopenharmony_ci    nb_entries = avio_rl32(pb);
884cabdff1aSopenharmony_ci    for (i = 0; i < nb_entries; i++) {
885cabdff1aSopenharmony_ci        pkt_num = avio_rl32(pb);
886cabdff1aSopenharmony_ci        offset = avio_skip(pb, 2);
887cabdff1aSopenharmony_ci        if (offset < 0) {
888cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Skipping failed in asf_read_simple_index.\n");
889cabdff1aSopenharmony_ci            return offset;
890cabdff1aSopenharmony_ci        }
891cabdff1aSopenharmony_ci        if (prev_pkt_num != pkt_num) {
892cabdff1aSopenharmony_ci            av_add_index_entry(st, asf->first_packet_offset + asf->packet_size *
893cabdff1aSopenharmony_ci                               pkt_num, av_rescale(interval, i, 10000),
894cabdff1aSopenharmony_ci                               asf->packet_size, 0, AVINDEX_KEYFRAME);
895cabdff1aSopenharmony_ci            prev_pkt_num = pkt_num;
896cabdff1aSopenharmony_ci        }
897cabdff1aSopenharmony_ci    }
898cabdff1aSopenharmony_ci    asf->is_simple_index = 1;
899cabdff1aSopenharmony_ci    align_position(pb, asf->offset, size);
900cabdff1aSopenharmony_ci
901cabdff1aSopenharmony_ci    return 0;
902cabdff1aSopenharmony_ci}
903cabdff1aSopenharmony_ci
904cabdff1aSopenharmony_cistatic const GUIDParseTable gdef[] = {
905cabdff1aSopenharmony_ci    { "Data",                         { 0x75, 0xB2, 0x26, 0x36, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_data, 1 },
906cabdff1aSopenharmony_ci    { "Simple Index",                 { 0x33, 0x00, 0x08, 0x90, 0xE5, 0xB1, 0x11, 0xCF, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB }, asf_read_simple_index, 1 },
907cabdff1aSopenharmony_ci    { "Content Description",          { 0x75, 0xB2, 0x26, 0x33, 0x66 ,0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_content_desc, 1 },
908cabdff1aSopenharmony_ci    { "Extended Content Description", { 0xD2, 0xD0, 0xA4, 0x40, 0xE3, 0x07, 0x11, 0xD2, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5e, 0xA8, 0x50 }, asf_read_ext_content, 1 },
909cabdff1aSopenharmony_ci    { "Stream Bitrate Properties",    { 0x7B, 0xF8, 0x75, 0xCE, 0x46, 0x8D, 0x11, 0xD1, 0x8D, 0x82, 0x00, 0x60, 0x97, 0xC9, 0xA2, 0xB2 }, asf_read_unknown, 1 },
910cabdff1aSopenharmony_ci    { "File Properties",              { 0x8C, 0xAB, 0xDC, 0xA1, 0xA9, 0x47, 0x11, 0xCF, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_properties, 1 },
911cabdff1aSopenharmony_ci    { "Header Extension",             { 0x5F, 0xBF, 0x03, 0xB5, 0xA9, 0x2E, 0x11, 0xCF, 0x8E, 0xE3, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_unknown, 0 },
912cabdff1aSopenharmony_ci    { "Stream Properties",            { 0xB7, 0xDC, 0x07, 0x91, 0xA9, 0xB7, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_stream_properties, 1 },
913cabdff1aSopenharmony_ci    { "Codec List",                   { 0x86, 0xD1, 0x52, 0x40, 0x31, 0x1D, 0x11, 0xD0, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 },
914cabdff1aSopenharmony_ci    { "Marker",                       { 0xF4, 0x87, 0xCD, 0x01, 0xA9, 0x51, 0x11, 0xCF, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, asf_read_marker, 1 },
915cabdff1aSopenharmony_ci    { "Script Command",               { 0x1E, 0xFB, 0x1A, 0x30, 0x0B, 0x62, 0x11, 0xD0, 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, asf_read_unknown, 1 },
916cabdff1aSopenharmony_ci    { "Language List",                { 0x7C, 0x43, 0x46, 0xa9, 0xef, 0xe0, 0x4B, 0xFC, 0xB2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 }, asf_read_language_list, 1},
917cabdff1aSopenharmony_ci    { "Padding",                      { 0x18, 0x06, 0xD4, 0x74, 0xCA, 0xDF, 0x45, 0x09, 0xA4, 0xBA, 0x9A, 0xAB, 0xCB, 0x96, 0xAA, 0xE8 }, asf_read_unknown, 1 },
918cabdff1aSopenharmony_ci    { "DRMv1 Header",                 { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 },
919cabdff1aSopenharmony_ci    { "DRMv2 Header",                 { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9c }, asf_read_unknown, 1 },
920cabdff1aSopenharmony_ci    { "Index",                        { 0xD6, 0xE2, 0x29, 0xD3, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
921cabdff1aSopenharmony_ci    { "Media Object Index",           { 0xFE, 0xB1, 0x03, 0xF8, 0x12, 0xAD, 0x4C, 0x64, 0x84, 0x0F, 0x2A, 0x1D, 0x2F, 0x7A, 0xD4, 0x8C }, asf_read_unknown, 1 },
922cabdff1aSopenharmony_ci    { "Timecode Index",               { 0x3C, 0xB7, 0x3F, 0xD0, 0x0C, 0x4A, 0x48, 0x03, 0x95, 0x3D, 0xED, 0xF7, 0xB6, 0x22, 0x8F, 0x0C }, asf_read_unknown, 0 },
923cabdff1aSopenharmony_ci    { "Bitrate_Mutual_Exclusion",     { 0xD6, 0xE2, 0x29, 0xDC, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
924cabdff1aSopenharmony_ci    { "Error Correction",             { 0x75, 0xB2, 0x26, 0x35, 0x66, 0x8E, 0x11, 0xCF, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, asf_read_unknown, 1 },
925cabdff1aSopenharmony_ci    { "Content Branding",             { 0x22, 0x11, 0xB3, 0xFA, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 },
926cabdff1aSopenharmony_ci    { "Content Encryption",           { 0x22, 0x11, 0xB3, 0xFB, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 },
927cabdff1aSopenharmony_ci    { "Extended Content Encryption",  { 0x29, 0x8A, 0xE6, 0x14, 0x26, 0x22, 0x4C, 0x17, 0xB9, 0x35, 0xDA, 0xE0, 0x7E, 0xE9, 0x28, 0x9C }, asf_read_unknown, 1 },
928cabdff1aSopenharmony_ci    { "Digital Signature",            { 0x22, 0x11, 0xB3, 0xFC, 0xBD, 0x23, 0x11, 0xD2, 0xB4, 0xB7, 0x00, 0xA0, 0xC9, 0x55, 0xFC, 0x6E }, asf_read_unknown, 1 },
929cabdff1aSopenharmony_ci    { "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 },
930cabdff1aSopenharmony_ci    { "Advanced Mutual Exclusion",    { 0xA0, 0x86, 0x49, 0xCF, 0x47, 0x75, 0x46, 0x70, 0x8A, 0x16, 0x6E, 0x35, 0x35, 0x75, 0x66, 0xCD }, asf_read_unknown, 1 },
931cabdff1aSopenharmony_ci    { "Group Mutual Exclusion",       { 0xD1, 0x46, 0x5A, 0x40, 0x5A, 0x79, 0x43, 0x38, 0xB7, 0x1B, 0xE3, 0x6B, 0x8F, 0xD6, 0xC2, 0x49 }, asf_read_unknown, 1},
932cabdff1aSopenharmony_ci    { "Stream Prioritization",        { 0xD4, 0xFE, 0xD1, 0x5B, 0x88, 0xD3, 0x45, 0x4F, 0x81, 0xF0, 0xED, 0x5C, 0x45, 0x99, 0x9E, 0x24 }, asf_read_unknown, 1 },
933cabdff1aSopenharmony_ci    { "Bandwidth Sharing Object",     { 0xA6, 0x96, 0x09, 0xE6, 0x51, 0x7B, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 },
934cabdff1aSopenharmony_ci    { "Metadata",                     { 0xC5, 0xF8, 0xCB, 0xEA, 0x5B, 0xAF, 0x48, 0x77, 0x84, 0x67, 0xAA, 0x8C, 0x44, 0xFA, 0x4C, 0xCA }, asf_read_metadata_obj, 1 },
935cabdff1aSopenharmony_ci    { "Metadata Library",             { 0x44, 0x23, 0x1C, 0x94, 0x94, 0x98, 0x49, 0xD1, 0xA1, 0x41, 0x1D, 0x13, 0x4E, 0x45, 0x70, 0x54 }, asf_read_metadata_obj, 1 },
936cabdff1aSopenharmony_ci    { "Audio Spread",                 { 0xBF, 0xC3, 0xCD, 0x50, 0x61, 0x8F, 0x11, 0xCF, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }, asf_read_unknown, 1 },
937cabdff1aSopenharmony_ci    { "Index Parameters",             { 0xD6, 0xE2, 0x29, 0xDF, 0x35, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
938cabdff1aSopenharmony_ci    { "Content Encryption System Windows Media DRM Network Devices",
939cabdff1aSopenharmony_ci                                      { 0x7A, 0x07, 0x9B, 0xB6, 0xDA, 0XA4, 0x4e, 0x12, 0xA5, 0xCA, 0x91, 0xD3, 0x8D, 0xC1, 0x1A, 0x8D }, asf_read_unknown, 1 },
940cabdff1aSopenharmony_ci    { "Mutex Language",               { 0xD6, 0xE2, 0x2A, 0x00, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
941cabdff1aSopenharmony_ci    { "Mutex Bitrate",                { 0xD6, 0xE2, 0x2A, 0x01, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
942cabdff1aSopenharmony_ci    { "Mutex Unknown",                { 0xD6, 0xE2, 0x2A, 0x02, 0x25, 0xDA, 0x11, 0xD1, 0x90, 0x34, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xBE }, asf_read_unknown, 1 },
943cabdff1aSopenharmony_ci    { "Bandwidth Sharing Exclusive",  { 0xAF, 0x60, 0x60, 0xAA, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 },
944cabdff1aSopenharmony_ci    { "Bandwidth Sharing Partial",    { 0xAF, 0x60, 0x60, 0xAB, 0x51, 0x97, 0x11, 0xD2, 0xB6, 0xAF, 0x00, 0xC0, 0x4F, 0xD9, 0x08, 0xE9 }, asf_read_unknown, 1 },
945cabdff1aSopenharmony_ci    { "Payload Extension System Timecode", { 0x39, 0x95, 0x95, 0xEC, 0x86, 0x67, 0x4E, 0x2D, 0x8F, 0xDB, 0x98, 0x81, 0x4C, 0xE7, 0x6C, 0x1E }, asf_read_unknown, 1 },
946cabdff1aSopenharmony_ci    { "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 },
947cabdff1aSopenharmony_ci    { "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 },
948cabdff1aSopenharmony_ci    { "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 },
949cabdff1aSopenharmony_ci    { "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 },
950cabdff1aSopenharmony_ci    { "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 },
951cabdff1aSopenharmony_ci    { "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 },
952cabdff1aSopenharmony_ci};
953cabdff1aSopenharmony_ci
954cabdff1aSopenharmony_ci#define READ_LEN(flag, name, len)            \
955cabdff1aSopenharmony_ci    do {                                     \
956cabdff1aSopenharmony_ci        if ((flag) == name ## IS_BYTE)       \
957cabdff1aSopenharmony_ci            len = avio_r8(pb);               \
958cabdff1aSopenharmony_ci        else if ((flag) == name ## IS_WORD)  \
959cabdff1aSopenharmony_ci            len = avio_rl16(pb);             \
960cabdff1aSopenharmony_ci        else if ((flag) == name ## IS_DWORD) \
961cabdff1aSopenharmony_ci            len = avio_rl32(pb);             \
962cabdff1aSopenharmony_ci        else                                 \
963cabdff1aSopenharmony_ci            len = 0;                         \
964cabdff1aSopenharmony_ci    } while(0)
965cabdff1aSopenharmony_ci
966cabdff1aSopenharmony_cistatic int asf_read_subpayload(AVFormatContext *s, AVPacket *pkt, int is_header)
967cabdff1aSopenharmony_ci{
968cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
969cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
970cabdff1aSopenharmony_ci    uint8_t sub_len;
971cabdff1aSopenharmony_ci    int ret, i;
972cabdff1aSopenharmony_ci
973cabdff1aSopenharmony_ci    if (is_header) {
974cabdff1aSopenharmony_ci        asf->dts_delta = avio_r8(pb);
975cabdff1aSopenharmony_ci        if (asf->nb_mult_left) {
976cabdff1aSopenharmony_ci            asf->mult_sub_len = avio_rl16(pb); // total
977cabdff1aSopenharmony_ci        }
978cabdff1aSopenharmony_ci        asf->sub_header_offset = avio_tell(pb);
979cabdff1aSopenharmony_ci        asf->nb_sub = 0;
980cabdff1aSopenharmony_ci        asf->sub_left = 1;
981cabdff1aSopenharmony_ci    }
982cabdff1aSopenharmony_ci    sub_len = avio_r8(pb);
983cabdff1aSopenharmony_ci    if ((ret = av_get_packet(pb, pkt, sub_len)) < 0) // each subpayload is entire frame
984cabdff1aSopenharmony_ci        return ret;
985cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
986cabdff1aSopenharmony_ci        if (asf->stream_index == asf->asf_st[i]->stream_index) {
987cabdff1aSopenharmony_ci            pkt->stream_index  = asf->asf_st[i]->index;
988cabdff1aSopenharmony_ci            break;
989cabdff1aSopenharmony_ci        }
990cabdff1aSopenharmony_ci    }
991cabdff1aSopenharmony_ci    asf->return_subpayload = 1;
992cabdff1aSopenharmony_ci    if (!sub_len)
993cabdff1aSopenharmony_ci        asf->return_subpayload = 0;
994cabdff1aSopenharmony_ci
995cabdff1aSopenharmony_ci    if (sub_len)
996cabdff1aSopenharmony_ci        asf->nb_sub++;
997cabdff1aSopenharmony_ci    pkt->dts = asf->sub_dts + (asf->nb_sub - 1) * asf->dts_delta - asf->preroll;
998cabdff1aSopenharmony_ci    if (asf->nb_mult_left && (avio_tell(pb) >=
999cabdff1aSopenharmony_ci                              (asf->sub_header_offset + asf->mult_sub_len))) {
1000cabdff1aSopenharmony_ci        asf->sub_left = 0;
1001cabdff1aSopenharmony_ci        asf->nb_mult_left--;
1002cabdff1aSopenharmony_ci    }
1003cabdff1aSopenharmony_ci    if (avio_tell(pb) >= asf->packet_offset + asf->packet_size - asf->pad_len) {
1004cabdff1aSopenharmony_ci        asf->sub_left = 0;
1005cabdff1aSopenharmony_ci        if (!asf->nb_mult_left) {
1006cabdff1aSopenharmony_ci            avio_skip(pb, asf->pad_len);
1007cabdff1aSopenharmony_ci            if (avio_tell(pb) != asf->packet_offset + asf->packet_size) {
1008cabdff1aSopenharmony_ci                if (!asf->packet_size)
1009cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1010cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING,
1011cabdff1aSopenharmony_ci                       "Position %"PRId64" wrong, should be %"PRId64"\n",
1012cabdff1aSopenharmony_ci                       avio_tell(pb), asf->packet_offset + asf->packet_size);
1013cabdff1aSopenharmony_ci                avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
1014cabdff1aSopenharmony_ci            }
1015cabdff1aSopenharmony_ci        }
1016cabdff1aSopenharmony_ci    }
1017cabdff1aSopenharmony_ci
1018cabdff1aSopenharmony_ci    return 0;
1019cabdff1aSopenharmony_ci}
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_cistatic void reset_packet(ASFPacket *asf_pkt)
1022cabdff1aSopenharmony_ci{
1023cabdff1aSopenharmony_ci    asf_pkt->size_left = 0;
1024cabdff1aSopenharmony_ci    asf_pkt->data_size = 0;
1025cabdff1aSopenharmony_ci    asf_pkt->duration  = 0;
1026cabdff1aSopenharmony_ci    asf_pkt->flags     = 0;
1027cabdff1aSopenharmony_ci    asf_pkt->dts       = 0;
1028cabdff1aSopenharmony_ci    av_packet_unref(asf_pkt->avpkt);
1029cabdff1aSopenharmony_ci}
1030cabdff1aSopenharmony_ci
1031cabdff1aSopenharmony_cistatic int asf_read_replicated_data(AVFormatContext *s, ASFPacket *asf_pkt)
1032cabdff1aSopenharmony_ci{
1033cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1034cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1035cabdff1aSopenharmony_ci    int ret, data_size;
1036cabdff1aSopenharmony_ci
1037cabdff1aSopenharmony_ci    if (!asf_pkt->data_size) {
1038cabdff1aSopenharmony_ci        data_size = avio_rl32(pb); // read media object size
1039cabdff1aSopenharmony_ci        if (data_size <= 0)
1040cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1041cabdff1aSopenharmony_ci        if ((ret = av_new_packet(asf_pkt->avpkt, data_size)) < 0)
1042cabdff1aSopenharmony_ci            return ret;
1043cabdff1aSopenharmony_ci        asf_pkt->data_size = asf_pkt->size_left = data_size;
1044cabdff1aSopenharmony_ci    } else
1045cabdff1aSopenharmony_ci        avio_skip(pb, 4); // reading of media object size is already done
1046cabdff1aSopenharmony_ci    asf_pkt->dts = avio_rl32(pb); // read presentation time
1047cabdff1aSopenharmony_ci    if (asf->rep_data_len >= 8)
1048cabdff1aSopenharmony_ci        avio_skip(pb, asf->rep_data_len - 8); // skip replicated data
1049cabdff1aSopenharmony_ci
1050cabdff1aSopenharmony_ci    return 0;
1051cabdff1aSopenharmony_ci}
1052cabdff1aSopenharmony_ci
1053cabdff1aSopenharmony_cistatic int asf_read_multiple_payload(AVFormatContext *s, AVPacket *pkt,
1054cabdff1aSopenharmony_ci                                 ASFPacket *asf_pkt)
1055cabdff1aSopenharmony_ci{
1056cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1057cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1058cabdff1aSopenharmony_ci    uint16_t pay_len;
1059cabdff1aSopenharmony_ci    unsigned char *p;
1060cabdff1aSopenharmony_ci    int ret;
1061cabdff1aSopenharmony_ci    int skip = 0;
1062cabdff1aSopenharmony_ci
1063cabdff1aSopenharmony_ci    // if replicated length is 1, subpayloads are present
1064cabdff1aSopenharmony_ci    if (asf->rep_data_len == 1) {
1065cabdff1aSopenharmony_ci        asf->sub_left = 1;
1066cabdff1aSopenharmony_ci        asf->state = READ_MULTI_SUB;
1067cabdff1aSopenharmony_ci        pkt->flags = asf_pkt->flags;
1068cabdff1aSopenharmony_ci        if ((ret = asf_read_subpayload(s, pkt, 1)) < 0)
1069cabdff1aSopenharmony_ci            return ret;
1070cabdff1aSopenharmony_ci    } else {
1071cabdff1aSopenharmony_ci        if (asf->rep_data_len)
1072cabdff1aSopenharmony_ci            if ((ret = asf_read_replicated_data(s, asf_pkt)) < 0)
1073cabdff1aSopenharmony_ci                return ret;
1074cabdff1aSopenharmony_ci        pay_len = avio_rl16(pb); // payload length should be WORD
1075cabdff1aSopenharmony_ci        if (pay_len > asf->packet_size) {
1076cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR,
1077cabdff1aSopenharmony_ci                   "Error: invalid data packet size, pay_len %"PRIu16", "
1078cabdff1aSopenharmony_ci                   "asf->packet_size %"PRIu32", offset %"PRId64".\n",
1079cabdff1aSopenharmony_ci                   pay_len, asf->packet_size, avio_tell(pb));
1080cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1081cabdff1aSopenharmony_ci        }
1082cabdff1aSopenharmony_ci        p = asf_pkt->avpkt->data + asf_pkt->data_size - asf_pkt->size_left;
1083cabdff1aSopenharmony_ci        if (pay_len > asf_pkt->size_left) {
1084cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR,
1085cabdff1aSopenharmony_ci                   "Error: invalid buffer size, pay_len %d, data size left %d.\n",
1086cabdff1aSopenharmony_ci            pay_len, asf_pkt->size_left);
1087cabdff1aSopenharmony_ci            skip = pay_len - asf_pkt->size_left;
1088cabdff1aSopenharmony_ci            pay_len = asf_pkt->size_left;
1089cabdff1aSopenharmony_ci        }
1090cabdff1aSopenharmony_ci        if (asf_pkt->size_left <= 0)
1091cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1092cabdff1aSopenharmony_ci        if ((ret = avio_read(pb, p, pay_len)) < 0)
1093cabdff1aSopenharmony_ci            return ret;
1094cabdff1aSopenharmony_ci        if (s->key && s->keylen == 20)
1095cabdff1aSopenharmony_ci            ff_asfcrypt_dec(s->key, p, ret);
1096cabdff1aSopenharmony_ci        avio_skip(pb, skip);
1097cabdff1aSopenharmony_ci        asf_pkt->size_left -= pay_len;
1098cabdff1aSopenharmony_ci        asf->nb_mult_left--;
1099cabdff1aSopenharmony_ci    }
1100cabdff1aSopenharmony_ci
1101cabdff1aSopenharmony_ci    return 0;
1102cabdff1aSopenharmony_ci}
1103cabdff1aSopenharmony_ci
1104cabdff1aSopenharmony_cistatic int asf_read_single_payload(AVFormatContext *s, ASFPacket *asf_pkt)
1105cabdff1aSopenharmony_ci{
1106cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1107cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1108cabdff1aSopenharmony_ci    int64_t  offset;
1109cabdff1aSopenharmony_ci    uint64_t size;
1110cabdff1aSopenharmony_ci    unsigned char *p;
1111cabdff1aSopenharmony_ci    int ret, data_size;
1112cabdff1aSopenharmony_ci
1113cabdff1aSopenharmony_ci    if (!asf_pkt->data_size) {
1114cabdff1aSopenharmony_ci        data_size = avio_rl32(pb); // read media object size
1115cabdff1aSopenharmony_ci        if (data_size <= 0)
1116cabdff1aSopenharmony_ci            return AVERROR_EOF;
1117cabdff1aSopenharmony_ci        if ((ret = av_new_packet(asf_pkt->avpkt, data_size)) < 0)
1118cabdff1aSopenharmony_ci            return ret;
1119cabdff1aSopenharmony_ci        asf_pkt->data_size = asf_pkt->size_left = data_size;
1120cabdff1aSopenharmony_ci    } else
1121cabdff1aSopenharmony_ci        avio_skip(pb, 4); // skip media object size
1122cabdff1aSopenharmony_ci    asf_pkt->dts = avio_rl32(pb); // read presentation time
1123cabdff1aSopenharmony_ci    if (asf->rep_data_len >= 8)
1124cabdff1aSopenharmony_ci        avio_skip(pb, asf->rep_data_len - 8); // skip replicated data
1125cabdff1aSopenharmony_ci    offset = avio_tell(pb);
1126cabdff1aSopenharmony_ci
1127cabdff1aSopenharmony_ci    // size of the payload - size of the packet without header and padding
1128cabdff1aSopenharmony_ci    if (asf->packet_size_internal)
1129cabdff1aSopenharmony_ci        size = asf->packet_size_internal - offset + asf->packet_offset - asf->pad_len;
1130cabdff1aSopenharmony_ci    else
1131cabdff1aSopenharmony_ci        size = asf->packet_size - offset + asf->packet_offset - asf->pad_len;
1132cabdff1aSopenharmony_ci    if (size > asf->packet_size) {
1133cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR,
1134cabdff1aSopenharmony_ci               "Error: invalid data packet size, offset %"PRId64".\n",
1135cabdff1aSopenharmony_ci               avio_tell(pb));
1136cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1137cabdff1aSopenharmony_ci    }
1138cabdff1aSopenharmony_ci    p = asf_pkt->avpkt->data + asf_pkt->data_size - asf_pkt->size_left;
1139cabdff1aSopenharmony_ci    if (size > asf_pkt->size_left || asf_pkt->size_left <= 0)
1140cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1141cabdff1aSopenharmony_ci    if (asf_pkt->size_left > size)
1142cabdff1aSopenharmony_ci        asf_pkt->size_left -= size;
1143cabdff1aSopenharmony_ci    else
1144cabdff1aSopenharmony_ci        asf_pkt->size_left = 0;
1145cabdff1aSopenharmony_ci    if ((ret = avio_read(pb, p, size)) < 0)
1146cabdff1aSopenharmony_ci        return ret;
1147cabdff1aSopenharmony_ci    if (s->key && s->keylen == 20)
1148cabdff1aSopenharmony_ci            ff_asfcrypt_dec(s->key, p, ret);
1149cabdff1aSopenharmony_ci    if (asf->packet_size_internal)
1150cabdff1aSopenharmony_ci        avio_skip(pb, asf->packet_size - asf->packet_size_internal);
1151cabdff1aSopenharmony_ci    avio_skip(pb, asf->pad_len); // skip padding
1152cabdff1aSopenharmony_ci
1153cabdff1aSopenharmony_ci    return 0;
1154cabdff1aSopenharmony_ci}
1155cabdff1aSopenharmony_ci
1156cabdff1aSopenharmony_cistatic int asf_read_payload(AVFormatContext *s, AVPacket *pkt)
1157cabdff1aSopenharmony_ci{
1158cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1159cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1160cabdff1aSopenharmony_ci    int ret, i;
1161cabdff1aSopenharmony_ci    ASFPacket *asf_pkt = NULL;
1162cabdff1aSopenharmony_ci
1163cabdff1aSopenharmony_ci    if (!asf->sub_left) {
1164cabdff1aSopenharmony_ci        uint32_t off_len, media_len;
1165cabdff1aSopenharmony_ci        uint8_t stream_num;
1166cabdff1aSopenharmony_ci
1167cabdff1aSopenharmony_ci        stream_num = avio_r8(pb);
1168cabdff1aSopenharmony_ci        asf->stream_index = stream_num & ASF_STREAM_NUM;
1169cabdff1aSopenharmony_ci        for (i = 0; i < asf->nb_streams; i++) {
1170cabdff1aSopenharmony_ci            if (asf->stream_index == asf->asf_st[i]->stream_index) {
1171cabdff1aSopenharmony_ci                asf_pkt               = &asf->asf_st[i]->pkt;
1172cabdff1aSopenharmony_ci                asf_pkt->stream_index = asf->asf_st[i]->index;
1173cabdff1aSopenharmony_ci                break;
1174cabdff1aSopenharmony_ci            }
1175cabdff1aSopenharmony_ci        }
1176cabdff1aSopenharmony_ci        if (!asf_pkt) {
1177cabdff1aSopenharmony_ci            if (asf->packet_offset + asf->packet_size <= asf->data_offset + asf->data_size) {
1178cabdff1aSopenharmony_ci                if (!asf->packet_size) {
1179cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_ERROR, "Invalid packet size 0.\n");
1180cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1181cabdff1aSopenharmony_ci                }
1182cabdff1aSopenharmony_ci                avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
1183cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING, "Skipping the stream with the invalid stream index %d.\n",
1184cabdff1aSopenharmony_ci                       asf->stream_index);
1185cabdff1aSopenharmony_ci                return AVERROR(EAGAIN);
1186cabdff1aSopenharmony_ci            } else
1187cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
1188cabdff1aSopenharmony_ci        }
1189cabdff1aSopenharmony_ci
1190cabdff1aSopenharmony_ci        if (stream_num >> 7)
1191cabdff1aSopenharmony_ci            asf_pkt->flags |= AV_PKT_FLAG_KEY;
1192cabdff1aSopenharmony_ci        READ_LEN(asf->prop_flags & ASF_PL_MASK_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_SIZE,
1193cabdff1aSopenharmony_ci                 ASF_PL_FLAG_MEDIA_OBJECT_NUMBER_LENGTH_FIELD_, media_len);
1194cabdff1aSopenharmony_ci        READ_LEN(asf->prop_flags & ASF_PL_MASK_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_SIZE,
1195cabdff1aSopenharmony_ci                 ASF_PL_FLAG_OFFSET_INTO_MEDIA_OBJECT_LENGTH_FIELD_, off_len);
1196cabdff1aSopenharmony_ci        READ_LEN(asf->prop_flags & ASF_PL_MASK_REPLICATED_DATA_LENGTH_FIELD_SIZE,
1197cabdff1aSopenharmony_ci                 ASF_PL_FLAG_REPLICATED_DATA_LENGTH_FIELD_, asf->rep_data_len);
1198cabdff1aSopenharmony_ci        if (asf_pkt->size_left && (asf_pkt->frame_num != media_len)) {
1199cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "Unfinished frame will be ignored\n");
1200cabdff1aSopenharmony_ci            reset_packet(asf_pkt);
1201cabdff1aSopenharmony_ci        }
1202cabdff1aSopenharmony_ci        asf_pkt->frame_num = media_len;
1203cabdff1aSopenharmony_ci        asf->sub_dts = off_len;
1204cabdff1aSopenharmony_ci        if (asf->nb_mult_left) {
1205cabdff1aSopenharmony_ci            if ((ret = asf_read_multiple_payload(s, pkt, asf_pkt)) < 0)
1206cabdff1aSopenharmony_ci                return ret;
1207cabdff1aSopenharmony_ci        } else if (asf->rep_data_len == 1) {
1208cabdff1aSopenharmony_ci            asf->sub_left = 1;
1209cabdff1aSopenharmony_ci            asf->state    = READ_SINGLE;
1210cabdff1aSopenharmony_ci            pkt->flags    = asf_pkt->flags;
1211cabdff1aSopenharmony_ci            if ((ret = asf_read_subpayload(s, pkt, 1)) < 0)
1212cabdff1aSopenharmony_ci                return ret;
1213cabdff1aSopenharmony_ci        } else {
1214cabdff1aSopenharmony_ci            if ((ret = asf_read_single_payload(s, asf_pkt)) < 0)
1215cabdff1aSopenharmony_ci                return ret;
1216cabdff1aSopenharmony_ci        }
1217cabdff1aSopenharmony_ci    } else {
1218cabdff1aSopenharmony_ci        for (i = 0; i <= asf->nb_streams; i++) {
1219cabdff1aSopenharmony_ci            if (asf->stream_index == asf->asf_st[i]->stream_index) {
1220cabdff1aSopenharmony_ci                asf_pkt = &asf->asf_st[i]->pkt;
1221cabdff1aSopenharmony_ci                break;
1222cabdff1aSopenharmony_ci            }
1223cabdff1aSopenharmony_ci        }
1224cabdff1aSopenharmony_ci        if (!asf_pkt)
1225cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1226cabdff1aSopenharmony_ci        pkt->flags         = asf_pkt->flags;
1227cabdff1aSopenharmony_ci        pkt->dts           = asf_pkt->dts;
1228cabdff1aSopenharmony_ci        pkt->stream_index  = asf->asf_st[i]->index;
1229cabdff1aSopenharmony_ci        if ((ret = asf_read_subpayload(s, pkt, 0)) < 0) // read subpayload without its header
1230cabdff1aSopenharmony_ci            return ret;
1231cabdff1aSopenharmony_ci    }
1232cabdff1aSopenharmony_ci
1233cabdff1aSopenharmony_ci    return 0;
1234cabdff1aSopenharmony_ci}
1235cabdff1aSopenharmony_ci
1236cabdff1aSopenharmony_cistatic int asf_read_packet_header(AVFormatContext *s)
1237cabdff1aSopenharmony_ci{
1238cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1239cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1240cabdff1aSopenharmony_ci    uint64_t size;
1241cabdff1aSopenharmony_ci    uint32_t av_unused seq;
1242cabdff1aSopenharmony_ci    unsigned char error_flags, len_flags, pay_flags;
1243cabdff1aSopenharmony_ci
1244cabdff1aSopenharmony_ci    asf->packet_offset = avio_tell(pb);
1245cabdff1aSopenharmony_ci    if (asf->packet_offset > INT64_MAX/2)
1246cabdff1aSopenharmony_ci        asf->packet_offset = 0;
1247cabdff1aSopenharmony_ci    error_flags = avio_r8(pb); // read Error Correction Flags
1248cabdff1aSopenharmony_ci    if (error_flags & ASF_PACKET_FLAG_ERROR_CORRECTION_PRESENT) {
1249cabdff1aSopenharmony_ci        if (!(error_flags & ASF_ERROR_CORRECTION_LENGTH_TYPE)) {
1250cabdff1aSopenharmony_ci            size = error_flags & ASF_PACKET_ERROR_CORRECTION_DATA_SIZE;
1251cabdff1aSopenharmony_ci            avio_skip(pb, size);
1252cabdff1aSopenharmony_ci        }
1253cabdff1aSopenharmony_ci        len_flags       = avio_r8(pb);
1254cabdff1aSopenharmony_ci    } else
1255cabdff1aSopenharmony_ci        len_flags = error_flags;
1256cabdff1aSopenharmony_ci    asf->prop_flags = avio_r8(pb);
1257cabdff1aSopenharmony_ci    READ_LEN(len_flags & ASF_PPI_MASK_PACKET_LENGTH_FIELD_SIZE,
1258cabdff1aSopenharmony_ci             ASF_PPI_FLAG_PACKET_LENGTH_FIELD_, asf->packet_size_internal);
1259cabdff1aSopenharmony_ci    READ_LEN(len_flags & ASF_PPI_MASK_SEQUENCE_FIELD_SIZE,
1260cabdff1aSopenharmony_ci             ASF_PPI_FLAG_SEQUENCE_FIELD_, seq);
1261cabdff1aSopenharmony_ci    READ_LEN(len_flags & ASF_PPI_MASK_PADDING_LENGTH_FIELD_SIZE,
1262cabdff1aSopenharmony_ci             ASF_PPI_FLAG_PADDING_LENGTH_FIELD_, asf->pad_len );
1263cabdff1aSopenharmony_ci    asf->send_time = avio_rl32(pb); // send time
1264cabdff1aSopenharmony_ci    avio_skip(pb, 2); // skip duration
1265cabdff1aSopenharmony_ci    if (len_flags & ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT) { // Multiple Payloads present
1266cabdff1aSopenharmony_ci        pay_flags = avio_r8(pb);
1267cabdff1aSopenharmony_ci        asf->nb_mult_left = (pay_flags & ASF_NUM_OF_PAYLOADS);
1268cabdff1aSopenharmony_ci    }
1269cabdff1aSopenharmony_ci
1270cabdff1aSopenharmony_ci    return 0;
1271cabdff1aSopenharmony_ci}
1272cabdff1aSopenharmony_ci
1273cabdff1aSopenharmony_cistatic int asf_deinterleave(AVFormatContext *s, ASFPacket *asf_pkt, int st_num)
1274cabdff1aSopenharmony_ci{
1275cabdff1aSopenharmony_ci    ASFContext *asf    = s->priv_data;
1276cabdff1aSopenharmony_ci    ASFStream *asf_st  = asf->asf_st[st_num];
1277cabdff1aSopenharmony_ci    unsigned char *p   = asf_pkt->avpkt->data;
1278cabdff1aSopenharmony_ci    uint16_t pkt_len   = asf->asf_st[st_num]->virtual_pkt_len;
1279cabdff1aSopenharmony_ci    uint16_t chunk_len = asf->asf_st[st_num]->virtual_chunk_len;
1280cabdff1aSopenharmony_ci    int nchunks        = pkt_len / chunk_len;
1281cabdff1aSopenharmony_ci    uint8_t *data;
1282cabdff1aSopenharmony_ci    int pos = 0, j, l, ret;
1283cabdff1aSopenharmony_ci
1284cabdff1aSopenharmony_ci
1285cabdff1aSopenharmony_ci    data = av_malloc(asf_pkt->data_size + AV_INPUT_BUFFER_PADDING_SIZE);
1286cabdff1aSopenharmony_ci    if (!data)
1287cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1288cabdff1aSopenharmony_ci    memset(data + asf_pkt->data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1289cabdff1aSopenharmony_ci
1290cabdff1aSopenharmony_ci    while (asf_pkt->data_size >= asf_st->span * pkt_len + pos) {
1291cabdff1aSopenharmony_ci        if (pos >= asf_pkt->data_size) {
1292cabdff1aSopenharmony_ci            break;
1293cabdff1aSopenharmony_ci        }
1294cabdff1aSopenharmony_ci        for (l = 0; l < pkt_len; l++) {
1295cabdff1aSopenharmony_ci            if (pos >= asf_pkt->data_size) {
1296cabdff1aSopenharmony_ci                break;
1297cabdff1aSopenharmony_ci            }
1298cabdff1aSopenharmony_ci            for (j = 0; j < asf_st->span; j++) {
1299cabdff1aSopenharmony_ci                if ((pos + chunk_len) >= asf_pkt->data_size)
1300cabdff1aSopenharmony_ci                    break;
1301cabdff1aSopenharmony_ci                memcpy(data + pos,
1302cabdff1aSopenharmony_ci                       p + (j * nchunks + l) * chunk_len,
1303cabdff1aSopenharmony_ci                       chunk_len);
1304cabdff1aSopenharmony_ci                pos += chunk_len;
1305cabdff1aSopenharmony_ci            }
1306cabdff1aSopenharmony_ci        }
1307cabdff1aSopenharmony_ci        p += asf_st->span * pkt_len;
1308cabdff1aSopenharmony_ci        if (p > asf_pkt->avpkt->data + asf_pkt->data_size)
1309cabdff1aSopenharmony_ci            break;
1310cabdff1aSopenharmony_ci    }
1311cabdff1aSopenharmony_ci    av_packet_unref(asf_pkt->avpkt);
1312cabdff1aSopenharmony_ci    ret = av_packet_from_data(asf_pkt->avpkt, data, asf_pkt->data_size);
1313cabdff1aSopenharmony_ci    if (ret < 0)
1314cabdff1aSopenharmony_ci        av_free(data);
1315cabdff1aSopenharmony_ci
1316cabdff1aSopenharmony_ci    return ret;
1317cabdff1aSopenharmony_ci}
1318cabdff1aSopenharmony_ci
1319cabdff1aSopenharmony_cistatic int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
1320cabdff1aSopenharmony_ci{
1321cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1322cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1323cabdff1aSopenharmony_ci    int ret, i;
1324cabdff1aSopenharmony_ci
1325cabdff1aSopenharmony_ci    if ((avio_tell(pb) >= asf->data_offset + asf->data_size) &&
1326cabdff1aSopenharmony_ci        !(asf->b_flags & ASF_FLAG_BROADCAST))
1327cabdff1aSopenharmony_ci        return AVERROR_EOF;
1328cabdff1aSopenharmony_ci    while (!pb->eof_reached) {
1329cabdff1aSopenharmony_ci        if (asf->state == PARSE_PACKET_HEADER) {
1330cabdff1aSopenharmony_ci            asf_read_packet_header(s);
1331cabdff1aSopenharmony_ci            if (pb->eof_reached)
1332cabdff1aSopenharmony_ci                break;
1333cabdff1aSopenharmony_ci            if (!asf->nb_mult_left)
1334cabdff1aSopenharmony_ci                asf->state = READ_SINGLE;
1335cabdff1aSopenharmony_ci            else
1336cabdff1aSopenharmony_ci                asf->state = READ_MULTI;
1337cabdff1aSopenharmony_ci        }
1338cabdff1aSopenharmony_ci        ret = asf_read_payload(s, pkt);
1339cabdff1aSopenharmony_ci        if (ret == AVERROR(EAGAIN)) {
1340cabdff1aSopenharmony_ci            asf->state = PARSE_PACKET_HEADER;
1341cabdff1aSopenharmony_ci            continue;
1342cabdff1aSopenharmony_ci        }
1343cabdff1aSopenharmony_ci        else if (ret < 0)
1344cabdff1aSopenharmony_ci            return ret;
1345cabdff1aSopenharmony_ci
1346cabdff1aSopenharmony_ci        switch (asf->state) {
1347cabdff1aSopenharmony_ci        case READ_SINGLE:
1348cabdff1aSopenharmony_ci            if (!asf->sub_left)
1349cabdff1aSopenharmony_ci                asf->state = PARSE_PACKET_HEADER;
1350cabdff1aSopenharmony_ci            break;
1351cabdff1aSopenharmony_ci        case READ_MULTI_SUB:
1352cabdff1aSopenharmony_ci            if (!asf->sub_left && !asf->nb_mult_left) {
1353cabdff1aSopenharmony_ci                asf->state = PARSE_PACKET_HEADER;
1354cabdff1aSopenharmony_ci                if (!asf->return_subpayload &&
1355cabdff1aSopenharmony_ci                    (avio_tell(pb) <= asf->packet_offset +
1356cabdff1aSopenharmony_ci                     asf->packet_size - asf->pad_len))
1357cabdff1aSopenharmony_ci                    avio_skip(pb, asf->pad_len); // skip padding
1358cabdff1aSopenharmony_ci                if (asf->packet_offset + asf->packet_size > avio_tell(pb))
1359cabdff1aSopenharmony_ci                    avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
1360cabdff1aSopenharmony_ci            } else if (!asf->sub_left)
1361cabdff1aSopenharmony_ci                asf->state = READ_MULTI;
1362cabdff1aSopenharmony_ci            break;
1363cabdff1aSopenharmony_ci        case READ_MULTI:
1364cabdff1aSopenharmony_ci            if (!asf->nb_mult_left) {
1365cabdff1aSopenharmony_ci                asf->state = PARSE_PACKET_HEADER;
1366cabdff1aSopenharmony_ci                if (!asf->return_subpayload &&
1367cabdff1aSopenharmony_ci                    (avio_tell(pb) <= asf->packet_offset +
1368cabdff1aSopenharmony_ci                     asf->packet_size - asf->pad_len))
1369cabdff1aSopenharmony_ci                    avio_skip(pb, asf->pad_len); // skip padding
1370cabdff1aSopenharmony_ci                if (asf->packet_offset + asf->packet_size > avio_tell(pb))
1371cabdff1aSopenharmony_ci                    avio_seek(pb, asf->packet_offset + asf->packet_size, SEEK_SET);
1372cabdff1aSopenharmony_ci            }
1373cabdff1aSopenharmony_ci            break;
1374cabdff1aSopenharmony_ci        }
1375cabdff1aSopenharmony_ci        if (asf->return_subpayload) {
1376cabdff1aSopenharmony_ci            asf->return_subpayload = 0;
1377cabdff1aSopenharmony_ci            return 0;
1378cabdff1aSopenharmony_ci        }
1379cabdff1aSopenharmony_ci        for (i = 0; i < asf->nb_streams; i++) {
1380cabdff1aSopenharmony_ci            ASFPacket *asf_pkt = &asf->asf_st[i]->pkt;
1381cabdff1aSopenharmony_ci            if (asf_pkt && !asf_pkt->size_left && asf_pkt->data_size) {
1382cabdff1aSopenharmony_ci                if (asf->asf_st[i]->span > 1 &&
1383cabdff1aSopenharmony_ci                    asf->asf_st[i]->type == AVMEDIA_TYPE_AUDIO)
1384cabdff1aSopenharmony_ci                    if ((ret = asf_deinterleave(s, asf_pkt, i)) < 0)
1385cabdff1aSopenharmony_ci                        return ret;
1386cabdff1aSopenharmony_ci                av_packet_move_ref(pkt, asf_pkt->avpkt);
1387cabdff1aSopenharmony_ci                pkt->stream_index  = asf->asf_st[i]->index;
1388cabdff1aSopenharmony_ci                pkt->flags         = asf_pkt->flags;
1389cabdff1aSopenharmony_ci                pkt->dts           = asf_pkt->dts - asf->preroll;
1390cabdff1aSopenharmony_ci                asf_pkt->data_size = 0;
1391cabdff1aSopenharmony_ci                asf_pkt->frame_num = 0;
1392cabdff1aSopenharmony_ci                return 0;
1393cabdff1aSopenharmony_ci            }
1394cabdff1aSopenharmony_ci        }
1395cabdff1aSopenharmony_ci    }
1396cabdff1aSopenharmony_ci
1397cabdff1aSopenharmony_ci    if (pb->eof_reached)
1398cabdff1aSopenharmony_ci        return AVERROR_EOF;
1399cabdff1aSopenharmony_ci
1400cabdff1aSopenharmony_ci    return 0;
1401cabdff1aSopenharmony_ci}
1402cabdff1aSopenharmony_ci
1403cabdff1aSopenharmony_cistatic int asf_read_close(AVFormatContext *s)
1404cabdff1aSopenharmony_ci{
1405cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1406cabdff1aSopenharmony_ci    int i;
1407cabdff1aSopenharmony_ci
1408cabdff1aSopenharmony_ci    for (i = 0; i < ASF_MAX_STREAMS; i++) {
1409cabdff1aSopenharmony_ci        av_dict_free(&asf->asf_sd[i].asf_met);
1410cabdff1aSopenharmony_ci        if (i < asf->nb_streams) {
1411cabdff1aSopenharmony_ci            av_packet_free(&asf->asf_st[i]->pkt.avpkt);
1412cabdff1aSopenharmony_ci            av_freep(&asf->asf_st[i]);
1413cabdff1aSopenharmony_ci        }
1414cabdff1aSopenharmony_ci    }
1415cabdff1aSopenharmony_ci
1416cabdff1aSopenharmony_ci    asf->nb_streams = 0;
1417cabdff1aSopenharmony_ci    return 0;
1418cabdff1aSopenharmony_ci}
1419cabdff1aSopenharmony_ci
1420cabdff1aSopenharmony_cistatic void reset_packet_state(AVFormatContext *s)
1421cabdff1aSopenharmony_ci{
1422cabdff1aSopenharmony_ci    ASFContext *asf        = s->priv_data;
1423cabdff1aSopenharmony_ci    int i;
1424cabdff1aSopenharmony_ci
1425cabdff1aSopenharmony_ci    asf->state             = PARSE_PACKET_HEADER;
1426cabdff1aSopenharmony_ci    asf->offset            = 0;
1427cabdff1aSopenharmony_ci    asf->return_subpayload = 0;
1428cabdff1aSopenharmony_ci    asf->sub_left          = 0;
1429cabdff1aSopenharmony_ci    asf->sub_header_offset = 0;
1430cabdff1aSopenharmony_ci    asf->packet_offset     = asf->first_packet_offset;
1431cabdff1aSopenharmony_ci    asf->pad_len           = 0;
1432cabdff1aSopenharmony_ci    asf->rep_data_len      = 0;
1433cabdff1aSopenharmony_ci    asf->dts_delta         = 0;
1434cabdff1aSopenharmony_ci    asf->mult_sub_len      = 0;
1435cabdff1aSopenharmony_ci    asf->nb_mult_left      = 0;
1436cabdff1aSopenharmony_ci    asf->nb_sub            = 0;
1437cabdff1aSopenharmony_ci    asf->prop_flags        = 0;
1438cabdff1aSopenharmony_ci    asf->sub_dts           = 0;
1439cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
1440cabdff1aSopenharmony_ci        ASFPacket *pkt = &asf->asf_st[i]->pkt;
1441cabdff1aSopenharmony_ci        reset_packet(pkt);
1442cabdff1aSopenharmony_ci    }
1443cabdff1aSopenharmony_ci}
1444cabdff1aSopenharmony_ci
1445cabdff1aSopenharmony_ci/*
1446cabdff1aSopenharmony_ci * Find a timestamp for the requested position within the payload
1447cabdff1aSopenharmony_ci * where the pos (position) is the offset inside the Data Object.
1448cabdff1aSopenharmony_ci * When position is not on the packet boundary, asf_read_timestamp tries
1449cabdff1aSopenharmony_ci * to find the closest packet offset after this position. If this packet
1450cabdff1aSopenharmony_ci * is a key frame, this packet timestamp is read and an index entry is created
1451cabdff1aSopenharmony_ci * for the packet. If this packet belongs to the requested stream,
1452cabdff1aSopenharmony_ci * asf_read_timestamp upgrades pos to the packet beginning offset and
1453cabdff1aSopenharmony_ci * returns this packet's dts. So returned dts is the dts of the first key frame with
1454cabdff1aSopenharmony_ci * matching stream number after given position.
1455cabdff1aSopenharmony_ci */
1456cabdff1aSopenharmony_cistatic int64_t asf_read_timestamp(AVFormatContext *s, int stream_index,
1457cabdff1aSopenharmony_ci                                  int64_t *pos, int64_t pos_limit)
1458cabdff1aSopenharmony_ci{
1459cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1460cabdff1aSopenharmony_ci    int64_t pkt_pos = *pos, pkt_offset, dts = AV_NOPTS_VALUE, data_end;
1461cabdff1aSopenharmony_ci    AVPacket *pkt = av_packet_alloc();
1462cabdff1aSopenharmony_ci    int n;
1463cabdff1aSopenharmony_ci
1464cabdff1aSopenharmony_ci    if (!pkt)
1465cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1466cabdff1aSopenharmony_ci
1467cabdff1aSopenharmony_ci    data_end = asf->data_offset + asf->data_size;
1468cabdff1aSopenharmony_ci
1469cabdff1aSopenharmony_ci    n = (pkt_pos - asf->first_packet_offset + asf->packet_size - 1) /
1470cabdff1aSopenharmony_ci        asf->packet_size;
1471cabdff1aSopenharmony_ci    n = av_clip(n, 0, ((data_end - asf->first_packet_offset) / asf->packet_size - 1));
1472cabdff1aSopenharmony_ci    pkt_pos = asf->first_packet_offset +  n * asf->packet_size;
1473cabdff1aSopenharmony_ci
1474cabdff1aSopenharmony_ci    avio_seek(s->pb, pkt_pos, SEEK_SET);
1475cabdff1aSopenharmony_ci    pkt_offset = pkt_pos;
1476cabdff1aSopenharmony_ci
1477cabdff1aSopenharmony_ci    reset_packet_state(s);
1478cabdff1aSopenharmony_ci    while (avio_tell(s->pb) < data_end) {
1479cabdff1aSopenharmony_ci
1480cabdff1aSopenharmony_ci        int i, ret, st_found;
1481cabdff1aSopenharmony_ci
1482cabdff1aSopenharmony_ci        pkt_offset = avio_tell(s->pb);
1483cabdff1aSopenharmony_ci        if ((ret = asf_read_packet(s, pkt)) < 0) {
1484cabdff1aSopenharmony_ci            av_packet_free(&pkt);
1485cabdff1aSopenharmony_ci            dts = AV_NOPTS_VALUE;
1486cabdff1aSopenharmony_ci            return ret;
1487cabdff1aSopenharmony_ci        }
1488cabdff1aSopenharmony_ci        // ASFPacket may contain fragments of packets belonging to different streams,
1489cabdff1aSopenharmony_ci        // pkt_offset is the offset of the first fragment within it.
1490cabdff1aSopenharmony_ci        if ((pkt_offset >= (pkt_pos + asf->packet_size)))
1491cabdff1aSopenharmony_ci            pkt_pos += asf->packet_size;
1492cabdff1aSopenharmony_ci        for (i = 0; i < asf->nb_streams; i++) {
1493cabdff1aSopenharmony_ci            ASFStream *st = asf->asf_st[i];
1494cabdff1aSopenharmony_ci
1495cabdff1aSopenharmony_ci            st_found = 0;
1496cabdff1aSopenharmony_ci            if (pkt->flags & AV_PKT_FLAG_KEY) {
1497cabdff1aSopenharmony_ci                dts = pkt->dts;
1498cabdff1aSopenharmony_ci                if (dts) {
1499cabdff1aSopenharmony_ci                    av_add_index_entry(s->streams[pkt->stream_index], pkt_pos,
1500cabdff1aSopenharmony_ci                                       dts, pkt->size, 0, AVINDEX_KEYFRAME);
1501cabdff1aSopenharmony_ci                    if (stream_index == st->index) {
1502cabdff1aSopenharmony_ci                        st_found = 1;
1503cabdff1aSopenharmony_ci                        break;
1504cabdff1aSopenharmony_ci                    }
1505cabdff1aSopenharmony_ci                }
1506cabdff1aSopenharmony_ci            }
1507cabdff1aSopenharmony_ci        }
1508cabdff1aSopenharmony_ci        if (st_found)
1509cabdff1aSopenharmony_ci            break;
1510cabdff1aSopenharmony_ci        av_packet_unref(pkt);
1511cabdff1aSopenharmony_ci    }
1512cabdff1aSopenharmony_ci    *pos = pkt_pos;
1513cabdff1aSopenharmony_ci
1514cabdff1aSopenharmony_ci    av_packet_free(&pkt);
1515cabdff1aSopenharmony_ci    return dts;
1516cabdff1aSopenharmony_ci}
1517cabdff1aSopenharmony_ci
1518cabdff1aSopenharmony_cistatic int asf_read_seek(AVFormatContext *s, int stream_index,
1519cabdff1aSopenharmony_ci                         int64_t timestamp, int flags)
1520cabdff1aSopenharmony_ci{
1521cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1522cabdff1aSopenharmony_ci    AVStream *const st = s->streams[stream_index];
1523cabdff1aSopenharmony_ci    FFStream *const sti = ffstream(st);
1524cabdff1aSopenharmony_ci    int idx, ret;
1525cabdff1aSopenharmony_ci
1526cabdff1aSopenharmony_ci    if (sti->nb_index_entries && asf->is_simple_index) {
1527cabdff1aSopenharmony_ci        idx = av_index_search_timestamp(st, timestamp, flags);
1528cabdff1aSopenharmony_ci        if (idx < 0 || idx >= sti->nb_index_entries)
1529cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1530cabdff1aSopenharmony_ci        avio_seek(s->pb, sti->index_entries[idx].pos, SEEK_SET);
1531cabdff1aSopenharmony_ci    } else {
1532cabdff1aSopenharmony_ci        if ((ret = ff_seek_frame_binary(s, stream_index, timestamp, flags)) < 0)
1533cabdff1aSopenharmony_ci            return ret;
1534cabdff1aSopenharmony_ci    }
1535cabdff1aSopenharmony_ci
1536cabdff1aSopenharmony_ci    reset_packet_state(s);
1537cabdff1aSopenharmony_ci
1538cabdff1aSopenharmony_ci    return 0;
1539cabdff1aSopenharmony_ci}
1540cabdff1aSopenharmony_ci
1541cabdff1aSopenharmony_cistatic const GUIDParseTable *find_guid(ff_asf_guid guid)
1542cabdff1aSopenharmony_ci{
1543cabdff1aSopenharmony_ci    int j, ret;
1544cabdff1aSopenharmony_ci    const GUIDParseTable *g;
1545cabdff1aSopenharmony_ci
1546cabdff1aSopenharmony_ci    swap_guid(guid);
1547cabdff1aSopenharmony_ci    g = gdef;
1548cabdff1aSopenharmony_ci    for (j = 0; j < FF_ARRAY_ELEMS(gdef); j++) {
1549cabdff1aSopenharmony_ci        if (!(ret = memcmp(guid, g->guid, sizeof(g->guid))))
1550cabdff1aSopenharmony_ci            return g;
1551cabdff1aSopenharmony_ci        g++;
1552cabdff1aSopenharmony_ci    }
1553cabdff1aSopenharmony_ci
1554cabdff1aSopenharmony_ci    return NULL;
1555cabdff1aSopenharmony_ci}
1556cabdff1aSopenharmony_ci
1557cabdff1aSopenharmony_cistatic int detect_unknown_subobject(AVFormatContext *s, int64_t offset, int64_t size)
1558cabdff1aSopenharmony_ci{
1559cabdff1aSopenharmony_ci    ASFContext *asf = s->priv_data;
1560cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1561cabdff1aSopenharmony_ci    const GUIDParseTable *g = NULL;
1562cabdff1aSopenharmony_ci    ff_asf_guid guid;
1563cabdff1aSopenharmony_ci    int ret;
1564cabdff1aSopenharmony_ci
1565cabdff1aSopenharmony_ci    if (offset > INT64_MAX - size)
1566cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1567cabdff1aSopenharmony_ci
1568cabdff1aSopenharmony_ci    while (avio_tell(pb) <= offset + size) {
1569cabdff1aSopenharmony_ci        if (avio_tell(pb) == asf->offset)
1570cabdff1aSopenharmony_ci            break;
1571cabdff1aSopenharmony_ci        asf->offset = avio_tell(pb);
1572cabdff1aSopenharmony_ci        if ((ret = ff_get_guid(pb, &guid)) < 0)
1573cabdff1aSopenharmony_ci            return ret;
1574cabdff1aSopenharmony_ci        g = find_guid(guid);
1575cabdff1aSopenharmony_ci        if (g) {
1576cabdff1aSopenharmony_ci            if ((ret = g->read_object(s, g)) < 0)
1577cabdff1aSopenharmony_ci                return ret;
1578cabdff1aSopenharmony_ci        } else {
1579cabdff1aSopenharmony_ci            GUIDParseTable g2;
1580cabdff1aSopenharmony_ci
1581cabdff1aSopenharmony_ci            g2.name         = "Unknown";
1582cabdff1aSopenharmony_ci            g2.is_subobject = 1;
1583cabdff1aSopenharmony_ci            asf_read_unknown(s, &g2);
1584cabdff1aSopenharmony_ci        }
1585cabdff1aSopenharmony_ci    }
1586cabdff1aSopenharmony_ci
1587cabdff1aSopenharmony_ci    return 0;
1588cabdff1aSopenharmony_ci}
1589cabdff1aSopenharmony_ci
1590cabdff1aSopenharmony_cistatic int asf_read_header(AVFormatContext *s)
1591cabdff1aSopenharmony_ci{
1592cabdff1aSopenharmony_ci    ASFContext *asf         = s->priv_data;
1593cabdff1aSopenharmony_ci    AVIOContext *pb         = s->pb;
1594cabdff1aSopenharmony_ci    const GUIDParseTable *g = NULL;
1595cabdff1aSopenharmony_ci    ff_asf_guid guid;
1596cabdff1aSopenharmony_ci    int i, ret;
1597cabdff1aSopenharmony_ci    uint64_t size;
1598cabdff1aSopenharmony_ci
1599cabdff1aSopenharmony_ci    asf->preroll         = 0;
1600cabdff1aSopenharmony_ci    asf->is_simple_index = 0;
1601cabdff1aSopenharmony_ci    ff_get_guid(pb, &guid);
1602cabdff1aSopenharmony_ci    if (ff_guidcmp(&guid, &ff_asf_header))
1603cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1604cabdff1aSopenharmony_ci    avio_skip(pb, 8); // skip header object size
1605cabdff1aSopenharmony_ci    avio_skip(pb, 6); // skip number of header objects and 2 reserved bytes
1606cabdff1aSopenharmony_ci    asf->data_reached = 0;
1607cabdff1aSopenharmony_ci
1608cabdff1aSopenharmony_ci    /* 1  is here instead of pb->eof_reached because (when not streaming), Data are skipped
1609cabdff1aSopenharmony_ci     * for the first time,
1610cabdff1aSopenharmony_ci     * Index object is processed and got eof and then seeking back to the Data is performed.
1611cabdff1aSopenharmony_ci     */
1612cabdff1aSopenharmony_ci    while (1) {
1613cabdff1aSopenharmony_ci        // for the cases when object size is invalid
1614cabdff1aSopenharmony_ci        if (avio_tell(pb) == asf->offset)
1615cabdff1aSopenharmony_ci            break;
1616cabdff1aSopenharmony_ci        asf->offset = avio_tell(pb);
1617cabdff1aSopenharmony_ci        if ((ret = ff_get_guid(pb, &guid)) < 0) {
1618cabdff1aSopenharmony_ci            if (ret == AVERROR_EOF && asf->data_reached)
1619cabdff1aSopenharmony_ci                break;
1620cabdff1aSopenharmony_ci            else
1621cabdff1aSopenharmony_ci                goto failed;
1622cabdff1aSopenharmony_ci        }
1623cabdff1aSopenharmony_ci        g = find_guid(guid);
1624cabdff1aSopenharmony_ci        if (g) {
1625cabdff1aSopenharmony_ci            asf->unknown_offset = asf->offset;
1626cabdff1aSopenharmony_ci            asf->is_header = 1;
1627cabdff1aSopenharmony_ci            if ((ret = g->read_object(s, g)) < 0)
1628cabdff1aSopenharmony_ci                goto failed;
1629cabdff1aSopenharmony_ci        } else {
1630cabdff1aSopenharmony_ci            size = avio_rl64(pb);
1631cabdff1aSopenharmony_ci            align_position(pb, asf->offset, size);
1632cabdff1aSopenharmony_ci        }
1633cabdff1aSopenharmony_ci        if (asf->data_reached &&
1634cabdff1aSopenharmony_ci            (!(pb->seekable & AVIO_SEEKABLE_NORMAL) ||
1635cabdff1aSopenharmony_ci             (asf->b_flags & ASF_FLAG_BROADCAST)))
1636cabdff1aSopenharmony_ci            break;
1637cabdff1aSopenharmony_ci    }
1638cabdff1aSopenharmony_ci
1639cabdff1aSopenharmony_ci    if (!asf->data_reached) {
1640cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Data Object was not found.\n");
1641cabdff1aSopenharmony_ci        ret = AVERROR_INVALIDDATA;
1642cabdff1aSopenharmony_ci        goto failed;
1643cabdff1aSopenharmony_ci    }
1644cabdff1aSopenharmony_ci    if (pb->seekable & AVIO_SEEKABLE_NORMAL)
1645cabdff1aSopenharmony_ci        avio_seek(pb, asf->first_packet_offset, SEEK_SET);
1646cabdff1aSopenharmony_ci
1647cabdff1aSopenharmony_ci    for (i = 0; i < asf->nb_streams; i++) {
1648cabdff1aSopenharmony_ci        const char *rfc1766 = asf->asf_sd[asf->asf_st[i]->lang_idx].langs;
1649cabdff1aSopenharmony_ci        AVStream *st        = s->streams[asf->asf_st[i]->index];
1650cabdff1aSopenharmony_ci        set_language(s, rfc1766, &st->metadata);
1651cabdff1aSopenharmony_ci    }
1652cabdff1aSopenharmony_ci
1653cabdff1aSopenharmony_ci    for (i = 0; i < ASF_MAX_STREAMS; i++) {
1654cabdff1aSopenharmony_ci        AVStream *st = NULL;
1655cabdff1aSopenharmony_ci
1656cabdff1aSopenharmony_ci        st = find_stream(s, i);
1657cabdff1aSopenharmony_ci        if (st) {
1658cabdff1aSopenharmony_ci            av_dict_copy(&st->metadata, asf->asf_sd[i].asf_met, AV_DICT_IGNORE_SUFFIX);
1659cabdff1aSopenharmony_ci            if (asf->asf_sd[i].aspect_ratio.num > 0 && asf->asf_sd[i].aspect_ratio.den > 0) {
1660cabdff1aSopenharmony_ci                st->sample_aspect_ratio.num = asf->asf_sd[i].aspect_ratio.num;
1661cabdff1aSopenharmony_ci                st->sample_aspect_ratio.den = asf->asf_sd[i].aspect_ratio.den;
1662cabdff1aSopenharmony_ci            }
1663cabdff1aSopenharmony_ci        }
1664cabdff1aSopenharmony_ci    }
1665cabdff1aSopenharmony_ci
1666cabdff1aSopenharmony_ci    return 0;
1667cabdff1aSopenharmony_ci
1668cabdff1aSopenharmony_cifailed:
1669cabdff1aSopenharmony_ci    asf_read_close(s);
1670cabdff1aSopenharmony_ci    return ret;
1671cabdff1aSopenharmony_ci}
1672cabdff1aSopenharmony_ci
1673cabdff1aSopenharmony_ciconst AVInputFormat ff_asf_o_demuxer = {
1674cabdff1aSopenharmony_ci    .name           = "asf_o",
1675cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
1676cabdff1aSopenharmony_ci    .priv_data_size = sizeof(ASFContext),
1677cabdff1aSopenharmony_ci    .read_probe     = asf_probe,
1678cabdff1aSopenharmony_ci    .read_header    = asf_read_header,
1679cabdff1aSopenharmony_ci    .read_packet    = asf_read_packet,
1680cabdff1aSopenharmony_ci    .read_close     = asf_read_close,
1681cabdff1aSopenharmony_ci    .read_timestamp = asf_read_timestamp,
1682cabdff1aSopenharmony_ci    .read_seek      = asf_read_seek,
1683cabdff1aSopenharmony_ci    .flags          = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH,
1684cabdff1aSopenharmony_ci};
1685