2 * Copyright (C) 2003 the ffmpeg project
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * id RoQ Video Decoder by Dr. Tim Ferguson
24 * For more information about the id RoQ format, visit:
25 * http://www.csse.monash.edu.au/~timf/
33 #include "bytestream.h"
36 static void roqvideo_decode_frame(RoqContext
*ri
)
38 unsigned int chunk_id
= 0, chunk_arg
= 0;
39 unsigned long chunk_size
= 0;
40 int i
, j
, k
, nv1
, nv2
, vqflg
= 0, vqflg_pos
= -1;
41 int vqid
, bpos
, xpos
, ypos
, xp
, yp
, x
, y
, mx
, my
;
42 int frame_stats
[2][4] = {{0},{0}};
44 const unsigned char *buf
= ri
->buf
;
45 const unsigned char *buf_end
= ri
->buf
+ ri
->size
;
47 while (buf
< buf_end
) {
48 chunk_id
= bytestream_get_le16(&buf
);
49 chunk_size
= bytestream_get_le32(&buf
);
50 chunk_arg
= bytestream_get_le16(&buf
);
52 if(chunk_id
== RoQ_QUAD_VQ
)
54 if(chunk_id
== RoQ_QUAD_CODEBOOK
) {
55 if((nv1
= chunk_arg
>> 8) == 0)
57 if((nv2
= chunk_arg
& 0xff) == 0 && nv1
* 6 < chunk_size
)
59 for(i
= 0; i
< nv1
; i
++) {
60 ri
->cb2x2
[i
].y
[0] = *buf
++;
61 ri
->cb2x2
[i
].y
[1] = *buf
++;
62 ri
->cb2x2
[i
].y
[2] = *buf
++;
63 ri
->cb2x2
[i
].y
[3] = *buf
++;
64 ri
->cb2x2
[i
].u
= *buf
++;
65 ri
->cb2x2
[i
].v
= *buf
++;
67 for(i
= 0; i
< nv2
; i
++)
68 for(j
= 0; j
< 4; j
++)
69 ri
->cb4x4
[i
].idx
[j
] = *buf
++;
73 bpos
= xpos
= ypos
= 0;
74 while(bpos
< chunk_size
) {
75 for (yp
= ypos
; yp
< ypos
+ 16; yp
+= 8)
76 for (xp
= xpos
; xp
< xpos
+ 16; xp
+= 8) {
78 vqflg
= buf
[bpos
++]; vqflg
|= (buf
[bpos
++] << 8);
81 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
82 frame_stats
[0][vqid
]++;
89 mx
= 8 - (buf
[bpos
] >> 4) - ((signed char) (chunk_arg
>> 8));
90 my
= 8 - (buf
[bpos
++] & 0xf) - ((signed char) chunk_arg
);
91 ff_apply_motion_8x8(ri
, xp
, yp
, mx
, my
);
94 qcell
= ri
->cb4x4
+ buf
[bpos
++];
95 ff_apply_vector_4x4(ri
, xp
, yp
, ri
->cb2x2
+ qcell
->idx
[0]);
96 ff_apply_vector_4x4(ri
, xp
+4, yp
, ri
->cb2x2
+ qcell
->idx
[1]);
97 ff_apply_vector_4x4(ri
, xp
, yp
+4, ri
->cb2x2
+ qcell
->idx
[2]);
98 ff_apply_vector_4x4(ri
, xp
+4, yp
+4, ri
->cb2x2
+ qcell
->idx
[3]);
101 for (k
= 0; k
< 4; k
++) {
108 vqflg
|= (buf
[bpos
++] << 8);
111 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
112 frame_stats
[1][vqid
]++;
118 mx
= 8 - (buf
[bpos
] >> 4) - ((signed char) (chunk_arg
>> 8));
119 my
= 8 - (buf
[bpos
++] & 0xf) - ((signed char) chunk_arg
);
120 ff_apply_motion_4x4(ri
, x
, y
, mx
, my
);
123 qcell
= ri
->cb4x4
+ buf
[bpos
++];
124 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ qcell
->idx
[0]);
125 ff_apply_vector_2x2(ri
, x
+2, y
, ri
->cb2x2
+ qcell
->idx
[1]);
126 ff_apply_vector_2x2(ri
, x
, y
+2, ri
->cb2x2
+ qcell
->idx
[2]);
127 ff_apply_vector_2x2(ri
, x
+2, y
+2, ri
->cb2x2
+ qcell
->idx
[3]);
130 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ buf
[bpos
]);
131 ff_apply_vector_2x2(ri
, x
+2, y
, ri
->cb2x2
+ buf
[bpos
+1]);
132 ff_apply_vector_2x2(ri
, x
, y
+2, ri
->cb2x2
+ buf
[bpos
+2]);
133 ff_apply_vector_2x2(ri
, x
+2, y
+2, ri
->cb2x2
+ buf
[bpos
+3]);
140 av_log(ri
->avctx
, AV_LOG_ERROR
, "Unknown vq code: %d\n", vqid
);
145 if (xpos
>= ri
->width
) {
149 if(ypos
>= ri
->height
)
155 static av_cold
int roq_decode_init(AVCodecContext
*avctx
)
157 RoqContext
*s
= avctx
->priv_data
;
160 s
->width
= avctx
->width
;
161 s
->height
= avctx
->height
;
162 s
->last_frame
= &s
->frames
[0];
163 s
->current_frame
= &s
->frames
[1];
164 avctx
->pix_fmt
= PIX_FMT_YUV444P
;
169 static int roq_decode_frame(AVCodecContext
*avctx
,
170 void *data
, int *data_size
,
173 const uint8_t *buf
= avpkt
->data
;
174 int buf_size
= avpkt
->size
;
175 RoqContext
*s
= avctx
->priv_data
;
176 int copy
= !s
->current_frame
->data
[0];
178 if (avctx
->reget_buffer(avctx
, s
->current_frame
)) {
179 av_log(avctx
, AV_LOG_ERROR
, " RoQ: get_buffer() failed\n");
184 av_picture_copy((AVPicture
*)s
->current_frame
, (AVPicture
*)s
->last_frame
,
185 avctx
->pix_fmt
, avctx
->width
, avctx
->height
);
189 roqvideo_decode_frame(s
);
191 *data_size
= sizeof(AVFrame
);
192 *(AVFrame
*)data
= *s
->current_frame
;
195 FFSWAP(AVFrame
*, s
->current_frame
, s
->last_frame
);
200 static av_cold
int roq_decode_end(AVCodecContext
*avctx
)
202 RoqContext
*s
= avctx
->priv_data
;
204 /* release the last frame */
205 if (s
->last_frame
->data
[0])
206 avctx
->release_buffer(avctx
, s
->last_frame
);
207 if (s
->current_frame
->data
[0])
208 avctx
->release_buffer(avctx
, s
->current_frame
);
213 AVCodec roq_decoder
= {
223 .long_name
= NULL_IF_CONFIG_SMALL("id RoQ video"),