2 * Discworld II BMV video and audio decoder
3 * Copyright (c) 2011 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
22 #include "libavutil/channel_layout.h"
24 #include "bytestream.h"
41 #define SCREEN_WIDE 640
42 #define SCREEN_HIGH 429
44 typedef struct BMVDecContext
{
45 AVCodecContext
*avctx
;
48 uint8_t *frame
, frame_base
[SCREEN_WIDE
* (SCREEN_HIGH
+ 1)];
50 const uint8_t *stream
;
53 #define NEXT_BYTE(v) v = forward ? v + 1 : v - 1;
55 static int decode_bmv_frame(const uint8_t *source
, int src_len
, uint8_t *frame
, int frame_off
)
57 unsigned val
, saved_val
= 0;
59 const uint8_t *src
, *source_end
= source
+ src_len
;
60 uint8_t *frame_end
= frame
+ SCREEN_WIDE
* SCREEN_HIGH
;
61 uint8_t *dst
, *dst_end
;
63 int forward
= (frame_off
<= -SCREEN_WIDE
) || (frame_off
>= 0);
64 int read_two_nibbles
, flag
;
77 src
= source
+ src_len
- 1;
85 /* The mode/len decoding is a bit strange:
86 * values are coded as variable-length codes with nibble units,
87 * code end is signalled by two top bits in the nibble being nonzero.
88 * And since data is bytepacked and we read two nibbles at a time,
89 * we may get a nibble belonging to the next code.
90 * Hence this convoluted loop.
92 if (!mode
|| (tmplen
== 4)) {
93 if (src
< source
|| src
>= source_end
)
103 if (!read_two_nibbles
) {
104 if (src
< source
|| src
>= source_end
)
107 val
|= *src
<< shift
;
111 // two upper bits of the nibble is zero,
112 // so shift top nibble value down into their place
113 read_two_nibbles
= 0;
115 mask
= (1 << shift
) - 1;
116 val
= ((val
>> 2) & ~mask
) | (val
& mask
);
118 if ((val
& (0xC << shift
))) {
129 saved_val
= val
>> (4 + shift
);
131 val
&= (1 << (shift
+ 4)) - 1;
134 advance_mode
= val
& 1;
135 len
= (val
>> 1) - 1;
136 mode
+= 1 + advance_mode
;
139 if (FFABS(dst_end
- dst
) < len
)
144 if (dst
- frame
+ SCREEN_WIDE
< frame_off
||
145 dst
- frame
+ SCREEN_WIDE
+ frame_off
< 0 ||
146 frame_end
- dst
< frame_off
+ len
||
147 frame_end
- dst
< len
)
149 for (i
= 0; i
< len
; i
++)
150 dst
[i
] = dst
[frame_off
+ i
];
154 if (dst
- frame
+ SCREEN_WIDE
< frame_off
||
155 dst
- frame
+ SCREEN_WIDE
+ frame_off
< 0 ||
156 frame_end
- dst
< frame_off
+ len
||
157 frame_end
- dst
< len
)
159 for (i
= len
- 1; i
>= 0; i
--)
160 dst
[i
] = dst
[frame_off
+ i
];
165 if (source
+ src_len
- src
< len
)
167 memcpy(dst
, src
, len
);
171 if (src
- source
< len
)
175 memcpy(dst
, src
, len
);
179 val
= forward ? dst
[-1] : dst
[1];
181 memset(dst
, val
, len
);
185 memset(dst
, val
, len
);
197 static int decode_frame(AVCodecContext
*avctx
, void *data
, int *data_size
, AVPacket
*pkt
)
199 BMVDecContext
* const c
= avctx
->priv_data
;
202 uint8_t *srcptr
, *outptr
;
204 c
->stream
= pkt
->data
;
205 type
= bytestream_get_byte(&c
->stream
);
206 if (type
& BMV_AUDIO
) {
207 int blobs
= bytestream_get_byte(&c
->stream
);
208 if (pkt
->size
< blobs
* 65 + 2) {
209 av_log(avctx
, AV_LOG_ERROR
, "Audio data doesn't fit in frame\n");
210 return AVERROR_INVALIDDATA
;
212 c
->stream
+= blobs
* 65;
214 if (type
& BMV_COMMAND
) {
215 int command_size
= (type
& BMV_PRINT
) ?
8 : 10;
216 if (c
->stream
- pkt
->data
+ command_size
> pkt
->size
) {
217 av_log(avctx
, AV_LOG_ERROR
, "Command data doesn't fit in frame\n");
218 return AVERROR_INVALIDDATA
;
220 c
->stream
+= command_size
;
222 if (type
& BMV_PALETTE
) {
223 if (c
->stream
- pkt
->data
> pkt
->size
- 768) {
224 av_log(avctx
, AV_LOG_ERROR
, "Palette data doesn't fit in frame\n");
225 return AVERROR_INVALIDDATA
;
227 for (i
= 0; i
< 256; i
++)
228 c
->pal
[i
] = bytestream_get_be24(&c
->stream
);
230 if (type
& BMV_SCROLL
) {
231 if (c
->stream
- pkt
->data
> pkt
->size
- 2) {
232 av_log(avctx
, AV_LOG_ERROR
, "Screen offset data doesn't fit in frame\n");
233 return AVERROR_INVALIDDATA
;
235 scr_off
= (int16_t)bytestream_get_le16(&c
->stream
);
236 } else if ((type
& BMV_INTRA
) == BMV_INTRA
) {
243 avctx
->release_buffer(avctx
, &c
->pic
);
245 c
->pic
.reference
= 3;
246 if ((ret
= ff_get_buffer(avctx
, &c
->pic
)) < 0) {
247 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
251 if (decode_bmv_frame(c
->stream
, pkt
->size
- (c
->stream
- pkt
->data
), c
->frame
, scr_off
)) {
252 av_log(avctx
, AV_LOG_ERROR
, "Error decoding frame data\n");
253 return AVERROR_INVALIDDATA
;
256 memcpy(c
->pic
.data
[1], c
->pal
, AVPALETTE_SIZE
);
257 c
->pic
.palette_has_changed
= type
& BMV_PALETTE
;
259 outptr
= c
->pic
.data
[0];
262 for (i
= 0; i
< avctx
->height
; i
++) {
263 memcpy(outptr
, srcptr
, avctx
->width
);
264 srcptr
+= avctx
->width
;
265 outptr
+= c
->pic
.linesize
[0];
268 *data_size
= sizeof(AVFrame
);
269 *(AVFrame
*)data
= c
->pic
;
271 /* always report that the buffer was completely consumed */
275 static av_cold
int decode_init(AVCodecContext
*avctx
)
277 BMVDecContext
* const c
= avctx
->priv_data
;
280 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
282 c
->frame
= c
->frame_base
+ 640;
287 static av_cold
int decode_end(AVCodecContext
*avctx
)
289 BMVDecContext
*c
= avctx
->priv_data
;
292 avctx
->release_buffer(avctx
, &c
->pic
);
297 typedef struct BMVAudioDecContext
{
299 } BMVAudioDecContext
;
301 static const int bmv_aud_mults
[16] = {
302 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32
305 static av_cold
int bmv_aud_decode_init(AVCodecContext
*avctx
)
307 BMVAudioDecContext
*c
= avctx
->priv_data
;
310 avctx
->channel_layout
= AV_CH_LAYOUT_STEREO
;
311 avctx
->sample_fmt
= AV_SAMPLE_FMT_S16
;
313 avcodec_get_frame_defaults(&c
->frame
);
314 avctx
->coded_frame
= &c
->frame
;
319 static int bmv_aud_decode_frame(AVCodecContext
*avctx
, void *data
,
320 int *got_frame_ptr
, AVPacket
*avpkt
)
322 BMVAudioDecContext
*c
= avctx
->priv_data
;
323 const uint8_t *buf
= avpkt
->data
;
324 int buf_size
= avpkt
->size
;
325 int blocks
= 0, total_blocks
, i
;
327 int16_t *output_samples
;
330 total_blocks
= *buf
++;
331 if (buf_size
< total_blocks
* 65 + 1) {
332 av_log(avctx
, AV_LOG_ERROR
, "expected %d bytes, got %d\n",
333 total_blocks
* 65 + 1, buf_size
);
334 return AVERROR_INVALIDDATA
;
337 /* get output buffer */
338 c
->frame
.nb_samples
= total_blocks
* 32;
339 if ((ret
= ff_get_buffer(avctx
, &c
->frame
)) < 0) {
340 av_log(avctx
, AV_LOG_ERROR
, "get_buffer() failed\n");
343 output_samples
= (int16_t *)c
->frame
.data
[0];
345 for (blocks
= 0; blocks
< total_blocks
; blocks
++) {
346 uint8_t code
= *buf
++;
347 code
= (code
>> 1) | (code
<< 7);
348 scale
[0] = bmv_aud_mults
[code
& 0xF];
349 scale
[1] = bmv_aud_mults
[code
>> 4];
350 for (i
= 0; i
< 32; i
++) {
351 *output_samples
++ = av_clip_int16((scale
[0] * (int8_t)*buf
++) >> 5);
352 *output_samples
++ = av_clip_int16((scale
[1] * (int8_t)*buf
++) >> 5);
357 *(AVFrame
*)data
= c
->frame
;
362 AVCodec ff_bmv_video_decoder
= {
364 .type
= AVMEDIA_TYPE_VIDEO
,
365 .id
= AV_CODEC_ID_BMV_VIDEO
,
366 .priv_data_size
= sizeof(BMVDecContext
),
369 .decode
= decode_frame
,
370 .capabilities
= CODEC_CAP_DR1
,
371 .long_name
= NULL_IF_CONFIG_SMALL("Discworld II BMV video"),
374 AVCodec ff_bmv_audio_decoder
= {
376 .type
= AVMEDIA_TYPE_AUDIO
,
377 .id
= AV_CODEC_ID_BMV_AUDIO
,
378 .priv_data_size
= sizeof(BMVAudioDecContext
),
379 .init
= bmv_aud_decode_init
,
380 .decode
= bmv_aud_decode_frame
,
381 .capabilities
= CODEC_CAP_DR1
,
382 .long_name
= NULL_IF_CONFIG_SMALL("Discworld II BMV audio"),