LCOV - code coverage report
Current view: top level - libavcodec - loco.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 112 170 65.9 %
Date: 2017-12-17 11:58:42 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * LOCO codec
       3             :  * Copyright (c) 2005 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             :  * LOCO codec.
      25             :  */
      26             : 
      27             : #include "avcodec.h"
      28             : #include "get_bits.h"
      29             : #include "golomb.h"
      30             : #include "internal.h"
      31             : #include "mathops.h"
      32             : 
      33             : enum LOCO_MODE {
      34             :     LOCO_UNKN  =  0,
      35             :     LOCO_CYUY2 = -1,
      36             :     LOCO_CRGB  = -2,
      37             :     LOCO_CRGBA = -3,
      38             :     LOCO_CYV12 = -4,
      39             :     LOCO_YUY2  =  1,
      40             :     LOCO_UYVY  =  2,
      41             :     LOCO_RGB   =  3,
      42             :     LOCO_RGBA  =  4,
      43             :     LOCO_YV12  =  5,
      44             : };
      45             : 
      46             : typedef struct LOCOContext {
      47             :     AVCodecContext *avctx;
      48             :     int lossy;
      49             :     enum LOCO_MODE mode;
      50             : } LOCOContext;
      51             : 
      52             : typedef struct RICEContext {
      53             :     GetBitContext gb;
      54             :     int save, run, run2; /* internal rice decoder state */
      55             :     int sum, count; /* sum and count for getting rice parameter */
      56             :     int lossy;
      57             : } RICEContext;
      58             : 
      59      500785 : static int loco_get_rice_param(RICEContext *r)
      60             : {
      61      500785 :     int cnt = 0;
      62      500785 :     int val = r->count;
      63             : 
      64     2889985 :     while (r->sum > val && cnt < 9) {
      65     1888415 :         val <<= 1;
      66     1888415 :         cnt++;
      67             :     }
      68             : 
      69      500785 :     return cnt;
      70             : }
      71             : 
      72      505344 : static inline void loco_update_rice_param(RICEContext *r, int val)
      73             : {
      74      505344 :     r->sum += val;
      75      505344 :     r->count++;
      76             : 
      77      505344 :     if (r->count == 16) {
      78       63144 :         r->sum   >>= 1;
      79       63144 :         r->count >>= 1;
      80             :     }
      81      505344 : }
      82             : 
      83      505344 : static inline int loco_get_rice(RICEContext *r)
      84             : {
      85             :     int v;
      86      505344 :     if (r->run > 0) { /* we have zero run */
      87        4559 :         r->run--;
      88        4559 :         loco_update_rice_param(r, 0);
      89        4559 :         return 0;
      90             :     }
      91      500785 :     v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
      92      500785 :     loco_update_rice_param(r, (v + 1) >> 1);
      93      500785 :     if (!v) {
      94       49474 :         if (r->save >= 0) {
      95        2574 :             r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
      96        2574 :             if (r->run > 1)
      97         901 :                 r->save += r->run + 1;
      98             :             else
      99        1673 :                 r->save -= 3;
     100             :         } else
     101       46900 :             r->run2++;
     102             :     } else {
     103      451311 :         v = ((v >> 1) + r->lossy) ^ -(v & 1);
     104      451311 :         if (r->run2 > 0) {
     105       27417 :             if (r->run2 > 2)
     106        3721 :                 r->save += r->run2;
     107             :             else
     108       23696 :                 r->save -= 3;
     109       27417 :             r->run2 = 0;
     110             :         }
     111             :     }
     112             : 
     113      500785 :     return v;
     114             : }
     115             : 
     116             : /* LOCO main predictor - LOCO-I/JPEG-LS predictor */
     117      498348 : static inline int loco_predict(uint8_t* data, int stride, int step)
     118             : {
     119             :     int a, b, c;
     120             : 
     121      498348 :     a = data[-stride];
     122      498348 :     b = data[-step];
     123      498348 :     c = data[-stride - step];
     124             : 
     125      498348 :     return mid_pred(a, a + b - c, b);
     126             : }
     127             : 
     128          24 : static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
     129             :                              int stride, const uint8_t *buf, int buf_size, int step)
     130             : {
     131             :     RICEContext rc;
     132             :     int val;
     133             :     int ret;
     134             :     int i, j;
     135             : 
     136          24 :     if(buf_size<=0)
     137           0 :         return -1;
     138             : 
     139          24 :     if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0)
     140           0 :         return ret;
     141             : 
     142          24 :     rc.save  = 0;
     143          24 :     rc.run   = 0;
     144          24 :     rc.run2  = 0;
     145          24 :     rc.lossy = l->lossy;
     146             : 
     147          24 :     rc.sum   = 8;
     148          24 :     rc.count = 1;
     149             : 
     150             :     /* restore top left pixel */
     151          24 :     val     = loco_get_rice(&rc);
     152          24 :     data[0] = 128 + val;
     153             :     /* restore top line */
     154        3948 :     for (i = 1; i < width; i++) {
     155        3924 :         val = loco_get_rice(&rc);
     156        3924 :         data[i * step] = data[i * step - step] + val;
     157             :     }
     158          24 :     data += stride;
     159        3072 :     for (j = 1; j < height; j++) {
     160             :         /* restore left column */
     161        3048 :         val = loco_get_rice(&rc);
     162        3048 :         data[0] = data[-stride] + val;
     163             :         /* restore all other pixels */
     164      501396 :         for (i = 1; i < width; i++) {
     165      498348 :             val = loco_get_rice(&rc);
     166      498348 :             data[i * step] = loco_predict(&data[i * step], stride, step) + val;
     167             :         }
     168        3048 :         data += stride;
     169             :     }
     170             : 
     171          24 :     return (get_bits_count(&rc.gb) + 7) >> 3;
     172             : }
     173             : 
     174           0 : static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride, int step)
     175             : {
     176             :     int y;
     177             : 
     178           0 :     for (y=1; y<height; y++) {
     179           0 :         if (width>=y) {
     180           0 :             memmove(data + y*stride,
     181           0 :                     data + y*(stride + step),
     182           0 :                     step*(width-y));
     183           0 :             if (y+1 < height)
     184           0 :                 memmove(data + y*stride + step*(width-y),
     185           0 :                         data + (y+1)*stride,
     186           0 :                         step*y);
     187             :         }
     188             :     }
     189           0 : }
     190             : 
     191           8 : static int decode_frame(AVCodecContext *avctx,
     192             :                         void *data, int *got_frame,
     193             :                         AVPacket *avpkt)
     194             : {
     195           8 :     LOCOContext * const l = avctx->priv_data;
     196           8 :     const uint8_t *buf    = avpkt->data;
     197           8 :     int buf_size          = avpkt->size;
     198           8 :     AVFrame * const p     = data;
     199             :     int decoded, ret;
     200             : 
     201           8 :     if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
     202           0 :         return ret;
     203           8 :     p->key_frame = 1;
     204             : 
     205             : #define ADVANCE_BY_DECODED do { \
     206             :     if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
     207             :     buf += decoded; buf_size -= decoded; \
     208             : } while(0)
     209           8 :     switch(l->mode) {
     210           3 :     case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
     211           3 :         decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
     212             :                                     p->linesize[0], buf, buf_size, 1);
     213           6 :         ADVANCE_BY_DECODED;
     214           3 :         decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
     215             :                                     p->linesize[1], buf, buf_size, 1);
     216           9 :         ADVANCE_BY_DECODED;
     217           3 :         decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
     218             :                                     p->linesize[2], buf, buf_size, 1);
     219           3 :         break;
     220           0 :     case LOCO_CYV12: case LOCO_YV12:
     221           0 :         decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
     222             :                                     p->linesize[0], buf, buf_size, 1);
     223           0 :         ADVANCE_BY_DECODED;
     224           0 :         decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
     225             :                                     p->linesize[2], buf, buf_size, 1);
     226           0 :         ADVANCE_BY_DECODED;
     227           0 :         decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
     228             :                                     p->linesize[1], buf, buf_size, 1);
     229           0 :         break;
     230           5 :     case LOCO_CRGB: case LOCO_RGB:
     231           5 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
     232           5 :                                     -p->linesize[0], buf, buf_size, 3);
     233          15 :         ADVANCE_BY_DECODED;
     234           5 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
     235           5 :                                     -p->linesize[0], buf, buf_size, 3);
     236          15 :         ADVANCE_BY_DECODED;
     237           5 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
     238           5 :                                     -p->linesize[0], buf, buf_size, 3);
     239           5 :         if (avctx->width & 1)
     240           0 :             rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0], 3);
     241           5 :         break;
     242           0 :     case LOCO_CRGBA:
     243             :     case LOCO_RGBA:
     244           0 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
     245           0 :                                     -p->linesize[0], buf, buf_size, 4);
     246           0 :         ADVANCE_BY_DECODED;
     247           0 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
     248           0 :                                     -p->linesize[0], buf, buf_size, 4);
     249           0 :         ADVANCE_BY_DECODED;
     250           0 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
     251           0 :                                     -p->linesize[0], buf, buf_size, 4);
     252           0 :         ADVANCE_BY_DECODED;
     253           0 :         decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height,
     254           0 :                                     -p->linesize[0], buf, buf_size, 4);
     255           0 :         break;
     256           0 :     default:
     257           0 :         av_assert0(0);
     258             :     }
     259             : 
     260          16 :     if (decoded < 0 || decoded > buf_size)
     261             :         goto buf_too_small;
     262           8 :     buf_size -= decoded;
     263             : 
     264           8 :     *got_frame      = 1;
     265             : 
     266           8 :     return avpkt->size - buf_size;
     267           0 : buf_too_small:
     268           0 :     av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
     269           0 :     return AVERROR(EINVAL);
     270             : }
     271             : 
     272           4 : static av_cold int decode_init(AVCodecContext *avctx)
     273             : {
     274           4 :     LOCOContext * const l = avctx->priv_data;
     275             :     int version;
     276             : 
     277           4 :     l->avctx = avctx;
     278           4 :     if (avctx->extradata_size < 12) {
     279           0 :         av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
     280             :                avctx->extradata_size);
     281           0 :         return AVERROR_INVALIDDATA;
     282             :     }
     283           4 :     version = AV_RL32(avctx->extradata);
     284           4 :     switch (version) {
     285           0 :     case 1:
     286           0 :         l->lossy = 0;
     287           0 :         break;
     288           4 :     case 2:
     289           4 :         l->lossy = AV_RL32(avctx->extradata + 8);
     290           4 :         break;
     291           0 :     default:
     292           0 :         l->lossy = AV_RL32(avctx->extradata + 8);
     293           0 :         avpriv_request_sample(avctx, "LOCO codec version %i", version);
     294             :     }
     295             : 
     296           4 :     l->mode = AV_RL32(avctx->extradata + 4);
     297           4 :     switch (l->mode) {
     298           2 :     case LOCO_CYUY2:
     299             :     case LOCO_YUY2:
     300             :     case LOCO_UYVY:
     301           2 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     302           2 :         break;
     303           2 :     case LOCO_CRGB:
     304             :     case LOCO_RGB:
     305           2 :         avctx->pix_fmt = AV_PIX_FMT_BGR24;
     306           2 :         break;
     307           0 :     case LOCO_CYV12:
     308             :     case LOCO_YV12:
     309           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     310           0 :         break;
     311           0 :     case LOCO_CRGBA:
     312             :     case LOCO_RGBA:
     313           0 :         avctx->pix_fmt = AV_PIX_FMT_BGRA;
     314           0 :         break;
     315           0 :     default:
     316           0 :         av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
     317           0 :         return AVERROR_INVALIDDATA;
     318             :     }
     319           4 :     if (avctx->debug & FF_DEBUG_PICT_INFO)
     320           0 :         av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
     321             : 
     322           4 :     return 0;
     323             : }
     324             : 
     325             : AVCodec ff_loco_decoder = {
     326             :     .name           = "loco",
     327             :     .long_name      = NULL_IF_CONFIG_SMALL("LOCO"),
     328             :     .type           = AVMEDIA_TYPE_VIDEO,
     329             :     .id             = AV_CODEC_ID_LOCO,
     330             :     .priv_data_size = sizeof(LOCOContext),
     331             :     .init           = decode_init,
     332             :     .decode         = decode_frame,
     333             :     .capabilities   = AV_CODEC_CAP_DR1,
     334             : };

Generated by: LCOV version 1.13