~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavcodec/roqvideo.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 * Id RoQ Video Decoder by Dr. Tim Ferguson
 
23
 * For more information about the Id RoQ format, visit:
 
24
 *   http://www.csse.monash.edu.au/~timf/
 
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 {
 
37
  unsigned char y0, y1, y2, y3, u, v;
 
38
} roq_cell;
 
39
 
 
40
typedef struct {
 
41
  int idx[4];
 
42
} roq_qcell;
 
43
 
 
44
 
 
45
typedef struct RoqContext {
 
46
 
 
47
    AVCodecContext *avctx;
 
48
    DSPContext dsp;
 
49
    AVFrame last_frame;
 
50
    AVFrame current_frame;
 
51
    int first_frame;
 
52
    int y_stride;
 
53
    int c_stride;
 
54
 
 
55
    roq_cell cells[256];
 
56
    roq_qcell qcells[256];
 
57
 
 
58
    unsigned char *buf;
 
59
    int size;
 
60
 
 
61
} RoqContext;
 
62
 
 
63
#define RoQ_INFO              0x1001
 
64
#define RoQ_QUAD_CODEBOOK     0x1002
 
65
#define RoQ_QUAD_VQ           0x1011
 
66
#define RoQ_SOUND_MONO        0x1020
 
67
#define RoQ_SOUND_STEREO      0x1021
 
68
 
 
69
#define RoQ_ID_MOT              0x00
 
70
#define RoQ_ID_FCC              0x01
 
71
#define RoQ_ID_SLD              0x02
 
72
#define RoQ_ID_CCC              0x03
 
73
 
 
74
#define get_byte(in_buffer) *(in_buffer++)
 
75
#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
 
76
  (in_buffer[-1] << 8 | in_buffer[-2])))
 
77
#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
 
78
  (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
 
79
 
 
80
 
 
81
static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
 
82
{
 
83
    unsigned char *yptr;
 
84
 
 
85
    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
 
86
    *yptr++ = cell->y0;
 
87
    *yptr++ = cell->y1;
 
88
    yptr += (ri->y_stride - 2);
 
89
    *yptr++ = cell->y2;
 
90
    *yptr++ = cell->y3;
 
91
    ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
 
92
    ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
 
93
}
 
94
 
 
95
static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
 
96
{
 
97
    unsigned long row_inc, c_row_inc;
 
98
    register unsigned char y0, y1, u, v;
 
99
    unsigned char *yptr, *uptr, *vptr;
 
100
 
 
101
    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
 
102
    uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
 
103
    vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
 
104
 
 
105
    row_inc = ri->y_stride - 4;
 
106
    c_row_inc = (ri->c_stride) - 2;
 
107
    *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
 
108
    *yptr++ = y0;
 
109
    *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
 
110
    *yptr++ = y1;
 
111
 
 
112
    yptr += row_inc;
 
113
 
 
114
    *yptr++ = y0;
 
115
    *yptr++ = y0;
 
116
    *yptr++ = y1;
 
117
    *yptr++ = y1;
 
118
 
 
119
    yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
 
120
 
 
121
    *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
 
122
    *yptr++ = y0;
 
123
    *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
 
124
    *yptr++ = y1;
 
125
 
 
126
    yptr += row_inc;
 
127
 
 
128
    *yptr++ = y0;
 
129
    *yptr++ = y0;
 
130
    *yptr++ = y1;
 
131
    *yptr++ = y1;
 
132
}
 
133
 
 
134
static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
 
135
    char mean_x, char mean_y)
 
136
{
 
137
    int i, mx, my;
 
138
    unsigned char *pa, *pb;
 
139
 
 
140
    mx = x + 8 - (mv >> 4) - mean_x;
 
141
    my = y + 8 - (mv & 0xf) - mean_y;
 
142
 
 
143
    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
 
144
    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
 
145
    for(i = 0; i < 4; i++) {
 
146
        pa[0] = pb[0];
 
147
        pa[1] = pb[1];
 
148
        pa[2] = pb[2];
 
149
        pa[3] = pb[3];
 
150
        pa += ri->y_stride;
 
151
        pb += ri->y_stride;
 
152
    }
 
153
 
 
154
    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
 
155
    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
 
156
    for(i = 0; i < 2; i++) {
 
157
        pa[0] = pb[0];
 
158
        pa[1] = pb[1];
 
159
        pa += ri->c_stride;
 
160
        pb += ri->c_stride;
 
161
    }
 
162
 
 
163
    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
 
164
    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
 
165
    for(i = 0; i < 2; i++) {
 
166
        pa[0] = pb[0];
 
167
        pa[1] = pb[1];
 
168
        pa += ri->c_stride;
 
169
        pb += ri->c_stride;
 
170
    }
 
171
}
 
172
 
 
173
static void apply_motion_8x8(RoqContext *ri, int x, int y,
 
174
    unsigned char mv, char mean_x, char mean_y)
 
175
{
 
176
    int mx, my, i;
 
177
    unsigned char *pa, *pb;
 
178
 
 
179
    mx = x + 8 - (mv >> 4) - mean_x;
 
180
    my = y + 8 - (mv & 0xf) - mean_y;
 
181
 
 
182
    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
 
183
    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
 
184
    for(i = 0; i < 8; i++) {
 
185
        pa[0] = pb[0];
 
186
        pa[1] = pb[1];
 
187
        pa[2] = pb[2];
 
188
        pa[3] = pb[3];
 
189
        pa[4] = pb[4];
 
190
        pa[5] = pb[5];
 
191
        pa[6] = pb[6];
 
192
        pa[7] = pb[7];
 
193
        pa += ri->y_stride;
 
194
        pb += ri->y_stride;
 
195
    }
 
196
 
 
197
    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
 
198
    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
 
199
    for(i = 0; i < 4; i++) {
 
200
        pa[0] = pb[0];
 
201
        pa[1] = pb[1];
 
202
        pa[2] = pb[2];
 
203
        pa[3] = pb[3];
 
204
        pa += ri->c_stride;
 
205
        pb += ri->c_stride;
 
206
    }
 
207
 
 
208
    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
 
209
    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
 
210
    for(i = 0; i < 4; i++) {
 
211
        pa[0] = pb[0];
 
212
        pa[1] = pb[1];
 
213
        pa[2] = pb[2];
 
214
        pa[3] = pb[3];
 
215
        pa += ri->c_stride;
 
216
        pb += ri->c_stride;
 
217
    }
 
218
}
 
219
 
 
220
static void roqvideo_decode_frame(RoqContext *ri)
 
221
{
 
222
    unsigned int chunk_id = 0, chunk_arg = 0;
 
223
    unsigned long chunk_size = 0;
 
224
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
 
225
    int vqid, bpos, xpos, ypos, xp, yp, x, y;
 
226
    int frame_stats[2][4] = {{0},{0}};
 
227
    roq_qcell *qcell;
 
228
    unsigned char *buf = ri->buf;
 
229
    unsigned char *buf_end = ri->buf + ri->size;
 
230
 
 
231
    while (buf < buf_end) {
 
232
        chunk_id = get_word(buf);
 
233
        chunk_size = get_long(buf);
 
234
        chunk_arg = get_word(buf);
 
235
 
 
236
        if(chunk_id == RoQ_QUAD_VQ)
 
237
            break;
 
238
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
 
239
            if((nv1 = chunk_arg >> 8) == 0)
 
240
                nv1 = 256;
 
241
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
 
242
                nv2 = 256;
 
243
            for(i = 0; i < nv1; i++) {
 
244
                ri->cells[i].y0 = get_byte(buf);
 
245
                ri->cells[i].y1 = get_byte(buf);
 
246
                ri->cells[i].y2 = get_byte(buf);
 
247
                ri->cells[i].y3 = get_byte(buf);
 
248
                ri->cells[i].u = get_byte(buf);
 
249
                ri->cells[i].v = get_byte(buf);
 
250
            }
 
251
            for(i = 0; i < nv2; i++)
 
252
                for(j = 0; j < 4; j++)
 
253
                    ri->qcells[i].idx[j] = get_byte(buf);
 
254
        }
 
255
    }
 
256
 
 
257
    bpos = xpos = ypos = 0;
 
258
    while(bpos < chunk_size) {
 
259
        for (yp = ypos; yp < ypos + 16; yp += 8)
 
260
            for (xp = xpos; xp < xpos + 16; xp += 8) {
 
261
                if (vqflg_pos < 0) {
 
262
                    vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
 
263
                    vqflg_pos = 7;
 
264
                }
 
265
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
 
266
                frame_stats[0][vqid]++;
 
267
                vqflg_pos--;
 
268
 
 
269
                switch(vqid) {
 
270
                case RoQ_ID_MOT:
 
271
                    apply_motion_8x8(ri, xp, yp, 0, 8, 8);
 
272
                    break;
 
273
                case RoQ_ID_FCC:
 
274
                    apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
 
275
                        chunk_arg & 0xff);
 
276
                    break;
 
277
                case RoQ_ID_SLD:
 
278
                    qcell = ri->qcells + buf[bpos++];
 
279
                    apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
 
280
                    apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
 
281
                    apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
 
282
                    apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
 
283
                    break;
 
284
                case RoQ_ID_CCC:
 
285
                    for (k = 0; k < 4; k++) {
 
286
                        x = xp; y = yp;
 
287
                        if(k & 0x01) x += 4;
 
288
                        if(k & 0x02) y += 4;
 
289
 
 
290
                        if (vqflg_pos < 0) {
 
291
                            vqflg = buf[bpos++];
 
292
                            vqflg |= (buf[bpos++] << 8);
 
293
                            vqflg_pos = 7;
 
294
                        }
 
295
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
 
296
                        frame_stats[1][vqid]++;
 
297
                        vqflg_pos--;
 
298
                        switch(vqid) {
 
299
                        case RoQ_ID_MOT:
 
300
                            apply_motion_4x4(ri, x, y, 0, 8, 8);
 
301
                            break;
 
302
                        case RoQ_ID_FCC:
 
303
                            apply_motion_4x4(ri, x, y, buf[bpos++], 
 
304
                                chunk_arg >> 8, chunk_arg & 0xff);
 
305
                            break;
 
306
                        case RoQ_ID_SLD:
 
307
                            qcell = ri->qcells + buf[bpos++];
 
308
                            apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
 
309
                            apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
 
310
                            apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
 
311
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
 
312
                            break;
 
313
                        case RoQ_ID_CCC:
 
314
                            apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
 
315
                            apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
 
316
                            apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
 
317
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
 
318
                            bpos += 4;
 
319
                            break;
 
320
                        }
 
321
                    }
 
322
                    break;
 
323
                default:
 
324
                    printf("Unknown vq code: %d\n", vqid);
 
325
            }
 
326
        }
 
327
 
 
328
        xpos += 16;
 
329
        if (xpos >= ri->avctx->width) {
 
330
            xpos -= ri->avctx->width;
 
331
            ypos += 16;
 
332
        }
 
333
        if(ypos >= ri->avctx->height)
 
334
            break;
 
335
    }
 
336
}
 
337
 
 
338
 
 
339
static int roq_decode_init(AVCodecContext *avctx)
 
340
{
 
341
    RoqContext *s = avctx->priv_data;
 
342
 
 
343
    s->avctx = avctx;
 
344
    s->first_frame = 1;
 
345
    avctx->pix_fmt = PIX_FMT_YUV420P;
 
346
    avctx->has_b_frames = 0;
 
347
    dsputil_init(&s->dsp, avctx);
 
348
 
 
349
    return 0;
 
350
}
 
351
 
 
352
static int roq_decode_frame(AVCodecContext *avctx,
 
353
                            void *data, int *data_size,
 
354
                            uint8_t *buf, int buf_size)
 
355
{
 
356
    RoqContext *s = avctx->priv_data;
 
357
 
 
358
    *data_size = 0;
 
359
 
 
360
    if (avctx->get_buffer(avctx, &s->current_frame)) {
 
361
        printf ("  RoQ: get_buffer() failed\n");
 
362
        return -1;
 
363
    }
 
364
    s->y_stride = s->current_frame.linesize[0];
 
365
    s->c_stride = s->current_frame.linesize[1];
 
366
 
 
367
    s->buf = buf;
 
368
    s->size = buf_size;
 
369
    roqvideo_decode_frame(s);
 
370
 
 
371
    /* release the last frame if it is allocated */
 
372
    if (s->first_frame)
 
373
        s->first_frame = 0;
 
374
    else
 
375
        avctx->release_buffer(avctx, &s->last_frame);
 
376
 
 
377
    /* shuffle frames */
 
378
    s->last_frame = s->current_frame;
 
379
 
 
380
    *data_size = sizeof(AVFrame);
 
381
    *(AVFrame*)data = s->current_frame;
 
382
 
 
383
    return buf_size;
 
384
}
 
385
 
 
386
static int roq_decode_end(AVCodecContext *avctx)
 
387
{
 
388
    RoqContext *s = avctx->priv_data;
 
389
 
 
390
    /* release the last frame */
 
391
    avctx->release_buffer(avctx, &s->last_frame);
 
392
 
 
393
    return 0;
 
394
}
 
395
 
 
396
AVCodec roq_decoder = {
 
397
    "roqvideo",
 
398
    CODEC_TYPE_VIDEO,
 
399
    CODEC_ID_ROQ,
 
400
    sizeof(RoqContext),
 
401
    roq_decode_init,
 
402
    NULL,
 
403
    roq_decode_end,
 
404
    roq_decode_frame,
 
405
    CODEC_CAP_DR1,
 
406
};