LCOV - code coverage report
Current view: top level - libavcodec - msvideo1.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 154 162 95.1 %
Date: 2017-12-16 21:16:39 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Microsoft Video-1 Decoder
       3             :  * Copyright (C) 2003 The FFmpeg project
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net)
      25             :  * For more information about the MS Video-1 format, visit:
      26             :  *   http://www.pcisys.net/~melanson/codecs/
      27             :  */
      28             : 
      29             : #include <stdio.h>
      30             : #include <stdlib.h>
      31             : #include <string.h>
      32             : 
      33             : #include "libavutil/internal.h"
      34             : #include "libavutil/intreadwrite.h"
      35             : #include "avcodec.h"
      36             : #include "internal.h"
      37             : 
      38             : #define PALETTE_COUNT 256
      39             : #define CHECK_STREAM_PTR(n) \
      40             :   if ((stream_ptr + n) > s->size ) { \
      41             :     av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
      42             :       stream_ptr + n, s->size); \
      43             :     return; \
      44             :   }
      45             : 
      46             : typedef struct Msvideo1Context {
      47             : 
      48             :     AVCodecContext *avctx;
      49             :     AVFrame *frame;
      50             : 
      51             :     const unsigned char *buf;
      52             :     int size;
      53             : 
      54             :     int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
      55             : 
      56             :     uint32_t pal[256];
      57             : } Msvideo1Context;
      58             : 
      59          13 : static av_cold int msvideo1_decode_init(AVCodecContext *avctx)
      60             : {
      61          13 :     Msvideo1Context *s = avctx->priv_data;
      62             : 
      63          13 :     s->avctx = avctx;
      64             : 
      65             :     /* figure out the colorspace based on the presence of a palette */
      66          13 :     if (s->avctx->bits_per_coded_sample == 8) {
      67           5 :         s->mode_8bit = 1;
      68           5 :         avctx->pix_fmt = AV_PIX_FMT_PAL8;
      69           5 :         if (avctx->extradata_size >= AVPALETTE_SIZE)
      70           5 :             memcpy(s->pal, avctx->extradata, AVPALETTE_SIZE);
      71             :     } else {
      72           8 :         s->mode_8bit = 0;
      73           8 :         avctx->pix_fmt = AV_PIX_FMT_RGB555;
      74             :     }
      75             : 
      76          13 :     s->frame = av_frame_alloc();
      77          13 :     if (!s->frame)
      78           0 :         return AVERROR(ENOMEM);
      79             : 
      80          13 :     return 0;
      81             : }
      82             : 
      83         147 : static void msvideo1_decode_8bit(Msvideo1Context *s)
      84             : {
      85             :     int block_ptr, pixel_ptr;
      86             :     int total_blocks;
      87             :     int pixel_x, pixel_y;  /* pixel width and height iterators */
      88             :     int block_x, block_y;  /* block width and height iterators */
      89             :     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
      90             :     int block_inc;
      91             :     int row_dec;
      92             : 
      93             :     /* decoding parameters */
      94             :     int stream_ptr;
      95             :     unsigned char byte_a, byte_b;
      96             :     unsigned short flags;
      97             :     int skip_blocks;
      98             :     unsigned char colors[8];
      99         147 :     unsigned char *pixels = s->frame->data[0];
     100         147 :     int stride = s->frame->linesize[0];
     101             : 
     102         147 :     stream_ptr = 0;
     103         147 :     skip_blocks = 0;
     104         147 :     blocks_wide = s->avctx->width / 4;
     105         147 :     blocks_high = s->avctx->height / 4;
     106         147 :     total_blocks = blocks_wide * blocks_high;
     107         147 :     block_inc = 4;
     108         147 :     row_dec = stride + 4;
     109             : 
     110        3977 :     for (block_y = blocks_high; block_y > 0; block_y--) {
     111        3830 :         block_ptr = ((block_y * 4) - 1) * stride;
     112      186030 :         for (block_x = blocks_wide; block_x > 0; block_x--) {
     113             :             /* check if this block should be skipped */
     114      182200 :             if (skip_blocks) {
     115       94392 :                 block_ptr += block_inc;
     116       94392 :                 skip_blocks--;
     117       94392 :                 total_blocks--;
     118       94392 :                 continue;
     119             :             }
     120             : 
     121       87808 :             pixel_ptr = block_ptr;
     122             : 
     123             :             /* get the next two bytes in the encoded data stream */
     124       87808 :             CHECK_STREAM_PTR(2);
     125       87808 :             byte_a = s->buf[stream_ptr++];
     126       87808 :             byte_b = s->buf[stream_ptr++];
     127             : 
     128             :             /* check if the decode is finished */
     129       87808 :             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
     130           0 :                 return;
     131       87808 :             else if ((byte_b & 0xFC) == 0x84) {
     132             :                 /* skip code, but don't count the current block */
     133        8662 :                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
     134       79146 :             } else if (byte_b < 0x80) {
     135             :                 /* 2-color encoding */
     136       11480 :                 flags = (byte_b << 8) | byte_a;
     137             : 
     138       11480 :                 CHECK_STREAM_PTR(2);
     139       11480 :                 colors[0] = s->buf[stream_ptr++];
     140       11480 :                 colors[1] = s->buf[stream_ptr++];
     141             : 
     142       57400 :                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     143      229600 :                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
     144      183680 :                         pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
     145       45920 :                     pixel_ptr -= row_dec;
     146             :                 }
     147       67666 :             } else if (byte_b >= 0x90) {
     148             :                 /* 8-color encoding */
     149       56844 :                 flags = (byte_b << 8) | byte_a;
     150             : 
     151       56844 :                 CHECK_STREAM_PTR(8);
     152       56844 :                 memcpy(colors, &s->buf[stream_ptr], 8);
     153       56844 :                 stream_ptr += 8;
     154             : 
     155      284220 :                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     156     1136880 :                     for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
     157     1819008 :                         pixels[pixel_ptr++] =
     158     2728512 :                             colors[((pixel_y & 0x2) << 1) +
     159     1819008 :                                 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
     160      227376 :                     pixel_ptr -= row_dec;
     161             :                 }
     162             :             } else {
     163             :                 /* 1-color encoding */
     164       10822 :                 colors[0] = byte_a;
     165             : 
     166       54110 :                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     167      216440 :                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
     168      173152 :                         pixels[pixel_ptr++] = colors[0];
     169       43288 :                     pixel_ptr -= row_dec;
     170             :                 }
     171             :             }
     172             : 
     173       87808 :             block_ptr += block_inc;
     174       87808 :             total_blocks--;
     175             :         }
     176             :     }
     177             : 
     178             :     /* make the palette available on the way out */
     179         147 :     if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
     180         147 :         memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE);
     181             : }
     182             : 
     183         180 : static void msvideo1_decode_16bit(Msvideo1Context *s)
     184             : {
     185             :     int block_ptr, pixel_ptr;
     186             :     int total_blocks;
     187             :     int pixel_x, pixel_y;  /* pixel width and height iterators */
     188             :     int block_x, block_y;  /* block width and height iterators */
     189             :     int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
     190             :     int block_inc;
     191             :     int row_dec;
     192             : 
     193             :     /* decoding parameters */
     194             :     int stream_ptr;
     195             :     unsigned char byte_a, byte_b;
     196             :     unsigned short flags;
     197             :     int skip_blocks;
     198             :     unsigned short colors[8];
     199         180 :     unsigned short *pixels = (unsigned short *)s->frame->data[0];
     200         180 :     int stride = s->frame->linesize[0] / 2;
     201             : 
     202         180 :     stream_ptr = 0;
     203         180 :     skip_blocks = 0;
     204         180 :     blocks_wide = s->avctx->width / 4;
     205         180 :     blocks_high = s->avctx->height / 4;
     206         180 :     total_blocks = blocks_wide * blocks_high;
     207         180 :     block_inc = 4;
     208         180 :     row_dec = stride + 4;
     209             : 
     210       12090 :     for (block_y = blocks_high; block_y > 0; block_y--) {
     211       11910 :         block_ptr = ((block_y * 4) - 1) * stride;
     212     1003380 :         for (block_x = blocks_wide; block_x > 0; block_x--) {
     213             :             /* check if this block should be skipped */
     214      991470 :             if (skip_blocks) {
     215      281140 :                 block_ptr += block_inc;
     216      281140 :                 skip_blocks--;
     217      281140 :                 total_blocks--;
     218      281140 :                 continue;
     219             :             }
     220             : 
     221      710330 :             pixel_ptr = block_ptr;
     222             : 
     223             :             /* get the next two bytes in the encoded data stream */
     224      710330 :             CHECK_STREAM_PTR(2);
     225      710330 :             byte_a = s->buf[stream_ptr++];
     226      710330 :             byte_b = s->buf[stream_ptr++];
     227             : 
     228             :             /* check if the decode is finished */
     229      710330 :             if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
     230           0 :                 return;
     231      710330 :             } else if ((byte_b & 0xFC) == 0x84) {
     232             :                 /* skip code, but don't count the current block */
     233      108271 :                 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
     234      602059 :             } else if (byte_b < 0x80) {
     235             :                 /* 2- or 8-color encoding modes */
     236      280291 :                 flags = (byte_b << 8) | byte_a;
     237             : 
     238      280291 :                 CHECK_STREAM_PTR(4);
     239      280291 :                 colors[0] = AV_RL16(&s->buf[stream_ptr]);
     240      280291 :                 stream_ptr += 2;
     241      280291 :                 colors[1] = AV_RL16(&s->buf[stream_ptr]);
     242      280291 :                 stream_ptr += 2;
     243             : 
     244      280291 :                 if (colors[0] & 0x8000) {
     245             :                     /* 8-color encoding */
     246      145448 :                     CHECK_STREAM_PTR(12);
     247      145448 :                     colors[2] = AV_RL16(&s->buf[stream_ptr]);
     248      145448 :                     stream_ptr += 2;
     249      145448 :                     colors[3] = AV_RL16(&s->buf[stream_ptr]);
     250      145448 :                     stream_ptr += 2;
     251      145448 :                     colors[4] = AV_RL16(&s->buf[stream_ptr]);
     252      145448 :                     stream_ptr += 2;
     253      145448 :                     colors[5] = AV_RL16(&s->buf[stream_ptr]);
     254      145448 :                     stream_ptr += 2;
     255      145448 :                     colors[6] = AV_RL16(&s->buf[stream_ptr]);
     256      145448 :                     stream_ptr += 2;
     257      145448 :                     colors[7] = AV_RL16(&s->buf[stream_ptr]);
     258      145448 :                     stream_ptr += 2;
     259             : 
     260      727240 :                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     261     2908960 :                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
     262     4654336 :                             pixels[pixel_ptr++] =
     263     6981504 :                                 colors[((pixel_y & 0x2) << 1) +
     264     4654336 :                                     (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
     265      581792 :                         pixel_ptr -= row_dec;
     266             :                     }
     267             :                 } else {
     268             :                     /* 2-color encoding */
     269      674215 :                     for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     270     2696860 :                         for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
     271     2157488 :                             pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
     272      539372 :                         pixel_ptr -= row_dec;
     273             :                     }
     274             :                 }
     275             :             } else {
     276             :                 /* otherwise, it's a 1-color block */
     277      321768 :                 colors[0] = (byte_b << 8) | byte_a;
     278             : 
     279     1608840 :                 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
     280     6435360 :                     for (pixel_x = 0; pixel_x < 4; pixel_x++)
     281     5148288 :                         pixels[pixel_ptr++] = colors[0];
     282     1287072 :                     pixel_ptr -= row_dec;
     283             :                 }
     284             :             }
     285             : 
     286      710330 :             block_ptr += block_inc;
     287      710330 :             total_blocks--;
     288             :         }
     289             :     }
     290             : }
     291             : 
     292         327 : static int msvideo1_decode_frame(AVCodecContext *avctx,
     293             :                                 void *data, int *got_frame,
     294             :                                 AVPacket *avpkt)
     295             : {
     296         327 :     const uint8_t *buf = avpkt->data;
     297         327 :     int buf_size = avpkt->size;
     298         327 :     Msvideo1Context *s = avctx->priv_data;
     299             :     int ret;
     300             : 
     301         327 :     s->buf = buf;
     302         327 :     s->size = buf_size;
     303             : 
     304             :     // Discard frame if its smaller than the minimum frame size
     305         327 :     if (buf_size < (avctx->width/4) * (avctx->height/4) / 512) {
     306           0 :         av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
     307           0 :         return AVERROR_INVALIDDATA;
     308             :     }
     309             : 
     310         327 :     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
     311           0 :         return ret;
     312             : 
     313         327 :     if (s->mode_8bit) {
     314             :         int size;
     315         147 :         const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
     316             : 
     317         147 :         if (pal && size == AVPALETTE_SIZE) {
     318           4 :             memcpy(s->pal, pal, AVPALETTE_SIZE);
     319           4 :             s->frame->palette_has_changed = 1;
     320         143 :         } else if (pal) {
     321           0 :             av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
     322             :         }
     323             :     }
     324             : 
     325         327 :     if (s->mode_8bit)
     326         147 :         msvideo1_decode_8bit(s);
     327             :     else
     328         180 :         msvideo1_decode_16bit(s);
     329             : 
     330         327 :     if ((ret = av_frame_ref(data, s->frame)) < 0)
     331           0 :         return ret;
     332             : 
     333         327 :     *got_frame      = 1;
     334             : 
     335             :     /* report that the buffer was completely consumed */
     336         327 :     return buf_size;
     337             : }
     338             : 
     339          13 : static av_cold int msvideo1_decode_end(AVCodecContext *avctx)
     340             : {
     341          13 :     Msvideo1Context *s = avctx->priv_data;
     342             : 
     343          13 :     av_frame_free(&s->frame);
     344             : 
     345          13 :     return 0;
     346             : }
     347             : 
     348             : AVCodec ff_msvideo1_decoder = {
     349             :     .name           = "msvideo1",
     350             :     .long_name      = NULL_IF_CONFIG_SMALL("Microsoft Video 1"),
     351             :     .type           = AVMEDIA_TYPE_VIDEO,
     352             :     .id             = AV_CODEC_ID_MSVIDEO1,
     353             :     .priv_data_size = sizeof(Msvideo1Context),
     354             :     .init           = msvideo1_decode_init,
     355             :     .close          = msvideo1_decode_end,
     356             :     .decode         = msvideo1_decode_frame,
     357             :     .capabilities   = AV_CODEC_CAP_DR1,
     358             : };

Generated by: LCOV version 1.13