3 * Copyright (c) 2015-2016 Florian Nouwt
4 * Copyright (c) 2017 Adib Surani
5 * Copyright (c) 2020 Paul B Mahol
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavcodec/bytestream.h"
30 typedef struct BitReader
{
35 typedef struct MOFLEXDemuxContext
{
45 static int pop(BitReader
*br
, AVIOContext
*pb
)
50 if ((br
->pos
& 7) == 0)
51 br
->last
= (unsigned)avio_r8(pb
) << 24U;
56 return !!(br
->last
& 0x80000000);
59 static int pop_int(BitReader
*br
, AVIOContext
*pb
, int n
)
63 for (int i
= 0; i
< n
; i
++) {
64 int ret
= pop(br
, pb
);
68 if (ret
> INT_MAX
- value
- value
)
69 return AVERROR_INVALIDDATA
;
70 value
= 2 * value
+ ret
;
76 static int pop_length(BitReader
*br
, AVIOContext
*pb
)
80 while ((ret
= pop(br
, pb
)) == 0)
88 static int read_var_byte(AVFormatContext
*s
, unsigned *out
)
90 AVIOContext
*pb
= s
->pb
;
91 unsigned value
= 0, data
;
99 value
= (data
& 0x7F) << 7;
101 if (!(data
& 0x80)) {
107 value
= ((data
& 0x7F) | value
) << 7;
109 if (!(data
& 0x80)) {
115 value
= (((data
& 0x7F) | value
) << 7) | avio_r8(pb
);
121 static int moflex_probe(const AVProbeData
*p
)
126 bytestream2_init(&gb
, p
->buf
, p
->buf_size
);
128 if (bytestream2_get_be16(&gb
) != 0x4C32)
132 bytestream2_skip(&gb
, 10);
133 if (bytestream2_get_be16(&gb
) == 0)
137 while (bytestream2_get_bytes_left(&gb
) > 0) {
138 int type
= bytestream2_get_byte(&gb
);
139 int size
= bytestream2_get_byte(&gb
);
142 score
+= 5 * (size
== 0);
145 if ((type
== 1 && size
== 12) ||
146 (type
== 2 && size
== 6) ||
147 (type
== 3 && size
== 13) ||
148 (type
== 4 && size
== 2))
150 bytestream2_skip(&gb
, size
);
153 return FFMIN(AVPROBE_SCORE_MAX
, score
);
156 static int moflex_read_sync(AVFormatContext
*s
)
158 MOFLEXDemuxContext
*m
= s
->priv_data
;
159 AVIOContext
*pb
= s
->pb
;
161 if (avio_rb16(pb
) != 0x4C32) {
164 avio_seek(pb
, -2, SEEK_CUR
);
169 m
->ts
= avio_rb64(pb
);
170 m
->size
= avio_rb16(pb
) + 1;
172 while (!avio_feof(pb
)) {
173 unsigned type
, ssize
, codec_id
= 0;
174 unsigned codec_type
, width
= 0, height
= 0, sample_rate
= 0, channels
= 0;
175 int stream_index
= -1;
176 AVRational tb
= av_make_q(0, 1);
178 read_var_byte(s
, &type
);
179 read_var_byte(s
, &ssize
);
184 avio_skip(pb
, ssize
);
187 codec_type
= AVMEDIA_TYPE_AUDIO
;
188 stream_index
= avio_r8(pb
);
189 codec_id
= avio_r8(pb
);
191 case 0: codec_id
= AV_CODEC_ID_FASTAUDIO
; break;
192 case 1: codec_id
= AV_CODEC_ID_ADPCM_IMA_MOFLEX
; break;
193 case 2: codec_id
= AV_CODEC_ID_PCM_S16LE
; break;
195 av_log(s
, AV_LOG_ERROR
, "Unsupported audio codec: %d\n", codec_id
);
196 return AVERROR_PATCHWELCOME
;
198 sample_rate
= avio_rb24(pb
) + 1;
199 tb
= av_make_q(1, sample_rate
);
200 channels
= avio_r8(pb
) + 1;
204 codec_type
= AVMEDIA_TYPE_VIDEO
;
205 stream_index
= avio_r8(pb
);
206 codec_id
= avio_r8(pb
);
208 case 0: codec_id
= AV_CODEC_ID_MOBICLIP
; break;
210 av_log(s
, AV_LOG_ERROR
, "Unsupported video codec: %d\n", codec_id
);
211 return AVERROR_PATCHWELCOME
;
213 tb
.den
= avio_rb16(pb
);
214 tb
.num
= avio_rb16(pb
);
215 width
= avio_rb16(pb
);
216 height
= avio_rb16(pb
);
217 avio_skip(pb
, type
== 3 ? 3 : 2);
220 codec_type
= AVMEDIA_TYPE_DATA
;
221 stream_index
= avio_r8(pb
);
226 if (stream_index
== s
->nb_streams
) {
227 AVStream
*st
= avformat_new_stream(s
, NULL
);
230 return AVERROR(ENOMEM
);
232 st
->codecpar
->codec_type
= codec_type
;
233 st
->codecpar
->codec_id
= codec_id
;
234 st
->codecpar
->width
= width
;
235 st
->codecpar
->height
= height
;
236 st
->codecpar
->sample_rate
= sample_rate
;
237 st
->codecpar
->ch_layout
.nb_channels
= channels
;
238 st
->priv_data
= av_packet_alloc();
240 return AVERROR(ENOMEM
);
243 avpriv_set_pts_info(st
, 63, tb
.num
, tb
.den
);
250 static int moflex_read_header(AVFormatContext
*s
)
254 ret
= moflex_read_sync(s
);
258 s
->ctx_flags
|= AVFMTCTX_NOHEADER
;
259 avio_seek(s
->pb
, 0, SEEK_SET
);
264 static int moflex_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
266 MOFLEXDemuxContext
*m
= s
->priv_data
;
267 AVIOContext
*pb
= s
->pb
;
268 BitReader
*br
= &m
->br
;
271 while (!avio_feof(pb
)) {
273 m
->pos
= avio_tell(pb
);
275 ret
= moflex_read_sync(s
);
279 m
->flags
= avio_r8(pb
);
284 while ((avio_tell(pb
) < m
->pos
+ m
->size
) && !avio_feof(pb
) && avio_r8(pb
)) {
285 int stream_index
, bits
, pkt_size
, endframe
;
290 avio_seek(pb
, -1, SEEK_CUR
);
291 br
->pos
= br
->last
= 0;
293 bits
= pop_length(br
, pb
);
296 stream_index
= pop_int(br
, pb
, bits
);
297 if (stream_index
< 0)
299 if (stream_index
>= s
->nb_streams
)
300 return AVERROR_INVALIDDATA
;
302 endframe
= pop(br
, pb
);
306 bits
= pop_length(br
, pb
);
309 pop_int(br
, pb
, bits
);
311 bits
= pop_length(br
, pb
);
314 pop_int(br
, pb
, bits
* 2 + 26);
317 pkt_size
= pop_int(br
, pb
, 13) + 1;
318 if (pkt_size
> m
->size
)
319 return AVERROR_INVALIDDATA
;
320 packet
= s
->streams
[stream_index
]->priv_data
;
322 avio_skip(pb
, pkt_size
);
326 ret
= av_append_packet(pb
, packet
, pkt_size
);
329 if (endframe
&& packet
->size
> 0) {
330 av_packet_move_ref(pkt
, packet
);
332 pkt
->stream_index
= stream_index
;
333 if (s
->streams
[stream_index
]->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
335 if (pkt
->data
[0] & 0x80)
336 pkt
->flags
|= AV_PKT_FLAG_KEY
;
338 pkt
->flags
|= AV_PKT_FLAG_KEY
;
346 if (m
->flags
% 2 == 0) {
348 return AVERROR_INVALIDDATA
;
349 avio_seek(pb
, m
->pos
+ m
->size
, SEEK_SET
);
356 static int moflex_read_seek(AVFormatContext
*s
, int stream_index
,
357 int64_t pts
, int flags
)
359 MOFLEXDemuxContext
*m
= s
->priv_data
;
366 static int moflex_read_close(AVFormatContext
*s
)
368 for (int i
= 0; i
< s
->nb_streams
; i
++) {
369 av_packet_free((AVPacket
**)&s
->streams
[i
]->priv_data
);
375 const FFInputFormat ff_moflex_demuxer
= {
377 .p
.long_name
= NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"),
378 .p
.extensions
= "moflex",
379 .p
.flags
= AVFMT_GENERIC_INDEX
,
380 .priv_data_size
= sizeof(MOFLEXDemuxContext
),
381 .read_probe
= moflex_probe
,
382 .read_header
= moflex_read_header
,
383 .read_packet
= moflex_read_packet
,
384 .read_seek
= moflex_read_seek
,
385 .read_close
= moflex_read_close
,
386 .flags_internal
= FF_INFMT_FLAG_INIT_CLEANUP
,