00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include "avcodec.h"
00035
00036 #define MM_PREAMBLE_SIZE 6
00037
00038 #define MM_TYPE_INTER 0x5
00039 #define MM_TYPE_INTRA 0x8
00040 #define MM_TYPE_INTRA_HH 0xc
00041 #define MM_TYPE_INTER_HH 0xd
00042 #define MM_TYPE_INTRA_HHV 0xe
00043 #define MM_TYPE_INTER_HHV 0xf
00044
00045 typedef struct MmContext {
00046 AVCodecContext *avctx;
00047 AVFrame frame;
00048 } MmContext;
00049
00050 static int mm_decode_init(AVCodecContext *avctx)
00051 {
00052 MmContext *s = avctx->priv_data;
00053
00054 s->avctx = avctx;
00055
00056 if (s->avctx->palctrl == NULL) {
00057 av_log(avctx, AV_LOG_ERROR, "mmvideo: palette expected.\n");
00058 return -1;
00059 }
00060
00061 avctx->pix_fmt = PIX_FMT_PAL8;
00062
00063 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height))
00064 return -1;
00065
00066 s->frame.reference = 1;
00067 if (avctx->get_buffer(avctx, &s->frame)) {
00068 av_log(s->avctx, AV_LOG_ERROR, "mmvideo: get_buffer() failed\n");
00069 return -1;
00070 }
00071
00072 return 0;
00073 }
00074
00075 static void mm_decode_intra(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
00076 {
00077 int i, x, y;
00078 i=0; x=0; y=0;
00079
00080 while(i<buf_size) {
00081 int run_length, color;
00082
00083 if (buf[i] & 0x80) {
00084 run_length = 1;
00085 color = buf[i];
00086 i++;
00087 }else{
00088 run_length = (buf[i] & 0x7f) + 2;
00089 color = buf[i+1];
00090 i+=2;
00091 }
00092
00093 if (half_horiz)
00094 run_length *=2;
00095
00096 if (color) {
00097 memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length);
00098 if (half_vert)
00099 memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length);
00100 }
00101 x+= run_length;
00102
00103 if (x >= s->avctx->width) {
00104 x=0;
00105 y += half_vert ? 2 : 1;
00106 }
00107 }
00108 }
00109
00110 static void mm_decode_inter(MmContext * s, int half_horiz, int half_vert, const uint8_t *buf, int buf_size)
00111 {
00112 const int data_ptr = 2 + AV_RL16(&buf[0]);
00113 int d, r, y;
00114 d = data_ptr; r = 2; y = 0;
00115
00116 while(r < data_ptr) {
00117 int i, j;
00118 int length = buf[r] & 0x7f;
00119 int x = buf[r+1] + ((buf[r] & 0x80) << 1);
00120 r += 2;
00121
00122 if (length==0) {
00123 y += x;
00124 continue;
00125 }
00126
00127 for(i=0; i<length; i++) {
00128 for(j=0; j<8; j++) {
00129 int replace = (buf[r+i] >> (7-j)) & 1;
00130 if (replace) {
00131 int color = buf[d];
00132 s->frame.data[0][y*s->frame.linesize[0] + x] = color;
00133 if (half_horiz)
00134 s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color;
00135 if (half_vert) {
00136 s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color;
00137 if (half_horiz)
00138 s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color;
00139 }
00140 d++;
00141 }
00142 x += half_horiz ? 2 : 1;
00143 }
00144 }
00145
00146 r += length;
00147 y += half_vert ? 2 : 1;
00148 }
00149 }
00150
00151 static int mm_decode_frame(AVCodecContext *avctx,
00152 void *data, int *data_size,
00153 const uint8_t *buf, int buf_size)
00154 {
00155 MmContext *s = avctx->priv_data;
00156 AVPaletteControl *palette_control = avctx->palctrl;
00157 int type;
00158
00159 if (palette_control->palette_changed) {
00160 memcpy(s->frame.data[1], palette_control->palette, AVPALETTE_SIZE);
00161 palette_control->palette_changed = 0;
00162 }
00163
00164 type = AV_RL16(&buf[0]);
00165 buf += MM_PREAMBLE_SIZE;
00166 buf_size -= MM_PREAMBLE_SIZE;
00167
00168 switch(type) {
00169 case MM_TYPE_INTRA : mm_decode_intra(s, 0, 0, buf, buf_size); break;
00170 case MM_TYPE_INTRA_HH : mm_decode_intra(s, 1, 0, buf, buf_size); break;
00171 case MM_TYPE_INTRA_HHV : mm_decode_intra(s, 1, 1, buf, buf_size); break;
00172 case MM_TYPE_INTER : mm_decode_inter(s, 0, 0, buf, buf_size); break;
00173 case MM_TYPE_INTER_HH : mm_decode_inter(s, 1, 0, buf, buf_size); break;
00174 case MM_TYPE_INTER_HHV : mm_decode_inter(s, 1, 1, buf, buf_size); break;
00175 default :
00176 return -1;
00177 }
00178
00179 *data_size = sizeof(AVFrame);
00180 *(AVFrame*)data = s->frame;
00181
00182 return buf_size;
00183 }
00184
00185 static int mm_decode_end(AVCodecContext *avctx)
00186 {
00187 MmContext *s = avctx->priv_data;
00188
00189 if(s->frame.data[0])
00190 avctx->release_buffer(avctx, &s->frame);
00191
00192 return 0;
00193 }
00194
00195 AVCodec mmvideo_decoder = {
00196 "mmvideo",
00197 CODEC_TYPE_VIDEO,
00198 CODEC_ID_MMVIDEO,
00199 sizeof(MmContext),
00200 mm_decode_init,
00201 NULL,
00202 mm_decode_end,
00203 mm_decode_frame,
00204 CODEC_CAP_DR1,
00205 };