LCOV - code coverage report
Current view: top level - libavcodec - lagarith.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 303 405 74.8 %
Date: 2017-12-15 18:13:28 Functions: 13 15 86.7 %

          Line data    Source code
       1             : /*
       2             :  * Lagarith lossless decoder
       3             :  * Copyright (c) 2009 Nathan Caldwell <saintdev (at) gmail.com>
       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             :  * Lagarith lossless decoder
      25             :  * @author Nathan Caldwell
      26             :  */
      27             : 
      28             : #include <inttypes.h>
      29             : 
      30             : #include "avcodec.h"
      31             : #include "get_bits.h"
      32             : #include "mathops.h"
      33             : #include "lagarithrac.h"
      34             : #include "lossless_videodsp.h"
      35             : #include "thread.h"
      36             : 
      37             : enum LagarithFrameType {
      38             :     FRAME_RAW           = 1,    /**< uncompressed */
      39             :     FRAME_U_RGB24       = 2,    /**< unaligned RGB24 */
      40             :     FRAME_ARITH_YUY2    = 3,    /**< arithmetic coded YUY2 */
      41             :     FRAME_ARITH_RGB24   = 4,    /**< arithmetic coded RGB24 */
      42             :     FRAME_SOLID_GRAY    = 5,    /**< solid grayscale color frame */
      43             :     FRAME_SOLID_COLOR   = 6,    /**< solid non-grayscale color frame */
      44             :     FRAME_OLD_ARITH_RGB = 7,    /**< obsolete arithmetic coded RGB (no longer encoded by upstream since version 1.1.0) */
      45             :     FRAME_ARITH_RGBA    = 8,    /**< arithmetic coded RGBA */
      46             :     FRAME_SOLID_RGBA    = 9,    /**< solid RGBA color frame */
      47             :     FRAME_ARITH_YV12    = 10,   /**< arithmetic coded YV12 */
      48             :     FRAME_REDUCED_RES   = 11,   /**< reduced resolution YV12 frame */
      49             : };
      50             : 
      51             : typedef struct LagarithContext {
      52             :     AVCodecContext *avctx;
      53             :     LLVidDSPContext llviddsp;
      54             :     int zeros;                  /**< number of consecutive zero bytes encountered */
      55             :     int zeros_rem;              /**< number of zero bytes remaining to output */
      56             :     uint8_t *rgb_planes;
      57             :     int      rgb_planes_allocated;
      58             :     int rgb_stride;
      59             : } LagarithContext;
      60             : 
      61             : /**
      62             :  * Compute the 52-bit mantissa of 1/(double)denom.
      63             :  * This crazy format uses floats in an entropy coder and we have to match x86
      64             :  * rounding exactly, thus ordinary floats aren't portable enough.
      65             :  * @param denom denominator
      66             :  * @return 52-bit mantissa
      67             :  * @see softfloat_mul
      68             :  */
      69         128 : static uint64_t softfloat_reciprocal(uint32_t denom)
      70             : {
      71         128 :     int shift = av_log2(denom - 1) + 1;
      72         128 :     uint64_t ret = (1ULL << 52) / denom;
      73         128 :     uint64_t err = (1ULL << 52) - ret * denom;
      74         128 :     ret <<= shift;
      75         128 :     err <<= shift;
      76         128 :     err +=  denom / 2;
      77         128 :     return ret + err / denom;
      78             : }
      79             : 
      80             : /**
      81             :  * (uint32_t)(x*f), where f has the given mantissa, and exponent 0
      82             :  * Used in combination with softfloat_reciprocal computes x/(double)denom.
      83             :  * @param x 32-bit integer factor
      84             :  * @param mantissa mantissa of f with exponent 0
      85             :  * @return 32-bit integer value (x*f)
      86             :  * @see softfloat_reciprocal
      87             :  */
      88       32768 : static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa)
      89             : {
      90       32768 :     uint64_t l = x * (mantissa & 0xffffffff);
      91       32768 :     uint64_t h = x * (mantissa >> 32);
      92       32768 :     h += l >> 32;
      93       32768 :     l &= 0xffffffff;
      94       32768 :     l += 1LL << av_log2(h >> 21);
      95       32768 :     h += l >> 32;
      96       32768 :     return h >> 20;
      97             : }
      98             : 
      99      466504 : static uint8_t lag_calc_zero_run(int8_t x)
     100             : {
     101      466504 :     return (x * 2) ^ (x >> 7);
     102             : }
     103             : 
     104       21472 : static int lag_decode_prob(GetBitContext *gb, uint32_t *value)
     105             : {
     106             :     static const uint8_t series[] = { 1, 2, 3, 5, 8, 13, 21 };
     107             :     int i;
     108       21472 :     int bit     = 0;
     109       21472 :     int bits    = 0;
     110       21472 :     int prevbit = 0;
     111             :     unsigned val;
     112             : 
     113       99357 :     for (i = 0; i < 7; i++) {
     114       99255 :         if (prevbit && bit)
     115       21370 :             break;
     116       77885 :         prevbit = bit;
     117       77885 :         bit = get_bits1(gb);
     118       77885 :         if (bit && !prevbit)
     119       26960 :             bits += series[i];
     120             :     }
     121       21472 :     bits--;
     122       21472 :     if (bits < 0 || bits > 31) {
     123           0 :         *value = 0;
     124           0 :         return -1;
     125       21472 :     } else if (bits == 0) {
     126        3939 :         *value = 0;
     127        3939 :         return 0;
     128             :     }
     129             : 
     130       17533 :     val  = get_bits_long(gb, bits);
     131       17533 :     val |= 1U << bits;
     132             : 
     133       17533 :     *value = val - 1;
     134             : 
     135       17533 :     return 0;
     136             : }
     137             : 
     138         130 : static int lag_read_prob_header(lag_rac *rac, GetBitContext *gb)
     139             : {
     140             :     int i, j, scale_factor;
     141             :     unsigned prob, cumulative_target;
     142         130 :     unsigned cumul_prob = 0;
     143         130 :     unsigned scaled_cumul_prob = 0;
     144             : 
     145         130 :     rac->prob[0] = 0;
     146         130 :     rac->prob[257] = UINT_MAX;
     147             :     /* Read probabilities from bitstream */
     148       18868 :     for (i = 1; i < 257; i++) {
     149       18738 :         if (lag_decode_prob(gb, &rac->prob[i]) < 0) {
     150           0 :             av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability encountered.\n");
     151           0 :             return -1;
     152             :         }
     153       18738 :         if ((uint64_t)cumul_prob + rac->prob[i] > UINT_MAX) {
     154           0 :             av_log(rac->avctx, AV_LOG_ERROR, "Integer overflow encountered in cumulative probability calculation.\n");
     155           0 :             return -1;
     156             :         }
     157       18738 :         cumul_prob += rac->prob[i];
     158       18738 :         if (!rac->prob[i]) {
     159        2734 :             if (lag_decode_prob(gb, &prob)) {
     160           0 :                 av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability run encountered.\n");
     161           0 :                 return -1;
     162             :             }
     163        2734 :             if (prob > 256 - i)
     164           0 :                 prob = 256 - i;
     165       17276 :             for (j = 0; j < prob; j++)
     166       14542 :                 rac->prob[++i] = 0;
     167             :         }
     168             :     }
     169             : 
     170         130 :     if (!cumul_prob) {
     171           0 :         av_log(rac->avctx, AV_LOG_ERROR, "All probabilities are 0!\n");
     172           0 :         return -1;
     173             :     }
     174             : 
     175             :     /* Scale probabilities so cumulative probability is an even power of 2. */
     176         130 :     scale_factor = av_log2(cumul_prob);
     177             : 
     178         130 :     if (cumul_prob & (cumul_prob - 1)) {
     179         128 :         uint64_t mul = softfloat_reciprocal(cumul_prob);
     180       16512 :         for (i = 1; i <= 128; i++) {
     181       16384 :             rac->prob[i] = softfloat_mul(rac->prob[i], mul);
     182       16384 :             scaled_cumul_prob += rac->prob[i];
     183             :         }
     184         128 :         if (scaled_cumul_prob <= 0) {
     185           0 :             av_log(rac->avctx, AV_LOG_ERROR, "Scaled probabilities invalid\n");
     186           0 :             return AVERROR_INVALIDDATA;
     187             :         }
     188       16512 :         for (; i < 257; i++) {
     189       16384 :             rac->prob[i] = softfloat_mul(rac->prob[i], mul);
     190       16384 :             scaled_cumul_prob += rac->prob[i];
     191             :         }
     192             : 
     193         128 :         scale_factor++;
     194         128 :         if (scale_factor >= 32U)
     195           0 :             return AVERROR_INVALIDDATA;
     196         128 :         cumulative_target = 1U << scale_factor;
     197             : 
     198         128 :         if (scaled_cumul_prob > cumulative_target) {
     199           0 :             av_log(rac->avctx, AV_LOG_ERROR,
     200             :                    "Scaled probabilities are larger than target!\n");
     201           0 :             return -1;
     202             :         }
     203             : 
     204         128 :         scaled_cumul_prob = cumulative_target - scaled_cumul_prob;
     205             : 
     206       13440 :         for (i = 1; scaled_cumul_prob; i = (i & 0x7f) + 1) {
     207       13312 :             if (rac->prob[i]) {
     208        7476 :                 rac->prob[i]++;
     209        7476 :                 scaled_cumul_prob--;
     210             :             }
     211             :             /* Comment from reference source:
     212             :              * if (b & 0x80 == 0) {     // order of operations is 'wrong'; it has been left this way
     213             :              *                          // since the compression change is negligible and fixing it
     214             :              *                          // breaks backwards compatibility
     215             :              *      b =- (signed int)b;
     216             :              *      b &= 0xFF;
     217             :              * } else {
     218             :              *      b++;
     219             :              *      b &= 0x7f;
     220             :              * }
     221             :              */
     222             :         }
     223             :     }
     224             : 
     225         130 :     rac->scale = scale_factor;
     226             : 
     227             :     /* Fill probability array with cumulative probability for each symbol. */
     228       33410 :     for (i = 1; i < 257; i++)
     229       33280 :         rac->prob[i] += rac->prob[i - 1];
     230             : 
     231         130 :     return 0;
     232             : }
     233             : 
     234       50756 : static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1,
     235             :                                       uint8_t *diff, int w, int *left,
     236             :                                       int *left_top)
     237             : {
     238             :     /* This is almost identical to add_hfyu_median_pred in huffyuvdsp.h.
     239             :      * However the &0xFF on the gradient predictor yields incorrect output
     240             :      * for lagarith.
     241             :      */
     242             :     int i;
     243             :     uint8_t l, lt;
     244             : 
     245       50756 :     l  = *left;
     246       50756 :     lt = *left_top;
     247             : 
     248    34347300 :     for (i = 0; i < w; i++) {
     249    34296544 :         l = mid_pred(l, src1[i], l + src1[i] - lt) + diff[i];
     250    34296544 :         lt = src1[i];
     251    34296544 :         dst[i] = l;
     252             :     }
     253             : 
     254       50756 :     *left     = l;
     255       50756 :     *left_top = lt;
     256       50756 : }
     257             : 
     258       50880 : static void lag_pred_line(LagarithContext *l, uint8_t *buf,
     259             :                           int width, int stride, int line)
     260             : {
     261             :     int L, TL;
     262             : 
     263       50880 :     if (!line) {
     264             :         /* Left prediction only for first line */
     265         124 :         L = l->llviddsp.add_left_pred(buf, buf, width, 0);
     266             :     } else {
     267             :         /* Left pixel is actually prev_row[width] */
     268       50756 :         L = buf[width - stride - 1];
     269             : 
     270       50756 :         if (line == 1) {
     271             :             /* Second line, left predict first pixel, the rest of the line is median predicted
     272             :              * NOTE: In the case of RGB this pixel is top predicted */
     273         124 :             TL = l->avctx->pix_fmt == AV_PIX_FMT_YUV420P ? buf[-stride] : L;
     274             :         } else {
     275             :             /* Top left is 2 rows back, last pixel */
     276       50632 :             TL = buf[width - (2 * stride) - 1];
     277             :         }
     278             : 
     279       50756 :         add_lag_median_prediction(buf, buf - stride, buf,
     280             :                                   width, &L, &TL);
     281             :     }
     282       50880 : }
     283             : 
     284        4608 : static void lag_pred_line_yuy2(LagarithContext *l, uint8_t *buf,
     285             :                                int width, int stride, int line,
     286             :                                int is_luma)
     287             : {
     288             :     int L, TL;
     289             : 
     290        4608 :     if (!line) {
     291           6 :         L= buf[0];
     292           6 :         if (is_luma)
     293           2 :             buf[0] = 0;
     294           6 :         l->llviddsp.add_left_pred(buf, buf, width, 0);
     295           6 :         if (is_luma)
     296           2 :             buf[0] = L;
     297           6 :         return;
     298             :     }
     299        4602 :     if (line == 1) {
     300           6 :         const int HEAD = is_luma ? 4 : 2;
     301             :         int i;
     302             : 
     303           6 :         L  = buf[width - stride - 1];
     304           6 :         TL = buf[HEAD  - stride - 1];
     305          22 :         for (i = 0; i < HEAD; i++) {
     306          16 :             L += buf[i];
     307          16 :             buf[i] = L;
     308             :         }
     309        4086 :         for (; i < width; i++) {
     310        4080 :             L      = mid_pred(L & 0xFF, buf[i - stride], (L + buf[i - stride] - TL) & 0xFF) + buf[i];
     311        4080 :             TL     = buf[i - stride];
     312        4080 :             buf[i] = L;
     313             :         }
     314             :     } else {
     315        4596 :         TL = buf[width - (2 * stride) - 1];
     316        4596 :         L  = buf[width - stride - 1];
     317        4596 :         l->llviddsp.add_median_pred(buf, buf - stride, buf, width, &L, &TL);
     318             :     }
     319             : }
     320             : 
     321       55488 : static int lag_decode_line(LagarithContext *l, lag_rac *rac,
     322             :                            uint8_t *dst, int width, int stride,
     323             :                            int esc_count)
     324             : {
     325       55488 :     int i = 0;
     326       55488 :     int ret = 0;
     327             : 
     328       55488 :     if (!esc_count)
     329        1656 :         esc_count = -1;
     330             : 
     331             :     /* Output any zeros remaining from the previous run */
     332      575824 : handle_zeros:
     333      521992 :     if (l->zeros_rem) {
     334      381611 :         int count = FFMIN(l->zeros_rem, width - i);
     335      381611 :         memset(dst + i, 0, count);
     336      381611 :         i += count;
     337      381611 :         l->zeros_rem -= count;
     338             :     }
     339             : 
     340     4729725 :     while (i < width) {
     341     4152245 :         dst[i] = lag_get_rac(rac);
     342     4152245 :         ret++;
     343             : 
     344     4152245 :         if (dst[i])
     345     2803136 :             l->zeros = 0;
     346             :         else
     347     1349109 :             l->zeros++;
     348             : 
     349     4152245 :         i++;
     350     4152245 :         if (l->zeros == esc_count) {
     351      466504 :             int index = lag_get_rac(rac);
     352      466504 :             ret++;
     353             : 
     354      466504 :             l->zeros = 0;
     355             : 
     356      466504 :             l->zeros_rem = lag_calc_zero_run(index);
     357      466504 :             goto handle_zeros;
     358             :         }
     359             :     }
     360       55488 :     return ret;
     361             : }
     362             : 
     363           0 : static int lag_decode_zero_run_line(LagarithContext *l, uint8_t *dst,
     364             :                                     const uint8_t *src, const uint8_t *src_end,
     365             :                                     int width, int esc_count)
     366             : {
     367           0 :     int i = 0;
     368             :     int count;
     369           0 :     uint8_t zero_run = 0;
     370           0 :     const uint8_t *src_start = src;
     371           0 :     uint8_t mask1 = -(esc_count < 2);
     372           0 :     uint8_t mask2 = -(esc_count < 3);
     373           0 :     uint8_t *end = dst + (width - 2);
     374             : 
     375           0 :     avpriv_request_sample(l->avctx, "zero_run_line");
     376             : 
     377           0 :     memset(dst, 0, width);
     378             : 
     379           0 : output_zeros:
     380           0 :     if (l->zeros_rem) {
     381           0 :         count = FFMIN(l->zeros_rem, width - i);
     382           0 :         if (end - dst < count) {
     383           0 :             av_log(l->avctx, AV_LOG_ERROR, "Too many zeros remaining.\n");
     384           0 :             return AVERROR_INVALIDDATA;
     385             :         }
     386             : 
     387           0 :         memset(dst, 0, count);
     388           0 :         l->zeros_rem -= count;
     389           0 :         dst += count;
     390             :     }
     391             : 
     392           0 :     while (dst < end) {
     393           0 :         i = 0;
     394           0 :         while (!zero_run && dst + i < end) {
     395           0 :             i++;
     396           0 :             if (i+2 >= src_end - src)
     397           0 :                 return AVERROR_INVALIDDATA;
     398           0 :             zero_run =
     399           0 :                 !(src[i] | (src[i + 1] & mask1) | (src[i + 2] & mask2));
     400             :         }
     401           0 :         if (zero_run) {
     402           0 :             zero_run = 0;
     403           0 :             i += esc_count;
     404           0 :             memcpy(dst, src, i);
     405           0 :             dst += i;
     406           0 :             l->zeros_rem = lag_calc_zero_run(src[i]);
     407             : 
     408           0 :             src += i + 1;
     409           0 :             goto output_zeros;
     410             :         } else {
     411           0 :             memcpy(dst, src, i);
     412           0 :             src += i;
     413           0 :             dst += i;
     414             :         }
     415             :     }
     416           0 :     return  src - src_start;
     417             : }
     418             : 
     419             : 
     420             : 
     421         140 : static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst,
     422             :                                   int width, int height, int stride,
     423             :                                   const uint8_t *src, int src_size)
     424             : {
     425         140 :     int i = 0;
     426         140 :     int read = 0;
     427             :     uint32_t length;
     428         140 :     uint32_t offset = 1;
     429             :     int esc_count;
     430             :     GetBitContext gb;
     431             :     lag_rac rac;
     432         140 :     const uint8_t *src_end = src + src_size;
     433             :     int ret;
     434             : 
     435         140 :     rac.avctx = l->avctx;
     436         140 :     l->zeros = 0;
     437             : 
     438         140 :     if(src_size < 2)
     439           0 :         return AVERROR_INVALIDDATA;
     440             : 
     441         140 :     esc_count = src[0];
     442         140 :     if (esc_count < 4) {
     443         130 :         length = width * height;
     444         130 :         if(src_size < 5)
     445           0 :             return AVERROR_INVALIDDATA;
     446         130 :         if (esc_count && AV_RL32(src + 1) < length) {
     447         127 :             length = AV_RL32(src + 1);
     448         127 :             offset += 4;
     449             :         }
     450             : 
     451         130 :         if ((ret = init_get_bits8(&gb, src + offset, src_size - offset)) < 0)
     452           0 :             return ret;
     453             : 
     454         130 :         if (lag_read_prob_header(&rac, &gb) < 0)
     455           0 :             return -1;
     456             : 
     457         130 :         ff_lag_rac_init(&rac, &gb, length - stride);
     458       55618 :         for (i = 0; i < height; i++) {
     459       55488 :             if (rac.overread > MAX_OVERREAD)
     460           0 :                 return AVERROR_INVALIDDATA;
     461       55488 :             read += lag_decode_line(l, &rac, dst + (i * stride), width,
     462             :                                     stride, esc_count);
     463             :         }
     464             : 
     465         130 :         if (read > length)
     466           0 :             av_log(l->avctx, AV_LOG_WARNING,
     467             :                    "Output more bytes than length (%d of %"PRIu32")\n", read,
     468             :                    length);
     469          10 :     } else if (esc_count < 8) {
     470           0 :         esc_count -= 4;
     471           0 :         src ++;
     472           0 :         src_size --;
     473           0 :         if (esc_count > 0) {
     474             :             /* Zero run coding only, no range coding. */
     475           0 :             for (i = 0; i < height; i++) {
     476           0 :                 int res = lag_decode_zero_run_line(l, dst + (i * stride), src,
     477             :                                                    src_end, width, esc_count);
     478           0 :                 if (res < 0)
     479           0 :                     return res;
     480           0 :                 src += res;
     481             :             }
     482             :         } else {
     483           0 :             if (src_size < width * height)
     484           0 :                 return AVERROR_INVALIDDATA; // buffer not big enough
     485             :             /* Plane is stored uncompressed */
     486           0 :             for (i = 0; i < height; i++) {
     487           0 :                 memcpy(dst + (i * stride), src, width);
     488           0 :                 src += width;
     489             :             }
     490             :         }
     491          10 :     } else if (esc_count == 0xff) {
     492             :         /* Plane is a solid run of given value */
     493        3610 :         for (i = 0; i < height; i++)
     494        3600 :             memset(dst + i * stride, src[1], width);
     495             :         /* Do not apply prediction.
     496             :            Note: memset to 0 above, setting first value to src[1]
     497             :            and applying prediction gives the same result. */
     498          10 :         return 0;
     499             :     } else {
     500           0 :         av_log(l->avctx, AV_LOG_ERROR,
     501             :                "Invalid zero run escape code! (%#x)\n", esc_count);
     502           0 :         return -1;
     503             :     }
     504             : 
     505         130 :     if (l->avctx->pix_fmt != AV_PIX_FMT_YUV422P) {
     506       51004 :         for (i = 0; i < height; i++) {
     507       50880 :             lag_pred_line(l, dst, width, stride, i);
     508       50880 :             dst += stride;
     509             :         }
     510             :     } else {
     511        4614 :         for (i = 0; i < height; i++) {
     512        4608 :             lag_pred_line_yuy2(l, dst, width, stride, i,
     513        4608 :                                width == l->avctx->width);
     514        4608 :             dst += stride;
     515             :         }
     516             :     }
     517             : 
     518         130 :     return 0;
     519             : }
     520             : 
     521             : /**
     522             :  * Decode a frame.
     523             :  * @param avctx codec context
     524             :  * @param data output AVFrame
     525             :  * @param data_size size of output data or 0 if no picture is returned
     526             :  * @param avpkt input packet
     527             :  * @return number of consumed bytes on success or negative if decode fails
     528             :  */
     529          82 : static int lag_decode_frame(AVCodecContext *avctx,
     530             :                             void *data, int *got_frame, AVPacket *avpkt)
     531             : {
     532          82 :     const uint8_t *buf = avpkt->data;
     533          82 :     unsigned int buf_size = avpkt->size;
     534          82 :     LagarithContext *l = avctx->priv_data;
     535          82 :     ThreadFrame frame = { .f = data };
     536          82 :     AVFrame *const p  = data;
     537          82 :     uint8_t frametype = 0;
     538          82 :     uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9;
     539             :     uint32_t offs[4];
     540             :     uint8_t *srcs[4], *dst;
     541          82 :     int i, j, planes = 3;
     542             :     int ret;
     543             : 
     544          82 :     p->key_frame = 1;
     545             : 
     546          82 :     frametype = buf[0];
     547             : 
     548          82 :     offset_gu = AV_RL32(buf + 1);
     549          82 :     offset_bv = AV_RL32(buf + 5);
     550             : 
     551          82 :     switch (frametype) {
     552           6 :     case FRAME_SOLID_RGBA:
     553           6 :         avctx->pix_fmt = AV_PIX_FMT_RGB32;
     554          16 :     case FRAME_SOLID_GRAY:
     555          16 :         if (frametype == FRAME_SOLID_GRAY)
     556          10 :             if (avctx->bits_per_coded_sample == 24) {
     557          10 :                 avctx->pix_fmt = AV_PIX_FMT_RGB24;
     558             :             } else {
     559           0 :                 avctx->pix_fmt = AV_PIX_FMT_0RGB32;
     560           0 :                 planes = 4;
     561             :             }
     562             : 
     563          16 :         if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
     564           0 :             return ret;
     565             : 
     566          16 :         dst = p->data[0];
     567          16 :         if (frametype == FRAME_SOLID_RGBA) {
     568        2886 :         for (j = 0; j < avctx->height; j++) {
     569     2076480 :             for (i = 0; i < avctx->width; i++)
     570     2073600 :                 AV_WN32(dst + i * 4, offset_gu);
     571        2880 :             dst += p->linesize[0];
     572             :         }
     573             :         } else {
     574        3610 :             for (j = 0; j < avctx->height; j++) {
     575        3600 :                 memset(dst, buf[1], avctx->width * planes);
     576        3600 :                 dst += p->linesize[0];
     577             :             }
     578             :         }
     579          16 :         break;
     580          26 :     case FRAME_SOLID_COLOR:
     581          26 :         if (avctx->bits_per_coded_sample == 24) {
     582          26 :             avctx->pix_fmt = AV_PIX_FMT_RGB24;
     583             :         } else {
     584           0 :             avctx->pix_fmt = AV_PIX_FMT_RGB32;
     585           0 :             offset_gu |= 0xFFU << 24;
     586             :         }
     587             : 
     588          26 :         if ((ret = ff_thread_get_buffer(avctx, &frame,0)) < 0)
     589           0 :             return ret;
     590             : 
     591          26 :         dst = p->data[0];
     592        6266 :         for (j = 0; j < avctx->height; j++) {
     593     2003040 :             for (i = 0; i < avctx->width; i++)
     594     1996800 :                 if (avctx->bits_per_coded_sample == 24) {
     595     1996800 :                     AV_WB24(dst + i * 3, offset_gu);
     596             :                 } else {
     597           0 :                     AV_WN32(dst + i * 4, offset_gu);
     598             :                 }
     599        6240 :             dst += p->linesize[0];
     600             :         }
     601          26 :         break;
     602          20 :     case FRAME_ARITH_RGBA:
     603          20 :         avctx->pix_fmt = AV_PIX_FMT_RGB32;
     604          20 :         planes = 4;
     605          20 :         offset_ry += 4;
     606          20 :         offs[3] = AV_RL32(buf + 9);
     607          35 :     case FRAME_ARITH_RGB24:
     608             :     case FRAME_U_RGB24:
     609          35 :         if (frametype == FRAME_ARITH_RGB24 || frametype == FRAME_U_RGB24)
     610          15 :             avctx->pix_fmt = AV_PIX_FMT_RGB24;
     611             : 
     612          35 :         if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
     613           0 :             return ret;
     614             : 
     615          35 :         offs[0] = offset_bv;
     616          35 :         offs[1] = offset_gu;
     617          35 :         offs[2] = offset_ry;
     618             : 
     619          35 :         l->rgb_stride = FFALIGN(avctx->width, 16);
     620          35 :         av_fast_malloc(&l->rgb_planes, &l->rgb_planes_allocated,
     621          35 :                        l->rgb_stride * avctx->height * planes + 1);
     622          35 :         if (!l->rgb_planes) {
     623           0 :             av_log(avctx, AV_LOG_ERROR, "cannot allocate temporary buffer\n");
     624           0 :             return AVERROR(ENOMEM);
     625             :         }
     626         160 :         for (i = 0; i < planes; i++)
     627         125 :             srcs[i] = l->rgb_planes + (i + 1) * l->rgb_stride * avctx->height - l->rgb_stride;
     628         160 :         for (i = 0; i < planes; i++)
     629         125 :             if (buf_size <= offs[i]) {
     630           0 :                 av_log(avctx, AV_LOG_ERROR,
     631             :                         "Invalid frame offsets\n");
     632           0 :                 return AVERROR_INVALIDDATA;
     633             :             }
     634             : 
     635         160 :         for (i = 0; i < planes; i++)
     636         375 :             lag_decode_arith_plane(l, srcs[i],
     637             :                                    avctx->width, avctx->height,
     638         250 :                                    -l->rgb_stride, buf + offs[i],
     639         125 :                                    buf_size - offs[i]);
     640          35 :         dst = p->data[0];
     641         160 :         for (i = 0; i < planes; i++)
     642         125 :             srcs[i] = l->rgb_planes + i * l->rgb_stride * avctx->height;
     643       14515 :         for (j = 0; j < avctx->height; j++) {
     644     9844880 :             for (i = 0; i < avctx->width; i++) {
     645             :                 uint8_t r, g, b, a;
     646     9830400 :                 r = srcs[0][i];
     647     9830400 :                 g = srcs[1][i];
     648     9830400 :                 b = srcs[2][i];
     649     9830400 :                 r += g;
     650     9830400 :                 b += g;
     651     9830400 :                 if (frametype == FRAME_ARITH_RGBA) {
     652     6912000 :                     a = srcs[3][i];
     653     6912000 :                     AV_WN32(dst + i * 4, MKBETAG(a, r, g, b));
     654             :                 } else {
     655     2918400 :                     dst[i * 3 + 0] = r;
     656     2918400 :                     dst[i * 3 + 1] = g;
     657     2918400 :                     dst[i * 3 + 2] = b;
     658             :                 }
     659             :             }
     660       14480 :             dst += p->linesize[0];
     661       67520 :             for (i = 0; i < planes; i++)
     662       53040 :                 srcs[i] += l->rgb_stride;
     663             :         }
     664          35 :         break;
     665           2 :     case FRAME_ARITH_YUY2:
     666           2 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     667             : 
     668           2 :         if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
     669           0 :             return ret;
     670             : 
     671           2 :         if (offset_ry >= buf_size ||
     672           2 :             offset_gu >= buf_size ||
     673             :             offset_bv >= buf_size) {
     674           0 :             av_log(avctx, AV_LOG_ERROR,
     675             :                    "Invalid frame offsets\n");
     676           0 :             return AVERROR_INVALIDDATA;
     677             :         }
     678             : 
     679           2 :         lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height,
     680             :                                p->linesize[0], buf + offset_ry,
     681           2 :                                buf_size - offset_ry);
     682           2 :         lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2,
     683             :                                avctx->height, p->linesize[1],
     684           2 :                                buf + offset_gu, buf_size - offset_gu);
     685           2 :         lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2,
     686             :                                avctx->height, p->linesize[2],
     687           2 :                                buf + offset_bv, buf_size - offset_bv);
     688           2 :         break;
     689           3 :     case FRAME_ARITH_YV12:
     690           3 :         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     691             : 
     692           3 :         if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
     693           0 :             return ret;
     694           3 :         if (buf_size <= offset_ry || buf_size <= offset_gu || buf_size <= offset_bv) {
     695           0 :             return AVERROR_INVALIDDATA;
     696             :         }
     697             : 
     698           3 :         if (offset_ry >= buf_size ||
     699           3 :             offset_gu >= buf_size ||
     700             :             offset_bv >= buf_size) {
     701           0 :             av_log(avctx, AV_LOG_ERROR,
     702             :                    "Invalid frame offsets\n");
     703           0 :             return AVERROR_INVALIDDATA;
     704             :         }
     705             : 
     706           3 :         lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height,
     707             :                                p->linesize[0], buf + offset_ry,
     708           3 :                                buf_size - offset_ry);
     709           6 :         lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2,
     710           3 :                                (avctx->height + 1) / 2, p->linesize[2],
     711           3 :                                buf + offset_gu, buf_size - offset_gu);
     712           6 :         lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2,
     713           3 :                                (avctx->height + 1) / 2, p->linesize[1],
     714           3 :                                buf + offset_bv, buf_size - offset_bv);
     715           3 :         break;
     716           0 :     default:
     717           0 :         av_log(avctx, AV_LOG_ERROR,
     718             :                "Unsupported Lagarith frame type: %#"PRIx8"\n", frametype);
     719           0 :         return AVERROR_PATCHWELCOME;
     720             :     }
     721             : 
     722          82 :     *got_frame = 1;
     723             : 
     724          82 :     return buf_size;
     725             : }
     726             : 
     727          20 : static av_cold int lag_decode_init(AVCodecContext *avctx)
     728             : {
     729          20 :     LagarithContext *l = avctx->priv_data;
     730          20 :     l->avctx = avctx;
     731             : 
     732          20 :     ff_llviddsp_init(&l->llviddsp);
     733             : 
     734          20 :     return 0;
     735             : }
     736             : 
     737             : #if HAVE_THREADS
     738           0 : static av_cold int lag_decode_init_thread_copy(AVCodecContext *avctx)
     739             : {
     740           0 :     LagarithContext *l = avctx->priv_data;
     741           0 :     l->avctx = avctx;
     742             : 
     743           0 :     return 0;
     744             : }
     745             : #endif
     746             : 
     747          20 : static av_cold int lag_decode_end(AVCodecContext *avctx)
     748             : {
     749          20 :     LagarithContext *l = avctx->priv_data;
     750             : 
     751          20 :     av_freep(&l->rgb_planes);
     752             : 
     753          20 :     return 0;
     754             : }
     755             : 
     756             : AVCodec ff_lagarith_decoder = {
     757             :     .name           = "lagarith",
     758             :     .long_name      = NULL_IF_CONFIG_SMALL("Lagarith lossless"),
     759             :     .type           = AVMEDIA_TYPE_VIDEO,
     760             :     .id             = AV_CODEC_ID_LAGARITH,
     761             :     .priv_data_size = sizeof(LagarithContext),
     762             :     .init           = lag_decode_init,
     763             :     .init_thread_copy = ONLY_IF_THREADS_ENABLED(lag_decode_init_thread_copy),
     764             :     .close          = lag_decode_end,
     765             :     .decode         = lag_decode_frame,
     766             :     .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     767             : };

Generated by: LCOV version 1.13