2
* Copyright (C) 2003 the ffmpeg project
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.
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.
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
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/
37
unsigned char y0, y1, y2, y3, u, v;
45
typedef struct RoqContext {
47
AVCodecContext *avctx;
50
AVFrame current_frame;
56
roq_qcell qcells[256];
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
69
#define RoQ_ID_MOT 0x00
70
#define RoQ_ID_FCC 0x01
71
#define RoQ_ID_SLD 0x02
72
#define RoQ_ID_CCC 0x03
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])))
81
static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
85
yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
88
yptr += (ri->y_stride - 2);
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;
95
static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
97
unsigned long row_inc, c_row_inc;
98
register unsigned char y0, y1, u, v;
99
unsigned char *yptr, *uptr, *vptr;
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;
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;
109
*yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
119
yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
121
*yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
123
*yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
134
static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
135
char mean_x, char mean_y)
138
unsigned char *pa, *pb;
140
mx = x + 8 - (mv >> 4) - mean_x;
141
my = y + 8 - (mv & 0xf) - mean_y;
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++) {
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++) {
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++) {
173
static void apply_motion_8x8(RoqContext *ri, int x, int y,
174
unsigned char mv, char mean_x, char mean_y)
177
unsigned char *pa, *pb;
179
mx = x + 8 - (mv >> 4) - mean_x;
180
my = y + 8 - (mv & 0xf) - mean_y;
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++) {
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++) {
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++) {
220
static void roqvideo_decode_frame(RoqContext *ri)
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}};
228
unsigned char *buf = ri->buf;
229
unsigned char *buf_end = ri->buf + ri->size;
231
while (buf < buf_end) {
232
chunk_id = get_word(buf);
233
chunk_size = get_long(buf);
234
chunk_arg = get_word(buf);
236
if(chunk_id == RoQ_QUAD_VQ)
238
if(chunk_id == RoQ_QUAD_CODEBOOK) {
239
if((nv1 = chunk_arg >> 8) == 0)
241
if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
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);
251
for(i = 0; i < nv2; i++)
252
for(j = 0; j < 4; j++)
253
ri->qcells[i].idx[j] = get_byte(buf);
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) {
262
vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
265
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
266
frame_stats[0][vqid]++;
271
apply_motion_8x8(ri, xp, yp, 0, 8, 8);
274
apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
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]);
285
for (k = 0; k < 4; k++) {
292
vqflg |= (buf[bpos++] << 8);
295
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
296
frame_stats[1][vqid]++;
300
apply_motion_4x4(ri, x, y, 0, 8, 8);
303
apply_motion_4x4(ri, x, y, buf[bpos++],
304
chunk_arg >> 8, chunk_arg & 0xff);
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]);
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]);
324
printf("Unknown vq code: %d\n", vqid);
329
if (xpos >= ri->avctx->width) {
330
xpos -= ri->avctx->width;
333
if(ypos >= ri->avctx->height)
339
static int roq_decode_init(AVCodecContext *avctx)
341
RoqContext *s = avctx->priv_data;
345
avctx->pix_fmt = PIX_FMT_YUV420P;
346
avctx->has_b_frames = 0;
347
dsputil_init(&s->dsp, avctx);
352
static int roq_decode_frame(AVCodecContext *avctx,
353
void *data, int *data_size,
354
uint8_t *buf, int buf_size)
356
RoqContext *s = avctx->priv_data;
360
if (avctx->get_buffer(avctx, &s->current_frame)) {
361
printf (" RoQ: get_buffer() failed\n");
364
s->y_stride = s->current_frame.linesize[0];
365
s->c_stride = s->current_frame.linesize[1];
369
roqvideo_decode_frame(s);
371
/* release the last frame if it is allocated */
375
avctx->release_buffer(avctx, &s->last_frame);
378
s->last_frame = s->current_frame;
380
*data_size = sizeof(AVFrame);
381
*(AVFrame*)data = s->current_frame;
386
static int roq_decode_end(AVCodecContext *avctx)
388
RoqContext *s = avctx->priv_data;
390
/* release the last frame */
391
avctx->release_buffer(avctx, &s->last_frame);
396
AVCodec roq_decoder = {