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
28 #include "bytestream.h"
31 typedef struct QpegContext
{
32 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 av_noinline
qpeg_decode_inter(QpegContext
*qctx
, uint8_t *dst
,
114 int stride
, int width
, int height
,
115 int delta
, const uint8_t *ctable
,
126 /* copy prev frame */
127 for(i
= 0; i
< height
; i
++)
128 memcpy(dst
+ (i
* stride
), refdata
+ (i
* stride
), width
);
130 orig_height
= height
;
132 dst
= dst
+ height
* stride
;
134 while ((bytestream2_get_bytes_left(&qctx
->buffer
) > 0) && (height
>= 0)) {
135 code
= bytestream2_get_byte(&qctx
->buffer
);
138 /* motion compensation */
139 while(bytestream2_get_bytes_left(&qctx
->buffer
) > 0 && (code
& 0xF0) == 0xF0) {
142 int me_w
, me_h
, me_x
, me_y
;
146 /* get block size by index */
148 me_w
= qpeg_table_w
[me_idx
];
149 me_h
= qpeg_table_h
[me_idx
];
151 /* extract motion vector */
152 corr
= bytestream2_get_byte(&qctx
->buffer
);
164 /* check motion vector */
165 if ((me_x
+ filled
< 0) || (me_x
+ me_w
+ filled
> width
) ||
166 (height
- me_y
- me_h
< 0) || (height
- me_y
>= orig_height
) ||
167 (filled
+ me_w
> width
) || (height
- me_h
< 0))
168 av_log(NULL
, AV_LOG_ERROR
, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
169 me_x
, me_y
, me_w
, me_h
, filled
, height
);
171 /* do motion compensation */
172 me_plane
= refdata
+ (filled
+ me_x
) + (height
- me_y
) * stride
;
173 for(j
= 0; j
< me_h
; j
++) {
174 for(i
= 0; i
< me_w
; i
++)
175 dst
[filled
+ i
- (j
* stride
)] = me_plane
[i
- (j
* stride
)];
179 code
= bytestream2_get_byte(&qctx
->buffer
);
183 if(code
== 0xE0) /* end-of-picture code */
185 if(code
> 0xE0) { /* run code: 0xE1..0xFF */
189 p
= bytestream2_get_byte(&qctx
->buffer
);
190 for(i
= 0; i
<= code
; i
++) {
192 if(filled
>= width
) {
200 } else if(code
>= 0xC0) { /* copy code: 0xC0..0xDF */
203 if(code
+ 1 > bytestream2_get_bytes_left(&qctx
->buffer
))
206 for(i
= 0; i
<= code
; i
++) {
207 dst
[filled
++] = bytestream2_get_byte(&qctx
->buffer
);
208 if(filled
>= width
) {
216 } else if(code
>= 0x80) { /* skip code: 0x80..0xBF */
220 /* codes 0x80 and 0x81 are actually escape codes,
221 skip value minus constant is in the next byte */
223 skip
= bytestream2_get_byte(&qctx
->buffer
) + 64;
225 skip
= bytestream2_get_byte(&qctx
->buffer
) + 320;
229 while( filled
>= width
) {
237 /* zero code treated as one-pixel skip */
239 dst
[filled
++] = ctable
[code
& 0x7F];
243 if(filled
>= width
) {
252 static int decode_frame(AVCodecContext
*avctx
,
253 void *data
, int *got_frame
,
257 QpegContext
* const a
= avctx
->priv_data
;
258 AVFrame
* const p
= a
->pic
;
259 AVFrame
* const ref
= a
->ref
;
262 const uint8_t *pal
= av_packet_get_side_data(avpkt
, AV_PKT_DATA_PALETTE
, NULL
);
264 if (avpkt
->size
< 0x86) {
265 av_log(avctx
, AV_LOG_ERROR
, "Packet is too small\n");
266 return AVERROR_INVALIDDATA
;
269 bytestream2_init(&a
->buffer
, avpkt
->data
, avpkt
->size
);
272 av_frame_move_ref(ref
, p
);
274 if ((ret
= ff_get_buffer(avctx
, p
, AV_GET_BUFFER_FLAG_REF
)) < 0)
276 outdata
= p
->data
[0];
277 bytestream2_skip(&a
->buffer
, 4);
278 bytestream2_get_buffer(&a
->buffer
, ctable
, 128);
279 bytestream2_skip(&a
->buffer
, 1);
281 delta
= bytestream2_get_byte(&a
->buffer
);
283 qpeg_decode_intra(a
, outdata
, p
->linesize
[0], avctx
->width
, avctx
->height
);
285 qpeg_decode_inter(a
, outdata
, p
->linesize
[0], avctx
->width
, avctx
->height
, delta
, ctable
, ref
->data
[0]);
288 /* make the palette available on the way out */
290 p
->palette_has_changed
= 1;
291 memcpy(a
->pal
, pal
, AVPALETTE_SIZE
);
293 memcpy(p
->data
[1], a
->pal
, AVPALETTE_SIZE
);
295 if ((ret
= av_frame_ref(data
, p
)) < 0)
303 static void decode_flush(AVCodecContext
*avctx
){
304 QpegContext
* const a
= avctx
->priv_data
;
306 const uint8_t *pal_src
;
308 pal_size
= FFMIN(1024U, avctx
->extradata_size
);
309 pal_src
= avctx
->extradata
+ avctx
->extradata_size
- pal_size
;
311 for (i
=0; i
<pal_size
/4; i
++)
312 a
->pal
[i
] = 0xFFU
<<24 | AV_RL32(pal_src
+4*i
);
315 static av_cold
int decode_end(AVCodecContext
*avctx
)
317 QpegContext
* const a
= avctx
->priv_data
;
319 av_frame_free(&a
->pic
);
320 av_frame_free(&a
->ref
);
325 static av_cold
int decode_init(AVCodecContext
*avctx
){
326 QpegContext
* const a
= avctx
->priv_data
;
329 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
333 a
->pic
= av_frame_alloc();
334 a
->ref
= av_frame_alloc();
335 if (!a
->pic
|| !a
->ref
) {
337 return AVERROR(ENOMEM
);
343 AVCodec ff_qpeg_decoder
= {
345 .long_name
= NULL_IF_CONFIG_SMALL("Q-team QPEG"),
346 .type
= AVMEDIA_TYPE_VIDEO
,
347 .id
= AV_CODEC_ID_QPEG
,
348 .priv_data_size
= sizeof(QpegContext
),
351 .decode
= decode_frame
,
352 .flush
= decode_flush
,
353 .capabilities
= CODEC_CAP_DR1
,