• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/msvideo1.c

Go to the documentation of this file.
00001 /*
00002  * Microsoft Video-1 Decoder
00003  * Copyright (C) 2003 the ffmpeg project
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "libavutil/intreadwrite.h"
00035 #include "avcodec.h"
00036 
00037 #define PALETTE_COUNT 256
00038 #define CHECK_STREAM_PTR(n) \
00039   if ((stream_ptr + n) > s->size ) { \
00040     av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
00041       stream_ptr + n, s->size); \
00042     return; \
00043   }
00044 
00045 typedef struct Msvideo1Context {
00046 
00047     AVCodecContext *avctx;
00048     AVFrame frame;
00049 
00050     const unsigned char *buf;
00051     int size;
00052 
00053     int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
00054 
00055     uint32_t pal[256];
00056 } Msvideo1Context;
00057 
00058 static av_cold int msvideo1_decode_init(AVCodecContext *avctx)
00059 {
00060     Msvideo1Context *s = avctx->priv_data;
00061 
00062     s->avctx = avctx;
00063 
00064     /* figure out the colorspace based on the presence of a palette */
00065     if (s->avctx->bits_per_coded_sample == 8) {
00066         s->mode_8bit = 1;
00067         avctx->pix_fmt = PIX_FMT_PAL8;
00068     } else {
00069         s->mode_8bit = 0;
00070         avctx->pix_fmt = PIX_FMT_RGB555;
00071     }
00072 
00073     s->frame.data[0] = NULL;
00074 
00075     return 0;
00076 }
00077 
00078 static void msvideo1_decode_8bit(Msvideo1Context *s)
00079 {
00080     int block_ptr, pixel_ptr;
00081     int total_blocks;
00082     int pixel_x, pixel_y;  /* pixel width and height iterators */
00083     int block_x, block_y;  /* block width and height iterators */
00084     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
00085     int block_inc;
00086     int row_dec;
00087 
00088     /* decoding parameters */
00089     int stream_ptr;
00090     unsigned char byte_a, byte_b;
00091     unsigned short flags;
00092     int skip_blocks;
00093     unsigned char colors[8];
00094     unsigned char *pixels = s->frame.data[0];
00095     int stride = s->frame.linesize[0];
00096 
00097     stream_ptr = 0;
00098     skip_blocks = 0;
00099     blocks_wide = s->avctx->width / 4;
00100     blocks_high = s->avctx->height / 4;
00101     total_blocks = blocks_wide * blocks_high;
00102     block_inc = 4;
00103     row_dec = stride + 4;
00104 
00105     for (block_y = blocks_high; block_y > 0; block_y--) {
00106         block_ptr = ((block_y * 4) - 1) * stride;
00107         for (block_x = blocks_wide; block_x > 0; block_x--) {
00108             /* check if this block should be skipped */
00109             if (skip_blocks) {
00110                 block_ptr += block_inc;
00111                 skip_blocks--;
00112                 total_blocks--;
00113                 continue;
00114             }
00115 
00116             pixel_ptr = block_ptr;
00117 
00118             /* get the next two bytes in the encoded data stream */
00119             CHECK_STREAM_PTR(2);
00120             byte_a = s->buf[stream_ptr++];
00121             byte_b = s->buf[stream_ptr++];
00122 
00123             /* check if the decode is finished */
00124             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
00125                 return;
00126             else if ((byte_b & 0xFC) == 0x84) {
00127                 /* skip code, but don't count the current block */
00128                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00129             } else if (byte_b < 0x80) {
00130                 /* 2-color encoding */
00131                 flags = (byte_b << 8) | byte_a;
00132 
00133                 CHECK_STREAM_PTR(2);
00134                 colors[0] = s->buf[stream_ptr++];
00135                 colors[1] = s->buf[stream_ptr++];
00136 
00137                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00138                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00139                         pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00140                     pixel_ptr -= row_dec;
00141                 }
00142             } else if (byte_b >= 0x90) {
00143                 /* 8-color encoding */
00144                 flags = (byte_b << 8) | byte_a;
00145 
00146                 CHECK_STREAM_PTR(8);
00147                 memcpy(colors, &s->buf[stream_ptr], 8);
00148                 stream_ptr += 8;
00149 
00150                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00151                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00152                         pixels[pixel_ptr++] =
00153                             colors[((pixel_y & 0x2) << 1) +
00154                                 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00155                     pixel_ptr -= row_dec;
00156                 }
00157             } else {
00158                 /* 1-color encoding */
00159                 colors[0] = byte_a;
00160 
00161                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00162                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
00163                         pixels[pixel_ptr++] = colors[0];
00164                     pixel_ptr -= row_dec;
00165                 }
00166             }
00167 
00168             block_ptr += block_inc;
00169             total_blocks--;
00170         }
00171     }
00172 
00173     /* make the palette available on the way out */
00174     if (s->avctx->pix_fmt == PIX_FMT_PAL8)
00175         memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
00176 }
00177 
00178 static void msvideo1_decode_16bit(Msvideo1Context *s)
00179 {
00180     int block_ptr, pixel_ptr;
00181     int total_blocks;
00182     int pixel_x, pixel_y;  /* pixel width and height iterators */
00183     int block_x, block_y;  /* block width and height iterators */
00184     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
00185     int block_inc;
00186     int row_dec;
00187 
00188     /* decoding parameters */
00189     int stream_ptr;
00190     unsigned char byte_a, byte_b;
00191     unsigned short flags;
00192     int skip_blocks;
00193     unsigned short colors[8];
00194     unsigned short *pixels = (unsigned short *)s->frame.data[0];
00195     int stride = s->frame.linesize[0] / 2;
00196 
00197     stream_ptr = 0;
00198     skip_blocks = 0;
00199     blocks_wide = s->avctx->width / 4;
00200     blocks_high = s->avctx->height / 4;
00201     total_blocks = blocks_wide * blocks_high;
00202     block_inc = 4;
00203     row_dec = stride + 4;
00204 
00205     for (block_y = blocks_high; block_y > 0; block_y--) {
00206         block_ptr = ((block_y * 4) - 1) * stride;
00207         for (block_x = blocks_wide; block_x > 0; block_x--) {
00208             /* check if this block should be skipped */
00209             if (skip_blocks) {
00210                 block_ptr += block_inc;
00211                 skip_blocks--;
00212                 total_blocks--;
00213                 continue;
00214             }
00215 
00216             pixel_ptr = block_ptr;
00217 
00218             /* get the next two bytes in the encoded data stream */
00219             CHECK_STREAM_PTR(2);
00220             byte_a = s->buf[stream_ptr++];
00221             byte_b = s->buf[stream_ptr++];
00222 
00223             /* check if the decode is finished */
00224             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
00225                 return;
00226             } else if ((byte_b & 0xFC) == 0x84) {
00227                 /* skip code, but don't count the current block */
00228                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
00229             } else if (byte_b < 0x80) {
00230                 /* 2- or 8-color encoding modes */
00231                 flags = (byte_b << 8) | byte_a;
00232 
00233                 CHECK_STREAM_PTR(4);
00234                 colors[0] = AV_RL16(&s->buf[stream_ptr]);
00235                 stream_ptr += 2;
00236                 colors[1] = AV_RL16(&s->buf[stream_ptr]);
00237                 stream_ptr += 2;
00238 
00239                 if (colors[0] & 0x8000) {
00240                     /* 8-color encoding */
00241                     CHECK_STREAM_PTR(12);
00242                     colors[2] = AV_RL16(&s->buf[stream_ptr]);
00243                     stream_ptr += 2;
00244                     colors[3] = AV_RL16(&s->buf[stream_ptr]);
00245                     stream_ptr += 2;
00246                     colors[4] = AV_RL16(&s->buf[stream_ptr]);
00247                     stream_ptr += 2;
00248                     colors[5] = AV_RL16(&s->buf[stream_ptr]);
00249                     stream_ptr += 2;
00250                     colors[6] = AV_RL16(&s->buf[stream_ptr]);
00251                     stream_ptr += 2;
00252                     colors[7] = AV_RL16(&s->buf[stream_ptr]);
00253                     stream_ptr += 2;
00254 
00255                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00256                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00257                             pixels[pixel_ptr++] =
00258                                 colors[((pixel_y & 0x2) << 1) +
00259                                     (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
00260                         pixel_ptr -= row_dec;
00261                     }
00262                 } else {
00263                     /* 2-color encoding */
00264                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00265                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
00266                             pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
00267                         pixel_ptr -= row_dec;
00268                     }
00269                 }
00270             } else {
00271                 /* otherwise, it's a 1-color block */
00272                 colors[0] = (byte_b << 8) | byte_a;
00273 
00274                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
00275                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
00276                         pixels[pixel_ptr++] = colors[0];
00277                     pixel_ptr -= row_dec;
00278                 }
00279             }
00280 
00281             block_ptr += block_inc;
00282             total_blocks--;
00283         }
00284     }
00285 }
00286 
00287 static int msvideo1_decode_frame(AVCodecContext *avctx,
00288                                 void *data, int *data_size,
00289                                 AVPacket *avpkt)
00290 {
00291     const uint8_t *buf = avpkt->data;
00292     int buf_size = avpkt->size;
00293     Msvideo1Context *s = avctx->priv_data;
00294 
00295     s->buf = buf;
00296     s->size = buf_size;
00297 
00298     s->frame.reference = 1;
00299     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
00300     if (avctx->reget_buffer(avctx, &s->frame)) {
00301         av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00302         return -1;
00303     }
00304 
00305     if (s->mode_8bit) {
00306         const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
00307 
00308         if (pal) {
00309             memcpy(s->pal, pal, AVPALETTE_SIZE);
00310             s->frame.palette_has_changed = 1;
00311         }
00312     }
00313 
00314     if (s->mode_8bit)
00315         msvideo1_decode_8bit(s);
00316     else
00317         msvideo1_decode_16bit(s);
00318 
00319     *data_size = sizeof(AVFrame);
00320     *(AVFrame*)data = s->frame;
00321 
00322     /* report that the buffer was completely consumed */
00323     return buf_size;
00324 }
00325 
00326 static av_cold int msvideo1_decode_end(AVCodecContext *avctx)
00327 {
00328     Msvideo1Context *s = avctx->priv_data;
00329 
00330     if (s->frame.data[0])
00331         avctx->release_buffer(avctx, &s->frame);
00332 
00333     return 0;
00334 }
00335 
00336 AVCodec ff_msvideo1_decoder = {
00337     .name           = "msvideo1",
00338     .type           = AVMEDIA_TYPE_VIDEO,
00339     .id             = CODEC_ID_MSVIDEO1,
00340     .priv_data_size = sizeof(Msvideo1Context),
00341     .init           = msvideo1_decode_init,
00342     .close          = msvideo1_decode_end,
00343     .decode         = msvideo1_decode_frame,
00344     .capabilities   = CODEC_CAP_DR1,
00345     .long_name= NULL_IF_CONFIG_SMALL("Microsoft Video 1"),
00346 };
Generated on Thu Jan 24 2013 17:08:52 for Libav by doxygen 1.7.1