1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Apple Pixlet decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2016 Paul B Mahol 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#include <stdint.h> 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 25cabdff1aSopenharmony_ci#include "libavutil/intmath.h" 26cabdff1aSopenharmony_ci#include "libavutil/opt.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "avcodec.h" 29cabdff1aSopenharmony_ci#include "bytestream.h" 30cabdff1aSopenharmony_ci#include "codec_internal.h" 31cabdff1aSopenharmony_ci#include "get_bits.h" 32cabdff1aSopenharmony_ci#include "internal.h" 33cabdff1aSopenharmony_ci#include "thread.h" 34cabdff1aSopenharmony_ci#include "unary.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#define NB_LEVELS 4 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci#define PIXLET_MAGIC 0xDEADBEEF 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#define H 0 41cabdff1aSopenharmony_ci#define V 1 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_citypedef struct SubBand { 44cabdff1aSopenharmony_ci unsigned width, height; 45cabdff1aSopenharmony_ci unsigned size; 46cabdff1aSopenharmony_ci unsigned x, y; 47cabdff1aSopenharmony_ci} SubBand; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_citypedef struct PixletContext { 50cabdff1aSopenharmony_ci AVClass *class; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci GetByteContext gb; 53cabdff1aSopenharmony_ci GetBitContext bc; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci int levels; 56cabdff1aSopenharmony_ci int depth; 57cabdff1aSopenharmony_ci int w, h; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci int16_t *filter[2]; 60cabdff1aSopenharmony_ci int16_t *prediction; 61cabdff1aSopenharmony_ci int64_t scaling[4][2][NB_LEVELS]; 62cabdff1aSopenharmony_ci uint16_t lut[65536]; 63cabdff1aSopenharmony_ci SubBand band[4][NB_LEVELS * 3 + 1]; 64cabdff1aSopenharmony_ci} PixletContext; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic av_cold int pixlet_init(AVCodecContext *avctx) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P16; 69cabdff1aSopenharmony_ci avctx->color_range = AVCOL_RANGE_JPEG; 70cabdff1aSopenharmony_ci return 0; 71cabdff1aSopenharmony_ci} 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_cistatic void free_buffers(AVCodecContext *avctx) 74cabdff1aSopenharmony_ci{ 75cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci av_freep(&ctx->filter[0]); 78cabdff1aSopenharmony_ci av_freep(&ctx->filter[1]); 79cabdff1aSopenharmony_ci av_freep(&ctx->prediction); 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic av_cold int pixlet_close(AVCodecContext *avctx) 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 85cabdff1aSopenharmony_ci free_buffers(avctx); 86cabdff1aSopenharmony_ci ctx->w = 0; 87cabdff1aSopenharmony_ci ctx->h = 0; 88cabdff1aSopenharmony_ci return 0; 89cabdff1aSopenharmony_ci} 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_cistatic int init_decoder(AVCodecContext *avctx) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 94cabdff1aSopenharmony_ci int i, plane; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci ctx->filter[0] = av_malloc_array(ctx->h, sizeof(int16_t)); 97cabdff1aSopenharmony_ci ctx->filter[1] = av_malloc_array(FFMAX(ctx->h, ctx->w) + 16, sizeof(int16_t)); 98cabdff1aSopenharmony_ci ctx->prediction = av_malloc_array((ctx->w >> NB_LEVELS), sizeof(int16_t)); 99cabdff1aSopenharmony_ci if (!ctx->filter[0] || !ctx->filter[1] || !ctx->prediction) 100cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci for (plane = 0; plane < 3; plane++) { 103cabdff1aSopenharmony_ci unsigned shift = plane > 0; 104cabdff1aSopenharmony_ci unsigned w = ctx->w >> shift; 105cabdff1aSopenharmony_ci unsigned h = ctx->h >> shift; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci ctx->band[plane][0].width = w >> NB_LEVELS; 108cabdff1aSopenharmony_ci ctx->band[plane][0].height = h >> NB_LEVELS; 109cabdff1aSopenharmony_ci ctx->band[plane][0].size = (w >> NB_LEVELS) * (h >> NB_LEVELS); 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci for (i = 0; i < NB_LEVELS * 3; i++) { 112cabdff1aSopenharmony_ci unsigned scale = ctx->levels - (i / 3); 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci ctx->band[plane][i + 1].width = w >> scale; 115cabdff1aSopenharmony_ci ctx->band[plane][i + 1].height = h >> scale; 116cabdff1aSopenharmony_ci ctx->band[plane][i + 1].size = (w >> scale) * (h >> scale); 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci ctx->band[plane][i + 1].x = (w >> scale) * (((i + 1) % 3) != 2); 119cabdff1aSopenharmony_ci ctx->band[plane][i + 1].y = (h >> scale) * (((i + 1) % 3) != 1); 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci return 0; 124cabdff1aSopenharmony_ci} 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_cistatic int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, 127cabdff1aSopenharmony_ci int width, ptrdiff_t stride) 128cabdff1aSopenharmony_ci{ 129cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 130cabdff1aSopenharmony_ci GetBitContext *bc = &ctx->bc; 131cabdff1aSopenharmony_ci unsigned cnt1, nbits, k, j = 0, i = 0; 132cabdff1aSopenharmony_ci int64_t value, state = 3; 133cabdff1aSopenharmony_ci int rlen, escape, flag = 0; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci while (i < size) { 136cabdff1aSopenharmony_ci nbits = FFMIN(ff_clz((state >> 8) + 3) ^ 0x1F, 14); 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci cnt1 = get_unary(bc, 0, 8); 139cabdff1aSopenharmony_ci if (cnt1 < 8) { 140cabdff1aSopenharmony_ci value = show_bits(bc, nbits); 141cabdff1aSopenharmony_ci if (value <= 1) { 142cabdff1aSopenharmony_ci skip_bits(bc, nbits - 1); 143cabdff1aSopenharmony_ci escape = ((1 << nbits) - 1) * cnt1; 144cabdff1aSopenharmony_ci } else { 145cabdff1aSopenharmony_ci skip_bits(bc, nbits); 146cabdff1aSopenharmony_ci escape = value + ((1 << nbits) - 1) * cnt1 - 1; 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } else { 149cabdff1aSopenharmony_ci escape = get_bits(bc, 16); 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci value = -((escape + flag) & 1) | 1; 153cabdff1aSopenharmony_ci dst[j++] = value * ((escape + flag + 1) >> 1); 154cabdff1aSopenharmony_ci i++; 155cabdff1aSopenharmony_ci if (j == width) { 156cabdff1aSopenharmony_ci j = 0; 157cabdff1aSopenharmony_ci dst += stride; 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci state = 120 * (escape + flag) + state - (120 * state >> 8); 160cabdff1aSopenharmony_ci flag = 0; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci if (state * 4ULL > 0xFF || i >= size) 163cabdff1aSopenharmony_ci continue; 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci nbits = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; 166cabdff1aSopenharmony_ci escape = av_mod_uintp2(16383, nbits); 167cabdff1aSopenharmony_ci cnt1 = get_unary(bc, 0, 8); 168cabdff1aSopenharmony_ci if (cnt1 > 7) { 169cabdff1aSopenharmony_ci rlen = get_bits(bc, 16); 170cabdff1aSopenharmony_ci } else { 171cabdff1aSopenharmony_ci value = show_bits(bc, nbits); 172cabdff1aSopenharmony_ci if (value > 1) { 173cabdff1aSopenharmony_ci skip_bits(bc, nbits); 174cabdff1aSopenharmony_ci rlen = value + escape * cnt1 - 1; 175cabdff1aSopenharmony_ci } else { 176cabdff1aSopenharmony_ci skip_bits(bc, nbits - 1); 177cabdff1aSopenharmony_ci rlen = escape * cnt1; 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci if (rlen > size - i) 182cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 183cabdff1aSopenharmony_ci i += rlen; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci for (k = 0; k < rlen; k++) { 186cabdff1aSopenharmony_ci dst[j++] = 0; 187cabdff1aSopenharmony_ci if (j == width) { 188cabdff1aSopenharmony_ci j = 0; 189cabdff1aSopenharmony_ci dst += stride; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci state = 0; 194cabdff1aSopenharmony_ci flag = rlen < 0xFFFF ? 1 : 0; 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci align_get_bits(bc); 198cabdff1aSopenharmony_ci return get_bits_count(bc) >> 3; 199cabdff1aSopenharmony_ci} 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_cistatic int read_high_coeffs(AVCodecContext *avctx, const uint8_t *src, int16_t *dst, 202cabdff1aSopenharmony_ci int size, int c, int a, int d, 203cabdff1aSopenharmony_ci int width, ptrdiff_t stride) 204cabdff1aSopenharmony_ci{ 205cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 206cabdff1aSopenharmony_ci GetBitContext *bc = &ctx->bc; 207cabdff1aSopenharmony_ci unsigned cnt1, shbits, rlen, nbits, length, i = 0, j = 0, k; 208cabdff1aSopenharmony_ci int ret, escape, pfx, value, yflag, xflag, flag = 0; 209cabdff1aSopenharmony_ci int64_t state = 3, tmp; 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci ret = init_get_bits8(bc, src, bytestream2_get_bytes_left(&ctx->gb)); 212cabdff1aSopenharmony_ci if (ret < 0) 213cabdff1aSopenharmony_ci return ret; 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci if (a ^ (a >> 31)) { 216cabdff1aSopenharmony_ci nbits = 33 - ff_clz(a ^ (a >> 31)); 217cabdff1aSopenharmony_ci if (nbits > 16) 218cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 219cabdff1aSopenharmony_ci } else { 220cabdff1aSopenharmony_ci nbits = 1; 221cabdff1aSopenharmony_ci } 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci length = 25 - nbits; 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci while (i < size) { 226cabdff1aSopenharmony_ci if (((state >> 8) + 3) & 0xFFFFFFF) 227cabdff1aSopenharmony_ci value = ff_clz((state >> 8) + 3) ^ 0x1F; 228cabdff1aSopenharmony_ci else 229cabdff1aSopenharmony_ci value = -1; 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci cnt1 = get_unary(bc, 0, length); 232cabdff1aSopenharmony_ci if (cnt1 >= length) { 233cabdff1aSopenharmony_ci cnt1 = get_bits(bc, nbits); 234cabdff1aSopenharmony_ci } else { 235cabdff1aSopenharmony_ci pfx = 14 + ((((uint64_t)(value - 14)) >> 32) & (value - 14)); 236cabdff1aSopenharmony_ci if (pfx < 1 || pfx > 25) 237cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 238cabdff1aSopenharmony_ci cnt1 *= (1 << pfx) - 1; 239cabdff1aSopenharmony_ci shbits = show_bits(bc, pfx); 240cabdff1aSopenharmony_ci if (shbits <= 1) { 241cabdff1aSopenharmony_ci skip_bits(bc, pfx - 1); 242cabdff1aSopenharmony_ci } else { 243cabdff1aSopenharmony_ci skip_bits(bc, pfx); 244cabdff1aSopenharmony_ci cnt1 += shbits - 1; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci } 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci xflag = flag + cnt1; 249cabdff1aSopenharmony_ci yflag = xflag; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci if (flag + cnt1 == 0) { 252cabdff1aSopenharmony_ci value = 0; 253cabdff1aSopenharmony_ci } else { 254cabdff1aSopenharmony_ci xflag &= 1u; 255cabdff1aSopenharmony_ci tmp = (int64_t)c * ((yflag + 1) >> 1) + (c >> 1); 256cabdff1aSopenharmony_ci value = xflag + (tmp ^ -xflag); 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci i++; 260cabdff1aSopenharmony_ci dst[j++] = value; 261cabdff1aSopenharmony_ci if (j == width) { 262cabdff1aSopenharmony_ci j = 0; 263cabdff1aSopenharmony_ci dst += stride; 264cabdff1aSopenharmony_ci } 265cabdff1aSopenharmony_ci state += (int64_t)d * (uint64_t)yflag - ((int64_t)(d * (uint64_t)state) >> 8); 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci flag = 0; 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci if ((uint64_t)state > 0xFF / 4 || i >= size) 270cabdff1aSopenharmony_ci continue; 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci pfx = ((state + 8) >> 5) + (state ? ff_clz(state) : 32) - 24; 273cabdff1aSopenharmony_ci escape = av_mod_uintp2(16383, pfx); 274cabdff1aSopenharmony_ci cnt1 = get_unary(bc, 0, 8); 275cabdff1aSopenharmony_ci if (cnt1 < 8) { 276cabdff1aSopenharmony_ci if (pfx < 1 || pfx > 25) 277cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci value = show_bits(bc, pfx); 280cabdff1aSopenharmony_ci if (value > 1) { 281cabdff1aSopenharmony_ci skip_bits(bc, pfx); 282cabdff1aSopenharmony_ci rlen = value + escape * cnt1 - 1; 283cabdff1aSopenharmony_ci } else { 284cabdff1aSopenharmony_ci skip_bits(bc, pfx - 1); 285cabdff1aSopenharmony_ci rlen = escape * cnt1; 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci } else { 288cabdff1aSopenharmony_ci if (get_bits1(bc)) 289cabdff1aSopenharmony_ci value = get_bits(bc, 16); 290cabdff1aSopenharmony_ci else 291cabdff1aSopenharmony_ci value = get_bits(bc, 8); 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci rlen = value + 8 * escape; 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci if (rlen > 0xFFFF || i + rlen > size) 297cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 298cabdff1aSopenharmony_ci i += rlen; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci for (k = 0; k < rlen; k++) { 301cabdff1aSopenharmony_ci dst[j++] = 0; 302cabdff1aSopenharmony_ci if (j == width) { 303cabdff1aSopenharmony_ci j = 0; 304cabdff1aSopenharmony_ci dst += stride; 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci } 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci state = 0; 309cabdff1aSopenharmony_ci flag = rlen < 0xFFFF ? 1 : 0; 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci align_get_bits(bc); 313cabdff1aSopenharmony_ci return get_bits_count(bc) >> 3; 314cabdff1aSopenharmony_ci} 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_cistatic int read_highpass(AVCodecContext *avctx, const uint8_t *ptr, 317cabdff1aSopenharmony_ci int plane, AVFrame *frame) 318cabdff1aSopenharmony_ci{ 319cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 320cabdff1aSopenharmony_ci ptrdiff_t stride = frame->linesize[plane] / 2; 321cabdff1aSopenharmony_ci int i, ret; 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci for (i = 0; i < ctx->levels * 3; i++) { 324cabdff1aSopenharmony_ci int32_t a = bytestream2_get_be32(&ctx->gb); 325cabdff1aSopenharmony_ci int32_t b = bytestream2_get_be32(&ctx->gb); 326cabdff1aSopenharmony_ci int32_t c = bytestream2_get_be32(&ctx->gb); 327cabdff1aSopenharmony_ci int32_t d = bytestream2_get_be32(&ctx->gb); 328cabdff1aSopenharmony_ci int16_t *dest = (int16_t *)frame->data[plane] + 329cabdff1aSopenharmony_ci ctx->band[plane][i + 1].x + 330cabdff1aSopenharmony_ci ctx->band[plane][i + 1].y * stride; 331cabdff1aSopenharmony_ci unsigned size = ctx->band[plane][i + 1].size; 332cabdff1aSopenharmony_ci uint32_t magic = bytestream2_get_be32(&ctx->gb); 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci if (magic != PIXLET_MAGIC) { 335cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 336cabdff1aSopenharmony_ci "wrong magic number: 0x%08"PRIX32" for plane %d, band %d\n", 337cabdff1aSopenharmony_ci magic, plane, i); 338cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 339cabdff1aSopenharmony_ci } 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci if (a == INT32_MIN) 342cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci ret = read_high_coeffs(avctx, ptr + bytestream2_tell(&ctx->gb), dest, size, 345cabdff1aSopenharmony_ci c, (b >= FFABS(a)) ? b : a, d, 346cabdff1aSopenharmony_ci ctx->band[plane][i + 1].width, stride); 347cabdff1aSopenharmony_ci if (ret < 0) { 348cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 349cabdff1aSopenharmony_ci "error in highpass coefficients for plane %d, band %d\n", 350cabdff1aSopenharmony_ci plane, i); 351cabdff1aSopenharmony_ci return ret; 352cabdff1aSopenharmony_ci } 353cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, ret); 354cabdff1aSopenharmony_ci } 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci return 0; 357cabdff1aSopenharmony_ci} 358cabdff1aSopenharmony_ci 359cabdff1aSopenharmony_cistatic void lowpass_prediction(int16_t *dst, int16_t *pred, 360cabdff1aSopenharmony_ci int width, int height, ptrdiff_t stride) 361cabdff1aSopenharmony_ci{ 362cabdff1aSopenharmony_ci int16_t val; 363cabdff1aSopenharmony_ci int i, j; 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci memset(pred, 0, width * sizeof(*pred)); 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci for (i = 0; i < height; i++) { 368cabdff1aSopenharmony_ci val = pred[0] + dst[0]; 369cabdff1aSopenharmony_ci dst[0] = pred[0] = val; 370cabdff1aSopenharmony_ci for (j = 1; j < width; j++) { 371cabdff1aSopenharmony_ci val = pred[j] + dst[j]; 372cabdff1aSopenharmony_ci dst[j] = pred[j] = val; 373cabdff1aSopenharmony_ci dst[j] += dst[j-1]; 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci dst += stride; 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci} 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_cistatic void filterfn(int16_t *dest, int16_t *tmp, unsigned size, int64_t scale) 380cabdff1aSopenharmony_ci{ 381cabdff1aSopenharmony_ci int16_t *low, *high, *ll, *lh, *hl, *hh; 382cabdff1aSopenharmony_ci int hsize, i, j; 383cabdff1aSopenharmony_ci int64_t value; 384cabdff1aSopenharmony_ci 385cabdff1aSopenharmony_ci hsize = size >> 1; 386cabdff1aSopenharmony_ci low = tmp + 4; 387cabdff1aSopenharmony_ci high = &low[hsize + 8]; 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_ci memcpy(low, dest, size); 390cabdff1aSopenharmony_ci memcpy(high, dest + hsize, size); 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci ll = &low[hsize]; 393cabdff1aSopenharmony_ci lh = &low[hsize]; 394cabdff1aSopenharmony_ci hl = &high[hsize]; 395cabdff1aSopenharmony_ci hh = hl; 396cabdff1aSopenharmony_ci for (i = 4, j = 2; i; i--, j++, ll--, hh++, lh++, hl--) { 397cabdff1aSopenharmony_ci low[i - 5] = low[j - 1]; 398cabdff1aSopenharmony_ci lh[0] = ll[-1]; 399cabdff1aSopenharmony_ci high[i - 5] = high[j - 2]; 400cabdff1aSopenharmony_ci hh[0] = hl[-2]; 401cabdff1aSopenharmony_ci } 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci for (i = 0; i < hsize; i++) { 404cabdff1aSopenharmony_ci value = (int64_t) low [i + 1] * -INT64_C(325392907) + 405cabdff1aSopenharmony_ci (int64_t) low [i + 0] * INT64_C(3687786320) + 406cabdff1aSopenharmony_ci (int64_t) low [i - 1] * -INT64_C(325392907) + 407cabdff1aSopenharmony_ci (int64_t) high[i + 0] * INT64_C(1518500249) + 408cabdff1aSopenharmony_ci (int64_t) high[i - 1] * INT64_C(1518500249); 409cabdff1aSopenharmony_ci dest[i * 2] = av_clip_int16(((value >> 32) * (uint64_t)scale) >> 32); 410cabdff1aSopenharmony_ci } 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci for (i = 0; i < hsize; i++) { 413cabdff1aSopenharmony_ci value = (int64_t) low [i + 2] * -INT64_C(65078576) + 414cabdff1aSopenharmony_ci (int64_t) low [i + 1] * INT64_C(1583578880) + 415cabdff1aSopenharmony_ci (int64_t) low [i + 0] * INT64_C(1583578880) + 416cabdff1aSopenharmony_ci (int64_t) low [i - 1] * -INT64_C(65078576) + 417cabdff1aSopenharmony_ci (int64_t) high[i + 1] * INT64_C(303700064) + 418cabdff1aSopenharmony_ci (int64_t) high[i + 0] * -INT64_C(3644400640) + 419cabdff1aSopenharmony_ci (int64_t) high[i - 1] * INT64_C(303700064); 420cabdff1aSopenharmony_ci dest[i * 2 + 1] = av_clip_int16(((value >> 32) * (uint64_t)scale) >> 32); 421cabdff1aSopenharmony_ci } 422cabdff1aSopenharmony_ci} 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_cistatic void reconstruction(AVCodecContext *avctx, int16_t *dest, 425cabdff1aSopenharmony_ci unsigned width, unsigned height, ptrdiff_t stride, 426cabdff1aSopenharmony_ci int64_t *scaling_h, int64_t *scaling_v) 427cabdff1aSopenharmony_ci{ 428cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 429cabdff1aSopenharmony_ci unsigned scaled_width, scaled_height; 430cabdff1aSopenharmony_ci int16_t *ptr, *tmp; 431cabdff1aSopenharmony_ci int i, j, k; 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_ci scaled_width = width >> NB_LEVELS; 434cabdff1aSopenharmony_ci scaled_height = height >> NB_LEVELS; 435cabdff1aSopenharmony_ci tmp = ctx->filter[0]; 436cabdff1aSopenharmony_ci 437cabdff1aSopenharmony_ci for (i = 0; i < NB_LEVELS; i++) { 438cabdff1aSopenharmony_ci int64_t scale_v = scaling_v[i]; 439cabdff1aSopenharmony_ci int64_t scale_h = scaling_h[i]; 440cabdff1aSopenharmony_ci scaled_width <<= 1; 441cabdff1aSopenharmony_ci scaled_height <<= 1; 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_ci ptr = dest; 444cabdff1aSopenharmony_ci for (j = 0; j < scaled_height; j++) { 445cabdff1aSopenharmony_ci filterfn(ptr, ctx->filter[1], scaled_width, scale_v); 446cabdff1aSopenharmony_ci ptr += stride; 447cabdff1aSopenharmony_ci } 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci for (j = 0; j < scaled_width; j++) { 450cabdff1aSopenharmony_ci ptr = dest + j; 451cabdff1aSopenharmony_ci for (k = 0; k < scaled_height; k++) { 452cabdff1aSopenharmony_ci tmp[k] = *ptr; 453cabdff1aSopenharmony_ci ptr += stride; 454cabdff1aSopenharmony_ci } 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci filterfn(tmp, ctx->filter[1], scaled_height, scale_h); 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci ptr = dest + j; 459cabdff1aSopenharmony_ci for (k = 0; k < scaled_height; k++) { 460cabdff1aSopenharmony_ci *ptr = tmp[k]; 461cabdff1aSopenharmony_ci ptr += stride; 462cabdff1aSopenharmony_ci } 463cabdff1aSopenharmony_ci } 464cabdff1aSopenharmony_ci } 465cabdff1aSopenharmony_ci} 466cabdff1aSopenharmony_ci 467cabdff1aSopenharmony_cistatic void build_luma_lut(AVCodecContext *avctx, int depth) 468cabdff1aSopenharmony_ci{ 469cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 470cabdff1aSopenharmony_ci int max = (1 << depth) - 1; 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_ci if (ctx->depth == depth) 473cabdff1aSopenharmony_ci return; 474cabdff1aSopenharmony_ci ctx->depth = depth; 475cabdff1aSopenharmony_ci 476cabdff1aSopenharmony_ci for (int i = 0; i < FF_ARRAY_ELEMS(ctx->lut); i++) 477cabdff1aSopenharmony_ci ctx->lut[i] = ((int64_t)i * i * 65535LL) / max / max; 478cabdff1aSopenharmony_ci} 479cabdff1aSopenharmony_ci 480cabdff1aSopenharmony_cistatic void postprocess_luma(AVCodecContext *avctx, AVFrame *frame, 481cabdff1aSopenharmony_ci int w, int h, int depth) 482cabdff1aSopenharmony_ci{ 483cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 484cabdff1aSopenharmony_ci uint16_t *dsty = (uint16_t *)frame->data[0]; 485cabdff1aSopenharmony_ci int16_t *srcy = (int16_t *)frame->data[0]; 486cabdff1aSopenharmony_ci ptrdiff_t stridey = frame->linesize[0] / 2; 487cabdff1aSopenharmony_ci uint16_t *lut = ctx->lut; 488cabdff1aSopenharmony_ci int i, j; 489cabdff1aSopenharmony_ci 490cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 491cabdff1aSopenharmony_ci for (i = 0; i < w; i++) { 492cabdff1aSopenharmony_ci if (srcy[i] <= 0) 493cabdff1aSopenharmony_ci dsty[i] = 0; 494cabdff1aSopenharmony_ci else if (srcy[i] > ((1 << depth) - 1)) 495cabdff1aSopenharmony_ci dsty[i] = 65535; 496cabdff1aSopenharmony_ci else 497cabdff1aSopenharmony_ci dsty[i] = lut[srcy[i]]; 498cabdff1aSopenharmony_ci } 499cabdff1aSopenharmony_ci dsty += stridey; 500cabdff1aSopenharmony_ci srcy += stridey; 501cabdff1aSopenharmony_ci } 502cabdff1aSopenharmony_ci} 503cabdff1aSopenharmony_ci 504cabdff1aSopenharmony_cistatic void postprocess_chroma(AVFrame *frame, int w, int h, int depth) 505cabdff1aSopenharmony_ci{ 506cabdff1aSopenharmony_ci uint16_t *dstu = (uint16_t *)frame->data[1]; 507cabdff1aSopenharmony_ci uint16_t *dstv = (uint16_t *)frame->data[2]; 508cabdff1aSopenharmony_ci int16_t *srcu = (int16_t *)frame->data[1]; 509cabdff1aSopenharmony_ci int16_t *srcv = (int16_t *)frame->data[2]; 510cabdff1aSopenharmony_ci ptrdiff_t strideu = frame->linesize[1] / 2; 511cabdff1aSopenharmony_ci ptrdiff_t stridev = frame->linesize[2] / 2; 512cabdff1aSopenharmony_ci const unsigned add = 1 << (depth - 1); 513cabdff1aSopenharmony_ci const unsigned shift = 16 - depth; 514cabdff1aSopenharmony_ci int i, j; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 517cabdff1aSopenharmony_ci for (i = 0; i < w; i++) { 518cabdff1aSopenharmony_ci dstu[i] = av_clip_uintp2_c(add + srcu[i], depth) << shift; 519cabdff1aSopenharmony_ci dstv[i] = av_clip_uintp2_c(add + srcv[i], depth) << shift; 520cabdff1aSopenharmony_ci } 521cabdff1aSopenharmony_ci dstu += strideu; 522cabdff1aSopenharmony_ci dstv += stridev; 523cabdff1aSopenharmony_ci srcu += strideu; 524cabdff1aSopenharmony_ci srcv += stridev; 525cabdff1aSopenharmony_ci } 526cabdff1aSopenharmony_ci} 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_cistatic int decode_plane(AVCodecContext *avctx, int plane, 529cabdff1aSopenharmony_ci const AVPacket *avpkt, AVFrame *frame) 530cabdff1aSopenharmony_ci{ 531cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 532cabdff1aSopenharmony_ci ptrdiff_t stride = frame->linesize[plane] / 2; 533cabdff1aSopenharmony_ci unsigned shift = plane > 0; 534cabdff1aSopenharmony_ci int16_t *dst; 535cabdff1aSopenharmony_ci int i, ret; 536cabdff1aSopenharmony_ci 537cabdff1aSopenharmony_ci for (i = ctx->levels - 1; i >= 0; i--) { 538cabdff1aSopenharmony_ci int32_t h = sign_extend(bytestream2_get_be32(&ctx->gb), 32); 539cabdff1aSopenharmony_ci int32_t v = sign_extend(bytestream2_get_be32(&ctx->gb), 32); 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci if (!h || !v) 542cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 543cabdff1aSopenharmony_ci 544cabdff1aSopenharmony_ci ctx->scaling[plane][H][i] = (1000000ULL << 32) / h; 545cabdff1aSopenharmony_ci ctx->scaling[plane][V][i] = (1000000ULL << 32) / v; 546cabdff1aSopenharmony_ci } 547cabdff1aSopenharmony_ci 548cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, 4); 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci dst = (int16_t *)frame->data[plane]; 551cabdff1aSopenharmony_ci dst[0] = sign_extend(bytestream2_get_be16(&ctx->gb), 16); 552cabdff1aSopenharmony_ci 553cabdff1aSopenharmony_ci ret = init_get_bits8(&ctx->bc, avpkt->data + bytestream2_tell(&ctx->gb), 554cabdff1aSopenharmony_ci bytestream2_get_bytes_left(&ctx->gb)); 555cabdff1aSopenharmony_ci if (ret < 0) 556cabdff1aSopenharmony_ci return ret; 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci ret = read_low_coeffs(avctx, dst + 1, ctx->band[plane][0].width - 1, 559cabdff1aSopenharmony_ci ctx->band[plane][0].width - 1, 0); 560cabdff1aSopenharmony_ci if (ret < 0) { 561cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 562cabdff1aSopenharmony_ci "error in lowpass coefficients for plane %d, top row\n", plane); 563cabdff1aSopenharmony_ci return ret; 564cabdff1aSopenharmony_ci } 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci ret = read_low_coeffs(avctx, dst + stride, 567cabdff1aSopenharmony_ci ctx->band[plane][0].height - 1, 1, stride); 568cabdff1aSopenharmony_ci if (ret < 0) { 569cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 570cabdff1aSopenharmony_ci "error in lowpass coefficients for plane %d, left column\n", 571cabdff1aSopenharmony_ci plane); 572cabdff1aSopenharmony_ci return ret; 573cabdff1aSopenharmony_ci } 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_ci ret = read_low_coeffs(avctx, dst + stride + 1, 576cabdff1aSopenharmony_ci (ctx->band[plane][0].width - 1) * (ctx->band[plane][0].height - 1), 577cabdff1aSopenharmony_ci ctx->band[plane][0].width - 1, stride); 578cabdff1aSopenharmony_ci if (ret < 0) { 579cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 580cabdff1aSopenharmony_ci "error in lowpass coefficients for plane %d, rest\n", plane); 581cabdff1aSopenharmony_ci return ret; 582cabdff1aSopenharmony_ci } 583cabdff1aSopenharmony_ci 584cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, ret); 585cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&ctx->gb) <= 0) { 586cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "no bytes left\n"); 587cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 588cabdff1aSopenharmony_ci } 589cabdff1aSopenharmony_ci 590cabdff1aSopenharmony_ci ret = read_highpass(avctx, avpkt->data, plane, frame); 591cabdff1aSopenharmony_ci if (ret < 0) 592cabdff1aSopenharmony_ci return ret; 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ci lowpass_prediction(dst, ctx->prediction, ctx->band[plane][0].width, 595cabdff1aSopenharmony_ci ctx->band[plane][0].height, stride); 596cabdff1aSopenharmony_ci 597cabdff1aSopenharmony_ci reconstruction(avctx, (int16_t *)frame->data[plane], ctx->w >> shift, 598cabdff1aSopenharmony_ci ctx->h >> shift, stride, ctx->scaling[plane][H], 599cabdff1aSopenharmony_ci ctx->scaling[plane][V]); 600cabdff1aSopenharmony_ci 601cabdff1aSopenharmony_ci return 0; 602cabdff1aSopenharmony_ci} 603cabdff1aSopenharmony_ci 604cabdff1aSopenharmony_cistatic int pixlet_decode_frame(AVCodecContext *avctx, AVFrame *p, 605cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 606cabdff1aSopenharmony_ci{ 607cabdff1aSopenharmony_ci PixletContext *ctx = avctx->priv_data; 608cabdff1aSopenharmony_ci int i, w, h, width, height, ret, version; 609cabdff1aSopenharmony_ci uint32_t pktsize, depth; 610cabdff1aSopenharmony_ci 611cabdff1aSopenharmony_ci bytestream2_init(&ctx->gb, avpkt->data, avpkt->size); 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci pktsize = bytestream2_get_be32(&ctx->gb); 614cabdff1aSopenharmony_ci if (pktsize <= 44 + (NB_LEVELS * 8 + 6) * 3 || pktsize - 4 > bytestream2_get_bytes_left(&ctx->gb)) { 615cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid packet size %"PRIu32"\n", pktsize); 616cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 617cabdff1aSopenharmony_ci } 618cabdff1aSopenharmony_ci 619cabdff1aSopenharmony_ci version = bytestream2_get_le32(&ctx->gb); 620cabdff1aSopenharmony_ci if (version != 1) 621cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Version %d", version); 622cabdff1aSopenharmony_ci 623cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, 4); 624cabdff1aSopenharmony_ci if (bytestream2_get_be32(&ctx->gb) != 1) 625cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 626cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, 4); 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci width = bytestream2_get_be32(&ctx->gb); 629cabdff1aSopenharmony_ci height = bytestream2_get_be32(&ctx->gb); 630cabdff1aSopenharmony_ci 631cabdff1aSopenharmony_ci if ( width > INT_MAX - (1U << (NB_LEVELS + 1)) 632cabdff1aSopenharmony_ci || height > INT_MAX - (1U << (NB_LEVELS + 1))) 633cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci w = FFALIGN(width, 1 << (NB_LEVELS + 1)); 636cabdff1aSopenharmony_ci h = FFALIGN(height, 1 << (NB_LEVELS + 1)); 637cabdff1aSopenharmony_ci 638cabdff1aSopenharmony_ci ctx->levels = bytestream2_get_be32(&ctx->gb); 639cabdff1aSopenharmony_ci if (ctx->levels != NB_LEVELS) 640cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 641cabdff1aSopenharmony_ci depth = bytestream2_get_be32(&ctx->gb); 642cabdff1aSopenharmony_ci if (depth < 8 || depth > 15) { 643cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "Depth %d", depth); 644cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 645cabdff1aSopenharmony_ci } 646cabdff1aSopenharmony_ci 647cabdff1aSopenharmony_ci build_luma_lut(avctx, depth); 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_ci ret = ff_set_dimensions(avctx, w, h); 650cabdff1aSopenharmony_ci if (ret < 0) 651cabdff1aSopenharmony_ci return ret; 652cabdff1aSopenharmony_ci avctx->width = width; 653cabdff1aSopenharmony_ci avctx->height = height; 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ci if (ctx->w != w || ctx->h != h) { 656cabdff1aSopenharmony_ci free_buffers(avctx); 657cabdff1aSopenharmony_ci ctx->w = w; 658cabdff1aSopenharmony_ci ctx->h = h; 659cabdff1aSopenharmony_ci 660cabdff1aSopenharmony_ci ret = init_decoder(avctx); 661cabdff1aSopenharmony_ci if (ret < 0) { 662cabdff1aSopenharmony_ci free_buffers(avctx); 663cabdff1aSopenharmony_ci ctx->w = 0; 664cabdff1aSopenharmony_ci ctx->h = 0; 665cabdff1aSopenharmony_ci return ret; 666cabdff1aSopenharmony_ci } 667cabdff1aSopenharmony_ci } 668cabdff1aSopenharmony_ci 669cabdff1aSopenharmony_ci bytestream2_skip(&ctx->gb, 8); 670cabdff1aSopenharmony_ci 671cabdff1aSopenharmony_ci p->pict_type = AV_PICTURE_TYPE_I; 672cabdff1aSopenharmony_ci p->key_frame = 1; 673cabdff1aSopenharmony_ci p->color_range = AVCOL_RANGE_JPEG; 674cabdff1aSopenharmony_ci 675cabdff1aSopenharmony_ci ret = ff_thread_get_buffer(avctx, p, 0); 676cabdff1aSopenharmony_ci if (ret < 0) 677cabdff1aSopenharmony_ci return ret; 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 680cabdff1aSopenharmony_ci ret = decode_plane(avctx, i, avpkt, p); 681cabdff1aSopenharmony_ci if (ret < 0) 682cabdff1aSopenharmony_ci return ret; 683cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_GRAY) 684cabdff1aSopenharmony_ci break; 685cabdff1aSopenharmony_ci } 686cabdff1aSopenharmony_ci 687cabdff1aSopenharmony_ci postprocess_luma(avctx, p, ctx->w, ctx->h, ctx->depth); 688cabdff1aSopenharmony_ci postprocess_chroma(p, ctx->w >> 1, ctx->h >> 1, ctx->depth); 689cabdff1aSopenharmony_ci 690cabdff1aSopenharmony_ci *got_frame = 1; 691cabdff1aSopenharmony_ci 692cabdff1aSopenharmony_ci return pktsize; 693cabdff1aSopenharmony_ci} 694cabdff1aSopenharmony_ci 695cabdff1aSopenharmony_ciconst FFCodec ff_pixlet_decoder = { 696cabdff1aSopenharmony_ci .p.name = "pixlet", 697cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), 698cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 699cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_PIXLET, 700cabdff1aSopenharmony_ci .init = pixlet_init, 701cabdff1aSopenharmony_ci .close = pixlet_close, 702cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(pixlet_decode_frame), 703cabdff1aSopenharmony_ci .priv_data_size = sizeof(PixletContext), 704cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1 | 705cabdff1aSopenharmony_ci AV_CODEC_CAP_FRAME_THREADS, 706cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | 707cabdff1aSopenharmony_ci FF_CODEC_CAP_INIT_CLEANUP, 708cabdff1aSopenharmony_ci}; 709