Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/ipmovie.c
Line
Count
Source
1
/*
2
 * Interplay MVE File Demuxer
3
 * Copyright (c) 2003 The FFmpeg project
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
/**
23
 * @file
24
 * Interplay MVE file demuxer
25
 * by Mike Melanson (melanson@pcisys.net)
26
 * For more information regarding the Interplay MVE file format, visit:
27
 *   http://www.pcisys.net/~melanson/codecs/
28
 * The aforementioned site also contains a command line utility for parsing
29
 * IP MVE files so that you can get a good idea of the typical structure of
30
 * such files. This demuxer is not the best example to use if you are trying
31
 * to write your own as it uses a rather roundabout approach for splitting
32
 * up and sending out the chunks.
33
 */
34
35
#include "libavutil/channel_layout.h"
36
#include "libavutil/intreadwrite.h"
37
#include "avformat.h"
38
#include "avio_internal.h"
39
#include "demux.h"
40
#include "internal.h"
41
42
3.84M
#define CHUNK_PREAMBLE_SIZE 4
43
797k
#define OPCODE_PREAMBLE_SIZE 4
44
45
949k
#define CHUNK_INIT_AUDIO   0x0000
46
602k
#define CHUNK_AUDIO_ONLY   0x0001
47
959k
#define CHUNK_INIT_VIDEO   0x0002
48
1.86M
#define CHUNK_VIDEO        0x0003
49
1.22M
#define CHUNK_SHUTDOWN     0x0004
50
2.45M
#define CHUNK_END          0x0005
51
/* these last types are used internally */
52
1.97M
#define CHUNK_HAVE_PACKET  0xFFFB
53
2.35M
#define CHUNK_DONE         0xFFFC
54
1.22M
#define CHUNK_NOMEM        0xFFFD
55
1.22M
#define CHUNK_EOF          0xFFFE
56
2.03M
#define CHUNK_BAD          0xFFFF
57
58
10.7k
#define OPCODE_END_OF_STREAM           0x00
59
1.04k
#define OPCODE_END_OF_CHUNK            0x01
60
4.10k
#define OPCODE_CREATE_TIMER            0x02
61
10.2k
#define OPCODE_INIT_AUDIO_BUFFERS      0x03
62
783
#define OPCODE_START_STOP_AUDIO        0x04
63
6.91k
#define OPCODE_INIT_VIDEO_BUFFERS      0x05
64
2.95k
#define OPCODE_VIDEO_DATA_06           0x06
65
1.47k
#define OPCODE_SEND_BUFFER             0x07
66
58.2k
#define OPCODE_AUDIO_FRAME             0x08
67
843
#define OPCODE_SILENCE_FRAME           0x09
68
450
#define OPCODE_INIT_VIDEO_MODE         0x0A
69
149
#define OPCODE_CREATE_GRADIENT         0x0B
70
1.85k
#define OPCODE_SET_PALETTE             0x0C
71
393
#define OPCODE_SET_PALETTE_COMPRESSED  0x0D
72
1.85k
#define OPCODE_SET_SKIP_MAP            0x0E
73
775
#define OPCODE_SET_DECODING_MAP        0x0F
74
695k
#define OPCODE_VIDEO_DATA_10           0x10
75
695k
#define OPCODE_VIDEO_DATA_11           0x11
76
291
#define OPCODE_UNKNOWN_12              0x12
77
839
#define OPCODE_UNKNOWN_13              0x13
78
1.30k
#define OPCODE_UNKNOWN_14              0x14
79
1.72k
#define OPCODE_UNKNOWN_15              0x15
80
81
#define PALETTE_COUNT 256
82
83
typedef struct IPMVEContext {
84
    AVFormatContext *avf;
85
    unsigned char *buf;
86
    int buf_size;
87
88
    uint64_t frame_pts_inc;
89
90
    unsigned int video_bpp;
91
    unsigned int video_width;
92
    unsigned int video_height;
93
    int64_t video_pts;
94
    uint32_t     palette[256];
95
    int          has_palette;
96
    int          changed;
97
    uint8_t      send_buffer;
98
    uint8_t      frame_format;
99
100
    unsigned int audio_bits;
101
    unsigned int audio_channels;
102
    unsigned int audio_sample_rate;
103
    enum AVCodecID audio_type;
104
    unsigned int audio_frame_count;
105
106
    int video_stream_index;
107
    int audio_stream_index;
108
109
    int64_t audio_chunk_offset;
110
    int audio_chunk_size;
111
    int64_t video_chunk_offset;
112
    int video_chunk_size;
113
    int64_t skip_map_chunk_offset;
114
    int skip_map_chunk_size;
115
    int64_t decode_map_chunk_offset;
116
    int decode_map_chunk_size;
117
118
    int64_t next_chunk_offset;
119
120
} IPMVEContext;
121
122
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
123
1.87M
    AVPacket *pkt) {
124
125
1.87M
    int chunk_type;
126
127
1.87M
    if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
128
56.4k
        if (s->audio_type == AV_CODEC_ID_NONE) {
129
6
            av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
130
6
                   "audio codec is known\n");
131
6
                return CHUNK_BAD;
132
6
        }
133
134
        /* adjust for PCM audio by skipping chunk header */
135
56.4k
        if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
136
1.16k
            s->audio_chunk_offset += 6;
137
1.16k
            s->audio_chunk_size -= 6;
138
1.16k
        }
139
140
56.4k
        avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
141
56.4k
        s->audio_chunk_offset = 0;
142
143
56.4k
        if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
144
236
            return CHUNK_EOF;
145
146
56.2k
        pkt->stream_index = s->audio_stream_index;
147
56.2k
        pkt->pts = s->audio_frame_count;
148
149
        /* audio frame maintenance */
150
56.2k
        if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM)
151
988
            s->audio_frame_count +=
152
988
            (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
153
55.2k
        else
154
55.2k
            s->audio_frame_count +=
155
55.2k
                (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
156
157
56.2k
        av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
158
56.2k
                pkt->pts, s->audio_frame_count);
159
160
56.2k
        chunk_type = CHUNK_HAVE_PACKET;
161
162
1.81M
    } else if (s->frame_format) {
163
164
        /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
165
166
694k
        if (av_new_packet(pkt, 8 + s->decode_map_chunk_size + s->video_chunk_size + s->skip_map_chunk_size))
167
0
            return CHUNK_NOMEM;
168
169
694k
        if (s->has_palette) {
170
1.38k
            uint8_t *pal;
171
172
1.38k
            pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
173
1.38k
                                          AVPALETTE_SIZE);
174
1.38k
            if (pal) {
175
1.38k
                memcpy(pal, s->palette, AVPALETTE_SIZE);
176
1.38k
                s->has_palette = 0;
177
1.38k
            }
178
1.38k
        }
179
180
694k
        if (s->changed) {
181
2.95k
            ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
182
2.95k
            s->changed = 0;
183
2.95k
        }
184
185
694k
        AV_WL8(pkt->data, s->frame_format);
186
694k
        AV_WL8(pkt->data + 1, s->send_buffer);
187
694k
        AV_WL16(pkt->data + 2, s->video_chunk_size);
188
694k
        AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
189
694k
        AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
190
191
694k
        s->frame_format = 0;
192
694k
        s->send_buffer = 0;
193
194
694k
        pkt->pos = s->video_chunk_offset;
195
694k
        avio_seek(pb, s->video_chunk_offset, SEEK_SET);
196
694k
        s->video_chunk_offset = 0;
197
198
694k
        if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
199
694k
            s->video_chunk_size) {
200
122
            return CHUNK_EOF;
201
122
        }
202
203
694k
        if (s->decode_map_chunk_size) {
204
689
            pkt->pos = s->decode_map_chunk_offset;
205
689
            avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
206
689
            s->decode_map_chunk_offset = 0;
207
208
689
            if (avio_read(pb, pkt->data + 8 + s->video_chunk_size,
209
689
                s->decode_map_chunk_size) != s->decode_map_chunk_size) {
210
34
                return CHUNK_EOF;
211
34
            }
212
689
        }
213
214
694k
        if (s->skip_map_chunk_size) {
215
1.26k
            pkt->pos = s->skip_map_chunk_offset;
216
1.26k
            avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET);
217
1.26k
            s->skip_map_chunk_offset = 0;
218
219
1.26k
            if (avio_read(pb, pkt->data + 8 + s->video_chunk_size + s->decode_map_chunk_size,
220
1.26k
                s->skip_map_chunk_size) != s->skip_map_chunk_size) {
221
34
                return CHUNK_EOF;
222
34
            }
223
1.26k
        }
224
225
694k
        s->video_chunk_size = 0;
226
694k
        s->decode_map_chunk_size = 0;
227
694k
        s->skip_map_chunk_size = 0;
228
229
694k
        pkt->stream_index = s->video_stream_index;
230
694k
        pkt->pts = s->video_pts;
231
232
694k
        av_log(s->avf, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts);
233
234
694k
        s->video_pts += s->frame_pts_inc;
235
236
694k
        chunk_type = CHUNK_HAVE_PACKET;
237
238
1.12M
    } else {
239
240
1.12M
        avio_seek(pb, s->next_chunk_offset, SEEK_SET);
241
1.12M
        chunk_type = CHUNK_DONE;
242
243
1.12M
    }
244
245
1.87M
    return chunk_type;
246
1.87M
}
247
248
static int init_audio(AVFormatContext *s)
249
1.46k
{
250
1.46k
    IPMVEContext *ipmovie = s->priv_data;
251
1.46k
    AVStream *st = avformat_new_stream(s, NULL);
252
1.46k
    if (!st)
253
0
        return AVERROR(ENOMEM);
254
1.46k
    avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
255
1.46k
    ipmovie->audio_stream_index = st->index;
256
1.46k
    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
257
1.46k
    st->codecpar->codec_id = ipmovie->audio_type;
258
1.46k
    st->codecpar->codec_tag = 0;  /* no tag */
259
1.46k
    av_channel_layout_default(&st->codecpar->ch_layout, ipmovie->audio_channels);
260
1.46k
    st->codecpar->sample_rate = ipmovie->audio_sample_rate;
261
1.46k
    st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
262
1.46k
    st->codecpar->bit_rate = ipmovie->audio_channels * st->codecpar->sample_rate *
263
1.46k
        st->codecpar->bits_per_coded_sample;
264
1.46k
    if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
265
667
        st->codecpar->bit_rate /= 2;
266
1.46k
    st->codecpar->block_align = ipmovie->audio_channels * st->codecpar->bits_per_coded_sample;
267
268
1.46k
    return 0;
269
1.46k
}
270
271
/* This function loads and processes a single chunk in an IP movie file.
272
 * It returns the type of chunk that was processed. */
273
static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
274
    AVPacket *pkt)
275
1.23M
{
276
1.23M
    unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
277
1.23M
    int chunk_type;
278
1.23M
    int chunk_size;
279
1.23M
    unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
280
1.23M
    unsigned char opcode_type;
281
1.23M
    unsigned char opcode_version;
282
1.23M
    int opcode_size;
283
1.23M
    unsigned char scratch[1024];
284
1.23M
    int i, j;
285
1.23M
    int first_color, last_color;
286
1.23M
    int audio_flags;
287
1.23M
    unsigned char r, g, b;
288
1.23M
    unsigned int width, height;
289
290
    /* see if there are any pending packets */
291
1.23M
    chunk_type = load_ipmovie_packet(s, pb, pkt);
292
1.23M
    if (chunk_type != CHUNK_DONE)
293
118k
        return chunk_type;
294
295
    /* read the next chunk, wherever the file happens to be pointing */
296
1.11M
    if (avio_feof(pb))
297
35
        return CHUNK_EOF;
298
1.11M
    if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
299
1.11M
        CHUNK_PREAMBLE_SIZE)
300
3.62k
        return CHUNK_BAD;
301
1.11M
    chunk_size = AV_RL16(&chunk_preamble[0]);
302
1.11M
    chunk_type = AV_RL16(&chunk_preamble[2]);
303
304
1.11M
    av_log(s->avf, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
305
306
1.11M
    switch (chunk_type) {
307
308
474k
    case CHUNK_INIT_AUDIO:
309
474k
        av_log(s->avf, AV_LOG_TRACE, "initialize audio\n");
310
474k
        break;
311
312
2.22k
    case CHUNK_AUDIO_ONLY:
313
2.22k
        av_log(s->avf, AV_LOG_TRACE, "audio only\n");
314
2.22k
        break;
315
316
5.20k
    case CHUNK_INIT_VIDEO:
317
5.20k
        av_log(s->avf, AV_LOG_TRACE, "initialize video\n");
318
5.20k
        break;
319
320
632k
    case CHUNK_VIDEO:
321
632k
        av_log(s->avf, AV_LOG_TRACE, "video (and audio)\n");
322
632k
        break;
323
324
45
    case CHUNK_SHUTDOWN:
325
45
        av_log(s->avf, AV_LOG_TRACE, "shutdown\n");
326
45
        break;
327
328
52
    case CHUNK_END:
329
52
        av_log(s->avf, AV_LOG_TRACE, "end\n");
330
52
        break;
331
332
794
    default:
333
794
        av_log(s->avf, AV_LOG_TRACE, "invalid chunk\n");
334
794
        chunk_type = CHUNK_BAD;
335
794
        break;
336
337
1.11M
    }
338
339
1.91M
    while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
340
341
        /* read the next chunk, wherever the file happens to be pointing */
342
799k
        if (avio_feof(pb)) {
343
314
            chunk_type = CHUNK_EOF;
344
314
            break;
345
314
        }
346
798k
        if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
347
798k
            CHUNK_PREAMBLE_SIZE) {
348
892
            chunk_type = CHUNK_BAD;
349
892
            break;
350
892
        }
351
352
797k
        opcode_size = AV_RL16(&opcode_preamble[0]);
353
797k
        opcode_type = opcode_preamble[2];
354
797k
        opcode_version = opcode_preamble[3];
355
356
797k
        chunk_size -= OPCODE_PREAMBLE_SIZE;
357
797k
        chunk_size -= opcode_size;
358
797k
        if (chunk_size < 0) {
359
253
            av_log(s->avf, AV_LOG_TRACE, "chunk_size countdown just went negative\n");
360
253
            chunk_type = CHUNK_BAD;
361
253
            break;
362
253
        }
363
364
797k
        av_log(s->avf, AV_LOG_TRACE, "  opcode type %02X, version %d, 0x%04X bytes: ",
365
797k
                opcode_type, opcode_version, opcode_size);
366
797k
        switch (opcode_type) {
367
368
10.7k
        case OPCODE_END_OF_STREAM:
369
10.7k
            av_log(s->avf, AV_LOG_TRACE, "end of stream\n");
370
10.7k
            avio_skip(pb, opcode_size);
371
10.7k
            break;
372
373
1.04k
        case OPCODE_END_OF_CHUNK:
374
1.04k
            av_log(s->avf, AV_LOG_TRACE, "end of chunk\n");
375
1.04k
            avio_skip(pb, opcode_size);
376
1.04k
            break;
377
378
4.10k
        case OPCODE_CREATE_TIMER:
379
4.10k
            av_log(s->avf, AV_LOG_TRACE, "create timer\n");
380
4.10k
            if ((opcode_version > 0) || (opcode_size != 6)) {
381
74
                av_log(s->avf, AV_LOG_TRACE, "bad create_timer opcode\n");
382
74
                chunk_type = CHUNK_BAD;
383
74
                break;
384
74
            }
385
4.03k
            if (avio_read(pb, scratch, opcode_size) !=
386
4.03k
                opcode_size) {
387
9
                chunk_type = CHUNK_BAD;
388
9
                break;
389
9
            }
390
4.02k
            s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
391
4.02k
            break;
392
393
10.2k
        case OPCODE_INIT_AUDIO_BUFFERS:
394
10.2k
            av_log(s->avf, AV_LOG_TRACE, "initialize audio buffers\n");
395
10.2k
            if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
396
45
                av_log(s->avf, AV_LOG_TRACE, "bad init_audio_buffers opcode\n");
397
45
                chunk_type = CHUNK_BAD;
398
45
                break;
399
45
            }
400
10.1k
            if (avio_read(pb, scratch, opcode_size) !=
401
10.1k
                opcode_size) {
402
13
                chunk_type = CHUNK_BAD;
403
13
                break;
404
13
            }
405
10.1k
            s->audio_sample_rate = AV_RL16(&scratch[4]);
406
10.1k
            audio_flags = AV_RL16(&scratch[2]);
407
            /* bit 0 of the flags: 0 = mono, 1 = stereo */
408
10.1k
            s->audio_channels = (audio_flags & 1) + 1;
409
            /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
410
10.1k
            s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
411
            /* bit 2 indicates compressed audio in version 1 opcode */
412
10.1k
            if ((opcode_version == 1) && (audio_flags & 0x4))
413
2.35k
                s->audio_type = AV_CODEC_ID_INTERPLAY_DPCM;
414
7.79k
            else if (s->audio_bits == 16)
415
864
                s->audio_type = AV_CODEC_ID_PCM_S16LE;
416
6.93k
            else
417
6.93k
                s->audio_type = AV_CODEC_ID_PCM_U8;
418
10.1k
            av_log(s->avf, AV_LOG_TRACE, "audio: %d bits, %d Hz, %s, %s format\n",
419
10.1k
                    s->audio_bits, s->audio_sample_rate,
420
10.1k
                    (s->audio_channels == 2) ? "stereo" : "mono",
421
10.1k
                    (s->audio_type == AV_CODEC_ID_INTERPLAY_DPCM) ?
422
7.79k
                    "Interplay audio" : "PCM");
423
10.1k
            break;
424
425
783
        case OPCODE_START_STOP_AUDIO:
426
783
            av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
427
783
            avio_skip(pb, opcode_size);
428
783
            break;
429
430
6.91k
        case OPCODE_INIT_VIDEO_BUFFERS:
431
6.91k
            av_log(s->avf, AV_LOG_TRACE, "initialize video buffers\n");
432
6.91k
            if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
433
6.88k
                || opcode_version == 2 && opcode_size < 8
434
6.91k
            ) {
435
44
                av_log(s->avf, AV_LOG_TRACE, "bad init_video_buffers opcode\n");
436
44
                chunk_type = CHUNK_BAD;
437
44
                break;
438
44
            }
439
6.87k
            if (avio_read(pb, scratch, opcode_size) !=
440
6.87k
                opcode_size) {
441
36
                chunk_type = CHUNK_BAD;
442
36
                break;
443
36
            }
444
6.83k
            width  = AV_RL16(&scratch[0]) * 8;
445
6.83k
            height = AV_RL16(&scratch[2]) * 8;
446
6.83k
            if (width != s->video_width) {
447
3.92k
                s->video_width = width;
448
3.92k
                s->changed++;
449
3.92k
            }
450
6.83k
            if (height != s->video_height) {
451
4.56k
                s->video_height = height;
452
4.56k
                s->changed++;
453
4.56k
            }
454
6.83k
            if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
455
6.27k
                s->video_bpp = 8;
456
6.27k
            } else {
457
558
                s->video_bpp = 16;
458
558
            }
459
6.83k
            av_log(s->avf, AV_LOG_TRACE, "video resolution: %d x %d\n",
460
6.83k
                    s->video_width, s->video_height);
461
6.83k
            break;
462
463
291
        case OPCODE_UNKNOWN_12:
464
839
        case OPCODE_UNKNOWN_13:
465
1.30k
        case OPCODE_UNKNOWN_14:
466
1.72k
        case OPCODE_UNKNOWN_15:
467
1.72k
            av_log(s->avf, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type);
468
1.72k
            avio_skip(pb, opcode_size);
469
1.72k
            break;
470
471
1.47k
        case OPCODE_SEND_BUFFER:
472
1.47k
            av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
473
1.47k
            avio_skip(pb, opcode_size);
474
1.47k
            s->send_buffer = 1;
475
1.47k
            break;
476
477
58.2k
        case OPCODE_AUDIO_FRAME:
478
58.2k
            av_log(s->avf, AV_LOG_TRACE, "audio frame\n");
479
480
            /* log position and move on for now */
481
58.2k
            s->audio_chunk_offset = avio_tell(pb);
482
58.2k
            s->audio_chunk_size = opcode_size;
483
58.2k
            avio_skip(pb, opcode_size);
484
58.2k
            break;
485
486
843
        case OPCODE_SILENCE_FRAME:
487
843
            av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
488
843
            avio_skip(pb, opcode_size);
489
843
            break;
490
491
450
        case OPCODE_INIT_VIDEO_MODE:
492
450
            av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
493
450
            avio_skip(pb, opcode_size);
494
450
            break;
495
496
149
        case OPCODE_CREATE_GRADIENT:
497
149
            av_log(s->avf, AV_LOG_TRACE, "create gradient\n");
498
149
            avio_skip(pb, opcode_size);
499
149
            break;
500
501
1.85k
        case OPCODE_SET_PALETTE:
502
1.85k
            av_log(s->avf, AV_LOG_TRACE, "set palette\n");
503
            /* check for the logical maximum palette size
504
             * (3 * 256 + 4 bytes) */
505
1.85k
            if (opcode_size > 0x304 || opcode_size < 4) {
506
20
                av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode with invalid size\n");
507
20
                chunk_type = CHUNK_BAD;
508
20
                break;
509
20
            }
510
1.83k
            if (avio_read(pb, scratch, opcode_size) != opcode_size) {
511
33
                chunk_type = CHUNK_BAD;
512
33
                break;
513
33
            }
514
515
            /* load the palette into internal data structure */
516
1.80k
            first_color = AV_RL16(&scratch[0]);
517
1.80k
            last_color = first_color + AV_RL16(&scratch[2]) - 1;
518
            /* sanity check (since they are 16 bit values) */
519
1.80k
            if (   (first_color > 0xFF) || (last_color > 0xFF)
520
1.77k
                || (last_color - first_color + 1)*3 + 4 > opcode_size) {
521
46
                av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
522
46
                    first_color, last_color);
523
46
                chunk_type = CHUNK_BAD;
524
46
                break;
525
46
            }
526
1.75k
            j = 4;  /* offset of first palette data */
527
5.71k
            for (i = first_color; i <= last_color; i++) {
528
                /* the palette is stored as a 6-bit VGA palette, thus each
529
                 * component is shifted up to a 8-bit range */
530
3.96k
                r = scratch[j++] * 4;
531
3.96k
                g = scratch[j++] * 4;
532
3.96k
                b = scratch[j++] * 4;
533
3.96k
                s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
534
3.96k
                s->palette[i] |= s->palette[i] >> 6 & 0x30303;
535
3.96k
            }
536
1.75k
            s->has_palette = 1;
537
1.75k
            break;
538
539
393
        case OPCODE_SET_PALETTE_COMPRESSED:
540
393
            av_log(s->avf, AV_LOG_TRACE, "set palette compressed\n");
541
393
            avio_skip(pb, opcode_size);
542
393
            break;
543
544
1.85k
        case OPCODE_SET_SKIP_MAP:
545
1.85k
            av_log(s->avf, AV_LOG_TRACE, "set skip map\n");
546
547
            /* log position and move on for now */
548
1.85k
            s->skip_map_chunk_offset = avio_tell(pb);
549
1.85k
            s->skip_map_chunk_size = opcode_size;
550
1.85k
            avio_skip(pb, opcode_size);
551
1.85k
            break;
552
553
775
        case OPCODE_SET_DECODING_MAP:
554
775
            av_log(s->avf, AV_LOG_TRACE, "set decoding map\n");
555
556
            /* log position and move on for now */
557
775
            s->decode_map_chunk_offset = avio_tell(pb);
558
775
            s->decode_map_chunk_size = opcode_size;
559
775
            avio_skip(pb, opcode_size);
560
775
            break;
561
562
2.95k
        case OPCODE_VIDEO_DATA_06:
563
695k
        case OPCODE_VIDEO_DATA_10:
564
695k
        case OPCODE_VIDEO_DATA_11:
565
695k
            s->frame_format = opcode_type;
566
695k
            av_log(s->avf, AV_LOG_TRACE, "set video data format 0x%02X\n",
567
695k
                   opcode_type);
568
569
            /* log position and move on for now */
570
695k
            s->video_chunk_offset = avio_tell(pb);
571
695k
            s->video_chunk_size = opcode_size;
572
695k
            avio_skip(pb, opcode_size);
573
695k
            break;
574
575
171
        default:
576
171
            av_log(s->avf, AV_LOG_TRACE, "*** unknown opcode type\n");
577
171
            chunk_type = CHUNK_BAD;
578
171
            break;
579
580
797k
        }
581
797k
    }
582
583
1.11M
    if (s->avf->nb_streams == 1 && s->audio_type)
584
621
        init_audio(s->avf);
585
586
    /* make a note of where the stream is sitting */
587
1.11M
    s->next_chunk_offset = avio_tell(pb);
588
589
1.11M
    return chunk_type;
590
1.11M
}
591
592
static const char signature[] = "Interplay MVE File\x1A\0\x1A";
593
594
static int ipmovie_probe(const AVProbeData *p)
595
967k
{
596
967k
    const uint8_t *b = p->buf;
597
967k
    const uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
598
3.26G
    do {
599
3.26G
        if (b[0] == signature[0] && memcmp(b, signature, sizeof(signature)) == 0)
600
4.06k
            return AVPROBE_SCORE_MAX;
601
3.26G
        b++;
602
3.26G
    } while (b < b_end);
603
604
963k
    return 0;
605
967k
}
606
607
static int ipmovie_read_header(AVFormatContext *s)
608
4.27k
{
609
4.27k
    IPMVEContext *ipmovie = s->priv_data;
610
4.27k
    AVIOContext *pb = s->pb;
611
4.27k
    AVStream *st;
612
4.27k
    unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
613
4.27k
    int chunk_type, i;
614
4.27k
    uint8_t signature_buffer[sizeof(signature)];
615
4.27k
    int ret;
616
617
4.27k
    ipmovie->avf = s;
618
619
4.27k
    ret = ffio_read_size(pb, signature_buffer, sizeof(signature_buffer));
620
4.27k
    if (ret < 0)
621
106
        return ret;
622
15.6M
    while (memcmp(signature_buffer, signature, sizeof(signature))) {
623
15.6M
        memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
624
15.6M
        signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
625
15.6M
        if (avio_feof(pb))
626
182
            return AVERROR_EOF;
627
15.6M
    }
628
629
    /* on the first read, this will position the stream at the first chunk */
630
3.98k
    ipmovie->next_chunk_offset = avio_tell(pb) + 4;
631
632
1.02M
    for (i = 0; i < 256; i++)
633
1.01M
        ipmovie->palette[i] = 0xFFU << 24;
634
635
    /* process the first chunk which should be CHUNK_INIT_VIDEO */
636
3.98k
    if (process_ipmovie_chunk(ipmovie, pb, NULL) != CHUNK_INIT_VIDEO) {
637
771
        return AVERROR_INVALIDDATA;
638
771
    }
639
640
    /* peek ahead to the next chunk-- if it is an init audio chunk, process
641
     * it; if it is the first video chunk, this is a silent file */
642
3.21k
    if ((ret = ffio_read_size(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE)) < 0)
643
6
        return ret;
644
3.20k
    chunk_type = AV_RL16(&chunk_preamble[2]);
645
3.20k
    avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
646
647
3.20k
    if (chunk_type == CHUNK_VIDEO)
648
1.39k
        ipmovie->audio_type = AV_CODEC_ID_NONE;  /* no audio */
649
1.81k
    else if (process_ipmovie_chunk(ipmovie, pb, ffformatcontext(s)->parse_pkt) != CHUNK_INIT_AUDIO) {
650
51
        return AVERROR_INVALIDDATA;
651
51
    }
652
653
    /* initialize the stream decoders */
654
3.15k
    st = avformat_new_stream(s, NULL);
655
3.15k
    if (!st)
656
0
        return AVERROR(ENOMEM);
657
3.15k
    avpriv_set_pts_info(st, 63, 1, 1000000);
658
3.15k
    ipmovie->video_stream_index = st->index;
659
3.15k
    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
660
3.15k
    st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
661
3.15k
    st->codecpar->codec_tag = 0;  /* no fourcc */
662
3.15k
    st->codecpar->width = ipmovie->video_width;
663
3.15k
    st->codecpar->height = ipmovie->video_height;
664
3.15k
    st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
665
666
3.15k
    if (ipmovie->audio_type) {
667
839
        return init_audio(s);
668
839
    } else
669
2.31k
       s->ctx_flags |= AVFMTCTX_NOHEADER;
670
671
2.31k
    return 0;
672
3.15k
}
673
674
static int ipmovie_read_packet(AVFormatContext *s,
675
                               AVPacket *pkt)
676
756k
{
677
756k
    IPMVEContext *ipmovie = s->priv_data;
678
756k
    AVIOContext *pb = s->pb;
679
756k
    int ret;
680
681
1.23M
    for (;;) {
682
1.23M
        ret = process_ipmovie_chunk(ipmovie, pb, pkt);
683
        /* dispatch the first of any pending packets */
684
1.23M
        if ((ret == CHUNK_VIDEO) || (ret == CHUNK_AUDIO_ONLY))
685
634k
            ret = load_ipmovie_packet(ipmovie, pb, pkt);
686
687
1.23M
        if (ret == CHUNK_BAD)
688
5.35k
            ret = AVERROR_INVALIDDATA;
689
1.22M
        else if (ret == CHUNK_EOF)
690
683
            ret = AVERROR_INVALIDDATA;
691
1.22M
        else if (ret == CHUNK_NOMEM)
692
0
            ret = AVERROR(ENOMEM);
693
1.22M
        else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
694
39
            ret = AVERROR_EOF;
695
1.22M
        else if (ret == CHUNK_HAVE_PACKET)
696
750k
            ret = 0;
697
475k
        else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
698
473k
            continue;
699
1.38k
        else
700
1.38k
            continue;
701
702
756k
        return ret;
703
1.23M
    }
704
756k
}
705
706
const FFInputFormat ff_ipmovie_demuxer = {
707
    .p.name         = "ipmovie",
708
    .p.long_name    = NULL_IF_CONFIG_SMALL("Interplay MVE"),
709
    .priv_data_size = sizeof(IPMVEContext),
710
    .read_probe     = ipmovie_probe,
711
    .read_header    = ipmovie_read_header,
712
    .read_packet    = ipmovie_read_packet,
713
};