LCOV - code coverage report
Current view: top level - libavcodec - zerocodec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 51 63 81.0 %
Date: 2017-12-17 04:34:43 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * ZeroCodec Decoder
       3             :  *
       4             :  * Copyright (c) 2012, Derek Buitenhuis
       5             :  *
       6             :  * Permission to use, copy, modify, and/or distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <zlib.h>
      20             : 
      21             : #include "avcodec.h"
      22             : #include "internal.h"
      23             : #include "libavutil/common.h"
      24             : 
      25             : typedef struct ZeroCodecContext {
      26             :     AVFrame  *previous_frame;
      27             :     z_stream zstream;
      28             : } ZeroCodecContext;
      29             : 
      30          38 : static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
      31             :                                   int *got_frame, AVPacket *avpkt)
      32             : {
      33          38 :     ZeroCodecContext *zc = avctx->priv_data;
      34          38 :     AVFrame *pic         = data;
      35          38 :     AVFrame *prev_pic    = zc->previous_frame;
      36          38 :     z_stream *zstream    = &zc->zstream;
      37          38 :     uint8_t *prev        = prev_pic->data[0];
      38             :     uint8_t *dst;
      39             :     int i, j, zret, ret;
      40             : 
      41          38 :     if (avpkt->flags & AV_PKT_FLAG_KEY) {
      42           3 :         pic->key_frame = 1;
      43           3 :         pic->pict_type = AV_PICTURE_TYPE_I;
      44             :     } else {
      45          35 :         if (!prev) {
      46           0 :             av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
      47           0 :             return AVERROR_INVALIDDATA;
      48             :         }
      49             : 
      50          35 :         prev += (avctx->height - 1) * prev_pic->linesize[0];
      51             : 
      52          35 :         pic->key_frame = 0;
      53          35 :         pic->pict_type = AV_PICTURE_TYPE_P;
      54             :     }
      55             : 
      56          38 :     zret = inflateReset(zstream);
      57          38 :     if (zret != Z_OK) {
      58           0 :         av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret);
      59           0 :         return AVERROR_INVALIDDATA;
      60             :     }
      61             : 
      62          38 :     if ((ret = ff_get_buffer(avctx, pic, AV_GET_BUFFER_FLAG_REF)) < 0)
      63           0 :         return ret;
      64             : 
      65          38 :     zstream->next_in  = avpkt->data;
      66          38 :     zstream->avail_in = avpkt->size;
      67             : 
      68          38 :     dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
      69             : 
      70             :     /**
      71             :      * ZeroCodec has very simple interframe compression. If a value
      72             :      * is the same as the previous frame, set it to 0.
      73             :      */
      74             : 
      75       27398 :     for (i = 0; i < avctx->height; i++) {
      76       27360 :         zstream->next_out  = dst;
      77       27360 :         zstream->avail_out = avctx->width << 1;
      78             : 
      79       27360 :         zret = inflate(zstream, Z_SYNC_FLUSH);
      80       27360 :         if (zret != Z_OK && zret != Z_STREAM_END) {
      81           0 :             av_log(avctx, AV_LOG_ERROR,
      82             :                    "Inflate failed with return code: %d.\n", zret);
      83           0 :             return AVERROR_INVALIDDATA;
      84             :         }
      85             : 
      86       27360 :         if (!(avpkt->flags & AV_PKT_FLAG_KEY))
      87    64537200 :             for (j = 0; j < avctx->width << 1; j++)
      88    64512000 :                 dst[j] += prev[j] & -!dst[j];
      89             : 
      90       27360 :         prev -= prev_pic->linesize[0];
      91       27360 :         dst  -= pic->linesize[0];
      92             :     }
      93             : 
      94          38 :     av_frame_unref(zc->previous_frame);
      95          38 :     if ((ret = av_frame_ref(zc->previous_frame, pic)) < 0)
      96           0 :         return ret;
      97             : 
      98          38 :     *got_frame = 1;
      99             : 
     100          38 :     return avpkt->size;
     101             : }
     102             : 
     103           2 : static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
     104             : {
     105           2 :     ZeroCodecContext *zc = avctx->priv_data;
     106             : 
     107           2 :     av_frame_free(&zc->previous_frame);
     108             : 
     109           2 :     inflateEnd(&zc->zstream);
     110             : 
     111           2 :     return 0;
     112             : }
     113             : 
     114           2 : static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
     115             : {
     116           2 :     ZeroCodecContext *zc = avctx->priv_data;
     117           2 :     z_stream *zstream    = &zc->zstream;
     118             :     int zret;
     119             : 
     120           2 :     avctx->pix_fmt             = AV_PIX_FMT_UYVY422;
     121           2 :     avctx->bits_per_raw_sample = 8;
     122             : 
     123           2 :     zstream->zalloc = Z_NULL;
     124           2 :     zstream->zfree  = Z_NULL;
     125           2 :     zstream->opaque = Z_NULL;
     126             : 
     127           2 :     zret = inflateInit(zstream);
     128           2 :     if (zret != Z_OK) {
     129           0 :         av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret);
     130           0 :         return AVERROR(ENOMEM);
     131             :     }
     132             : 
     133           2 :     zc->previous_frame = av_frame_alloc();
     134           2 :     if (!zc->previous_frame) {
     135           0 :         zerocodec_decode_close(avctx);
     136           0 :         return AVERROR(ENOMEM);
     137             :     }
     138             : 
     139           2 :     return 0;
     140             : }
     141             : 
     142             : AVCodec ff_zerocodec_decoder = {
     143             :     .type           = AVMEDIA_TYPE_VIDEO,
     144             :     .name           = "zerocodec",
     145             :     .long_name      = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),
     146             :     .id             = AV_CODEC_ID_ZEROCODEC,
     147             :     .priv_data_size = sizeof(ZeroCodecContext),
     148             :     .init           = zerocodec_decode_init,
     149             :     .decode         = zerocodec_decode_frame,
     150             :     .close          = zerocodec_decode_close,
     151             :     .capabilities   = AV_CODEC_CAP_DR1,
     152             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     153             : };

Generated by: LCOV version 1.13