LCOV - code coverage report
Current view: top level - libavcodec - truemotion2rt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 94 106 88.7 %
Date: 2018-05-20 11:54:08 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 :     if (avctx->width / s->hscale * avctx->height * s->delta_size > avpkt->size * 8LL * 4)
     120           0 :         return AVERROR_INVALIDDATA;
     121             : 
     122           3 :     ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret);
     123           3 :     if (ret < 0)
     124           0 :         return ret;
     125             : 
     126           3 :     ret = ff_get_buffer(avctx, p, 0);
     127           3 :     if (ret < 0)
     128           0 :         return ret;
     129             : 
     130           3 :     skip_bits(gb, 32);
     131           3 :     delta_mode = s->delta_size - 2;
     132           3 :     dst = p->data[0];
     133         663 :     for (y = 0; y < avctx->height; y++) {
     134         660 :         int diff = 0;
     135       93428 :         for (x = 0; x < avctx->width; x += s->hscale) {
     136       92768 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     137       92768 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff);
     138             :         }
     139         660 :         dst += p->linesize[0];
     140             :     }
     141             : 
     142           3 :     if (s->hscale > 1) {
     143           2 :         dst = p->data[0];
     144         430 :         for (y = 0; y < avctx->height; y++) {
     145       44940 :             for (x = 1; x < avctx->width; x += s->hscale)
     146       44512 :                 dst[x] = dst[x - 1];
     147         428 :             dst += p->linesize[0];
     148             :         }
     149             :     }
     150             : 
     151           3 :     dst = p->data[0];
     152         663 :     for (y = 0; y < avctx->height; y++) {
     153      137940 :         for (x = 0; x < avctx->width; x++)
     154      137280 :             dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3);
     155         660 :         dst += p->linesize[0];
     156             :     }
     157             : 
     158           3 :     dst = p->data[1];
     159         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     160         165 :         int diff = 0;
     161        5963 :         for (x = 0; x < avctx->width >> 2; x += s->hscale) {
     162        5798 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     163        5798 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff);
     164             :         }
     165         165 :         dst += p->linesize[1];
     166             :     }
     167             : 
     168           3 :     if (s->hscale > 1) {
     169           2 :         dst = p->data[1];
     170         109 :         for (y = 0; y < avctx->height >> 2; y++) {
     171        2889 :             for (x = 1; x < avctx->width >> 2; x += s->hscale)
     172        2782 :                 dst[x] = dst[x - 1];
     173         107 :             dst += p->linesize[1];
     174             :         }
     175             :     }
     176             : 
     177           3 :     dst = p->data[1];
     178         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     179        8745 :         for (x = 0; x < avctx->width >> 2; x++)
     180        8580 :             dst[x] += (dst[x] - 128) / 8;
     181         165 :         dst += p->linesize[1];
     182             :     }
     183             : 
     184           3 :     dst = p->data[2];
     185         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     186         165 :         int diff = 0;
     187        5963 :         for (x = 0; x < avctx->width >> 2; x += s->hscale) {
     188        5798 :             diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
     189        5798 :             dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff);
     190             :         }
     191         165 :         dst += p->linesize[2];
     192             :     }
     193             : 
     194           3 :     if (s->hscale > 1) {
     195           2 :         dst = p->data[2];
     196         109 :         for (y = 0; y < avctx->height >> 2; y++) {
     197        2889 :             for (x = 1; x < avctx->width >> 2; x += s->hscale)
     198        2782 :                 dst[x] = dst[x - 1];
     199         107 :             dst += p->linesize[2];
     200             :         }
     201             :     }
     202             : 
     203           3 :     dst = p->data[2];
     204         168 :     for (y = 0; y < avctx->height >> 2; y++) {
     205        8745 :         for (x = 0; x < avctx->width >> 2; x++)
     206        8580 :             dst[x] += (dst[x] - 128) / 8;
     207         165 :         dst += p->linesize[2];
     208             :     }
     209             : 
     210           3 :     p->pict_type = AV_PICTURE_TYPE_I;
     211           3 :     p->key_frame = 1;
     212           3 :     *got_frame = 1;
     213             : 
     214           3 :     return avpkt->size;
     215             : }
     216             : 
     217           6 : static av_cold int truemotion2rt_decode_init(AVCodecContext *avctx)
     218             : {
     219           6 :     avctx->pix_fmt = AV_PIX_FMT_YUV410P;
     220           6 :     return 0;
     221             : }
     222             : 
     223             : AVCodec ff_truemotion2rt_decoder = {
     224             :     .name           = "truemotion2rt",
     225             :     .long_name      = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
     226             :     .type           = AVMEDIA_TYPE_VIDEO,
     227             :     .id             = AV_CODEC_ID_TRUEMOTION2RT,
     228             :     .priv_data_size = sizeof(TrueMotion2RTContext),
     229             :     .init           = truemotion2rt_decode_init,
     230             :     .decode         = truemotion2rt_decode_frame,
     231             :     .capabilities   = AV_CODEC_CAP_DR1,
     232             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     233             : };

Generated by: LCOV version 1.13