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
;
44 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)]
48 typedef struct RoqContext
{
50 AVCodecContext
*avctx
;
53 AVFrame current_frame
;
59 roq_qcell qcells
[256];
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
72 #define RoQ_ID_MOT 0x00
73 #define RoQ_ID_FCC 0x01
74 #define RoQ_ID_SLD 0x02
75 #define RoQ_ID_CCC 0x03
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])))
84 static void apply_vector_2x2(RoqContext
*ri
, int x
, int y
, roq_cell
*cell
)
88 yptr
= ri
->current_frame
.data
[0] + (y
* ri
->y_stride
) + x
;
91 yptr
+= (ri
->y_stride
- 2);
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
;
98 static void apply_vector_4x4(RoqContext
*ri
, int x
, int y
, roq_cell
*cell
)
100 unsigned long row_inc
, c_row_inc
;
101 register unsigned char y0
, y1
, u
, v
;
102 unsigned char *yptr
, *uptr
, *vptr
;
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;
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
;
112 *yptr
++ = y1
= cell
->y1
; *uptr
++ = u
; *vptr
++ = v
;
122 yptr
+= row_inc
; uptr
+= c_row_inc
; vptr
+= c_row_inc
;
124 *yptr
++ = y0
= cell
->y2
; *uptr
++ = u
; *vptr
++ = v
;
126 *yptr
++ = y1
= cell
->y3
; *uptr
++ = u
; *vptr
++ = v
;
137 static void apply_motion_4x4(RoqContext
*ri
, int x
, int y
, unsigned char mv
,
138 signed char mean_x
, signed char mean_y
)
141 unsigned char *pa
, *pb
;
143 mx
= x
+ 8 - (mv
>> 4) - mean_x
;
144 my
= y
+ 8 - (mv
& 0xf) - mean_y
;
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
++) {
158 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
++) {
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
++) {
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;
180 for(i
= 0; i
< 2; i
++) {
181 switch(((my
& 0x01) << 1) | (mx
& 0x01)) {
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]);
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]);
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]);
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;
218 static void apply_motion_8x8(RoqContext
*ri
, int x
, int y
,
219 unsigned char mv
, signed char mean_x
, signed char mean_y
)
221 int mx
, my
, i
, j
, hw
;
222 unsigned char *pa
, *pb
;
224 mx
= x
+ 8 - (mv
>> 4) - mean_x
;
225 my
= y
+ 8 - (mv
& 0xf) - mean_y
;
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
++) {
243 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
++) {
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
++) {
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)) {
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]);
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]);
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]);
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;
310 static void roqvideo_decode_frame(RoqContext
*ri
)
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}};
318 unsigned char *buf
= ri
->buf
;
319 unsigned char *buf_end
= ri
->buf
+ ri
->size
;
321 while (buf
< buf_end
) {
322 chunk_id
= get_word(buf
);
323 chunk_size
= get_long(buf
);
324 chunk_arg
= get_word(buf
);
326 if(chunk_id
== RoQ_QUAD_VQ
)
328 if(chunk_id
== RoQ_QUAD_CODEBOOK
) {
329 if((nv1
= chunk_arg
>> 8) == 0)
331 if((nv2
= chunk_arg
& 0xff) == 0 && nv1
* 6 < chunk_size
)
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
);
341 for(i
= 0; i
< nv2
; i
++)
342 for(j
= 0; j
< 4; j
++)
343 ri
->qcells
[i
].idx
[j
] = get_byte(buf
);
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) {
352 vqflg
= buf
[bpos
++]; vqflg
|= (buf
[bpos
++] << 8);
355 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
356 frame_stats
[0][vqid
]++;
361 apply_motion_8x8(ri
, xp
, yp
, 0, 8, 8);
364 apply_motion_8x8(ri
, xp
, yp
, buf
[bpos
++], chunk_arg
>> 8,
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]);
375 for (k
= 0; k
< 4; k
++) {
382 vqflg
|= (buf
[bpos
++] << 8);
385 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
386 frame_stats
[1][vqid
]++;
390 apply_motion_4x4(ri
, x
, y
, 0, 8, 8);
393 apply_motion_4x4(ri
, x
, y
, buf
[bpos
++],
394 chunk_arg
>> 8, chunk_arg
& 0xff);
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]);
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]);
414 av_log(ri
->avctx
, AV_LOG_ERROR
, "Unknown vq code: %d\n", vqid
);
419 if (xpos
>= ri
->avctx
->width
) {
420 xpos
-= ri
->avctx
->width
;
423 if(ypos
>= ri
->avctx
->height
)
429 static int roq_decode_init(AVCodecContext
*avctx
)
431 RoqContext
*s
= avctx
->priv_data
;
436 avctx
->pix_fmt
= PIX_FMT_YUV420P
;
437 avctx
->has_b_frames
= 0;
438 dsputil_init(&s
->dsp
, avctx
);
441 for(i
= -512; i
< 512; i
++)
442 uiclp
[i
] = (i
< 0 ? 0 : (i
> 255 ? 255 : i
));
447 static int roq_decode_frame(AVCodecContext
*avctx
,
448 void *data
, int *data_size
,
449 uint8_t *buf
, int buf_size
)
451 RoqContext
*s
= avctx
->priv_data
;
453 if (avctx
->get_buffer(avctx
, &s
->current_frame
)) {
454 av_log(avctx
, AV_LOG_ERROR
, " RoQ: get_buffer() failed\n");
457 s
->y_stride
= s
->current_frame
.linesize
[0];
458 s
->c_stride
= s
->current_frame
.linesize
[1];
462 roqvideo_decode_frame(s
);
464 /* release the last frame if it is allocated */
468 avctx
->release_buffer(avctx
, &s
->last_frame
);
471 s
->last_frame
= s
->current_frame
;
473 *data_size
= sizeof(AVFrame
);
474 *(AVFrame
*)data
= s
->current_frame
;
479 static int roq_decode_end(AVCodecContext
*avctx
)
481 RoqContext
*s
= avctx
->priv_data
;
483 /* release the last frame */
484 avctx
->release_buffer(avctx
, &s
->last_frame
);
489 AVCodec roq_decoder
= {