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
22 * @file libavcodec/roqvideodec.c
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/
34 #include "bytestream.h"
37 static void roqvideo_decode_frame(RoqContext
*ri
)
39 unsigned int chunk_id
= 0, chunk_arg
= 0;
40 unsigned long chunk_size
= 0;
41 int i
, j
, k
, nv1
, nv2
, vqflg
= 0, vqflg_pos
= -1;
42 int vqid
, bpos
, xpos
, ypos
, xp
, yp
, x
, y
, mx
, my
;
43 int frame_stats
[2][4] = {{0},{0}};
45 const unsigned char *buf
= ri
->buf
;
46 const unsigned char *buf_end
= ri
->buf
+ ri
->size
;
48 while (buf
< buf_end
) {
49 chunk_id
= bytestream_get_le16(&buf
);
50 chunk_size
= bytestream_get_le32(&buf
);
51 chunk_arg
= bytestream_get_le16(&buf
);
53 if(chunk_id
== RoQ_QUAD_VQ
)
55 if(chunk_id
== RoQ_QUAD_CODEBOOK
) {
56 if((nv1
= chunk_arg
>> 8) == 0)
58 if((nv2
= chunk_arg
& 0xff) == 0 && nv1
* 6 < chunk_size
)
60 for(i
= 0; i
< nv1
; i
++) {
61 ri
->cb2x2
[i
].y
[0] = *buf
++;
62 ri
->cb2x2
[i
].y
[1] = *buf
++;
63 ri
->cb2x2
[i
].y
[2] = *buf
++;
64 ri
->cb2x2
[i
].y
[3] = *buf
++;
65 ri
->cb2x2
[i
].u
= *buf
++;
66 ri
->cb2x2
[i
].v
= *buf
++;
68 for(i
= 0; i
< nv2
; i
++)
69 for(j
= 0; j
< 4; j
++)
70 ri
->cb4x4
[i
].idx
[j
] = *buf
++;
74 bpos
= xpos
= ypos
= 0;
75 while(bpos
< chunk_size
) {
76 for (yp
= ypos
; yp
< ypos
+ 16; yp
+= 8)
77 for (xp
= xpos
; xp
< xpos
+ 16; xp
+= 8) {
79 vqflg
= buf
[bpos
++]; vqflg
|= (buf
[bpos
++] << 8);
82 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
83 frame_stats
[0][vqid
]++;
90 mx
= 8 - (buf
[bpos
] >> 4) - ((signed char) (chunk_arg
>> 8));
91 my
= 8 - (buf
[bpos
++] & 0xf) - ((signed char) chunk_arg
);
92 ff_apply_motion_8x8(ri
, xp
, yp
, mx
, my
);
95 qcell
= ri
->cb4x4
+ buf
[bpos
++];
96 ff_apply_vector_4x4(ri
, xp
, yp
, ri
->cb2x2
+ qcell
->idx
[0]);
97 ff_apply_vector_4x4(ri
, xp
+4, yp
, ri
->cb2x2
+ qcell
->idx
[1]);
98 ff_apply_vector_4x4(ri
, xp
, yp
+4, ri
->cb2x2
+ qcell
->idx
[2]);
99 ff_apply_vector_4x4(ri
, xp
+4, yp
+4, ri
->cb2x2
+ qcell
->idx
[3]);
102 for (k
= 0; k
< 4; k
++) {
109 vqflg
|= (buf
[bpos
++] << 8);
112 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
113 frame_stats
[1][vqid
]++;
119 mx
= 8 - (buf
[bpos
] >> 4) - ((signed char) (chunk_arg
>> 8));
120 my
= 8 - (buf
[bpos
++] & 0xf) - ((signed char) chunk_arg
);
121 ff_apply_motion_4x4(ri
, x
, y
, mx
, my
);
124 qcell
= ri
->cb4x4
+ buf
[bpos
++];
125 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ qcell
->idx
[0]);
126 ff_apply_vector_2x2(ri
, x
+2, y
, ri
->cb2x2
+ qcell
->idx
[1]);
127 ff_apply_vector_2x2(ri
, x
, y
+2, ri
->cb2x2
+ qcell
->idx
[2]);
128 ff_apply_vector_2x2(ri
, x
+2, y
+2, ri
->cb2x2
+ qcell
->idx
[3]);
131 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ buf
[bpos
]);
132 ff_apply_vector_2x2(ri
, x
+2, y
, ri
->cb2x2
+ buf
[bpos
+1]);
133 ff_apply_vector_2x2(ri
, x
, y
+2, ri
->cb2x2
+ buf
[bpos
+2]);
134 ff_apply_vector_2x2(ri
, x
+2, y
+2, ri
->cb2x2
+ buf
[bpos
+3]);
141 av_log(ri
->avctx
, AV_LOG_ERROR
, "Unknown vq code: %d\n", vqid
);
146 if (xpos
>= ri
->width
) {
150 if(ypos
>= ri
->height
)
156 static av_cold
int roq_decode_init(AVCodecContext
*avctx
)
158 RoqContext
*s
= avctx
->priv_data
;
161 s
->width
= avctx
->width
;
162 s
->height
= avctx
->height
;
163 s
->last_frame
= &s
->frames
[0];
164 s
->current_frame
= &s
->frames
[1];
165 avctx
->pix_fmt
= PIX_FMT_YUV444P
;
170 static int roq_decode_frame(AVCodecContext
*avctx
,
171 void *data
, int *data_size
,
172 const uint8_t *buf
, int buf_size
)
174 RoqContext
*s
= avctx
->priv_data
;
175 int copy
= !s
->current_frame
->data
[0];
177 if (avctx
->reget_buffer(avctx
, s
->current_frame
)) {
178 av_log(avctx
, AV_LOG_ERROR
, " RoQ: get_buffer() failed\n");
183 av_picture_copy((AVPicture
*)s
->current_frame
, (AVPicture
*)s
->last_frame
,
184 avctx
->pix_fmt
, avctx
->width
, avctx
->height
);
188 roqvideo_decode_frame(s
);
190 *data_size
= sizeof(AVFrame
);
191 *(AVFrame
*)data
= *s
->current_frame
;
194 FFSWAP(AVFrame
*, s
->current_frame
, s
->last_frame
);
199 static av_cold
int roq_decode_end(AVCodecContext
*avctx
)
201 RoqContext
*s
= avctx
->priv_data
;
203 /* release the last frame */
204 if (s
->last_frame
->data
[0])
205 avctx
->release_buffer(avctx
, s
->last_frame
);
206 if (s
->current_frame
->data
[0])
207 avctx
->release_buffer(avctx
, s
->current_frame
);
212 AVCodec roq_decoder
= {
222 .long_name
= NULL_IF_CONFIG_SMALL("id RoQ video"),