LCOV - code coverage report
Current view: top level - libavcodec - jvdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 112 120 93.3 %
Date: 2017-12-17 04:34:43 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Bitmap Brothers JV video decoder
       3             :  * Copyright (c) 2011 Peter Ross <pross@xvid.org>
       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             :  * Bitmap Brothers JV video decoder
      25             :  * @author Peter Ross <pross@xvid.org>
      26             :  */
      27             : 
      28             : #include "libavutil/intreadwrite.h"
      29             : 
      30             : #include "avcodec.h"
      31             : #include "blockdsp.h"
      32             : #include "get_bits.h"
      33             : #include "internal.h"
      34             : 
      35             : typedef struct JvContext {
      36             :     BlockDSPContext bdsp;
      37             :     AVFrame   *frame;
      38             :     uint32_t   palette[AVPALETTE_COUNT];
      39             :     int        palette_has_changed;
      40             : } JvContext;
      41             : 
      42           3 : static av_cold int decode_init(AVCodecContext *avctx)
      43             : {
      44           3 :     JvContext *s = avctx->priv_data;
      45             : 
      46           6 :     if (!avctx->width || !avctx->height ||
      47           6 :         (avctx->width & 7) || (avctx->height & 7)) {
      48           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid video dimensions: %dx%d\n",
      49             :                avctx->width, avctx->height);
      50           0 :         return AVERROR(EINVAL);
      51             :     }
      52             : 
      53           3 :     s->frame = av_frame_alloc();
      54           3 :     if (!s->frame)
      55           0 :         return AVERROR(ENOMEM);
      56             : 
      57           3 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
      58           3 :     ff_blockdsp_init(&s->bdsp, avctx);
      59           3 :     return 0;
      60             : }
      61             : 
      62             : /**
      63             :  * Decode 2x2 block
      64             :  */
      65       14056 : static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize)
      66             : {
      67             :     int i, j, v[2];
      68             : 
      69       14056 :     switch (get_bits(gb, 2)) {
      70         348 :     case 1:
      71         348 :         v[0] = get_bits(gb, 8);
      72        1044 :         for (j = 0; j < 2; j++)
      73         696 :             memset(dst + j * linesize, v[0], 2);
      74         348 :         break;
      75        9984 :     case 2:
      76        9984 :         v[0] = get_bits(gb, 8);
      77        9984 :         v[1] = get_bits(gb, 8);
      78       29952 :         for (j = 0; j < 2; j++)
      79       59904 :             for (i = 0; i < 2; i++)
      80       39936 :                 dst[j * linesize + i] = v[get_bits1(gb)];
      81        9984 :         break;
      82          51 :     case 3:
      83         153 :         for (j = 0; j < 2; j++)
      84         306 :             for (i = 0; i < 2; i++)
      85         204 :                 dst[j * linesize + i] = get_bits(gb, 8);
      86             :     }
      87       14056 : }
      88             : 
      89             : /**
      90             :  * Decode 4x4 block
      91             :  */
      92       17028 : static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize)
      93             : {
      94             :     int i, j, v[2];
      95             : 
      96       17028 :     switch (get_bits(gb, 2)) {
      97         139 :     case 1:
      98         139 :         v[0] = get_bits(gb, 8);
      99         695 :         for (j = 0; j < 4; j++)
     100         556 :             memset(dst + j * linesize, v[0], 4);
     101         139 :         break;
     102       11062 :     case 2:
     103       11062 :         v[0] = get_bits(gb, 8);
     104       11062 :         v[1] = get_bits(gb, 8);
     105       33186 :         for (j = 2; j >= 0; j -= 2) {
     106      110620 :             for (i = 0; i < 4; i++)
     107       88496 :                 dst[j * linesize + i] = v[get_bits1(gb)];
     108      110620 :             for (i = 0; i < 4; i++)
     109       88496 :                 dst[(j + 1) * linesize + i] = v[get_bits1(gb)];
     110             :         }
     111       11062 :         break;
     112        3514 :     case 3:
     113       10542 :         for (j = 0; j < 4; j += 2)
     114       21084 :             for (i = 0; i < 4; i += 2)
     115       14056 :                 decode2x2(gb, dst + j * linesize + i, linesize);
     116             :     }
     117       17028 : }
     118             : 
     119             : /**
     120             :  * Decode 8x8 block
     121             :  */
     122        6000 : static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize,
     123             :                              BlockDSPContext *bdsp)
     124             : {
     125             :     int i, j, v[2];
     126             : 
     127        6000 :     switch (get_bits(gb, 2)) {
     128          29 :     case 1:
     129          29 :         v[0] = get_bits(gb, 8);
     130          29 :         bdsp->fill_block_tab[1](dst, v[0], linesize, 8);
     131          29 :         break;
     132         218 :     case 2:
     133         218 :         v[0] = get_bits(gb, 8);
     134         218 :         v[1] = get_bits(gb, 8);
     135        1962 :         for (j = 7; j >= 0; j--)
     136       15696 :             for (i = 0; i < 8; i++)
     137       13952 :                 dst[j * linesize + i] = v[get_bits1(gb)];
     138         218 :         break;
     139        4257 :     case 3:
     140       12771 :         for (j = 0; j < 8; j += 4)
     141       25542 :             for (i = 0; i < 8; i += 4)
     142       17028 :                 decode4x4(gb, dst + j * linesize + i, linesize);
     143             :     }
     144        6000 : }
     145             : 
     146           9 : static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     147             :                         AVPacket *avpkt)
     148             : {
     149           9 :     JvContext *s = avctx->priv_data;
     150           9 :     const uint8_t *buf = avpkt->data;
     151           9 :     const uint8_t *buf_end = buf + avpkt->size;
     152             :     int video_size, video_type, i, j, ret;
     153             : 
     154           9 :     if (avpkt->size < 6)
     155           0 :         return AVERROR_INVALIDDATA;
     156             : 
     157           9 :     video_size = AV_RL32(buf);
     158           9 :     video_type = buf[4];
     159           9 :     buf += 5;
     160             : 
     161           9 :     if (video_size) {
     162           8 :         if (video_size < 0 || video_size > avpkt->size - 5) {
     163           1 :             av_log(avctx, AV_LOG_ERROR, "video size %d invalid\n", video_size);
     164           1 :             return AVERROR_INVALIDDATA;
     165             :         }
     166           7 :         if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
     167           0 :             return ret;
     168             : 
     169          13 :         if (video_type == 0 || video_type == 1) {
     170             :             GetBitContext gb;
     171           6 :             init_get_bits(&gb, buf, 8 * video_size);
     172             : 
     173         156 :             for (j = 0; j < avctx->height; j += 8)
     174        6150 :                 for (i = 0; i < avctx->width; i += 8)
     175       18000 :                     decode8x8(&gb,
     176        6000 :                               s->frame->data[0] + j * s->frame->linesize[0] + i,
     177        6000 :                               s->frame->linesize[0], &s->bdsp);
     178             : 
     179           6 :             buf += video_size;
     180           1 :         } else if (video_type == 2) {
     181           1 :             int v = *buf++;
     182         201 :             for (j = 0; j < avctx->height; j++)
     183         200 :                 memset(s->frame->data[0] + j * s->frame->linesize[0],
     184         200 :                        v, avctx->width);
     185             :         } else {
     186           0 :             av_log(avctx, AV_LOG_WARNING,
     187             :                    "unsupported frame type %i\n", video_type);
     188           0 :             return AVERROR_INVALIDDATA;
     189             :         }
     190             :     }
     191             : 
     192           8 :     if (buf_end - buf >= AVPALETTE_COUNT * 3) {
     193         257 :         for (i = 0; i < AVPALETTE_COUNT; i++) {
     194         256 :             uint32_t pal = AV_RB24(buf);
     195         256 :             s->palette[i] = 0xFFU << 24 | pal << 2 | ((pal >> 4) & 0x30303);
     196         256 :             buf += 3;
     197             :         }
     198           1 :         s->palette_has_changed = 1;
     199             :     }
     200             : 
     201           8 :     if (video_size) {
     202           7 :         s->frame->key_frame           = 1;
     203           7 :         s->frame->pict_type           = AV_PICTURE_TYPE_I;
     204           7 :         s->frame->palette_has_changed = s->palette_has_changed;
     205           7 :         s->palette_has_changed        = 0;
     206           7 :         memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
     207             : 
     208           7 :         if ((ret = av_frame_ref(data, s->frame)) < 0)
     209           0 :             return ret;
     210           7 :         *got_frame = 1;
     211             :     }
     212             : 
     213           8 :     return avpkt->size;
     214             : }
     215             : 
     216           3 : static av_cold int decode_close(AVCodecContext *avctx)
     217             : {
     218           3 :     JvContext *s = avctx->priv_data;
     219             : 
     220           3 :     av_frame_free(&s->frame);
     221             : 
     222           3 :     return 0;
     223             : }
     224             : 
     225             : AVCodec ff_jv_decoder = {
     226             :     .name           = "jv",
     227             :     .long_name      = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"),
     228             :     .type           = AVMEDIA_TYPE_VIDEO,
     229             :     .id             = AV_CODEC_ID_JV,
     230             :     .priv_data_size = sizeof(JvContext),
     231             :     .init           = decode_init,
     232             :     .close          = decode_close,
     233             :     .decode         = decode_frame,
     234             :     .capabilities   = AV_CODEC_CAP_DR1,
     235             : };

Generated by: LCOV version 1.13