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