1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * FLV demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2003 The FFmpeg Project
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This demuxer will generate a 1 byte extradata for VP6F content.
6cabdff1aSopenharmony_ci * It is composed of:
7cabdff1aSopenharmony_ci *  - upper 4 bits: difference between encoded width and visible width
8cabdff1aSopenharmony_ci *  - lower 4 bits: difference between encoded height and visible height
9cabdff1aSopenharmony_ci *
10cabdff1aSopenharmony_ci * This file is part of FFmpeg.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
13cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
14cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
15cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
18cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
19cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20cabdff1aSopenharmony_ci * Lesser General Public License for more details.
21cabdff1aSopenharmony_ci *
22cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
23cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
24cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25cabdff1aSopenharmony_ci */
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
28cabdff1aSopenharmony_ci#include "libavutil/avstring.h"
29cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
30cabdff1aSopenharmony_ci#include "libavutil/dict.h"
31cabdff1aSopenharmony_ci#include "libavutil/opt.h"
32cabdff1aSopenharmony_ci#include "libavutil/internal.h"
33cabdff1aSopenharmony_ci#include "libavutil/intfloat.h"
34cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
35cabdff1aSopenharmony_ci#include "libavutil/mathematics.h"
36cabdff1aSopenharmony_ci#include "avformat.h"
37cabdff1aSopenharmony_ci#include "demux.h"
38cabdff1aSopenharmony_ci#include "internal.h"
39cabdff1aSopenharmony_ci#include "flv.h"
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci#define VALIDATE_INDEX_TS_THRESH 2500
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci#define RESYNC_BUFFER_SIZE (1<<20)
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci#define MAX_DEPTH 16      ///< arbitrary limit to prevent unbounded recursion
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_citypedef struct FLVContext {
48cabdff1aSopenharmony_ci    const AVClass *class; ///< Class for private options.
49cabdff1aSopenharmony_ci    int trust_metadata;   ///< configure streams according onMetaData
50cabdff1aSopenharmony_ci    int trust_datasize;   ///< trust data size of FLVTag
51cabdff1aSopenharmony_ci    int dump_full_metadata;   ///< Dump full metadata of the onMetadata
52cabdff1aSopenharmony_ci    int wrong_dts;        ///< wrong dts due to negative cts
53cabdff1aSopenharmony_ci    uint8_t *new_extradata[FLV_STREAM_TYPE_NB];
54cabdff1aSopenharmony_ci    int new_extradata_size[FLV_STREAM_TYPE_NB];
55cabdff1aSopenharmony_ci    int last_sample_rate;
56cabdff1aSopenharmony_ci    int last_channels;
57cabdff1aSopenharmony_ci    struct {
58cabdff1aSopenharmony_ci        int64_t dts;
59cabdff1aSopenharmony_ci        int64_t pos;
60cabdff1aSopenharmony_ci    } validate_index[2];
61cabdff1aSopenharmony_ci    int validate_next;
62cabdff1aSopenharmony_ci    int validate_count;
63cabdff1aSopenharmony_ci    int searched_for_end;
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ci    uint8_t resync_buffer[2*RESYNC_BUFFER_SIZE];
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_ci    int broken_sizes;
68cabdff1aSopenharmony_ci    int64_t sum_flv_tag_size;
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci    int last_keyframe_stream_index;
71cabdff1aSopenharmony_ci    int keyframe_count;
72cabdff1aSopenharmony_ci    int64_t video_bit_rate;
73cabdff1aSopenharmony_ci    int64_t audio_bit_rate;
74cabdff1aSopenharmony_ci    int64_t *keyframe_times;
75cabdff1aSopenharmony_ci    int64_t *keyframe_filepositions;
76cabdff1aSopenharmony_ci    int missing_streams;
77cabdff1aSopenharmony_ci    AVRational framerate;
78cabdff1aSopenharmony_ci    int64_t last_ts;
79cabdff1aSopenharmony_ci    int64_t time_offset;
80cabdff1aSopenharmony_ci    int64_t time_pos;
81cabdff1aSopenharmony_ci} FLVContext;
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci/* AMF date type */
84cabdff1aSopenharmony_citypedef struct amf_date {
85cabdff1aSopenharmony_ci    double   milliseconds;
86cabdff1aSopenharmony_ci    int16_t  timezone;
87cabdff1aSopenharmony_ci} amf_date;
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_cistatic int probe(const AVProbeData *p, int live)
90cabdff1aSopenharmony_ci{
91cabdff1aSopenharmony_ci    const uint8_t *d = p->buf;
92cabdff1aSopenharmony_ci    unsigned offset = AV_RB32(d + 5);
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci    if (d[0] == 'F' &&
95cabdff1aSopenharmony_ci        d[1] == 'L' &&
96cabdff1aSopenharmony_ci        d[2] == 'V' &&
97cabdff1aSopenharmony_ci        d[3] < 5 && d[5] == 0 &&
98cabdff1aSopenharmony_ci        offset + 100 < p->buf_size &&
99cabdff1aSopenharmony_ci        offset > 8) {
100cabdff1aSopenharmony_ci        int is_live = !memcmp(d + offset + 40, "NGINX RTMP", 10);
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci        if (live == is_live)
103cabdff1aSopenharmony_ci            return AVPROBE_SCORE_MAX;
104cabdff1aSopenharmony_ci    }
105cabdff1aSopenharmony_ci    return 0;
106cabdff1aSopenharmony_ci}
107cabdff1aSopenharmony_ci
108cabdff1aSopenharmony_cistatic int flv_probe(const AVProbeData *p)
109cabdff1aSopenharmony_ci{
110cabdff1aSopenharmony_ci    return probe(p, 0);
111cabdff1aSopenharmony_ci}
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_cistatic int live_flv_probe(const AVProbeData *p)
114cabdff1aSopenharmony_ci{
115cabdff1aSopenharmony_ci    return probe(p, 1);
116cabdff1aSopenharmony_ci}
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_cistatic int kux_probe(const AVProbeData *p)
119cabdff1aSopenharmony_ci{
120cabdff1aSopenharmony_ci    const uint8_t *d = p->buf;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    if (d[0] == 'K' &&
123cabdff1aSopenharmony_ci        d[1] == 'D' &&
124cabdff1aSopenharmony_ci        d[2] == 'K' &&
125cabdff1aSopenharmony_ci        d[3] == 0 &&
126cabdff1aSopenharmony_ci        d[4] == 0) {
127cabdff1aSopenharmony_ci        return AVPROBE_SCORE_EXTENSION + 1;
128cabdff1aSopenharmony_ci    }
129cabdff1aSopenharmony_ci    return 0;
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_cistatic void add_keyframes_index(AVFormatContext *s)
133cabdff1aSopenharmony_ci{
134cabdff1aSopenharmony_ci    FLVContext *flv   = s->priv_data;
135cabdff1aSopenharmony_ci    AVStream *stream  = NULL;
136cabdff1aSopenharmony_ci    unsigned int i    = 0;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci    if (flv->last_keyframe_stream_index < 0) {
139cabdff1aSopenharmony_ci        av_log(s, AV_LOG_DEBUG, "keyframe stream hasn't been created\n");
140cabdff1aSopenharmony_ci        return;
141cabdff1aSopenharmony_ci    }
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    av_assert0(flv->last_keyframe_stream_index <= s->nb_streams);
144cabdff1aSopenharmony_ci    stream = s->streams[flv->last_keyframe_stream_index];
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    if (ffstream(stream)->nb_index_entries == 0) {
147cabdff1aSopenharmony_ci        for (i = 0; i < flv->keyframe_count; i++) {
148cabdff1aSopenharmony_ci            av_log(s, AV_LOG_TRACE, "keyframe filepositions = %"PRId64" times = %"PRId64"\n",
149cabdff1aSopenharmony_ci                   flv->keyframe_filepositions[i], flv->keyframe_times[i] * 1000);
150cabdff1aSopenharmony_ci            av_add_index_entry(stream, flv->keyframe_filepositions[i],
151cabdff1aSopenharmony_ci                flv->keyframe_times[i] * 1000, 0, 0, AVINDEX_KEYFRAME);
152cabdff1aSopenharmony_ci        }
153cabdff1aSopenharmony_ci    } else
154cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING, "Skipping duplicate index\n");
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci    if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
157cabdff1aSopenharmony_ci        av_freep(&flv->keyframe_times);
158cabdff1aSopenharmony_ci        av_freep(&flv->keyframe_filepositions);
159cabdff1aSopenharmony_ci        flv->keyframe_count = 0;
160cabdff1aSopenharmony_ci    }
161cabdff1aSopenharmony_ci}
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_cistatic AVStream *create_stream(AVFormatContext *s, int codec_type)
164cabdff1aSopenharmony_ci{
165cabdff1aSopenharmony_ci    FLVContext *flv   = s->priv_data;
166cabdff1aSopenharmony_ci    AVStream *st = avformat_new_stream(s, NULL);
167cabdff1aSopenharmony_ci    if (!st)
168cabdff1aSopenharmony_ci        return NULL;
169cabdff1aSopenharmony_ci    st->codecpar->codec_type = codec_type;
170cabdff1aSopenharmony_ci    if (s->nb_streams>=3 ||(   s->nb_streams==2
171cabdff1aSopenharmony_ci                           && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE
172cabdff1aSopenharmony_ci                           && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE
173cabdff1aSopenharmony_ci                           && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_DATA
174cabdff1aSopenharmony_ci                           && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_DATA))
175cabdff1aSopenharmony_ci        s->ctx_flags &= ~AVFMTCTX_NOHEADER;
176cabdff1aSopenharmony_ci    if (codec_type == AVMEDIA_TYPE_AUDIO) {
177cabdff1aSopenharmony_ci        st->codecpar->bit_rate = flv->audio_bit_rate;
178cabdff1aSopenharmony_ci        flv->missing_streams &= ~FLV_HEADER_FLAG_HASAUDIO;
179cabdff1aSopenharmony_ci    }
180cabdff1aSopenharmony_ci    if (codec_type == AVMEDIA_TYPE_VIDEO) {
181cabdff1aSopenharmony_ci        st->codecpar->bit_rate = flv->video_bit_rate;
182cabdff1aSopenharmony_ci        flv->missing_streams &= ~FLV_HEADER_FLAG_HASVIDEO;
183cabdff1aSopenharmony_ci        st->avg_frame_rate = flv->framerate;
184cabdff1aSopenharmony_ci    }
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_ci    avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
188cabdff1aSopenharmony_ci    flv->last_keyframe_stream_index = s->nb_streams - 1;
189cabdff1aSopenharmony_ci    add_keyframes_index(s);
190cabdff1aSopenharmony_ci    return st;
191cabdff1aSopenharmony_ci}
192cabdff1aSopenharmony_ci
193cabdff1aSopenharmony_cistatic int flv_same_audio_codec(AVCodecParameters *apar, int flags)
194cabdff1aSopenharmony_ci{
195cabdff1aSopenharmony_ci    int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
196cabdff1aSopenharmony_ci    int flv_codecid           = flags & FLV_AUDIO_CODECID_MASK;
197cabdff1aSopenharmony_ci    int codec_id;
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci    if (!apar->codec_id && !apar->codec_tag)
200cabdff1aSopenharmony_ci        return 1;
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci    if (apar->bits_per_coded_sample != bits_per_coded_sample)
203cabdff1aSopenharmony_ci        return 0;
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    switch (flv_codecid) {
206cabdff1aSopenharmony_ci    // no distinction between S16 and S8 PCM codec flags
207cabdff1aSopenharmony_ci    case FLV_CODECID_PCM:
208cabdff1aSopenharmony_ci        codec_id = bits_per_coded_sample == 8
209cabdff1aSopenharmony_ci                   ? AV_CODEC_ID_PCM_U8
210cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN
211cabdff1aSopenharmony_ci                   : AV_CODEC_ID_PCM_S16BE;
212cabdff1aSopenharmony_ci#else
213cabdff1aSopenharmony_ci                   : AV_CODEC_ID_PCM_S16LE;
214cabdff1aSopenharmony_ci#endif
215cabdff1aSopenharmony_ci        return codec_id == apar->codec_id;
216cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_LE:
217cabdff1aSopenharmony_ci        codec_id = bits_per_coded_sample == 8
218cabdff1aSopenharmony_ci                   ? AV_CODEC_ID_PCM_U8
219cabdff1aSopenharmony_ci                   : AV_CODEC_ID_PCM_S16LE;
220cabdff1aSopenharmony_ci        return codec_id == apar->codec_id;
221cabdff1aSopenharmony_ci    case FLV_CODECID_AAC:
222cabdff1aSopenharmony_ci        return apar->codec_id == AV_CODEC_ID_AAC;
223cabdff1aSopenharmony_ci    case FLV_CODECID_ADPCM:
224cabdff1aSopenharmony_ci        return apar->codec_id == AV_CODEC_ID_ADPCM_SWF;
225cabdff1aSopenharmony_ci    case FLV_CODECID_SPEEX:
226cabdff1aSopenharmony_ci        return apar->codec_id == AV_CODEC_ID_SPEEX;
227cabdff1aSopenharmony_ci    case FLV_CODECID_MP3:
228cabdff1aSopenharmony_ci        return apar->codec_id == AV_CODEC_ID_MP3;
229cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
230cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
231cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER:
232cabdff1aSopenharmony_ci        return apar->codec_id == AV_CODEC_ID_NELLYMOSER;
233cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_MULAW:
234cabdff1aSopenharmony_ci        return apar->sample_rate == 8000 &&
235cabdff1aSopenharmony_ci               apar->codec_id    == AV_CODEC_ID_PCM_MULAW;
236cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_ALAW:
237cabdff1aSopenharmony_ci        return apar->sample_rate == 8000 &&
238cabdff1aSopenharmony_ci               apar->codec_id    == AV_CODEC_ID_PCM_ALAW;
239cabdff1aSopenharmony_ci    default:
240cabdff1aSopenharmony_ci        return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
241cabdff1aSopenharmony_ci    }
242cabdff1aSopenharmony_ci}
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_cistatic void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
245cabdff1aSopenharmony_ci                                AVCodecParameters *apar, int flv_codecid)
246cabdff1aSopenharmony_ci{
247cabdff1aSopenharmony_ci    switch (flv_codecid) {
248cabdff1aSopenharmony_ci    // no distinction between S16 and S8 PCM codec flags
249cabdff1aSopenharmony_ci    case FLV_CODECID_PCM:
250cabdff1aSopenharmony_ci        apar->codec_id = apar->bits_per_coded_sample == 8
251cabdff1aSopenharmony_ci                           ? AV_CODEC_ID_PCM_U8
252cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN
253cabdff1aSopenharmony_ci                           : AV_CODEC_ID_PCM_S16BE;
254cabdff1aSopenharmony_ci#else
255cabdff1aSopenharmony_ci                           : AV_CODEC_ID_PCM_S16LE;
256cabdff1aSopenharmony_ci#endif
257cabdff1aSopenharmony_ci        break;
258cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_LE:
259cabdff1aSopenharmony_ci        apar->codec_id = apar->bits_per_coded_sample == 8
260cabdff1aSopenharmony_ci                           ? AV_CODEC_ID_PCM_U8
261cabdff1aSopenharmony_ci                           : AV_CODEC_ID_PCM_S16LE;
262cabdff1aSopenharmony_ci        break;
263cabdff1aSopenharmony_ci    case FLV_CODECID_AAC:
264cabdff1aSopenharmony_ci        apar->codec_id = AV_CODEC_ID_AAC;
265cabdff1aSopenharmony_ci        break;
266cabdff1aSopenharmony_ci    case FLV_CODECID_ADPCM:
267cabdff1aSopenharmony_ci        apar->codec_id = AV_CODEC_ID_ADPCM_SWF;
268cabdff1aSopenharmony_ci        break;
269cabdff1aSopenharmony_ci    case FLV_CODECID_SPEEX:
270cabdff1aSopenharmony_ci        apar->codec_id    = AV_CODEC_ID_SPEEX;
271cabdff1aSopenharmony_ci        apar->sample_rate = 16000;
272cabdff1aSopenharmony_ci        break;
273cabdff1aSopenharmony_ci    case FLV_CODECID_MP3:
274cabdff1aSopenharmony_ci        apar->codec_id      = AV_CODEC_ID_MP3;
275cabdff1aSopenharmony_ci        ffstream(astream)->need_parsing = AVSTREAM_PARSE_FULL;
276cabdff1aSopenharmony_ci        break;
277cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
278cabdff1aSopenharmony_ci        // in case metadata does not otherwise declare samplerate
279cabdff1aSopenharmony_ci        apar->sample_rate = 8000;
280cabdff1aSopenharmony_ci        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;
281cabdff1aSopenharmony_ci        break;
282cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
283cabdff1aSopenharmony_ci        apar->sample_rate = 16000;
284cabdff1aSopenharmony_ci        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;
285cabdff1aSopenharmony_ci        break;
286cabdff1aSopenharmony_ci    case FLV_CODECID_NELLYMOSER:
287cabdff1aSopenharmony_ci        apar->codec_id = AV_CODEC_ID_NELLYMOSER;
288cabdff1aSopenharmony_ci        break;
289cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_MULAW:
290cabdff1aSopenharmony_ci        apar->sample_rate = 8000;
291cabdff1aSopenharmony_ci        apar->codec_id    = AV_CODEC_ID_PCM_MULAW;
292cabdff1aSopenharmony_ci        break;
293cabdff1aSopenharmony_ci    case FLV_CODECID_PCM_ALAW:
294cabdff1aSopenharmony_ci        apar->sample_rate = 8000;
295cabdff1aSopenharmony_ci        apar->codec_id    = AV_CODEC_ID_PCM_ALAW;
296cabdff1aSopenharmony_ci        break;
297cabdff1aSopenharmony_ci    default:
298cabdff1aSopenharmony_ci        avpriv_request_sample(s, "Audio codec (%x)",
299cabdff1aSopenharmony_ci               flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
300cabdff1aSopenharmony_ci        apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
301cabdff1aSopenharmony_ci    }
302cabdff1aSopenharmony_ci}
303cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
304cabdff1aSopenharmony_cistatic int flv_same_video_codec(AVCodecParameters *vpar, uint32_t flv_codecid)
305cabdff1aSopenharmony_ci{
306cabdff1aSopenharmony_ci    if (!vpar->codec_id && !vpar->codec_tag)
307cabdff1aSopenharmony_ci        return 1;
308cabdff1aSopenharmony_ci
309cabdff1aSopenharmony_ci    switch (flv_codecid) {
310cabdff1aSopenharmony_ci    case MKBETAG('h', 'v', 'c', '1'):
311cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_HEVC;
312cabdff1aSopenharmony_ci    case FLV_CODECID_H263:
313cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLV1;
314cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN:
315cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLASHSV;
316cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN2:
317cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLASHSV2;
318cabdff1aSopenharmony_ci    case FLV_CODECID_VP6:
319cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_VP6F;
320cabdff1aSopenharmony_ci    case FLV_CODECID_VP6A:
321cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_VP6A;
322cabdff1aSopenharmony_ci    case FLV_CODECID_H264:
323cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_H264;
324cabdff1aSopenharmony_ci    case FLV_CODECID_HEVC:
325cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_HEVC;
326cabdff1aSopenharmony_ci    default:
327cabdff1aSopenharmony_ci        return vpar->codec_tag == flv_codecid;
328cabdff1aSopenharmony_ci    }
329cabdff1aSopenharmony_ci}
330cabdff1aSopenharmony_ci#else
331cabdff1aSopenharmony_cistatic int flv_same_video_codec(AVCodecParameters *vpar, int flags)
332cabdff1aSopenharmony_ci{
333cabdff1aSopenharmony_ci    int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_ci    if (!vpar->codec_id && !vpar->codec_tag)
336cabdff1aSopenharmony_ci        return 1;
337cabdff1aSopenharmony_ci
338cabdff1aSopenharmony_ci    switch (flv_codecid) {
339cabdff1aSopenharmony_ci    case FLV_CODECID_H263:
340cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLV1;
341cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN:
342cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLASHSV;
343cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN2:
344cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_FLASHSV2;
345cabdff1aSopenharmony_ci    case FLV_CODECID_VP6:
346cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_VP6F;
347cabdff1aSopenharmony_ci    case FLV_CODECID_VP6A:
348cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_VP6A;
349cabdff1aSopenharmony_ci    case FLV_CODECID_H264:
350cabdff1aSopenharmony_ci        return vpar->codec_id == AV_CODEC_ID_H264;
351cabdff1aSopenharmony_ci    default:
352cabdff1aSopenharmony_ci        return vpar->codec_tag == flv_codecid;
353cabdff1aSopenharmony_ci    }
354cabdff1aSopenharmony_ci}
355cabdff1aSopenharmony_ci#endif
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_cistatic int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
358cabdff1aSopenharmony_ci                               int flv_codecid, int read)
359cabdff1aSopenharmony_ci{
360cabdff1aSopenharmony_ci    FFStream *const vstreami = ffstream(vstream);
361cabdff1aSopenharmony_ci    int ret = 0;
362cabdff1aSopenharmony_ci    AVCodecParameters *par = vstream->codecpar;
363cabdff1aSopenharmony_ci    enum AVCodecID old_codec_id = vstream->codecpar->codec_id;
364cabdff1aSopenharmony_ci    switch (flv_codecid) {
365cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
366cabdff1aSopenharmony_ci    case MKBETAG('h', 'v', 'c', '1'):
367cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_HEVC;
368cabdff1aSopenharmony_ci        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
369cabdff1aSopenharmony_ci        break;
370cabdff1aSopenharmony_ci#endif
371cabdff1aSopenharmony_ci    case FLV_CODECID_H263:
372cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_FLV1;
373cabdff1aSopenharmony_ci        break;
374cabdff1aSopenharmony_ci    case FLV_CODECID_REALH263:
375cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_H263;
376cabdff1aSopenharmony_ci        break; // Really mean it this time
377cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN:
378cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_FLASHSV;
379cabdff1aSopenharmony_ci        break;
380cabdff1aSopenharmony_ci    case FLV_CODECID_SCREEN2:
381cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_FLASHSV2;
382cabdff1aSopenharmony_ci        break;
383cabdff1aSopenharmony_ci    case FLV_CODECID_VP6:
384cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_VP6F;
385cabdff1aSopenharmony_ci    case FLV_CODECID_VP6A:
386cabdff1aSopenharmony_ci        if (flv_codecid == FLV_CODECID_VP6A)
387cabdff1aSopenharmony_ci            par->codec_id = AV_CODEC_ID_VP6A;
388cabdff1aSopenharmony_ci        if (read) {
389cabdff1aSopenharmony_ci            if (par->extradata_size != 1) {
390cabdff1aSopenharmony_ci                ff_alloc_extradata(par, 1);
391cabdff1aSopenharmony_ci            }
392cabdff1aSopenharmony_ci            if (par->extradata)
393cabdff1aSopenharmony_ci                par->extradata[0] = avio_r8(s->pb);
394cabdff1aSopenharmony_ci            else
395cabdff1aSopenharmony_ci                avio_skip(s->pb, 1);
396cabdff1aSopenharmony_ci        }
397cabdff1aSopenharmony_ci        ret = 1;     // 1 byte body size adjustment for flv_read_packet()
398cabdff1aSopenharmony_ci        break;
399cabdff1aSopenharmony_ci    case FLV_CODECID_H264:
400cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_H264;
401cabdff1aSopenharmony_ci        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
402cabdff1aSopenharmony_ci#ifndef OHOS_H265_DEMUXER
403cabdff1aSopenharmony_ci        ret = 3;
404cabdff1aSopenharmony_ci#endif
405cabdff1aSopenharmony_ci        break;
406cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
407cabdff1aSopenharmony_ci    case FLV_CODECID_HEVC:
408cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_HEVC;
409cabdff1aSopenharmony_ci        vstreami->need_parsing = AVSTREAM_PARSE_HEADERS;
410cabdff1aSopenharmony_ci        break;
411cabdff1aSopenharmony_ci#endif
412cabdff1aSopenharmony_ci    case FLV_CODECID_MPEG4:
413cabdff1aSopenharmony_ci        par->codec_id = AV_CODEC_ID_MPEG4;
414cabdff1aSopenharmony_ci#ifndef OHOS_H265_DEMUXER
415cabdff1aSopenharmony_ci        ret = 3;
416cabdff1aSopenharmony_ci#endif
417cabdff1aSopenharmony_ci        break;
418cabdff1aSopenharmony_ci    default:
419cabdff1aSopenharmony_ci        avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
420cabdff1aSopenharmony_ci        par->codec_tag = flv_codecid;
421cabdff1aSopenharmony_ci    }
422cabdff1aSopenharmony_ci
423cabdff1aSopenharmony_ci    if (!vstreami->need_context_update && par->codec_id != old_codec_id) {
424cabdff1aSopenharmony_ci        avpriv_request_sample(s, "Changing the codec id midstream");
425cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
426cabdff1aSopenharmony_ci    }
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    return ret;
429cabdff1aSopenharmony_ci}
430cabdff1aSopenharmony_ci
431cabdff1aSopenharmony_cistatic int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
432cabdff1aSopenharmony_ci{
433cabdff1aSopenharmony_ci    int ret;
434cabdff1aSopenharmony_ci    int length = avio_rb16(ioc);
435cabdff1aSopenharmony_ci    if (length >= buffsize) {
436cabdff1aSopenharmony_ci        avio_skip(ioc, length);
437cabdff1aSopenharmony_ci        return -1;
438cabdff1aSopenharmony_ci    }
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_ci    ret = avio_read(ioc, buffer, length);
441cabdff1aSopenharmony_ci    if (ret < 0)
442cabdff1aSopenharmony_ci        return ret;
443cabdff1aSopenharmony_ci    if (ret < length)
444cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
445cabdff1aSopenharmony_ci
446cabdff1aSopenharmony_ci    buffer[length] = '\0';
447cabdff1aSopenharmony_ci
448cabdff1aSopenharmony_ci    return length;
449cabdff1aSopenharmony_ci}
450cabdff1aSopenharmony_ci
451cabdff1aSopenharmony_cistatic int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t max_pos)
452cabdff1aSopenharmony_ci{
453cabdff1aSopenharmony_ci    FLVContext *flv       = s->priv_data;
454cabdff1aSopenharmony_ci    unsigned int timeslen = 0, fileposlen = 0, i;
455cabdff1aSopenharmony_ci    char str_val[256];
456cabdff1aSopenharmony_ci    int64_t *times         = NULL;
457cabdff1aSopenharmony_ci    int64_t *filepositions = NULL;
458cabdff1aSopenharmony_ci    int ret                = AVERROR(ENOSYS);
459cabdff1aSopenharmony_ci    int64_t initial_pos    = avio_tell(ioc);
460cabdff1aSopenharmony_ci
461cabdff1aSopenharmony_ci    if (flv->keyframe_count > 0) {
462cabdff1aSopenharmony_ci        av_log(s, AV_LOG_DEBUG, "keyframes have been parsed\n");
463cabdff1aSopenharmony_ci        return 0;
464cabdff1aSopenharmony_ci    }
465cabdff1aSopenharmony_ci    av_assert0(!flv->keyframe_times);
466cabdff1aSopenharmony_ci    av_assert0(!flv->keyframe_filepositions);
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci    if (s->flags & AVFMT_FLAG_IGNIDX)
469cabdff1aSopenharmony_ci        return 0;
470cabdff1aSopenharmony_ci
471cabdff1aSopenharmony_ci    while (avio_tell(ioc) < max_pos - 2 &&
472cabdff1aSopenharmony_ci           amf_get_string(ioc, str_val, sizeof(str_val)) > 0) {
473cabdff1aSopenharmony_ci        int64_t **current_array;
474cabdff1aSopenharmony_ci        unsigned int arraylen;
475cabdff1aSopenharmony_ci
476cabdff1aSopenharmony_ci        // Expect array object in context
477cabdff1aSopenharmony_ci        if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY)
478cabdff1aSopenharmony_ci            break;
479cabdff1aSopenharmony_ci
480cabdff1aSopenharmony_ci        arraylen = avio_rb32(ioc);
481cabdff1aSopenharmony_ci        if (arraylen>>28)
482cabdff1aSopenharmony_ci            break;
483cabdff1aSopenharmony_ci
484cabdff1aSopenharmony_ci        if       (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times) {
485cabdff1aSopenharmony_ci            current_array = &times;
486cabdff1aSopenharmony_ci            timeslen      = arraylen;
487cabdff1aSopenharmony_ci        } else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) &&
488cabdff1aSopenharmony_ci                   !filepositions) {
489cabdff1aSopenharmony_ci            current_array = &filepositions;
490cabdff1aSopenharmony_ci            fileposlen    = arraylen;
491cabdff1aSopenharmony_ci        } else
492cabdff1aSopenharmony_ci            // unexpected metatag inside keyframes, will not use such
493cabdff1aSopenharmony_ci            // metadata for indexing
494cabdff1aSopenharmony_ci            break;
495cabdff1aSopenharmony_ci
496cabdff1aSopenharmony_ci        if (!(*current_array = av_mallocz(sizeof(**current_array) * arraylen))) {
497cabdff1aSopenharmony_ci            ret = AVERROR(ENOMEM);
498cabdff1aSopenharmony_ci            goto finish;
499cabdff1aSopenharmony_ci        }
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci        for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
502cabdff1aSopenharmony_ci            double d;
503cabdff1aSopenharmony_ci            if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER)
504cabdff1aSopenharmony_ci                goto invalid;
505cabdff1aSopenharmony_ci            d = av_int2double(avio_rb64(ioc));
506cabdff1aSopenharmony_ci            if (isnan(d) || d < INT64_MIN || d > INT64_MAX)
507cabdff1aSopenharmony_ci                goto invalid;
508cabdff1aSopenharmony_ci            if (current_array == &times && (d <= INT64_MIN / 1000 || d >= INT64_MAX / 1000))
509cabdff1aSopenharmony_ci                goto invalid;
510cabdff1aSopenharmony_ci            if (avio_feof(ioc))
511cabdff1aSopenharmony_ci                goto invalid;
512cabdff1aSopenharmony_ci            current_array[0][i] = d;
513cabdff1aSopenharmony_ci        }
514cabdff1aSopenharmony_ci        if (times && filepositions) {
515cabdff1aSopenharmony_ci            // All done, exiting at a position allowing amf_parse_object
516cabdff1aSopenharmony_ci            // to finish parsing the object
517cabdff1aSopenharmony_ci            ret = 0;
518cabdff1aSopenharmony_ci            break;
519cabdff1aSopenharmony_ci        }
520cabdff1aSopenharmony_ci    }
521cabdff1aSopenharmony_ci
522cabdff1aSopenharmony_ci    if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) {
523cabdff1aSopenharmony_ci        for (i = 0; i < FFMIN(2,fileposlen); i++) {
524cabdff1aSopenharmony_ci            flv->validate_index[i].pos = filepositions[i];
525cabdff1aSopenharmony_ci            flv->validate_index[i].dts = times[i] * 1000;
526cabdff1aSopenharmony_ci            flv->validate_count        = i + 1;
527cabdff1aSopenharmony_ci        }
528cabdff1aSopenharmony_ci        flv->keyframe_times = times;
529cabdff1aSopenharmony_ci        flv->keyframe_filepositions = filepositions;
530cabdff1aSopenharmony_ci        flv->keyframe_count = timeslen;
531cabdff1aSopenharmony_ci        times = NULL;
532cabdff1aSopenharmony_ci        filepositions = NULL;
533cabdff1aSopenharmony_ci    } else {
534cabdff1aSopenharmony_ciinvalid:
535cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
536cabdff1aSopenharmony_ci    }
537cabdff1aSopenharmony_ci
538cabdff1aSopenharmony_cifinish:
539cabdff1aSopenharmony_ci    av_freep(&times);
540cabdff1aSopenharmony_ci    av_freep(&filepositions);
541cabdff1aSopenharmony_ci    avio_seek(ioc, initial_pos, SEEK_SET);
542cabdff1aSopenharmony_ci    return ret;
543cabdff1aSopenharmony_ci}
544cabdff1aSopenharmony_ci
545cabdff1aSopenharmony_cistatic int amf_parse_object(AVFormatContext *s, AVStream *astream,
546cabdff1aSopenharmony_ci                            AVStream *vstream, const char *key,
547cabdff1aSopenharmony_ci                            int64_t max_pos, int depth)
548cabdff1aSopenharmony_ci{
549cabdff1aSopenharmony_ci    AVCodecParameters *apar, *vpar;
550cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
551cabdff1aSopenharmony_ci    AVIOContext *ioc;
552cabdff1aSopenharmony_ci    AMFDataType amf_type;
553cabdff1aSopenharmony_ci    char str_val[1024];
554cabdff1aSopenharmony_ci    double num_val;
555cabdff1aSopenharmony_ci    amf_date date;
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci    if (depth > MAX_DEPTH)
558cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
559cabdff1aSopenharmony_ci
560cabdff1aSopenharmony_ci    num_val  = 0;
561cabdff1aSopenharmony_ci    ioc      = s->pb;
562cabdff1aSopenharmony_ci    if (avio_feof(ioc))
563cabdff1aSopenharmony_ci        return AVERROR_EOF;
564cabdff1aSopenharmony_ci    amf_type = avio_r8(ioc);
565cabdff1aSopenharmony_ci
566cabdff1aSopenharmony_ci    switch (amf_type) {
567cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_NUMBER:
568cabdff1aSopenharmony_ci        num_val = av_int2double(avio_rb64(ioc));
569cabdff1aSopenharmony_ci        break;
570cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_BOOL:
571cabdff1aSopenharmony_ci        num_val = avio_r8(ioc);
572cabdff1aSopenharmony_ci        break;
573cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_STRING:
574cabdff1aSopenharmony_ci        if (amf_get_string(ioc, str_val, sizeof(str_val)) < 0) {
575cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "AMF_DATA_TYPE_STRING parsing failed\n");
576cabdff1aSopenharmony_ci            return -1;
577cabdff1aSopenharmony_ci        }
578cabdff1aSopenharmony_ci        break;
579cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_OBJECT:
580cabdff1aSopenharmony_ci        if (key &&
581cabdff1aSopenharmony_ci            (ioc->seekable & AVIO_SEEKABLE_NORMAL) &&
582cabdff1aSopenharmony_ci            !strcmp(KEYFRAMES_TAG, key) && depth == 1)
583cabdff1aSopenharmony_ci            if (parse_keyframes_index(s, ioc, max_pos) < 0)
584cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n");
585cabdff1aSopenharmony_ci            else
586cabdff1aSopenharmony_ci                add_keyframes_index(s);
587cabdff1aSopenharmony_ci        while (avio_tell(ioc) < max_pos - 2 &&
588cabdff1aSopenharmony_ci               amf_get_string(ioc, str_val, sizeof(str_val)) > 0)
589cabdff1aSopenharmony_ci            if (amf_parse_object(s, astream, vstream, str_val, max_pos,
590cabdff1aSopenharmony_ci                                 depth + 1) < 0)
591cabdff1aSopenharmony_ci                return -1;     // if we couldn't skip, bomb out.
592cabdff1aSopenharmony_ci        if (avio_r8(ioc) != AMF_END_OF_OBJECT) {
593cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Missing AMF_END_OF_OBJECT in AMF_DATA_TYPE_OBJECT\n");
594cabdff1aSopenharmony_ci            return -1;
595cabdff1aSopenharmony_ci        }
596cabdff1aSopenharmony_ci        break;
597cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_NULL:
598cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_UNDEFINED:
599cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_UNSUPPORTED:
600cabdff1aSopenharmony_ci        break;     // these take up no additional space
601cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_MIXEDARRAY:
602cabdff1aSopenharmony_ci    {
603cabdff1aSopenharmony_ci        unsigned v;
604cabdff1aSopenharmony_ci        avio_skip(ioc, 4);     // skip 32-bit max array index
605cabdff1aSopenharmony_ci        while (avio_tell(ioc) < max_pos - 2 &&
606cabdff1aSopenharmony_ci               amf_get_string(ioc, str_val, sizeof(str_val)) > 0)
607cabdff1aSopenharmony_ci            // this is the only case in which we would want a nested
608cabdff1aSopenharmony_ci            // parse to not skip over the object
609cabdff1aSopenharmony_ci            if (amf_parse_object(s, astream, vstream, str_val, max_pos,
610cabdff1aSopenharmony_ci                                 depth + 1) < 0)
611cabdff1aSopenharmony_ci                return -1;
612cabdff1aSopenharmony_ci        v = avio_r8(ioc);
613cabdff1aSopenharmony_ci        if (v != AMF_END_OF_OBJECT) {
614cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Missing AMF_END_OF_OBJECT in AMF_DATA_TYPE_MIXEDARRAY, found %d\n", v);
615cabdff1aSopenharmony_ci            return -1;
616cabdff1aSopenharmony_ci        }
617cabdff1aSopenharmony_ci        break;
618cabdff1aSopenharmony_ci    }
619cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_ARRAY:
620cabdff1aSopenharmony_ci    {
621cabdff1aSopenharmony_ci        unsigned int arraylen, i;
622cabdff1aSopenharmony_ci
623cabdff1aSopenharmony_ci        arraylen = avio_rb32(ioc);
624cabdff1aSopenharmony_ci        for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++)
625cabdff1aSopenharmony_ci            if (amf_parse_object(s, NULL, NULL, NULL, max_pos,
626cabdff1aSopenharmony_ci                                 depth + 1) < 0)
627cabdff1aSopenharmony_ci                return -1;      // if we couldn't skip, bomb out.
628cabdff1aSopenharmony_ci    }
629cabdff1aSopenharmony_ci    break;
630cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_DATE:
631cabdff1aSopenharmony_ci        // timestamp (double) and UTC offset (int16)
632cabdff1aSopenharmony_ci        date.milliseconds = av_int2double(avio_rb64(ioc));
633cabdff1aSopenharmony_ci        date.timezone = avio_rb16(ioc);
634cabdff1aSopenharmony_ci        break;
635cabdff1aSopenharmony_ci    default:                    // unsupported type, we couldn't skip
636cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "unsupported amf type %d\n", amf_type);
637cabdff1aSopenharmony_ci        return -1;
638cabdff1aSopenharmony_ci    }
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci    if (key) {
641cabdff1aSopenharmony_ci        apar = astream ? astream->codecpar : NULL;
642cabdff1aSopenharmony_ci        vpar = vstream ? vstream->codecpar : NULL;
643cabdff1aSopenharmony_ci
644cabdff1aSopenharmony_ci        // stream info doesn't live any deeper than the first object
645cabdff1aSopenharmony_ci        if (depth == 1) {
646cabdff1aSopenharmony_ci            if (amf_type == AMF_DATA_TYPE_NUMBER ||
647cabdff1aSopenharmony_ci                amf_type == AMF_DATA_TYPE_BOOL) {
648cabdff1aSopenharmony_ci                if (!strcmp(key, "duration"))
649cabdff1aSopenharmony_ci                    s->duration = num_val * AV_TIME_BASE;
650cabdff1aSopenharmony_ci                else if (!strcmp(key, "videodatarate") &&
651cabdff1aSopenharmony_ci                         0 <= (int)(num_val * 1024.0))
652cabdff1aSopenharmony_ci                    flv->video_bit_rate = num_val * 1024.0;
653cabdff1aSopenharmony_ci                else if (!strcmp(key, "audiodatarate") &&
654cabdff1aSopenharmony_ci                         0 <= (int)(num_val * 1024.0))
655cabdff1aSopenharmony_ci                    flv->audio_bit_rate = num_val * 1024.0;
656cabdff1aSopenharmony_ci                else if (!strcmp(key, "datastream")) {
657cabdff1aSopenharmony_ci                    AVStream *st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
658cabdff1aSopenharmony_ci                    if (!st)
659cabdff1aSopenharmony_ci                        return AVERROR(ENOMEM);
660cabdff1aSopenharmony_ci                    st->codecpar->codec_id = AV_CODEC_ID_TEXT;
661cabdff1aSopenharmony_ci                } else if (!strcmp(key, "framerate")) {
662cabdff1aSopenharmony_ci                    flv->framerate = av_d2q(num_val, 1000);
663cabdff1aSopenharmony_ci                    if (vstream)
664cabdff1aSopenharmony_ci                        vstream->avg_frame_rate = flv->framerate;
665cabdff1aSopenharmony_ci                } else if (flv->trust_metadata) {
666cabdff1aSopenharmony_ci                    if (!strcmp(key, "videocodecid") && vpar) {
667cabdff1aSopenharmony_ci                        int ret = flv_set_video_codec(s, vstream, num_val, 0);
668cabdff1aSopenharmony_ci                        if (ret < 0)
669cabdff1aSopenharmony_ci                            return ret;
670cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "audiocodecid") && apar) {
671cabdff1aSopenharmony_ci                        int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET;
672cabdff1aSopenharmony_ci                        flv_set_audio_codec(s, astream, apar, id);
673cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "audiosamplerate") && apar) {
674cabdff1aSopenharmony_ci                        apar->sample_rate = num_val;
675cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "audiosamplesize") && apar) {
676cabdff1aSopenharmony_ci                        apar->bits_per_coded_sample = num_val;
677cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "stereo") && apar) {
678cabdff1aSopenharmony_ci                        av_channel_layout_default(&apar->ch_layout, num_val + 1);
679cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "width") && vpar) {
680cabdff1aSopenharmony_ci                        vpar->width = num_val;
681cabdff1aSopenharmony_ci                    } else if (!strcmp(key, "height") && vpar) {
682cabdff1aSopenharmony_ci                        vpar->height = num_val;
683cabdff1aSopenharmony_ci                    }
684cabdff1aSopenharmony_ci                }
685cabdff1aSopenharmony_ci            }
686cabdff1aSopenharmony_ci            if (amf_type == AMF_DATA_TYPE_STRING) {
687cabdff1aSopenharmony_ci                if (!strcmp(key, "encoder")) {
688cabdff1aSopenharmony_ci                    int version = -1;
689cabdff1aSopenharmony_ci                    if (1 == sscanf(str_val, "Open Broadcaster Software v0.%d", &version)) {
690cabdff1aSopenharmony_ci                        if (version > 0 && version <= 655)
691cabdff1aSopenharmony_ci                            flv->broken_sizes = 1;
692cabdff1aSopenharmony_ci                    }
693cabdff1aSopenharmony_ci                } else if (!strcmp(key, "metadatacreator")) {
694cabdff1aSopenharmony_ci                    if (   !strcmp (str_val, "MEGA")
695cabdff1aSopenharmony_ci                        || !strncmp(str_val, "FlixEngine", 10))
696cabdff1aSopenharmony_ci                        flv->broken_sizes = 1;
697cabdff1aSopenharmony_ci                }
698cabdff1aSopenharmony_ci            }
699cabdff1aSopenharmony_ci        }
700cabdff1aSopenharmony_ci
701cabdff1aSopenharmony_ci        if (amf_type == AMF_DATA_TYPE_OBJECT && s->nb_streams == 1 &&
702cabdff1aSopenharmony_ci           ((!apar && !strcmp(key, "audiocodecid")) ||
703cabdff1aSopenharmony_ci            (!vpar && !strcmp(key, "videocodecid"))))
704cabdff1aSopenharmony_ci                s->ctx_flags &= ~AVFMTCTX_NOHEADER; //If there is either audio/video missing, codecid will be an empty object
705cabdff1aSopenharmony_ci
706cabdff1aSopenharmony_ci        if ((!strcmp(key, "duration")        ||
707cabdff1aSopenharmony_ci            !strcmp(key, "filesize")        ||
708cabdff1aSopenharmony_ci            !strcmp(key, "width")           ||
709cabdff1aSopenharmony_ci            !strcmp(key, "height")          ||
710cabdff1aSopenharmony_ci            !strcmp(key, "videodatarate")   ||
711cabdff1aSopenharmony_ci            !strcmp(key, "framerate")       ||
712cabdff1aSopenharmony_ci            !strcmp(key, "videocodecid")    ||
713cabdff1aSopenharmony_ci            !strcmp(key, "audiodatarate")   ||
714cabdff1aSopenharmony_ci            !strcmp(key, "audiosamplerate") ||
715cabdff1aSopenharmony_ci            !strcmp(key, "audiosamplesize") ||
716cabdff1aSopenharmony_ci            !strcmp(key, "stereo")          ||
717cabdff1aSopenharmony_ci            !strcmp(key, "audiocodecid")    ||
718cabdff1aSopenharmony_ci            !strcmp(key, "datastream")) && !flv->dump_full_metadata)
719cabdff1aSopenharmony_ci            return 0;
720cabdff1aSopenharmony_ci
721cabdff1aSopenharmony_ci        s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED;
722cabdff1aSopenharmony_ci        if (amf_type == AMF_DATA_TYPE_BOOL) {
723cabdff1aSopenharmony_ci            av_strlcpy(str_val, num_val > 0 ? "true" : "false",
724cabdff1aSopenharmony_ci                       sizeof(str_val));
725cabdff1aSopenharmony_ci            av_dict_set(&s->metadata, key, str_val, 0);
726cabdff1aSopenharmony_ci        } else if (amf_type == AMF_DATA_TYPE_NUMBER) {
727cabdff1aSopenharmony_ci            snprintf(str_val, sizeof(str_val), "%.f", num_val);
728cabdff1aSopenharmony_ci            av_dict_set(&s->metadata, key, str_val, 0);
729cabdff1aSopenharmony_ci        } else if (amf_type == AMF_DATA_TYPE_STRING) {
730cabdff1aSopenharmony_ci            av_dict_set(&s->metadata, key, str_val, 0);
731cabdff1aSopenharmony_ci        } else if (   amf_type == AMF_DATA_TYPE_DATE
732cabdff1aSopenharmony_ci                   && isfinite(date.milliseconds)
733cabdff1aSopenharmony_ci                   && date.milliseconds > INT64_MIN/1000
734cabdff1aSopenharmony_ci                   && date.milliseconds < INT64_MAX/1000
735cabdff1aSopenharmony_ci                  ) {
736cabdff1aSopenharmony_ci            // timezone is ignored, since there is no easy way to offset the UTC
737cabdff1aSopenharmony_ci            // timestamp into the specified timezone
738cabdff1aSopenharmony_ci            avpriv_dict_set_timestamp(&s->metadata, key, 1000 * (int64_t)date.milliseconds);
739cabdff1aSopenharmony_ci        }
740cabdff1aSopenharmony_ci    }
741cabdff1aSopenharmony_ci
742cabdff1aSopenharmony_ci    return 0;
743cabdff1aSopenharmony_ci}
744cabdff1aSopenharmony_ci
745cabdff1aSopenharmony_ci#define TYPE_ONTEXTDATA 1
746cabdff1aSopenharmony_ci#define TYPE_ONCAPTION 2
747cabdff1aSopenharmony_ci#define TYPE_ONCAPTIONINFO 3
748cabdff1aSopenharmony_ci#define TYPE_UNKNOWN 9
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_cistatic int flv_read_metabody(AVFormatContext *s, int64_t next_pos)
751cabdff1aSopenharmony_ci{
752cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
753cabdff1aSopenharmony_ci    AMFDataType type;
754cabdff1aSopenharmony_ci    AVStream *stream, *astream, *vstream;
755cabdff1aSopenharmony_ci    AVStream av_unused *dstream;
756cabdff1aSopenharmony_ci    AVIOContext *ioc;
757cabdff1aSopenharmony_ci    int i;
758cabdff1aSopenharmony_ci    char buffer[32];
759cabdff1aSopenharmony_ci
760cabdff1aSopenharmony_ci    astream = NULL;
761cabdff1aSopenharmony_ci    vstream = NULL;
762cabdff1aSopenharmony_ci    dstream = NULL;
763cabdff1aSopenharmony_ci    ioc     = s->pb;
764cabdff1aSopenharmony_ci
765cabdff1aSopenharmony_ci    // first object needs to be "onMetaData" string
766cabdff1aSopenharmony_ci    type = avio_r8(ioc);
767cabdff1aSopenharmony_ci    if (type != AMF_DATA_TYPE_STRING ||
768cabdff1aSopenharmony_ci        amf_get_string(ioc, buffer, sizeof(buffer)) < 0)
769cabdff1aSopenharmony_ci        return TYPE_UNKNOWN;
770cabdff1aSopenharmony_ci
771cabdff1aSopenharmony_ci    if (!strcmp(buffer, "onTextData"))
772cabdff1aSopenharmony_ci        return TYPE_ONTEXTDATA;
773cabdff1aSopenharmony_ci
774cabdff1aSopenharmony_ci    if (!strcmp(buffer, "onCaption"))
775cabdff1aSopenharmony_ci        return TYPE_ONCAPTION;
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci    if (!strcmp(buffer, "onCaptionInfo"))
778cabdff1aSopenharmony_ci        return TYPE_ONCAPTIONINFO;
779cabdff1aSopenharmony_ci
780cabdff1aSopenharmony_ci    if (strcmp(buffer, "onMetaData") && strcmp(buffer, "onCuePoint") && strcmp(buffer, "|RtmpSampleAccess")) {
781cabdff1aSopenharmony_ci        av_log(s, AV_LOG_DEBUG, "Unknown type %s\n", buffer);
782cabdff1aSopenharmony_ci        return TYPE_UNKNOWN;
783cabdff1aSopenharmony_ci    }
784cabdff1aSopenharmony_ci
785cabdff1aSopenharmony_ci    // find the streams now so that amf_parse_object doesn't need to do
786cabdff1aSopenharmony_ci    // the lookup every time it is called.
787cabdff1aSopenharmony_ci    for (i = 0; i < s->nb_streams; i++) {
788cabdff1aSopenharmony_ci        stream = s->streams[i];
789cabdff1aSopenharmony_ci        if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
790cabdff1aSopenharmony_ci            vstream = stream;
791cabdff1aSopenharmony_ci            flv->last_keyframe_stream_index = i;
792cabdff1aSopenharmony_ci        } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
793cabdff1aSopenharmony_ci            astream = stream;
794cabdff1aSopenharmony_ci            if (flv->last_keyframe_stream_index == -1)
795cabdff1aSopenharmony_ci                flv->last_keyframe_stream_index = i;
796cabdff1aSopenharmony_ci        } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
797cabdff1aSopenharmony_ci            dstream = stream;
798cabdff1aSopenharmony_ci    }
799cabdff1aSopenharmony_ci
800cabdff1aSopenharmony_ci    // parse the second object (we want a mixed array)
801cabdff1aSopenharmony_ci    if (amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0)
802cabdff1aSopenharmony_ci        return -1;
803cabdff1aSopenharmony_ci
804cabdff1aSopenharmony_ci    return 0;
805cabdff1aSopenharmony_ci}
806cabdff1aSopenharmony_ci
807cabdff1aSopenharmony_cistatic int flv_read_header(AVFormatContext *s)
808cabdff1aSopenharmony_ci{
809cabdff1aSopenharmony_ci    int flags;
810cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
811cabdff1aSopenharmony_ci    int offset;
812cabdff1aSopenharmony_ci    int pre_tag_size = 0;
813cabdff1aSopenharmony_ci
814cabdff1aSopenharmony_ci    /* Actual FLV data at 0xe40000 in KUX file */
815cabdff1aSopenharmony_ci    if(!strcmp(s->iformat->name, "kux"))
816cabdff1aSopenharmony_ci        avio_skip(s->pb, 0xe40000);
817cabdff1aSopenharmony_ci
818cabdff1aSopenharmony_ci    avio_skip(s->pb, 4);
819cabdff1aSopenharmony_ci    flags = avio_r8(s->pb);
820cabdff1aSopenharmony_ci
821cabdff1aSopenharmony_ci    flv->missing_streams = flags & (FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO);
822cabdff1aSopenharmony_ci
823cabdff1aSopenharmony_ci    s->ctx_flags |= AVFMTCTX_NOHEADER;
824cabdff1aSopenharmony_ci
825cabdff1aSopenharmony_ci    offset = avio_rb32(s->pb);
826cabdff1aSopenharmony_ci    avio_seek(s->pb, offset, SEEK_SET);
827cabdff1aSopenharmony_ci
828cabdff1aSopenharmony_ci    /* Annex E. The FLV File Format
829cabdff1aSopenharmony_ci     * E.3 TheFLVFileBody
830cabdff1aSopenharmony_ci     *     Field               Type    Comment
831cabdff1aSopenharmony_ci     *     PreviousTagSize0    UI32    Always 0
832cabdff1aSopenharmony_ci     * */
833cabdff1aSopenharmony_ci    pre_tag_size = avio_rb32(s->pb);
834cabdff1aSopenharmony_ci    if (pre_tag_size) {
835cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING, "Read FLV header error, input file is not a standard flv format, first PreviousTagSize0 always is 0\n");
836cabdff1aSopenharmony_ci    }
837cabdff1aSopenharmony_ci
838cabdff1aSopenharmony_ci    s->start_time = 0;
839cabdff1aSopenharmony_ci    flv->sum_flv_tag_size = 0;
840cabdff1aSopenharmony_ci    flv->last_keyframe_stream_index = -1;
841cabdff1aSopenharmony_ci
842cabdff1aSopenharmony_ci    return 0;
843cabdff1aSopenharmony_ci}
844cabdff1aSopenharmony_ci
845cabdff1aSopenharmony_cistatic int flv_read_close(AVFormatContext *s)
846cabdff1aSopenharmony_ci{
847cabdff1aSopenharmony_ci    int i;
848cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
849cabdff1aSopenharmony_ci    for (i=0; i<FLV_STREAM_TYPE_NB; i++)
850cabdff1aSopenharmony_ci        av_freep(&flv->new_extradata[i]);
851cabdff1aSopenharmony_ci    av_freep(&flv->keyframe_times);
852cabdff1aSopenharmony_ci    av_freep(&flv->keyframe_filepositions);
853cabdff1aSopenharmony_ci    return 0;
854cabdff1aSopenharmony_ci}
855cabdff1aSopenharmony_ci
856cabdff1aSopenharmony_cistatic int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
857cabdff1aSopenharmony_ci{
858cabdff1aSopenharmony_ci    int ret;
859cabdff1aSopenharmony_ci    if (!size)
860cabdff1aSopenharmony_ci        return 0;
861cabdff1aSopenharmony_ci
862cabdff1aSopenharmony_ci    if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
863cabdff1aSopenharmony_ci        return ret;
864cabdff1aSopenharmony_ci    ffstream(st)->need_context_update = 1;
865cabdff1aSopenharmony_ci    return 0;
866cabdff1aSopenharmony_ci}
867cabdff1aSopenharmony_ci
868cabdff1aSopenharmony_cistatic int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
869cabdff1aSopenharmony_ci                               int size)
870cabdff1aSopenharmony_ci{
871cabdff1aSopenharmony_ci    if (!size)
872cabdff1aSopenharmony_ci        return 0;
873cabdff1aSopenharmony_ci
874cabdff1aSopenharmony_ci    av_free(flv->new_extradata[stream]);
875cabdff1aSopenharmony_ci    flv->new_extradata[stream] = av_mallocz(size +
876cabdff1aSopenharmony_ci                                            AV_INPUT_BUFFER_PADDING_SIZE);
877cabdff1aSopenharmony_ci    if (!flv->new_extradata[stream])
878cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
879cabdff1aSopenharmony_ci    flv->new_extradata_size[stream] = size;
880cabdff1aSopenharmony_ci    avio_read(pb, flv->new_extradata[stream], size);
881cabdff1aSopenharmony_ci    return 0;
882cabdff1aSopenharmony_ci}
883cabdff1aSopenharmony_ci
884cabdff1aSopenharmony_cistatic void clear_index_entries(AVFormatContext *s, int64_t pos)
885cabdff1aSopenharmony_ci{
886cabdff1aSopenharmony_ci    av_log(s, AV_LOG_WARNING,
887cabdff1aSopenharmony_ci           "Found invalid index entries, clearing the index.\n");
888cabdff1aSopenharmony_ci    for (unsigned i = 0; i < s->nb_streams; i++) {
889cabdff1aSopenharmony_ci        FFStream *const sti = ffstream(s->streams[i]);
890cabdff1aSopenharmony_ci        int out = 0;
891cabdff1aSopenharmony_ci        /* Remove all index entries that point to >= pos */
892cabdff1aSopenharmony_ci        for (int j = 0; j < sti->nb_index_entries; j++)
893cabdff1aSopenharmony_ci            if (sti->index_entries[j].pos < pos)
894cabdff1aSopenharmony_ci                sti->index_entries[out++] = sti->index_entries[j];
895cabdff1aSopenharmony_ci        sti->nb_index_entries = out;
896cabdff1aSopenharmony_ci    }
897cabdff1aSopenharmony_ci}
898cabdff1aSopenharmony_ci
899cabdff1aSopenharmony_cistatic int amf_skip_tag(AVIOContext *pb, AMFDataType type, int depth)
900cabdff1aSopenharmony_ci{
901cabdff1aSopenharmony_ci    int nb = -1, ret, parse_name = 1;
902cabdff1aSopenharmony_ci
903cabdff1aSopenharmony_ci    if (depth > MAX_DEPTH)
904cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
905cabdff1aSopenharmony_ci
906cabdff1aSopenharmony_ci    if (avio_feof(pb))
907cabdff1aSopenharmony_ci        return AVERROR_EOF;
908cabdff1aSopenharmony_ci
909cabdff1aSopenharmony_ci    switch (type) {
910cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_NUMBER:
911cabdff1aSopenharmony_ci        avio_skip(pb, 8);
912cabdff1aSopenharmony_ci        break;
913cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_BOOL:
914cabdff1aSopenharmony_ci        avio_skip(pb, 1);
915cabdff1aSopenharmony_ci        break;
916cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_STRING:
917cabdff1aSopenharmony_ci        avio_skip(pb, avio_rb16(pb));
918cabdff1aSopenharmony_ci        break;
919cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_ARRAY:
920cabdff1aSopenharmony_ci        parse_name = 0;
921cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_MIXEDARRAY:
922cabdff1aSopenharmony_ci        nb = avio_rb32(pb);
923cabdff1aSopenharmony_ci        if (nb < 0)
924cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
925cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_OBJECT:
926cabdff1aSopenharmony_ci        while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) {
927cabdff1aSopenharmony_ci            if (parse_name) {
928cabdff1aSopenharmony_ci                int size = avio_rb16(pb);
929cabdff1aSopenharmony_ci                if (!size) {
930cabdff1aSopenharmony_ci                    avio_skip(pb, 1);
931cabdff1aSopenharmony_ci                    break;
932cabdff1aSopenharmony_ci                }
933cabdff1aSopenharmony_ci                avio_skip(pb, size);
934cabdff1aSopenharmony_ci            }
935cabdff1aSopenharmony_ci            if ((ret = amf_skip_tag(pb, avio_r8(pb), depth + 1)) < 0)
936cabdff1aSopenharmony_ci                return ret;
937cabdff1aSopenharmony_ci        }
938cabdff1aSopenharmony_ci        break;
939cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_NULL:
940cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_OBJECT_END:
941cabdff1aSopenharmony_ci        break;
942cabdff1aSopenharmony_ci    default:
943cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
944cabdff1aSopenharmony_ci    }
945cabdff1aSopenharmony_ci    return 0;
946cabdff1aSopenharmony_ci}
947cabdff1aSopenharmony_ci
948cabdff1aSopenharmony_cistatic int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
949cabdff1aSopenharmony_ci                           int64_t dts, int64_t next)
950cabdff1aSopenharmony_ci{
951cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
952cabdff1aSopenharmony_ci    AVStream *st    = NULL;
953cabdff1aSopenharmony_ci    char buf[20];
954cabdff1aSopenharmony_ci    int ret = AVERROR_INVALIDDATA;
955cabdff1aSopenharmony_ci    int i, length = -1;
956cabdff1aSopenharmony_ci    int array = 0;
957cabdff1aSopenharmony_ci
958cabdff1aSopenharmony_ci    switch (avio_r8(pb)) {
959cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_ARRAY:
960cabdff1aSopenharmony_ci        array = 1;
961cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_MIXEDARRAY:
962cabdff1aSopenharmony_ci        avio_seek(pb, 4, SEEK_CUR);
963cabdff1aSopenharmony_ci    case AMF_DATA_TYPE_OBJECT:
964cabdff1aSopenharmony_ci        break;
965cabdff1aSopenharmony_ci    default:
966cabdff1aSopenharmony_ci        goto skip;
967cabdff1aSopenharmony_ci    }
968cabdff1aSopenharmony_ci
969cabdff1aSopenharmony_ci    while (array || (ret = amf_get_string(pb, buf, sizeof(buf))) > 0) {
970cabdff1aSopenharmony_ci        AMFDataType type = avio_r8(pb);
971cabdff1aSopenharmony_ci        if (type == AMF_DATA_TYPE_STRING && (array || !strcmp(buf, "text"))) {
972cabdff1aSopenharmony_ci            length = avio_rb16(pb);
973cabdff1aSopenharmony_ci            ret    = av_get_packet(pb, pkt, length);
974cabdff1aSopenharmony_ci            if (ret < 0)
975cabdff1aSopenharmony_ci                goto skip;
976cabdff1aSopenharmony_ci            else
977cabdff1aSopenharmony_ci                break;
978cabdff1aSopenharmony_ci        } else {
979cabdff1aSopenharmony_ci            if ((ret = amf_skip_tag(pb, type, 0)) < 0)
980cabdff1aSopenharmony_ci                goto skip;
981cabdff1aSopenharmony_ci        }
982cabdff1aSopenharmony_ci    }
983cabdff1aSopenharmony_ci
984cabdff1aSopenharmony_ci    if (length < 0) {
985cabdff1aSopenharmony_ci        ret = AVERROR_INVALIDDATA;
986cabdff1aSopenharmony_ci        goto skip;
987cabdff1aSopenharmony_ci    }
988cabdff1aSopenharmony_ci
989cabdff1aSopenharmony_ci    for (i = 0; i < s->nb_streams; i++) {
990cabdff1aSopenharmony_ci        st = s->streams[i];
991cabdff1aSopenharmony_ci        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
992cabdff1aSopenharmony_ci            break;
993cabdff1aSopenharmony_ci    }
994cabdff1aSopenharmony_ci
995cabdff1aSopenharmony_ci    if (i == s->nb_streams) {
996cabdff1aSopenharmony_ci        st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
997cabdff1aSopenharmony_ci        if (!st)
998cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
999cabdff1aSopenharmony_ci        st->codecpar->codec_id = AV_CODEC_ID_TEXT;
1000cabdff1aSopenharmony_ci    }
1001cabdff1aSopenharmony_ci
1002cabdff1aSopenharmony_ci    pkt->dts  = dts;
1003cabdff1aSopenharmony_ci    pkt->pts  = dts;
1004cabdff1aSopenharmony_ci    pkt->size = ret;
1005cabdff1aSopenharmony_ci
1006cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
1007cabdff1aSopenharmony_ci    pkt->flags       |= AV_PKT_FLAG_KEY;
1008cabdff1aSopenharmony_ci
1009cabdff1aSopenharmony_ciskip:
1010cabdff1aSopenharmony_ci    avio_seek(s->pb, next + 4, SEEK_SET);
1011cabdff1aSopenharmony_ci
1012cabdff1aSopenharmony_ci    return ret;
1013cabdff1aSopenharmony_ci}
1014cabdff1aSopenharmony_ci
1015cabdff1aSopenharmony_cistatic int resync(AVFormatContext *s)
1016cabdff1aSopenharmony_ci{
1017cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
1018cabdff1aSopenharmony_ci    int64_t i;
1019cabdff1aSopenharmony_ci    int64_t pos = avio_tell(s->pb);
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_ci    for (i=0; !avio_feof(s->pb); i++) {
1022cabdff1aSopenharmony_ci        int j  = i & (RESYNC_BUFFER_SIZE-1);
1023cabdff1aSopenharmony_ci        int j1 = j + RESYNC_BUFFER_SIZE;
1024cabdff1aSopenharmony_ci        flv->resync_buffer[j ] =
1025cabdff1aSopenharmony_ci        flv->resync_buffer[j1] = avio_r8(s->pb);
1026cabdff1aSopenharmony_ci
1027cabdff1aSopenharmony_ci        if (i >= 8 && pos) {
1028cabdff1aSopenharmony_ci            uint8_t *d = flv->resync_buffer + j1 - 8;
1029cabdff1aSopenharmony_ci            if (d[0] == 'F' &&
1030cabdff1aSopenharmony_ci                d[1] == 'L' &&
1031cabdff1aSopenharmony_ci                d[2] == 'V' &&
1032cabdff1aSopenharmony_ci                d[3] < 5 && d[5] == 0) {
1033cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING, "Concatenated FLV detected, might fail to demux, decode and seek %"PRId64"\n", flv->last_ts);
1034cabdff1aSopenharmony_ci                flv->time_offset = flv->last_ts + 1;
1035cabdff1aSopenharmony_ci                flv->time_pos    = avio_tell(s->pb);
1036cabdff1aSopenharmony_ci            }
1037cabdff1aSopenharmony_ci        }
1038cabdff1aSopenharmony_ci
1039cabdff1aSopenharmony_ci        if (i > 22) {
1040cabdff1aSopenharmony_ci            unsigned lsize2 = AV_RB32(flv->resync_buffer + j1 - 4);
1041cabdff1aSopenharmony_ci            if (lsize2 >= 11 && lsize2 + 8LL < FFMIN(i, RESYNC_BUFFER_SIZE)) {
1042cabdff1aSopenharmony_ci                unsigned  size2 = AV_RB24(flv->resync_buffer + j1 - lsize2 + 1 - 4);
1043cabdff1aSopenharmony_ci                unsigned lsize1 = AV_RB32(flv->resync_buffer + j1 - lsize2 - 8);
1044cabdff1aSopenharmony_ci                if (lsize1 >= 11 && lsize1 + 8LL + lsize2 < FFMIN(i, RESYNC_BUFFER_SIZE)) {
1045cabdff1aSopenharmony_ci                    unsigned  size1 = AV_RB24(flv->resync_buffer + j1 - lsize1 + 1 - lsize2 - 8);
1046cabdff1aSopenharmony_ci                    if (size1 == lsize1 - 11 && size2  == lsize2 - 11) {
1047cabdff1aSopenharmony_ci                        avio_seek(s->pb, pos + i - lsize1 - lsize2 - 8, SEEK_SET);
1048cabdff1aSopenharmony_ci                        return 1;
1049cabdff1aSopenharmony_ci                    }
1050cabdff1aSopenharmony_ci                }
1051cabdff1aSopenharmony_ci            }
1052cabdff1aSopenharmony_ci        }
1053cabdff1aSopenharmony_ci    }
1054cabdff1aSopenharmony_ci    return AVERROR_EOF;
1055cabdff1aSopenharmony_ci}
1056cabdff1aSopenharmony_ci
1057cabdff1aSopenharmony_cistatic int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
1058cabdff1aSopenharmony_ci{
1059cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
1060cabdff1aSopenharmony_ci    int ret, i, size, flags;
1061cabdff1aSopenharmony_ci    enum FlvTagType type;
1062cabdff1aSopenharmony_ci    int stream_type=-1;
1063cabdff1aSopenharmony_ci    int64_t next, pos, meta_pos;
1064cabdff1aSopenharmony_ci    int64_t dts, pts = AV_NOPTS_VALUE;
1065cabdff1aSopenharmony_ci    int av_uninit(channels);
1066cabdff1aSopenharmony_ci    int av_uninit(sample_rate);
1067cabdff1aSopenharmony_ci    AVStream *st    = NULL;
1068cabdff1aSopenharmony_ci    int last = -1;
1069cabdff1aSopenharmony_ci    int orig_size;
1070cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1071cabdff1aSopenharmony_ci    uint32_t video_codec_id = 0;
1072cabdff1aSopenharmony_ci    int enhanced_flv = 0;
1073cabdff1aSopenharmony_ci#endif
1074cabdff1aSopenharmony_ci
1075cabdff1aSopenharmony_ciretry:
1076cabdff1aSopenharmony_ci    /* pkt size is repeated at end. skip it */
1077cabdff1aSopenharmony_ci    pos  = avio_tell(s->pb);
1078cabdff1aSopenharmony_ci    type = (avio_r8(s->pb) & 0x1F);
1079cabdff1aSopenharmony_ci    orig_size =
1080cabdff1aSopenharmony_ci    size = avio_rb24(s->pb);
1081cabdff1aSopenharmony_ci    flv->sum_flv_tag_size += size + 11LL;
1082cabdff1aSopenharmony_ci    dts  = avio_rb24(s->pb);
1083cabdff1aSopenharmony_ci    dts |= (unsigned)avio_r8(s->pb) << 24;
1084cabdff1aSopenharmony_ci    av_log(s, AV_LOG_TRACE, "type:%d, size:%d, last:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, last, dts, avio_tell(s->pb));
1085cabdff1aSopenharmony_ci    if (avio_feof(s->pb))
1086cabdff1aSopenharmony_ci        return AVERROR_EOF;
1087cabdff1aSopenharmony_ci    avio_skip(s->pb, 3); /* stream id, always 0 */
1088cabdff1aSopenharmony_ci    flags = 0;
1089cabdff1aSopenharmony_ci
1090cabdff1aSopenharmony_ci    if (flv->validate_next < flv->validate_count) {
1091cabdff1aSopenharmony_ci        int64_t validate_pos = flv->validate_index[flv->validate_next].pos;
1092cabdff1aSopenharmony_ci        if (pos == validate_pos) {
1093cabdff1aSopenharmony_ci            if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <=
1094cabdff1aSopenharmony_ci                VALIDATE_INDEX_TS_THRESH) {
1095cabdff1aSopenharmony_ci                flv->validate_next++;
1096cabdff1aSopenharmony_ci            } else {
1097cabdff1aSopenharmony_ci                clear_index_entries(s, validate_pos);
1098cabdff1aSopenharmony_ci                flv->validate_count = 0;
1099cabdff1aSopenharmony_ci            }
1100cabdff1aSopenharmony_ci        } else if (pos > validate_pos) {
1101cabdff1aSopenharmony_ci            clear_index_entries(s, validate_pos);
1102cabdff1aSopenharmony_ci            flv->validate_count = 0;
1103cabdff1aSopenharmony_ci        }
1104cabdff1aSopenharmony_ci    }
1105cabdff1aSopenharmony_ci
1106cabdff1aSopenharmony_ci    if (size == 0) {
1107cabdff1aSopenharmony_ci        ret = FFERROR_REDO;
1108cabdff1aSopenharmony_ci        goto leave;
1109cabdff1aSopenharmony_ci    }
1110cabdff1aSopenharmony_ci
1111cabdff1aSopenharmony_ci    next = size + avio_tell(s->pb);
1112cabdff1aSopenharmony_ci
1113cabdff1aSopenharmony_ci    if (type == FLV_TAG_TYPE_AUDIO) {
1114cabdff1aSopenharmony_ci        stream_type = FLV_STREAM_TYPE_AUDIO;
1115cabdff1aSopenharmony_ci        flags    = avio_r8(s->pb);
1116cabdff1aSopenharmony_ci        size--;
1117cabdff1aSopenharmony_ci    } else if (type == FLV_TAG_TYPE_VIDEO) {
1118cabdff1aSopenharmony_ci        stream_type = FLV_STREAM_TYPE_VIDEO;
1119cabdff1aSopenharmony_ci        flags    = avio_r8(s->pb);
1120cabdff1aSopenharmony_ci        size--;
1121cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1122cabdff1aSopenharmony_ci        video_codec_id = flags & FLV_VIDEO_CODECID_MASK;
1123cabdff1aSopenharmony_ci        enhanced_flv = (flags >> 7) & 1;
1124cabdff1aSopenharmony_ci        if (enhanced_flv) {
1125cabdff1aSopenharmony_ci            video_codec_id = avio_rb32(s->pb);
1126cabdff1aSopenharmony_ci            size -= 4;
1127cabdff1aSopenharmony_ci        }
1128cabdff1aSopenharmony_ci#endif
1129cabdff1aSopenharmony_ci        if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD)
1130cabdff1aSopenharmony_ci            goto skip;
1131cabdff1aSopenharmony_ci    } else if (type == FLV_TAG_TYPE_META) {
1132cabdff1aSopenharmony_ci        stream_type=FLV_STREAM_TYPE_SUBTITLE;
1133cabdff1aSopenharmony_ci        if (size > 13 + 1 + 4) { // Header-type metadata stuff
1134cabdff1aSopenharmony_ci            int type;
1135cabdff1aSopenharmony_ci            meta_pos = avio_tell(s->pb);
1136cabdff1aSopenharmony_ci            type = flv_read_metabody(s, next);
1137cabdff1aSopenharmony_ci            if (type == 0 && dts == 0 || type < 0) {
1138cabdff1aSopenharmony_ci                if (type < 0 && flv->validate_count &&
1139cabdff1aSopenharmony_ci                    flv->validate_index[0].pos     > next &&
1140cabdff1aSopenharmony_ci                    flv->validate_index[0].pos - 4 < next) {
1141cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_WARNING, "Adjusting next position due to index mismatch\n");
1142cabdff1aSopenharmony_ci                    next = flv->validate_index[0].pos - 4;
1143cabdff1aSopenharmony_ci                }
1144cabdff1aSopenharmony_ci                goto skip;
1145cabdff1aSopenharmony_ci            } else if (type == TYPE_ONTEXTDATA) {
1146cabdff1aSopenharmony_ci                avpriv_request_sample(s, "OnTextData packet");
1147cabdff1aSopenharmony_ci                return flv_data_packet(s, pkt, dts, next);
1148cabdff1aSopenharmony_ci            } else if (type == TYPE_ONCAPTION) {
1149cabdff1aSopenharmony_ci                return flv_data_packet(s, pkt, dts, next);
1150cabdff1aSopenharmony_ci            } else if (type == TYPE_UNKNOWN) {
1151cabdff1aSopenharmony_ci                stream_type = FLV_STREAM_TYPE_DATA;
1152cabdff1aSopenharmony_ci            }
1153cabdff1aSopenharmony_ci            avio_seek(s->pb, meta_pos, SEEK_SET);
1154cabdff1aSopenharmony_ci        }
1155cabdff1aSopenharmony_ci    } else {
1156cabdff1aSopenharmony_ci        av_log(s, AV_LOG_DEBUG,
1157cabdff1aSopenharmony_ci               "Skipping flv packet: type %d, size %d, flags %d.\n",
1158cabdff1aSopenharmony_ci               type, size, flags);
1159cabdff1aSopenharmony_ciskip:
1160cabdff1aSopenharmony_ci        if (avio_seek(s->pb, next, SEEK_SET) != next) {
1161cabdff1aSopenharmony_ci            // This can happen if flv_read_metabody above read past
1162cabdff1aSopenharmony_ci            // next, on a non-seekable input, and the preceding data has
1163cabdff1aSopenharmony_ci            // been flushed out from the IO buffer.
1164cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");
1165cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1166cabdff1aSopenharmony_ci        }
1167cabdff1aSopenharmony_ci        ret = FFERROR_REDO;
1168cabdff1aSopenharmony_ci        goto leave;
1169cabdff1aSopenharmony_ci    }
1170cabdff1aSopenharmony_ci
1171cabdff1aSopenharmony_ci    /* skip empty data packets */
1172cabdff1aSopenharmony_ci    if (!size) {
1173cabdff1aSopenharmony_ci        ret = FFERROR_REDO;
1174cabdff1aSopenharmony_ci        goto leave;
1175cabdff1aSopenharmony_ci    }
1176cabdff1aSopenharmony_ci
1177cabdff1aSopenharmony_ci    /* now find stream */
1178cabdff1aSopenharmony_ci    for (i = 0; i < s->nb_streams; i++) {
1179cabdff1aSopenharmony_ci        st = s->streams[i];
1180cabdff1aSopenharmony_ci        if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1181cabdff1aSopenharmony_ci            if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
1182cabdff1aSopenharmony_ci                (s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags)))
1183cabdff1aSopenharmony_ci                break;
1184cabdff1aSopenharmony_ci        } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1185cabdff1aSopenharmony_ci            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1186cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1187cabdff1aSopenharmony_ci                (s->video_codec_id || flv_same_video_codec(st->codecpar, video_codec_id))
1188cabdff1aSopenharmony_ci#else
1189cabdff1aSopenharmony_ci                (s->video_codec_id || flv_same_video_codec(st->codecpar, flags))
1190cabdff1aSopenharmony_ci#endif
1191cabdff1aSopenharmony_ci            )
1192cabdff1aSopenharmony_ci                break;
1193cabdff1aSopenharmony_ci        } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
1194cabdff1aSopenharmony_ci            if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
1195cabdff1aSopenharmony_ci                break;
1196cabdff1aSopenharmony_ci        } else if (stream_type == FLV_STREAM_TYPE_DATA) {
1197cabdff1aSopenharmony_ci            if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
1198cabdff1aSopenharmony_ci                break;
1199cabdff1aSopenharmony_ci        }
1200cabdff1aSopenharmony_ci    }
1201cabdff1aSopenharmony_ci    if (i == s->nb_streams) {
1202cabdff1aSopenharmony_ci        static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE, AVMEDIA_TYPE_DATA};
1203cabdff1aSopenharmony_ci        st = create_stream(s, stream_types[stream_type]);
1204cabdff1aSopenharmony_ci        if (!st)
1205cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1206cabdff1aSopenharmony_ci    }
1207cabdff1aSopenharmony_ci    av_log(s, AV_LOG_TRACE, "%d %X %d \n", stream_type, flags, st->discard);
1208cabdff1aSopenharmony_ci
1209cabdff1aSopenharmony_ci    if (flv->time_pos <= pos) {
1210cabdff1aSopenharmony_ci        dts += flv->time_offset;
1211cabdff1aSopenharmony_ci    }
1212cabdff1aSopenharmony_ci
1213cabdff1aSopenharmony_ci    if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
1214cabdff1aSopenharmony_ci        ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||
1215cabdff1aSopenharmony_ci         stream_type == FLV_STREAM_TYPE_AUDIO))
1216cabdff1aSopenharmony_ci        av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME);
1217cabdff1aSopenharmony_ci
1218cabdff1aSopenharmony_ci    if ((st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO)) ||
1219cabdff1aSopenharmony_ci        (st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && stream_type == FLV_STREAM_TYPE_VIDEO)) ||
1220cabdff1aSopenharmony_ci         st->discard >= AVDISCARD_ALL) {
1221cabdff1aSopenharmony_ci        avio_seek(s->pb, next, SEEK_SET);
1222cabdff1aSopenharmony_ci        ret = FFERROR_REDO;
1223cabdff1aSopenharmony_ci        goto leave;
1224cabdff1aSopenharmony_ci    }
1225cabdff1aSopenharmony_ci
1226cabdff1aSopenharmony_ci    // if not streamed and no duration from metadata then seek to end to find
1227cabdff1aSopenharmony_ci    // the duration from the timestamps
1228cabdff1aSopenharmony_ci    if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) &&
1229cabdff1aSopenharmony_ci        (!s->duration || s->duration == AV_NOPTS_VALUE) &&
1230cabdff1aSopenharmony_ci        !flv->searched_for_end) {
1231cabdff1aSopenharmony_ci        int size;
1232cabdff1aSopenharmony_ci        const int64_t pos   = avio_tell(s->pb);
1233cabdff1aSopenharmony_ci        // Read the last 4 bytes of the file, this should be the size of the
1234cabdff1aSopenharmony_ci        // previous FLV tag. Use the timestamp of its payload as duration.
1235cabdff1aSopenharmony_ci        int64_t fsize       = avio_size(s->pb);
1236cabdff1aSopenharmony_ciretry_duration:
1237cabdff1aSopenharmony_ci        avio_seek(s->pb, fsize - 4, SEEK_SET);
1238cabdff1aSopenharmony_ci        size = avio_rb32(s->pb);
1239cabdff1aSopenharmony_ci        if (size > 0 && size < fsize) {
1240cabdff1aSopenharmony_ci            // Seek to the start of the last FLV tag at position (fsize - 4 - size)
1241cabdff1aSopenharmony_ci            // but skip the byte indicating the type.
1242cabdff1aSopenharmony_ci            avio_seek(s->pb, fsize - 3 - size, SEEK_SET);
1243cabdff1aSopenharmony_ci            if (size == avio_rb24(s->pb) + 11) {
1244cabdff1aSopenharmony_ci                uint32_t ts = avio_rb24(s->pb);
1245cabdff1aSopenharmony_ci                ts         |= (unsigned)avio_r8(s->pb) << 24;
1246cabdff1aSopenharmony_ci                if (ts)
1247cabdff1aSopenharmony_ci                    s->duration = ts * (int64_t)AV_TIME_BASE / 1000;
1248cabdff1aSopenharmony_ci                else if (fsize >= 8 && fsize - 8 >= size) {
1249cabdff1aSopenharmony_ci                    fsize -= size+4;
1250cabdff1aSopenharmony_ci                    goto retry_duration;
1251cabdff1aSopenharmony_ci                }
1252cabdff1aSopenharmony_ci            }
1253cabdff1aSopenharmony_ci        }
1254cabdff1aSopenharmony_ci
1255cabdff1aSopenharmony_ci        avio_seek(s->pb, pos, SEEK_SET);
1256cabdff1aSopenharmony_ci        flv->searched_for_end = 1;
1257cabdff1aSopenharmony_ci    }
1258cabdff1aSopenharmony_ci
1259cabdff1aSopenharmony_ci    if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1260cabdff1aSopenharmony_ci        int bits_per_coded_sample;
1261cabdff1aSopenharmony_ci        channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
1262cabdff1aSopenharmony_ci        sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
1263cabdff1aSopenharmony_ci                                FLV_AUDIO_SAMPLERATE_OFFSET) >> 3;
1264cabdff1aSopenharmony_ci        bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
1265cabdff1aSopenharmony_ci        if (!av_channel_layout_check(&st->codecpar->ch_layout) ||
1266cabdff1aSopenharmony_ci            !st->codecpar->sample_rate ||
1267cabdff1aSopenharmony_ci            !st->codecpar->bits_per_coded_sample) {
1268cabdff1aSopenharmony_ci            av_channel_layout_default(&st->codecpar->ch_layout, channels);
1269cabdff1aSopenharmony_ci            st->codecpar->sample_rate           = sample_rate;
1270cabdff1aSopenharmony_ci            st->codecpar->bits_per_coded_sample = bits_per_coded_sample;
1271cabdff1aSopenharmony_ci        }
1272cabdff1aSopenharmony_ci        if (!st->codecpar->codec_id) {
1273cabdff1aSopenharmony_ci            flv_set_audio_codec(s, st, st->codecpar,
1274cabdff1aSopenharmony_ci                                flags & FLV_AUDIO_CODECID_MASK);
1275cabdff1aSopenharmony_ci            flv->last_sample_rate =
1276cabdff1aSopenharmony_ci            sample_rate           = st->codecpar->sample_rate;
1277cabdff1aSopenharmony_ci            flv->last_channels    =
1278cabdff1aSopenharmony_ci            channels              = st->codecpar->ch_layout.nb_channels;
1279cabdff1aSopenharmony_ci        } else {
1280cabdff1aSopenharmony_ci            AVCodecParameters *par = avcodec_parameters_alloc();
1281cabdff1aSopenharmony_ci            if (!par) {
1282cabdff1aSopenharmony_ci                ret = AVERROR(ENOMEM);
1283cabdff1aSopenharmony_ci                goto leave;
1284cabdff1aSopenharmony_ci            }
1285cabdff1aSopenharmony_ci            par->sample_rate = sample_rate;
1286cabdff1aSopenharmony_ci            par->bits_per_coded_sample = bits_per_coded_sample;
1287cabdff1aSopenharmony_ci            flv_set_audio_codec(s, st, par, flags & FLV_AUDIO_CODECID_MASK);
1288cabdff1aSopenharmony_ci            sample_rate = par->sample_rate;
1289cabdff1aSopenharmony_ci            avcodec_parameters_free(&par);
1290cabdff1aSopenharmony_ci        }
1291cabdff1aSopenharmony_ci    } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1292cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1293cabdff1aSopenharmony_ci        int ret = flv_set_video_codec(s, st, video_codec_id, 1);
1294cabdff1aSopenharmony_ci#else
1295cabdff1aSopenharmony_ci        int ret = flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1);
1296cabdff1aSopenharmony_ci#endif
1297cabdff1aSopenharmony_ci        if (ret < 0)
1298cabdff1aSopenharmony_ci            return ret;
1299cabdff1aSopenharmony_ci        size -= ret;
1300cabdff1aSopenharmony_ci    } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
1301cabdff1aSopenharmony_ci        st->codecpar->codec_id = AV_CODEC_ID_TEXT;
1302cabdff1aSopenharmony_ci    } else if (stream_type == FLV_STREAM_TYPE_DATA) {
1303cabdff1aSopenharmony_ci        st->codecpar->codec_id = AV_CODEC_ID_NONE; // Opaque AMF data
1304cabdff1aSopenharmony_ci    }
1305cabdff1aSopenharmony_ci
1306cabdff1aSopenharmony_ci    if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1307cabdff1aSopenharmony_ci        st->codecpar->codec_id == AV_CODEC_ID_H264 ||
1308cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1309cabdff1aSopenharmony_ci        st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
1310cabdff1aSopenharmony_ci        st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
1311cabdff1aSopenharmony_ci        int type = 0;
1312cabdff1aSopenharmony_ci        if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO) {
1313cabdff1aSopenharmony_ci            type = flags & 0x0F;
1314cabdff1aSopenharmony_ci        } else {
1315cabdff1aSopenharmony_ci            type = avio_r8(s->pb);
1316cabdff1aSopenharmony_ci            size--;
1317cabdff1aSopenharmony_ci        }
1318cabdff1aSopenharmony_ci#else
1319cabdff1aSopenharmony_ci        st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
1320cabdff1aSopenharmony_ci        int type = avio_r8(s->pb);
1321cabdff1aSopenharmony_ci        size--;
1322cabdff1aSopenharmony_ci#endif
1323cabdff1aSopenharmony_ci        if (size < 0) {
1324cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
1325cabdff1aSopenharmony_ci            goto leave;
1326cabdff1aSopenharmony_ci        }
1327cabdff1aSopenharmony_ci
1328cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1329cabdff1aSopenharmony_ci        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
1330cabdff1aSopenharmony_ci            (enhanced_flv && st->codecpar->codec_id == AV_CODEC_ID_HEVC && type == PacketTypeCodedFrames) ||
1331cabdff1aSopenharmony_ci            video_codec_id == FLV_CODECID_HEVC) {
1332cabdff1aSopenharmony_ci#else
1333cabdff1aSopenharmony_ci        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
1334cabdff1aSopenharmony_ci#endif
1335cabdff1aSopenharmony_ci            // sign extension
1336cabdff1aSopenharmony_ci            int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
1337cabdff1aSopenharmony_ci            pts = av_sat_add64(dts, cts);
1338cabdff1aSopenharmony_ci            if (cts < 0) { // dts might be wrong
1339cabdff1aSopenharmony_ci                if (!flv->wrong_dts)
1340cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_WARNING,
1341cabdff1aSopenharmony_ci                        "Negative cts, previous timestamps might be wrong.\n");
1342cabdff1aSopenharmony_ci                flv->wrong_dts = 1;
1343cabdff1aSopenharmony_ci            } else if (FFABS(dts - pts) > 1000*60*15) {
1344cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING,
1345cabdff1aSopenharmony_ci                       "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
1346cabdff1aSopenharmony_ci                dts = pts = AV_NOPTS_VALUE;
1347cabdff1aSopenharmony_ci            }
1348cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1349cabdff1aSopenharmony_ci            size -= 3;
1350cabdff1aSopenharmony_ci#endif
1351cabdff1aSopenharmony_ci        }
1352cabdff1aSopenharmony_ci        if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1353cabdff1aSopenharmony_ci#ifdef OHOS_H265_DEMUXER
1354cabdff1aSopenharmony_ci            st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
1355cabdff1aSopenharmony_ci#else
1356cabdff1aSopenharmony_ci            st->codecpar->codec_id == AV_CODEC_ID_H264)) {
1357cabdff1aSopenharmony_ci#endif
1358cabdff1aSopenharmony_ci            AVDictionaryEntry *t;
1359cabdff1aSopenharmony_ci
1360cabdff1aSopenharmony_ci            if (st->codecpar->extradata) {
1361cabdff1aSopenharmony_ci                if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
1362cabdff1aSopenharmony_ci                    return ret;
1363cabdff1aSopenharmony_ci                ret = FFERROR_REDO;
1364cabdff1aSopenharmony_ci                goto leave;
1365cabdff1aSopenharmony_ci            }
1366cabdff1aSopenharmony_ci            if ((ret = flv_get_extradata(s, st, size)) < 0)
1367cabdff1aSopenharmony_ci                return ret;
1368cabdff1aSopenharmony_ci
1369cabdff1aSopenharmony_ci            /* Workaround for buggy Omnia A/XE encoder */
1370cabdff1aSopenharmony_ci            t = av_dict_get(s->metadata, "Encoder", NULL, 0);
1371cabdff1aSopenharmony_ci            if (st->codecpar->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE"))
1372cabdff1aSopenharmony_ci                st->codecpar->extradata_size = 2;
1373cabdff1aSopenharmony_ci
1374cabdff1aSopenharmony_ci            ret = FFERROR_REDO;
1375cabdff1aSopenharmony_ci            goto leave;
1376cabdff1aSopenharmony_ci        }
1377cabdff1aSopenharmony_ci    }
1378cabdff1aSopenharmony_ci
1379cabdff1aSopenharmony_ci    /* skip empty data packets */
1380cabdff1aSopenharmony_ci    if (!size) {
1381cabdff1aSopenharmony_ci        ret = FFERROR_REDO;
1382cabdff1aSopenharmony_ci        goto leave;
1383cabdff1aSopenharmony_ci    }
1384cabdff1aSopenharmony_ci
1385cabdff1aSopenharmony_ci    ret = av_get_packet(s->pb, pkt, size);
1386cabdff1aSopenharmony_ci    if (ret < 0)
1387cabdff1aSopenharmony_ci        return ret;
1388cabdff1aSopenharmony_ci    pkt->dts          = dts;
1389cabdff1aSopenharmony_ci    pkt->pts          = pts == AV_NOPTS_VALUE ? dts : pts;
1390cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
1391cabdff1aSopenharmony_ci    pkt->pos          = pos;
1392cabdff1aSopenharmony_ci    if (flv->new_extradata[stream_type]) {
1393cabdff1aSopenharmony_ci        int ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
1394cabdff1aSopenharmony_ci                                          flv->new_extradata[stream_type],
1395cabdff1aSopenharmony_ci                                          flv->new_extradata_size[stream_type]);
1396cabdff1aSopenharmony_ci        if (ret >= 0) {
1397cabdff1aSopenharmony_ci            flv->new_extradata[stream_type]      = NULL;
1398cabdff1aSopenharmony_ci            flv->new_extradata_size[stream_type] = 0;
1399cabdff1aSopenharmony_ci        }
1400cabdff1aSopenharmony_ci    }
1401cabdff1aSopenharmony_ci    if (stream_type == FLV_STREAM_TYPE_AUDIO &&
1402cabdff1aSopenharmony_ci                    (sample_rate != flv->last_sample_rate ||
1403cabdff1aSopenharmony_ci                     channels    != flv->last_channels)) {
1404cabdff1aSopenharmony_ci        flv->last_sample_rate = sample_rate;
1405cabdff1aSopenharmony_ci        flv->last_channels    = channels;
1406cabdff1aSopenharmony_ci        ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0);
1407cabdff1aSopenharmony_ci    }
1408cabdff1aSopenharmony_ci
1409cabdff1aSopenharmony_ci    if (stream_type == FLV_STREAM_TYPE_AUDIO ||
1410cabdff1aSopenharmony_ci        (flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ||
1411cabdff1aSopenharmony_ci        stream_type == FLV_STREAM_TYPE_SUBTITLE ||
1412cabdff1aSopenharmony_ci        stream_type == FLV_STREAM_TYPE_DATA)
1413cabdff1aSopenharmony_ci        pkt->flags |= AV_PKT_FLAG_KEY;
1414cabdff1aSopenharmony_ci
1415cabdff1aSopenharmony_cileave:
1416cabdff1aSopenharmony_ci    last = avio_rb32(s->pb);
1417cabdff1aSopenharmony_ci    if (!flv->trust_datasize) {
1418cabdff1aSopenharmony_ci        if (last != orig_size + 11 && last != orig_size + 10 &&
1419cabdff1aSopenharmony_ci            !avio_feof(s->pb) &&
1420cabdff1aSopenharmony_ci            (last != orig_size || !last) && last != flv->sum_flv_tag_size &&
1421cabdff1aSopenharmony_ci            !flv->broken_sizes) {
1422cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Packet mismatch %d %d %"PRId64"\n", last, orig_size + 11, flv->sum_flv_tag_size);
1423cabdff1aSopenharmony_ci            avio_seek(s->pb, pos + 1, SEEK_SET);
1424cabdff1aSopenharmony_ci            ret = resync(s);
1425cabdff1aSopenharmony_ci            av_packet_unref(pkt);
1426cabdff1aSopenharmony_ci            if (ret >= 0) {
1427cabdff1aSopenharmony_ci                goto retry;
1428cabdff1aSopenharmony_ci            }
1429cabdff1aSopenharmony_ci        }
1430cabdff1aSopenharmony_ci    }
1431cabdff1aSopenharmony_ci
1432cabdff1aSopenharmony_ci    if (ret >= 0)
1433cabdff1aSopenharmony_ci        flv->last_ts = pkt->dts;
1434cabdff1aSopenharmony_ci
1435cabdff1aSopenharmony_ci    return ret;
1436cabdff1aSopenharmony_ci}
1437cabdff1aSopenharmony_ci
1438cabdff1aSopenharmony_cistatic int flv_read_seek(AVFormatContext *s, int stream_index,
1439cabdff1aSopenharmony_ci                         int64_t ts, int flags)
1440cabdff1aSopenharmony_ci{
1441cabdff1aSopenharmony_ci    FLVContext *flv = s->priv_data;
1442cabdff1aSopenharmony_ci    flv->validate_count = 0;
1443cabdff1aSopenharmony_ci    return avio_seek_time(s->pb, stream_index, ts, flags);
1444cabdff1aSopenharmony_ci}
1445cabdff1aSopenharmony_ci
1446cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(FLVContext, x)
1447cabdff1aSopenharmony_ci#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
1448cabdff1aSopenharmony_cistatic const AVOption options[] = {
1449cabdff1aSopenharmony_ci    { "flv_metadata", "Allocate streams according to the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1450cabdff1aSopenharmony_ci    { "flv_full_metadata", "Dump full metadata of the onMetadata", OFFSET(dump_full_metadata), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1451cabdff1aSopenharmony_ci    { "flv_ignore_prevtag", "Ignore the Size of previous tag", OFFSET(trust_datasize), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD },
1452cabdff1aSopenharmony_ci    { "missing_streams", "", OFFSET(missing_streams), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xFF, VD | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
1453cabdff1aSopenharmony_ci    { NULL }
1454cabdff1aSopenharmony_ci};
1455cabdff1aSopenharmony_ci
1456cabdff1aSopenharmony_cistatic const AVClass flv_kux_class = {
1457cabdff1aSopenharmony_ci    .class_name = "(live) flv/kux demuxer",
1458cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
1459cabdff1aSopenharmony_ci    .option     = options,
1460cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
1461cabdff1aSopenharmony_ci};
1462cabdff1aSopenharmony_ci
1463cabdff1aSopenharmony_ciconst AVInputFormat ff_flv_demuxer = {
1464cabdff1aSopenharmony_ci    .name           = "flv",
1465cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
1466cabdff1aSopenharmony_ci    .priv_data_size = sizeof(FLVContext),
1467cabdff1aSopenharmony_ci    .read_probe     = flv_probe,
1468cabdff1aSopenharmony_ci    .read_header    = flv_read_header,
1469cabdff1aSopenharmony_ci    .read_packet    = flv_read_packet,
1470cabdff1aSopenharmony_ci    .read_seek      = flv_read_seek,
1471cabdff1aSopenharmony_ci    .read_close     = flv_read_close,
1472cabdff1aSopenharmony_ci    .extensions     = "flv",
1473cabdff1aSopenharmony_ci    .priv_class     = &flv_kux_class,
1474cabdff1aSopenharmony_ci};
1475cabdff1aSopenharmony_ci
1476cabdff1aSopenharmony_ciconst AVInputFormat ff_live_flv_demuxer = {
1477cabdff1aSopenharmony_ci    .name           = "live_flv",
1478cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("live RTMP FLV (Flash Video)"),
1479cabdff1aSopenharmony_ci    .priv_data_size = sizeof(FLVContext),
1480cabdff1aSopenharmony_ci    .read_probe     = live_flv_probe,
1481cabdff1aSopenharmony_ci    .read_header    = flv_read_header,
1482cabdff1aSopenharmony_ci    .read_packet    = flv_read_packet,
1483cabdff1aSopenharmony_ci    .read_seek      = flv_read_seek,
1484cabdff1aSopenharmony_ci    .read_close     = flv_read_close,
1485cabdff1aSopenharmony_ci    .extensions     = "flv",
1486cabdff1aSopenharmony_ci    .priv_class     = &flv_kux_class,
1487cabdff1aSopenharmony_ci    .flags          = AVFMT_TS_DISCONT
1488cabdff1aSopenharmony_ci};
1489cabdff1aSopenharmony_ci
1490cabdff1aSopenharmony_ciconst AVInputFormat ff_kux_demuxer = {
1491cabdff1aSopenharmony_ci    .name           = "kux",
1492cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("KUX (YouKu)"),
1493cabdff1aSopenharmony_ci    .priv_data_size = sizeof(FLVContext),
1494cabdff1aSopenharmony_ci    .read_probe     = kux_probe,
1495cabdff1aSopenharmony_ci    .read_header    = flv_read_header,
1496cabdff1aSopenharmony_ci    .read_packet    = flv_read_packet,
1497cabdff1aSopenharmony_ci    .read_seek      = flv_read_seek,
1498cabdff1aSopenharmony_ci    .read_close     = flv_read_close,
1499cabdff1aSopenharmony_ci    .extensions     = "kux",
1500cabdff1aSopenharmony_ci    .priv_class     = &flv_kux_class,
1501cabdff1aSopenharmony_ci};
1502