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