Statistics
| Branch: | Revision:

ffmpeg / libavcodec / roqvideo.c @ b846b231

History | View | Annotate | Download (15 KB)

1 3ef8be2b Mike Melanson
/*
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 ec59fd53 Mike Melanson
static int uiclip[1024], *uiclp;  /* clipping table */
45
#define avg2(a,b) uiclp[(((int)(a)+(int)(b)+1)>>1)]
46
#define avg4(a,b,c,d) uiclp[(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)]
47 3ef8be2b Mike Melanson
48
typedef struct RoqContext {
49
50
    AVCodecContext *avctx;
51
    DSPContext dsp;
52
    AVFrame last_frame;
53
    AVFrame current_frame;
54
    int first_frame;
55
    int y_stride;
56
    int c_stride;
57
58
    roq_cell cells[256];
59
    roq_qcell qcells[256];
60
61
    unsigned char *buf;
62
    int size;
63
64
} RoqContext;
65
66
#define RoQ_INFO              0x1001
67
#define RoQ_QUAD_CODEBOOK     0x1002
68
#define RoQ_QUAD_VQ           0x1011
69
#define RoQ_SOUND_MONO        0x1020
70
#define RoQ_SOUND_STEREO      0x1021
71
72
#define RoQ_ID_MOT              0x00
73
#define RoQ_ID_FCC              0x01
74
#define RoQ_ID_SLD              0x02
75
#define RoQ_ID_CCC              0x03
76
77
#define get_byte(in_buffer) *(in_buffer++)
78
#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
79
  (in_buffer[-1] << 8 | in_buffer[-2])))
80
#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
81
  (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
82
83
84
static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
85
{
86
    unsigned char *yptr;
87
88
    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
89
    *yptr++ = cell->y0;
90
    *yptr++ = cell->y1;
91
    yptr += (ri->y_stride - 2);
92
    *yptr++ = cell->y2;
93
    *yptr++ = cell->y3;
94
    ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
95
    ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
96
}
97
98
static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
99
{
100
    unsigned long row_inc, c_row_inc;
101
    register unsigned char y0, y1, u, v;
102
    unsigned char *yptr, *uptr, *vptr;
103
104
    yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
105
    uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
106
    vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
107
108
    row_inc = ri->y_stride - 4;
109
    c_row_inc = (ri->c_stride) - 2;
110
    *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
111
    *yptr++ = y0;
112
    *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
113
    *yptr++ = y1;
114
115
    yptr += row_inc;
116
117
    *yptr++ = y0;
118
    *yptr++ = y0;
119
    *yptr++ = y1;
120
    *yptr++ = y1;
121
122
    yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
123
124
    *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
125
    *yptr++ = y0;
126
    *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
127
    *yptr++ = y1;
128
129
    yptr += row_inc;
130
131
    *yptr++ = y0;
132
    *yptr++ = y0;
133
    *yptr++ = y1;
134
    *yptr++ = y1;
135
}
136
137
static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
138 ec59fd53 Mike Melanson
    signed char mean_x, signed char mean_y)
139 3ef8be2b Mike Melanson
{
140 ec59fd53 Mike Melanson
    int i, hw, mx, my;
141 3ef8be2b Mike Melanson
    unsigned char *pa, *pb;
142
143
    mx = x + 8 - (mv >> 4) - mean_x;
144
    my = y + 8 - (mv & 0xf) - mean_y;
145
146
    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
147
    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
148
    for(i = 0; i < 4; i++) {
149
        pa[0] = pb[0];
150
        pa[1] = pb[1];
151
        pa[2] = pb[2];
152
        pa[3] = pb[3];
153
        pa += ri->y_stride;
154
        pb += ri->y_stride;
155
    }
156
157 ec59fd53 Mike Melanson
#if 0
158 3ef8be2b Mike Melanson
    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
159
    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
160
    for(i = 0; i < 2; i++) {
161
        pa[0] = pb[0];
162
        pa[1] = pb[1];
163
        pa += ri->c_stride;
164
        pb += ri->c_stride;
165
    }
166

167
    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
168
    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
169
    for(i = 0; i < 2; i++) {
170
        pa[0] = pb[0];
171
        pa[1] = pb[1];
172
        pa += ri->c_stride;
173
        pb += ri->c_stride;
174
    }
175 ec59fd53 Mike Melanson
#else
176
    hw = ri->y_stride/2;
177
    pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
178
    pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
179
180
    for(i = 0; i < 2; i++) {
181
        switch(((my & 0x01) << 1) | (mx & 0x01)) {
182
183
        case 0:
184
            pa[0] = pb[0];
185
            pa[1] = pb[1];
186
            pa[hw] = pb[hw];
187
            pa[hw+1] = pb[hw+1];
188
            break;
189
190
        case 1:
191
            pa[0] = avg2(pb[0], pb[1]);
192
            pa[1] = avg2(pb[1], pb[2]);
193
            pa[hw] = avg2(pb[hw], pb[hw+1]);
194
            pa[hw+1] = avg2(pb[hw+1], pb[hw+2]);
195
            break;
196
197
        case 2:
198
            pa[0] = avg2(pb[0], pb[hw]);
199
            pa[1] = avg2(pb[1], pb[hw+1]);
200
            pa[hw] = avg2(pb[hw], pb[hw*2]);
201
            pa[hw+1] = avg2(pb[hw+1], pb[(hw*2)+1]);
202
            break;
203
204
        case 3:
205
            pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
206
            pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
207
            pa[hw] = avg4(pb[hw], pb[hw+1], pb[hw*2], pb[(hw*2)+1]);
208
            pa[hw+1] = avg4(pb[hw+1], pb[hw+2], pb[(hw*2)+1], pb[(hw*2)+1]);
209
            break;
210
        }
211
212
        pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
213
        pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
214
    }
215
#endif
216 3ef8be2b Mike Melanson
}
217
218
static void apply_motion_8x8(RoqContext *ri, int x, int y,
219 ec59fd53 Mike Melanson
    unsigned char mv, signed char mean_x, signed char mean_y)
220 3ef8be2b Mike Melanson
{
221 ec59fd53 Mike Melanson
    int mx, my, i, j, hw;
222 3ef8be2b Mike Melanson
    unsigned char *pa, *pb;
223
224
    mx = x + 8 - (mv >> 4) - mean_x;
225
    my = y + 8 - (mv & 0xf) - mean_y;
226
227
    pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
228
    pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
229
    for(i = 0; i < 8; i++) {
230
        pa[0] = pb[0];
231
        pa[1] = pb[1];
232
        pa[2] = pb[2];
233
        pa[3] = pb[3];
234
        pa[4] = pb[4];
235
        pa[5] = pb[5];
236
        pa[6] = pb[6];
237
        pa[7] = pb[7];
238
        pa += ri->y_stride;
239
        pb += ri->y_stride;
240
    }
241
242 ec59fd53 Mike Melanson
#if 0
243 3ef8be2b Mike Melanson
    pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
244
    pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2;
245
    for(i = 0; i < 4; i++) {
246
        pa[0] = pb[0];
247
        pa[1] = pb[1];
248
        pa[2] = pb[2];
249
        pa[3] = pb[3];
250
        pa += ri->c_stride;
251
        pb += ri->c_stride;
252
    }
253

254
    pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
255
    pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2;
256
    for(i = 0; i < 4; i++) {
257
        pa[0] = pb[0];
258
        pa[1] = pb[1];
259
        pa[2] = pb[2];
260
        pa[3] = pb[3];
261
        pa += ri->c_stride;
262
        pb += ri->c_stride;
263
    }
264 ec59fd53 Mike Melanson
#else
265
    hw = ri->c_stride;
266
    pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
267
    pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
268
    for(j = 0; j < 2; j++) {
269
        for(i = 0; i < 4; i++) {
270
            switch(((my & 0x01) << 1) | (mx & 0x01)) {
271
272
            case 0:
273
                pa[0] = pb[0];
274
                pa[1] = pb[1];
275
                pa[2] = pb[2];
276
                pa[3] = pb[3];
277
                break;
278
279
            case 1:
280
                pa[0] = avg2(pb[0], pb[1]);
281
                pa[1] = avg2(pb[1], pb[2]);
282
                pa[2] = avg2(pb[2], pb[3]);
283
                pa[3] = avg2(pb[3], pb[4]);
284
                break;
285
 
286
            case 2:
287
                pa[0] = avg2(pb[0], pb[hw]);
288
                pa[1] = avg2(pb[1], pb[hw+1]);
289
                pa[2] = avg2(pb[2], pb[hw+2]);
290
                pa[3] = avg2(pb[3], pb[hw+3]);
291
                break;
292
293
            case 3:
294
                pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
295
                pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
296
                pa[2] = avg4(pb[2], pb[3], pb[hw+2], pb[hw+3]);
297
                pa[3] = avg4(pb[3], pb[4], pb[hw+3], pb[hw+4]);
298
                break;
299
            }
300
            pa += ri->c_stride;
301
            pb += ri->c_stride;
302
        }
303
304
        pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
305
        pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
306
    }
307
#endif
308 3ef8be2b Mike Melanson
}
309
310
static void roqvideo_decode_frame(RoqContext *ri)
311
{
312
    unsigned int chunk_id = 0, chunk_arg = 0;
313
    unsigned long chunk_size = 0;
314
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
315
    int vqid, bpos, xpos, ypos, xp, yp, x, y;
316
    int frame_stats[2][4] = {{0},{0}};
317
    roq_qcell *qcell;
318
    unsigned char *buf = ri->buf;
319
    unsigned char *buf_end = ri->buf + ri->size;
320
321
    while (buf < buf_end) {
322
        chunk_id = get_word(buf);
323
        chunk_size = get_long(buf);
324
        chunk_arg = get_word(buf);
325
326
        if(chunk_id == RoQ_QUAD_VQ)
327
            break;
328
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
329
            if((nv1 = chunk_arg >> 8) == 0)
330
                nv1 = 256;
331
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
332
                nv2 = 256;
333
            for(i = 0; i < nv1; i++) {
334
                ri->cells[i].y0 = get_byte(buf);
335
                ri->cells[i].y1 = get_byte(buf);
336
                ri->cells[i].y2 = get_byte(buf);
337
                ri->cells[i].y3 = get_byte(buf);
338
                ri->cells[i].u = get_byte(buf);
339
                ri->cells[i].v = get_byte(buf);
340
            }
341
            for(i = 0; i < nv2; i++)
342
                for(j = 0; j < 4; j++)
343
                    ri->qcells[i].idx[j] = get_byte(buf);
344
        }
345
    }
346
347
    bpos = xpos = ypos = 0;
348
    while(bpos < chunk_size) {
349
        for (yp = ypos; yp < ypos + 16; yp += 8)
350
            for (xp = xpos; xp < xpos + 16; xp += 8) {
351
                if (vqflg_pos < 0) {
352
                    vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
353
                    vqflg_pos = 7;
354
                }
355
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
356
                frame_stats[0][vqid]++;
357
                vqflg_pos--;
358
359
                switch(vqid) {
360
                case RoQ_ID_MOT:
361
                    apply_motion_8x8(ri, xp, yp, 0, 8, 8);
362
                    break;
363
                case RoQ_ID_FCC:
364
                    apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
365
                        chunk_arg & 0xff);
366
                    break;
367
                case RoQ_ID_SLD:
368
                    qcell = ri->qcells + buf[bpos++];
369
                    apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
370
                    apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
371
                    apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
372
                    apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
373
                    break;
374
                case RoQ_ID_CCC:
375
                    for (k = 0; k < 4; k++) {
376
                        x = xp; y = yp;
377
                        if(k & 0x01) x += 4;
378
                        if(k & 0x02) y += 4;
379
380
                        if (vqflg_pos < 0) {
381
                            vqflg = buf[bpos++];
382
                            vqflg |= (buf[bpos++] << 8);
383
                            vqflg_pos = 7;
384
                        }
385
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
386
                        frame_stats[1][vqid]++;
387
                        vqflg_pos--;
388
                        switch(vqid) {
389
                        case RoQ_ID_MOT:
390
                            apply_motion_4x4(ri, x, y, 0, 8, 8);
391
                            break;
392
                        case RoQ_ID_FCC:
393
                            apply_motion_4x4(ri, x, y, buf[bpos++], 
394
                                chunk_arg >> 8, chunk_arg & 0xff);
395
                            break;
396
                        case RoQ_ID_SLD:
397
                            qcell = ri->qcells + buf[bpos++];
398
                            apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
399
                            apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
400
                            apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
401
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
402
                            break;
403
                        case RoQ_ID_CCC:
404
                            apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
405
                            apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
406
                            apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
407
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
408
                            bpos += 4;
409
                            break;
410
                        }
411
                    }
412
                    break;
413
                default:
414 9b879566 Michel Bardiaux
                    av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
415 3ef8be2b Mike Melanson
            }
416
        }
417
418
        xpos += 16;
419
        if (xpos >= ri->avctx->width) {
420
            xpos -= ri->avctx->width;
421
            ypos += 16;
422
        }
423
        if(ypos >= ri->avctx->height)
424
            break;
425
    }
426
}
427
428
429
static int roq_decode_init(AVCodecContext *avctx)
430
{
431
    RoqContext *s = avctx->priv_data;
432 ec59fd53 Mike Melanson
    int i;
433 3ef8be2b Mike Melanson
434
    s->avctx = avctx;
435
    s->first_frame = 1;
436
    avctx->pix_fmt = PIX_FMT_YUV420P;
437
    avctx->has_b_frames = 0;
438
    dsputil_init(&s->dsp, avctx);
439
440 ec59fd53 Mike Melanson
    uiclp = uiclip+512;
441
    for(i = -512; i < 512; i++)
442
        uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
443
444 3ef8be2b Mike Melanson
    return 0;
445
}
446
447
static int roq_decode_frame(AVCodecContext *avctx,
448
                            void *data, int *data_size,
449
                            uint8_t *buf, int buf_size)
450
{
451
    RoqContext *s = avctx->priv_data;
452
453
    *data_size = 0;
454
455
    if (avctx->get_buffer(avctx, &s->current_frame)) {
456 9b879566 Michel Bardiaux
        av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failed\n");
457 3ef8be2b Mike Melanson
        return -1;
458
    }
459
    s->y_stride = s->current_frame.linesize[0];
460
    s->c_stride = s->current_frame.linesize[1];
461
462
    s->buf = buf;
463
    s->size = buf_size;
464
    roqvideo_decode_frame(s);
465
466
    /* release the last frame if it is allocated */
467
    if (s->first_frame)
468
        s->first_frame = 0;
469
    else
470
        avctx->release_buffer(avctx, &s->last_frame);
471
472
    /* shuffle frames */
473
    s->last_frame = s->current_frame;
474
475
    *data_size = sizeof(AVFrame);
476
    *(AVFrame*)data = s->current_frame;
477
478
    return buf_size;
479
}
480
481
static int roq_decode_end(AVCodecContext *avctx)
482
{
483
    RoqContext *s = avctx->priv_data;
484
485
    /* release the last frame */
486
    avctx->release_buffer(avctx, &s->last_frame);
487
488
    return 0;
489
}
490
491
AVCodec roq_decoder = {
492
    "roqvideo",
493
    CODEC_TYPE_VIDEO,
494
    CODEC_ID_ROQ,
495
    sizeof(RoqContext),
496
    roq_decode_init,
497
    NULL,
498
    roq_decode_end,
499
    roq_decode_frame,
500
    CODEC_CAP_DR1,
501
};