FFmpeg  4.4.4
moflex.c
Go to the documentation of this file.
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 
43 
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 
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 
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 
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 
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 
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 tb = av_make_q(0, 1);
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:
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  tb = av_make_q(1, sample_rate);
199  channels = avio_r8(pb) + 1;
200  break;
201  case 1:
202  case 3:
204  stream_index = avio_r8(pb);
205  codec_id = avio_r8(pb);
206  switch (codec_id) {
207  case 0: codec_id = AV_CODEC_ID_MOBICLIP; break;
208  default:
209  av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id);
210  return AVERROR_PATCHWELCOME;
211  }
212  tb.den = avio_rb16(pb);
213  tb.num = avio_rb16(pb);
214  width = avio_rb16(pb);
215  height = avio_rb16(pb);
216  avio_skip(pb, type == 3 ? 3 : 2);
217  break;
218  case 4:
220  stream_index = avio_r8(pb);
221  avio_skip(pb, 1);
222  break;
223  }
224 
225  if (stream_index == s->nb_streams) {
227 
228  if (!st)
229  return AVERROR(ENOMEM);
230 
232  st->codecpar->codec_id = codec_id;
233  st->codecpar->width = width;
234  st->codecpar->height = height;
236  st->codecpar->channels = channels;
237  st->priv_data = av_packet_alloc();
238  if (!st->priv_data)
239  return AVERROR(ENOMEM);
240 
241  if (tb.num)
242  avpriv_set_pts_info(st, 63, tb.num, tb.den);
243  }
244  }
245 
246  return 0;
247 }
248 
250 {
251  int ret;
252 
253  ret = moflex_read_sync(s);
254  if (ret < 0)
255  return ret;
256 
257  s->ctx_flags |= AVFMTCTX_NOHEADER;
258  avio_seek(s->pb, 0, SEEK_SET);
259 
260  return 0;
261 }
262 
264 {
265  MOFLEXDemuxContext *m = s->priv_data;
266  AVIOContext *pb = s->pb;
267  BitReader *br = &m->br;
268  int ret;
269 
270  while (!avio_feof(pb)) {
271  if (!m->in_block) {
272  m->pos = avio_tell(pb);
273 
274  ret = moflex_read_sync(s);
275  if (ret < 0)
276  return ret;
277 
278  m->flags = avio_r8(pb);
279  if (m->flags & 2)
280  avio_skip(pb, 2);
281  }
282 
283  while ((avio_tell(pb) < m->pos + m->size) && !avio_feof(pb) && avio_r8(pb)) {
284  int stream_index, bits, pkt_size, endframe;
285  AVPacket *packet;
286 
287  m->in_block = 1;
288 
289  avio_seek(pb, -1, SEEK_CUR);
290  br->pos = br->last = 0;
291 
292  bits = pop_length(br, pb);
293  if (bits < 0)
294  return bits;
295  stream_index = pop_int(br, pb, bits);
296  if (stream_index < 0)
297  return stream_index;
298  if (stream_index >= s->nb_streams)
299  return AVERROR_INVALIDDATA;
300 
301  endframe = pop(br, pb);
302  if (endframe < 0)
303  return endframe;
304  if (endframe) {
305  bits = pop_length(br, pb);
306  if (bits < 0)
307  return bits;
308  pop_int(br, pb, bits);
309  pop(br, pb);
310  bits = pop_length(br, pb);
311  if (bits < 0)
312  return bits;
313  pop_int(br, pb, bits * 2 + 26);
314  }
315 
316  pkt_size = pop_int(br, pb, 13) + 1;
317  if (pkt_size > m->size)
318  return AVERROR_INVALIDDATA;
319  packet = s->streams[stream_index]->priv_data;
320  if (!packet) {
321  avio_skip(pb, pkt_size);
322  continue;
323  }
324 
325  ret = av_append_packet(pb, packet, pkt_size);
326  if (ret < 0)
327  return ret;
328  if (endframe && packet->size > 0) {
329  av_packet_move_ref(pkt, packet);
330  pkt->pos = m->pos;
331  pkt->stream_index = stream_index;
332  if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
333  pkt->duration = 1;
334  if (pkt->data[0] & 0x80)
336  } else {
338  }
339  return ret;
340  }
341  }
342 
343  m->in_block = 0;
344 
345  if (m->flags % 2 == 0) {
346  if (m->size <= 0)
347  return AVERROR_INVALIDDATA;
348  avio_seek(pb, m->pos + m->size, SEEK_SET);
349  }
350  }
351 
352  return AVERROR_EOF;
353 }
354 
355 static int moflex_read_seek(AVFormatContext *s, int stream_index,
356  int64_t pts, int flags)
357 {
358  MOFLEXDemuxContext *m = s->priv_data;
359 
360  m->in_block = 0;
361 
362  return -1;
363 }
364 
366 {
367  for (int i = 0; i < s->nb_streams; i++) {
368  AVPacket *packet = s->streams[i]->priv_data;
369 
370  av_packet_free(&packet);
371  s->streams[i]->priv_data = 0;
372  }
373 
374  return 0;
375 }
376 
378  .name = "moflex",
379  .long_name = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"),
380  .priv_data_size = sizeof(MOFLEXDemuxContext),
386  .extensions = "moflex",
388 };
channels
Definition: aptx.h:33
Main libavformat public API header.
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
Read data and append it to the current content of the AVPacket.
Definition: utils.c:326
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:453
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1177
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:463
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:253
uint64_t avio_rb64(AVIOContext *s)
Definition: aviobuf.c:902
unsigned int avio_rb16(AVIOContext *s)
Definition: aviobuf.c:766
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:364
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:337
unsigned int avio_rb24(AVIOContext *s)
Definition: aviobuf.c:774
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:624
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFMIN(a, b)
Definition: common.h:105
#define NULL
Definition: coverity.c:32
double value
Definition: eval.c:98
sample_rate
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:545
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:313
@ AV_CODEC_ID_FASTAUDIO
Definition: codec_id.h:519
@ AV_CODEC_ID_MOBICLIP
Definition: codec_id.h:303
@ AV_CODEC_ID_ADPCM_IMA_MOFLEX
Definition: codec_id.h:403
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:410
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:690
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:64
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4509
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
@ AVMEDIA_TYPE_DATA
Opaque data information usually continuous.
Definition: avutil.h:203
cl_device_type type
int i
Definition: input.c:407
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4945
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:153
static int moflex_read_sync(AVFormatContext *s)
Definition: moflex.c:155
static int pop_int(BitReader *br, AVIOContext *pb, int n)
Definition: moflex.c:58
static int pop(BitReader *br, AVIOContext *pb)
Definition: moflex.c:44
static int read_var_byte(AVFormatContext *s, unsigned *out)
Definition: moflex.c:87
static int moflex_probe(const AVProbeData *p)
Definition: moflex.c:120
static int moflex_read_close(AVFormatContext *s)
Definition: moflex.c:365
static int moflex_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: moflex.c:263
static int pop_length(BitReader *br, AVIOContext *pb)
Definition: moflex.c:75
AVInputFormat ff_moflex_demuxer
Definition: moflex.c:377
static int moflex_read_header(AVFormatContext *s)
Definition: moflex.c:249
static int moflex_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
Definition: moflex.c:355
const char data[16]
Definition: mxf.c:142
#define tb
Definition: regdef.h:68
enum AVMediaType codec_type
Definition: rtp.c:37
int channels
Audio only.
Definition: codec_par.h:166
int width
Video only.
Definition: codec_par.h:126
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int sample_rate
Audio only.
Definition: codec_par.h:170
Format I/O context.
Definition: avformat.h:1232
Bytestream IO Context.
Definition: avio.h:161
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:645
This structure stores compressed data.
Definition: packet.h:346
int stream_index
Definition: packet.h:371
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:375
int size
Definition: packet.h:370
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:387
uint8_t * data
Definition: packet.h:369
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:444
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
Rational number (pair of numerator and denominator).
Definition: rational.h:58
Stream structure.
Definition: avformat.h:873
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1038
void * priv_data
Definition: avformat.h:888
unsigned pos
Definition: moflex.c:31
unsigned last
Definition: moflex.c:30
int64_t ts
Definition: moflex.c:37
BitReader br
Definition: moflex.c:41
int64_t pos
Definition: moflex.c:36
unsigned size
Definition: moflex.c:35
#define av_log(a,...)
FILE * out
Definition: movenc.c:54
AVPacket * pkt
Definition: movenc.c:59
#define height
#define width
static int64_t pts
int size
enum AVCodecID codec_id
Definition: vaapi_decode.c:369
uint8_t bits
Definition: vp3data.h:141