LCOV - code coverage report
Current view: top level - libavcodec - truemotion2rt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 93 104 89.4 %
Date: 2017-12-17 16:07:53 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Duck TrueMotion 2.0 Real Time decoder
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : 
      25             : #include "libavutil/imgutils.h"
      26             : #include "libavutil/internal.h"
      27             : #include "libavutil/intreadwrite.h"
      28             : #include "libavutil/mem.h"
      29             : 
      30             : #define BITSTREAM_READER_LE
      31             : #include "avcodec.h"
      32             : #include "get_bits.h"
      33             : #include "internal.h"
      34             : 
      35             : typedef struct TrueMotion2RTContext {
      36             :     GetBitContext gb;
      37             :     int delta_size;
      38             :     int hscale;
      39             : } TrueMotion2RTContext;
      40             : 
      41             : static const int16_t delta_tab2[] = {
      42             :     5, -7, 36, -36,
      43             : };
      44             : 
      45             : static const int16_t delta_tab3[] = {
      46             :     2, -3, 8, -8, 18, -18, 36, -36,
      47             : };
      48             : 
      49             : static const int16_t delta_tab4[] = {
      50             :     1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144,
      51             : };
      52             : 
      53             : static const int16_t *const delta_tabs[] = {
      54             :     delta_tab2, delta_tab3, delta_tab4,
      55             : };
      56             : 
      57             : /* Returns the number of bytes consumed from the bytestream, or
      58             :  * AVERROR_INVALIDDATA if there was an error while decoding the header. */
      59           3 : static int truemotion2rt_decode_header(AVCodecContext *avctx, const AVPacket *avpkt)
      60             : {
      61           3 :     TrueMotion2RTContext *s = avctx->priv_data;
      62             :     int header_size;
      63           3 :     uint8_t header_buffer[128] = { 0 };  /* logical maximum header size */
      64           3 :     const uint8_t *buf = avpkt->data;
      65           3 :     int size = avpkt->size;
      66             :     int width, height;
      67             :     int ret, i;
      68             : 
      69           3 :     if (size < 1) {
      70           0 :         av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size);
      71           0 :         return AVERROR_INVALIDDATA;
      72             :     }
      73             : 
      74           3 :     header_size = ((buf[0] >> 5) | (buf[0] << 3)) & 0x7f;
      75           3 :     if (header_size < 10) {
      76           0 :         av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size);
      77           0 :         return AVERROR_INVALIDDATA;
      78             :     }
      79             : 
      80           3 :     if (header_size + 1 > size) {
      81           0 :         av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size);
      82           0 :         return AVERROR_INVALIDDATA;
      83             :     }
      84             : 
      85             :     /* unscramble the header bytes with a XOR operation */
      86          60 :     for (i = 1; i < header_size; i++)
      87          57 :         header_buffer[i - 1] = buf[i] ^ buf[i + 1];
      88             : 
      89           3 :     s->delta_size = header_buffer[1];
      90           3 :     s->hscale = 1 + !!header_buffer[3];
      91           3 :     if (s->delta_size < 2 || s->delta_size > 4)
      92           0 :         return AVERROR_INVALIDDATA;
      93             : 
      94           3 :     height = AV_RL16(header_buffer + 5);
      95           3 :     width  = AV_RL16(header_buffer + 7);
      96             : 
      97           3 :     ret = ff_set_dimensions(avctx, width, height);
      98           3 :     if (ret < 0)
      99           0 :         return ret;
     100             : 
     101           3 :     av_log(avctx, AV_LOG_DEBUG, "Header size: %d\n", header_size);
     102           3 :     return header_size;
     103             : }
     104             : 
     105           3 : static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data,
     106             :                                       int *got_frame, AVPacket *avpkt)
     107             : {
     108           3 :     TrueMotion2RTContext *s = avctx->priv_data;
     109           3 :     AVFrame * const p = data;
     110           3 :     GetBitContext *gb = &s->gb;
     111             :     uint8_t *dst;
     112             :     int x, y, delta_mode;
     113             :     int ret;
     114             : 
     115           3 :     ret = truemotion2rt_decode_header(avctx, avpkt);
     116           3 :     if (ret < 0)
     117           0 :         return ret;
     118             : 
     119           3 :     ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret);
     120           3 :     if (ret < 0)
     121           0 :         return ret;
     122             : 
     123           3 :     ret = ff_get_buffer(avctx, p, 0);
     124           3 :     if (ret < 0)
     125           0 :         return ret;
     126             : 
     127           3 :     skip_bits(gb, 32);
     128           3 :     delta_mode = s->delta_size - 2;
     129           3 :     dst = p->data[0];
     130         663 :     for (y = 0; y < avctx->height; y++) {
     131         660 :         int diff = 0;
     132       93428 :         for (x = 0; x < avctx->width; x += s->hscale) {
     133       92768 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     134       92768 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff);
     135             :         }
     136         660 :         dst += p->linesize[0];
     137             :     }
     138             : 
     139           3 :     if (s->hscale > 1) {
     140           2 :         dst = p->data[0];
     141         430 :         for (y = 0; y < avctx->height; y++) {
     142       44940 :             for (x = 1; x < avctx->width; x += s->hscale)
     143       44512 :                 dst[x] = dst[x - 1];
     144         428 :             dst += p->linesize[0];
     145             :         }
     146             :     }
     147             : 
     148           3 :     dst = p->data[0];
     149         663 :     for (y = 0; y < avctx->height; y++) {
     150      137940 :         for (x = 0; x < avctx->width; x++)
     151      137280 :             dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3);
     152         660 :         dst += p->linesize[0];
     153             :     }
     154             : 
     155           3 :     dst = p->data[1];
     156         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     157         165 :         int diff = 0;
     158        5963 :         for (x = 0; x < avctx->width >> 2; x += s->hscale) {
     159        5798 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     160        5798 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff);
     161             :         }
     162         165 :         dst += p->linesize[1];
     163             :     }
     164             : 
     165           3 :     if (s->hscale > 1) {
     166           2 :         dst = p->data[1];
     167         109 :         for (y = 0; y < avctx->height >> 2; y++) {
     168        2889 :             for (x = 1; x < avctx->width >> 2; x += s->hscale)
     169        2782 :                 dst[x] = dst[x - 1];
     170         107 :             dst += p->linesize[1];
     171             :         }
     172             :     }
     173             : 
     174           3 :     dst = p->data[1];
     175         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     176        8745 :         for (x = 0; x < avctx->width >> 2; x++)
     177        8580 :             dst[x] += (dst[x] - 128) / 8;
     178         165 :         dst += p->linesize[1];
     179             :     }
     180             : 
     181           3 :     dst = p->data[2];
     182         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     183         165 :         int diff = 0;
     184        5963 :         for (x = 0; x < avctx->width >> 2; x += s->hscale) {
     185        5798 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     186        5798 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff);
     187             :         }
     188         165 :         dst += p->linesize[2];
     189             :     }
     190             : 
     191           3 :     if (s->hscale > 1) {
     192           2 :         dst = p->data[2];
     193         109 :         for (y = 0; y < avctx->height >> 2; y++) {
     194        2889 :             for (x = 1; x < avctx->width >> 2; x += s->hscale)
     195        2782 :                 dst[x] = dst[x - 1];
     196         107 :             dst += p->linesize[2];
     197             :         }
     198             :     }
     199             : 
     200           3 :     dst = p->data[2];
     201         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     202        8745 :         for (x = 0; x < avctx->width >> 2; x++)
     203        8580 :             dst[x] += (dst[x] - 128) / 8;
     204         165 :         dst += p->linesize[2];
     205             :     }
     206             : 
     207           3 :     p->pict_type = AV_PICTURE_TYPE_I;
     208           3 :     p->key_frame = 1;
     209           3 :     *got_frame = 1;
     210             : 
     211           3 :     return avpkt->size;
     212             : }
     213             : 
     214           6 : static av_cold int truemotion2rt_decode_init(AVCodecContext *avctx)
     215             : {
     216           6 :     avctx->pix_fmt = AV_PIX_FMT_YUV410P;
     217           6 :     return 0;
     218             : }
     219             : 
     220             : AVCodec ff_truemotion2rt_decoder = {
     221             :     .name           = "truemotion2rt",
     222             :     .long_name      = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
     223             :     .type           = AVMEDIA_TYPE_VIDEO,
     224             :     .id             = AV_CODEC_ID_TRUEMOTION2RT,
     225             :     .priv_data_size = sizeof(TrueMotion2RTContext),
     226             :     .init           = truemotion2rt_decode_init,
     227             :     .decode         = truemotion2rt_decode_frame,
     228             :     .capabilities   = AV_CODEC_CAP_DR1,
     229             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     230             : };

Generated by: LCOV version 1.13