LCOV - code coverage report
Current view: top level - libavcodec - zmbvenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 169 0.0 %
Date: 2017-12-15 11:05:35 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Zip Motion Blocks Video (ZMBV) encoder
       3             :  * Copyright (c) 2006 Konstantin Shishkov
       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             :  * Zip Motion Blocks Video encoder
      25             :  */
      26             : 
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : 
      30             : #include "libavutil/common.h"
      31             : #include "libavutil/intreadwrite.h"
      32             : #include "avcodec.h"
      33             : #include "internal.h"
      34             : 
      35             : #include <zlib.h>
      36             : 
      37             : #define ZMBV_KEYFRAME 1
      38             : #define ZMBV_DELTAPAL 2
      39             : 
      40             : #define ZMBV_BLOCK 16
      41             : 
      42             : /**
      43             :  * Encoder context
      44             :  */
      45             : typedef struct ZmbvEncContext {
      46             :     AVCodecContext *avctx;
      47             : 
      48             :     int range;
      49             :     uint8_t *comp_buf, *work_buf;
      50             :     uint8_t pal[768];
      51             :     uint32_t pal2[256]; //for quick comparisons
      52             :     uint8_t *prev;
      53             :     int pstride;
      54             :     int comp_size;
      55             :     int keyint, curfrm;
      56             :     z_stream zstream;
      57             : 
      58             :     int score_tab[256];
      59             : } ZmbvEncContext;
      60             : 
      61             : 
      62             : /** Block comparing function
      63             :  * XXX should be optimized and moved to DSPContext
      64             :  * TODO handle out of edge ME
      65             :  */
      66           0 : static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
      67             :                             uint8_t *src2, int stride2, int bw, int bh,
      68             :                             int *xored)
      69             : {
      70           0 :     int sum = 0;
      71             :     int i, j;
      72           0 :     uint8_t histogram[256] = {0};
      73             : 
      74           0 :     *xored = 0;
      75           0 :     for(j = 0; j < bh; j++){
      76           0 :         for(i = 0; i < bw; i++){
      77           0 :             int t = src[i] ^ src2[i];
      78           0 :             histogram[t]++;
      79           0 :             *xored |= t;
      80             :         }
      81           0 :         src += stride;
      82           0 :         src2 += stride2;
      83             :     }
      84             : 
      85           0 :     for(i = 1; i < 256; i++)
      86           0 :         sum += c->score_tab[histogram[i]];
      87             : 
      88           0 :     return sum;
      89             : }
      90             : 
      91             : /** Motion estimation function
      92             :  * TODO make better ME decisions
      93             :  */
      94           0 : static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
      95             :                    int pstride, int x, int y, int *mx, int *my, int *xored)
      96             : {
      97             :     int dx, dy, tx, ty, tv, bv, bw, bh;
      98             : 
      99           0 :     *mx = *my = 0;
     100           0 :     bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x);
     101           0 :     bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y);
     102           0 :     bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored);
     103           0 :     if(!bv) return 0;
     104           0 :     for(ty = FFMAX(y - c->range, 0); ty < FFMIN(y + c->range, c->avctx->height - bh); ty++){
     105           0 :         for(tx = FFMAX(x - c->range, 0); tx < FFMIN(x + c->range, c->avctx->width - bw); tx++){
     106           0 :             if(tx == x && ty == y) continue; // we already tested this block
     107           0 :             dx = tx - x;
     108           0 :             dy = ty - y;
     109           0 :             tv = block_cmp(c, src, sstride, prev + dx + dy * pstride, pstride, bw, bh, xored);
     110           0 :             if(tv < bv){
     111           0 :                  bv = tv;
     112           0 :                  *mx = dx;
     113           0 :                  *my = dy;
     114           0 :                  if(!bv) return 0;
     115             :              }
     116             :          }
     117             :     }
     118           0 :     return bv;
     119             : }
     120             : 
     121           0 : static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     122             :                         const AVFrame *pict, int *got_packet)
     123             : {
     124           0 :     ZmbvEncContext * const c = avctx->priv_data;
     125           0 :     const AVFrame * const p = pict;
     126             :     uint8_t *src, *prev, *buf;
     127             :     uint32_t *palptr;
     128             :     int keyframe, chpal;
     129             :     int fl;
     130           0 :     int work_size = 0, pkt_size;
     131             :     int bw, bh;
     132             :     int i, j, ret;
     133             : 
     134           0 :     keyframe = !c->curfrm;
     135           0 :     c->curfrm++;
     136           0 :     if(c->curfrm == c->keyint)
     137           0 :         c->curfrm = 0;
     138             : #if FF_API_CODED_FRAME
     139             : FF_DISABLE_DEPRECATION_WARNINGS
     140           0 :     avctx->coded_frame->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
     141           0 :     avctx->coded_frame->key_frame = keyframe;
     142             : FF_ENABLE_DEPRECATION_WARNINGS
     143             : #endif
     144           0 :     chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
     145             : 
     146           0 :     palptr = (uint32_t*)p->data[1];
     147           0 :     src = p->data[0];
     148           0 :     prev = c->prev;
     149           0 :     if(chpal){
     150             :         uint8_t tpal[3];
     151           0 :         for(i = 0; i < 256; i++){
     152           0 :             AV_WB24(tpal, palptr[i]);
     153           0 :             c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0];
     154           0 :             c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1];
     155           0 :             c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2];
     156           0 :             c->pal[i * 3 + 0] = tpal[0];
     157           0 :             c->pal[i * 3 + 1] = tpal[1];
     158           0 :             c->pal[i * 3 + 2] = tpal[2];
     159             :         }
     160           0 :         memcpy(c->pal2, p->data[1], 1024);
     161             :     }
     162           0 :     if(keyframe){
     163           0 :         for(i = 0; i < 256; i++){
     164           0 :             AV_WB24(c->pal+(i*3), palptr[i]);
     165             :         }
     166           0 :         memcpy(c->work_buf, c->pal, 768);
     167           0 :         memcpy(c->pal2, p->data[1], 1024);
     168           0 :         work_size = 768;
     169           0 :         for(i = 0; i < avctx->height; i++){
     170           0 :             memcpy(c->work_buf + work_size, src, avctx->width);
     171           0 :             src += p->linesize[0];
     172           0 :             work_size += avctx->width;
     173             :         }
     174             :     }else{
     175             :         int x, y, bh2, bw2, xored;
     176             :         uint8_t *tsrc, *tprev;
     177             :         uint8_t *mv;
     178             :         int mx, my;
     179             : 
     180           0 :         bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
     181           0 :         bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
     182           0 :         mv = c->work_buf + work_size;
     183           0 :         memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
     184           0 :         work_size += (bw * bh * 2 + 3) & ~3;
     185             :         /* for now just XOR'ing */
     186           0 :         for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
     187           0 :             bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
     188           0 :             for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
     189           0 :                 bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
     190             : 
     191           0 :                 tsrc = src + x;
     192           0 :                 tprev = prev + x;
     193             : 
     194           0 :                 zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
     195           0 :                 mv[0] = (mx << 1) | !!xored;
     196           0 :                 mv[1] = my << 1;
     197           0 :                 tprev += mx + my * c->pstride;
     198           0 :                 if(xored){
     199           0 :                     for(j = 0; j < bh2; j++){
     200           0 :                         for(i = 0; i < bw2; i++)
     201           0 :                             c->work_buf[work_size++] = tsrc[i] ^ tprev[i];
     202           0 :                         tsrc += p->linesize[0];
     203           0 :                         tprev += c->pstride;
     204             :                     }
     205             :                 }
     206             :             }
     207           0 :             src += p->linesize[0] * ZMBV_BLOCK;
     208           0 :             prev += c->pstride * ZMBV_BLOCK;
     209             :         }
     210             :     }
     211             :     /* save the previous frame */
     212           0 :     src = p->data[0];
     213           0 :     prev = c->prev;
     214           0 :     for(i = 0; i < avctx->height; i++){
     215           0 :         memcpy(prev, src, avctx->width);
     216           0 :         prev += c->pstride;
     217           0 :         src += p->linesize[0];
     218             :     }
     219             : 
     220           0 :     if (keyframe)
     221           0 :         deflateReset(&c->zstream);
     222             : 
     223           0 :     c->zstream.next_in = c->work_buf;
     224           0 :     c->zstream.avail_in = work_size;
     225           0 :     c->zstream.total_in = 0;
     226             : 
     227           0 :     c->zstream.next_out = c->comp_buf;
     228           0 :     c->zstream.avail_out = c->comp_size;
     229           0 :     c->zstream.total_out = 0;
     230           0 :     if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){
     231           0 :         av_log(avctx, AV_LOG_ERROR, "Error compressing data\n");
     232           0 :         return -1;
     233             :     }
     234             : 
     235           0 :     pkt_size = c->zstream.total_out + 1 + 6*keyframe;
     236           0 :     if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size, 0)) < 0)
     237           0 :         return ret;
     238           0 :     buf = pkt->data;
     239             : 
     240           0 :     fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
     241           0 :     *buf++ = fl;
     242           0 :     if (keyframe) {
     243           0 :         *buf++ = 0; // hi ver
     244           0 :         *buf++ = 1; // lo ver
     245           0 :         *buf++ = 1; // comp
     246           0 :         *buf++ = 4; // format - 8bpp
     247           0 :         *buf++ = ZMBV_BLOCK; // block width
     248           0 :         *buf++ = ZMBV_BLOCK; // block height
     249             :     }
     250           0 :     memcpy(buf, c->comp_buf, c->zstream.total_out);
     251             : 
     252           0 :     pkt->flags |= AV_PKT_FLAG_KEY*keyframe;
     253           0 :     *got_packet = 1;
     254             : 
     255           0 :     return 0;
     256             : }
     257             : 
     258           0 : static av_cold int encode_end(AVCodecContext *avctx)
     259             : {
     260           0 :     ZmbvEncContext * const c = avctx->priv_data;
     261             : 
     262           0 :     av_freep(&c->comp_buf);
     263           0 :     av_freep(&c->work_buf);
     264             : 
     265           0 :     deflateEnd(&c->zstream);
     266           0 :     av_freep(&c->prev);
     267             : 
     268           0 :     return 0;
     269             : }
     270             : 
     271             : /**
     272             :  * Init zmbv encoder
     273             :  */
     274           0 : static av_cold int encode_init(AVCodecContext *avctx)
     275             : {
     276           0 :     ZmbvEncContext * const c = avctx->priv_data;
     277             :     int zret; // Zlib return code
     278             :     int i;
     279           0 :     int lvl = 9;
     280             : 
     281           0 :     for(i=1; i<256; i++)
     282           0 :         c->score_tab[i] = -i * log2(i / (double)(ZMBV_BLOCK * ZMBV_BLOCK)) * 256;
     283             : 
     284           0 :     c->avctx = avctx;
     285             : 
     286           0 :     c->curfrm = 0;
     287           0 :     c->keyint = avctx->keyint_min;
     288           0 :     c->range = 8;
     289           0 :     if(avctx->me_range > 0)
     290           0 :         c->range = FFMIN(avctx->me_range, 127);
     291             : 
     292           0 :     if(avctx->compression_level >= 0)
     293           0 :         lvl = avctx->compression_level;
     294           0 :     if(lvl < 0 || lvl > 9){
     295           0 :         av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
     296           0 :         return AVERROR(EINVAL);
     297             :     }
     298             : 
     299             :     // Needed if zlib unused or init aborted before deflateInit
     300           0 :     memset(&c->zstream, 0, sizeof(z_stream));
     301           0 :     c->comp_size = avctx->width * avctx->height + 1024 +
     302           0 :         ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
     303           0 :     if (!(c->work_buf = av_malloc(c->comp_size))) {
     304           0 :         av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
     305           0 :         return AVERROR(ENOMEM);
     306             :     }
     307             :     /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
     308           0 :     c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
     309           0 :                            ((c->comp_size + 63) >> 6) + 11;
     310             : 
     311             :     /* Allocate compression buffer */
     312           0 :     if (!(c->comp_buf = av_malloc(c->comp_size))) {
     313           0 :         av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
     314           0 :         return AVERROR(ENOMEM);
     315             :     }
     316           0 :     c->pstride = FFALIGN(avctx->width, 16);
     317           0 :     if (!(c->prev = av_malloc(c->pstride * avctx->height))) {
     318           0 :         av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
     319           0 :         return AVERROR(ENOMEM);
     320             :     }
     321             : 
     322           0 :     c->zstream.zalloc = Z_NULL;
     323           0 :     c->zstream.zfree = Z_NULL;
     324           0 :     c->zstream.opaque = Z_NULL;
     325           0 :     zret = deflateInit(&c->zstream, lvl);
     326           0 :     if (zret != Z_OK) {
     327           0 :         av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
     328           0 :         return -1;
     329             :     }
     330             : 
     331           0 :     return 0;
     332             : }
     333             : 
     334             : AVCodec ff_zmbv_encoder = {
     335             :     .name           = "zmbv",
     336             :     .long_name      = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
     337             :     .type           = AVMEDIA_TYPE_VIDEO,
     338             :     .id             = AV_CODEC_ID_ZMBV,
     339             :     .priv_data_size = sizeof(ZmbvEncContext),
     340             :     .init           = encode_init,
     341             :     .encode2        = encode_frame,
     342             :     .close          = encode_end,
     343             :     .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE },
     344             : };

Generated by: LCOV version 1.13