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

Generated on Wed Apr 11 2012 07:31:34 for FFmpeg by  doxygen 1.7.1