2 * Electronic Arts TGV Video Decoder
3 * Copyright (c) 2007-2008 Peter Ross
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 St, Fifth Floor, Boston, MA 02110-1301 USA
24 * Electronic Arts TGV Video Decoder
25 * by Peter Ross (pross@xvid.org)
27 * Technical details here:
28 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV
32 #define BITSTREAM_READER_LE
35 #include "libavutil/imgutils.h"
36 #include "libavutil/mem.h"
38 #define EA_PREAMBLE_SIZE 8
39 #define kVGT_TAG MKTAG('k', 'V', 'G', 'T')
41 typedef struct TgvContext
{
42 AVCodecContext
*avctx
;
44 uint8_t *frame_buffer
;
46 uint32_t palette
[AVPALETTE_COUNT
];
48 int (*mv_codebook
)[2];
49 uint8_t (*block_codebook
)[16];
50 int num_mvs
; ///< current length of mv_codebook
51 int num_blocks_packed
; ///< current length of block_codebook
54 static av_cold
int tgv_decode_init(AVCodecContext
*avctx
)
56 TgvContext
*s
= avctx
->priv_data
;
58 avctx
->framerate
= (AVRational
){ 15, 1 };
59 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
61 s
->last_frame
= av_frame_alloc();
63 return AVERROR(ENOMEM
);
70 * @return 0 on success, -1 on critical buffer underflow
72 static int unpack(const uint8_t *src
, const uint8_t *src_end
,
73 uint8_t *dst
, int width
, int height
)
75 uint8_t *dst_end
= dst
+ width
*height
;
76 int size
, size1
, size2
, offset
, run
;
77 uint8_t *dst_start
= dst
;
84 if (src_end
- src
< 3)
85 return AVERROR_INVALIDDATA
;
89 while (size
> 0 && src
< src_end
) {
91 /* determine size1 and size2 */
93 if (src
[0] & 0x80) { // 1
94 if (src
[0] & 0x40 ) { // 11
95 if (src
[0] & 0x20) { // 111
96 if (src
[0] < 0xFC) // !(111111)
97 size1
= (((src
[0] & 31) + 1) << 2);
101 offset
= ((src
[0] & 0x10) << 12) + AV_RB16(&src
[1]) + 1;
102 size2
= ((src
[0] & 0xC) << 6) + src
[3] + 5;
106 size1
= ((src
[1] & 0xC0) >> 6);
107 offset
= (AV_RB16(&src
[1]) & 0x3FFF) + 1;
108 size2
= (src
[0] & 0x3F) + 4;
112 offset
= ((src
[0] & 0x60) << 3) + src
[1] + 1;
113 size2
= ((src
[0] & 0x1C) >> 2) + 3;
118 /* fetch strip from src */
119 if (size1
> src_end
- src
)
124 run
= FFMIN(size1
, dst_end
- dst
);
125 memcpy(dst
, src
, run
);
131 if (dst
- dst_start
< offset
)
134 run
= FFMIN(size2
, dst_end
- dst
);
135 av_memcpy_backptr(dst
, offset
, run
);
145 * @return 0 on success, -1 on critical buffer underflow
147 static int tgv_decode_inter(TgvContext
*s
, AVFrame
*frame
,
148 const uint8_t *buf
, const uint8_t *buf_end
)
152 int num_blocks_packed
;
157 const uint8_t *blocks_raw
;
159 if(buf_end
- buf
< 12)
160 return AVERROR_INVALIDDATA
;
162 num_mvs
= AV_RL16(&buf
[0]);
163 num_blocks_raw
= AV_RL16(&buf
[2]);
164 num_blocks_packed
= AV_RL16(&buf
[4]);
165 vector_bits
= AV_RL16(&buf
[6]);
168 if (vector_bits
> MIN_CACHE_BITS
|| !vector_bits
) {
169 av_log(s
->avctx
, AV_LOG_ERROR
,
170 "Invalid value for motion vector bits: %d\n", vector_bits
);
171 return AVERROR_INVALIDDATA
;
174 /* allocate codebook buffers as necessary */
175 if (num_mvs
> s
->num_mvs
) {
176 if (av_reallocp_array(&s
->mv_codebook
, num_mvs
, sizeof(*s
->mv_codebook
))) {
178 return AVERROR(ENOMEM
);
180 s
->num_mvs
= num_mvs
;
183 if (num_blocks_packed
> s
->num_blocks_packed
) {
185 if ((err
= av_reallocp(&s
->block_codebook
, num_blocks_packed
* 16)) < 0) {
186 s
->num_blocks_packed
= 0;
189 s
->num_blocks_packed
= num_blocks_packed
;
192 /* read motion vectors */
193 mvbits
= (num_mvs
* 2 * 10 + 31) & ~31;
195 if (buf_end
- buf
< (mvbits
>>3) + 16*num_blocks_raw
+ 8*num_blocks_packed
)
196 return AVERROR_INVALIDDATA
;
198 init_get_bits(&gb
, buf
, mvbits
);
199 for (i
= 0; i
< num_mvs
; i
++) {
200 s
->mv_codebook
[i
][0] = get_sbits(&gb
, 10);
201 s
->mv_codebook
[i
][1] = get_sbits(&gb
, 10);
205 /* note ptr to uncompressed blocks */
207 buf
+= num_blocks_raw
* 16;
209 /* read compressed blocks */
210 init_get_bits(&gb
, buf
, (buf_end
- buf
) << 3);
211 for (i
= 0; i
< num_blocks_packed
; i
++) {
213 for (j
= 0; j
< 4; j
++)
214 tmp
[j
] = get_bits(&gb
, 8);
215 for (j
= 0; j
< 16; j
++)
216 s
->block_codebook
[i
][15-j
] = tmp
[get_bits(&gb
, 2)];
219 if (get_bits_left(&gb
) < vector_bits
*
220 (s
->avctx
->height
/ 4) * (s
->avctx
->width
/ 4))
221 return AVERROR_INVALIDDATA
;
223 /* read vectors and build frame */
224 for (y
= 0; y
< s
->avctx
->height
/ 4; y
++)
225 for (x
= 0; x
< s
->avctx
->width
/ 4; x
++) {
226 unsigned int vector
= get_bits(&gb
, vector_bits
);
230 if (vector
< num_mvs
) {
231 int mx
= x
* 4 + s
->mv_codebook
[vector
][0];
232 int my
= y
* 4 + s
->mv_codebook
[vector
][1];
234 if (mx
< 0 || mx
+ 4 > s
->avctx
->width
||
235 my
< 0 || my
+ 4 > s
->avctx
->height
) {
236 av_log(s
->avctx
, AV_LOG_ERROR
, "MV %d %d out of picture\n", mx
, my
);
240 src
= s
->last_frame
->data
[0] + mx
+ my
* s
->last_frame
->linesize
[0];
241 src_stride
= s
->last_frame
->linesize
[0];
243 int offset
= vector
- num_mvs
;
244 if (offset
< num_blocks_raw
)
245 src
= blocks_raw
+ 16*offset
;
246 else if (offset
- num_blocks_raw
< num_blocks_packed
)
247 src
= s
->block_codebook
[offset
- num_blocks_raw
];
253 for (j
= 0; j
< 4; j
++)
254 for (i
= 0; i
< 4; i
++)
255 frame
->data
[0][(y
* 4 + j
) * frame
->linesize
[0] + (x
* 4 + i
)] =
256 src
[j
* src_stride
+ i
];
262 static int tgv_decode_frame(AVCodecContext
*avctx
,
263 void *data
, int *got_frame
,
266 const uint8_t *buf
= avpkt
->data
;
267 int buf_size
= avpkt
->size
;
268 TgvContext
*s
= avctx
->priv_data
;
269 const uint8_t *buf_end
= buf
+ buf_size
;
270 AVFrame
*frame
= data
;
273 if (buf_end
- buf
< EA_PREAMBLE_SIZE
)
274 return AVERROR_INVALIDDATA
;
276 chunk_type
= AV_RL32(&buf
[0]);
277 buf
+= EA_PREAMBLE_SIZE
;
279 if (chunk_type
== kVGT_TAG
) {
281 if(buf_end
- buf
< 12) {
282 av_log(avctx
, AV_LOG_WARNING
, "truncated header\n");
283 return AVERROR_INVALIDDATA
;
286 s
->width
= AV_RL16(&buf
[0]);
287 s
->height
= AV_RL16(&buf
[2]);
288 if (s
->avctx
->width
!= s
->width
|| s
->avctx
->height
!= s
->height
) {
289 av_freep(&s
->frame_buffer
);
290 av_frame_unref(s
->last_frame
);
291 if ((ret
= ff_set_dimensions(s
->avctx
, s
->width
, s
->height
)) < 0)
295 pal_count
= AV_RL16(&buf
[6]);
297 for(i
= 0; i
< pal_count
&& i
< AVPALETTE_COUNT
&& buf_end
- buf
>= 3; i
++) {
298 s
->palette
[i
] = 0xFFU
<< 24 | AV_RB24(buf
);
303 if ((ret
= ff_get_buffer(avctx
, frame
, AV_GET_BUFFER_FLAG_REF
)) < 0)
306 memcpy(frame
->data
[1], s
->palette
, AVPALETTE_SIZE
);
308 if (chunk_type
== kVGT_TAG
) {
310 frame
->key_frame
= 1;
311 frame
->pict_type
= AV_PICTURE_TYPE_I
;
313 if (!s
->frame_buffer
&&
314 !(s
->frame_buffer
= av_mallocz(s
->width
* s
->height
)))
315 return AVERROR(ENOMEM
);
317 if (unpack(buf
, buf_end
, s
->frame_buffer
, s
->avctx
->width
, s
->avctx
->height
) < 0) {
318 av_log(avctx
, AV_LOG_WARNING
, "truncated intra frame\n");
319 return AVERROR_INVALIDDATA
;
321 for (y
= 0; y
< s
->height
; y
++)
322 memcpy(frame
->data
[0] + y
* frame
->linesize
[0],
323 s
->frame_buffer
+ y
* s
->width
,
326 if (!s
->last_frame
->data
[0]) {
327 av_log(avctx
, AV_LOG_WARNING
, "inter frame without corresponding intra frame\n");
330 frame
->key_frame
= 0;
331 frame
->pict_type
= AV_PICTURE_TYPE_P
;
332 if (tgv_decode_inter(s
, frame
, buf
, buf_end
) < 0) {
333 av_log(avctx
, AV_LOG_WARNING
, "truncated inter frame\n");
334 return AVERROR_INVALIDDATA
;
338 av_frame_unref(s
->last_frame
);
339 if ((ret
= av_frame_ref(s
->last_frame
, frame
)) < 0)
347 static av_cold
int tgv_decode_end(AVCodecContext
*avctx
)
349 TgvContext
*s
= avctx
->priv_data
;
350 av_frame_free(&s
->last_frame
);
351 av_freep(&s
->frame_buffer
);
352 av_freep(&s
->mv_codebook
);
353 av_freep(&s
->block_codebook
);
357 AVCodec ff_eatgv_decoder
= {
359 .long_name
= NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"),
360 .type
= AVMEDIA_TYPE_VIDEO
,
361 .id
= AV_CODEC_ID_TGV
,
362 .priv_data_size
= sizeof(TgvContext
),
363 .init
= tgv_decode_init
,
364 .close
= tgv_decode_end
,
365 .decode
= tgv_decode_frame
,
366 .capabilities
= CODEC_CAP_DR1
,