Browse code

initial commit for Id RoQ and Interplay MVE multimedia subsystems

Originally committed as revision 2195 to svn://svn.ffmpeg.org/ffmpeg/trunk

Mike Melanson authored on 2003/09/02 13:32:02
Showing 11 changed files
... ...
@@ -17,7 +17,8 @@ OBJS= common.o utils.o mem.o allcodecs.o \
17 17
       mpeg12.o mpegaudiodec.o pcm.o simple_idct.o \
18 18
       ratecontrol.o adpcm.o eval.o dv.o error_resilience.o \
19 19
       fft.o mdct.o mace.o huffyuv.o cyuv.o opts.o raw.o h264.o golomb.o \
20
-      vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o
20
+      vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \
21
+      roqvideo.o dpcm.o interplayvideo.o
21 22
 
22 23
 ifeq ($(AMR_NB),yes)
23 24
 ifeq ($(AMR_NB_FIXED),yes)
... ...
@@ -121,11 +121,15 @@ void avcodec_register_all(void)
121 121
     register_avcodec(&cljr_decoder);
122 122
     register_avcodec(&fourxm_decoder);
123 123
     register_avcodec(&mdec_decoder);
124
+    register_avcodec(&roq_decoder);
125
+    register_avcodec(&interplay_video_decoder);
124 126
 #ifdef CONFIG_AC3
125 127
     register_avcodec(&ac3_decoder);
126 128
 #endif
127 129
     register_avcodec(&ra_144_decoder);
128 130
     register_avcodec(&ra_288_decoder);
131
+    register_avcodec(&roq_dpcm_decoder);
132
+    register_avcodec(&interplay_dpcm_decoder);
129 133
 #endif /* CONFIG_DECODERS */
130 134
 
131 135
 #ifdef AMR_NB
... ...
@@ -66,6 +66,8 @@ enum CodecID {
66 66
     CODEC_ID_VCR1,
67 67
     CODEC_ID_CLJR,
68 68
     CODEC_ID_MDEC,
69
+    CODEC_ID_ROQ,
70
+    CODEC_ID_INTERPLAY_VIDEO,
69 71
 
70 72
     /* various pcm "codecs" */
71 73
     CODEC_ID_PCM_S16LE,
... ...
@@ -88,6 +90,10 @@ enum CodecID {
88 88
     /* RealAudio codecs*/
89 89
     CODEC_ID_RA_144,
90 90
     CODEC_ID_RA_288,
91
+
92
+    /* various DPCM codecs */
93
+    CODEC_ID_ROQ_DPCM,
94
+    CODEC_ID_INTERPLAY_DPCM,
91 95
 };
92 96
 
93 97
 enum CodecType {
... ...
@@ -1347,8 +1353,12 @@ extern AVCodec cljr_decoder;
1347 1347
 extern AVCodec ffv1_decoder;
1348 1348
 extern AVCodec fourxm_decoder;
1349 1349
 extern AVCodec mdec_decoder;
1350
+extern AVCodec roq_decoder;
1351
+extern AVCodec interplay_video_decoder;
1350 1352
 extern AVCodec ra_144_decoder;
1351 1353
 extern AVCodec ra_288_decoder;
1354
+extern AVCodec roq_dpcm_decoder;
1355
+extern AVCodec interplay_dpcm_decoder;
1352 1356
 
1353 1357
 /* pcm codecs */
1354 1358
 #define PCM_CODEC(id, name) \
1355 1359
new file mode 100644
... ...
@@ -0,0 +1,200 @@
0
+/*
1
+ * Assorted DPCM codecs
2
+ * Copyright (c) 2003 The ffmpeg Project.
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ */
18
+
19
+/**
20
+ * @file: dpcm.c
21
+ * Assorted DPCM (differential pulse code modulation) audio codecs
22
+ * by Mike Melanson (melanson@pcisys.net)
23
+ * for more information on the specific data formats, visit:
24
+ *   http://www.pcisys.net/~melanson/codecs/simpleaudio.html
25
+ */
26
+
27
+#include "avcodec.h"
28
+
29
+typedef struct DPCMContext {
30
+    int channels;
31
+    short roq_square_array[256];
32
+    int last_delta[2];
33
+} DPCMContext;
34
+
35
+#define SATURATE_S16(x)  if (x < -32768) x = -32768; \
36
+  else if (x > 32767) x = 32767;
37
+#define SE_16BIT(x)  if (x & 0x8000) x -= 0x10000;
38
+#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
39
+#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
40
+                   (((uint8_t*)(x))[2] << 16) | \
41
+                   (((uint8_t*)(x))[1] << 8) | \
42
+                    ((uint8_t*)(x))[0])
43
+
44
+static int interplay_delta_table[] = {
45
+         0,      1,      2,      3,      4,      5,      6,      7,
46
+         8,      9,     10,     11,     12,     13,     14,     15,
47
+        16,     17,     18,     19,     20,     21,     22,     23,
48
+        24,     25,     26,     27,     28,     29,     30,     31,
49
+        32,     33,     34,     35,     36,     37,     38,     39,
50
+        40,     41,     42,     43,     47,     51,     56,     61,
51
+        66,     72,     79,     86,     94,    102,    112,    122,
52
+       133,    145,    158,    173,    189,    206,    225,    245,
53
+       267,    292,    318,    348,    379,    414,    452,    493,
54
+       538,    587,    640,    699,    763,    832,    908,    991,
55
+      1081,   1180,   1288,   1405,   1534,   1673,   1826,   1993,
56
+      2175,   2373,   2590,   2826,   3084,   3365,   3672,   4008,
57
+      4373,   4772,   5208,   5683,   6202,   6767,   7385,   8059,
58
+      8794,   9597,  10472,  11428,  12471,  13609,  14851,  16206,
59
+     17685,  19298,  21060,  22981,  25078,  27367,  29864,  32589,
60
+    -29973, -26728, -23186, -19322, -15105, -10503,  -5481,     -1,
61
+         1,      1,   5481,  10503,  15105,  19322,  23186,  26728,
62
+     29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298,
63
+    -17685, -16206, -14851, -13609, -12471, -11428, -10472,  -9597,
64
+     -8794,  -8059,  -7385,  -6767,  -6202,  -5683,  -5208,  -4772,
65
+     -4373,  -4008,  -3672,  -3365,  -3084,  -2826,  -2590,  -2373,
66
+     -2175,  -1993,  -1826,  -1673,  -1534,  -1405,  -1288,  -1180,
67
+     -1081,   -991,   -908,   -832,   -763,   -699,   -640,   -587,
68
+      -538,   -493,   -452,   -414,   -379,   -348,   -318,   -292,
69
+      -267,   -245,   -225,   -206,   -189,   -173,   -158,   -145,
70
+      -133,   -122,   -112,   -102,    -94,    -86,    -79,    -72,
71
+       -66,    -61,    -56,    -51,    -47,    -43,    -42,    -41,
72
+       -40,    -39,    -38,    -37,    -36,    -35,    -34,    -33,
73
+       -32,    -31,    -30,    -29,    -28,    -27,    -26,    -25,
74
+       -24,    -23,    -22,    -21,    -20,    -19,    -18,    -17,
75
+       -16,    -15,    -14,    -13,    -12,    -11,    -10,     -9,
76
+        -8,     -7,     -6,     -5,     -4,     -3,     -2,     -1
77
+
78
+};
79
+
80
+static int dpcm_decode_init(AVCodecContext *avctx)
81
+{
82
+    DPCMContext *s = avctx->priv_data;
83
+    int i;
84
+    short square;
85
+
86
+    s->channels = avctx->channels;
87
+
88
+    switch(avctx->codec->id) {
89
+
90
+    case CODEC_ID_ROQ_DPCM:
91
+        /* initialize square table */
92
+        for (i = 0; i < 128; i++) {
93
+            square = i * i;
94
+            s->roq_square_array[i] = square;
95
+            s->roq_square_array[i + 128] = -square;
96
+        }
97
+        break;
98
+
99
+    default:
100
+        break;
101
+    }
102
+
103
+    return 0;
104
+}
105
+
106
+static int dpcm_decode_frame(AVCodecContext *avctx,
107
+                             void *data, int *data_size,
108
+                             uint8_t *buf, int buf_size)
109
+{
110
+    DPCMContext *s = avctx->priv_data;
111
+    int in, out = 0;
112
+    int i;
113
+    int predictor[2];
114
+    int channel_number = 0;
115
+    short *output_samples = data;
116
+    int sequence_number;
117
+
118
+    switch(avctx->codec->id) {
119
+
120
+    case CODEC_ID_ROQ_DPCM:
121
+        if (s->channels == 1)
122
+            predictor[0] = LE_16(&buf[6]);
123
+        else {
124
+            predictor[0] = buf[7] << 8;
125
+            predictor[1] = buf[6] << 8;
126
+        }
127
+        SE_16BIT(predictor[0]);
128
+        SE_16BIT(predictor[1]);
129
+
130
+        /* decode the samples */
131
+        for (in = 8, out = 0; in < buf_size; in++, out++) {
132
+            predictor[channel_number] += s->roq_square_array[buf[in]];
133
+            SATURATE_S16(predictor[channel_number]);
134
+            output_samples[out] = predictor[channel_number];
135
+
136
+            /* toggle channel */
137
+            channel_number ^= s->channels - 1;
138
+        }
139
+        break;
140
+
141
+    case CODEC_ID_INTERPLAY_DPCM:
142
+        in = 0;
143
+        sequence_number = LE_16(&buf[in]);
144
+        in += 6;  /* skip over the stream mask and stream length */
145
+        if (sequence_number == 1) {
146
+            predictor[0] = LE_16(&buf[in]);
147
+            in += 2;
148
+            SE_16BIT(predictor[0])
149
+            if (s->channels == 2) {
150
+                predictor[1] = LE_16(&buf[in]);
151
+                SE_16BIT(predictor[1])
152
+                in += 2;
153
+            }
154
+        } else {
155
+            for (i = 0; i < s->channels; i++)
156
+                predictor[i] = s->last_delta[i];
157
+        }
158
+
159
+        while (in < buf_size) {
160
+            predictor[channel_number] += interplay_delta_table[buf[in++]];
161
+            SATURATE_S16(predictor[channel_number]);
162
+            output_samples[out++] = predictor[channel_number];
163
+
164
+            /* toggle channel */
165
+            channel_number ^= s->channels - 1;
166
+        }
167
+
168
+        /* save predictors for next round */
169
+        for (i = 0; i < s->channels; i++)
170
+            s->last_delta[i] = predictor[i];
171
+
172
+        break;
173
+    }
174
+
175
+    *data_size = out * sizeof(short);
176
+    return buf_size;
177
+}
178
+
179
+AVCodec roq_dpcm_decoder = {
180
+    "roq_dpcm",
181
+    CODEC_TYPE_AUDIO,
182
+    CODEC_ID_ROQ_DPCM,
183
+    sizeof(DPCMContext),
184
+    dpcm_decode_init,
185
+    NULL,
186
+    NULL,
187
+    dpcm_decode_frame,
188
+};
189
+
190
+AVCodec interplay_dpcm_decoder = {
191
+    "interplay_dpcm",
192
+    CODEC_TYPE_AUDIO,
193
+    CODEC_ID_INTERPLAY_DPCM,
194
+    sizeof(DPCMContext),
195
+    dpcm_decode_init,
196
+    NULL,
197
+    NULL,
198
+    dpcm_decode_frame,
199
+};
0 200
new file mode 100644
... ...
@@ -0,0 +1,145 @@
0
+/*
1
+ * Interplay MVE Video Decoder
2
+ * Copyright (C) 2003 the ffmpeg project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ *
18
+ */
19
+
20
+/**
21
+ * @file roqvideo.c
22
+ * Interplay MVE Video Decoder by Mike Melanson
23
+ * For more information about the Interplay MVE format, visit:
24
+ *   http://www.pcisys.net/~melanson/codecs/
25
+ */
26
+
27
+#include <stdio.h>
28
+#include <stdlib.h>
29
+#include <string.h>
30
+#include <unistd.h>
31
+
32
+#include "common.h"
33
+#include "avcodec.h"
34
+#include "dsputil.h"
35
+
36
+typedef struct IpvideoContext {
37
+
38
+    AVCodecContext *avctx;
39
+    DSPContext dsp;
40
+    AVFrame last_frame;
41
+    AVFrame current_frame;
42
+    int first_frame;
43
+    int receiving_decoding_map;
44
+    unsigned char *decoding_map;
45
+    int decoding_map_size;
46
+
47
+    unsigned char *buf;
48
+    int size;
49
+
50
+} IpvideoContext;
51
+
52
+static int ipvideo_decode_init(AVCodecContext *avctx)
53
+{
54
+    IpvideoContext *s = avctx->priv_data;
55
+
56
+    s->avctx = avctx;
57
+    avctx->pix_fmt = PIX_FMT_YUV444P;
58
+    avctx->has_b_frames = 0;
59
+    dsputil_init(&s->dsp, avctx);
60
+
61
+    s->first_frame = 1;
62
+    s->receiving_decoding_map = 1;  /* decoding map will be received first */
63
+
64
+    /* decoding map contains 4 bits of information per 8x8 block */
65
+    s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2);
66
+    s->decoding_map = av_malloc(s->decoding_map_size);
67
+
68
+    return 0;
69
+}
70
+
71
+static int ipvideo_decode_frame(AVCodecContext *avctx,
72
+                                void *data, int *data_size,
73
+                                uint8_t *buf, int buf_size)
74
+{
75
+    IpvideoContext *s = avctx->priv_data;
76
+
77
+    if (s->receiving_decoding_map) {
78
+        /* receiving the decoding map on this iteration */
79
+        s->receiving_decoding_map = 0;
80
+
81
+        if (buf_size != s->decoding_map_size)
82
+            printf (" Interplay video: buf_size != decoding_map_size (%d != %d)\n",
83
+                buf_size, s->decoding_map_size);
84
+        else
85
+            memcpy(s->decoding_map, buf, buf_size);
86
+
87
+        *data_size = 0;
88
+        *(AVFrame*)data = s->last_frame;
89
+    } else {
90
+        /* receiving the compressed video data on this iteration */
91
+        s->receiving_decoding_map = 1;
92
+        s->buf = buf;
93
+        s->size = buf_size;
94
+
95
+        if (avctx->get_buffer(avctx, &s->current_frame)) {
96
+            printf ("  Interplay Video: get_buffer() failed\n");
97
+            return -1;
98
+        }
99
+
100
+//        ipvideo_decode_frame(s);
101
+memset(s->current_frame.data[0], 0x80, s->current_frame.linesize[0] * avctx->height);
102
+memset(s->current_frame.data[1], 0x80, s->current_frame.linesize[1] * avctx->height / 4);
103
+memset(s->current_frame.data[2], 0x80, s->current_frame.linesize[2] * avctx->height / 4);
104
+
105
+        /* release the last frame if it is allocated */
106
+        if (s->first_frame)
107
+            s->first_frame = 0;
108
+        else
109
+            avctx->release_buffer(avctx, &s->last_frame);
110
+
111
+        /* shuffle frames */
112
+        s->last_frame = s->current_frame;
113
+
114
+        *data_size = sizeof(AVFrame);
115
+        *(AVFrame*)data = s->current_frame;
116
+    }
117
+
118
+    /* always report that the buffer was completely consumed */
119
+    return buf_size;
120
+}
121
+
122
+static int ipvideo_decode_end(AVCodecContext *avctx)
123
+{
124
+    IpvideoContext *s = avctx->priv_data;
125
+
126
+    /* release the last frame */
127
+    avctx->release_buffer(avctx, &s->last_frame);
128
+
129
+    av_free(s->decoding_map);
130
+
131
+    return 0;
132
+}
133
+
134
+AVCodec interplay_video_decoder = {
135
+    "interplayvideo",
136
+    CODEC_TYPE_VIDEO,
137
+    CODEC_ID_INTERPLAY_VIDEO,
138
+    sizeof(IpvideoContext),
139
+    ipvideo_decode_init,
140
+    NULL,
141
+    ipvideo_decode_end,
142
+    ipvideo_decode_frame,
143
+    CODEC_CAP_DR1,
144
+};
0 145
new file mode 100644
... ...
@@ -0,0 +1,406 @@
0
+/*
1
+ * Copyright (C) 2003 the ffmpeg project
2
+ *
3
+ * This library is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2 of the License, or (at your option) any later version.
7
+ *
8
+ * This library is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with this library; if not, write to the Free Software
15
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
+ *
17
+ */
18
+
19
+/**
20
+ * @file roqvideo.c
21
+ * Id RoQ Video Decoder by Dr. Tim Ferguson
22
+ * For more information about the Id RoQ format, visit:
23
+ *   http://www.csse.monash.edu.au/~timf/
24
+ */
25
+
26
+#include <stdio.h>
27
+#include <stdlib.h>
28
+#include <string.h>
29
+#include <unistd.h>
30
+
31
+#include "common.h"
32
+#include "avcodec.h"
33
+#include "dsputil.h"
34
+
35
+typedef struct {
36
+  unsigned char y0, y1, y2, y3, u, v;
37
+} roq_cell;
38
+
39
+typedef struct {
40
+  int idx[4];
41
+} roq_qcell;
42
+
43
+
44
+typedef struct RoqContext {
45
+
46
+    AVCodecContext *avctx;
47
+    DSPContext dsp;
48
+    AVFrame last_frame;
49
+    AVFrame current_frame;
50
+    int first_frame;
51
+    int y_stride;
52
+    int c_stride;
53
+
54
+    roq_cell cells[256];
55
+    roq_qcell qcells[256];
56
+
57
+    unsigned char *buf;
58
+    int size;
59
+
60
+} RoqContext;
61
+
62
+#define RoQ_INFO              0x1001
63
+#define RoQ_QUAD_CODEBOOK     0x1002
64
+#define RoQ_QUAD_VQ           0x1011
65
+#define RoQ_SOUND_MONO        0x1020
66
+#define RoQ_SOUND_STEREO      0x1021
67
+
68
+#define RoQ_ID_MOT              0x00
69
+#define RoQ_ID_FCC              0x01
70
+#define RoQ_ID_SLD              0x02
71
+#define RoQ_ID_CCC              0x03
72
+
73
+#define get_byte(in_buffer) *(in_buffer++)
74
+#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
75
+  (in_buffer[-1] << 8 | in_buffer[-2])))
76
+#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
77
+  (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
78
+
79
+
80
+static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
81
+{
82
+    unsigned char *yptr;
83
+
84
+    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
85
+    *yptr++ = cell->y0;
86
+    *yptr++ = cell->y1;
87
+    yptr += (ri->y_stride - 2);
88
+    *yptr++ = cell->y2;
89
+    *yptr++ = cell->y3;
90
+    ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
91
+    ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
92
+}
93
+
94
+static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
95
+{
96
+    unsigned long row_inc, c_row_inc;
97
+    register unsigned char y0, y1, u, v;
98
+    unsigned char *yptr, *uptr, *vptr;
99
+
100
+    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
101
+    uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
102
+    vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
103
+
104
+    row_inc = ri->y_stride - 4;
105
+    c_row_inc = (ri->c_stride) - 2;
106
+    *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
107
+    *yptr++ = y0;
108
+    *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
109
+    *yptr++ = y1;
110
+
111
+    yptr += row_inc;
112
+
113
+    *yptr++ = y0;
114
+    *yptr++ = y0;
115
+    *yptr++ = y1;
116
+    *yptr++ = y1;
117
+
118
+    yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
119
+
120
+    *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
121
+    *yptr++ = y0;
122
+    *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
123
+    *yptr++ = y1;
124
+
125
+    yptr += row_inc;
126
+
127
+    *yptr++ = y0;
128
+    *yptr++ = y0;
129
+    *yptr++ = y1;
130
+    *yptr++ = y1;
131
+}
132
+
133
+static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
134
+    char mean_x, char mean_y)
135
+{
136
+    int i, mx, my;
137
+    unsigned char *pa, *pb;
138
+
139
+    mx = x + 8 - (mv >> 4) - mean_x;
140
+    my = y + 8 - (mv & 0xf) - mean_y;
141
+
142
+    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
143
+    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
144
+    for(i = 0; i < 4; i++) {
145
+        pa[0] = pb[0];
146
+        pa[1] = pb[1];
147
+        pa[2] = pb[2];
148
+        pa[3] = pb[3];
149
+        pa += ri->y_stride;
150
+        pb += ri->y_stride;
151
+    }
152
+
153
+    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
154
+    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
155
+    for(i = 0; i < 2; i++) {
156
+        pa[0] = pb[0];
157
+        pa[1] = pb[1];
158
+        pa += ri->c_stride;
159
+        pb += ri->c_stride;
160
+    }
161
+
162
+    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
163
+    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
164
+    for(i = 0; i < 2; i++) {
165
+        pa[0] = pb[0];
166
+        pa[1] = pb[1];
167
+        pa += ri->c_stride;
168
+        pb += ri->c_stride;
169
+    }
170
+}
171
+
172
+static void apply_motion_8x8(RoqContext *ri, int x, int y,
173
+    unsigned char mv, char mean_x, char mean_y)
174
+{
175
+    int mx, my, i;
176
+    unsigned char *pa, *pb;
177
+
178
+    mx = x + 8 - (mv >> 4) - mean_x;
179
+    my = y + 8 - (mv & 0xf) - mean_y;
180
+
181
+    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
182
+    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
183
+    for(i = 0; i < 8; i++) {
184
+        pa[0] = pb[0];
185
+        pa[1] = pb[1];
186
+        pa[2] = pb[2];
187
+        pa[3] = pb[3];
188
+        pa[4] = pb[4];
189
+        pa[5] = pb[5];
190
+        pa[6] = pb[6];
191
+        pa[7] = pb[7];
192
+        pa += ri->y_stride;
193
+        pb += ri->y_stride;
194
+    }
195
+
196
+    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
197
+    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
198
+    for(i = 0; i < 4; i++) {
199
+        pa[0] = pb[0];
200
+        pa[1] = pb[1];
201
+        pa[2] = pb[2];
202
+        pa[3] = pb[3];
203
+        pa += ri->c_stride;
204
+        pb += ri->c_stride;
205
+    }
206
+
207
+    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
208
+    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
209
+    for(i = 0; i < 4; i++) {
210
+        pa[0] = pb[0];
211
+        pa[1] = pb[1];
212
+        pa[2] = pb[2];
213
+        pa[3] = pb[3];
214
+        pa += ri->c_stride;
215
+        pb += ri->c_stride;
216
+    }
217
+}
218
+
219
+static void roqvideo_decode_frame(RoqContext *ri)
220
+{
221
+    unsigned int chunk_id = 0, chunk_arg = 0;
222
+    unsigned long chunk_size = 0;
223
+    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
224
+    int vqid, bpos, xpos, ypos, xp, yp, x, y;
225
+    int frame_stats[2][4] = {{0},{0}};
226
+    roq_qcell *qcell;
227
+    unsigned char *buf = ri->buf;
228
+    unsigned char *buf_end = ri->buf + ri->size;
229
+
230
+    while (buf < buf_end) {
231
+        chunk_id = get_word(buf);
232
+        chunk_size = get_long(buf);
233
+        chunk_arg = get_word(buf);
234
+
235
+        if(chunk_id == RoQ_QUAD_VQ)
236
+            break;
237
+        if(chunk_id == RoQ_QUAD_CODEBOOK) {
238
+            if((nv1 = chunk_arg >> 8) == 0)
239
+                nv1 = 256;
240
+            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
241
+                nv2 = 256;
242
+            for(i = 0; i < nv1; i++) {
243
+                ri->cells[i].y0 = get_byte(buf);
244
+                ri->cells[i].y1 = get_byte(buf);
245
+                ri->cells[i].y2 = get_byte(buf);
246
+                ri->cells[i].y3 = get_byte(buf);
247
+                ri->cells[i].u = get_byte(buf);
248
+                ri->cells[i].v = get_byte(buf);
249
+            }
250
+            for(i = 0; i < nv2; i++)
251
+                for(j = 0; j < 4; j++)
252
+                    ri->qcells[i].idx[j] = get_byte(buf);
253
+        }
254
+    }
255
+
256
+    bpos = xpos = ypos = 0;
257
+    while(bpos < chunk_size) {
258
+        for (yp = ypos; yp < ypos + 16; yp += 8)
259
+            for (xp = xpos; xp < xpos + 16; xp += 8) {
260
+                if (vqflg_pos < 0) {
261
+                    vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
262
+                    vqflg_pos = 7;
263
+                }
264
+                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
265
+                frame_stats[0][vqid]++;
266
+                vqflg_pos--;
267
+
268
+                switch(vqid) {
269
+                case RoQ_ID_MOT:
270
+                    apply_motion_8x8(ri, xp, yp, 0, 8, 8);
271
+                    break;
272
+                case RoQ_ID_FCC:
273
+                    apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
274
+                        chunk_arg & 0xff);
275
+                    break;
276
+                case RoQ_ID_SLD:
277
+                    qcell = ri->qcells + buf[bpos++];
278
+                    apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
279
+                    apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
280
+                    apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
281
+                    apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
282
+                    break;
283
+                case RoQ_ID_CCC:
284
+                    for (k = 0; k < 4; k++) {
285
+                        x = xp; y = yp;
286
+                        if(k & 0x01) x += 4;
287
+                        if(k & 0x02) y += 4;
288
+
289
+                        if (vqflg_pos < 0) {
290
+                            vqflg = buf[bpos++];
291
+                            vqflg |= (buf[bpos++] << 8);
292
+                            vqflg_pos = 7;
293
+                        }
294
+                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
295
+                        frame_stats[1][vqid]++;
296
+                        vqflg_pos--;
297
+                        switch(vqid) {
298
+                        case RoQ_ID_MOT:
299
+                            apply_motion_4x4(ri, x, y, 0, 8, 8);
300
+                            break;
301
+                        case RoQ_ID_FCC:
302
+                            apply_motion_4x4(ri, x, y, buf[bpos++], 
303
+                                chunk_arg >> 8, chunk_arg & 0xff);
304
+                            break;
305
+                        case RoQ_ID_SLD:
306
+                            qcell = ri->qcells + buf[bpos++];
307
+                            apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
308
+                            apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
309
+                            apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
310
+                            apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
311
+                            break;
312
+                        case RoQ_ID_CCC:
313
+                            apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
314
+                            apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
315
+                            apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
316
+                            apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
317
+                            bpos += 4;
318
+                            break;
319
+                        }
320
+                    }
321
+                    break;
322
+                default:
323
+                    printf("Unknown vq code: %d\n", vqid);
324
+            }
325
+        }
326
+
327
+        xpos += 16;
328
+        if (xpos >= ri->avctx->width) {
329
+            xpos -= ri->avctx->width;
330
+            ypos += 16;
331
+        }
332
+        if(ypos >= ri->avctx->height)
333
+            break;
334
+    }
335
+}
336
+
337
+
338
+static int roq_decode_init(AVCodecContext *avctx)
339
+{
340
+    RoqContext *s = avctx->priv_data;
341
+
342
+    s->avctx = avctx;
343
+    s->first_frame = 1;
344
+    avctx->pix_fmt = PIX_FMT_YUV420P;
345
+    avctx->has_b_frames = 0;
346
+    dsputil_init(&s->dsp, avctx);
347
+
348
+    return 0;
349
+}
350
+
351
+static int roq_decode_frame(AVCodecContext *avctx,
352
+                            void *data, int *data_size,
353
+                            uint8_t *buf, int buf_size)
354
+{
355
+    RoqContext *s = avctx->priv_data;
356
+
357
+    *data_size = 0;
358
+
359
+    if (avctx->get_buffer(avctx, &s->current_frame)) {
360
+        printf ("  RoQ: get_buffer() failed\n");
361
+        return -1;
362
+    }
363
+    s->y_stride = s->current_frame.linesize[0];
364
+    s->c_stride = s->current_frame.linesize[1];
365
+
366
+    s->buf = buf;
367
+    s->size = buf_size;
368
+    roqvideo_decode_frame(s);
369
+
370
+    /* release the last frame if it is allocated */
371
+    if (s->first_frame)
372
+        s->first_frame = 0;
373
+    else
374
+        avctx->release_buffer(avctx, &s->last_frame);
375
+
376
+    /* shuffle frames */
377
+    s->last_frame = s->current_frame;
378
+
379
+    *data_size = sizeof(AVFrame);
380
+    *(AVFrame*)data = s->current_frame;
381
+
382
+    return buf_size;
383
+}
384
+
385
+static int roq_decode_end(AVCodecContext *avctx)
386
+{
387
+    RoqContext *s = avctx->priv_data;
388
+
389
+    /* release the last frame */
390
+    avctx->release_buffer(avctx, &s->last_frame);
391
+
392
+    return 0;
393
+}
394
+
395
+AVCodec roq_decoder = {
396
+    "roqvideo",
397
+    CODEC_TYPE_VIDEO,
398
+    CODEC_ID_ROQ,
399
+    sizeof(RoqContext),
400
+    roq_decode_init,
401
+    NULL,
402
+    roq_decode_end,
403
+    roq_decode_frame,
404
+    CODEC_CAP_DR1,
405
+};
... ...
@@ -14,7 +14,7 @@ PPOBJS=
14 14
 # mux and demuxes
15 15
 OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o raw.o rm.o \
16 16
       avienc.o avidec.o wav.o swf.o au.o gif.o mov.o mpjpeg.o dvcore.o dv.o \
17
-      yuv4mpeg.o 4xm.o flvenc.o flvdec.o movenc.o psxstr.o
17
+      yuv4mpeg.o 4xm.o flvenc.o flvdec.o movenc.o psxstr.o idroq.o ipmovie.o
18 18
 
19 19
 ifeq ($(CONFIG_RISKY),yes)
20 20
 OBJS+= asf.o
... ...
@@ -52,6 +52,8 @@ void av_register_all(void)
52 52
     flvenc_init();
53 53
     flvdec_init();
54 54
     str_init();
55
+    roq_init();
56
+    ipmovie_init();
55 57
 
56 58
 #ifdef AMR_NB
57 59
     amr_init();
... ...
@@ -383,6 +383,12 @@ int fourxm_init(void);
383 383
 /* psxstr.c */
384 384
 int str_init(void);
385 385
 
386
+/* idroq.c */
387
+int roq_init(void);
388
+
389
+/* ipmovie.c */
390
+int ipmovie_init(void);
391
+
386 392
 #include "rtp.h"
387 393
 
388 394
 #include "rtsp.h"
389 395
new file mode 100644
... ...
@@ -0,0 +1,299 @@
0
+/*
1
+ * Id RoQ (.roq) File Demuxer
2
+ * Copyright (c) 2003 The ffmpeg Project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ */
18
+
19
+/**
20
+ * @file idroq.c
21
+ * Id RoQ format file demuxer
22
+ * by Mike Melanson (melanson@pcisys.net)
23
+ * for more information on the .roq file format, visit:
24
+ *   http://www.csse.monash.edu.au/~timf/
25
+ */
26
+
27
+#include "avformat.h"
28
+
29
+#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
30
+#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
31
+                   (((uint8_t*)(x))[2] << 16) | \
32
+                   (((uint8_t*)(x))[1] << 8) | \
33
+                    ((uint8_t*)(x))[0])
34
+
35
+#define RoQ_MAGIC_NUMBER 0x1084
36
+#define RoQ_CHUNK_PREAMBLE_SIZE 8
37
+#define RoQ_AUDIO_SAMPLE_RATE 22050
38
+#define RoQ_CHUNKS_TO_SCAN 30
39
+
40
+#define RoQ_INFO           0x1001
41
+#define RoQ_QUAD_CODEBOOK  0x1002
42
+#define RoQ_QUAD_VQ        0x1011
43
+#define RoQ_SOUND_MONO     0x1020
44
+#define RoQ_SOUND_STEREO   0x1021
45
+
46
+typedef struct RoqDemuxContext {
47
+
48
+    int width;
49
+    int height;
50
+    int audio_channels;
51
+    int framerate;
52
+    int frame_pts_inc;
53
+
54
+    int video_stream_index;
55
+    int audio_stream_index;
56
+
57
+    int64_t video_pts;
58
+    unsigned int audio_frame_count;
59
+
60
+} RoqDemuxContext;
61
+
62
+static int roq_probe(AVProbeData *p)
63
+{
64
+    if ((LE_16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
65
+        (LE_32(&p->buf[2]) != 0xFFFFFFFF))
66
+        return 0;
67
+
68
+    return AVPROBE_SCORE_MAX;
69
+}
70
+
71
+static int roq_read_header(AVFormatContext *s,
72
+                           AVFormatParameters *ap)
73
+{
74
+    RoqDemuxContext *roq = s->priv_data;
75
+    ByteIOContext *pb = &s->pb;
76
+    AVStream *st;
77
+    unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
78
+    int i;
79
+    unsigned int chunk_size;
80
+    unsigned int chunk_type;
81
+
82
+    /* get the main header */
83
+    if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != 
84
+        RoQ_CHUNK_PREAMBLE_SIZE)
85
+        return AVERROR_IO;
86
+    roq->framerate = LE_16(&preamble[6]);
87
+    roq->frame_pts_inc = 90000 / roq->framerate;
88
+
89
+    /* set the pts reference (1 pts = 1/90000) */
90
+    s->pts_num = 1;
91
+    s->pts_den = 90000;
92
+
93
+    /* init private context parameters */
94
+    roq->width = roq->height = roq->audio_channels = roq->video_pts = 
95
+    roq->audio_frame_count = 0;
96
+
97
+    /* scan the first n chunks searching for A/V parameters */
98
+    for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
99
+        if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != 
100
+            RoQ_CHUNK_PREAMBLE_SIZE)
101
+            return AVERROR_IO;
102
+
103
+        chunk_type = LE_16(&preamble[0]);
104
+        chunk_size = LE_32(&preamble[2]);
105
+
106
+        switch (chunk_type) {
107
+
108
+        case RoQ_INFO:
109
+            /* fetch the width and height; reuse the preamble bytes */
110
+            if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != 
111
+                RoQ_CHUNK_PREAMBLE_SIZE)
112
+                return AVERROR_IO;
113
+            roq->width = LE_16(&preamble[0]);
114
+            roq->height = LE_16(&preamble[2]);
115
+            break;
116
+
117
+        case RoQ_QUAD_CODEBOOK:
118
+        case RoQ_QUAD_VQ:
119
+            /* ignore during this scan */
120
+            url_fseek(pb, chunk_size, SEEK_CUR);
121
+            break;
122
+
123
+        case RoQ_SOUND_MONO:
124
+            roq->audio_channels = 1;
125
+            url_fseek(pb, chunk_size, SEEK_CUR);
126
+            break;
127
+
128
+        case RoQ_SOUND_STEREO:
129
+            roq->audio_channels = 2;
130
+            url_fseek(pb, chunk_size, SEEK_CUR);
131
+            break;
132
+
133
+        default:
134
+            printf (" unknown RoQ chunk type (%04X)\n", LE_16(&preamble[0]));
135
+            return AVERROR_INVALIDDATA;
136
+            break;
137
+        }
138
+
139
+        /* if all necessary parameters have been gathered, exit early */
140
+        if ((roq->width && roq->height) && roq->audio_channels)
141
+            break;
142
+    }
143
+
144
+    /* seek back to the first chunk */
145
+    url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
146
+
147
+    /* initialize the decoders */
148
+    st = av_new_stream(s, 0);
149
+    if (!st)
150
+        return AVERROR_NOMEM;
151
+    roq->video_stream_index = st->index;
152
+    st->codec.codec_type = CODEC_TYPE_VIDEO;
153
+    st->codec.codec_id = CODEC_ID_ROQ;
154
+    st->codec.codec_tag = 0;  /* no fourcc */
155
+    st->codec.width = roq->width;
156
+    st->codec.height = roq->height;
157
+
158
+    if (roq->audio_channels) {
159
+        st = av_new_stream(s, 0);
160
+        if (!st)
161
+            return AVERROR_NOMEM;
162
+        roq->audio_stream_index = st->index;
163
+        st->codec.codec_type = CODEC_TYPE_AUDIO;
164
+        st->codec.codec_id = CODEC_ID_ROQ_DPCM;
165
+        st->codec.codec_tag = 0;  /* no tag */
166
+        st->codec.channels = roq->audio_channels;
167
+        st->codec.sample_rate = RoQ_AUDIO_SAMPLE_RATE;
168
+        st->codec.bits_per_sample = 16;
169
+        st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
170
+            st->codec.bits_per_sample;
171
+        st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
172
+    }
173
+printf (" video is %d x %d, audio is %d channels\n",
174
+  roq->width, roq->height, roq->audio_channels);
175
+
176
+    return 0;
177
+}
178
+
179
+static int roq_read_packet(AVFormatContext *s,
180
+                           AVPacket *pkt)
181
+{
182
+    RoqDemuxContext *roq = s->priv_data;
183
+    ByteIOContext *pb = &s->pb;
184
+    int ret = 0;
185
+    unsigned int chunk_size;
186
+    unsigned int chunk_type;
187
+    unsigned int codebook_size;
188
+    unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
189
+    int packet_read = 0;
190
+    offset_t codebook_offset;
191
+
192
+    while (!packet_read) {
193
+
194
+        if (url_feof(&s->pb))
195
+            return -EIO;
196
+
197
+        /* get the next chunk preamble */
198
+        if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) != 
199
+            RoQ_CHUNK_PREAMBLE_SIZE)
200
+            return -EIO;
201
+
202
+        chunk_type = LE_16(&preamble[0]);
203
+        chunk_size = LE_32(&preamble[2]);
204
+
205
+        switch (chunk_type) {
206
+
207
+        case RoQ_INFO:
208
+            /* don't care about this chunk anymore */
209
+            url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
210
+            break;
211
+
212
+        case RoQ_QUAD_CODEBOOK:
213
+            /* packet needs to contain both this codebook and next VQ chunk */
214
+            codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
215
+            codebook_size = chunk_size;
216
+            url_fseek(pb, codebook_size, SEEK_CUR);
217
+            if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != 
218
+                RoQ_CHUNK_PREAMBLE_SIZE)
219
+                return -EIO;
220
+            chunk_size = LE_32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 + 
221
+                codebook_size;
222
+
223
+            /* rewind */
224
+            url_fseek(pb, codebook_offset, SEEK_SET);
225
+
226
+            /* load up the packet */
227
+            if (av_new_packet(pkt, chunk_size))
228
+                return -EIO;
229
+            pkt->stream_index = roq->video_stream_index;
230
+            pkt->pts = roq->video_pts;
231
+            ret = get_buffer(pb, pkt->data, chunk_size);
232
+            if (ret != chunk_size)
233
+                ret = -EIO;
234
+
235
+            roq->video_pts += roq->frame_pts_inc;
236
+            packet_read = 1;
237
+            break;
238
+
239
+        case RoQ_SOUND_MONO:
240
+        case RoQ_SOUND_STEREO:
241
+        case RoQ_QUAD_VQ:
242
+            /* load up the packet */
243
+            if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
244
+                return -EIO;
245
+            /* copy over preamble */
246
+            memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
247
+
248
+            if (chunk_type == RoQ_QUAD_VQ) {
249
+                pkt->stream_index = roq->video_stream_index;
250
+                pkt->pts = roq->video_pts;
251
+                roq->video_pts += roq->frame_pts_inc;
252
+            } else {
253
+                pkt->stream_index = roq->audio_stream_index;
254
+                pkt->pts = roq->audio_frame_count;
255
+                pkt->pts *= 90000;
256
+                pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
257
+                roq->audio_frame_count += (chunk_size / roq->audio_channels);
258
+            }
259
+
260
+            ret = get_buffer(pb, pkt->data, chunk_size);
261
+            if (ret != chunk_size)
262
+                ret = -EIO;
263
+
264
+            packet_read = 1;
265
+            break;
266
+
267
+        default:
268
+            printf ("  unknown RoQ chunk (%04X)\n", chunk_type);
269
+            return AVERROR_INVALIDDATA;
270
+            break;
271
+        }
272
+    }
273
+
274
+    return ret;
275
+}
276
+
277
+static int roq_read_close(AVFormatContext *s)
278
+{
279
+//    RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
280
+
281
+    return 0;
282
+}
283
+
284
+static AVInputFormat roq_iformat = {
285
+    "RoQ",
286
+    "Id RoQ format",
287
+    sizeof(RoqDemuxContext),
288
+    roq_probe,
289
+    roq_read_header,
290
+    roq_read_packet,
291
+    roq_read_close,
292
+};
293
+
294
+int roq_init(void)
295
+{
296
+    av_register_input_format(&roq_iformat);
297
+    return 0;
298
+}
0 299
new file mode 100644
... ...
@@ -0,0 +1,618 @@
0
+/*
1
+ * Interplay MVE File Demuxer
2
+ * Copyright (c) 2003 The ffmpeg Project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ */
18
+
19
+/**
20
+ * @file ipmovie.c
21
+ * Interplay MVE file demuxer
22
+ * by Mike Melanson (melanson@pcisys.net)
23
+ * For more information regarding the Interplay MVE file format, visit:
24
+ *   http://www.pcisys.net/~melanson/codecs/
25
+ * The aforementioned site also contains a command line utility for parsing
26
+ * IP MVE files so that you can get a good idea of the typical structure of
27
+ * such files. This demuxer is not the best example to use if you are trying
28
+ * to write your own as it uses a rather roundabout approach for splitting
29
+ * up and sending out the chunks.
30
+ */
31
+
32
+#include "avformat.h"
33
+
34
+/* debugging support: #define DEBUG_IPMOVIE as non-zero to see extremely
35
+ * verbose information about the demux process */
36
+#define DEBUG_IPMOVIE 0
37
+
38
+#if DEBUG_IPMOVIE
39
+#define debug_ipmovie printf
40
+#else
41
+static inline void debug_ipmovie(const char *format, ...) { }
42
+#endif
43
+
44
+
45
+#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
46
+#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
47
+                   (((uint8_t*)(x))[2] << 16) | \
48
+                   (((uint8_t*)(x))[1] << 8) | \
49
+                    ((uint8_t*)(x))[0])
50
+
51
+#define IPMOVIE_SIGNATURE "Interplay MVE File\x1A\0"
52
+#define IPMOVIE_SIGNATURE_SIZE 20
53
+#define CHUNK_PREAMBLE_SIZE 4
54
+#define OPCODE_PREAMBLE_SIZE 4
55
+
56
+#define CHUNK_INIT_AUDIO   0x0000
57
+#define CHUNK_AUDIO_ONLY   0x0001
58
+#define CHUNK_INIT_VIDEO   0x0002
59
+#define CHUNK_VIDEO        0x0003
60
+#define CHUNK_SHUTDOWN     0x0004
61
+#define CHUNK_END          0x0005
62
+/* these last types are used internally */
63
+#define CHUNK_DONE         0xFFFC
64
+#define CHUNK_NOMEM        0xFFFD
65
+#define CHUNK_EOF          0xFFFE
66
+#define CHUNK_BAD          0xFFFF
67
+
68
+#define OPCODE_END_OF_STREAM           0x00
69
+#define OPCODE_END_OF_CHUNK            0x01
70
+#define OPCODE_CREATE_TIMER            0x02
71
+#define OPCODE_INIT_AUDIO_BUFFERS      0x03
72
+#define OPCODE_START_STOP_AUDIO        0x04
73
+#define OPCODE_INIT_VIDEO_BUFFERS      0x05
74
+#define OPCODE_UNKNOWN_06              0x06
75
+#define OPCODE_SEND_BUFFER             0x07
76
+#define OPCODE_AUDIO_FRAME             0x08
77
+#define OPCODE_SILENCE_FRAME           0x09
78
+#define OPCODE_INIT_VIDEO_MODE         0x0A
79
+#define OPCODE_CREATE_GRADIENT         0x0B
80
+#define OPCODE_SET_PALETTE             0x0C
81
+#define OPCODE_SET_PALETTE_COMPRESSED  0x0D
82
+#define OPCODE_UNKNOWN_0E              0x0E
83
+#define OPCODE_SET_DECODING_MAP        0x0F
84
+#define OPCODE_UNKNOWN_10              0x10
85
+#define OPCODE_VIDEO_DATA              0x11
86
+#define OPCODE_UNKNOWN_12              0x12
87
+#define OPCODE_UNKNOWN_13              0x13
88
+#define OPCODE_UNKNOWN_14              0x14
89
+#define OPCODE_UNKNOWN_15              0x15
90
+
91
+#define PALETTE_COUNT 256
92
+
93
+typedef struct IPMVEContext {
94
+
95
+    unsigned char *buf;
96
+    int buf_size;
97
+
98
+    int fps;
99
+    int frame_pts_inc;
100
+
101
+    unsigned int video_width;
102
+    unsigned int video_height;
103
+    int64_t video_pts;
104
+
105
+    unsigned int audio_bits;
106
+    unsigned int audio_channels;
107
+    unsigned int audio_sample_rate;
108
+    unsigned int audio_type;
109
+    unsigned int audio_frame_count;
110
+
111
+    int video_stream_index;
112
+    int audio_stream_index;
113
+
114
+    offset_t audio_chunk_offset;
115
+    int audio_chunk_size;
116
+    offset_t video_chunk_offset;
117
+    int video_chunk_size;
118
+    offset_t decode_map_chunk_offset;
119
+    int decode_map_chunk_size;
120
+
121
+    offset_t next_chunk_offset;
122
+
123
+} IPMVEContext;
124
+
125
+static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb, 
126
+    AVPacket *pkt) {
127
+
128
+    int chunk_type;
129
+    int64_t audio_pts = 0;
130
+
131
+    if (s->audio_chunk_offset) {
132
+
133
+        url_fseek(pb, s->audio_chunk_offset, SEEK_SET);
134
+        s->audio_chunk_offset = 0;
135
+
136
+        /* figure out the audio pts */
137
+        audio_pts = 90000;
138
+        audio_pts *= s->audio_frame_count;
139
+        audio_pts /= s->audio_sample_rate;
140
+
141
+        if (av_new_packet(pkt, s->audio_chunk_size))
142
+            return CHUNK_NOMEM;
143
+
144
+        pkt->stream_index = s->audio_stream_index;
145
+        pkt->pts = audio_pts;
146
+        if (get_buffer(pb, pkt->data, s->audio_chunk_size) != 
147
+            s->audio_chunk_size) {
148
+            av_free_packet(pkt);
149
+            return CHUNK_EOF;
150
+        }
151
+
152
+        /* audio frame maintenance */
153
+        if (s->audio_type != CODEC_ID_INTERPLAY_DPCM)
154
+            s->audio_frame_count +=
155
+            (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
156
+        else
157
+            s->audio_frame_count +=
158
+                (s->audio_chunk_size - 6) / s->audio_channels;
159
+
160
+        debug_ipmovie("sending audio frame with pts %lld (%d audio frames)\n",
161
+            audio_pts, s->audio_frame_count);
162
+
163
+        chunk_type = CHUNK_VIDEO;
164
+
165
+    } else if (s->decode_map_chunk_offset) {
166
+
167
+        url_fseek(pb, s->decode_map_chunk_offset, SEEK_SET);
168
+        s->decode_map_chunk_offset = 0;
169
+
170
+        if (av_new_packet(pkt, s->decode_map_chunk_size))
171
+            return CHUNK_NOMEM;
172
+
173
+        pkt->stream_index = s->video_stream_index;
174
+        pkt->pts = s->video_pts;
175
+        if (get_buffer(pb, pkt->data, s->decode_map_chunk_size) != 
176
+            s->decode_map_chunk_size) {
177
+            av_free_packet(pkt);
178
+            return CHUNK_EOF;
179
+        }
180
+
181
+        chunk_type = CHUNK_VIDEO;
182
+
183
+    } else if (s->video_chunk_offset) {
184
+
185
+        url_fseek(pb, s->video_chunk_offset, SEEK_SET);
186
+        s->video_chunk_offset = 0;
187
+
188
+        if (av_new_packet(pkt, s->video_chunk_size))
189
+            return CHUNK_NOMEM;
190
+
191
+        pkt->stream_index = s->video_stream_index;
192
+        pkt->pts = s->video_pts;
193
+        if (get_buffer(pb, pkt->data, s->video_chunk_size) != 
194
+            s->video_chunk_size) {
195
+            av_free_packet(pkt);
196
+            return CHUNK_EOF;
197
+        }
198
+
199
+        s->video_pts += s->frame_pts_inc;
200
+
201
+        chunk_type = CHUNK_VIDEO;
202
+
203
+    } else {
204
+
205
+        url_fseek(pb, s->next_chunk_offset, SEEK_SET);
206
+        chunk_type = CHUNK_DONE;
207
+
208
+    }
209
+
210
+    return chunk_type;
211
+}
212
+
213
+/* This function loads and processes a single chunk in an IP movie file.
214
+ * It returns the type of chunk that was processed. */
215
+static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, 
216
+    AVPacket *pkt)
217
+{
218
+    unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
219
+    int chunk_type;
220
+    int chunk_size;
221
+    unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
222
+    unsigned char opcode_type;
223
+    unsigned char opcode_version;
224
+    int opcode_size;
225
+    unsigned char scratch[1024];
226
+    int j;
227
+    int first_color, last_color;
228
+    int audio_flags;
229
+
230
+    /* see if there are any pending packets */
231
+    chunk_type = load_ipmovie_packet(s, pb, pkt);
232
+    if ((chunk_type == CHUNK_VIDEO) && (chunk_type != CHUNK_DONE))
233
+        return chunk_type;
234
+
235
+    /* read the next chunk, wherever the file happens to be pointing */
236
+    if (url_feof(pb))
237
+        return CHUNK_EOF;
238
+    if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
239
+        CHUNK_PREAMBLE_SIZE)
240
+        return CHUNK_BAD;
241
+    chunk_size = LE_16(&chunk_preamble[0]);
242
+    chunk_type = LE_16(&chunk_preamble[2]);
243
+
244
+    debug_ipmovie("chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
245
+
246
+    switch (chunk_type) {
247
+
248
+    case CHUNK_INIT_AUDIO:
249
+        debug_ipmovie("initialize audio\n");
250
+        break;
251
+
252
+    case CHUNK_AUDIO_ONLY:
253
+        debug_ipmovie("audio only\n");
254
+        break;
255
+
256
+    case CHUNK_INIT_VIDEO:
257
+        debug_ipmovie("initialize video\n");
258
+        break;
259
+
260
+    case CHUNK_VIDEO:
261
+        debug_ipmovie("video (and audio)\n");
262
+        break;
263
+
264
+    case CHUNK_SHUTDOWN:
265
+        debug_ipmovie("shutdown\n");
266
+        break;
267
+
268
+    case CHUNK_END:
269
+        debug_ipmovie("end\n");
270
+        break;
271
+
272
+    default:
273
+        debug_ipmovie("invalid chunk\n");
274
+        chunk_type = CHUNK_BAD;
275
+        break;
276
+
277
+    }
278
+
279
+    while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
280
+
281
+        /* read the next chunk, wherever the file happens to be pointing */
282
+       if (url_feof(pb)) {
283
+            chunk_type = CHUNK_EOF;
284
+            break;
285
+        }
286
+        if (get_buffer(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
287
+            CHUNK_PREAMBLE_SIZE) {
288
+            chunk_type = CHUNK_BAD;
289
+            break;
290
+        }
291
+
292
+        opcode_size = LE_16(&opcode_preamble[0]);
293
+        opcode_type = opcode_preamble[2];
294
+        opcode_version = opcode_preamble[3];
295
+
296
+        chunk_size -= OPCODE_PREAMBLE_SIZE;
297
+        chunk_size -= opcode_size;
298
+        if (chunk_size < 0) {
299
+            debug_ipmovie("chunk_size countdown just went negative\n");
300
+            chunk_type = CHUNK_BAD;
301
+            break;
302
+        }
303
+
304
+        debug_ipmovie("  opcode type %02X, version %d, 0x%04X bytes: ",
305
+            opcode_type, opcode_version, opcode_size);
306
+        switch (opcode_type) {
307
+
308
+        case OPCODE_END_OF_STREAM:
309
+            debug_ipmovie("end of stream\n");
310
+            url_fseek(pb, opcode_size, SEEK_CUR);
311
+            break;
312
+
313
+        case OPCODE_END_OF_CHUNK:
314
+            debug_ipmovie("end of chunk\n");
315
+            url_fseek(pb, opcode_size, SEEK_CUR);
316
+            break;
317
+
318
+        case OPCODE_CREATE_TIMER:
319
+            debug_ipmovie("create timer\n");
320
+            if ((opcode_version > 0) || (opcode_size > 6)) {
321
+                debug_ipmovie("bad create_timer opcode\n");
322
+                chunk_type = CHUNK_BAD;
323
+                break;
324
+            }
325
+            if (get_buffer(pb, scratch, opcode_size) !=
326
+                opcode_size) {
327
+                chunk_type = CHUNK_BAD;
328
+                break;
329
+            }
330
+            s->fps = 1000000 / (LE_32(&scratch[0]) * LE_16(&scratch[4]));
331
+            s->fps++;  /* above calculation usually yields 14.9; we need 15 */
332
+            s->frame_pts_inc = 90000 / s->fps;
333
+            debug_ipmovie("%d frames/second (timer div = %d, subdiv = %d)\n",
334
+                s->fps, LE_32(&scratch[0]), LE_16(&scratch[4]));
335
+            break;
336
+
337
+        case OPCODE_INIT_AUDIO_BUFFERS:
338
+            debug_ipmovie("initialize audio buffers\n");
339
+            if ((opcode_version > 1) || (opcode_size > 10)) {
340
+                debug_ipmovie("bad init_audio_buffers opcode\n");
341
+                chunk_type = CHUNK_BAD;
342
+                break;
343
+            }
344
+            if (get_buffer(pb, scratch, opcode_size) !=
345
+                opcode_size) {
346
+                chunk_type = CHUNK_BAD;
347
+                break;
348
+            }
349
+            s->audio_sample_rate = LE_16(&scratch[4]);
350
+            audio_flags = LE_16(&scratch[2]);
351
+            /* bit 0 of the flags: 0 = mono, 1 = stereo */
352
+            s->audio_channels = (audio_flags & 1) + 1;
353
+            /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
354
+            s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
355
+            /* bit 2 indicates compressed audio in version 1 opcode */
356
+            if ((opcode_version == 1) && (audio_flags & 0x4))
357
+                s->audio_type = CODEC_ID_INTERPLAY_DPCM;
358
+            else if (s->audio_bits == 16)
359
+                s->audio_type = CODEC_ID_PCM_S16LE;
360
+            else
361
+                s->audio_type = CODEC_ID_PCM_U8;
362
+            debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n",
363
+                s->audio_bits,
364
+                s->audio_sample_rate,
365
+                (s->audio_channels == 2) ? "stereo" : "mono",
366
+                (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ? 
367
+                "Interplay audio" : "PCM");
368
+            break;
369
+
370
+        case OPCODE_START_STOP_AUDIO:
371
+            debug_ipmovie("start/stop audio\n");
372
+            url_fseek(pb, opcode_size, SEEK_CUR);
373
+            break;
374
+
375
+        case OPCODE_INIT_VIDEO_BUFFERS:
376
+            debug_ipmovie("initialize video buffers\n");
377
+            if ((opcode_version > 2) || (opcode_size > 8)) {
378
+                debug_ipmovie("bad init_video_buffers opcode\n");
379
+                chunk_type = CHUNK_BAD;
380
+                break;
381
+            }
382
+            if (get_buffer(pb, scratch, opcode_size) !=
383
+                opcode_size) {
384
+                chunk_type = CHUNK_BAD;
385
+                break;
386
+            }
387
+            s->video_width = LE_16(&scratch[0]) * 8;
388
+            s->video_height = LE_16(&scratch[2]) * 8;
389
+            debug_ipmovie("video resolution: %d x %d\n",
390
+                s->video_width, s->video_height);
391
+            break;
392
+
393
+        case OPCODE_UNKNOWN_06:
394
+        case OPCODE_UNKNOWN_0E:
395
+        case OPCODE_UNKNOWN_10:
396
+        case OPCODE_UNKNOWN_12:
397
+        case OPCODE_UNKNOWN_13:
398
+        case OPCODE_UNKNOWN_14:
399
+        case OPCODE_UNKNOWN_15:
400
+            debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type);
401
+            url_fseek(pb, opcode_size, SEEK_CUR);
402
+            break;
403
+
404
+        case OPCODE_SEND_BUFFER:
405
+            debug_ipmovie("send buffer\n");
406
+            url_fseek(pb, opcode_size, SEEK_CUR);
407
+            break;
408
+
409
+        case OPCODE_AUDIO_FRAME:
410
+            debug_ipmovie("audio frame\n");
411
+
412
+            /* log position and move on for now */
413
+            s->audio_chunk_offset = url_ftell(pb);
414
+            s->audio_chunk_size = opcode_size;
415
+            url_fseek(pb, opcode_size, SEEK_CUR);
416
+            break;
417
+
418
+        case OPCODE_SILENCE_FRAME:
419
+            debug_ipmovie("silence frame\n");
420
+            url_fseek(pb, opcode_size, SEEK_CUR);
421
+            break;
422
+
423
+        case OPCODE_INIT_VIDEO_MODE:
424
+            debug_ipmovie("initialize video mode\n");
425
+            url_fseek(pb, opcode_size, SEEK_CUR);
426
+            break;
427
+
428
+        case OPCODE_CREATE_GRADIENT:
429
+            debug_ipmovie("create gradient\n");
430
+            url_fseek(pb, opcode_size, SEEK_CUR);
431
+            break;
432
+
433
+        case OPCODE_SET_PALETTE:
434
+            debug_ipmovie("set palette\n");
435
+            /* check for the logical maximum palette size
436
+             * (3 * 256 + 4 bytes) */
437
+            if (opcode_size > 0x304) {
438
+                debug_ipmovie("demux_ipmovie: set_palette opcode too large\n");
439
+                chunk_type = CHUNK_BAD;
440
+                break;
441
+            }
442
+            if (get_buffer(pb, scratch, opcode_size) != opcode_size) {
443
+                chunk_type = CHUNK_BAD;
444
+                break;
445
+            }
446
+
447
+            /* load the palette into internal data structure */
448
+            first_color = LE_16(&scratch[0]);
449
+            last_color = LE_16(&scratch[2]);
450
+            /* sanity check (since they are 16 bit values) */
451
+            if ((first_color > 0xFF) || (last_color > 0xFF)) {
452
+                debug_ipmovie("demux_ipmovie: set_palette indices out of range (%d -> %d)\n",
453
+                    first_color, last_color);
454
+                chunk_type = CHUNK_BAD;
455
+                break;
456
+            }
457
+            j = 4;  /* offset of first palette data */
458
+#if 0
459
+            for (i = first_color; i <= last_color; i++) {
460
+                s->palette[i].r = scratch[j++] * 4;
461
+                s->palette[i].g = scratch[j++] * 4;
462
+                s->palette[i].b = scratch[j++] * 4;
463
+            }
464
+#endif
465
+            break;
466
+
467
+        case OPCODE_SET_PALETTE_COMPRESSED:
468
+            debug_ipmovie("set palette compressed\n");
469
+            url_fseek(pb, opcode_size, SEEK_CUR);
470
+            break;
471
+
472
+        case OPCODE_SET_DECODING_MAP:
473
+            debug_ipmovie("set decoding map\n");
474
+
475
+            /* log position and move on for now */
476
+            s->decode_map_chunk_offset = url_ftell(pb);
477
+            s->decode_map_chunk_size = opcode_size;
478
+            url_fseek(pb, opcode_size, SEEK_CUR);
479
+            break;
480
+
481
+        case OPCODE_VIDEO_DATA:
482
+            debug_ipmovie("set video data\n");
483
+
484
+            /* log position and move on for now */
485
+            s->video_chunk_offset = url_ftell(pb);
486
+            s->video_chunk_size = opcode_size;
487
+            url_fseek(pb, opcode_size, SEEK_CUR);
488
+            break;
489
+
490
+        default:
491
+            debug_ipmovie("*** unknown opcode type\n");
492
+            chunk_type = CHUNK_BAD;
493
+            break;
494
+
495
+        }
496
+    }
497
+
498
+    /* make a note of where the stream is sitting */
499
+    s->next_chunk_offset = url_ftell(pb);
500
+
501
+    /* dispatch the first of any pending packets */
502
+    if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
503
+        chunk_type = load_ipmovie_packet(s, pb, pkt);
504
+
505
+    return chunk_type;
506
+}
507
+
508
+static int ipmovie_probe(AVProbeData *p)
509
+{
510
+    if (p->buf_size < IPMOVIE_SIGNATURE_SIZE)
511
+        return 0;
512
+    if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0)
513
+        return 0;
514
+
515
+    return AVPROBE_SCORE_MAX;
516
+}
517
+
518
+static int ipmovie_read_header(AVFormatContext *s,
519
+                               AVFormatParameters *ap)
520
+{
521
+    IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
522
+    ByteIOContext *pb = &s->pb;
523
+    AVPacket pkt;
524
+    AVStream *st;
525
+
526
+    /* initialize private context members */
527
+    ipmovie->video_pts = ipmovie->audio_frame_count = 0;
528
+    ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
529
+    ipmovie->decode_map_chunk_offset = 0;
530
+
531
+    /* on the first read, this will position the stream at the first chunk */
532
+    ipmovie->next_chunk_offset = IPMOVIE_SIGNATURE_SIZE + 6;
533
+
534
+    /* process the first chunk which should be CHUNK_INIT_VIDEO */
535
+    if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
536
+        return AVERROR_INVALIDDATA;
537
+
538
+    /* process the next chunk which should be CHUNK_INIT_AUDIO */
539
+    if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
540
+        return AVERROR_INVALIDDATA;
541
+
542
+    /* set the pts reference (1 pts = 1/90000) */
543
+    s->pts_num = 1;
544
+    s->pts_den = 90000;
545
+
546
+    /* initialize the stream decoders */
547
+    st = av_new_stream(s, 0);
548
+    if (!st)
549
+        return AVERROR_NOMEM;
550
+    ipmovie->video_stream_index = st->index;
551
+    st->codec.codec_type = CODEC_TYPE_VIDEO;
552
+    st->codec.codec_id = CODEC_ID_INTERPLAY_VIDEO;
553
+    st->codec.codec_tag = 0;  /* no fourcc */
554
+    st->codec.width = ipmovie->video_width;
555
+    st->codec.height = ipmovie->video_height;
556
+
557
+    st = av_new_stream(s, 0);
558
+    if (!st)
559
+        return AVERROR_NOMEM;
560
+    ipmovie->audio_stream_index = st->index;
561
+    st->codec.codec_type = CODEC_TYPE_AUDIO;
562
+    st->codec.codec_id = ipmovie->audio_type;
563
+    st->codec.codec_tag = 0;  /* no tag */
564
+    st->codec.channels = ipmovie->audio_channels;
565
+    st->codec.sample_rate = ipmovie->audio_sample_rate;
566
+    st->codec.bits_per_sample = ipmovie->audio_bits;
567
+    st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
568
+        st->codec.bits_per_sample / 
569
+        (st->codec.codec_id == CODEC_ID_INTERPLAY_DPCM) ? 2 : 1;
570
+    st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
571
+
572
+    return 0;
573
+}
574
+
575
+static int ipmovie_read_packet(AVFormatContext *s,
576
+                               AVPacket *pkt)
577
+{
578
+    IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
579
+    ByteIOContext *pb = &s->pb;
580
+    int ret;
581
+
582
+    ret = process_ipmovie_chunk(ipmovie, pb, pkt);
583
+    if (ret == CHUNK_BAD)
584
+        ret = AVERROR_INVALIDDATA;
585
+    else if (ret == CHUNK_EOF)
586
+        ret = -EIO;
587
+    else if (ret == CHUNK_NOMEM)
588
+        ret = AVERROR_NOMEM;
589
+    else
590
+        ret = 0;
591
+
592
+    return ret;
593
+}
594
+
595
+static int ipmovie_read_close(AVFormatContext *s)
596
+{
597
+//    IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data;
598
+
599
+    return 0;
600
+}
601
+
602
+static AVInputFormat ipmovie_iformat = {
603
+    "ipmovie",
604
+    "Interplay MVE format",
605
+    sizeof(IPMVEContext),
606
+    ipmovie_probe,
607
+    ipmovie_read_header,
608
+    ipmovie_read_packet,
609
+    ipmovie_read_close,
610
+};
611
+
612
+int ipmovie_init(void)
613
+{
614
+    av_register_input_format(&ipmovie_iformat);
615
+    return 0;
616
+}
617
+