xref: /third_party/ffmpeg/libavformat/rmdec.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * "Real" compatible demuxer.
3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001 Fabrice Bellard
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 <inttypes.h>
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
25cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
26cabdff1aSopenharmony_ci#include "libavutil/internal.h"
27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
28cabdff1aSopenharmony_ci#include "libavutil/dict.h"
29cabdff1aSopenharmony_ci#include "avformat.h"
30cabdff1aSopenharmony_ci#include "avio_internal.h"
31cabdff1aSopenharmony_ci#include "demux.h"
32cabdff1aSopenharmony_ci#include "internal.h"
33cabdff1aSopenharmony_ci#include "rmsipr.h"
34cabdff1aSopenharmony_ci#include "rm.h"
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci#define DEINT_ID_GENR MKTAG('g', 'e', 'n', 'r') ///< interleaving for Cooker/ATRAC
37cabdff1aSopenharmony_ci#define DEINT_ID_INT0 MKTAG('I', 'n', 't', '0') ///< no interleaving needed
38cabdff1aSopenharmony_ci#define DEINT_ID_INT4 MKTAG('I', 'n', 't', '4') ///< interleaving for 28.8
39cabdff1aSopenharmony_ci#define DEINT_ID_SIPR MKTAG('s', 'i', 'p', 'r') ///< interleaving for Sipro
40cabdff1aSopenharmony_ci#define DEINT_ID_VBRF MKTAG('v', 'b', 'r', 'f') ///< VBR case for AAC
41cabdff1aSopenharmony_ci#define DEINT_ID_VBRS MKTAG('v', 'b', 'r', 's') ///< VBR case for AAC
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_cistruct RMStream {
44cabdff1aSopenharmony_ci    AVPacket pkt;      ///< place to store merged video frame / reordered audio data
45cabdff1aSopenharmony_ci    int videobufsize;  ///< current assembled frame size
46cabdff1aSopenharmony_ci    int videobufpos;   ///< position for the next slice in the video buffer
47cabdff1aSopenharmony_ci    int curpic_num;    ///< picture number of current frame
48cabdff1aSopenharmony_ci    int cur_slice, slices;
49cabdff1aSopenharmony_ci    int64_t pktpos;    ///< first slice position in file
50cabdff1aSopenharmony_ci    /// Audio descrambling matrix parameters
51cabdff1aSopenharmony_ci    int64_t audiotimestamp; ///< Audio packet timestamp
52cabdff1aSopenharmony_ci    int sub_packet_cnt; // Subpacket counter, used while reading
53cabdff1aSopenharmony_ci    int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container
54cabdff1aSopenharmony_ci    int audio_framesize; /// Audio frame size from container
55cabdff1aSopenharmony_ci    int sub_packet_lengths[16]; /// Length of each subpacket
56cabdff1aSopenharmony_ci    int32_t deint_id;  ///< deinterleaver used in audio stream
57cabdff1aSopenharmony_ci};
58cabdff1aSopenharmony_ci
59cabdff1aSopenharmony_citypedef struct RMDemuxContext {
60cabdff1aSopenharmony_ci    int nb_packets;
61cabdff1aSopenharmony_ci    int old_format;
62cabdff1aSopenharmony_ci    int current_stream;
63cabdff1aSopenharmony_ci    int remaining_len;
64cabdff1aSopenharmony_ci    int audio_stream_num; ///< Stream number for audio packets
65cabdff1aSopenharmony_ci    int audio_pkt_cnt; ///< Output packet counter
66cabdff1aSopenharmony_ci    int data_end;
67cabdff1aSopenharmony_ci} RMDemuxContext;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_cistatic inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len)
70cabdff1aSopenharmony_ci{
71cabdff1aSopenharmony_ci    int read = avio_get_str(pb, len, buf, buf_size);
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    if (read > 0)
74cabdff1aSopenharmony_ci        avio_skip(pb, len - read);
75cabdff1aSopenharmony_ci}
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_cistatic void get_str8(AVIOContext *pb, char *buf, int buf_size)
78cabdff1aSopenharmony_ci{
79cabdff1aSopenharmony_ci    get_strl(pb, buf, buf_size, avio_r8(pb));
80cabdff1aSopenharmony_ci}
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_cistatic int rm_read_extradata(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, unsigned size)
83cabdff1aSopenharmony_ci{
84cabdff1aSopenharmony_ci    if (size >= 1<<24) {
85cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "extradata size %u too large\n", size);
86cabdff1aSopenharmony_ci        return -1;
87cabdff1aSopenharmony_ci    }
88cabdff1aSopenharmony_ci    return ff_get_extradata(s, par, pb, size);
89cabdff1aSopenharmony_ci}
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_cistatic void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide)
92cabdff1aSopenharmony_ci{
93cabdff1aSopenharmony_ci    char buf[1024];
94cabdff1aSopenharmony_ci    int i;
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
97cabdff1aSopenharmony_ci        int len = wide ? avio_rb16(pb) : avio_r8(pb);
98cabdff1aSopenharmony_ci        if (len > 0) {
99cabdff1aSopenharmony_ci            get_strl(pb, buf, sizeof(buf), len);
100cabdff1aSopenharmony_ci            av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0);
101cabdff1aSopenharmony_ci        }
102cabdff1aSopenharmony_ci    }
103cabdff1aSopenharmony_ci}
104cabdff1aSopenharmony_ci
105cabdff1aSopenharmony_ciRMStream *ff_rm_alloc_rmstream (void)
106cabdff1aSopenharmony_ci{
107cabdff1aSopenharmony_ci    RMStream *rms = av_mallocz(sizeof(RMStream));
108cabdff1aSopenharmony_ci    if (!rms)
109cabdff1aSopenharmony_ci        return NULL;
110cabdff1aSopenharmony_ci    rms->curpic_num = -1;
111cabdff1aSopenharmony_ci    return rms;
112cabdff1aSopenharmony_ci}
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_civoid ff_rm_free_rmstream (RMStream *rms)
115cabdff1aSopenharmony_ci{
116cabdff1aSopenharmony_ci    if (!rms)
117cabdff1aSopenharmony_ci        return;
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    av_packet_unref(&rms->pkt);
120cabdff1aSopenharmony_ci}
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_cistatic int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
123cabdff1aSopenharmony_ci                                     AVStream *st, RMStream *ast, int read_all)
124cabdff1aSopenharmony_ci{
125cabdff1aSopenharmony_ci    FFStream *const sti = ffstream(st);
126cabdff1aSopenharmony_ci    char buf[256];
127cabdff1aSopenharmony_ci    uint32_t version;
128cabdff1aSopenharmony_ci    int ret;
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci    /* ra type header */
131cabdff1aSopenharmony_ci    version = avio_rb16(pb); /* version */
132cabdff1aSopenharmony_ci    if (version == 3) {
133cabdff1aSopenharmony_ci        unsigned bytes_per_minute;
134cabdff1aSopenharmony_ci        int header_size = avio_rb16(pb);
135cabdff1aSopenharmony_ci        int64_t startpos = avio_tell(pb);
136cabdff1aSopenharmony_ci        avio_skip(pb, 8);
137cabdff1aSopenharmony_ci        bytes_per_minute = avio_rb16(pb);
138cabdff1aSopenharmony_ci        avio_skip(pb, 4);
139cabdff1aSopenharmony_ci        rm_read_metadata(s, pb, 0);
140cabdff1aSopenharmony_ci        if ((startpos + header_size) >= avio_tell(pb) + 2) {
141cabdff1aSopenharmony_ci            // fourcc (should always be "lpcJ")
142cabdff1aSopenharmony_ci            avio_r8(pb);
143cabdff1aSopenharmony_ci            get_str8(pb, buf, sizeof(buf));
144cabdff1aSopenharmony_ci        }
145cabdff1aSopenharmony_ci        // Skip extra header crap (this should never happen)
146cabdff1aSopenharmony_ci        if ((startpos + header_size) > avio_tell(pb))
147cabdff1aSopenharmony_ci            avio_skip(pb, header_size + startpos - avio_tell(pb));
148cabdff1aSopenharmony_ci        if (bytes_per_minute)
149cabdff1aSopenharmony_ci            st->codecpar->bit_rate = 8LL * bytes_per_minute / 60;
150cabdff1aSopenharmony_ci        st->codecpar->sample_rate = 8000;
151cabdff1aSopenharmony_ci        st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
152cabdff1aSopenharmony_ci        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
153cabdff1aSopenharmony_ci        st->codecpar->codec_id = AV_CODEC_ID_RA_144;
154cabdff1aSopenharmony_ci        ast->deint_id = DEINT_ID_INT0;
155cabdff1aSopenharmony_ci    } else {
156cabdff1aSopenharmony_ci        int flavor, sub_packet_h, coded_framesize, sub_packet_size;
157cabdff1aSopenharmony_ci        int codecdata_length;
158cabdff1aSopenharmony_ci        unsigned bytes_per_minute;
159cabdff1aSopenharmony_ci        /* old version (4) */
160cabdff1aSopenharmony_ci        avio_skip(pb, 2); /* unused */
161cabdff1aSopenharmony_ci        avio_rb32(pb); /* .ra4 */
162cabdff1aSopenharmony_ci        avio_rb32(pb); /* data size */
163cabdff1aSopenharmony_ci        avio_rb16(pb); /* version2 */
164cabdff1aSopenharmony_ci        avio_rb32(pb); /* header size */
165cabdff1aSopenharmony_ci        flavor= avio_rb16(pb); /* add codec info / flavor */
166cabdff1aSopenharmony_ci        coded_framesize = avio_rb32(pb); /* coded frame size */
167cabdff1aSopenharmony_ci        if (coded_framesize < 0)
168cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
169cabdff1aSopenharmony_ci        ast->coded_framesize = coded_framesize;
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci        avio_rb32(pb); /* ??? */
172cabdff1aSopenharmony_ci        bytes_per_minute = avio_rb32(pb);
173cabdff1aSopenharmony_ci        if (version == 4) {
174cabdff1aSopenharmony_ci            if (bytes_per_minute)
175cabdff1aSopenharmony_ci                st->codecpar->bit_rate = 8LL * bytes_per_minute / 60;
176cabdff1aSopenharmony_ci        }
177cabdff1aSopenharmony_ci        avio_rb32(pb); /* ??? */
178cabdff1aSopenharmony_ci        ast->sub_packet_h = sub_packet_h = avio_rb16(pb); /* 1 */
179cabdff1aSopenharmony_ci        st->codecpar->block_align= avio_rb16(pb); /* frame size */
180cabdff1aSopenharmony_ci        ast->sub_packet_size = sub_packet_size = avio_rb16(pb); /* sub packet size */
181cabdff1aSopenharmony_ci        avio_rb16(pb); /* ??? */
182cabdff1aSopenharmony_ci        if (version == 5) {
183cabdff1aSopenharmony_ci            avio_rb16(pb); avio_rb16(pb); avio_rb16(pb);
184cabdff1aSopenharmony_ci        }
185cabdff1aSopenharmony_ci        st->codecpar->sample_rate = avio_rb16(pb);
186cabdff1aSopenharmony_ci        avio_rb32(pb);
187cabdff1aSopenharmony_ci        st->codecpar->ch_layout.nb_channels = avio_rb16(pb);
188cabdff1aSopenharmony_ci        if (version == 5) {
189cabdff1aSopenharmony_ci            ast->deint_id = avio_rl32(pb);
190cabdff1aSopenharmony_ci            avio_read(pb, buf, 4);
191cabdff1aSopenharmony_ci            buf[4] = 0;
192cabdff1aSopenharmony_ci        } else {
193cabdff1aSopenharmony_ci            AV_WL32(buf, 0);
194cabdff1aSopenharmony_ci            get_str8(pb, buf, sizeof(buf)); /* desc */
195cabdff1aSopenharmony_ci            ast->deint_id = AV_RL32(buf);
196cabdff1aSopenharmony_ci            get_str8(pb, buf, sizeof(buf)); /* desc */
197cabdff1aSopenharmony_ci        }
198cabdff1aSopenharmony_ci        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
199cabdff1aSopenharmony_ci        st->codecpar->codec_tag  = AV_RL32(buf);
200cabdff1aSopenharmony_ci        st->codecpar->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
201cabdff1aSopenharmony_ci                                                   st->codecpar->codec_tag);
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci        switch (st->codecpar->codec_id) {
204cabdff1aSopenharmony_ci        case AV_CODEC_ID_AC3:
205cabdff1aSopenharmony_ci            sti->need_parsing = AVSTREAM_PARSE_FULL;
206cabdff1aSopenharmony_ci            break;
207cabdff1aSopenharmony_ci        case AV_CODEC_ID_RA_288:
208cabdff1aSopenharmony_ci            st->codecpar->extradata_size= 0;
209cabdff1aSopenharmony_ci            av_freep(&st->codecpar->extradata);
210cabdff1aSopenharmony_ci            ast->audio_framesize = st->codecpar->block_align;
211cabdff1aSopenharmony_ci            st->codecpar->block_align = coded_framesize;
212cabdff1aSopenharmony_ci            break;
213cabdff1aSopenharmony_ci        case AV_CODEC_ID_COOK:
214cabdff1aSopenharmony_ci            sti->need_parsing = AVSTREAM_PARSE_HEADERS;
215cabdff1aSopenharmony_ci        case AV_CODEC_ID_ATRAC3:
216cabdff1aSopenharmony_ci        case AV_CODEC_ID_SIPR:
217cabdff1aSopenharmony_ci            if (read_all) {
218cabdff1aSopenharmony_ci                codecdata_length = 0;
219cabdff1aSopenharmony_ci            } else {
220cabdff1aSopenharmony_ci                avio_rb16(pb); avio_r8(pb);
221cabdff1aSopenharmony_ci                if (version == 5)
222cabdff1aSopenharmony_ci                    avio_r8(pb);
223cabdff1aSopenharmony_ci                codecdata_length = avio_rb32(pb);
224cabdff1aSopenharmony_ci                if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){
225cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
226cabdff1aSopenharmony_ci                    return -1;
227cabdff1aSopenharmony_ci                }
228cabdff1aSopenharmony_ci            }
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_ci            ast->audio_framesize = st->codecpar->block_align;
231cabdff1aSopenharmony_ci            if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) {
232cabdff1aSopenharmony_ci                if (flavor > 3) {
233cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n",
234cabdff1aSopenharmony_ci                           flavor);
235cabdff1aSopenharmony_ci                    return -1;
236cabdff1aSopenharmony_ci                }
237cabdff1aSopenharmony_ci                st->codecpar->block_align = ff_sipr_subpk_size[flavor];
238cabdff1aSopenharmony_ci                sti->need_parsing = AVSTREAM_PARSE_FULL_RAW;
239cabdff1aSopenharmony_ci            } else {
240cabdff1aSopenharmony_ci                if(sub_packet_size <= 0){
241cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
242cabdff1aSopenharmony_ci                    return -1;
243cabdff1aSopenharmony_ci                }
244cabdff1aSopenharmony_ci                st->codecpar->block_align = ast->sub_packet_size;
245cabdff1aSopenharmony_ci            }
246cabdff1aSopenharmony_ci            if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length)) < 0)
247cabdff1aSopenharmony_ci                return ret;
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_ci            break;
250cabdff1aSopenharmony_ci        case AV_CODEC_ID_AAC:
251cabdff1aSopenharmony_ci            avio_rb16(pb); avio_r8(pb);
252cabdff1aSopenharmony_ci            if (version == 5)
253cabdff1aSopenharmony_ci                avio_r8(pb);
254cabdff1aSopenharmony_ci            codecdata_length = avio_rb32(pb);
255cabdff1aSopenharmony_ci            if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){
256cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "codecdata_length too large\n");
257cabdff1aSopenharmony_ci                return -1;
258cabdff1aSopenharmony_ci            }
259cabdff1aSopenharmony_ci            if (codecdata_length >= 1) {
260cabdff1aSopenharmony_ci                avio_r8(pb);
261cabdff1aSopenharmony_ci                if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length - 1)) < 0)
262cabdff1aSopenharmony_ci                    return ret;
263cabdff1aSopenharmony_ci            }
264cabdff1aSopenharmony_ci            break;
265cabdff1aSopenharmony_ci        }
266cabdff1aSopenharmony_ci        switch (ast->deint_id) {
267cabdff1aSopenharmony_ci        case DEINT_ID_INT4:
268cabdff1aSopenharmony_ci            if (ast->coded_framesize > ast->audio_framesize ||
269cabdff1aSopenharmony_ci                sub_packet_h <= 1 ||
270cabdff1aSopenharmony_ci                ast->coded_framesize * (uint64_t)sub_packet_h > (2 + (sub_packet_h & 1)) * ast->audio_framesize)
271cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
272cabdff1aSopenharmony_ci            if (ast->coded_framesize * (uint64_t)sub_packet_h != 2*ast->audio_framesize) {
273cabdff1aSopenharmony_ci                avpriv_request_sample(s, "mismatching interleaver parameters");
274cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
275cabdff1aSopenharmony_ci            }
276cabdff1aSopenharmony_ci            break;
277cabdff1aSopenharmony_ci        case DEINT_ID_GENR:
278cabdff1aSopenharmony_ci            if (ast->sub_packet_size <= 0 ||
279cabdff1aSopenharmony_ci                ast->sub_packet_size > ast->audio_framesize)
280cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
281cabdff1aSopenharmony_ci            if (ast->audio_framesize % ast->sub_packet_size)
282cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
283cabdff1aSopenharmony_ci            break;
284cabdff1aSopenharmony_ci        case DEINT_ID_SIPR:
285cabdff1aSopenharmony_ci        case DEINT_ID_INT0:
286cabdff1aSopenharmony_ci        case DEINT_ID_VBRS:
287cabdff1aSopenharmony_ci        case DEINT_ID_VBRF:
288cabdff1aSopenharmony_ci            break;
289cabdff1aSopenharmony_ci        default:
290cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR ,"Unknown interleaver %"PRIX32"\n", ast->deint_id);
291cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
292cabdff1aSopenharmony_ci        }
293cabdff1aSopenharmony_ci        if (ast->deint_id == DEINT_ID_INT4 ||
294cabdff1aSopenharmony_ci            ast->deint_id == DEINT_ID_GENR ||
295cabdff1aSopenharmony_ci            ast->deint_id == DEINT_ID_SIPR) {
296cabdff1aSopenharmony_ci            if (st->codecpar->block_align <= 0 ||
297cabdff1aSopenharmony_ci                ast->audio_framesize * (uint64_t)sub_packet_h > (unsigned)INT_MAX ||
298cabdff1aSopenharmony_ci                ast->audio_framesize * sub_packet_h < st->codecpar->block_align)
299cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
300cabdff1aSopenharmony_ci            if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
301cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
302cabdff1aSopenharmony_ci        }
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_ci        if (read_all) {
305cabdff1aSopenharmony_ci            avio_r8(pb);
306cabdff1aSopenharmony_ci            avio_r8(pb);
307cabdff1aSopenharmony_ci            avio_r8(pb);
308cabdff1aSopenharmony_ci            rm_read_metadata(s, pb, 0);
309cabdff1aSopenharmony_ci        }
310cabdff1aSopenharmony_ci    }
311cabdff1aSopenharmony_ci    return 0;
312cabdff1aSopenharmony_ci}
313cabdff1aSopenharmony_ci
314cabdff1aSopenharmony_ciint ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb,
315cabdff1aSopenharmony_ci                              AVStream *st, RMStream *rst,
316cabdff1aSopenharmony_ci                              unsigned int codec_data_size, const uint8_t *mime)
317cabdff1aSopenharmony_ci{
318cabdff1aSopenharmony_ci    unsigned int v;
319cabdff1aSopenharmony_ci    int size;
320cabdff1aSopenharmony_ci    int64_t codec_pos;
321cabdff1aSopenharmony_ci    int ret;
322cabdff1aSopenharmony_ci
323cabdff1aSopenharmony_ci    if (codec_data_size > INT_MAX)
324cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
325cabdff1aSopenharmony_ci    if (codec_data_size == 0)
326cabdff1aSopenharmony_ci        return 0;
327cabdff1aSopenharmony_ci
328cabdff1aSopenharmony_ci    // Duplicate tags
329cabdff1aSopenharmony_ci    if (   st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN
330cabdff1aSopenharmony_ci        && st->codecpar->codec_type != AVMEDIA_TYPE_DATA)
331cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_ci    avpriv_set_pts_info(st, 64, 1, 1000);
334cabdff1aSopenharmony_ci    codec_pos = avio_tell(pb);
335cabdff1aSopenharmony_ci    v = avio_rb32(pb);
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci    if (v == MKTAG(0xfd, 'a', 'r', '.')) {
338cabdff1aSopenharmony_ci        /* ra type header */
339cabdff1aSopenharmony_ci        if (rm_read_audio_stream_info(s, pb, st, rst, 0))
340cabdff1aSopenharmony_ci            return -1;
341cabdff1aSopenharmony_ci    } else if (v == MKBETAG('L', 'S', 'D', ':')) {
342cabdff1aSopenharmony_ci        avio_seek(pb, -4, SEEK_CUR);
343cabdff1aSopenharmony_ci        if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size)) < 0)
344cabdff1aSopenharmony_ci            return ret;
345cabdff1aSopenharmony_ci
346cabdff1aSopenharmony_ci        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
347cabdff1aSopenharmony_ci        st->codecpar->codec_tag  = AV_RL32(st->codecpar->extradata);
348cabdff1aSopenharmony_ci        st->codecpar->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
349cabdff1aSopenharmony_ci                                                st->codecpar->codec_tag);
350cabdff1aSopenharmony_ci    } else if(mime && !strcmp(mime, "logical-fileinfo")){
351cabdff1aSopenharmony_ci        int stream_count, rule_count, property_count, i;
352cabdff1aSopenharmony_ci        ff_remove_stream(s, st);
353cabdff1aSopenharmony_ci        if (avio_rb16(pb) != 0) {
354cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "Unsupported version\n");
355cabdff1aSopenharmony_ci            goto skip;
356cabdff1aSopenharmony_ci        }
357cabdff1aSopenharmony_ci        stream_count = avio_rb16(pb);
358cabdff1aSopenharmony_ci        avio_skip(pb, 6*stream_count);
359cabdff1aSopenharmony_ci        rule_count = avio_rb16(pb);
360cabdff1aSopenharmony_ci        avio_skip(pb, 2*rule_count);
361cabdff1aSopenharmony_ci        property_count = avio_rb16(pb);
362cabdff1aSopenharmony_ci        for(i=0; i<property_count; i++){
363cabdff1aSopenharmony_ci            uint8_t name[128], val[128];
364cabdff1aSopenharmony_ci            avio_rb32(pb);
365cabdff1aSopenharmony_ci            if (avio_rb16(pb) != 0) {
366cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING, "Unsupported Name value property version\n");
367cabdff1aSopenharmony_ci                goto skip; //FIXME skip just this one
368cabdff1aSopenharmony_ci            }
369cabdff1aSopenharmony_ci            get_str8(pb, name, sizeof(name));
370cabdff1aSopenharmony_ci            switch(avio_rb32(pb)) {
371cabdff1aSopenharmony_ci            case 2: get_strl(pb, val, sizeof(val), avio_rb16(pb));
372cabdff1aSopenharmony_ci                av_dict_set(&s->metadata, name, val, 0);
373cabdff1aSopenharmony_ci                break;
374cabdff1aSopenharmony_ci            default: avio_skip(pb, avio_rb16(pb));
375cabdff1aSopenharmony_ci            }
376cabdff1aSopenharmony_ci        }
377cabdff1aSopenharmony_ci    } else {
378cabdff1aSopenharmony_ci        int fps;
379cabdff1aSopenharmony_ci        if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) {
380cabdff1aSopenharmony_ci        fail1:
381cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "Unsupported stream type %08x\n", v);
382cabdff1aSopenharmony_ci            goto skip;
383cabdff1aSopenharmony_ci        }
384cabdff1aSopenharmony_ci        st->codecpar->codec_tag = avio_rl32(pb);
385cabdff1aSopenharmony_ci        st->codecpar->codec_id  = ff_codec_get_id(ff_rm_codec_tags,
386cabdff1aSopenharmony_ci                                                  st->codecpar->codec_tag);
387cabdff1aSopenharmony_ci        av_log(s, AV_LOG_TRACE, "%"PRIX32" %X\n",
388cabdff1aSopenharmony_ci               st->codecpar->codec_tag, MKTAG('R', 'V', '2', '0'));
389cabdff1aSopenharmony_ci        if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
390cabdff1aSopenharmony_ci            goto fail1;
391cabdff1aSopenharmony_ci        st->codecpar->width  = avio_rb16(pb);
392cabdff1aSopenharmony_ci        st->codecpar->height = avio_rb16(pb);
393cabdff1aSopenharmony_ci        avio_skip(pb, 2); // looks like bits per sample
394cabdff1aSopenharmony_ci        avio_skip(pb, 4); // always zero?
395cabdff1aSopenharmony_ci        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
396cabdff1aSopenharmony_ci        ffstream(st)->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
397cabdff1aSopenharmony_ci        fps = avio_rb32(pb);
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci        if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
400cabdff1aSopenharmony_ci            return ret;
401cabdff1aSopenharmony_ci
402cabdff1aSopenharmony_ci        if (fps > 0) {
403cabdff1aSopenharmony_ci            av_reduce(&st->avg_frame_rate.den, &st->avg_frame_rate.num,
404cabdff1aSopenharmony_ci                      0x10000, fps, (1 << 30) - 1);
405cabdff1aSopenharmony_ci#if FF_API_R_FRAME_RATE
406cabdff1aSopenharmony_ci            st->r_frame_rate = st->avg_frame_rate;
407cabdff1aSopenharmony_ci#endif
408cabdff1aSopenharmony_ci        } else if (s->error_recognition & AV_EF_EXPLODE) {
409cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Invalid framerate\n");
410cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
411cabdff1aSopenharmony_ci        }
412cabdff1aSopenharmony_ci    }
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_ciskip:
415cabdff1aSopenharmony_ci    /* skip codec info */
416cabdff1aSopenharmony_ci    size = avio_tell(pb) - codec_pos;
417cabdff1aSopenharmony_ci    if (codec_data_size >= size) {
418cabdff1aSopenharmony_ci        avio_skip(pb, codec_data_size - size);
419cabdff1aSopenharmony_ci    } else {
420cabdff1aSopenharmony_ci        av_log(s, AV_LOG_WARNING, "codec_data_size %u < size %d\n", codec_data_size, size);
421cabdff1aSopenharmony_ci    }
422cabdff1aSopenharmony_ci
423cabdff1aSopenharmony_ci    return 0;
424cabdff1aSopenharmony_ci}
425cabdff1aSopenharmony_ci
426cabdff1aSopenharmony_ci/** this function assumes that the demuxer has already seeked to the start
427cabdff1aSopenharmony_ci * of the INDX chunk, and will bail out if not. */
428cabdff1aSopenharmony_cistatic int rm_read_index(AVFormatContext *s)
429cabdff1aSopenharmony_ci{
430cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
431cabdff1aSopenharmony_ci    unsigned int size, n_pkts, str_id, next_off, n, pos, pts;
432cabdff1aSopenharmony_ci    AVStream *st;
433cabdff1aSopenharmony_ci
434cabdff1aSopenharmony_ci    do {
435cabdff1aSopenharmony_ci        if (avio_rl32(pb) != MKTAG('I','N','D','X'))
436cabdff1aSopenharmony_ci            return -1;
437cabdff1aSopenharmony_ci        size     = avio_rb32(pb);
438cabdff1aSopenharmony_ci        if (size < 20)
439cabdff1aSopenharmony_ci            return -1;
440cabdff1aSopenharmony_ci        avio_skip(pb, 2);
441cabdff1aSopenharmony_ci        n_pkts   = avio_rb32(pb);
442cabdff1aSopenharmony_ci        str_id   = avio_rb16(pb);
443cabdff1aSopenharmony_ci        next_off = avio_rb32(pb);
444cabdff1aSopenharmony_ci        for (n = 0; n < s->nb_streams; n++)
445cabdff1aSopenharmony_ci            if (s->streams[n]->id == str_id) {
446cabdff1aSopenharmony_ci                st = s->streams[n];
447cabdff1aSopenharmony_ci                break;
448cabdff1aSopenharmony_ci            }
449cabdff1aSopenharmony_ci        if (n == s->nb_streams) {
450cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR,
451cabdff1aSopenharmony_ci                   "Invalid stream index %d for index at pos %"PRId64"\n",
452cabdff1aSopenharmony_ci                   str_id, avio_tell(pb));
453cabdff1aSopenharmony_ci            goto skip;
454cabdff1aSopenharmony_ci        } else if ((avio_size(pb) - avio_tell(pb)) / 14 < n_pkts) {
455cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR,
456cabdff1aSopenharmony_ci                   "Nr. of packets in packet index for stream index %d "
457cabdff1aSopenharmony_ci                   "exceeds filesize (%"PRId64" at %"PRId64" = %"PRId64")\n",
458cabdff1aSopenharmony_ci                   str_id, avio_size(pb), avio_tell(pb),
459cabdff1aSopenharmony_ci                   (avio_size(pb) - avio_tell(pb)) / 14);
460cabdff1aSopenharmony_ci            goto skip;
461cabdff1aSopenharmony_ci        }
462cabdff1aSopenharmony_ci
463cabdff1aSopenharmony_ci        for (n = 0; n < n_pkts; n++) {
464cabdff1aSopenharmony_ci            if (avio_feof(pb))
465cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
466cabdff1aSopenharmony_ci            avio_skip(pb, 2);
467cabdff1aSopenharmony_ci            pts = avio_rb32(pb);
468cabdff1aSopenharmony_ci            pos = avio_rb32(pb);
469cabdff1aSopenharmony_ci            avio_skip(pb, 4); /* packet no. */
470cabdff1aSopenharmony_ci
471cabdff1aSopenharmony_ci            av_add_index_entry(st, pos, pts, 0, 0, AVINDEX_KEYFRAME);
472cabdff1aSopenharmony_ci        }
473cabdff1aSopenharmony_ci
474cabdff1aSopenharmony_ciskip:
475cabdff1aSopenharmony_ci        if (next_off && avio_tell(pb) < next_off &&
476cabdff1aSopenharmony_ci            avio_seek(pb, next_off, SEEK_SET) < 0) {
477cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR,
478cabdff1aSopenharmony_ci                   "Non-linear index detected, not supported\n");
479cabdff1aSopenharmony_ci            return -1;
480cabdff1aSopenharmony_ci        }
481cabdff1aSopenharmony_ci    } while (next_off);
482cabdff1aSopenharmony_ci
483cabdff1aSopenharmony_ci    return 0;
484cabdff1aSopenharmony_ci}
485cabdff1aSopenharmony_ci
486cabdff1aSopenharmony_cistatic int rm_read_header_old(AVFormatContext *s)
487cabdff1aSopenharmony_ci{
488cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
489cabdff1aSopenharmony_ci    AVStream *st;
490cabdff1aSopenharmony_ci
491cabdff1aSopenharmony_ci    rm->old_format = 1;
492cabdff1aSopenharmony_ci    st = avformat_new_stream(s, NULL);
493cabdff1aSopenharmony_ci    if (!st)
494cabdff1aSopenharmony_ci        return -1;
495cabdff1aSopenharmony_ci    st->priv_data = ff_rm_alloc_rmstream();
496cabdff1aSopenharmony_ci    if (!st->priv_data)
497cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
498cabdff1aSopenharmony_ci    return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1);
499cabdff1aSopenharmony_ci}
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_cistatic int rm_read_multi(AVFormatContext *s, AVIOContext *pb,
502cabdff1aSopenharmony_ci                         AVStream *st, char *mime)
503cabdff1aSopenharmony_ci{
504cabdff1aSopenharmony_ci    int number_of_streams = avio_rb16(pb);
505cabdff1aSopenharmony_ci    int number_of_mdpr;
506cabdff1aSopenharmony_ci    int i, ret;
507cabdff1aSopenharmony_ci    unsigned size2;
508cabdff1aSopenharmony_ci    for (i = 0; i<number_of_streams; i++)
509cabdff1aSopenharmony_ci        avio_rb16(pb);
510cabdff1aSopenharmony_ci    number_of_mdpr = avio_rb16(pb);
511cabdff1aSopenharmony_ci    if (number_of_mdpr != 1) {
512cabdff1aSopenharmony_ci        avpriv_request_sample(s, "MLTI with multiple (%d) MDPR", number_of_mdpr);
513cabdff1aSopenharmony_ci    }
514cabdff1aSopenharmony_ci    for (i = 0; i < number_of_mdpr; i++) {
515cabdff1aSopenharmony_ci        AVStream *st2;
516cabdff1aSopenharmony_ci        if (i > 0) {
517cabdff1aSopenharmony_ci            st2 = avformat_new_stream(s, NULL);
518cabdff1aSopenharmony_ci            if (!st2) {
519cabdff1aSopenharmony_ci                ret = AVERROR(ENOMEM);
520cabdff1aSopenharmony_ci                return ret;
521cabdff1aSopenharmony_ci            }
522cabdff1aSopenharmony_ci            st2->id = st->id + (i<<16);
523cabdff1aSopenharmony_ci            st2->codecpar->bit_rate = st->codecpar->bit_rate;
524cabdff1aSopenharmony_ci            st2->start_time = st->start_time;
525cabdff1aSopenharmony_ci            st2->duration   = st->duration;
526cabdff1aSopenharmony_ci            st2->codecpar->codec_type = AVMEDIA_TYPE_DATA;
527cabdff1aSopenharmony_ci            st2->priv_data = ff_rm_alloc_rmstream();
528cabdff1aSopenharmony_ci            if (!st2->priv_data)
529cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
530cabdff1aSopenharmony_ci        } else
531cabdff1aSopenharmony_ci            st2 = st;
532cabdff1aSopenharmony_ci
533cabdff1aSopenharmony_ci        size2 = avio_rb32(pb);
534cabdff1aSopenharmony_ci        ret = ff_rm_read_mdpr_codecdata(s, s->pb, st2, st2->priv_data,
535cabdff1aSopenharmony_ci                                        size2, NULL);
536cabdff1aSopenharmony_ci        if (ret < 0)
537cabdff1aSopenharmony_ci            return ret;
538cabdff1aSopenharmony_ci    }
539cabdff1aSopenharmony_ci    return 0;
540cabdff1aSopenharmony_ci}
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_cistatic int rm_read_header(AVFormatContext *s)
543cabdff1aSopenharmony_ci{
544cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
545cabdff1aSopenharmony_ci    AVStream *st;
546cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
547cabdff1aSopenharmony_ci    unsigned int tag;
548cabdff1aSopenharmony_ci    int tag_size;
549cabdff1aSopenharmony_ci    unsigned int start_time, duration;
550cabdff1aSopenharmony_ci    unsigned int data_off = 0, indx_off = 0;
551cabdff1aSopenharmony_ci    char buf[128], mime[128];
552cabdff1aSopenharmony_ci    int flags = 0;
553cabdff1aSopenharmony_ci    int ret;
554cabdff1aSopenharmony_ci    unsigned size, v;
555cabdff1aSopenharmony_ci    int64_t codec_pos;
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci    tag = avio_rl32(pb);
558cabdff1aSopenharmony_ci    if (tag == MKTAG('.', 'r', 'a', 0xfd)) {
559cabdff1aSopenharmony_ci        /* very old .ra format */
560cabdff1aSopenharmony_ci        return rm_read_header_old(s);
561cabdff1aSopenharmony_ci    } else if (tag != MKTAG('.', 'R', 'M', 'F')) {
562cabdff1aSopenharmony_ci        return AVERROR(EIO);
563cabdff1aSopenharmony_ci    }
564cabdff1aSopenharmony_ci
565cabdff1aSopenharmony_ci    tag_size = avio_rb32(pb);
566cabdff1aSopenharmony_ci    if (tag_size < 0)
567cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
568cabdff1aSopenharmony_ci    avio_skip(pb, tag_size - 8);
569cabdff1aSopenharmony_ci
570cabdff1aSopenharmony_ci    for(;;) {
571cabdff1aSopenharmony_ci        if (avio_feof(pb))
572cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
573cabdff1aSopenharmony_ci        tag = avio_rl32(pb);
574cabdff1aSopenharmony_ci        tag_size = avio_rb32(pb);
575cabdff1aSopenharmony_ci        avio_rb16(pb);
576cabdff1aSopenharmony_ci        av_log(s, AV_LOG_TRACE, "tag=%s size=%d\n",
577cabdff1aSopenharmony_ci               av_fourcc2str(tag), tag_size);
578cabdff1aSopenharmony_ci        if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A'))
579cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
580cabdff1aSopenharmony_ci        switch(tag) {
581cabdff1aSopenharmony_ci        case MKTAG('P', 'R', 'O', 'P'):
582cabdff1aSopenharmony_ci            /* file header */
583cabdff1aSopenharmony_ci            avio_rb32(pb); /* max bit rate */
584cabdff1aSopenharmony_ci            avio_rb32(pb); /* avg bit rate */
585cabdff1aSopenharmony_ci            avio_rb32(pb); /* max packet size */
586cabdff1aSopenharmony_ci            avio_rb32(pb); /* avg packet size */
587cabdff1aSopenharmony_ci            avio_rb32(pb); /* nb packets */
588cabdff1aSopenharmony_ci            duration = avio_rb32(pb); /* duration */
589cabdff1aSopenharmony_ci            s->duration = av_rescale(duration, AV_TIME_BASE, 1000);
590cabdff1aSopenharmony_ci            avio_rb32(pb); /* preroll */
591cabdff1aSopenharmony_ci            indx_off = avio_rb32(pb); /* index offset */
592cabdff1aSopenharmony_ci            data_off = avio_rb32(pb); /* data offset */
593cabdff1aSopenharmony_ci            avio_rb16(pb); /* nb streams */
594cabdff1aSopenharmony_ci            flags = avio_rb16(pb); /* flags */
595cabdff1aSopenharmony_ci            break;
596cabdff1aSopenharmony_ci        case MKTAG('C', 'O', 'N', 'T'):
597cabdff1aSopenharmony_ci            rm_read_metadata(s, pb, 1);
598cabdff1aSopenharmony_ci            break;
599cabdff1aSopenharmony_ci        case MKTAG('M', 'D', 'P', 'R'):
600cabdff1aSopenharmony_ci            st = avformat_new_stream(s, NULL);
601cabdff1aSopenharmony_ci            if (!st)
602cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
603cabdff1aSopenharmony_ci            st->id = avio_rb16(pb);
604cabdff1aSopenharmony_ci            avio_rb32(pb); /* max bit rate */
605cabdff1aSopenharmony_ci            st->codecpar->bit_rate = avio_rb32(pb); /* bit rate */
606cabdff1aSopenharmony_ci            avio_rb32(pb); /* max packet size */
607cabdff1aSopenharmony_ci            avio_rb32(pb); /* avg packet size */
608cabdff1aSopenharmony_ci            start_time = avio_rb32(pb); /* start time */
609cabdff1aSopenharmony_ci            avio_rb32(pb); /* preroll */
610cabdff1aSopenharmony_ci            duration = avio_rb32(pb); /* duration */
611cabdff1aSopenharmony_ci            st->start_time = start_time;
612cabdff1aSopenharmony_ci            st->duration = duration;
613cabdff1aSopenharmony_ci            if(duration>0)
614cabdff1aSopenharmony_ci                s->duration = AV_NOPTS_VALUE;
615cabdff1aSopenharmony_ci            get_str8(pb, buf, sizeof(buf)); /* desc */
616cabdff1aSopenharmony_ci            get_str8(pb, mime, sizeof(mime)); /* mimetype */
617cabdff1aSopenharmony_ci            st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
618cabdff1aSopenharmony_ci            st->priv_data = ff_rm_alloc_rmstream();
619cabdff1aSopenharmony_ci            if (!st->priv_data)
620cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
621cabdff1aSopenharmony_ci
622cabdff1aSopenharmony_ci            size = avio_rb32(pb);
623cabdff1aSopenharmony_ci            codec_pos = avio_tell(pb);
624cabdff1aSopenharmony_ci
625cabdff1aSopenharmony_ci            ffio_ensure_seekback(pb, 4);
626cabdff1aSopenharmony_ci            v = avio_rb32(pb);
627cabdff1aSopenharmony_ci            if (v == MKBETAG('M', 'L', 'T', 'I')) {
628cabdff1aSopenharmony_ci                ret = rm_read_multi(s, s->pb, st, mime);
629cabdff1aSopenharmony_ci                if (ret < 0)
630cabdff1aSopenharmony_ci                    return ret;
631cabdff1aSopenharmony_ci                avio_seek(pb, codec_pos + size, SEEK_SET);
632cabdff1aSopenharmony_ci            } else {
633cabdff1aSopenharmony_ci                avio_skip(pb, -4);
634cabdff1aSopenharmony_ci                ret = ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data,
635cabdff1aSopenharmony_ci                                                size, mime);
636cabdff1aSopenharmony_ci                if (ret < 0)
637cabdff1aSopenharmony_ci                    return ret;
638cabdff1aSopenharmony_ci            }
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci            break;
641cabdff1aSopenharmony_ci        case MKTAG('D', 'A', 'T', 'A'):
642cabdff1aSopenharmony_ci            goto header_end;
643cabdff1aSopenharmony_ci        default:
644cabdff1aSopenharmony_ci            /* unknown tag: skip it */
645cabdff1aSopenharmony_ci            avio_skip(pb, tag_size - 10);
646cabdff1aSopenharmony_ci            break;
647cabdff1aSopenharmony_ci        }
648cabdff1aSopenharmony_ci    }
649cabdff1aSopenharmony_ci header_end:
650cabdff1aSopenharmony_ci    rm->nb_packets = avio_rb32(pb); /* number of packets */
651cabdff1aSopenharmony_ci    if (!rm->nb_packets && (flags & 4))
652cabdff1aSopenharmony_ci        rm->nb_packets = 3600 * 25;
653cabdff1aSopenharmony_ci    avio_rb32(pb); /* next data header */
654cabdff1aSopenharmony_ci
655cabdff1aSopenharmony_ci    if (!data_off)
656cabdff1aSopenharmony_ci        data_off = avio_tell(pb) - 18;
657cabdff1aSopenharmony_ci    if (indx_off && (pb->seekable & AVIO_SEEKABLE_NORMAL) &&
658cabdff1aSopenharmony_ci        !(s->flags & AVFMT_FLAG_IGNIDX) &&
659cabdff1aSopenharmony_ci        avio_seek(pb, indx_off, SEEK_SET) >= 0) {
660cabdff1aSopenharmony_ci        rm_read_index(s);
661cabdff1aSopenharmony_ci        avio_seek(pb, data_off + 18, SEEK_SET);
662cabdff1aSopenharmony_ci    }
663cabdff1aSopenharmony_ci
664cabdff1aSopenharmony_ci    return 0;
665cabdff1aSopenharmony_ci}
666cabdff1aSopenharmony_ci
667cabdff1aSopenharmony_cistatic int get_num(AVIOContext *pb, int *len)
668cabdff1aSopenharmony_ci{
669cabdff1aSopenharmony_ci    int n, n1;
670cabdff1aSopenharmony_ci
671cabdff1aSopenharmony_ci    n = avio_rb16(pb);
672cabdff1aSopenharmony_ci    (*len)-=2;
673cabdff1aSopenharmony_ci    n &= 0x7FFF;
674cabdff1aSopenharmony_ci    if (n >= 0x4000) {
675cabdff1aSopenharmony_ci        return n - 0x4000;
676cabdff1aSopenharmony_ci    } else {
677cabdff1aSopenharmony_ci        n1 = avio_rb16(pb);
678cabdff1aSopenharmony_ci        (*len)-=2;
679cabdff1aSopenharmony_ci        return (n << 16) | n1;
680cabdff1aSopenharmony_ci    }
681cabdff1aSopenharmony_ci}
682cabdff1aSopenharmony_ci
683cabdff1aSopenharmony_ci/* multiple of 20 bytes for ra144 (ugly) */
684cabdff1aSopenharmony_ci#define RAW_PACKET_SIZE 1000
685cabdff1aSopenharmony_ci
686cabdff1aSopenharmony_cistatic int rm_sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
687cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
688cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
689cabdff1aSopenharmony_ci    AVStream *st;
690cabdff1aSopenharmony_ci    uint32_t state=0xFFFFFFFF;
691cabdff1aSopenharmony_ci
692cabdff1aSopenharmony_ci    while(!avio_feof(pb)){
693cabdff1aSopenharmony_ci        int len, num, i;
694cabdff1aSopenharmony_ci        int mlti_id;
695cabdff1aSopenharmony_ci        *pos= avio_tell(pb) - 3;
696cabdff1aSopenharmony_ci        if(rm->remaining_len > 0){
697cabdff1aSopenharmony_ci            num= rm->current_stream;
698cabdff1aSopenharmony_ci            mlti_id = 0;
699cabdff1aSopenharmony_ci            len= rm->remaining_len;
700cabdff1aSopenharmony_ci            *timestamp = AV_NOPTS_VALUE;
701cabdff1aSopenharmony_ci            *flags= 0;
702cabdff1aSopenharmony_ci        }else{
703cabdff1aSopenharmony_ci            state= (state<<8) + avio_r8(pb);
704cabdff1aSopenharmony_ci
705cabdff1aSopenharmony_ci            if(state == MKBETAG('I', 'N', 'D', 'X')){
706cabdff1aSopenharmony_ci                int n_pkts;
707cabdff1aSopenharmony_ci                int64_t expected_len;
708cabdff1aSopenharmony_ci                len = avio_rb32(pb);
709cabdff1aSopenharmony_ci                avio_skip(pb, 2);
710cabdff1aSopenharmony_ci                n_pkts = avio_rb32(pb);
711cabdff1aSopenharmony_ci                expected_len = 20 + n_pkts * 14LL;
712cabdff1aSopenharmony_ci
713cabdff1aSopenharmony_ci                if (len == 20 && expected_len <= INT_MAX)
714cabdff1aSopenharmony_ci                    /* some files don't add index entries to chunk size... */
715cabdff1aSopenharmony_ci                    len = expected_len;
716cabdff1aSopenharmony_ci                else if (len != expected_len)
717cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_WARNING,
718cabdff1aSopenharmony_ci                           "Index size %d (%d pkts) is wrong, should be %"PRId64".\n",
719cabdff1aSopenharmony_ci                           len, n_pkts, expected_len);
720cabdff1aSopenharmony_ci                if(len < 14)
721cabdff1aSopenharmony_ci                    continue;
722cabdff1aSopenharmony_ci                len -= 14; // we already read part of the index header
723cabdff1aSopenharmony_ci                goto skip;
724cabdff1aSopenharmony_ci            } else if (state == MKBETAG('D','A','T','A')) {
725cabdff1aSopenharmony_ci                av_log(s, AV_LOG_WARNING,
726cabdff1aSopenharmony_ci                       "DATA tag in middle of chunk, file may be broken.\n");
727cabdff1aSopenharmony_ci            }
728cabdff1aSopenharmony_ci
729cabdff1aSopenharmony_ci            if(state > (unsigned)0xFFFF || state <= 12)
730cabdff1aSopenharmony_ci                continue;
731cabdff1aSopenharmony_ci            len=state - 12;
732cabdff1aSopenharmony_ci            state= 0xFFFFFFFF;
733cabdff1aSopenharmony_ci
734cabdff1aSopenharmony_ci            num = avio_rb16(pb);
735cabdff1aSopenharmony_ci            *timestamp = avio_rb32(pb);
736cabdff1aSopenharmony_ci            mlti_id = (avio_r8(pb) >> 1) - 1;
737cabdff1aSopenharmony_ci            mlti_id = FFMAX(mlti_id, 0) << 16;
738cabdff1aSopenharmony_ci            *flags = avio_r8(pb); /* flags */
739cabdff1aSopenharmony_ci        }
740cabdff1aSopenharmony_ci        for(i=0;i<s->nb_streams;i++) {
741cabdff1aSopenharmony_ci            st = s->streams[i];
742cabdff1aSopenharmony_ci            if (mlti_id + num == st->id)
743cabdff1aSopenharmony_ci                break;
744cabdff1aSopenharmony_ci        }
745cabdff1aSopenharmony_ci        if (i == s->nb_streams) {
746cabdff1aSopenharmony_ciskip:
747cabdff1aSopenharmony_ci            /* skip packet if unknown number */
748cabdff1aSopenharmony_ci            avio_skip(pb, len);
749cabdff1aSopenharmony_ci            rm->remaining_len = 0;
750cabdff1aSopenharmony_ci            continue;
751cabdff1aSopenharmony_ci        }
752cabdff1aSopenharmony_ci        *stream_index= i;
753cabdff1aSopenharmony_ci
754cabdff1aSopenharmony_ci        return len;
755cabdff1aSopenharmony_ci    }
756cabdff1aSopenharmony_ci    return -1;
757cabdff1aSopenharmony_ci}
758cabdff1aSopenharmony_ci
759cabdff1aSopenharmony_cistatic int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
760cabdff1aSopenharmony_ci                                   RMDemuxContext *rm, RMStream *vst,
761cabdff1aSopenharmony_ci                                   AVPacket *pkt, int len, int *pseq,
762cabdff1aSopenharmony_ci                                   int64_t *timestamp)
763cabdff1aSopenharmony_ci{
764cabdff1aSopenharmony_ci    int hdr;
765cabdff1aSopenharmony_ci    int seq = 0, pic_num = 0, len2 = 0, pos = 0; //init to silence compiler warning
766cabdff1aSopenharmony_ci    int type;
767cabdff1aSopenharmony_ci    int ret;
768cabdff1aSopenharmony_ci
769cabdff1aSopenharmony_ci    hdr = avio_r8(pb); len--;
770cabdff1aSopenharmony_ci    type = hdr >> 6;
771cabdff1aSopenharmony_ci
772cabdff1aSopenharmony_ci    if(type != 3){  // not frame as a part of packet
773cabdff1aSopenharmony_ci        seq = avio_r8(pb); len--;
774cabdff1aSopenharmony_ci    }
775cabdff1aSopenharmony_ci    if(type != 1){  // not whole frame
776cabdff1aSopenharmony_ci        len2 = get_num(pb, &len);
777cabdff1aSopenharmony_ci        pos  = get_num(pb, &len);
778cabdff1aSopenharmony_ci        pic_num = avio_r8(pb); len--;
779cabdff1aSopenharmony_ci    }
780cabdff1aSopenharmony_ci    if(len<0) {
781cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Insufficient data\n");
782cabdff1aSopenharmony_ci        return -1;
783cabdff1aSopenharmony_ci    }
784cabdff1aSopenharmony_ci    rm->remaining_len = len;
785cabdff1aSopenharmony_ci    if(type&1){     // frame, not slice
786cabdff1aSopenharmony_ci        if(type == 3){  // frame as a part of packet
787cabdff1aSopenharmony_ci            len= len2;
788cabdff1aSopenharmony_ci            *timestamp = pos;
789cabdff1aSopenharmony_ci        }
790cabdff1aSopenharmony_ci        if(rm->remaining_len < len) {
791cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Insufficient remaining len\n");
792cabdff1aSopenharmony_ci            return -1;
793cabdff1aSopenharmony_ci        }
794cabdff1aSopenharmony_ci        rm->remaining_len -= len;
795cabdff1aSopenharmony_ci        if ((ret = av_new_packet(pkt, len + 9)) < 0)
796cabdff1aSopenharmony_ci            return ret;
797cabdff1aSopenharmony_ci        pkt->data[0] = 0;
798cabdff1aSopenharmony_ci        AV_WL32(pkt->data + 1, 1);
799cabdff1aSopenharmony_ci        AV_WL32(pkt->data + 5, 0);
800cabdff1aSopenharmony_ci        if ((ret = avio_read(pb, pkt->data + 9, len)) != len) {
801cabdff1aSopenharmony_ci            av_packet_unref(pkt);
802cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Failed to read %d bytes\n", len);
803cabdff1aSopenharmony_ci            return ret < 0 ? ret : AVERROR(EIO);
804cabdff1aSopenharmony_ci        }
805cabdff1aSopenharmony_ci        return 0;
806cabdff1aSopenharmony_ci    }
807cabdff1aSopenharmony_ci    //now we have to deal with single slice
808cabdff1aSopenharmony_ci
809cabdff1aSopenharmony_ci    *pseq = seq;
810cabdff1aSopenharmony_ci    if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){
811cabdff1aSopenharmony_ci        if (len2 > ffio_limit(pb, len2)) {
812cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "Impossibly sized packet\n");
813cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
814cabdff1aSopenharmony_ci        }
815cabdff1aSopenharmony_ci        vst->slices = ((hdr & 0x3F) << 1) + 1;
816cabdff1aSopenharmony_ci        vst->videobufsize = len2 + 8*vst->slices + 1;
817cabdff1aSopenharmony_ci        av_packet_unref(&vst->pkt); //FIXME this should be output.
818cabdff1aSopenharmony_ci        if ((ret = av_new_packet(&vst->pkt, vst->videobufsize)) < 0)
819cabdff1aSopenharmony_ci            return ret;
820cabdff1aSopenharmony_ci        vst->videobufpos = 8*vst->slices + 1;
821cabdff1aSopenharmony_ci        vst->cur_slice = 0;
822cabdff1aSopenharmony_ci        vst->curpic_num = pic_num;
823cabdff1aSopenharmony_ci        vst->pktpos = avio_tell(pb);
824cabdff1aSopenharmony_ci    }
825cabdff1aSopenharmony_ci    if(type == 2)
826cabdff1aSopenharmony_ci        len = FFMIN(len, pos);
827cabdff1aSopenharmony_ci
828cabdff1aSopenharmony_ci    if(++vst->cur_slice > vst->slices) {
829cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "cur slice %d, too large\n", vst->cur_slice);
830cabdff1aSopenharmony_ci        return 1;
831cabdff1aSopenharmony_ci    }
832cabdff1aSopenharmony_ci    if(!vst->pkt.data)
833cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
834cabdff1aSopenharmony_ci    AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1);
835cabdff1aSopenharmony_ci    AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1);
836cabdff1aSopenharmony_ci    if(vst->videobufpos + len > vst->videobufsize) {
837cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "outside videobufsize\n");
838cabdff1aSopenharmony_ci        return 1;
839cabdff1aSopenharmony_ci    }
840cabdff1aSopenharmony_ci    if (avio_read(pb, vst->pkt.data + vst->videobufpos, len) != len)
841cabdff1aSopenharmony_ci        return AVERROR(EIO);
842cabdff1aSopenharmony_ci    vst->videobufpos += len;
843cabdff1aSopenharmony_ci    rm->remaining_len-= len;
844cabdff1aSopenharmony_ci
845cabdff1aSopenharmony_ci    if (type == 2 || vst->videobufpos == vst->videobufsize) {
846cabdff1aSopenharmony_ci        vst->pkt.data[0] = vst->cur_slice-1;
847cabdff1aSopenharmony_ci        av_packet_move_ref(pkt, &vst->pkt);
848cabdff1aSopenharmony_ci        if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin
849cabdff1aSopenharmony_ci            memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
850cabdff1aSopenharmony_ci                vst->videobufpos - 1 - 8*vst->slices);
851cabdff1aSopenharmony_ci        av_shrink_packet(pkt, vst->videobufpos + 8*(vst->cur_slice - vst->slices));
852cabdff1aSopenharmony_ci        pkt->pts = AV_NOPTS_VALUE;
853cabdff1aSopenharmony_ci        pkt->pos = vst->pktpos;
854cabdff1aSopenharmony_ci        vst->slices = 0;
855cabdff1aSopenharmony_ci        return 0;
856cabdff1aSopenharmony_ci    }
857cabdff1aSopenharmony_ci
858cabdff1aSopenharmony_ci    return 1;
859cabdff1aSopenharmony_ci}
860cabdff1aSopenharmony_ci
861cabdff1aSopenharmony_cistatic inline void
862cabdff1aSopenharmony_cirm_ac3_swap_bytes (AVStream *st, AVPacket *pkt)
863cabdff1aSopenharmony_ci{
864cabdff1aSopenharmony_ci    uint8_t *ptr;
865cabdff1aSopenharmony_ci    int j;
866cabdff1aSopenharmony_ci
867cabdff1aSopenharmony_ci    if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
868cabdff1aSopenharmony_ci        ptr = pkt->data;
869cabdff1aSopenharmony_ci        for (j=0;j<pkt->size;j+=2) {
870cabdff1aSopenharmony_ci            FFSWAP(int, ptr[0], ptr[1]);
871cabdff1aSopenharmony_ci            ptr += 2;
872cabdff1aSopenharmony_ci        }
873cabdff1aSopenharmony_ci    }
874cabdff1aSopenharmony_ci}
875cabdff1aSopenharmony_ci
876cabdff1aSopenharmony_cistatic int readfull(AVFormatContext *s, AVIOContext *pb, uint8_t *dst, int n) {
877cabdff1aSopenharmony_ci    int ret = avio_read(pb, dst, n);
878cabdff1aSopenharmony_ci    if (ret != n) {
879cabdff1aSopenharmony_ci        if (ret >= 0) memset(dst + ret, 0, n - ret);
880cabdff1aSopenharmony_ci        else          memset(dst      , 0, n);
881cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Failed to fully read block\n");
882cabdff1aSopenharmony_ci    }
883cabdff1aSopenharmony_ci    return ret;
884cabdff1aSopenharmony_ci}
885cabdff1aSopenharmony_ci
886cabdff1aSopenharmony_ciint
887cabdff1aSopenharmony_ciff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
888cabdff1aSopenharmony_ci                    AVStream *st, RMStream *ast, int len, AVPacket *pkt,
889cabdff1aSopenharmony_ci                    int *seq, int flags, int64_t timestamp)
890cabdff1aSopenharmony_ci{
891cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
892cabdff1aSopenharmony_ci    int ret;
893cabdff1aSopenharmony_ci
894cabdff1aSopenharmony_ci    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
895cabdff1aSopenharmony_ci        rm->current_stream= st->id;
896cabdff1aSopenharmony_ci        ret = rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, &timestamp);
897cabdff1aSopenharmony_ci        if(ret)
898cabdff1aSopenharmony_ci            return ret < 0 ? ret : -1; //got partial frame or error
899cabdff1aSopenharmony_ci    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
900cabdff1aSopenharmony_ci        if ((ast->deint_id == DEINT_ID_GENR) ||
901cabdff1aSopenharmony_ci            (ast->deint_id == DEINT_ID_INT4) ||
902cabdff1aSopenharmony_ci            (ast->deint_id == DEINT_ID_SIPR)) {
903cabdff1aSopenharmony_ci            int x;
904cabdff1aSopenharmony_ci            int sps = ast->sub_packet_size;
905cabdff1aSopenharmony_ci            int cfs = ast->coded_framesize;
906cabdff1aSopenharmony_ci            int h = ast->sub_packet_h;
907cabdff1aSopenharmony_ci            int y = ast->sub_packet_cnt;
908cabdff1aSopenharmony_ci            int w = ast->audio_framesize;
909cabdff1aSopenharmony_ci
910cabdff1aSopenharmony_ci            if (flags & 2)
911cabdff1aSopenharmony_ci                y = ast->sub_packet_cnt = 0;
912cabdff1aSopenharmony_ci            if (!y)
913cabdff1aSopenharmony_ci                ast->audiotimestamp = timestamp;
914cabdff1aSopenharmony_ci
915cabdff1aSopenharmony_ci            switch (ast->deint_id) {
916cabdff1aSopenharmony_ci                case DEINT_ID_INT4:
917cabdff1aSopenharmony_ci                    for (x = 0; x < h/2; x++)
918cabdff1aSopenharmony_ci                        readfull(s, pb, ast->pkt.data+x*2*w+y*cfs, cfs);
919cabdff1aSopenharmony_ci                    break;
920cabdff1aSopenharmony_ci                case DEINT_ID_GENR:
921cabdff1aSopenharmony_ci                    for (x = 0; x < w/sps; x++)
922cabdff1aSopenharmony_ci                        readfull(s, pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps);
923cabdff1aSopenharmony_ci                    break;
924cabdff1aSopenharmony_ci                case DEINT_ID_SIPR:
925cabdff1aSopenharmony_ci                    readfull(s, pb, ast->pkt.data + y * w, w);
926cabdff1aSopenharmony_ci                    break;
927cabdff1aSopenharmony_ci            }
928cabdff1aSopenharmony_ci
929cabdff1aSopenharmony_ci            if (++(ast->sub_packet_cnt) < h)
930cabdff1aSopenharmony_ci                return -1;
931cabdff1aSopenharmony_ci            if (ast->deint_id == DEINT_ID_SIPR)
932cabdff1aSopenharmony_ci                ff_rm_reorder_sipr_data(ast->pkt.data, h, w);
933cabdff1aSopenharmony_ci
934cabdff1aSopenharmony_ci             ast->sub_packet_cnt = 0;
935cabdff1aSopenharmony_ci             rm->audio_stream_num = st->index;
936cabdff1aSopenharmony_ci            if (st->codecpar->block_align <= 0) {
937cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Invalid block alignment %d\n", st->codecpar->block_align);
938cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
939cabdff1aSopenharmony_ci            }
940cabdff1aSopenharmony_ci             rm->audio_pkt_cnt = h * w / st->codecpar->block_align;
941cabdff1aSopenharmony_ci        } else if ((ast->deint_id == DEINT_ID_VBRF) ||
942cabdff1aSopenharmony_ci                   (ast->deint_id == DEINT_ID_VBRS)) {
943cabdff1aSopenharmony_ci            int x;
944cabdff1aSopenharmony_ci            rm->audio_stream_num = st->index;
945cabdff1aSopenharmony_ci            ast->sub_packet_cnt = (avio_rb16(pb) & 0xf0) >> 4;
946cabdff1aSopenharmony_ci            if (ast->sub_packet_cnt) {
947cabdff1aSopenharmony_ci                for (x = 0; x < ast->sub_packet_cnt; x++)
948cabdff1aSopenharmony_ci                    ast->sub_packet_lengths[x] = avio_rb16(pb);
949cabdff1aSopenharmony_ci                rm->audio_pkt_cnt = ast->sub_packet_cnt;
950cabdff1aSopenharmony_ci                ast->audiotimestamp = timestamp;
951cabdff1aSopenharmony_ci            } else
952cabdff1aSopenharmony_ci                return -1;
953cabdff1aSopenharmony_ci        } else {
954cabdff1aSopenharmony_ci            ret = av_get_packet(pb, pkt, len);
955cabdff1aSopenharmony_ci            if (ret < 0)
956cabdff1aSopenharmony_ci                return ret;
957cabdff1aSopenharmony_ci            rm_ac3_swap_bytes(st, pkt);
958cabdff1aSopenharmony_ci        }
959cabdff1aSopenharmony_ci    } else {
960cabdff1aSopenharmony_ci        ret = av_get_packet(pb, pkt, len);
961cabdff1aSopenharmony_ci        if (ret < 0)
962cabdff1aSopenharmony_ci            return ret;
963cabdff1aSopenharmony_ci    }
964cabdff1aSopenharmony_ci
965cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
966cabdff1aSopenharmony_ci
967cabdff1aSopenharmony_ci    pkt->pts = timestamp;
968cabdff1aSopenharmony_ci    if (flags & 2)
969cabdff1aSopenharmony_ci        pkt->flags |= AV_PKT_FLAG_KEY;
970cabdff1aSopenharmony_ci
971cabdff1aSopenharmony_ci    return st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
972cabdff1aSopenharmony_ci}
973cabdff1aSopenharmony_ci
974cabdff1aSopenharmony_ciint
975cabdff1aSopenharmony_ciff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb,
976cabdff1aSopenharmony_ci                      AVStream *st, RMStream *ast, AVPacket *pkt)
977cabdff1aSopenharmony_ci{
978cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
979cabdff1aSopenharmony_ci    int ret;
980cabdff1aSopenharmony_ci
981cabdff1aSopenharmony_ci    av_assert0 (rm->audio_pkt_cnt > 0);
982cabdff1aSopenharmony_ci
983cabdff1aSopenharmony_ci    if (ast->deint_id == DEINT_ID_VBRF ||
984cabdff1aSopenharmony_ci        ast->deint_id == DEINT_ID_VBRS) {
985cabdff1aSopenharmony_ci        ret = av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]);
986cabdff1aSopenharmony_ci        if (ret < 0)
987cabdff1aSopenharmony_ci            return ret;
988cabdff1aSopenharmony_ci    } else {
989cabdff1aSopenharmony_ci        ret = av_new_packet(pkt, st->codecpar->block_align);
990cabdff1aSopenharmony_ci        if (ret < 0)
991cabdff1aSopenharmony_ci            return ret;
992cabdff1aSopenharmony_ci        memcpy(pkt->data, ast->pkt.data + st->codecpar->block_align * //FIXME avoid this
993cabdff1aSopenharmony_ci               (ast->sub_packet_h * ast->audio_framesize / st->codecpar->block_align - rm->audio_pkt_cnt),
994cabdff1aSopenharmony_ci               st->codecpar->block_align);
995cabdff1aSopenharmony_ci    }
996cabdff1aSopenharmony_ci    rm->audio_pkt_cnt--;
997cabdff1aSopenharmony_ci    if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
998cabdff1aSopenharmony_ci        ast->audiotimestamp = AV_NOPTS_VALUE;
999cabdff1aSopenharmony_ci        pkt->flags = AV_PKT_FLAG_KEY;
1000cabdff1aSopenharmony_ci    } else
1001cabdff1aSopenharmony_ci        pkt->flags = 0;
1002cabdff1aSopenharmony_ci    pkt->stream_index = st->index;
1003cabdff1aSopenharmony_ci
1004cabdff1aSopenharmony_ci    return rm->audio_pkt_cnt;
1005cabdff1aSopenharmony_ci}
1006cabdff1aSopenharmony_ci
1007cabdff1aSopenharmony_cistatic int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
1008cabdff1aSopenharmony_ci{
1009cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
1010cabdff1aSopenharmony_ci    AVStream *st = NULL; // init to silence compiler warning
1011cabdff1aSopenharmony_ci    int i, res, seq = 1;
1012cabdff1aSopenharmony_ci    int64_t timestamp, pos, len;
1013cabdff1aSopenharmony_ci    int flags;
1014cabdff1aSopenharmony_ci
1015cabdff1aSopenharmony_ci    for (;;) {
1016cabdff1aSopenharmony_ci        if (rm->audio_pkt_cnt) {
1017cabdff1aSopenharmony_ci            // If there are queued audio packet return them first
1018cabdff1aSopenharmony_ci            st = s->streams[rm->audio_stream_num];
1019cabdff1aSopenharmony_ci            res = ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
1020cabdff1aSopenharmony_ci            if(res < 0)
1021cabdff1aSopenharmony_ci                return res;
1022cabdff1aSopenharmony_ci            flags = 0;
1023cabdff1aSopenharmony_ci        } else {
1024cabdff1aSopenharmony_ci            if (rm->old_format) {
1025cabdff1aSopenharmony_ci                RMStream *ast;
1026cabdff1aSopenharmony_ci
1027cabdff1aSopenharmony_ci                st = s->streams[0];
1028cabdff1aSopenharmony_ci                ast = st->priv_data;
1029cabdff1aSopenharmony_ci                timestamp = AV_NOPTS_VALUE;
1030cabdff1aSopenharmony_ci                len = !ast->audio_framesize ? RAW_PACKET_SIZE :
1031cabdff1aSopenharmony_ci                    ast->coded_framesize * (int64_t)ast->sub_packet_h / 2;
1032cabdff1aSopenharmony_ci                if (len > INT_MAX)
1033cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1034cabdff1aSopenharmony_ci                flags = (seq++ == 1) ? 2 : 0;
1035cabdff1aSopenharmony_ci                pos = avio_tell(s->pb);
1036cabdff1aSopenharmony_ci            } else {
1037cabdff1aSopenharmony_ci                len = rm_sync(s, &timestamp, &flags, &i, &pos);
1038cabdff1aSopenharmony_ci                if (len > 0)
1039cabdff1aSopenharmony_ci                    st = s->streams[i];
1040cabdff1aSopenharmony_ci            }
1041cabdff1aSopenharmony_ci
1042cabdff1aSopenharmony_ci            if (avio_feof(s->pb))
1043cabdff1aSopenharmony_ci                return AVERROR_EOF;
1044cabdff1aSopenharmony_ci            if (len <= 0)
1045cabdff1aSopenharmony_ci                return AVERROR(EIO);
1046cabdff1aSopenharmony_ci
1047cabdff1aSopenharmony_ci            res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
1048cabdff1aSopenharmony_ci                                      &seq, flags, timestamp);
1049cabdff1aSopenharmony_ci            if (res < -1)
1050cabdff1aSopenharmony_ci                return res;
1051cabdff1aSopenharmony_ci            if((flags&2) && (seq&0x7F) == 1)
1052cabdff1aSopenharmony_ci                av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
1053cabdff1aSopenharmony_ci            if (res)
1054cabdff1aSopenharmony_ci                continue;
1055cabdff1aSopenharmony_ci        }
1056cabdff1aSopenharmony_ci
1057cabdff1aSopenharmony_ci        if(  (st->discard >= AVDISCARD_NONKEY && !(flags&2))
1058cabdff1aSopenharmony_ci           || st->discard >= AVDISCARD_ALL){
1059cabdff1aSopenharmony_ci            av_packet_unref(pkt);
1060cabdff1aSopenharmony_ci        } else
1061cabdff1aSopenharmony_ci            break;
1062cabdff1aSopenharmony_ci    }
1063cabdff1aSopenharmony_ci
1064cabdff1aSopenharmony_ci    return 0;
1065cabdff1aSopenharmony_ci}
1066cabdff1aSopenharmony_ci
1067cabdff1aSopenharmony_cistatic int rm_read_close(AVFormatContext *s)
1068cabdff1aSopenharmony_ci{
1069cabdff1aSopenharmony_ci    int i;
1070cabdff1aSopenharmony_ci
1071cabdff1aSopenharmony_ci    for (i=0;i<s->nb_streams;i++)
1072cabdff1aSopenharmony_ci        ff_rm_free_rmstream(s->streams[i]->priv_data);
1073cabdff1aSopenharmony_ci
1074cabdff1aSopenharmony_ci    return 0;
1075cabdff1aSopenharmony_ci}
1076cabdff1aSopenharmony_ci
1077cabdff1aSopenharmony_cistatic int rm_probe(const AVProbeData *p)
1078cabdff1aSopenharmony_ci{
1079cabdff1aSopenharmony_ci    /* check file header */
1080cabdff1aSopenharmony_ci    if ((p->buf[0] == '.' && p->buf[1] == 'R' &&
1081cabdff1aSopenharmony_ci         p->buf[2] == 'M' && p->buf[3] == 'F' &&
1082cabdff1aSopenharmony_ci         p->buf[4] == 0 && p->buf[5] == 0) ||
1083cabdff1aSopenharmony_ci        (p->buf[0] == '.' && p->buf[1] == 'r' &&
1084cabdff1aSopenharmony_ci         p->buf[2] == 'a' && p->buf[3] == 0xfd))
1085cabdff1aSopenharmony_ci        return AVPROBE_SCORE_MAX;
1086cabdff1aSopenharmony_ci    else
1087cabdff1aSopenharmony_ci        return 0;
1088cabdff1aSopenharmony_ci}
1089cabdff1aSopenharmony_ci
1090cabdff1aSopenharmony_cistatic int64_t rm_read_dts(AVFormatContext *s, int stream_index,
1091cabdff1aSopenharmony_ci                               int64_t *ppos, int64_t pos_limit)
1092cabdff1aSopenharmony_ci{
1093cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
1094cabdff1aSopenharmony_ci    int64_t pos, dts;
1095cabdff1aSopenharmony_ci    int stream_index2, flags, len, h;
1096cabdff1aSopenharmony_ci
1097cabdff1aSopenharmony_ci    pos = *ppos;
1098cabdff1aSopenharmony_ci
1099cabdff1aSopenharmony_ci    if(rm->old_format)
1100cabdff1aSopenharmony_ci        return AV_NOPTS_VALUE;
1101cabdff1aSopenharmony_ci
1102cabdff1aSopenharmony_ci    if (avio_seek(s->pb, pos, SEEK_SET) < 0)
1103cabdff1aSopenharmony_ci        return AV_NOPTS_VALUE;
1104cabdff1aSopenharmony_ci
1105cabdff1aSopenharmony_ci    rm->remaining_len=0;
1106cabdff1aSopenharmony_ci    for(;;){
1107cabdff1aSopenharmony_ci        int seq=1;
1108cabdff1aSopenharmony_ci        AVStream *st;
1109cabdff1aSopenharmony_ci
1110cabdff1aSopenharmony_ci        len = rm_sync(s, &dts, &flags, &stream_index2, &pos);
1111cabdff1aSopenharmony_ci        if(len<0)
1112cabdff1aSopenharmony_ci            return AV_NOPTS_VALUE;
1113cabdff1aSopenharmony_ci
1114cabdff1aSopenharmony_ci        st = s->streams[stream_index2];
1115cabdff1aSopenharmony_ci        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1116cabdff1aSopenharmony_ci            h= avio_r8(s->pb); len--;
1117cabdff1aSopenharmony_ci            if(!(h & 0x40)){
1118cabdff1aSopenharmony_ci                seq = avio_r8(s->pb); len--;
1119cabdff1aSopenharmony_ci            }
1120cabdff1aSopenharmony_ci        }
1121cabdff1aSopenharmony_ci
1122cabdff1aSopenharmony_ci        if((flags&2) && (seq&0x7F) == 1){
1123cabdff1aSopenharmony_ci            av_log(s, AV_LOG_TRACE, "%d %d-%d %"PRId64" %d\n",
1124cabdff1aSopenharmony_ci                    flags, stream_index2, stream_index, dts, seq);
1125cabdff1aSopenharmony_ci            av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME);
1126cabdff1aSopenharmony_ci            if(stream_index2 == stream_index)
1127cabdff1aSopenharmony_ci                break;
1128cabdff1aSopenharmony_ci        }
1129cabdff1aSopenharmony_ci
1130cabdff1aSopenharmony_ci        avio_skip(s->pb, len);
1131cabdff1aSopenharmony_ci    }
1132cabdff1aSopenharmony_ci    *ppos = pos;
1133cabdff1aSopenharmony_ci    return dts;
1134cabdff1aSopenharmony_ci}
1135cabdff1aSopenharmony_ci
1136cabdff1aSopenharmony_cistatic int rm_read_seek(AVFormatContext *s, int stream_index,
1137cabdff1aSopenharmony_ci                        int64_t pts, int flags)
1138cabdff1aSopenharmony_ci{
1139cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
1140cabdff1aSopenharmony_ci
1141cabdff1aSopenharmony_ci    if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0)
1142cabdff1aSopenharmony_ci        return -1;
1143cabdff1aSopenharmony_ci    rm->audio_pkt_cnt = 0;
1144cabdff1aSopenharmony_ci    return 0;
1145cabdff1aSopenharmony_ci}
1146cabdff1aSopenharmony_ci
1147cabdff1aSopenharmony_ci
1148cabdff1aSopenharmony_ciconst AVInputFormat ff_rm_demuxer = {
1149cabdff1aSopenharmony_ci    .name           = "rm",
1150cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("RealMedia"),
1151cabdff1aSopenharmony_ci    .priv_data_size = sizeof(RMDemuxContext),
1152cabdff1aSopenharmony_ci    .flags_internal = FF_FMT_INIT_CLEANUP,
1153cabdff1aSopenharmony_ci    .read_probe     = rm_probe,
1154cabdff1aSopenharmony_ci    .read_header    = rm_read_header,
1155cabdff1aSopenharmony_ci    .read_packet    = rm_read_packet,
1156cabdff1aSopenharmony_ci    .read_close     = rm_read_close,
1157cabdff1aSopenharmony_ci    .read_timestamp = rm_read_dts,
1158cabdff1aSopenharmony_ci    .read_seek      = rm_read_seek,
1159cabdff1aSopenharmony_ci};
1160cabdff1aSopenharmony_ci
1161cabdff1aSopenharmony_ciconst AVInputFormat ff_rdt_demuxer = {
1162cabdff1aSopenharmony_ci    .name           = "rdt",
1163cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("RDT demuxer"),
1164cabdff1aSopenharmony_ci    .priv_data_size = sizeof(RMDemuxContext),
1165cabdff1aSopenharmony_ci    .read_close     = rm_read_close,
1166cabdff1aSopenharmony_ci    .flags          = AVFMT_NOFILE,
1167cabdff1aSopenharmony_ci};
1168cabdff1aSopenharmony_ci
1169cabdff1aSopenharmony_cistatic int ivr_probe(const AVProbeData *p)
1170cabdff1aSopenharmony_ci{
1171cabdff1aSopenharmony_ci    if (memcmp(p->buf, ".R1M\x0\x1\x1", 7) &&
1172cabdff1aSopenharmony_ci        memcmp(p->buf, ".REC", 4))
1173cabdff1aSopenharmony_ci        return 0;
1174cabdff1aSopenharmony_ci
1175cabdff1aSopenharmony_ci    return AVPROBE_SCORE_MAX;
1176cabdff1aSopenharmony_ci}
1177cabdff1aSopenharmony_ci
1178cabdff1aSopenharmony_cistatic int ivr_read_header(AVFormatContext *s)
1179cabdff1aSopenharmony_ci{
1180cabdff1aSopenharmony_ci    unsigned tag, type, len, tlen, value;
1181cabdff1aSopenharmony_ci    int i, j, n, count, nb_streams = 0, ret;
1182cabdff1aSopenharmony_ci    uint8_t key[256], val[256];
1183cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1184cabdff1aSopenharmony_ci    AVStream *st;
1185cabdff1aSopenharmony_ci    int64_t pos, offset=0, temp;
1186cabdff1aSopenharmony_ci
1187cabdff1aSopenharmony_ci    pos = avio_tell(pb);
1188cabdff1aSopenharmony_ci    tag = avio_rl32(pb);
1189cabdff1aSopenharmony_ci    if (tag == MKTAG('.','R','1','M')) {
1190cabdff1aSopenharmony_ci        if (avio_rb16(pb) != 1)
1191cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1192cabdff1aSopenharmony_ci        if (avio_r8(pb) != 1)
1193cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1194cabdff1aSopenharmony_ci        len = avio_rb32(pb);
1195cabdff1aSopenharmony_ci        avio_skip(pb, len);
1196cabdff1aSopenharmony_ci        avio_skip(pb, 5);
1197cabdff1aSopenharmony_ci        temp = avio_rb64(pb);
1198cabdff1aSopenharmony_ci        while (!avio_feof(pb) && temp) {
1199cabdff1aSopenharmony_ci            offset = temp;
1200cabdff1aSopenharmony_ci            temp = avio_rb64(pb);
1201cabdff1aSopenharmony_ci        }
1202cabdff1aSopenharmony_ci        if (offset <= 0)
1203cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1204cabdff1aSopenharmony_ci        avio_skip(pb, offset - avio_tell(pb));
1205cabdff1aSopenharmony_ci        if (avio_r8(pb) != 1)
1206cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1207cabdff1aSopenharmony_ci        len = avio_rb32(pb);
1208cabdff1aSopenharmony_ci        avio_skip(pb, len);
1209cabdff1aSopenharmony_ci        if (avio_r8(pb) != 2)
1210cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1211cabdff1aSopenharmony_ci        avio_skip(pb, 16);
1212cabdff1aSopenharmony_ci        pos = avio_tell(pb);
1213cabdff1aSopenharmony_ci        tag = avio_rl32(pb);
1214cabdff1aSopenharmony_ci    }
1215cabdff1aSopenharmony_ci
1216cabdff1aSopenharmony_ci    if (tag != MKTAG('.','R','E','C'))
1217cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1218cabdff1aSopenharmony_ci
1219cabdff1aSopenharmony_ci    if (avio_r8(pb) != 0)
1220cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1221cabdff1aSopenharmony_ci    count = avio_rb32(pb);
1222cabdff1aSopenharmony_ci    for (i = 0; i < count; i++) {
1223cabdff1aSopenharmony_ci        if (avio_feof(pb))
1224cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1225cabdff1aSopenharmony_ci
1226cabdff1aSopenharmony_ci        type = avio_r8(pb);
1227cabdff1aSopenharmony_ci        tlen = avio_rb32(pb);
1228cabdff1aSopenharmony_ci        avio_get_str(pb, tlen, key, sizeof(key));
1229cabdff1aSopenharmony_ci        len = avio_rb32(pb);
1230cabdff1aSopenharmony_ci        if (type == 5) {
1231cabdff1aSopenharmony_ci            avio_get_str(pb, len, val, sizeof(val));
1232cabdff1aSopenharmony_ci            av_log(s, AV_LOG_DEBUG, "%s = '%s'\n", key, val);
1233cabdff1aSopenharmony_ci        } else if (type == 4) {
1234cabdff1aSopenharmony_ci            av_log(s, AV_LOG_DEBUG, "%s = '0x", key);
1235cabdff1aSopenharmony_ci            for (j = 0; j < len; j++) {
1236cabdff1aSopenharmony_ci                if (avio_feof(pb))
1237cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1238cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "%X", avio_r8(pb));
1239cabdff1aSopenharmony_ci            }
1240cabdff1aSopenharmony_ci            av_log(s, AV_LOG_DEBUG, "'\n");
1241cabdff1aSopenharmony_ci        } else if (len == 4 && type == 3 && !strncmp(key, "StreamCount", tlen)) {
1242cabdff1aSopenharmony_ci            nb_streams = value = avio_rb32(pb);
1243cabdff1aSopenharmony_ci        } else if (len == 4 && type == 3) {
1244cabdff1aSopenharmony_ci            value = avio_rb32(pb);
1245cabdff1aSopenharmony_ci            av_log(s, AV_LOG_DEBUG, "%s = %d\n", key, value);
1246cabdff1aSopenharmony_ci        } else {
1247cabdff1aSopenharmony_ci            av_log(s, AV_LOG_DEBUG, "Skipping unsupported key: %s\n", key);
1248cabdff1aSopenharmony_ci            avio_skip(pb, len);
1249cabdff1aSopenharmony_ci        }
1250cabdff1aSopenharmony_ci    }
1251cabdff1aSopenharmony_ci
1252cabdff1aSopenharmony_ci    for (n = 0; n < nb_streams; n++) {
1253cabdff1aSopenharmony_ci        if (!(st = avformat_new_stream(s, NULL)) ||
1254cabdff1aSopenharmony_ci            !(st->priv_data = ff_rm_alloc_rmstream()))
1255cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
1256cabdff1aSopenharmony_ci
1257cabdff1aSopenharmony_ci        if (avio_r8(pb) != 1)
1258cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
1259cabdff1aSopenharmony_ci
1260cabdff1aSopenharmony_ci        count = avio_rb32(pb);
1261cabdff1aSopenharmony_ci        for (i = 0; i < count; i++) {
1262cabdff1aSopenharmony_ci            if (avio_feof(pb))
1263cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
1264cabdff1aSopenharmony_ci
1265cabdff1aSopenharmony_ci            type = avio_r8(pb);
1266cabdff1aSopenharmony_ci            tlen  = avio_rb32(pb);
1267cabdff1aSopenharmony_ci            avio_get_str(pb, tlen, key, sizeof(key));
1268cabdff1aSopenharmony_ci            len  = avio_rb32(pb);
1269cabdff1aSopenharmony_ci            if (type == 5) {
1270cabdff1aSopenharmony_ci                avio_get_str(pb, len, val, sizeof(val));
1271cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "%s = '%s'\n", key, val);
1272cabdff1aSopenharmony_ci            } else if (type == 4 && !strncmp(key, "OpaqueData", tlen)) {
1273cabdff1aSopenharmony_ci                ret = ffio_ensure_seekback(pb, 4);
1274cabdff1aSopenharmony_ci                if (ret < 0)
1275cabdff1aSopenharmony_ci                    return ret;
1276cabdff1aSopenharmony_ci                if (avio_rb32(pb) == MKBETAG('M', 'L', 'T', 'I')) {
1277cabdff1aSopenharmony_ci                    ret = rm_read_multi(s, pb, st, NULL);
1278cabdff1aSopenharmony_ci                } else {
1279cabdff1aSopenharmony_ci                    if (avio_feof(pb))
1280cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
1281cabdff1aSopenharmony_ci                    avio_seek(pb, -4, SEEK_CUR);
1282cabdff1aSopenharmony_ci                    ret = ff_rm_read_mdpr_codecdata(s, pb, st, st->priv_data, len, NULL);
1283cabdff1aSopenharmony_ci                }
1284cabdff1aSopenharmony_ci
1285cabdff1aSopenharmony_ci                if (ret < 0)
1286cabdff1aSopenharmony_ci                    return ret;
1287cabdff1aSopenharmony_ci            } else if (type == 4) {
1288cabdff1aSopenharmony_ci                int j;
1289cabdff1aSopenharmony_ci
1290cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "%s = '0x", key);
1291cabdff1aSopenharmony_ci                for (j = 0; j < len; j++) {
1292cabdff1aSopenharmony_ci                    if (avio_feof(pb))
1293cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
1294cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_DEBUG, "%X", avio_r8(pb));
1295cabdff1aSopenharmony_ci                }
1296cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "'\n");
1297cabdff1aSopenharmony_ci            } else if (len == 4 && type == 3 && !strncmp(key, "Duration", tlen)) {
1298cabdff1aSopenharmony_ci                st->duration = avio_rb32(pb);
1299cabdff1aSopenharmony_ci            } else if (len == 4 && type == 3) {
1300cabdff1aSopenharmony_ci                value = avio_rb32(pb);
1301cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "%s = %d\n", key, value);
1302cabdff1aSopenharmony_ci            } else {
1303cabdff1aSopenharmony_ci                av_log(s, AV_LOG_DEBUG, "Skipping unsupported key: %s\n", key);
1304cabdff1aSopenharmony_ci                avio_skip(pb, len);
1305cabdff1aSopenharmony_ci            }
1306cabdff1aSopenharmony_ci        }
1307cabdff1aSopenharmony_ci    }
1308cabdff1aSopenharmony_ci
1309cabdff1aSopenharmony_ci    if (avio_r8(pb) != 6)
1310cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1311cabdff1aSopenharmony_ci    avio_skip(pb, 12);
1312cabdff1aSopenharmony_ci    avio_seek(pb, avio_rb64(pb) + pos, SEEK_SET);
1313cabdff1aSopenharmony_ci    if (avio_r8(pb) != 8)
1314cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1315cabdff1aSopenharmony_ci    avio_skip(pb, 8);
1316cabdff1aSopenharmony_ci
1317cabdff1aSopenharmony_ci    return 0;
1318cabdff1aSopenharmony_ci}
1319cabdff1aSopenharmony_ci
1320cabdff1aSopenharmony_cistatic int ivr_read_packet(AVFormatContext *s, AVPacket *pkt)
1321cabdff1aSopenharmony_ci{
1322cabdff1aSopenharmony_ci    RMDemuxContext *rm = s->priv_data;
1323cabdff1aSopenharmony_ci    int ret = AVERROR_EOF, opcode;
1324cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
1325cabdff1aSopenharmony_ci    unsigned size, index;
1326cabdff1aSopenharmony_ci    int64_t pos, pts;
1327cabdff1aSopenharmony_ci
1328cabdff1aSopenharmony_ci    if (avio_feof(pb) || rm->data_end)
1329cabdff1aSopenharmony_ci        return AVERROR_EOF;
1330cabdff1aSopenharmony_ci
1331cabdff1aSopenharmony_ci    pos = avio_tell(pb);
1332cabdff1aSopenharmony_ci
1333cabdff1aSopenharmony_ci    for (;;) {
1334cabdff1aSopenharmony_ci        if (rm->audio_pkt_cnt) {
1335cabdff1aSopenharmony_ci            // If there are queued audio packet return them first
1336cabdff1aSopenharmony_ci            AVStream *st;
1337cabdff1aSopenharmony_ci
1338cabdff1aSopenharmony_ci            st = s->streams[rm->audio_stream_num];
1339cabdff1aSopenharmony_ci            ret = ff_rm_retrieve_cache(s, pb, st, st->priv_data, pkt);
1340cabdff1aSopenharmony_ci            if (ret < 0) {
1341cabdff1aSopenharmony_ci                return ret;
1342cabdff1aSopenharmony_ci            }
1343cabdff1aSopenharmony_ci        } else {
1344cabdff1aSopenharmony_ci            if (rm->remaining_len) {
1345cabdff1aSopenharmony_ci                avio_skip(pb, rm->remaining_len);
1346cabdff1aSopenharmony_ci                rm->remaining_len = 0;
1347cabdff1aSopenharmony_ci            }
1348cabdff1aSopenharmony_ci
1349cabdff1aSopenharmony_ci            if (avio_feof(pb))
1350cabdff1aSopenharmony_ci                return AVERROR_EOF;
1351cabdff1aSopenharmony_ci
1352cabdff1aSopenharmony_ci            opcode = avio_r8(pb);
1353cabdff1aSopenharmony_ci            if (opcode == 2) {
1354cabdff1aSopenharmony_ci                AVStream *st;
1355cabdff1aSopenharmony_ci                int seq = 1;
1356cabdff1aSopenharmony_ci
1357cabdff1aSopenharmony_ci                pts = avio_rb32(pb);
1358cabdff1aSopenharmony_ci                index = avio_rb16(pb);
1359cabdff1aSopenharmony_ci                if (index >= s->nb_streams)
1360cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1361cabdff1aSopenharmony_ci
1362cabdff1aSopenharmony_ci                avio_skip(pb, 4);
1363cabdff1aSopenharmony_ci                size = avio_rb32(pb);
1364cabdff1aSopenharmony_ci                avio_skip(pb, 4);
1365cabdff1aSopenharmony_ci
1366cabdff1aSopenharmony_ci                if (size < 1 || size > INT_MAX/4) {
1367cabdff1aSopenharmony_ci                    av_log(s, AV_LOG_ERROR, "size %u is invalid\n", size);
1368cabdff1aSopenharmony_ci                    return AVERROR_INVALIDDATA;
1369cabdff1aSopenharmony_ci                }
1370cabdff1aSopenharmony_ci
1371cabdff1aSopenharmony_ci                st = s->streams[index];
1372cabdff1aSopenharmony_ci                ret = ff_rm_parse_packet(s, pb, st, st->priv_data, size, pkt,
1373cabdff1aSopenharmony_ci                                         &seq, 0, pts);
1374cabdff1aSopenharmony_ci                if (ret < -1) {
1375cabdff1aSopenharmony_ci                    return ret;
1376cabdff1aSopenharmony_ci                } else if (ret) {
1377cabdff1aSopenharmony_ci                    continue;
1378cabdff1aSopenharmony_ci                }
1379cabdff1aSopenharmony_ci
1380cabdff1aSopenharmony_ci                pkt->pos = pos;
1381cabdff1aSopenharmony_ci                pkt->pts = pts;
1382cabdff1aSopenharmony_ci                pkt->stream_index = index;
1383cabdff1aSopenharmony_ci            } else if (opcode == 7) {
1384cabdff1aSopenharmony_ci                pos = avio_rb64(pb);
1385cabdff1aSopenharmony_ci                if (!pos) {
1386cabdff1aSopenharmony_ci                    rm->data_end = 1;
1387cabdff1aSopenharmony_ci                    return AVERROR_EOF;
1388cabdff1aSopenharmony_ci                }
1389cabdff1aSopenharmony_ci            } else {
1390cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Unsupported opcode=%d at %"PRIX64"\n", opcode, avio_tell(pb) - 1);
1391cabdff1aSopenharmony_ci                return AVERROR(EIO);
1392cabdff1aSopenharmony_ci            }
1393cabdff1aSopenharmony_ci        }
1394cabdff1aSopenharmony_ci
1395cabdff1aSopenharmony_ci        break;
1396cabdff1aSopenharmony_ci    }
1397cabdff1aSopenharmony_ci
1398cabdff1aSopenharmony_ci    return ret;
1399cabdff1aSopenharmony_ci}
1400cabdff1aSopenharmony_ci
1401cabdff1aSopenharmony_ciconst AVInputFormat ff_ivr_demuxer = {
1402cabdff1aSopenharmony_ci    .name           = "ivr",
1403cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("IVR (Internet Video Recording)"),
1404cabdff1aSopenharmony_ci    .priv_data_size = sizeof(RMDemuxContext),
1405cabdff1aSopenharmony_ci    .flags_internal = FF_FMT_INIT_CLEANUP,
1406cabdff1aSopenharmony_ci    .read_probe     = ivr_probe,
1407cabdff1aSopenharmony_ci    .read_header    = ivr_read_header,
1408cabdff1aSopenharmony_ci    .read_packet    = ivr_read_packet,
1409cabdff1aSopenharmony_ci    .read_close     = rm_read_close,
1410cabdff1aSopenharmony_ci    .extensions     = "ivr",
1411cabdff1aSopenharmony_ci};
1412