00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/avassert.h"
00023 #include "libavutil/channel_layout.h"
00024 #include "avcodec.h"
00025 #include "bytestream.h"
00026 #include "internal.h"
00027
00028 enum BMVFlags{
00029 BMV_NOP = 0,
00030 BMV_END,
00031 BMV_DELTA,
00032 BMV_INTRA,
00033
00034 BMV_SCROLL = 0x04,
00035 BMV_PALETTE = 0x08,
00036 BMV_COMMAND = 0x10,
00037 BMV_AUDIO = 0x20,
00038 BMV_EXT = 0x40,
00039 BMV_PRINT = 0x80
00040 };
00041
00042 #define SCREEN_WIDE 640
00043 #define SCREEN_HIGH 429
00044
00045 typedef struct BMVDecContext {
00046 AVCodecContext *avctx;
00047 AVFrame pic;
00048
00049 uint8_t *frame, frame_base[SCREEN_WIDE * (SCREEN_HIGH + 1)];
00050 uint32_t pal[256];
00051 const uint8_t *stream;
00052 } BMVDecContext;
00053
00054 #define NEXT_BYTE(v) v = forward ? v + 1 : v - 1;
00055
00056 static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, int frame_off)
00057 {
00058 unsigned val, saved_val = 0;
00059 int tmplen = src_len;
00060 const uint8_t *src, *source_end = source + src_len;
00061 uint8_t *frame_end = frame + SCREEN_WIDE * SCREEN_HIGH;
00062 uint8_t *dst, *dst_end;
00063 int len, mask;
00064 int forward = (frame_off <= -SCREEN_WIDE) || (frame_off >= 0);
00065 int read_two_nibbles, flag;
00066 int advance_mode;
00067 int mode = 0;
00068 int i;
00069
00070 if (src_len <= 0)
00071 return -1;
00072
00073 if (forward) {
00074 src = source;
00075 dst = frame;
00076 dst_end = frame_end;
00077 } else {
00078 src = source + src_len - 1;
00079 dst = frame_end - 1;
00080 dst_end = frame - 1;
00081 }
00082 for (;;) {
00083 int shift = 0;
00084 flag = 0;
00085
00086
00087
00088
00089
00090
00091
00092
00093 if (!mode || (tmplen == 4)) {
00094 if (src < source || src >= source_end)
00095 return -1;
00096 val = *src;
00097 read_two_nibbles = 1;
00098 } else {
00099 val = saved_val;
00100 read_two_nibbles = 0;
00101 }
00102 if (!(val & 0xC)) {
00103 for (;;) {
00104 if(shift>22)
00105 return -1;
00106 if (!read_two_nibbles) {
00107 if (src < source || src >= source_end)
00108 return -1;
00109 shift += 2;
00110 val |= *src << shift;
00111 if (*src & 0xC)
00112 break;
00113 }
00114
00115
00116 read_two_nibbles = 0;
00117 shift += 2;
00118 mask = (1 << shift) - 1;
00119 val = ((val >> 2) & ~mask) | (val & mask);
00120 NEXT_BYTE(src);
00121 if ((val & (0xC << shift))) {
00122 flag = 1;
00123 break;
00124 }
00125 }
00126 } else if (mode) {
00127 flag = tmplen != 4;
00128 }
00129 if (flag) {
00130 tmplen = 4;
00131 } else {
00132 saved_val = val >> (4 + shift);
00133 tmplen = 0;
00134 val &= (1 << (shift + 4)) - 1;
00135 NEXT_BYTE(src);
00136 }
00137 advance_mode = val & 1;
00138 len = (val >> 1) - 1;
00139 av_assert0(len>0);
00140 mode += 1 + advance_mode;
00141 if (mode >= 4)
00142 mode -= 3;
00143 if (FFABS(dst_end - dst) < len)
00144 return -1;
00145 switch (mode) {
00146 case 1:
00147 if (forward) {
00148 if (dst - frame + SCREEN_WIDE < frame_off ||
00149 dst - frame + SCREEN_WIDE + frame_off < 0 ||
00150 frame_end - dst < frame_off + len ||
00151 frame_end - dst < len)
00152 return -1;
00153 for (i = 0; i < len; i++)
00154 dst[i] = dst[frame_off + i];
00155 dst += len;
00156 } else {
00157 dst -= len;
00158 if (dst - frame + SCREEN_WIDE < frame_off ||
00159 dst - frame + SCREEN_WIDE + frame_off < 0 ||
00160 frame_end - dst < frame_off + len ||
00161 frame_end - dst < len)
00162 return -1;
00163 for (i = len - 1; i >= 0; i--)
00164 dst[i] = dst[frame_off + i];
00165 }
00166 break;
00167 case 2:
00168 if (forward) {
00169 if (source + src_len - src < len)
00170 return -1;
00171 memcpy(dst, src, len);
00172 dst += len;
00173 src += len;
00174 } else {
00175 if (src - source < len)
00176 return -1;
00177 dst -= len;
00178 src -= len;
00179 memcpy(dst, src, len);
00180 }
00181 break;
00182 case 3:
00183 val = forward ? dst[-1] : dst[1];
00184 if (forward) {
00185 memset(dst, val, len);
00186 dst += len;
00187 } else {
00188 dst -= len;
00189 memset(dst, val, len);
00190 }
00191 break;
00192 }
00193 if (dst == dst_end)
00194 return 0;
00195 }
00196 return 0;
00197 }
00198
00199 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
00200 AVPacket *pkt)
00201 {
00202 BMVDecContext * const c = avctx->priv_data;
00203 int type, scr_off;
00204 int i, ret;
00205 uint8_t *srcptr, *outptr;
00206
00207 c->stream = pkt->data;
00208 type = bytestream_get_byte(&c->stream);
00209 if (type & BMV_AUDIO) {
00210 int blobs = bytestream_get_byte(&c->stream);
00211 if (pkt->size < blobs * 65 + 2) {
00212 av_log(avctx, AV_LOG_ERROR, "Audio data doesn't fit in frame\n");
00213 return AVERROR_INVALIDDATA;
00214 }
00215 c->stream += blobs * 65;
00216 }
00217 if (type & BMV_COMMAND) {
00218 int command_size = (type & BMV_PRINT) ? 8 : 10;
00219 if (c->stream - pkt->data + command_size > pkt->size) {
00220 av_log(avctx, AV_LOG_ERROR, "Command data doesn't fit in frame\n");
00221 return AVERROR_INVALIDDATA;
00222 }
00223 c->stream += command_size;
00224 }
00225 if (type & BMV_PALETTE) {
00226 if (c->stream - pkt->data > pkt->size - 768) {
00227 av_log(avctx, AV_LOG_ERROR, "Palette data doesn't fit in frame\n");
00228 return AVERROR_INVALIDDATA;
00229 }
00230 for (i = 0; i < 256; i++)
00231 c->pal[i] = 0xFFU << 24 | bytestream_get_be24(&c->stream);
00232 }
00233 if (type & BMV_SCROLL) {
00234 if (c->stream - pkt->data > pkt->size - 2) {
00235 av_log(avctx, AV_LOG_ERROR, "Screen offset data doesn't fit in frame\n");
00236 return AVERROR_INVALIDDATA;
00237 }
00238 scr_off = (int16_t)bytestream_get_le16(&c->stream);
00239 } else if ((type & BMV_INTRA) == BMV_INTRA) {
00240 scr_off = -640;
00241 } else {
00242 scr_off = 0;
00243 }
00244
00245 if (c->pic.data[0])
00246 avctx->release_buffer(avctx, &c->pic);
00247
00248 c->pic.reference = 3;
00249 if ((ret = ff_get_buffer(avctx, &c->pic)) < 0) {
00250 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00251 return ret;
00252 }
00253
00254 if (decode_bmv_frame(c->stream, pkt->size - (c->stream - pkt->data), c->frame, scr_off)) {
00255 av_log(avctx, AV_LOG_ERROR, "Error decoding frame data\n");
00256 return AVERROR_INVALIDDATA;
00257 }
00258
00259 memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
00260 c->pic.palette_has_changed = type & BMV_PALETTE;
00261
00262 outptr = c->pic.data[0];
00263 srcptr = c->frame;
00264
00265 for (i = 0; i < avctx->height; i++) {
00266 memcpy(outptr, srcptr, avctx->width);
00267 srcptr += avctx->width;
00268 outptr += c->pic.linesize[0];
00269 }
00270
00271 *got_frame = 1;
00272 *(AVFrame*)data = c->pic;
00273
00274
00275 return pkt->size;
00276 }
00277
00278 static av_cold int decode_init(AVCodecContext *avctx)
00279 {
00280 BMVDecContext * const c = avctx->priv_data;
00281
00282 c->avctx = avctx;
00283 avctx->pix_fmt = AV_PIX_FMT_PAL8;
00284
00285 if (avctx->width != SCREEN_WIDE || avctx->height != SCREEN_HIGH) {
00286 av_log(avctx, AV_LOG_ERROR, "Invalid dimension %dx%d\n", avctx->width, avctx->height);
00287 return AVERROR_INVALIDDATA;
00288 }
00289
00290 c->frame = c->frame_base + 640;
00291
00292 return 0;
00293 }
00294
00295 static av_cold int decode_end(AVCodecContext *avctx)
00296 {
00297 BMVDecContext *c = avctx->priv_data;
00298
00299 if (c->pic.data[0])
00300 avctx->release_buffer(avctx, &c->pic);
00301
00302 return 0;
00303 }
00304
00305 typedef struct BMVAudioDecContext {
00306 AVFrame frame;
00307 } BMVAudioDecContext;
00308
00309 static const int bmv_aud_mults[16] = {
00310 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32
00311 };
00312
00313 static av_cold int bmv_aud_decode_init(AVCodecContext *avctx)
00314 {
00315 BMVAudioDecContext *c = avctx->priv_data;
00316
00317 avctx->channels = 2;
00318 avctx->channel_layout = AV_CH_LAYOUT_STEREO;
00319 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
00320
00321 avcodec_get_frame_defaults(&c->frame);
00322 avctx->coded_frame = &c->frame;
00323
00324 return 0;
00325 }
00326
00327 static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data,
00328 int *got_frame_ptr, AVPacket *avpkt)
00329 {
00330 BMVAudioDecContext *c = avctx->priv_data;
00331 const uint8_t *buf = avpkt->data;
00332 int buf_size = avpkt->size;
00333 int blocks = 0, total_blocks, i;
00334 int ret;
00335 int16_t *output_samples;
00336 int scale[2];
00337
00338 total_blocks = *buf++;
00339 if (buf_size < total_blocks * 65 + 1) {
00340 av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n",
00341 total_blocks * 65 + 1, buf_size);
00342 return AVERROR_INVALIDDATA;
00343 }
00344
00345
00346 c->frame.nb_samples = total_blocks * 32;
00347 if ((ret = ff_get_buffer(avctx, &c->frame)) < 0) {
00348 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00349 return ret;
00350 }
00351 output_samples = (int16_t *)c->frame.data[0];
00352
00353 for (blocks = 0; blocks < total_blocks; blocks++) {
00354 uint8_t code = *buf++;
00355 code = (code >> 1) | (code << 7);
00356 scale[0] = bmv_aud_mults[code & 0xF];
00357 scale[1] = bmv_aud_mults[code >> 4];
00358 for (i = 0; i < 32; i++) {
00359 *output_samples++ = av_clip_int16((scale[0] * (int8_t)*buf++) >> 5);
00360 *output_samples++ = av_clip_int16((scale[1] * (int8_t)*buf++) >> 5);
00361 }
00362 }
00363
00364 *got_frame_ptr = 1;
00365 *(AVFrame *)data = c->frame;
00366
00367 return buf_size;
00368 }
00369
00370 AVCodec ff_bmv_video_decoder = {
00371 .name = "bmv_video",
00372 .type = AVMEDIA_TYPE_VIDEO,
00373 .id = AV_CODEC_ID_BMV_VIDEO,
00374 .priv_data_size = sizeof(BMVDecContext),
00375 .init = decode_init,
00376 .close = decode_end,
00377 .decode = decode_frame,
00378 .capabilities = CODEC_CAP_DR1,
00379 .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"),
00380 };
00381
00382 AVCodec ff_bmv_audio_decoder = {
00383 .name = "bmv_audio",
00384 .type = AVMEDIA_TYPE_AUDIO,
00385 .id = AV_CODEC_ID_BMV_AUDIO,
00386 .priv_data_size = sizeof(BMVAudioDecContext),
00387 .init = bmv_aud_decode_init,
00388 .decode = bmv_aud_decode_frame,
00389 .capabilities = CODEC_CAP_DR1,
00390 .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"),
00391 };