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