00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include "libavutil/intreadwrite.h"
00035 #include "avcodec.h"
00036 #include "bytestream.h"
00037
00038 #define MM_PREAMBLE_SIZE 6
00039
00040 #define MM_TYPE_INTER 0x5
00041 #define MM_TYPE_INTRA 0x8
00042 #define MM_TYPE_INTRA_HH 0xc
00043 #define MM_TYPE_INTER_HH 0xd
00044 #define MM_TYPE_INTRA_HHV 0xe
00045 #define MM_TYPE_INTER_HHV 0xf
00046 #define MM_TYPE_PALETTE 0x31
00047
00048 typedef struct MmContext {
00049 AVCodecContext *avctx;
00050 AVFrame frame;
00051 int palette[AVPALETTE_COUNT];
00052 GetByteContext gb;
00053 } MmContext;
00054
00055 static av_cold int mm_decode_init(AVCodecContext *avctx)
00056 {
00057 MmContext *s = avctx->priv_data;
00058
00059 s->avctx = avctx;
00060
00061 avctx->pix_fmt = PIX_FMT_PAL8;
00062
00063 avcodec_get_frame_defaults(&s->frame);
00064 s->frame.reference = 3;
00065
00066 return 0;
00067 }
00068
00069 static int mm_decode_pal(MmContext *s)
00070 {
00071 int i;
00072
00073 bytestream2_skip(&s->gb, 4);
00074 for (i = 0; i < 128; i++) {
00075 s->palette[i] = 0xFF << 24 | bytestream2_get_be24(&s->gb);
00076 s->palette[i+128] = s->palette[i]<<2;
00077 }
00078
00079 return 0;
00080 }
00081
00086 static int mm_decode_intra(MmContext * s, int half_horiz, int half_vert)
00087 {
00088 int i, x, y;
00089 i=0; x=0; y=0;
00090
00091 while (bytestream2_get_bytes_left(&s->gb) > 0) {
00092 int run_length, color;
00093
00094 if (y >= s->avctx->height)
00095 return 0;
00096
00097 color = bytestream2_get_byte(&s->gb);
00098 if (color & 0x80) {
00099 run_length = 1;
00100 }else{
00101 run_length = (color & 0x7f) + 2;
00102 color = bytestream2_get_byte(&s->gb);
00103 }
00104
00105 if (half_horiz)
00106 run_length *=2;
00107
00108 if (color) {
00109 memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length);
00110 if (half_vert)
00111 memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length);
00112 }
00113 x+= run_length;
00114
00115 if (x >= s->avctx->width) {
00116 x=0;
00117 y += 1 + half_vert;
00118 }
00119 }
00120
00121 return 0;
00122 }
00123
00124
00125
00126
00127
00128 static int mm_decode_inter(MmContext * s, int half_horiz, int half_vert)
00129 {
00130 int data_off = bytestream2_get_le16(&s->gb), y = 0;
00131 GetByteContext data_ptr;
00132
00133 if (bytestream2_get_bytes_left(&s->gb) < data_off)
00134 return AVERROR_INVALIDDATA;
00135
00136 bytestream2_init(&data_ptr, s->gb.buffer + data_off, bytestream2_get_bytes_left(&s->gb) - data_off);
00137 while (s->gb.buffer < data_ptr.buffer_start) {
00138 int i, j;
00139 int length = bytestream2_get_byte(&s->gb);
00140 int x = bytestream2_get_byte(&s->gb) + ((length & 0x80) << 1);
00141 length &= 0x7F;
00142
00143 if (length==0) {
00144 y += x;
00145 continue;
00146 }
00147
00148 if (y + half_vert >= s->avctx->height)
00149 return 0;
00150
00151 for(i=0; i<length; i++) {
00152 int replace_array = bytestream2_get_byte(&s->gb);
00153 for(j=0; j<8; j++) {
00154 int replace = (replace_array >> (7-j)) & 1;
00155 if (replace) {
00156 int color = bytestream2_get_byte(&data_ptr);
00157 s->frame.data[0][y*s->frame.linesize[0] + x] = color;
00158 if (half_horiz)
00159 s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;
00160 if (half_vert) {
00161 s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;
00162 if (half_horiz)
00163 s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;
00164 }
00165 }
00166 x += 1 + half_horiz;
00167 }
00168 }
00169
00170 y += 1 + half_vert;
00171 }
00172
00173 return 0;
00174 }
00175
00176 static int mm_decode_frame(AVCodecContext *avctx,
00177 void *data, int *data_size,
00178 AVPacket *avpkt)
00179 {
00180 const uint8_t *buf = avpkt->data;
00181 int buf_size = avpkt->size;
00182 MmContext *s = avctx->priv_data;
00183 int type, res;
00184
00185 if (buf_size < MM_PREAMBLE_SIZE)
00186 return AVERROR_INVALIDDATA;
00187 type = AV_RL16(&buf[0]);
00188 buf += MM_PREAMBLE_SIZE;
00189 buf_size -= MM_PREAMBLE_SIZE;
00190 bytestream2_init(&s->gb, buf, buf_size);
00191
00192 if (avctx->reget_buffer(avctx, &s->frame) < 0) {
00193 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00194 return -1;
00195 }
00196
00197 switch(type) {
00198 case MM_TYPE_PALETTE : res = mm_decode_pal(s); return buf_size;
00199 case MM_TYPE_INTRA : res = mm_decode_intra(s, 0, 0); break;
00200 case MM_TYPE_INTRA_HH : res = mm_decode_intra(s, 1, 0); break;
00201 case MM_TYPE_INTRA_HHV : res = mm_decode_intra(s, 1, 1); break;
00202 case MM_TYPE_INTER : res = mm_decode_inter(s, 0, 0); break;
00203 case MM_TYPE_INTER_HH : res = mm_decode_inter(s, 1, 0); break;
00204 case MM_TYPE_INTER_HHV : res = mm_decode_inter(s, 1, 1); break;
00205 default:
00206 res = AVERROR_INVALIDDATA;
00207 break;
00208 }
00209 if (res < 0)
00210 return res;
00211
00212 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00213
00214 *data_size = sizeof(AVFrame);
00215 *(AVFrame*)data = s->frame;
00216
00217 return buf_size;
00218 }
00219
00220 static av_cold int mm_decode_end(AVCodecContext *avctx)
00221 {
00222 MmContext *s = avctx->priv_data;
00223
00224 if(s->frame.data[0])
00225 avctx->release_buffer(avctx, &s->frame);
00226
00227 return 0;
00228 }
00229
00230 AVCodec ff_mmvideo_decoder = {
00231 .name = "mmvideo",
00232 .type = AVMEDIA_TYPE_VIDEO,
00233 .id = CODEC_ID_MMVIDEO,
00234 .priv_data_size = sizeof(MmContext),
00235 .init = mm_decode_init,
00236 .close = mm_decode_end,
00237 .decode = mm_decode_frame,
00238 .capabilities = CODEC_CAP_DR1,
00239 .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"),
00240 };