3 * Copyright (c) 2004 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "bytestream.h"
30 typedef struct QpegContext
{
31 AVCodecContext
*avctx
;
35 GetByteContext buffer
;
38 static void qpeg_decode_intra(QpegContext
*qctx
, uint8_t *dst
,
39 int stride
, int width
, int height
)
50 dst
= dst
+ height
* stride
;
52 while ((bytestream2_get_bytes_left(&qctx
->buffer
) > 0) && (rows_to_go
> 0)) {
53 code
= bytestream2_get_byte(&qctx
->buffer
);
55 if(code
== 0xFC) /* end-of-picture code */
57 if(code
>= 0xF8) { /* very long run */
58 c0
= bytestream2_get_byte(&qctx
->buffer
);
59 c1
= bytestream2_get_byte(&qctx
->buffer
);
60 run
= ((code
& 0x7) << 16) + (c0
<< 8) + c1
+ 2;
61 } else if (code
>= 0xF0) { /* long run */
62 c0
= bytestream2_get_byte(&qctx
->buffer
);
63 run
= ((code
& 0xF) << 8) + c0
+ 2;
64 } else if (code
>= 0xE0) { /* short run */
65 run
= (code
& 0x1F) + 2;
66 } else if (code
>= 0xC0) { /* very long copy */
67 c0
= bytestream2_get_byte(&qctx
->buffer
);
68 c1
= bytestream2_get_byte(&qctx
->buffer
);
69 copy
= ((code
& 0x3F) << 16) + (c0
<< 8) + c1
+ 1;
70 } else if (code
>= 0x80) { /* long copy */
71 c0
= bytestream2_get_byte(&qctx
->buffer
);
72 copy
= ((code
& 0x7F) << 8) + c0
+ 1;
73 } else { /* short copy */
77 /* perform actual run or copy */
81 p
= bytestream2_get_byte(&qctx
->buffer
);
82 for(i
= 0; i
< run
; i
++) {
84 if (filled
>= width
) {
93 for(i
= 0; i
< copy
; i
++) {
94 dst
[filled
++] = bytestream2_get_byte(&qctx
->buffer
);
95 if (filled
>= width
) {
107 static const int qpeg_table_h
[16] =
108 { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
109 static const int qpeg_table_w
[16] =
110 { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
112 /* Decodes delta frames */
113 static void qpeg_decode_inter(QpegContext
*qctx
, uint8_t *dst
,
114 int stride
, int width
, int height
,
115 int delta
, const uint8_t *ctable
,
123 /* copy prev frame */
124 for(i
= 0; i
< height
; i
++)
125 memcpy(refdata
+ (i
* width
), dst
+ (i
* stride
), width
);
127 orig_height
= height
;
129 dst
= dst
+ height
* stride
;
131 while ((bytestream2_get_bytes_left(&qctx
->buffer
) > 0) && (height
>= 0)) {
132 code
= bytestream2_get_byte(&qctx
->buffer
);
135 /* motion compensation */
136 while((code
& 0xF0) == 0xF0) {
139 int me_w
, me_h
, me_x
, me_y
;
143 /* get block size by index */
145 me_w
= qpeg_table_w
[me_idx
];
146 me_h
= qpeg_table_h
[me_idx
];
148 /* extract motion vector */
149 corr
= bytestream2_get_byte(&qctx
->buffer
);
161 /* check motion vector */
162 if ((me_x
+ filled
< 0) || (me_x
+ me_w
+ filled
> width
) ||
163 (height
- me_y
- me_h
< 0) || (height
- me_y
> orig_height
) ||
164 (filled
+ me_w
> width
) || (height
- me_h
< 0))
165 av_log(NULL
, AV_LOG_ERROR
, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
166 me_x
, me_y
, me_w
, me_h
, filled
, height
);
168 /* do motion compensation */
169 me_plane
= refdata
+ (filled
+ me_x
) + (height
- me_y
) * width
;
170 for(j
= 0; j
< me_h
; j
++) {
171 for(i
= 0; i
< me_w
; i
++)
172 dst
[filled
+ i
- (j
* stride
)] = me_plane
[i
- (j
* width
)];
176 code
= bytestream2_get_byte(&qctx
->buffer
);
180 if(code
== 0xE0) /* end-of-picture code */
182 if(code
> 0xE0) { /* run code: 0xE1..0xFF */
186 p
= bytestream2_get_byte(&qctx
->buffer
);
187 for(i
= 0; i
<= code
; i
++) {
189 if(filled
>= width
) {
195 } else if(code
>= 0xC0) { /* copy code: 0xC0..0xDF */
198 for(i
= 0; i
<= code
; i
++) {
199 dst
[filled
++] = bytestream2_get_byte(&qctx
->buffer
);
200 if(filled
>= width
) {
206 } else if(code
>= 0x80) { /* skip code: 0x80..0xBF */
210 /* codes 0x80 and 0x81 are actually escape codes,
211 skip value minus constant is in the next byte */
213 skip
= bytestream2_get_byte(&qctx
->buffer
) + 64;
215 skip
= bytestream2_get_byte(&qctx
->buffer
) + 320;
219 while( filled
>= width
) {
227 /* zero code treated as one-pixel skip */
229 dst
[filled
++] = ctable
[code
& 0x7F];
233 if(filled
>= width
) {
242 static int decode_frame(AVCodecContext
*avctx
,
243 void *data
, int *got_frame
,
247 QpegContext
* const a
= avctx
->priv_data
;
248 AVFrame
* const p
= &a
->pic
;
251 const uint8_t *pal
= av_packet_get_side_data(avpkt
, AV_PKT_DATA_PALETTE
, NULL
);
253 if (avpkt
->size
< 0x86) {
254 av_log(avctx
, AV_LOG_ERROR
, "Packet is too small\n");
255 return AVERROR_INVALIDDATA
;
258 bytestream2_init(&a
->buffer
, avpkt
->data
, avpkt
->size
);
260 if ((ret
= avctx
->reget_buffer(avctx
, p
)) < 0) {
261 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
264 outdata
= a
->pic
.data
[0];
265 bytestream2_skip(&a
->buffer
, 4);
266 bytestream2_get_buffer(&a
->buffer
, ctable
, 128);
267 bytestream2_skip(&a
->buffer
, 1);
269 delta
= bytestream2_get_byte(&a
->buffer
);
271 qpeg_decode_intra(a
, outdata
, a
->pic
.linesize
[0], avctx
->width
, avctx
->height
);
273 qpeg_decode_inter(a
, outdata
, a
->pic
.linesize
[0], avctx
->width
, avctx
->height
, delta
, ctable
, a
->refdata
);
276 /* make the palette available on the way out */
278 a
->pic
.palette_has_changed
= 1;
279 memcpy(a
->pal
, pal
, AVPALETTE_SIZE
);
281 memcpy(a
->pic
.data
[1], a
->pal
, AVPALETTE_SIZE
);
284 *(AVFrame
*)data
= a
->pic
;
289 static av_cold
int decode_init(AVCodecContext
*avctx
){
290 QpegContext
* const a
= avctx
->priv_data
;
293 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
294 a
->refdata
= av_malloc(avctx
->width
* avctx
->height
);
299 static av_cold
int decode_end(AVCodecContext
*avctx
){
300 QpegContext
* const a
= avctx
->priv_data
;
301 AVFrame
* const p
= &a
->pic
;
304 avctx
->release_buffer(avctx
, p
);
310 AVCodec ff_qpeg_decoder
= {
312 .type
= AVMEDIA_TYPE_VIDEO
,
313 .id
= AV_CODEC_ID_QPEG
,
314 .priv_data_size
= sizeof(QpegContext
),
317 .decode
= decode_frame
,
318 .capabilities
= CODEC_CAP_DR1
,
319 .long_name
= NULL_IF_CONFIG_SMALL("Q-team QPEG"),