00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033
00034 #include "libavutil/internal.h"
00035 #include "libavutil/intreadwrite.h"
00036 #include "avcodec.h"
00037
00038 #define PALETTE_COUNT 256
00039 #define CHECK_STREAM_PTR(n) \
00040 if ((stream_ptr + n) > s->size ) { \
00041 av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
00042 stream_ptr + n, s->size); \
00043 return; \
00044 }
00045
00046 typedef struct Msvideo1Context {
00047
00048 AVCodecContext *avctx;
00049 AVFrame frame;
00050
00051 const unsigned char *buf;
00052 int size;
00053
00054 int mode_8bit;
00055
00056 uint32_t pal[256];
00057 } Msvideo1Context;
00058
00059 static av_cold int msvideo1_decode_init(AVCodecContext *avctx)
00060 {
00061 Msvideo1Context *s = avctx->priv_data;
00062
00063 s->avctx = avctx;
00064
00065
00066 if (s->avctx->bits_per_coded_sample == 8) {
00067 s->mode_8bit = 1;
00068 avctx->pix_fmt = PIX_FMT_PAL8;
00069 } else {
00070 s->mode_8bit = 0;
00071 avctx->pix_fmt = PIX_FMT_RGB555;
00072 }
00073
00074 avcodec_get_frame_defaults(&s->frame);
00075 s->frame.data[0] = NULL;
00076
00077 return 0;
00078 }
00079
00080 static void msvideo1_decode_8bit(Msvideo1Context *s)
00081 {
00082 int block_ptr, pixel_ptr;
00083 int total_blocks;
00084 int pixel_x, pixel_y;
00085 int block_x, block_y;
00086 int blocks_wide, blocks_high;
00087 int block_inc;
00088 int row_dec;
00089
00090
00091 int stream_ptr;
00092 unsigned char byte_a, byte_b;
00093 unsigned short flags;
00094 int skip_blocks;
00095 unsigned char colors[8];
00096 unsigned char *pixels = s->frame.data[0];
00097 int stride = s->frame.linesize[0];
00098
00099 stream_ptr = 0;
00100 skip_blocks = 0;
00101 blocks_wide = s->avctx->width / 4;
00102 blocks_high = s->avctx->height / 4;
00103 total_blocks = blocks_wide * blocks_high;
00104 block_inc = 4;
00105 row_dec = stride + 4;
00106
00107 for (block_y = blocks_high; block_y > 0; block_y--) {
00108 block_ptr = ((block_y * 4) - 1) * stride;
00109 for (block_x = blocks_wide; block_x > 0; block_x--) {
00110
00111 if (skip_blocks) {
00112 block_ptr += block_inc;
00113 skip_blocks--;
00114 total_blocks--;
00115 continue;
00116 }
00117
00118 pixel_ptr = block_ptr;
00119
00120
00121 CHECK_STREAM_PTR(2);
00122 byte_a = s->buf[stream_ptr++];
00123 byte_b = s->buf[stream_ptr++];
00124
00125
00126 if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
00127 return;
00128 else if ((byte_b & 0xFC) == 0x84) {
00129
00130 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00131 } else if (byte_b < 0x80) {
00132
00133 flags = (byte_b << 8) | byte_a;
00134
00135 CHECK_STREAM_PTR(2);
00136 colors[0] = s->buf[stream_ptr++];
00137 colors[1] = s->buf[stream_ptr++];
00138
00139 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00140 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00141 pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00142 pixel_ptr -= row_dec;
00143 }
00144 } else if (byte_b >= 0x90) {
00145
00146 flags = (byte_b << 8) | byte_a;
00147
00148 CHECK_STREAM_PTR(8);
00149 memcpy(colors, &s->buf[stream_ptr], 8);
00150 stream_ptr += 8;
00151
00152 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00153 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00154 pixels[pixel_ptr++] =
00155 colors[((pixel_y & 0x2) << 1) +
00156 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00157 pixel_ptr -= row_dec;
00158 }
00159 } else {
00160
00161 colors[0] = byte_a;
00162
00163 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00164 for (pixel_x = 0; pixel_x < 4; pixel_x++)
00165 pixels[pixel_ptr++] = colors[0];
00166 pixel_ptr -= row_dec;
00167 }
00168 }
00169
00170 block_ptr += block_inc;
00171 total_blocks--;
00172 }
00173 }
00174
00175
00176 if (s->avctx->pix_fmt == PIX_FMT_PAL8)
00177 memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
00178 }
00179
00180 static void msvideo1_decode_16bit(Msvideo1Context *s)
00181 {
00182 int block_ptr, pixel_ptr;
00183 int total_blocks;
00184 int pixel_x, pixel_y;
00185 int block_x, block_y;
00186 int blocks_wide, blocks_high;
00187 int block_inc;
00188 int row_dec;
00189
00190
00191 int stream_ptr;
00192 unsigned char byte_a, byte_b;
00193 unsigned short flags;
00194 int skip_blocks;
00195 unsigned short colors[8];
00196 unsigned short *pixels = (unsigned short *)s->frame.data[0];
00197 int stride = s->frame.linesize[0] / 2;
00198
00199 stream_ptr = 0;
00200 skip_blocks = 0;
00201 blocks_wide = s->avctx->width / 4;
00202 blocks_high = s->avctx->height / 4;
00203 total_blocks = blocks_wide * blocks_high;
00204 block_inc = 4;
00205 row_dec = stride + 4;
00206
00207 for (block_y = blocks_high; block_y > 0; block_y--) {
00208 block_ptr = ((block_y * 4) - 1) * stride;
00209 for (block_x = blocks_wide; block_x > 0; block_x--) {
00210
00211 if (skip_blocks) {
00212 block_ptr += block_inc;
00213 skip_blocks--;
00214 total_blocks--;
00215 continue;
00216 }
00217
00218 pixel_ptr = block_ptr;
00219
00220
00221 CHECK_STREAM_PTR(2);
00222 byte_a = s->buf[stream_ptr++];
00223 byte_b = s->buf[stream_ptr++];
00224
00225
00226 if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
00227 return;
00228 } else if ((byte_b & 0xFC) == 0x84) {
00229
00230 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00231 } else if (byte_b < 0x80) {
00232
00233 flags = (byte_b << 8) | byte_a;
00234
00235 CHECK_STREAM_PTR(4);
00236 colors[0] = AV_RL16(&s->buf[stream_ptr]);
00237 stream_ptr += 2;
00238 colors[1] = AV_RL16(&s->buf[stream_ptr]);
00239 stream_ptr += 2;
00240
00241 if (colors[0] & 0x8000) {
00242
00243 CHECK_STREAM_PTR(12);
00244 colors[2] = AV_RL16(&s->buf[stream_ptr]);
00245 stream_ptr += 2;
00246 colors[3] = AV_RL16(&s->buf[stream_ptr]);
00247 stream_ptr += 2;
00248 colors[4] = AV_RL16(&s->buf[stream_ptr]);
00249 stream_ptr += 2;
00250 colors[5] = AV_RL16(&s->buf[stream_ptr]);
00251 stream_ptr += 2;
00252 colors[6] = AV_RL16(&s->buf[stream_ptr]);
00253 stream_ptr += 2;
00254 colors[7] = AV_RL16(&s->buf[stream_ptr]);
00255 stream_ptr += 2;
00256
00257 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00258 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00259 pixels[pixel_ptr++] =
00260 colors[((pixel_y & 0x2) << 1) +
00261 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00262 pixel_ptr -= row_dec;
00263 }
00264 } else {
00265
00266 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00267 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00268 pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00269 pixel_ptr -= row_dec;
00270 }
00271 }
00272 } else {
00273
00274 colors[0] = (byte_b << 8) | byte_a;
00275
00276 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00277 for (pixel_x = 0; pixel_x < 4; pixel_x++)
00278 pixels[pixel_ptr++] = colors[0];
00279 pixel_ptr -= row_dec;
00280 }
00281 }
00282
00283 block_ptr += block_inc;
00284 total_blocks--;
00285 }
00286 }
00287 }
00288
00289 static int msvideo1_decode_frame(AVCodecContext *avctx,
00290 void *data, int *data_size,
00291 AVPacket *avpkt)
00292 {
00293 const uint8_t *buf = avpkt->data;
00294 int buf_size = avpkt->size;
00295 Msvideo1Context *s = avctx->priv_data;
00296
00297 s->buf = buf;
00298 s->size = buf_size;
00299
00300 s->frame.reference = 3;
00301 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00302 if (avctx->reget_buffer(avctx, &s->frame)) {
00303 av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00304 return -1;
00305 }
00306
00307 if (s->mode_8bit) {
00308 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
00309
00310 if (pal) {
00311 memcpy(s->pal, pal, AVPALETTE_SIZE);
00312 s->frame.palette_has_changed = 1;
00313 }
00314 }
00315
00316 if (s->mode_8bit)
00317 msvideo1_decode_8bit(s);
00318 else
00319 msvideo1_decode_16bit(s);
00320
00321 *data_size = sizeof(AVFrame);
00322 *(AVFrame*)data = s->frame;
00323
00324
00325 return buf_size;
00326 }
00327
00328 static av_cold int msvideo1_decode_end(AVCodecContext *avctx)
00329 {
00330 Msvideo1Context *s = avctx->priv_data;
00331
00332 if (s->frame.data[0])
00333 avctx->release_buffer(avctx, &s->frame);
00334
00335 return 0;
00336 }
00337
00338 AVCodec ff_msvideo1_decoder = {
00339 .name = "msvideo1",
00340 .type = AVMEDIA_TYPE_VIDEO,
00341 .id = AV_CODEC_ID_MSVIDEO1,
00342 .priv_data_size = sizeof(Msvideo1Context),
00343 .init = msvideo1_decode_init,
00344 .close = msvideo1_decode_end,
00345 .decode = msvideo1_decode_frame,
00346 .capabilities = CODEC_CAP_DR1,
00347 .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video 1"),
00348 };