ipmovie.c 21 KB
Newer Older
1 2 3 4
/*
 * Interplay MVE File Demuxer
 * Copyright (c) 2003 The ffmpeg Project
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * 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
 * Libav is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; 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 25 26 27 28 29 30 31 32 33 34
 * Interplay MVE file demuxer
 * by Mike Melanson (melanson@pcisys.net)
 * For more information regarding the Interplay MVE file format, visit:
 *   http://www.pcisys.net/~melanson/codecs/
 * The aforementioned site also contains a command line utility for parsing
 * IP MVE files so that you can get a good idea of the typical structure of
 * such files. This demuxer is not the best example to use if you are trying
 * to write your own as it uses a rather roundabout approach for splitting
 * up and sending out the chunks.
 */

35
#include "libavutil/intreadwrite.h"
36
#include "avformat.h"
37
#include "internal.h"
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

#define CHUNK_PREAMBLE_SIZE 4
#define OPCODE_PREAMBLE_SIZE 4

#define CHUNK_INIT_AUDIO   0x0000
#define CHUNK_AUDIO_ONLY   0x0001
#define CHUNK_INIT_VIDEO   0x0002
#define CHUNK_VIDEO        0x0003
#define CHUNK_SHUTDOWN     0x0004
#define CHUNK_END          0x0005
/* these last types are used internally */
#define CHUNK_DONE         0xFFFC
#define CHUNK_NOMEM        0xFFFD
#define CHUNK_EOF          0xFFFE
#define CHUNK_BAD          0xFFFF

#define OPCODE_END_OF_STREAM           0x00
#define OPCODE_END_OF_CHUNK            0x01
#define OPCODE_CREATE_TIMER            0x02
#define OPCODE_INIT_AUDIO_BUFFERS      0x03
#define OPCODE_START_STOP_AUDIO        0x04
#define OPCODE_INIT_VIDEO_BUFFERS      0x05
#define OPCODE_UNKNOWN_06              0x06
#define OPCODE_SEND_BUFFER             0x07
#define OPCODE_AUDIO_FRAME             0x08
#define OPCODE_SILENCE_FRAME           0x09
#define OPCODE_INIT_VIDEO_MODE         0x0A
#define OPCODE_CREATE_GRADIENT         0x0B
#define OPCODE_SET_PALETTE             0x0C
#define OPCODE_SET_PALETTE_COMPRESSED  0x0D
#define OPCODE_UNKNOWN_0E              0x0E
#define OPCODE_SET_DECODING_MAP        0x0F
#define OPCODE_UNKNOWN_10              0x10
#define OPCODE_VIDEO_DATA              0x11
#define OPCODE_UNKNOWN_12              0x12
#define OPCODE_UNKNOWN_13              0x13
#define OPCODE_UNKNOWN_14              0x14
#define OPCODE_UNKNOWN_15              0x15

#define PALETTE_COUNT 256

typedef struct IPMVEContext {

    unsigned char *buf;
    int buf_size;

84
    uint64_t frame_pts_inc;
85

86
    unsigned int video_bpp;
87 88 89
    unsigned int video_width;
    unsigned int video_height;
    int64_t video_pts;
90 91
    uint32_t     palette[256];
    int          has_palette;
92
    int          changed;
93 94 95 96

    unsigned int audio_bits;
    unsigned int audio_channels;
    unsigned int audio_sample_rate;
97
    enum AVCodecID audio_type;
98 99 100 101 102
    unsigned int audio_frame_count;

    int video_stream_index;
    int audio_stream_index;

103
    int64_t audio_chunk_offset;
104
    int audio_chunk_size;
105
    int64_t video_chunk_offset;
106
    int video_chunk_size;
107
    int64_t decode_map_chunk_offset;
108 109
    int decode_map_chunk_size;

110
    int64_t next_chunk_offset;
111 112 113

} IPMVEContext;

114
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
115 116 117 118 119
    AVPacket *pkt) {

    int chunk_type;

    if (s->audio_chunk_offset) {
120
        if (s->audio_type == AV_CODEC_ID_NONE) {
121 122 123 124
            av_log(NULL, AV_LOG_ERROR, "Can not read audio packet before"
                   "audio codec is known\n");
                return CHUNK_BAD;
        }
125

126
        /* adjust for PCM audio by skipping chunk header */
127
        if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
128 129 130 131
            s->audio_chunk_offset += 6;
            s->audio_chunk_size -= 6;
        }

132
        avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
133 134
        s->audio_chunk_offset = 0;

Michael Niedermayer's avatar
Michael Niedermayer committed
135 136
        if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
            return CHUNK_EOF;
137 138

        pkt->stream_index = s->audio_stream_index;
139
        pkt->pts = s->audio_frame_count;
140 141

        /* audio frame maintenance */
142
        if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM)
143 144 145 146
            s->audio_frame_count +=
            (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
        else
            s->audio_frame_count +=
147
                (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
148

149 150
        av_dlog(NULL, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
                pkt->pts, s->audio_frame_count);
151 152 153 154 155

        chunk_type = CHUNK_VIDEO;

    } else if (s->decode_map_chunk_offset) {

156
        /* send both the decode map and the video data together */
157

158
        if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size))
159 160
            return CHUNK_NOMEM;

161 162 163 164 165 166 167 168 169 170 171
        if (s->has_palette) {
            uint8_t *pal;

            pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
                                          AVPALETTE_SIZE);
            if (pal) {
                memcpy(pal, s->palette, AVPALETTE_SIZE);
                s->has_palette = 0;
            }
        }

172 173 174 175
        if (s->changed) {
            ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
            s->changed = 0;
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
176
        pkt->pos= s->decode_map_chunk_offset;
177
        avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
178 179
        s->decode_map_chunk_offset = 0;

180
        if (avio_read(pb, pkt->data, s->decode_map_chunk_size) !=
181 182 183 184 185
            s->decode_map_chunk_size) {
            av_free_packet(pkt);
            return CHUNK_EOF;
        }

186
        avio_seek(pb, s->video_chunk_offset, SEEK_SET);
187 188
        s->video_chunk_offset = 0;

189
        if (avio_read(pb, pkt->data + s->decode_map_chunk_size,
190
            s->video_chunk_size) != s->video_chunk_size) {
191 192 193 194
            av_free_packet(pkt);
            return CHUNK_EOF;
        }

195 196 197
        pkt->stream_index = s->video_stream_index;
        pkt->pts = s->video_pts;

198
        av_dlog(NULL, "sending video frame with pts %"PRId64"\n", pkt->pts);
199

200 201 202 203 204 205
        s->video_pts += s->frame_pts_inc;

        chunk_type = CHUNK_VIDEO;

    } else {

206
        avio_seek(pb, s->next_chunk_offset, SEEK_SET);
207 208 209 210 211 212 213 214 215
        chunk_type = CHUNK_DONE;

    }

    return chunk_type;
}

/* This function loads and processes a single chunk in an IP movie file.
 * It returns the type of chunk that was processed. */
216
static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
217 218 219 220 221 222 223 224 225 226
    AVPacket *pkt)
{
    unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
    int chunk_type;
    int chunk_size;
    unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
    unsigned char opcode_type;
    unsigned char opcode_version;
    int opcode_size;
    unsigned char scratch[1024];
227
    int i, j;
228 229
    int first_color, last_color;
    int audio_flags;
230
    unsigned char r, g, b;
231
    unsigned int width, height;
232 233 234

    /* see if there are any pending packets */
    chunk_type = load_ipmovie_packet(s, pb, pkt);
235
    if (chunk_type != CHUNK_DONE)
236 237 238
        return chunk_type;

    /* read the next chunk, wherever the file happens to be pointing */
Anton Khirnov's avatar
Anton Khirnov committed
239
    if (pb->eof_reached)
240
        return CHUNK_EOF;
241
    if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
242 243
        CHUNK_PREAMBLE_SIZE)
        return CHUNK_BAD;
244 245
    chunk_size = AV_RL16(&chunk_preamble[0]);
    chunk_type = AV_RL16(&chunk_preamble[2]);
246

247
    av_dlog(NULL, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
248 249 250 251

    switch (chunk_type) {

    case CHUNK_INIT_AUDIO:
252
        av_dlog(NULL, "initialize audio\n");
253 254 255
        break;

    case CHUNK_AUDIO_ONLY:
256
        av_dlog(NULL, "audio only\n");
257 258 259
        break;

    case CHUNK_INIT_VIDEO:
260
        av_dlog(NULL, "initialize video\n");
261 262 263
        break;

    case CHUNK_VIDEO:
264
        av_dlog(NULL, "video (and audio)\n");
265 266 267
        break;

    case CHUNK_SHUTDOWN:
268
        av_dlog(NULL, "shutdown\n");
269 270 271
        break;

    case CHUNK_END:
272
        av_dlog(NULL, "end\n");
273 274 275
        break;

    default:
276
        av_dlog(NULL, "invalid chunk\n");
277 278 279 280 281 282 283 284
        chunk_type = CHUNK_BAD;
        break;

    }

    while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {

        /* read the next chunk, wherever the file happens to be pointing */
Anton Khirnov's avatar
Anton Khirnov committed
285
        if (pb->eof_reached) {
286 287 288
            chunk_type = CHUNK_EOF;
            break;
        }
289
        if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
290 291 292 293 294
            CHUNK_PREAMBLE_SIZE) {
            chunk_type = CHUNK_BAD;
            break;
        }

295
        opcode_size = AV_RL16(&opcode_preamble[0]);
296 297 298 299 300 301
        opcode_type = opcode_preamble[2];
        opcode_version = opcode_preamble[3];

        chunk_size -= OPCODE_PREAMBLE_SIZE;
        chunk_size -= opcode_size;
        if (chunk_size < 0) {
302
            av_dlog(NULL, "chunk_size countdown just went negative\n");
303 304 305 306
            chunk_type = CHUNK_BAD;
            break;
        }

307 308
        av_dlog(NULL, "  opcode type %02X, version %d, 0x%04X bytes: ",
                opcode_type, opcode_version, opcode_size);
309 310 311
        switch (opcode_type) {

        case OPCODE_END_OF_STREAM:
312
            av_dlog(NULL, "end of stream\n");
313
            avio_skip(pb, opcode_size);
314 315 316
            break;

        case OPCODE_END_OF_CHUNK:
317
            av_dlog(NULL, "end of chunk\n");
318
            avio_skip(pb, opcode_size);
319 320 321
            break;

        case OPCODE_CREATE_TIMER:
322
            av_dlog(NULL, "create timer\n");
323
            if ((opcode_version > 0) || (opcode_size > 6)) {
324
                av_dlog(NULL, "bad create_timer opcode\n");
325 326 327
                chunk_type = CHUNK_BAD;
                break;
            }
328
            if (avio_read(pb, scratch, opcode_size) !=
329 330 331 332
                opcode_size) {
                chunk_type = CHUNK_BAD;
                break;
            }
333
            s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
334 335 336
            av_dlog(NULL, "  %.2f frames/second (timer div = %d, subdiv = %d)\n",
                    1000000.0 / s->frame_pts_inc, AV_RL32(&scratch[0]),
                    AV_RL16(&scratch[4]));
337 338 339
            break;

        case OPCODE_INIT_AUDIO_BUFFERS:
340
            av_dlog(NULL, "initialize audio buffers\n");
341
            if ((opcode_version > 1) || (opcode_size > 10)) {
342
                av_dlog(NULL, "bad init_audio_buffers opcode\n");
343 344 345
                chunk_type = CHUNK_BAD;
                break;
            }
346
            if (avio_read(pb, scratch, opcode_size) !=
347 348 349 350
                opcode_size) {
                chunk_type = CHUNK_BAD;
                break;
            }
351 352
            s->audio_sample_rate = AV_RL16(&scratch[4]);
            audio_flags = AV_RL16(&scratch[2]);
353 354 355 356 357 358
            /* bit 0 of the flags: 0 = mono, 1 = stereo */
            s->audio_channels = (audio_flags & 1) + 1;
            /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
            s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
            /* bit 2 indicates compressed audio in version 1 opcode */
            if ((opcode_version == 1) && (audio_flags & 0x4))
359
                s->audio_type = AV_CODEC_ID_INTERPLAY_DPCM;
360
            else if (s->audio_bits == 16)
361
                s->audio_type = AV_CODEC_ID_PCM_S16LE;
362
            else
363
                s->audio_type = AV_CODEC_ID_PCM_U8;
364 365 366
            av_dlog(NULL, "audio: %d bits, %d Hz, %s, %s format\n",
                    s->audio_bits, s->audio_sample_rate,
                    (s->audio_channels == 2) ? "stereo" : "mono",
367
                    (s->audio_type == AV_CODEC_ID_INTERPLAY_DPCM) ?
368
                    "Interplay audio" : "PCM");
369 370 371
            break;

        case OPCODE_START_STOP_AUDIO:
372
            av_dlog(NULL, "start/stop audio\n");
373
            avio_skip(pb, opcode_size);
374 375 376
            break;

        case OPCODE_INIT_VIDEO_BUFFERS:
377
            av_dlog(NULL, "initialize video buffers\n");
378
            if ((opcode_version > 2) || (opcode_size > 8)) {
379
                av_dlog(NULL, "bad init_video_buffers opcode\n");
380 381 382
                chunk_type = CHUNK_BAD;
                break;
            }
383
            if (avio_read(pb, scratch, opcode_size) !=
384 385 386 387
                opcode_size) {
                chunk_type = CHUNK_BAD;
                break;
            }
388 389 390 391 392 393 394 395 396 397
            width  = AV_RL16(&scratch[0]) * 8;
            height = AV_RL16(&scratch[2]) * 8;
            if (width != s->video_width) {
                s->video_width = width;
                s->changed++;
            }
            if (height != s->video_height) {
                s->video_height = height;
                s->changed++;
            }
398 399 400 401 402
            if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
                s->video_bpp = 8;
            } else {
                s->video_bpp = 16;
            }
403 404
            av_dlog(NULL, "video resolution: %d x %d\n",
                    s->video_width, s->video_height);
405 406 407 408 409 410 411 412 413
            break;

        case OPCODE_UNKNOWN_06:
        case OPCODE_UNKNOWN_0E:
        case OPCODE_UNKNOWN_10:
        case OPCODE_UNKNOWN_12:
        case OPCODE_UNKNOWN_13:
        case OPCODE_UNKNOWN_14:
        case OPCODE_UNKNOWN_15:
414
            av_dlog(NULL, "unknown (but documented) opcode %02X\n", opcode_type);
415
            avio_skip(pb, opcode_size);
416 417 418
            break;

        case OPCODE_SEND_BUFFER:
419
            av_dlog(NULL, "send buffer\n");
420
            avio_skip(pb, opcode_size);
421 422 423
            break;

        case OPCODE_AUDIO_FRAME:
424
            av_dlog(NULL, "audio frame\n");
425 426

            /* log position and move on for now */
427
            s->audio_chunk_offset = avio_tell(pb);
428
            s->audio_chunk_size = opcode_size;
429
            avio_skip(pb, opcode_size);
430 431 432
            break;

        case OPCODE_SILENCE_FRAME:
433
            av_dlog(NULL, "silence frame\n");
434
            avio_skip(pb, opcode_size);
435 436 437
            break;

        case OPCODE_INIT_VIDEO_MODE:
438
            av_dlog(NULL, "initialize video mode\n");
439
            avio_skip(pb, opcode_size);
440 441 442
            break;

        case OPCODE_CREATE_GRADIENT:
443
            av_dlog(NULL, "create gradient\n");
444
            avio_skip(pb, opcode_size);
445 446 447
            break;

        case OPCODE_SET_PALETTE:
448
            av_dlog(NULL, "set palette\n");
449 450 451
            /* check for the logical maximum palette size
             * (3 * 256 + 4 bytes) */
            if (opcode_size > 0x304) {
452
                av_dlog(NULL, "demux_ipmovie: set_palette opcode too large\n");
453 454 455
                chunk_type = CHUNK_BAD;
                break;
            }
456
            if (avio_read(pb, scratch, opcode_size) != opcode_size) {
457 458 459 460 461
                chunk_type = CHUNK_BAD;
                break;
            }

            /* load the palette into internal data structure */
462 463
            first_color = AV_RL16(&scratch[0]);
            last_color = first_color + AV_RL16(&scratch[2]) - 1;
464 465
            /* sanity check (since they are 16 bit values) */
            if ((first_color > 0xFF) || (last_color > 0xFF)) {
466
                av_dlog(NULL, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
467 468 469 470 471 472
                    first_color, last_color);
                chunk_type = CHUNK_BAD;
                break;
            }
            j = 4;  /* offset of first palette data */
            for (i = first_color; i <= last_color; i++) {
473 474
                /* the palette is stored as a 6-bit VGA palette, thus each
                 * component is shifted up to a 8-bit range */
475 476 477
                r = scratch[j++] * 4;
                g = scratch[j++] * 4;
                b = scratch[j++] * 4;
478
                s->palette[i] = (r << 16) | (g << 8) | (b);
479
            }
480
            s->has_palette = 1;
481 482 483
            break;

        case OPCODE_SET_PALETTE_COMPRESSED:
484
            av_dlog(NULL, "set palette compressed\n");
485
            avio_skip(pb, opcode_size);
486 487 488
            break;

        case OPCODE_SET_DECODING_MAP:
489
            av_dlog(NULL, "set decoding map\n");
490 491

            /* log position and move on for now */
492
            s->decode_map_chunk_offset = avio_tell(pb);
493
            s->decode_map_chunk_size = opcode_size;
494
            avio_skip(pb, opcode_size);
495 496 497
            break;

        case OPCODE_VIDEO_DATA:
498
            av_dlog(NULL, "set video data\n");
499 500

            /* log position and move on for now */
501
            s->video_chunk_offset = avio_tell(pb);
502
            s->video_chunk_size = opcode_size;
503
            avio_skip(pb, opcode_size);
504 505 506
            break;

        default:
507
            av_dlog(NULL, "*** unknown opcode type\n");
508 509 510 511 512 513 514
            chunk_type = CHUNK_BAD;
            break;

        }
    }

    /* make a note of where the stream is sitting */
515
    s->next_chunk_offset = avio_tell(pb);
516 517 518 519 520 521 522 523

    /* dispatch the first of any pending packets */
    if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
        chunk_type = load_ipmovie_packet(s, pb, pkt);

    return chunk_type;
}

524 525
static const char signature[] = "Interplay MVE File\x1A\0\x1A";

526 527
static int ipmovie_probe(AVProbeData *p)
{
528 529 530 531 532 533 534 535
    uint8_t *b = p->buf;
    uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
    do {
        if (memcmp(b++, signature, sizeof(signature)) == 0)
            return AVPROBE_SCORE_MAX;
    } while (b < b_end);

    return 0;
536 537
}

538
static int ipmovie_read_header(AVFormatContext *s)
539
{
540
    IPMVEContext *ipmovie = s->priv_data;
541
    AVIOContext *pb = s->pb;
542 543
    AVPacket pkt;
    AVStream *st;
544 545
    unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
    int chunk_type;
546 547
    uint8_t signature_buffer[sizeof(signature)];

548
    avio_read(pb, signature_buffer, sizeof(signature_buffer));
549 550
    while (memcmp(signature_buffer, signature, sizeof(signature))) {
        memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
551
        signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
Anton Khirnov's avatar
Anton Khirnov committed
552
        if (pb->eof_reached)
553 554
            return AVERROR_EOF;
    }
555 556 557 558 559 560
    /* initialize private context members */
    ipmovie->video_pts = ipmovie->audio_frame_count = 0;
    ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
    ipmovie->decode_map_chunk_offset = 0;

    /* on the first read, this will position the stream at the first chunk */
561
    ipmovie->next_chunk_offset = avio_tell(pb) + 4;
562 563 564 565 566

    /* process the first chunk which should be CHUNK_INIT_VIDEO */
    if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
        return AVERROR_INVALIDDATA;

567 568
    /* peek ahead to the next chunk-- if it is an init audio chunk, process
     * it; if it is the first video chunk, this is a silent file */
569
    if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
570
        CHUNK_PREAMBLE_SIZE)
571
        return AVERROR(EIO);
572
    chunk_type = AV_RL16(&chunk_preamble[2]);
573
    avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
574 575

    if (chunk_type == CHUNK_VIDEO)
576
        ipmovie->audio_type = AV_CODEC_ID_NONE;  /* no audio */
577
    else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
578 579 580
        return AVERROR_INVALIDDATA;

    /* initialize the stream decoders */
581
    st = avformat_new_stream(s, NULL);
582
    if (!st)
583
        return AVERROR(ENOMEM);
584
    avpriv_set_pts_info(st, 63, 1, 1000000);
585
    ipmovie->video_stream_index = st->index;
586
    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
587
    st->codec->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
588 589 590
    st->codec->codec_tag = 0;  /* no fourcc */
    st->codec->width = ipmovie->video_width;
    st->codec->height = ipmovie->video_height;
591
    st->codec->bits_per_coded_sample = ipmovie->video_bpp;
592

593
    if (ipmovie->audio_type) {
594
        st = avformat_new_stream(s, NULL);
595
        if (!st)
596
            return AVERROR(ENOMEM);
597
        avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
598
        ipmovie->audio_stream_index = st->index;
599
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
600 601 602 603
        st->codec->codec_id = ipmovie->audio_type;
        st->codec->codec_tag = 0;  /* no tag */
        st->codec->channels = ipmovie->audio_channels;
        st->codec->sample_rate = ipmovie->audio_sample_rate;
604
        st->codec->bits_per_coded_sample = ipmovie->audio_bits;
605
        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
606
            st->codec->bits_per_coded_sample;
607
        if (st->codec->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
608
            st->codec->bit_rate /= 2;
609
        st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
610
    }
611 612 613 614 615 616 617

    return 0;
}

static int ipmovie_read_packet(AVFormatContext *s,
                               AVPacket *pkt)
{
618
    IPMVEContext *ipmovie = s->priv_data;
619
    AVIOContext *pb = s->pb;
620 621 622 623 624 625
    int ret;

    ret = process_ipmovie_chunk(ipmovie, pb, pkt);
    if (ret == CHUNK_BAD)
        ret = AVERROR_INVALIDDATA;
    else if (ret == CHUNK_EOF)
626
        ret = AVERROR(EIO);
627
    else if (ret == CHUNK_NOMEM)
628
        ret = AVERROR(ENOMEM);
629
    else if (ret == CHUNK_VIDEO)
630
        ret = 0;
631 632
    else
        ret = -1;
633 634 635 636

    return ret;
}

637
AVInputFormat ff_ipmovie_demuxer = {
638
    .name           = "ipmovie",
639
    .long_name      = NULL_IF_CONFIG_SMALL("Interplay MVE"),
640 641 642 643
    .priv_data_size = sizeof(IPMVEContext),
    .read_probe     = ipmovie_probe,
    .read_header    = ipmovie_read_header,
    .read_packet    = ipmovie_read_packet,
644
};