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"
29 #include "codec_internal.h"
33 typedef struct QpegContext
{
34 AVCodecContext
*avctx
;
37 GetByteContext buffer
;
40 static void qpeg_decode_intra(QpegContext
*qctx
, uint8_t *dst
,
41 int stride
, int width
, int height
)
52 dst
= dst
+ height
* stride
;
54 while ((bytestream2_get_bytes_left(&qctx
->buffer
) > 0) && (rows_to_go
> 0)) {
55 code
= bytestream2_get_byte(&qctx
->buffer
);
57 if(code
== 0xFC) /* end-of-picture code */
59 if(code
>= 0xF8) { /* very long run */
60 c0
= bytestream2_get_byte(&qctx
->buffer
);
61 c1
= bytestream2_get_byte(&qctx
->buffer
);
62 run
= ((code
& 0x7) << 16) + (c0
<< 8) + c1
+ 2;
63 } else if (code
>= 0xF0) { /* long run */
64 c0
= bytestream2_get_byte(&qctx
->buffer
);
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 */
69 c0
= bytestream2_get_byte(&qctx
->buffer
);
70 c1
= bytestream2_get_byte(&qctx
->buffer
);
71 copy
= ((code
& 0x3F) << 16) + (c0
<< 8) + c1
+ 1;
72 } else if (code
>= 0x80) { /* long copy */
73 c0
= bytestream2_get_byte(&qctx
->buffer
);
74 copy
= ((code
& 0x7F) << 8) + c0
+ 1;
75 } else { /* short copy */
79 /* perform actual run or copy */
83 p
= bytestream2_get_byte(&qctx
->buffer
);
84 for(i
= 0; i
< run
; i
++) {
85 int step
= FFMIN(run
- i
, width
- filled
);
86 memset(dst
+filled
, p
, step
);
89 if (filled
>= width
) {
93 while (run
- i
> width
&& rows_to_go
> 0) {
94 memset(dst
, p
, width
);
104 if (bytestream2_get_bytes_left(&qctx
->buffer
) < copy
)
105 copy
= bytestream2_get_bytes_left(&qctx
->buffer
);
107 int step
= FFMIN(copy
, width
- filled
);
108 bytestream2_get_bufferu(&qctx
->buffer
, dst
+ filled
, step
);
111 if (filled
>= width
) {
123 static const uint8_t qpeg_table_h
[16] =
124 { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
125 static const uint8_t qpeg_table_w
[16] =
126 { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
128 /* Decodes delta frames */
129 static void av_noinline
qpeg_decode_inter(QpegContext
*qctx
, uint8_t *dst
,
130 int stride
, int width
, int height
,
131 int delta
, const uint8_t *ctable
,
140 /* copy prev frame */
141 for (i
= 0; i
< height
; i
++)
142 memcpy(dst
+ (i
* stride
), refdata
+ (i
* stride
), width
);
147 orig_height
= height
;
149 dst
= dst
+ height
* stride
;
151 while ((bytestream2_get_bytes_left(&qctx
->buffer
) > 0) && (height
>= 0)) {
152 code
= bytestream2_get_byte(&qctx
->buffer
);
155 /* motion compensation */
156 while(bytestream2_get_bytes_left(&qctx
->buffer
) > 0 && (code
& 0xF0) == 0xF0) {
159 int me_w
, me_h
, me_x
, me_y
;
163 /* get block size by index */
165 me_w
= qpeg_table_w
[me_idx
];
166 me_h
= qpeg_table_h
[me_idx
];
168 /* extract motion vector */
169 corr
= bytestream2_get_byte(&qctx
->buffer
);
181 /* check motion vector */
182 if ((me_x
+ filled
< 0) || (me_x
+ me_w
+ filled
> width
) ||
183 (height
- me_y
- me_h
< 0) || (height
- me_y
>= orig_height
) ||
184 (filled
+ me_w
> width
) || (height
- me_h
< 0))
185 av_log(qctx
->avctx
, AV_LOG_ERROR
, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
186 me_x
, me_y
, me_w
, me_h
, filled
, height
);
188 /* do motion compensation */
189 me_plane
= refdata
+ (filled
+ me_x
) + (height
- me_y
) * stride
;
190 for(j
= 0; j
< me_h
; j
++) {
191 for(i
= 0; i
< me_w
; i
++)
192 dst
[filled
+ i
- (j
* stride
)] = me_plane
[i
- (j
* stride
)];
196 code
= bytestream2_get_byte(&qctx
->buffer
);
200 if(code
== 0xE0) /* end-of-picture code */
202 if(code
> 0xE0) { /* run code: 0xE1..0xFF */
206 p
= bytestream2_get_byte(&qctx
->buffer
);
207 for(i
= 0; i
<= code
; i
++) {
209 if(filled
>= width
) {
217 } else if(code
>= 0xC0) { /* copy code: 0xC0..0xDF */
220 if(code
+ 1 > bytestream2_get_bytes_left(&qctx
->buffer
))
223 for(i
= 0; i
<= code
; i
++) {
224 dst
[filled
++] = bytestream2_get_byte(&qctx
->buffer
);
225 if(filled
>= width
) {
233 } else if(code
>= 0x80) { /* skip code: 0x80..0xBF */
237 /* codes 0x80 and 0x81 are actually escape codes,
238 skip value minus constant is in the next byte */
240 skip
= bytestream2_get_byte(&qctx
->buffer
) + 64;
242 skip
= bytestream2_get_byte(&qctx
->buffer
) + 320;
246 while( filled
>= width
) {
254 /* zero code treated as one-pixel skip */
256 dst
[filled
++] = ctable
[code
& 0x7F];
260 if(filled
>= width
) {
269 static int decode_frame(AVCodecContext
*avctx
, AVFrame
*p
,
270 int *got_frame
, AVPacket
*avpkt
)
273 QpegContext
* const a
= avctx
->priv_data
;
274 AVFrame
* const ref
= a
->ref
;
276 int delta
, intra
, ret
;
278 if (avpkt
->size
< 0x86) {
279 av_log(avctx
, AV_LOG_ERROR
, "Packet is too small\n");
280 return AVERROR_INVALIDDATA
;
283 bytestream2_init(&a
->buffer
, avpkt
->data
, avpkt
->size
);
285 if ((ret
= ff_get_buffer(avctx
, p
, AV_GET_BUFFER_FLAG_REF
)) < 0)
287 outdata
= p
->data
[0];
288 bytestream2_skip(&a
->buffer
, 4);
289 bytestream2_get_buffer(&a
->buffer
, ctable
, 128);
290 bytestream2_skip(&a
->buffer
, 1);
292 delta
= bytestream2_get_byte(&a
->buffer
);
293 intra
= delta
== 0x10;
295 qpeg_decode_intra(a
, outdata
, p
->linesize
[0], avctx
->width
, avctx
->height
);
297 qpeg_decode_inter(a
, outdata
, p
->linesize
[0], avctx
->width
, avctx
->height
, delta
, ctable
, ref
->data
[0]);
300 /* make the palette available on the way out */
301 p
->palette_has_changed
= ff_copy_palette(a
->pal
, avpkt
, avctx
);
302 memcpy(p
->data
[1], a
->pal
, AVPALETTE_SIZE
);
305 if ((ret
= av_frame_ref(ref
, p
)) < 0)
308 p
->key_frame
= intra
;
309 p
->pict_type
= intra
? AV_PICTURE_TYPE_I
: AV_PICTURE_TYPE_P
;
316 static void decode_flush(AVCodecContext
*avctx
){
317 QpegContext
* const a
= avctx
->priv_data
;
319 const uint8_t *pal_src
;
321 av_frame_unref(a
->ref
);
323 pal_size
= FFMIN(1024U, avctx
->extradata_size
);
324 pal_src
= avctx
->extradata
+ avctx
->extradata_size
- pal_size
;
326 for (i
=0; i
<pal_size
/4; i
++)
327 a
->pal
[i
] = 0xFFU
<<24 | AV_RL32(pal_src
+4*i
);
330 static av_cold
int decode_end(AVCodecContext
*avctx
)
332 QpegContext
* const a
= avctx
->priv_data
;
334 av_frame_free(&a
->ref
);
339 static av_cold
int decode_init(AVCodecContext
*avctx
){
340 QpegContext
* const a
= avctx
->priv_data
;
343 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
345 a
->ref
= av_frame_alloc();
347 return AVERROR(ENOMEM
);
354 const FFCodec ff_qpeg_decoder
= {
356 .p
.long_name
= NULL_IF_CONFIG_SMALL("Q-team QPEG"),
357 .p
.type
= AVMEDIA_TYPE_VIDEO
,
358 .p
.id
= AV_CODEC_ID_QPEG
,
359 .priv_data_size
= sizeof(QpegContext
),
362 FF_CODEC_DECODE_CB(decode_frame
),
363 .flush
= decode_flush
,
364 .p
.capabilities
= AV_CODEC_CAP_DR1
,
365 .caps_internal
= FF_CODEC_CAP_INIT_THREADSAFE
|
366 FF_CODEC_CAP_INIT_CLEANUP
,