X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmmvideo.c;h=60e00fbe29052ea8082acf0dcd0470bf4bf4b2c0;hb=b7ec5cc4013242a9f30c429d2ce9c20ec01b03eb;hp=e23b664d6259f2cb99c0b31f291a689ae931d33c;hpb=fe4bf37455e81ecf2c0b769c979bdf6eec785602;p=ffmpeg diff --git a/libavcodec/mmvideo.c b/libavcodec/mmvideo.c index e23b664d625..60e00fbe290 100644 --- a/libavcodec/mmvideo.c +++ b/libavcodec/mmvideo.c @@ -1,6 +1,6 @@ /* * American Laser Games MM Video Decoder - * Copyright (c) 2006 Peter Ross + * Copyright (c) 2006,2008 Peter Ross * * This file is part of FFmpeg. * @@ -20,9 +20,9 @@ */ /** - * @file mm.c + * @file * American Laser Games MM Video Decoder - * by Peter Ross (suxen_drol at hotmail dot com) + * by Peter Ross (pross@xvid.org) * * The MM format was used by IBM-PC ports of ALG's "arcade shooter" games, * including Mad Dog McCree and Crime Patrol. @@ -31,6 +31,7 @@ * http://wiki.multimedia.cx/index.php?title=American_Laser_Games_MM */ +#include "libavutil/intreadwrite.h" #include "avcodec.h" #define MM_PREAMBLE_SIZE 6 @@ -41,10 +42,12 @@ #define MM_TYPE_INTER_HH 0xd #define MM_TYPE_INTRA_HHV 0xe #define MM_TYPE_INTER_HHV 0xf +#define MM_TYPE_PALETTE 0x31 typedef struct MmContext { AVCodecContext *avctx; AVFrame frame; + int palette[AVPALETTE_COUNT]; } MmContext; static av_cold int mm_decode_init(AVCodecContext *avctx) @@ -53,25 +56,32 @@ static av_cold int mm_decode_init(AVCodecContext *avctx) s->avctx = avctx; - if (s->avctx->palctrl == NULL) { - av_log(avctx, AV_LOG_ERROR, "mmvideo: palette expected.\n"); - return -1; - } - avctx->pix_fmt = PIX_FMT_PAL8; - if (avcodec_check_dimensions(avctx, avctx->width, avctx->height)) - return -1; - s->frame.reference = 1; if (avctx->get_buffer(avctx, &s->frame)) { - av_log(s->avctx, AV_LOG_ERROR, "mmvideo: get_buffer() failed\n"); + av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } return 0; } +static void mm_decode_pal(MmContext *s, const uint8_t *buf, const uint8_t *buf_end) +{ + int i; + buf += 4; + for (i=0; i<128 && buf+2palette[i] = AV_RB24(buf); + s->palette[i+128] = s->palette[i]<<2; + buf += 3; + } +} + +/** + * @param half_horiz Half horizontal resolution (0 or 1) + * @param half_vert Half vertical resolution (0 or 1) + */ static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size) { int i, x, y; @@ -80,6 +90,9 @@ static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const while(i= s->avctx->height) + return; + if (buf[i] & 0x80) { run_length = 1; color = buf[i]; @@ -102,11 +115,15 @@ static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const if (x >= s->avctx->width) { x=0; - y += half_vert ? 2 : 1; + y += 1 + half_vert; } } } +/* + * @param half_horiz Half horizontal resolution (0 or 1) + * @param half_vert Half vertical resolution (0 or 1) + */ static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size) { const int data_ptr = 2 + AV_RL16(&buf[0]); @@ -124,6 +141,9 @@ static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const continue; } + if (y + half_vert >= s->avctx->height) + return; + for(i=0; i> (7-j)) & 1; @@ -139,33 +159,31 @@ static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const } d++; } - x += half_horiz ? 2 : 1; + x += 1 + half_horiz; } } r += length; - y += half_vert ? 2 : 1; + y += 1 + half_vert; } } static int mm_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - const uint8_t *buf, int buf_size) + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; MmContext *s = avctx->priv_data; - AVPaletteControl *palette_control = avctx->palctrl; + const uint8_t *buf_end = buf+buf_size; int type; - if (palette_control->palette_changed) { - memcpy(s->frame.data[1], palette_control->palette, AVPALETTE_SIZE); - palette_control->palette_changed = 0; - } - type = AV_RL16(&buf[0]); buf += MM_PREAMBLE_SIZE; buf_size -= MM_PREAMBLE_SIZE; switch(type) { + case MM_TYPE_PALETTE : mm_decode_pal(s, buf, buf_end); return buf_size; case MM_TYPE_INTRA : mm_decode_intra(s, 0, 0, buf, buf_size); break; case MM_TYPE_INTRA_HH : mm_decode_intra(s, 1, 0, buf, buf_size); break; case MM_TYPE_INTRA_HHV : mm_decode_intra(s, 1, 1, buf, buf_size); break; @@ -176,6 +194,8 @@ static int mm_decode_frame(AVCodecContext *avctx, return -1; } + memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); + *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; @@ -192,9 +212,9 @@ static av_cold int mm_decode_end(AVCodecContext *avctx) return 0; } -AVCodec mmvideo_decoder = { +AVCodec ff_mmvideo_decoder = { "mmvideo", - CODEC_TYPE_VIDEO, + AVMEDIA_TYPE_VIDEO, CODEC_ID_MMVIDEO, sizeof(MmContext), mm_decode_init,