3 * Copyright (c) 2004 Konstantin Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "mpegvideo.h"
31 typedef struct QpegContext{
32 AVCodecContext *avctx;
37 static void qpeg_decode_intra(uint8_t *src, uint8_t *dst, int size,
38 int stride, int width, int height)
49 dst = dst + height * stride;
51 while((size > 0) && (rows_to_go > 0)) {
55 if(code == 0xFC) /* end-of-picture code */
57 if(code >= 0xF8) { /* very long run */
61 run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
62 } else if (code >= 0xF0) { /* long run */
65 run = ((code & 0xF) << 8) + c0 + 2;
66 } else if (code >= 0xE0) { /* short run */
67 run = (code & 0x1F) + 2;
68 } else if (code >= 0xC0) { /* very long copy */
72 copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
73 } else if (code >= 0x80) { /* long copy */
76 copy = ((code & 0x7F) << 8) + c0 + 1;
77 } else { /* short copy */
81 /* perform actual run or copy */
87 for(i = 0; i < run; i++) {
89 if (filled >= width) {
99 for(i = 0; i < copy; i++) {
100 dst[filled++] = *src++;
101 if (filled >= width) {
113 static int qpeg_table_h[16] =
114 { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
115 static int qpeg_table_w[16] =
116 { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
118 /* Decodes delta frames */
119 static void qpeg_decode_inter(uint8_t *src, uint8_t *dst, int size,
120 int stride, int width, int height,
121 int delta, uint8_t *ctable, uint8_t *refdata)
129 /* copy prev frame */
130 for(i = 0; i < height; i++)
131 memcpy(refdata + (i * width), dst + (i * stride), width);
133 orig_height = height;
134 blkdata = src - 0x86;
136 dst = dst + height * stride;
138 while((size > 0) && (height >= 0)) {
143 /* motion compensation */
144 while((code & 0xF0) == 0xF0) {
147 int me_w, me_h, me_x, me_y;
151 /* get block size by index */
153 me_w = qpeg_table_w[me_idx];
154 me_h = qpeg_table_h[me_idx];
156 /* extract motion vector */
170 /* check motion vector */
171 if ((me_x + filled < 0) || (me_x + me_w + filled > width) ||
172 (height - me_y - me_h < 0) || (height - me_y > orig_height) ||
173 (filled + me_w > width) || (height - me_h < 0))
174 av_log(NULL, AV_LOG_ERROR, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
175 me_x, me_y, me_w, me_h, filled, height);
177 /* do motion compensation */
178 me_plane = refdata + (filled + me_x) + (height - me_y) * width;
179 for(j = 0; j < me_h; j++) {
180 for(i = 0; i < me_w; i++)
181 dst[filled + i - (j * stride)] = me_plane[i - (j * width)];
190 if(code == 0xE0) /* end-of-picture code */
192 if(code > 0xE0) { /* run code: 0xE1..0xFF */
198 for(i = 0; i <= code; i++) {
200 if(filled >= width) {
206 } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
209 for(i = 0; i <= code; i++) {
210 dst[filled++] = *src++;
211 if(filled >= width) {
218 } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
222 /* codes 0x80 and 0x81 are actually escape codes,
223 skip value minus constant is in the next byte */
225 skip = (*src++) + 64;
227 skip = (*src++) + 320;
231 while( filled >= width) {
239 /* zero code treated as one-pixel skip */
241 dst[filled++] = ctable[code & 0x7F];
244 if(filled >= width) {
253 static int decode_frame(AVCodecContext *avctx,
254 void *data, int *data_size,
255 uint8_t *buf, int buf_size)
257 QpegContext * const a = avctx->priv_data;
258 AVFrame * const p= (AVFrame*)&a->pic;
263 avctx->release_buffer(avctx, p);
266 if(avctx->get_buffer(avctx, p) < 0){
267 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
270 outdata = a->pic.data[0];
271 if(buf[0x85] == 0x10) {
272 qpeg_decode_intra(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height);
275 qpeg_decode_inter(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height, delta, buf + 4, a->refdata);
278 /* make the palette available on the way out */
279 memcpy(a->pic.data[1], a->avctx->palctrl->palette, AVPALETTE_SIZE);
280 if (a->avctx->palctrl->palette_changed) {
281 a->pic.palette_has_changed = 1;
282 a->avctx->palctrl->palette_changed = 0;
285 *data_size = sizeof(AVFrame);
286 *(AVFrame*)data = a->pic;
291 static int decode_init(AVCodecContext *avctx){
292 QpegContext * const a = avctx->priv_data;
295 avctx->pix_fmt= PIX_FMT_PAL8;
296 avctx->has_b_frames = 0;
297 a->pic.data[0] = NULL;
298 a->refdata = av_malloc(avctx->width * avctx->height);
303 static int decode_end(AVCodecContext *avctx){
304 QpegContext * const a = avctx->priv_data;
305 AVFrame * const p= (AVFrame*)&a->pic;
308 avctx->release_buffer(avctx, p);
314 AVCodec qpeg_decoder = {