2 * Interplay C93 video decoder
3 * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
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
23 #include "bytestream.h"
26 typedef struct C93DecoderContext
{
32 C93_8X8_FROM_PREV
= 0x02,
33 C93_4X4_FROM_PREV
= 0x06,
34 C93_4X4_FROM_CURR
= 0x07,
35 C93_8X8_2COLOR
= 0x08,
36 C93_4X4_2COLOR
= 0x0A,
37 C93_4X4_4COLOR_GRP
= 0x0B,
38 C93_4X4_4COLOR
= 0x0D,
46 #define C93_HAS_PALETTE 0x01
47 #define C93_FIRST_FRAME 0x02
49 static av_cold
int decode_end(AVCodecContext
*avctx
)
51 C93DecoderContext
* const c93
= avctx
->priv_data
;
53 av_frame_free(&c93
->pictures
[0]);
54 av_frame_free(&c93
->pictures
[1]);
59 static av_cold
int decode_init(AVCodecContext
*avctx
)
61 C93DecoderContext
*s
= avctx
->priv_data
;
62 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
64 s
->pictures
[0] = av_frame_alloc();
65 s
->pictures
[1] = av_frame_alloc();
66 if (!s
->pictures
[0] || !s
->pictures
[1]) {
68 return AVERROR(ENOMEM
);
74 static inline int copy_block(AVCodecContext
*avctx
, uint8_t *to
,
75 uint8_t *from
, int offset
, int height
, int stride
)
79 int from_x
= offset
% WIDTH
;
80 int from_y
= offset
/ WIDTH
;
81 int overflow
= from_x
+ width
- WIDTH
;
84 /* silently ignoring predictive blocks in first frame */
88 if (from_y
+ height
> HEIGHT
) {
89 av_log(avctx
, AV_LOG_ERROR
, "invalid offset %d during C93 decoding\n",
91 return AVERROR_INVALIDDATA
;
96 for (i
= 0; i
< height
; i
++) {
97 memcpy(&to
[i
*stride
+width
], &from
[(from_y
+i
)*stride
], overflow
);
101 for (i
= 0; i
< height
; i
++) {
102 memcpy(&to
[i
*stride
], &from
[(from_y
+i
)*stride
+from_x
], width
);
108 static inline void draw_n_color(uint8_t *out
, int stride
, int width
,
109 int height
, int bpp
, uint8_t cols
[4], uint8_t grps
[4], uint32_t col
)
112 for (y
= 0; y
< height
; y
++) {
114 cols
[0] = grps
[3 * (y
>> 1)];
115 for (x
= 0; x
< width
; x
++) {
117 cols
[1]= grps
[(x
>> 1) + 1];
118 out
[x
+ y
*stride
] = cols
[col
& ((1 << bpp
) - 1)];
124 static int decode_frame(AVCodecContext
*avctx
, void *data
,
125 int *got_frame
, AVPacket
*avpkt
)
127 const uint8_t *buf
= avpkt
->data
;
128 int buf_size
= avpkt
->size
;
129 C93DecoderContext
* const c93
= avctx
->priv_data
;
130 AVFrame
* const newpic
= c93
->pictures
[c93
->currentpic
];
131 AVFrame
* const oldpic
= c93
->pictures
[c93
->currentpic
^1];
134 int stride
, ret
, i
, x
, y
, b
, bt
= 0;
136 c93
->currentpic
^= 1;
138 if ((ret
= ff_reget_buffer(avctx
, newpic
)) < 0) {
139 av_log(avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
143 stride
= newpic
->linesize
[0];
145 bytestream2_init(&gb
, buf
, buf_size
);
146 b
= bytestream2_get_byte(&gb
);
147 if (b
& C93_FIRST_FRAME
) {
148 newpic
->pict_type
= AV_PICTURE_TYPE_I
;
149 newpic
->key_frame
= 1;
151 newpic
->pict_type
= AV_PICTURE_TYPE_P
;
152 newpic
->key_frame
= 0;
155 for (y
= 0; y
< HEIGHT
; y
+= 8) {
156 out
= newpic
->data
[0] + y
* stride
;
157 for (x
= 0; x
< WIDTH
; x
+= 8) {
158 uint8_t *copy_from
= oldpic
->data
[0];
159 unsigned int offset
, j
;
160 uint8_t cols
[4], grps
[4];
161 C93BlockType block_type
;
164 bt
= bytestream2_get_byte(&gb
);
166 block_type
= bt
& 0x0F;
167 switch (block_type
) {
168 case C93_8X8_FROM_PREV
:
169 offset
= bytestream2_get_le16(&gb
);
170 if ((ret
= copy_block(avctx
, out
, copy_from
, offset
, 8, stride
)) < 0)
174 case C93_4X4_FROM_CURR
:
175 copy_from
= newpic
->data
[0];
176 case C93_4X4_FROM_PREV
:
177 for (j
= 0; j
< 8; j
+= 4) {
178 for (i
= 0; i
< 8; i
+= 4) {
179 offset
= bytestream2_get_le16(&gb
);
180 if ((ret
= copy_block(avctx
, &out
[j
*stride
+i
],
181 copy_from
, offset
, 4, stride
)) < 0)
188 bytestream2_get_buffer(&gb
, cols
, 2);
189 for (i
= 0; i
< 8; i
++) {
190 draw_n_color(out
+ i
*stride
, stride
, 8, 1, 1, cols
,
191 NULL
, bytestream2_get_byte(&gb
));
198 case C93_4X4_4COLOR_GRP
:
199 for (j
= 0; j
< 8; j
+= 4) {
200 for (i
= 0; i
< 8; i
+= 4) {
201 if (block_type
== C93_4X4_2COLOR
) {
202 bytestream2_get_buffer(&gb
, cols
, 2);
203 draw_n_color(out
+ i
+ j
*stride
, stride
, 4, 4,
204 1, cols
, NULL
, bytestream2_get_le16(&gb
));
205 } else if (block_type
== C93_4X4_4COLOR
) {
206 bytestream2_get_buffer(&gb
, cols
, 4);
207 draw_n_color(out
+ i
+ j
*stride
, stride
, 4, 4,
208 2, cols
, NULL
, bytestream2_get_le32(&gb
));
210 bytestream2_get_buffer(&gb
, grps
, 4);
211 draw_n_color(out
+ i
+ j
*stride
, stride
, 4, 4,
212 1, cols
, grps
, bytestream2_get_le16(&gb
));
222 for (j
= 0; j
< 8; j
++)
223 bytestream2_get_buffer(&gb
, out
+ j
*stride
, 8);
227 av_log(avctx
, AV_LOG_ERROR
, "unexpected type %x at %dx%d\n",
229 return AVERROR_INVALIDDATA
;
236 if (b
& C93_HAS_PALETTE
) {
237 uint32_t *palette
= (uint32_t *) newpic
->data
[1];
238 for (i
= 0; i
< 256; i
++) {
239 palette
[i
] = bytestream2_get_be24(&gb
);
241 newpic
->palette_has_changed
= 1;
244 memcpy(newpic
->data
[1], oldpic
->data
[1], 256 * 4);
247 if ((ret
= av_frame_ref(data
, newpic
)) < 0)
254 AVCodec ff_c93_decoder
= {
256 .long_name
= NULL_IF_CONFIG_SMALL("Interplay C93"),
257 .type
= AVMEDIA_TYPE_VIDEO
,
258 .id
= AV_CODEC_ID_C93
,
259 .priv_data_size
= sizeof(C93DecoderContext
),
262 .decode
= decode_frame
,
263 .capabilities
= AV_CODEC_CAP_DR1
,
264 .caps_internal
= FF_CODEC_CAP_INIT_THREADSAFE
,