1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * MOFLEX demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2015-2016 Florian Nouwt
4cabdff1aSopenharmony_ci * Copyright (c) 2017 Adib Surani
5cabdff1aSopenharmony_ci * Copyright (c) 2020 Paul B Mahol
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * This file is part of FFmpeg.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17cabdff1aSopenharmony_ci * Lesser General Public License for more details.
18cabdff1aSopenharmony_ci *
19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22cabdff1aSopenharmony_ci */
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "avformat.h"
27cabdff1aSopenharmony_ci#include "internal.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_citypedef struct BitReader {
30cabdff1aSopenharmony_ci    unsigned last;
31cabdff1aSopenharmony_ci    unsigned pos;
32cabdff1aSopenharmony_ci} BitReader;
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_citypedef struct MOFLEXDemuxContext {
35cabdff1aSopenharmony_ci    unsigned size;
36cabdff1aSopenharmony_ci    int64_t pos;
37cabdff1aSopenharmony_ci    int64_t ts;
38cabdff1aSopenharmony_ci    int flags;
39cabdff1aSopenharmony_ci    int in_block;
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci    BitReader br;
42cabdff1aSopenharmony_ci} MOFLEXDemuxContext;
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_cistatic int pop(BitReader *br, AVIOContext *pb)
45cabdff1aSopenharmony_ci{
46cabdff1aSopenharmony_ci    if (avio_feof(pb))
47cabdff1aSopenharmony_ci        return AVERROR_EOF;
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_ci    if ((br->pos & 7) == 0)
50cabdff1aSopenharmony_ci        br->last = (unsigned)avio_r8(pb) << 24U;
51cabdff1aSopenharmony_ci    else
52cabdff1aSopenharmony_ci        br->last <<= 1;
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    br->pos++;
55cabdff1aSopenharmony_ci    return !!(br->last & 0x80000000);
56cabdff1aSopenharmony_ci}
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_cistatic int pop_int(BitReader *br, AVIOContext *pb, int n)
59cabdff1aSopenharmony_ci{
60cabdff1aSopenharmony_ci    int value = 0;
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_ci    for (int i = 0; i < n; i++) {
63cabdff1aSopenharmony_ci        int ret = pop(br, pb);
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ci        if (ret < 0)
66cabdff1aSopenharmony_ci            return ret;
67cabdff1aSopenharmony_ci        if (ret > INT_MAX - value - value)
68cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
69cabdff1aSopenharmony_ci        value = 2 * value + ret;
70cabdff1aSopenharmony_ci    }
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    return value;
73cabdff1aSopenharmony_ci}
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_cistatic int pop_length(BitReader *br, AVIOContext *pb)
76cabdff1aSopenharmony_ci{
77cabdff1aSopenharmony_ci    int ret, n = 1;
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    while ((ret = pop(br, pb)) == 0)
80cabdff1aSopenharmony_ci        n++;
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci    if (ret < 0)
83cabdff1aSopenharmony_ci        return ret;
84cabdff1aSopenharmony_ci    return n;
85cabdff1aSopenharmony_ci}
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_cistatic int read_var_byte(AVFormatContext *s, unsigned *out)
88cabdff1aSopenharmony_ci{
89cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
90cabdff1aSopenharmony_ci    unsigned value = 0, data;
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci    data = avio_r8(pb);
93cabdff1aSopenharmony_ci    if (!(data & 0x80)) {
94cabdff1aSopenharmony_ci        *out = data;
95cabdff1aSopenharmony_ci        return 0;
96cabdff1aSopenharmony_ci    }
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci    value = (data & 0x7F) << 7;
99cabdff1aSopenharmony_ci    data = avio_r8(pb);
100cabdff1aSopenharmony_ci    if (!(data & 0x80)) {
101cabdff1aSopenharmony_ci        value |= data;
102cabdff1aSopenharmony_ci        *out = value;
103cabdff1aSopenharmony_ci        return 0;
104cabdff1aSopenharmony_ci    }
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci    value = ((data & 0x7F) | value) << 7;
107cabdff1aSopenharmony_ci    data = avio_r8(pb);
108cabdff1aSopenharmony_ci    if (!(data & 0x80)) {
109cabdff1aSopenharmony_ci        value |= data;
110cabdff1aSopenharmony_ci        *out = value;
111cabdff1aSopenharmony_ci        return 0;
112cabdff1aSopenharmony_ci    }
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    value = (((data & 0x7F) | value) << 7) | avio_r8(pb);
115cabdff1aSopenharmony_ci    *out = value;
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    return 0;
118cabdff1aSopenharmony_ci}
119cabdff1aSopenharmony_ci
120cabdff1aSopenharmony_cistatic int moflex_probe(const AVProbeData *p)
121cabdff1aSopenharmony_ci{
122cabdff1aSopenharmony_ci    GetByteContext gb;
123cabdff1aSopenharmony_ci    int score = 0;
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    bytestream2_init(&gb, p->buf, p->buf_size);
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci    if (bytestream2_get_be16(&gb) != 0x4C32)
128cabdff1aSopenharmony_ci        return 0;
129cabdff1aSopenharmony_ci    score += 10;
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_ci    bytestream2_skip(&gb, 10);
132cabdff1aSopenharmony_ci    if (bytestream2_get_be16(&gb) == 0)
133cabdff1aSopenharmony_ci        return 0;
134cabdff1aSopenharmony_ci    score += 5;
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(&gb) > 0) {
137cabdff1aSopenharmony_ci        int type = bytestream2_get_byte(&gb);
138cabdff1aSopenharmony_ci        int size = bytestream2_get_byte(&gb);
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci        if (type == 0) {
141cabdff1aSopenharmony_ci            score += 5 * (size == 0);
142cabdff1aSopenharmony_ci            break;
143cabdff1aSopenharmony_ci        }
144cabdff1aSopenharmony_ci        if ((type == 1 && size == 12) ||
145cabdff1aSopenharmony_ci            (type == 2 && size ==  6) ||
146cabdff1aSopenharmony_ci            (type == 3 && size == 13) ||
147cabdff1aSopenharmony_ci            (type == 4 && size ==  2))
148cabdff1aSopenharmony_ci            score += 20;
149cabdff1aSopenharmony_ci        bytestream2_skip(&gb, size);
150cabdff1aSopenharmony_ci    }
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    return FFMIN(AVPROBE_SCORE_MAX, score);
153cabdff1aSopenharmony_ci}
154cabdff1aSopenharmony_ci
155cabdff1aSopenharmony_cistatic int moflex_read_sync(AVFormatContext *s)
156cabdff1aSopenharmony_ci{
157cabdff1aSopenharmony_ci    MOFLEXDemuxContext *m = s->priv_data;
158cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci    if (avio_rb16(pb) != 0x4C32) {
161cabdff1aSopenharmony_ci        if (avio_feof(pb))
162cabdff1aSopenharmony_ci            return AVERROR_EOF;
163cabdff1aSopenharmony_ci        avio_seek(pb, -2, SEEK_CUR);
164cabdff1aSopenharmony_ci        return 1;
165cabdff1aSopenharmony_ci    }
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_ci    avio_skip(pb, 2);
168cabdff1aSopenharmony_ci    m->ts = avio_rb64(pb);
169cabdff1aSopenharmony_ci    m->size = avio_rb16(pb) + 1;
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci    while (!avio_feof(pb)) {
172cabdff1aSopenharmony_ci        unsigned type, ssize, codec_id = 0;
173cabdff1aSopenharmony_ci        unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0;
174cabdff1aSopenharmony_ci        int stream_index = -1;
175cabdff1aSopenharmony_ci        AVRational tb = av_make_q(0, 1);
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci        read_var_byte(s, &type);
178cabdff1aSopenharmony_ci        read_var_byte(s, &ssize);
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci        switch (type) {
181cabdff1aSopenharmony_ci        case 0:
182cabdff1aSopenharmony_ci            if (ssize > 0)
183cabdff1aSopenharmony_ci                avio_skip(pb, ssize);
184cabdff1aSopenharmony_ci            return 0;
185cabdff1aSopenharmony_ci        case 2:
186cabdff1aSopenharmony_ci            codec_type = AVMEDIA_TYPE_AUDIO;
187cabdff1aSopenharmony_ci            stream_index = avio_r8(pb);
188cabdff1aSopenharmony_ci            codec_id = avio_r8(pb);
189cabdff1aSopenharmony_ci            switch (codec_id) {
190cabdff1aSopenharmony_ci            case 0: codec_id = AV_CODEC_ID_FASTAUDIO; break;
191cabdff1aSopenharmony_ci            case 1: codec_id = AV_CODEC_ID_ADPCM_IMA_MOFLEX; break;
192cabdff1aSopenharmony_ci            case 2: codec_id = AV_CODEC_ID_PCM_S16LE; break;
193cabdff1aSopenharmony_ci            default:
194cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Unsupported audio codec: %d\n", codec_id);
195cabdff1aSopenharmony_ci                return AVERROR_PATCHWELCOME;
196cabdff1aSopenharmony_ci            }
197cabdff1aSopenharmony_ci            sample_rate = avio_rb24(pb) + 1;
198cabdff1aSopenharmony_ci            tb = av_make_q(1, sample_rate);
199cabdff1aSopenharmony_ci            channels = avio_r8(pb) + 1;
200cabdff1aSopenharmony_ci            break;
201cabdff1aSopenharmony_ci        case 1:
202cabdff1aSopenharmony_ci        case 3:
203cabdff1aSopenharmony_ci            codec_type = AVMEDIA_TYPE_VIDEO;
204cabdff1aSopenharmony_ci            stream_index = avio_r8(pb);
205cabdff1aSopenharmony_ci            codec_id = avio_r8(pb);
206cabdff1aSopenharmony_ci            switch (codec_id) {
207cabdff1aSopenharmony_ci            case 0: codec_id = AV_CODEC_ID_MOBICLIP; break;
208cabdff1aSopenharmony_ci            default:
209cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id);
210cabdff1aSopenharmony_ci                return AVERROR_PATCHWELCOME;
211cabdff1aSopenharmony_ci            }
212cabdff1aSopenharmony_ci            tb.den = avio_rb16(pb);
213cabdff1aSopenharmony_ci            tb.num = avio_rb16(pb);
214cabdff1aSopenharmony_ci            width = avio_rb16(pb);
215cabdff1aSopenharmony_ci            height = avio_rb16(pb);
216cabdff1aSopenharmony_ci            avio_skip(pb, type == 3 ? 3 : 2);
217cabdff1aSopenharmony_ci            break;
218cabdff1aSopenharmony_ci        case 4:
219cabdff1aSopenharmony_ci            codec_type = AVMEDIA_TYPE_DATA;
220cabdff1aSopenharmony_ci            stream_index = avio_r8(pb);
221cabdff1aSopenharmony_ci            avio_skip(pb, 1);
222cabdff1aSopenharmony_ci            break;
223cabdff1aSopenharmony_ci        }
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci        if (stream_index == s->nb_streams) {
226cabdff1aSopenharmony_ci            AVStream *st = avformat_new_stream(s, NULL);
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci            if (!st)
229cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
230cabdff1aSopenharmony_ci
231cabdff1aSopenharmony_ci            st->codecpar->codec_type = codec_type;
232cabdff1aSopenharmony_ci            st->codecpar->codec_id   = codec_id;
233cabdff1aSopenharmony_ci            st->codecpar->width      = width;
234cabdff1aSopenharmony_ci            st->codecpar->height     = height;
235cabdff1aSopenharmony_ci            st->codecpar->sample_rate= sample_rate;
236cabdff1aSopenharmony_ci            st->codecpar->ch_layout.nb_channels = channels;
237cabdff1aSopenharmony_ci            st->priv_data            = av_packet_alloc();
238cabdff1aSopenharmony_ci            if (!st->priv_data)
239cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
240cabdff1aSopenharmony_ci
241cabdff1aSopenharmony_ci            if (tb.num)
242cabdff1aSopenharmony_ci                avpriv_set_pts_info(st, 63, tb.num, tb.den);
243cabdff1aSopenharmony_ci        }
244cabdff1aSopenharmony_ci    }
245cabdff1aSopenharmony_ci
246cabdff1aSopenharmony_ci    return 0;
247cabdff1aSopenharmony_ci}
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_cistatic int moflex_read_header(AVFormatContext *s)
250cabdff1aSopenharmony_ci{
251cabdff1aSopenharmony_ci    int ret;
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci    ret = moflex_read_sync(s);
254cabdff1aSopenharmony_ci    if (ret < 0)
255cabdff1aSopenharmony_ci        return ret;
256cabdff1aSopenharmony_ci
257cabdff1aSopenharmony_ci    s->ctx_flags |= AVFMTCTX_NOHEADER;
258cabdff1aSopenharmony_ci    avio_seek(s->pb, 0, SEEK_SET);
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci    return 0;
261cabdff1aSopenharmony_ci}
262cabdff1aSopenharmony_ci
263cabdff1aSopenharmony_cistatic int moflex_read_packet(AVFormatContext *s, AVPacket *pkt)
264cabdff1aSopenharmony_ci{
265cabdff1aSopenharmony_ci    MOFLEXDemuxContext *m = s->priv_data;
266cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
267cabdff1aSopenharmony_ci    BitReader *br = &m->br;
268cabdff1aSopenharmony_ci    int ret;
269cabdff1aSopenharmony_ci
270cabdff1aSopenharmony_ci    while (!avio_feof(pb)) {
271cabdff1aSopenharmony_ci        if (!m->in_block) {
272cabdff1aSopenharmony_ci            m->pos = avio_tell(pb);
273cabdff1aSopenharmony_ci
274cabdff1aSopenharmony_ci            ret = moflex_read_sync(s);
275cabdff1aSopenharmony_ci            if (ret < 0)
276cabdff1aSopenharmony_ci                return ret;
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_ci            m->flags = avio_r8(pb);
279cabdff1aSopenharmony_ci            if (m->flags & 2)
280cabdff1aSopenharmony_ci                avio_skip(pb, 2);
281cabdff1aSopenharmony_ci        }
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci        while ((avio_tell(pb) < m->pos + m->size) && !avio_feof(pb) && avio_r8(pb)) {
284cabdff1aSopenharmony_ci            int stream_index, bits, pkt_size, endframe;
285cabdff1aSopenharmony_ci            AVPacket *packet;
286cabdff1aSopenharmony_ci
287cabdff1aSopenharmony_ci            m->in_block = 1;
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci            avio_seek(pb, -1, SEEK_CUR);
290cabdff1aSopenharmony_ci            br->pos = br->last = 0;
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci            bits = pop_length(br, pb);
293cabdff1aSopenharmony_ci            if (bits < 0)
294cabdff1aSopenharmony_ci                return bits;
295cabdff1aSopenharmony_ci            stream_index = pop_int(br, pb, bits);
296cabdff1aSopenharmony_ci            if (stream_index < 0)
297cabdff1aSopenharmony_ci                return stream_index;
298cabdff1aSopenharmony_ci            if (stream_index >= s->nb_streams)
299cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci            endframe = pop(br, pb);
302cabdff1aSopenharmony_ci            if (endframe < 0)
303cabdff1aSopenharmony_ci                return endframe;
304cabdff1aSopenharmony_ci            if (endframe) {
305cabdff1aSopenharmony_ci                bits = pop_length(br, pb);
306cabdff1aSopenharmony_ci                if (bits < 0)
307cabdff1aSopenharmony_ci                    return bits;
308cabdff1aSopenharmony_ci                pop_int(br, pb, bits);
309cabdff1aSopenharmony_ci                pop(br, pb);
310cabdff1aSopenharmony_ci                bits = pop_length(br, pb);
311cabdff1aSopenharmony_ci                if (bits < 0)
312cabdff1aSopenharmony_ci                    return bits;
313cabdff1aSopenharmony_ci                pop_int(br, pb, bits * 2 + 26);
314cabdff1aSopenharmony_ci            }
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci            pkt_size = pop_int(br, pb, 13) + 1;
317cabdff1aSopenharmony_ci            if (pkt_size > m->size)
318cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
319cabdff1aSopenharmony_ci            packet   = s->streams[stream_index]->priv_data;
320cabdff1aSopenharmony_ci            if (!packet) {
321cabdff1aSopenharmony_ci                avio_skip(pb, pkt_size);
322cabdff1aSopenharmony_ci                continue;
323cabdff1aSopenharmony_ci            }
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_ci            ret = av_append_packet(pb, packet, pkt_size);
326cabdff1aSopenharmony_ci            if (ret < 0)
327cabdff1aSopenharmony_ci                return ret;
328cabdff1aSopenharmony_ci            if (endframe && packet->size > 0) {
329cabdff1aSopenharmony_ci                av_packet_move_ref(pkt, packet);
330cabdff1aSopenharmony_ci                pkt->pos = m->pos;
331cabdff1aSopenharmony_ci                pkt->stream_index = stream_index;
332cabdff1aSopenharmony_ci                if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
333cabdff1aSopenharmony_ci                    pkt->duration = 1;
334cabdff1aSopenharmony_ci                    if (pkt->data[0] & 0x80)
335cabdff1aSopenharmony_ci                        pkt->flags |= AV_PKT_FLAG_KEY;
336cabdff1aSopenharmony_ci                } else {
337cabdff1aSopenharmony_ci                    pkt->flags |= AV_PKT_FLAG_KEY;
338cabdff1aSopenharmony_ci                }
339cabdff1aSopenharmony_ci                return ret;
340cabdff1aSopenharmony_ci            }
341cabdff1aSopenharmony_ci        }
342cabdff1aSopenharmony_ci
343cabdff1aSopenharmony_ci        m->in_block = 0;
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci        if (m->flags % 2 == 0) {
346cabdff1aSopenharmony_ci            if (m->size <= 0)
347cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
348cabdff1aSopenharmony_ci            avio_seek(pb, m->pos + m->size, SEEK_SET);
349cabdff1aSopenharmony_ci        }
350cabdff1aSopenharmony_ci    }
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    return AVERROR_EOF;
353cabdff1aSopenharmony_ci}
354cabdff1aSopenharmony_ci
355cabdff1aSopenharmony_cistatic int moflex_read_seek(AVFormatContext *s, int stream_index,
356cabdff1aSopenharmony_ci                            int64_t pts, int flags)
357cabdff1aSopenharmony_ci{
358cabdff1aSopenharmony_ci    MOFLEXDemuxContext *m = s->priv_data;
359cabdff1aSopenharmony_ci
360cabdff1aSopenharmony_ci    m->in_block = 0;
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    return -1;
363cabdff1aSopenharmony_ci}
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_cistatic int moflex_read_close(AVFormatContext *s)
366cabdff1aSopenharmony_ci{
367cabdff1aSopenharmony_ci    for (int i = 0; i < s->nb_streams; i++) {
368cabdff1aSopenharmony_ci        av_packet_free((AVPacket **)&s->streams[i]->priv_data);
369cabdff1aSopenharmony_ci    }
370cabdff1aSopenharmony_ci
371cabdff1aSopenharmony_ci    return 0;
372cabdff1aSopenharmony_ci}
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ciconst AVInputFormat ff_moflex_demuxer = {
375cabdff1aSopenharmony_ci    .name           = "moflex",
376cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"),
377cabdff1aSopenharmony_ci    .priv_data_size = sizeof(MOFLEXDemuxContext),
378cabdff1aSopenharmony_ci    .read_probe     = moflex_probe,
379cabdff1aSopenharmony_ci    .read_header    = moflex_read_header,
380cabdff1aSopenharmony_ci    .read_packet    = moflex_read_packet,
381cabdff1aSopenharmony_ci    .read_seek      = moflex_read_seek,
382cabdff1aSopenharmony_ci    .read_close     = moflex_read_close,
383cabdff1aSopenharmony_ci    .extensions     = "moflex",
384cabdff1aSopenharmony_ci    .flags          = AVFMT_GENERIC_INDEX,
385cabdff1aSopenharmony_ci    .flags_internal = FF_FMT_INIT_CLEANUP,
386cabdff1aSopenharmony_ci};
387