]> git.sesse.net Git - ffmpeg/blob - libavformat/moflex.c
avformat/argo_asf: fix enforcement of chunk count
[ffmpeg] / libavformat / moflex.c
1 /*
2  * MOFLEX demuxer
3  * Copyright (c) 2020 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavcodec/bytestream.h"
23
24 #include "avformat.h"
25 #include "internal.h"
26
27 typedef struct BitReader {
28     unsigned last;
29     unsigned pos;
30 } BitReader;
31
32 typedef struct MOFLEXDemuxContext {
33     unsigned size;
34     int64_t pos;
35     int64_t ts;
36     int flags;
37     int in_block;
38
39     BitReader br;
40 } MOFLEXDemuxContext;
41
42 static int pop(BitReader *br, AVIOContext *pb)
43 {
44     if (avio_feof(pb))
45         return AVERROR_EOF;
46
47     if ((br->pos & 7) == 0)
48         br->last = (unsigned)avio_r8(pb) << 24U;
49     else
50         br->last <<= 1;
51
52     br->pos++;
53     return !!(br->last & 0x80000000);
54 }
55
56 static int pop_int(BitReader *br, AVIOContext *pb, int n)
57 {
58     int value = 0;
59
60     for (int i = 0; i < n; i++) {
61         int ret = pop(br, pb);
62
63         if (ret < 0)
64             return ret;
65         value = 2 * value + ret;
66     }
67
68     return value;
69 }
70
71 static int pop_length(BitReader *br, AVIOContext *pb)
72 {
73     int ret, n = 1;
74
75     while ((ret = pop(br, pb)) == 0)
76         n++;
77
78     if (ret < 0)
79         return ret;
80     return n;
81 }
82
83 static int read_var_byte(AVFormatContext *s, unsigned *out)
84 {
85     AVIOContext *pb = s->pb;
86     unsigned value = 0, data;
87
88     data = avio_r8(pb);
89     if (!(data & 0x80)) {
90         *out = data;
91         return 0;
92     }
93
94     value = (data & 0x7F) << 7;
95     data = avio_r8(pb);
96     if (!(data & 0x80)) {
97         value |= data;
98         *out = value;
99         return 0;
100     }
101
102     value = ((data & 0x7F) | value) << 7;
103     data = avio_r8(pb);
104     if (!(data & 0x80)) {
105         value |= data;
106         *out = value;
107         return 0;
108     }
109
110     value = (((data & 0x7F) | value) << 7) | avio_r8(pb);
111     *out = value;
112
113     return 0;
114 }
115
116 static int moflex_probe(const AVProbeData *p)
117 {
118     GetByteContext gb;
119     int score = 0;
120
121     bytestream2_init(&gb, p->buf, p->buf_size);
122
123     if (bytestream2_get_be16(&gb) != 0x4C32)
124         return 0;
125     score += 10;
126
127     bytestream2_skip(&gb, 10);
128     if (bytestream2_get_be16(&gb) == 0)
129         return 0;
130     score += 5;
131
132     while (bytestream2_get_bytes_left(&gb) > 0) {
133         int type = bytestream2_get_byte(&gb);
134         int size = bytestream2_get_byte(&gb);
135
136         if (type == 0) {
137             score += 5 * (size == 0);
138             break;
139         }
140         if ((type == 1 && size == 12) ||
141             (type == 2 && size ==  6) ||
142             (type == 3 && size == 13) ||
143             (type == 4 && size ==  2))
144             score += 20;
145         bytestream2_skip(&gb, size);
146     }
147
148     return FFMIN(AVPROBE_SCORE_MAX, score);
149 }
150
151 static int moflex_read_sync(AVFormatContext *s)
152 {
153     MOFLEXDemuxContext *m = s->priv_data;
154     AVIOContext *pb = s->pb;
155
156     if (avio_rb16(pb) != 0x4C32) {
157         if (avio_feof(pb))
158             return AVERROR_EOF;
159         avio_seek(pb, -2, SEEK_CUR);
160         return 1;
161     }
162
163     avio_skip(pb, 2);
164     m->ts = avio_rb64(pb);
165     m->size = avio_rb16(pb) + 1;
166
167     while (!avio_feof(pb)) {
168         unsigned type, ssize, codec_id = 0;
169         unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0;
170         int stream_index = -1;
171         int format;
172         AVRational fps;
173
174         read_var_byte(s, &type);
175         read_var_byte(s, &ssize);
176
177         switch (type) {
178         case 0:
179             if (ssize > 0)
180                 avio_skip(pb, ssize);
181             return 0;
182         case 2:
183             codec_type = AVMEDIA_TYPE_AUDIO;
184             stream_index = avio_r8(pb);
185             codec_id = avio_r8(pb);
186             switch (codec_id) {
187             case 0: codec_id = AV_CODEC_ID_FASTAUDIO; break;
188             case 1: codec_id = AV_CODEC_ID_ADPCM_IMA_MOFLEX; break;
189             case 2: codec_id = AV_CODEC_ID_PCM_S16LE; break;
190             default:
191                 av_log(s, AV_LOG_ERROR, "Unsupported audio codec: %d\n", codec_id);
192                 return AVERROR_PATCHWELCOME;
193             }
194             sample_rate = avio_rb24(pb) + 1;
195             channels = avio_r8(pb) + 1;
196             break;
197         case 1:
198         case 3:
199             codec_type = AVMEDIA_TYPE_VIDEO;
200             stream_index = avio_r8(pb);
201             codec_id = avio_r8(pb);
202             switch (codec_id) {
203             case 0: codec_id = AV_CODEC_ID_MOBICLIP; break;
204             default:
205                 av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id);
206                 return AVERROR_PATCHWELCOME;
207             }
208             fps.num = avio_rb16(pb);
209             fps.den = avio_rb16(pb);
210             width = avio_rb16(pb);
211             height = avio_rb16(pb);
212             format = AV_PIX_FMT_YUV420P;
213             avio_skip(pb, type == 3 ? 3 : 2);
214             break;
215         case 4:
216             codec_type = AVMEDIA_TYPE_DATA;
217             stream_index = avio_r8(pb);
218             avio_skip(pb, 1);
219             break;
220         }
221
222         if (stream_index == s->nb_streams) {
223             AVStream *st = avformat_new_stream(s, NULL);
224
225             if (!st)
226                 return AVERROR(ENOMEM);
227
228             st->codecpar->codec_type = codec_type;
229             st->codecpar->codec_id   = codec_id;
230             st->codecpar->width      = width;
231             st->codecpar->height     = height;
232             st->codecpar->sample_rate= sample_rate;
233             st->codecpar->channels   = channels;
234             st->codecpar->format     = format;
235             st->priv_data            = av_packet_alloc();
236             if (!st->priv_data)
237                 return AVERROR(ENOMEM);
238
239             if (sample_rate)
240                 avpriv_set_pts_info(st, 63, 1, sample_rate);
241             else
242                 avpriv_set_pts_info(st, 63, fps.den, fps.num);
243         }
244     }
245
246     return 0;
247 }
248
249 static int moflex_read_header(AVFormatContext *s)
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
263 static int moflex_read_packet(AVFormatContext *s, AVPacket *pkt)
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             packet   = s->streams[stream_index]->priv_data;
318             if (!packet) {
319                 avio_skip(pb, pkt_size);
320                 continue;
321             }
322
323             ret = av_append_packet(pb, packet, pkt_size);
324             if (ret < 0)
325                 return ret;
326             if (endframe && packet->size > 0) {
327                 av_packet_move_ref(pkt, packet);
328                 pkt->pos = m->pos;
329                 pkt->stream_index = stream_index;
330                 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
331                     pkt->duration = 1;
332                     if (pkt->data[0] & 0x80)
333                         pkt->flags |= AV_PKT_FLAG_KEY;
334                 } else {
335                     pkt->flags |= AV_PKT_FLAG_KEY;
336                 }
337                 return ret;
338             }
339         }
340
341         m->in_block = 0;
342
343         if (m->flags % 2 == 0)
344             avio_seek(pb, m->pos + m->size, SEEK_SET);
345     }
346
347     return AVERROR_EOF;
348 }
349
350 static int moflex_read_seek(AVFormatContext *s, int stream_index,
351                             int64_t pts, int flags)
352 {
353     MOFLEXDemuxContext *m = s->priv_data;
354
355     m->in_block = 0;
356
357     return -1;
358 }
359
360 static int moflex_read_close(AVFormatContext *s)
361 {
362     for (int i = 0; i < s->nb_streams; i++) {
363         AVPacket *packet = s->streams[i]->priv_data;
364
365         av_packet_free(&packet);
366         s->streams[i]->priv_data = 0;
367     }
368
369     return 0;
370 }
371
372 AVInputFormat ff_moflex_demuxer = {
373     .name           = "moflex",
374     .long_name      = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"),
375     .priv_data_size = sizeof(MOFLEXDemuxContext),
376     .read_probe     = moflex_probe,
377     .read_header    = moflex_read_header,
378     .read_packet    = moflex_read_packet,
379     .read_seek      = moflex_read_seek,
380     .read_close     = moflex_read_close,
381     .extensions     = "moflex",
382     .flags          = AVFMT_GENERIC_INDEX,
383 };