2 * Copyright (C) 2003 the ffmpeg project
4 * This file is part of Libav.
6 * Libav 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 * Libav 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 Libav; 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
, xpos
, ypos
, xp
, yp
, x
, y
, mx
, my
;
42 int frame_stats
[2][4] = {{0},{0}};
46 while (bytestream2_get_bytes_left(&ri
->gb
) > 0) {
47 chunk_id
= bytestream2_get_le16(&ri
->gb
);
48 chunk_size
= bytestream2_get_le32(&ri
->gb
);
49 chunk_arg
= bytestream2_get_le16(&ri
->gb
);
51 if(chunk_id
== RoQ_QUAD_VQ
)
53 if(chunk_id
== RoQ_QUAD_CODEBOOK
) {
54 if((nv1
= chunk_arg
>> 8) == 0)
56 if((nv2
= chunk_arg
& 0xff) == 0 && nv1
* 6 < chunk_size
)
58 for(i
= 0; i
< nv1
; i
++) {
59 ri
->cb2x2
[i
].y
[0] = bytestream2_get_byte(&ri
->gb
);
60 ri
->cb2x2
[i
].y
[1] = bytestream2_get_byte(&ri
->gb
);
61 ri
->cb2x2
[i
].y
[2] = bytestream2_get_byte(&ri
->gb
);
62 ri
->cb2x2
[i
].y
[3] = bytestream2_get_byte(&ri
->gb
);
63 ri
->cb2x2
[i
].u
= bytestream2_get_byte(&ri
->gb
);
64 ri
->cb2x2
[i
].v
= bytestream2_get_byte(&ri
->gb
);
66 for(i
= 0; i
< nv2
; i
++)
67 for(j
= 0; j
< 4; j
++)
68 ri
->cb4x4
[i
].idx
[j
] = bytestream2_get_byte(&ri
->gb
);
72 chunk_start
= bytestream2_tell(&ri
->gb
);
74 while (bytestream2_tell(&ri
->gb
) < chunk_start
+ chunk_size
) {
75 for (yp
= ypos
; yp
< ypos
+ 16; yp
+= 8)
76 for (xp
= xpos
; xp
< xpos
+ 16; xp
+= 8) {
78 vqflg
= bytestream2_get_le16(&ri
->gb
);
81 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
82 frame_stats
[0][vqid
]++;
89 int byte
= bytestream2_get_byte(&ri
->gb
);
90 mx
= 8 - (byte
>> 4) - ((signed char) (chunk_arg
>> 8));
91 my
= 8 - (byte
& 0xf) - ((signed char) chunk_arg
);
92 ff_apply_motion_8x8(ri
, xp
, yp
, mx
, my
);
96 qcell
= ri
->cb4x4
+ bytestream2_get_byte(&ri
->gb
);
97 ff_apply_vector_4x4(ri
, xp
, yp
, ri
->cb2x2
+ qcell
->idx
[0]);
98 ff_apply_vector_4x4(ri
, xp
+ 4, yp
, ri
->cb2x2
+ qcell
->idx
[1]);
99 ff_apply_vector_4x4(ri
, xp
, yp
+ 4, ri
->cb2x2
+ qcell
->idx
[2]);
100 ff_apply_vector_4x4(ri
, xp
+ 4, yp
+ 4, ri
->cb2x2
+ qcell
->idx
[3]);
103 for (k
= 0; k
< 4; k
++) {
109 vqflg
= bytestream2_get_le16(&ri
->gb
);
112 vqid
= (vqflg
>> (vqflg_pos
* 2)) & 0x3;
113 frame_stats
[1][vqid
]++;
119 int byte
= bytestream2_get_byte(&ri
->gb
);
120 mx
= 8 - (byte
>> 4) - ((signed char) (chunk_arg
>> 8));
121 my
= 8 - (byte
& 0xf) - ((signed char) chunk_arg
);
122 ff_apply_motion_4x4(ri
, x
, y
, mx
, my
);
126 qcell
= ri
->cb4x4
+ bytestream2_get_byte(&ri
->gb
);
127 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ qcell
->idx
[0]);
128 ff_apply_vector_2x2(ri
, x
+ 2, y
, ri
->cb2x2
+ qcell
->idx
[1]);
129 ff_apply_vector_2x2(ri
, x
, y
+ 2, ri
->cb2x2
+ qcell
->idx
[2]);
130 ff_apply_vector_2x2(ri
, x
+ 2, y
+ 2, ri
->cb2x2
+ qcell
->idx
[3]);
133 ff_apply_vector_2x2(ri
, x
, y
, ri
->cb2x2
+ bytestream2_get_byte(&ri
->gb
));
134 ff_apply_vector_2x2(ri
, x
+ 2, y
, ri
->cb2x2
+ bytestream2_get_byte(&ri
->gb
));
135 ff_apply_vector_2x2(ri
, x
, y
+ 2, ri
->cb2x2
+ bytestream2_get_byte(&ri
->gb
));
136 ff_apply_vector_2x2(ri
, x
+ 2, y
+ 2, ri
->cb2x2
+ bytestream2_get_byte(&ri
->gb
));
142 av_log(ri
->avctx
, AV_LOG_ERROR
, "Unknown vq code: %d\n", vqid
);
147 if (xpos
>= ri
->width
) {
151 if(ypos
>= ri
->height
)
157 static av_cold
int roq_decode_init(AVCodecContext
*avctx
)
159 RoqContext
*s
= avctx
->priv_data
;
162 s
->width
= avctx
->width
;
163 s
->height
= avctx
->height
;
164 s
->last_frame
= &s
->frames
[0];
165 s
->current_frame
= &s
->frames
[1];
166 avctx
->pix_fmt
= AV_PIX_FMT_YUV444P
;
171 static int roq_decode_frame(AVCodecContext
*avctx
,
172 void *data
, int *got_frame
,
175 const uint8_t *buf
= avpkt
->data
;
176 int buf_size
= avpkt
->size
;
177 RoqContext
*s
= avctx
->priv_data
;
178 int copy
= !s
->current_frame
->data
[0];
180 s
->current_frame
->reference
= 3;
181 if (avctx
->reget_buffer(avctx
, s
->current_frame
)) {
182 av_log(avctx
, AV_LOG_ERROR
, " RoQ: get_buffer() failed\n");
187 av_picture_copy((AVPicture
*)s
->current_frame
, (AVPicture
*)s
->last_frame
,
188 avctx
->pix_fmt
, avctx
->width
, avctx
->height
);
190 bytestream2_init(&s
->gb
, buf
, buf_size
);
191 roqvideo_decode_frame(s
);
194 *(AVFrame
*)data
= *s
->current_frame
;
197 FFSWAP(AVFrame
*, s
->current_frame
, s
->last_frame
);
202 static av_cold
int roq_decode_end(AVCodecContext
*avctx
)
204 RoqContext
*s
= avctx
->priv_data
;
206 /* release the last frame */
207 if (s
->last_frame
->data
[0])
208 avctx
->release_buffer(avctx
, s
->last_frame
);
209 if (s
->current_frame
->data
[0])
210 avctx
->release_buffer(avctx
, s
->current_frame
);
215 AVCodec ff_roq_decoder
= {
217 .type
= AVMEDIA_TYPE_VIDEO
,
218 .id
= AV_CODEC_ID_ROQ
,
219 .priv_data_size
= sizeof(RoqContext
),
220 .init
= roq_decode_init
,
221 .close
= roq_decode_end
,
222 .decode
= roq_decode_frame
,
223 .capabilities
= CODEC_CAP_DR1
,
224 .long_name
= NULL_IF_CONFIG_SMALL("id RoQ video"),