FFmpeg  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  int format;
176  AVRational fps;
177 
178  read_var_byte(s, &type);
179  read_var_byte(s, &ssize);
180 
181  switch (type) {
182  case 0:
183  if (ssize > 0)
184  avio_skip(pb, ssize);
185  return 0;
186  case 2:
188  stream_index = avio_r8(pb);
189  codec_id = avio_r8(pb);
190  switch (codec_id) {
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;
194  default:
195  av_log(s, AV_LOG_ERROR, "Unsupported audio codec: %d\n", codec_id);
196  return AVERROR_PATCHWELCOME;
197  }
198  sample_rate = avio_rb24(pb) + 1;
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  fps.num = avio_rb16(pb);
213  fps.den = avio_rb16(pb);
214  width = avio_rb16(pb);
215  height = avio_rb16(pb);
217  avio_skip(pb, type == 3 ? 3 : 2);
218  break;
219  case 4:
221  stream_index = avio_r8(pb);
222  avio_skip(pb, 1);
223  break;
224  }
225 
226  if (stream_index == s->nb_streams) {
228 
229  if (!st)
230  return AVERROR(ENOMEM);
231 
233  st->codecpar->codec_id = codec_id;
234  st->codecpar->width = width;
235  st->codecpar->height = height;
237  st->codecpar->channels = channels;
238  st->codecpar->format = format;
239  st->priv_data = av_packet_alloc();
240  if (!st->priv_data)
241  return AVERROR(ENOMEM);
242 
243  if (sample_rate)
244  avpriv_set_pts_info(st, 63, 1, sample_rate);
245  else
246  avpriv_set_pts_info(st, 63, fps.den, fps.num);
247  }
248  }
249 
250  return 0;
251 }
252 
254 {
255  int ret;
256 
257  ret = moflex_read_sync(s);
258  if (ret < 0)
259  return ret;
260 
261  s->ctx_flags |= AVFMTCTX_NOHEADER;
262  avio_seek(s->pb, 0, SEEK_SET);
263 
264  return 0;
265 }
266 
268 {
269  MOFLEXDemuxContext *m = s->priv_data;
270  AVIOContext *pb = s->pb;
271  BitReader *br = &m->br;
272  int ret;
273 
274  while (!avio_feof(pb)) {
275  if (!m->in_block) {
276  m->pos = avio_tell(pb);
277 
278  ret = moflex_read_sync(s);
279  if (ret < 0)
280  return ret;
281 
282  m->flags = avio_r8(pb);
283  if (m->flags & 2)
284  avio_skip(pb, 2);
285  }
286 
287  while ((avio_tell(pb) < m->pos + m->size) && !avio_feof(pb) && avio_r8(pb)) {
288  int stream_index, bits, pkt_size, endframe;
289  AVPacket *packet;
290 
291  m->in_block = 1;
292 
293  avio_seek(pb, -1, SEEK_CUR);
294  br->pos = br->last = 0;
295 
296  bits = pop_length(br, pb);
297  if (bits < 0)
298  return bits;
299  stream_index = pop_int(br, pb, bits);
300  if (stream_index < 0)
301  return stream_index;
302  if (stream_index >= s->nb_streams)
303  return AVERROR_INVALIDDATA;
304 
305  endframe = pop(br, pb);
306  if (endframe < 0)
307  return endframe;
308  if (endframe) {
309  bits = pop_length(br, pb);
310  if (bits < 0)
311  return bits;
312  pop_int(br, pb, bits);
313  pop(br, pb);
314  bits = pop_length(br, pb);
315  if (bits < 0)
316  return bits;
317  pop_int(br, pb, bits * 2 + 26);
318  }
319 
320  pkt_size = pop_int(br, pb, 13) + 1;
321  if (pkt_size > m->size)
322  return AVERROR_INVALIDDATA;
323  packet = s->streams[stream_index]->priv_data;
324  if (!packet) {
325  avio_skip(pb, pkt_size);
326  continue;
327  }
328 
329  ret = av_append_packet(pb, packet, pkt_size);
330  if (ret < 0)
331  return ret;
332  if (endframe && packet->size > 0) {
333  av_packet_move_ref(pkt, packet);
334  pkt->pos = m->pos;
335  pkt->stream_index = stream_index;
336  if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
337  pkt->duration = 1;
338  if (pkt->data[0] & 0x80)
340  } else {
342  }
343  return ret;
344  }
345  }
346 
347  m->in_block = 0;
348 
349  if (m->flags % 2 == 0) {
350  if (m->size <= 0)
351  return AVERROR_INVALIDDATA;
352  avio_seek(pb, m->pos + m->size, SEEK_SET);
353  }
354  }
355 
356  return AVERROR_EOF;
357 }
358 
359 static int moflex_read_seek(AVFormatContext *s, int stream_index,
360  int64_t pts, int flags)
361 {
362  MOFLEXDemuxContext *m = s->priv_data;
363 
364  m->in_block = 0;
365 
366  return -1;
367 }
368 
370 {
371  for (int i = 0; i < s->nb_streams; i++) {
372  AVPacket *packet = s->streams[i]->priv_data;
373 
374  av_packet_free(&packet);
375  s->streams[i]->priv_data = 0;
376  }
377 
378  return 0;
379 }
380 
382  .name = "moflex",
383  .long_name = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"),
384  .priv_data_size = sizeof(MOFLEXDemuxContext),
390  .extensions = "moflex",
392 };
static const char *const format[]
Definition: af_aiir.c:456
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:527
@ 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:4505
#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
@ 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:4941
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:369
static int moflex_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: moflex.c:267
static int pop_length(BitReader *br, AVIOContext *pb)
Definition: moflex.c:75
AVInputFormat ff_moflex_demuxer
Definition: moflex.c:381
static int moflex_read_header(AVFormatContext *s)
Definition: moflex.c:253
static int moflex_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
Definition: moflex.c:359
const char data[16]
Definition: mxf.c:142
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
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
int num
Numerator.
Definition: rational.h:59
int den
Denominator.
Definition: rational.h:60
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