1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Apple ProRes encoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2011 Anatoliy Wasserman 5cabdff1aSopenharmony_ci * Copyright (c) 2012 Konstantin Shishkov 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci/** 25cabdff1aSopenharmony_ci * @file 26cabdff1aSopenharmony_ci * Apple ProRes encoder (Anatoliy Wasserman version) 27cabdff1aSopenharmony_ci * Known FOURCCs: 'ap4h' (444), 'apch' (HQ), 'apcn' (422), 'apcs' (LT), 'acpo' (Proxy) 28cabdff1aSopenharmony_ci */ 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h" 31cabdff1aSopenharmony_ci#include "libavutil/opt.h" 32cabdff1aSopenharmony_ci#include "avcodec.h" 33cabdff1aSopenharmony_ci#include "codec_internal.h" 34cabdff1aSopenharmony_ci#include "dct.h" 35cabdff1aSopenharmony_ci#include "encode.h" 36cabdff1aSopenharmony_ci#include "internal.h" 37cabdff1aSopenharmony_ci#include "profiles.h" 38cabdff1aSopenharmony_ci#include "proresdata.h" 39cabdff1aSopenharmony_ci#include "put_bits.h" 40cabdff1aSopenharmony_ci#include "bytestream.h" 41cabdff1aSopenharmony_ci#include "fdctdsp.h" 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci#define DEFAULT_SLICE_MB_WIDTH 8 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistatic const AVProfile profiles[] = { 46cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_PROXY, "apco"}, 47cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_LT, "apcs"}, 48cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_STANDARD, "apcn"}, 49cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_HQ, "apch"}, 50cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_4444, "ap4h"}, 51cabdff1aSopenharmony_ci { FF_PROFILE_PRORES_XQ, "ap4x"}, 52cabdff1aSopenharmony_ci { FF_PROFILE_UNKNOWN } 53cabdff1aSopenharmony_ci}; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic const int qp_start_table[] = { 8, 3, 2, 1, 1, 1}; 56cabdff1aSopenharmony_cistatic const int qp_end_table[] = { 13, 9, 6, 6, 5, 4}; 57cabdff1aSopenharmony_cistatic const int bitrate_table[] = { 1000, 2100, 3500, 5400, 7000, 10000}; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_cistatic const int valid_primaries[] = { AVCOL_PRI_RESERVED0, AVCOL_PRI_BT709, AVCOL_PRI_UNSPECIFIED, AVCOL_PRI_BT470BG, 60cabdff1aSopenharmony_ci AVCOL_PRI_SMPTE170M, AVCOL_PRI_BT2020, AVCOL_PRI_SMPTE431, AVCOL_PRI_SMPTE432, INT_MAX }; 61cabdff1aSopenharmony_cistatic const int valid_trc[] = { AVCOL_TRC_RESERVED0, AVCOL_TRC_BT709, AVCOL_TRC_UNSPECIFIED, AVCOL_TRC_SMPTE2084, 62cabdff1aSopenharmony_ci AVCOL_TRC_ARIB_STD_B67, INT_MAX }; 63cabdff1aSopenharmony_cistatic const int valid_colorspace[] = { AVCOL_SPC_BT709, AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_SMPTE170M, 64cabdff1aSopenharmony_ci AVCOL_SPC_BT2020_NCL, INT_MAX }; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic const uint8_t QMAT_LUMA[6][64] = { 67cabdff1aSopenharmony_ci { 68cabdff1aSopenharmony_ci 4, 7, 9, 11, 13, 14, 15, 63, 69cabdff1aSopenharmony_ci 7, 7, 11, 12, 14, 15, 63, 63, 70cabdff1aSopenharmony_ci 9, 11, 13, 14, 15, 63, 63, 63, 71cabdff1aSopenharmony_ci 11, 11, 13, 14, 63, 63, 63, 63, 72cabdff1aSopenharmony_ci 11, 13, 14, 63, 63, 63, 63, 63, 73cabdff1aSopenharmony_ci 13, 14, 63, 63, 63, 63, 63, 63, 74cabdff1aSopenharmony_ci 13, 63, 63, 63, 63, 63, 63, 63, 75cabdff1aSopenharmony_ci 63, 63, 63, 63, 63, 63, 63, 63 76cabdff1aSopenharmony_ci }, { 77cabdff1aSopenharmony_ci 4, 5, 6, 7, 9, 11, 13, 15, 78cabdff1aSopenharmony_ci 5, 5, 7, 8, 11, 13, 15, 17, 79cabdff1aSopenharmony_ci 6, 7, 9, 11, 13, 15, 15, 17, 80cabdff1aSopenharmony_ci 7, 7, 9, 11, 13, 15, 17, 19, 81cabdff1aSopenharmony_ci 7, 9, 11, 13, 14, 16, 19, 23, 82cabdff1aSopenharmony_ci 9, 11, 13, 14, 16, 19, 23, 29, 83cabdff1aSopenharmony_ci 9, 11, 13, 15, 17, 21, 28, 35, 84cabdff1aSopenharmony_ci 11, 13, 16, 17, 21, 28, 35, 41 85cabdff1aSopenharmony_ci }, { 86cabdff1aSopenharmony_ci 4, 4, 5, 5, 6, 7, 7, 9, 87cabdff1aSopenharmony_ci 4, 4, 5, 6, 7, 7, 9, 9, 88cabdff1aSopenharmony_ci 5, 5, 6, 7, 7, 9, 9, 10, 89cabdff1aSopenharmony_ci 5, 5, 6, 7, 7, 9, 9, 10, 90cabdff1aSopenharmony_ci 5, 6, 7, 7, 8, 9, 10, 12, 91cabdff1aSopenharmony_ci 6, 7, 7, 8, 9, 10, 12, 15, 92cabdff1aSopenharmony_ci 6, 7, 7, 9, 10, 11, 14, 17, 93cabdff1aSopenharmony_ci 7, 7, 9, 10, 11, 14, 17, 21 94cabdff1aSopenharmony_ci }, { 95cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 96cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 97cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 98cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 5, 99cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 5, 5, 100cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 5, 5, 6, 101cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 5, 6, 7, 102cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 6, 7, 7 103cabdff1aSopenharmony_ci }, { /* 444 */ 104cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 105cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 106cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 107cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 5, 108cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 5, 5, 109cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 5, 5, 6, 110cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 5, 6, 7, 111cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 6, 7, 7 112cabdff1aSopenharmony_ci }, { /* 444 XQ */ 113cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 2, 2, 2, 114cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 2, 2, 2, 115cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 2, 2, 2, 116cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 2, 2, 3, 117cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 2, 3, 3, 118cabdff1aSopenharmony_ci 2, 2, 2, 2, 2, 3, 3, 3, 119cabdff1aSopenharmony_ci 2, 2, 2, 2, 3, 3, 3, 4, 120cabdff1aSopenharmony_ci 2, 2, 2, 2, 3, 3, 4, 4, 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci}; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic const uint8_t QMAT_CHROMA[6][64] = { 125cabdff1aSopenharmony_ci { 126cabdff1aSopenharmony_ci 4, 7, 9, 11, 13, 14, 63, 63, 127cabdff1aSopenharmony_ci 7, 7, 11, 12, 14, 63, 63, 63, 128cabdff1aSopenharmony_ci 9, 11, 13, 14, 63, 63, 63, 63, 129cabdff1aSopenharmony_ci 11, 11, 13, 14, 63, 63, 63, 63, 130cabdff1aSopenharmony_ci 11, 13, 14, 63, 63, 63, 63, 63, 131cabdff1aSopenharmony_ci 13, 14, 63, 63, 63, 63, 63, 63, 132cabdff1aSopenharmony_ci 13, 63, 63, 63, 63, 63, 63, 63, 133cabdff1aSopenharmony_ci 63, 63, 63, 63, 63, 63, 63, 63 134cabdff1aSopenharmony_ci }, { 135cabdff1aSopenharmony_ci 4, 5, 6, 7, 9, 11, 13, 15, 136cabdff1aSopenharmony_ci 5, 5, 7, 8, 11, 13, 15, 17, 137cabdff1aSopenharmony_ci 6, 7, 9, 11, 13, 15, 15, 17, 138cabdff1aSopenharmony_ci 7, 7, 9, 11, 13, 15, 17, 19, 139cabdff1aSopenharmony_ci 7, 9, 11, 13, 14, 16, 19, 23, 140cabdff1aSopenharmony_ci 9, 11, 13, 14, 16, 19, 23, 29, 141cabdff1aSopenharmony_ci 9, 11, 13, 15, 17, 21, 28, 35, 142cabdff1aSopenharmony_ci 11, 13, 16, 17, 21, 28, 35, 41 143cabdff1aSopenharmony_ci }, { 144cabdff1aSopenharmony_ci 4, 4, 5, 5, 6, 7, 7, 9, 145cabdff1aSopenharmony_ci 4, 4, 5, 6, 7, 7, 9, 9, 146cabdff1aSopenharmony_ci 5, 5, 6, 7, 7, 9, 9, 10, 147cabdff1aSopenharmony_ci 5, 5, 6, 7, 7, 9, 9, 10, 148cabdff1aSopenharmony_ci 5, 6, 7, 7, 8, 9, 10, 12, 149cabdff1aSopenharmony_ci 6, 7, 7, 8, 9, 10, 12, 15, 150cabdff1aSopenharmony_ci 6, 7, 7, 9, 10, 11, 14, 17, 151cabdff1aSopenharmony_ci 7, 7, 9, 10, 11, 14, 17, 21 152cabdff1aSopenharmony_ci }, { 153cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 154cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 155cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 156cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 5, 157cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 5, 5, 158cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 5, 5, 6, 159cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 5, 6, 7, 160cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 6, 7, 7 161cabdff1aSopenharmony_ci }, { /* 444 */ 162cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 163cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 164cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 165cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 5, 166cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 5, 5, 167cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 5, 5, 6, 168cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 5, 6, 7, 169cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 6, 7, 7 170cabdff1aSopenharmony_ci }, { /* 444 xq */ 171cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 172cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 173cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 4, 174cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 4, 5, 175cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 4, 5, 5, 176cabdff1aSopenharmony_ci 4, 4, 4, 4, 4, 5, 5, 6, 177cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 5, 6, 7, 178cabdff1aSopenharmony_ci 4, 4, 4, 4, 5, 6, 7, 7 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci}; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_citypedef struct { 184cabdff1aSopenharmony_ci AVClass *class; 185cabdff1aSopenharmony_ci FDCTDSPContext fdsp; 186cabdff1aSopenharmony_ci uint8_t* fill_y; 187cabdff1aSopenharmony_ci uint8_t* fill_u; 188cabdff1aSopenharmony_ci uint8_t* fill_v; 189cabdff1aSopenharmony_ci uint8_t* fill_a; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci int qmat_luma[16][64]; 192cabdff1aSopenharmony_ci int qmat_chroma[16][64]; 193cabdff1aSopenharmony_ci const uint8_t *scantable; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci int is_422; 196cabdff1aSopenharmony_ci int need_alpha; 197cabdff1aSopenharmony_ci int is_interlaced; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci char *vendor; 200cabdff1aSopenharmony_ci} ProresContext; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_cistatic void encode_codeword(PutBitContext *pb, int val, int codebook) 203cabdff1aSopenharmony_ci{ 204cabdff1aSopenharmony_ci unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci /* number of bits to switch between rice and exp golomb */ 207cabdff1aSopenharmony_ci switch_bits = codebook & 3; 208cabdff1aSopenharmony_ci rice_order = codebook >> 5; 209cabdff1aSopenharmony_ci exp_order = (codebook >> 2) & 7; 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci first_exp = ((switch_bits + 1) << rice_order); 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci if (val >= first_exp) { /* exp golomb */ 214cabdff1aSopenharmony_ci val -= first_exp; 215cabdff1aSopenharmony_ci val += (1 << exp_order); 216cabdff1aSopenharmony_ci exp = av_log2(val); 217cabdff1aSopenharmony_ci zeros = exp - exp_order + switch_bits + 1; 218cabdff1aSopenharmony_ci put_bits(pb, zeros, 0); 219cabdff1aSopenharmony_ci put_bits(pb, exp + 1, val); 220cabdff1aSopenharmony_ci } else if (rice_order) { 221cabdff1aSopenharmony_ci put_bits(pb, (val >> rice_order), 0); 222cabdff1aSopenharmony_ci put_bits(pb, 1, 1); 223cabdff1aSopenharmony_ci put_sbits(pb, rice_order, val); 224cabdff1aSopenharmony_ci } else { 225cabdff1aSopenharmony_ci put_bits(pb, val, 0); 226cabdff1aSopenharmony_ci put_bits(pb, 1, 1); 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci} 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci#define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind])) 231cabdff1aSopenharmony_ci#define TO_GOLOMB(val) (((val) * 2) ^ ((val) >> 31)) 232cabdff1aSopenharmony_ci#define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign)) 233cabdff1aSopenharmony_ci#define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1) 234cabdff1aSopenharmony_ci#define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign)) 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_cistatic av_always_inline int get_level(int val) 237cabdff1aSopenharmony_ci{ 238cabdff1aSopenharmony_ci int sign = (val >> 31); 239cabdff1aSopenharmony_ci return (val ^ sign) - sign; 240cabdff1aSopenharmony_ci} 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci#define FIRST_DC_CB 0xB8 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_cistatic const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70}; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_cistatic void encode_dc_coeffs(PutBitContext *pb, int16_t *in, 247cabdff1aSopenharmony_ci int blocks_per_slice, int *qmat) 248cabdff1aSopenharmony_ci{ 249cabdff1aSopenharmony_ci int prev_dc, code; 250cabdff1aSopenharmony_ci int i, sign, idx; 251cabdff1aSopenharmony_ci int new_dc, delta, diff_sign, new_code; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci prev_dc = QSCALE(qmat, 0, in[0] - 16384); 254cabdff1aSopenharmony_ci code = TO_GOLOMB(prev_dc); 255cabdff1aSopenharmony_ci encode_codeword(pb, code, FIRST_DC_CB); 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci code = 5; sign = 0; idx = 64; 258cabdff1aSopenharmony_ci for (i = 1; i < blocks_per_slice; i++, idx += 64) { 259cabdff1aSopenharmony_ci new_dc = QSCALE(qmat, 0, in[idx] - 16384); 260cabdff1aSopenharmony_ci delta = new_dc - prev_dc; 261cabdff1aSopenharmony_ci diff_sign = DIFF_SIGN(delta, sign); 262cabdff1aSopenharmony_ci new_code = TO_GOLOMB2(get_level(delta), diff_sign); 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci encode_codeword(pb, new_code, dc_codebook[FFMIN(code, 6)]); 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci code = new_code; 267cabdff1aSopenharmony_ci sign = delta >> 31; 268cabdff1aSopenharmony_ci prev_dc = new_dc; 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci} 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_cistatic const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 273cabdff1aSopenharmony_ci 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C }; 274cabdff1aSopenharmony_cistatic const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 275cabdff1aSopenharmony_ci 0x28, 0x28, 0x28, 0x4C }; 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_cistatic void encode_ac_coeffs(PutBitContext *pb, 278cabdff1aSopenharmony_ci int16_t *in, int blocks_per_slice, int *qmat, const uint8_t ff_prores_scan[64]) 279cabdff1aSopenharmony_ci{ 280cabdff1aSopenharmony_ci int prev_run = 4; 281cabdff1aSopenharmony_ci int prev_level = 2; 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci int run = 0, level, code, i, j; 284cabdff1aSopenharmony_ci for (i = 1; i < 64; i++) { 285cabdff1aSopenharmony_ci int indp = ff_prores_scan[i]; 286cabdff1aSopenharmony_ci for (j = 0; j < blocks_per_slice; j++) { 287cabdff1aSopenharmony_ci int val = QSCALE(qmat, indp, in[(j << 6) + indp]); 288cabdff1aSopenharmony_ci if (val) { 289cabdff1aSopenharmony_ci encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]); 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci prev_run = run; 292cabdff1aSopenharmony_ci run = 0; 293cabdff1aSopenharmony_ci level = get_level(val); 294cabdff1aSopenharmony_ci code = level - 1; 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci encode_codeword(pb, code, lev_to_cb[FFMIN(prev_level, 9)]); 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci prev_level = level; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci put_bits(pb, 1, IS_NEGATIVE(val)); 301cabdff1aSopenharmony_ci } else { 302cabdff1aSopenharmony_ci ++run; 303cabdff1aSopenharmony_ci } 304cabdff1aSopenharmony_ci } 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci} 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_cistatic void get(uint8_t *pixels, int stride, int16_t* block) 309cabdff1aSopenharmony_ci{ 310cabdff1aSopenharmony_ci int i; 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 313cabdff1aSopenharmony_ci AV_WN64(block, AV_RN64(pixels)); 314cabdff1aSopenharmony_ci AV_WN64(block+4, AV_RN64(pixels+8)); 315cabdff1aSopenharmony_ci pixels += stride; 316cabdff1aSopenharmony_ci block += 8; 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci} 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_cistatic void fdct_get(FDCTDSPContext *fdsp, uint8_t *pixels, int stride, int16_t* block) 321cabdff1aSopenharmony_ci{ 322cabdff1aSopenharmony_ci get(pixels, stride, block); 323cabdff1aSopenharmony_ci fdsp->fdct(block); 324cabdff1aSopenharmony_ci} 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_cistatic void calc_plane_dct(FDCTDSPContext *fdsp, uint8_t *src, int16_t * blocks, int src_stride, int mb_count, int chroma, int is_422) 327cabdff1aSopenharmony_ci{ 328cabdff1aSopenharmony_ci int16_t *block; 329cabdff1aSopenharmony_ci int i; 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci block = blocks; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci if (!chroma) { /* Luma plane */ 334cabdff1aSopenharmony_ci for (i = 0; i < mb_count; i++) { 335cabdff1aSopenharmony_ci fdct_get(fdsp, src, src_stride, block + (0 << 6)); 336cabdff1aSopenharmony_ci fdct_get(fdsp, src + 16, src_stride, block + (1 << 6)); 337cabdff1aSopenharmony_ci fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (2 << 6)); 338cabdff1aSopenharmony_ci fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6)); 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci block += 256; 341cabdff1aSopenharmony_ci src += 32; 342cabdff1aSopenharmony_ci } 343cabdff1aSopenharmony_ci } else if (chroma && is_422){ /* chroma plane 422 */ 344cabdff1aSopenharmony_ci for (i = 0; i < mb_count; i++) { 345cabdff1aSopenharmony_ci fdct_get(fdsp, src, src_stride, block + (0 << 6)); 346cabdff1aSopenharmony_ci fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (1 << 6)); 347cabdff1aSopenharmony_ci block += (256 >> 1); 348cabdff1aSopenharmony_ci src += (32 >> 1); 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci } else { /* chroma plane 444 */ 351cabdff1aSopenharmony_ci for (i = 0; i < mb_count; i++) { 352cabdff1aSopenharmony_ci fdct_get(fdsp, src, src_stride, block + (0 << 6)); 353cabdff1aSopenharmony_ci fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (1 << 6)); 354cabdff1aSopenharmony_ci fdct_get(fdsp, src + 16, src_stride, block + (2 << 6)); 355cabdff1aSopenharmony_ci fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6)); 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci block += 256; 358cabdff1aSopenharmony_ci src += 32; 359cabdff1aSopenharmony_ci } 360cabdff1aSopenharmony_ci } 361cabdff1aSopenharmony_ci} 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_cistatic int encode_slice_plane(int16_t *blocks, int mb_count, uint8_t *buf, unsigned buf_size, int *qmat, int sub_sample_chroma, 364cabdff1aSopenharmony_ci const uint8_t ff_prores_scan[64]) 365cabdff1aSopenharmony_ci{ 366cabdff1aSopenharmony_ci int blocks_per_slice; 367cabdff1aSopenharmony_ci PutBitContext pb; 368cabdff1aSopenharmony_ci 369cabdff1aSopenharmony_ci blocks_per_slice = mb_count << (2 - sub_sample_chroma); 370cabdff1aSopenharmony_ci init_put_bits(&pb, buf, buf_size); 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat); 373cabdff1aSopenharmony_ci encode_ac_coeffs(&pb, blocks, blocks_per_slice, qmat, ff_prores_scan); 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ci flush_put_bits(&pb); 376cabdff1aSopenharmony_ci return put_bits_ptr(&pb) - pb.buf; 377cabdff1aSopenharmony_ci} 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_cistatic av_always_inline unsigned encode_slice_data(AVCodecContext *avctx, 380cabdff1aSopenharmony_ci int16_t * blocks_y, int16_t * blocks_u, int16_t * blocks_v, 381cabdff1aSopenharmony_ci unsigned mb_count, uint8_t *buf, unsigned data_size, 382cabdff1aSopenharmony_ci unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size, 383cabdff1aSopenharmony_ci int qp) 384cabdff1aSopenharmony_ci{ 385cabdff1aSopenharmony_ci ProresContext* ctx = avctx->priv_data; 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci *y_data_size = encode_slice_plane(blocks_y, mb_count, 388cabdff1aSopenharmony_ci buf, data_size, ctx->qmat_luma[qp - 1], 0, ctx->scantable); 389cabdff1aSopenharmony_ci 390cabdff1aSopenharmony_ci if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) { 391cabdff1aSopenharmony_ci *u_data_size = encode_slice_plane(blocks_u, mb_count, buf + *y_data_size, data_size - *y_data_size, 392cabdff1aSopenharmony_ci ctx->qmat_chroma[qp - 1], ctx->is_422, ctx->scantable); 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci *v_data_size = encode_slice_plane(blocks_v, mb_count, buf + *y_data_size + *u_data_size, 395cabdff1aSopenharmony_ci data_size - *y_data_size - *u_data_size, 396cabdff1aSopenharmony_ci ctx->qmat_chroma[qp - 1], ctx->is_422, ctx->scantable); 397cabdff1aSopenharmony_ci } 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci return *y_data_size + *u_data_size + *v_data_size; 400cabdff1aSopenharmony_ci} 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_cistatic void put_alpha_diff(PutBitContext *pb, int cur, int prev) 403cabdff1aSopenharmony_ci{ 404cabdff1aSopenharmony_ci const int abits = 16; 405cabdff1aSopenharmony_ci const int dbits = 7; 406cabdff1aSopenharmony_ci const int dsize = 1 << dbits - 1; 407cabdff1aSopenharmony_ci int diff = cur - prev; 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci diff = av_mod_uintp2(diff, abits); 410cabdff1aSopenharmony_ci if (diff >= (1 << abits) - dsize) 411cabdff1aSopenharmony_ci diff -= 1 << abits; 412cabdff1aSopenharmony_ci if (diff < -dsize || diff > dsize || !diff) { 413cabdff1aSopenharmony_ci put_bits(pb, 1, 1); 414cabdff1aSopenharmony_ci put_bits(pb, abits, diff); 415cabdff1aSopenharmony_ci } else { 416cabdff1aSopenharmony_ci put_bits(pb, 1, 0); 417cabdff1aSopenharmony_ci put_bits(pb, dbits - 1, FFABS(diff) - 1); 418cabdff1aSopenharmony_ci put_bits(pb, 1, diff < 0); 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci} 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_cistatic inline void put_alpha_run(PutBitContext *pb, int run) 423cabdff1aSopenharmony_ci{ 424cabdff1aSopenharmony_ci if (run) { 425cabdff1aSopenharmony_ci put_bits(pb, 1, 0); 426cabdff1aSopenharmony_ci if (run < 0x10) 427cabdff1aSopenharmony_ci put_bits(pb, 4, run); 428cabdff1aSopenharmony_ci else 429cabdff1aSopenharmony_ci put_bits(pb, 15, run); 430cabdff1aSopenharmony_ci } else { 431cabdff1aSopenharmony_ci put_bits(pb, 1, 1); 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci} 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_cistatic av_always_inline int encode_alpha_slice_data(AVCodecContext *avctx, int8_t * src_a, 436cabdff1aSopenharmony_ci unsigned mb_count, uint8_t *buf, unsigned data_size, unsigned* a_data_size) 437cabdff1aSopenharmony_ci{ 438cabdff1aSopenharmony_ci const int abits = 16; 439cabdff1aSopenharmony_ci const int mask = (1 << abits) - 1; 440cabdff1aSopenharmony_ci const int num_coeffs = mb_count * 256; 441cabdff1aSopenharmony_ci int prev = mask, cur; 442cabdff1aSopenharmony_ci int idx = 0; 443cabdff1aSopenharmony_ci int run = 0; 444cabdff1aSopenharmony_ci int16_t * blocks = (int16_t *)src_a; 445cabdff1aSopenharmony_ci PutBitContext pb; 446cabdff1aSopenharmony_ci init_put_bits(&pb, buf, data_size); 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci cur = blocks[idx++]; 449cabdff1aSopenharmony_ci put_alpha_diff(&pb, cur, prev); 450cabdff1aSopenharmony_ci prev = cur; 451cabdff1aSopenharmony_ci do { 452cabdff1aSopenharmony_ci cur = blocks[idx++]; 453cabdff1aSopenharmony_ci if (cur != prev) { 454cabdff1aSopenharmony_ci put_alpha_run (&pb, run); 455cabdff1aSopenharmony_ci put_alpha_diff(&pb, cur, prev); 456cabdff1aSopenharmony_ci prev = cur; 457cabdff1aSopenharmony_ci run = 0; 458cabdff1aSopenharmony_ci } else { 459cabdff1aSopenharmony_ci run++; 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci } while (idx < num_coeffs); 462cabdff1aSopenharmony_ci if (run) 463cabdff1aSopenharmony_ci put_alpha_run(&pb, run); 464cabdff1aSopenharmony_ci flush_put_bits(&pb); 465cabdff1aSopenharmony_ci *a_data_size = put_bytes_output(&pb); 466cabdff1aSopenharmony_ci 467cabdff1aSopenharmony_ci if (put_bits_left(&pb) < 0) { 468cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 469cabdff1aSopenharmony_ci "Underestimated required buffer size.\n"); 470cabdff1aSopenharmony_ci return AVERROR_BUG; 471cabdff1aSopenharmony_ci } else { 472cabdff1aSopenharmony_ci return 0; 473cabdff1aSopenharmony_ci } 474cabdff1aSopenharmony_ci} 475cabdff1aSopenharmony_ci 476cabdff1aSopenharmony_cistatic inline void subimage_with_fill_template(uint16_t *src, unsigned x, unsigned y, 477cabdff1aSopenharmony_ci unsigned stride, unsigned width, unsigned height, uint16_t *dst, 478cabdff1aSopenharmony_ci unsigned dst_width, unsigned dst_height, int is_alpha_plane, 479cabdff1aSopenharmony_ci int is_interlaced, int is_top_field) 480cabdff1aSopenharmony_ci{ 481cabdff1aSopenharmony_ci int box_width = FFMIN(width - x, dst_width); 482cabdff1aSopenharmony_ci int i, j, src_stride, box_height; 483cabdff1aSopenharmony_ci uint16_t last_pix, *last_line; 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci if (!is_interlaced) { 486cabdff1aSopenharmony_ci src_stride = stride >> 1; 487cabdff1aSopenharmony_ci src += y * src_stride + x; 488cabdff1aSopenharmony_ci box_height = FFMIN(height - y, dst_height); 489cabdff1aSopenharmony_ci } else { 490cabdff1aSopenharmony_ci src_stride = stride; /* 2 lines stride */ 491cabdff1aSopenharmony_ci src += y * src_stride + x; 492cabdff1aSopenharmony_ci box_height = FFMIN(height/2 - y, dst_height); 493cabdff1aSopenharmony_ci if (!is_top_field) 494cabdff1aSopenharmony_ci src += stride >> 1; 495cabdff1aSopenharmony_ci } 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci for (i = 0; i < box_height; ++i) { 498cabdff1aSopenharmony_ci for (j = 0; j < box_width; ++j) { 499cabdff1aSopenharmony_ci if (!is_alpha_plane) { 500cabdff1aSopenharmony_ci dst[j] = src[j]; 501cabdff1aSopenharmony_ci } else { 502cabdff1aSopenharmony_ci dst[j] = src[j] << 6; /* alpha 10b to 16b */ 503cabdff1aSopenharmony_ci } 504cabdff1aSopenharmony_ci } 505cabdff1aSopenharmony_ci if (!is_alpha_plane) { 506cabdff1aSopenharmony_ci last_pix = dst[j - 1]; 507cabdff1aSopenharmony_ci } else { 508cabdff1aSopenharmony_ci last_pix = dst[j - 1] << 6; /* alpha 10b to 16b */ 509cabdff1aSopenharmony_ci } 510cabdff1aSopenharmony_ci for (; j < dst_width; j++) 511cabdff1aSopenharmony_ci dst[j] = last_pix; 512cabdff1aSopenharmony_ci src += src_stride; 513cabdff1aSopenharmony_ci dst += dst_width; 514cabdff1aSopenharmony_ci } 515cabdff1aSopenharmony_ci last_line = dst - dst_width; 516cabdff1aSopenharmony_ci for (; i < dst_height; i++) { 517cabdff1aSopenharmony_ci for (j = 0; j < dst_width; ++j) { 518cabdff1aSopenharmony_ci dst[j] = last_line[j]; 519cabdff1aSopenharmony_ci } 520cabdff1aSopenharmony_ci dst += dst_width; 521cabdff1aSopenharmony_ci } 522cabdff1aSopenharmony_ci} 523cabdff1aSopenharmony_ci 524cabdff1aSopenharmony_cistatic void subimage_with_fill(uint16_t *src, unsigned x, unsigned y, 525cabdff1aSopenharmony_ci unsigned stride, unsigned width, unsigned height, uint16_t *dst, 526cabdff1aSopenharmony_ci unsigned dst_width, unsigned dst_height, int is_interlaced, int is_top_field) 527cabdff1aSopenharmony_ci{ 528cabdff1aSopenharmony_ci subimage_with_fill_template(src, x, y, stride, width, height, dst, dst_width, dst_height, 0, is_interlaced, is_top_field); 529cabdff1aSopenharmony_ci} 530cabdff1aSopenharmony_ci 531cabdff1aSopenharmony_ci/* reorganize alpha data and convert 10b -> 16b */ 532cabdff1aSopenharmony_cistatic void subimage_alpha_with_fill(uint16_t *src, unsigned x, unsigned y, 533cabdff1aSopenharmony_ci unsigned stride, unsigned width, unsigned height, uint16_t *dst, 534cabdff1aSopenharmony_ci unsigned dst_width, unsigned dst_height, int is_interlaced, int is_top_field) 535cabdff1aSopenharmony_ci{ 536cabdff1aSopenharmony_ci subimage_with_fill_template(src, x, y, stride, width, height, dst, dst_width, dst_height, 1, is_interlaced, is_top_field); 537cabdff1aSopenharmony_ci} 538cabdff1aSopenharmony_ci 539cabdff1aSopenharmony_cistatic int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x, 540cabdff1aSopenharmony_ci int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size, 541cabdff1aSopenharmony_ci int unsafe, int *qp, int is_interlaced, int is_top_field) 542cabdff1aSopenharmony_ci{ 543cabdff1aSopenharmony_ci int luma_stride, chroma_stride, alpha_stride = 0; 544cabdff1aSopenharmony_ci ProresContext* ctx = avctx->priv_data; 545cabdff1aSopenharmony_ci int hdr_size = 6 + (ctx->need_alpha * 2); /* v data size is write when there is alpha */ 546cabdff1aSopenharmony_ci int ret = 0, slice_size; 547cabdff1aSopenharmony_ci uint8_t *dest_y, *dest_u, *dest_v; 548cabdff1aSopenharmony_ci unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0, a_data_size = 0; 549cabdff1aSopenharmony_ci FDCTDSPContext *fdsp = &ctx->fdsp; 550cabdff1aSopenharmony_ci int tgt_bits = (mb_count * bitrate_table[avctx->profile]) >> 2; 551cabdff1aSopenharmony_ci int low_bytes = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation 552cabdff1aSopenharmony_ci int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3; 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci LOCAL_ALIGNED(16, int16_t, blocks_y, [DEFAULT_SLICE_MB_WIDTH << 8]); 555cabdff1aSopenharmony_ci LOCAL_ALIGNED(16, int16_t, blocks_u, [DEFAULT_SLICE_MB_WIDTH << 8]); 556cabdff1aSopenharmony_ci LOCAL_ALIGNED(16, int16_t, blocks_v, [DEFAULT_SLICE_MB_WIDTH << 8]); 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci luma_stride = pic->linesize[0]; 559cabdff1aSopenharmony_ci chroma_stride = pic->linesize[1]; 560cabdff1aSopenharmony_ci 561cabdff1aSopenharmony_ci if (ctx->need_alpha) 562cabdff1aSopenharmony_ci alpha_stride = pic->linesize[3]; 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci if (!is_interlaced) { 565cabdff1aSopenharmony_ci dest_y = pic->data[0] + (mb_y << 4) * luma_stride + (mb_x << 5); 566cabdff1aSopenharmony_ci dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << (5 - ctx->is_422)); 567cabdff1aSopenharmony_ci dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << (5 - ctx->is_422)); 568cabdff1aSopenharmony_ci } else { 569cabdff1aSopenharmony_ci dest_y = pic->data[0] + (mb_y << 4) * luma_stride * 2 + (mb_x << 5); 570cabdff1aSopenharmony_ci dest_u = pic->data[1] + (mb_y << 4) * chroma_stride * 2 + (mb_x << (5 - ctx->is_422)); 571cabdff1aSopenharmony_ci dest_v = pic->data[2] + (mb_y << 4) * chroma_stride * 2 + (mb_x << (5 - ctx->is_422)); 572cabdff1aSopenharmony_ci if (!is_top_field){ /* bottom field, offset dest */ 573cabdff1aSopenharmony_ci dest_y += luma_stride; 574cabdff1aSopenharmony_ci dest_u += chroma_stride; 575cabdff1aSopenharmony_ci dest_v += chroma_stride; 576cabdff1aSopenharmony_ci } 577cabdff1aSopenharmony_ci } 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci if (unsafe) { 580cabdff1aSopenharmony_ci subimage_with_fill((uint16_t *) pic->data[0], mb_x << 4, mb_y << 4, 581cabdff1aSopenharmony_ci luma_stride, avctx->width, avctx->height, 582cabdff1aSopenharmony_ci (uint16_t *) ctx->fill_y, mb_count << 4, 16, is_interlaced, is_top_field); 583cabdff1aSopenharmony_ci subimage_with_fill((uint16_t *) pic->data[1], mb_x << (4 - ctx->is_422), mb_y << 4, 584cabdff1aSopenharmony_ci chroma_stride, avctx->width >> ctx->is_422, avctx->height, 585cabdff1aSopenharmony_ci (uint16_t *) ctx->fill_u, mb_count << (4 - ctx->is_422), 16, is_interlaced, is_top_field); 586cabdff1aSopenharmony_ci subimage_with_fill((uint16_t *) pic->data[2], mb_x << (4 - ctx->is_422), mb_y << 4, 587cabdff1aSopenharmony_ci chroma_stride, avctx->width >> ctx->is_422, avctx->height, 588cabdff1aSopenharmony_ci (uint16_t *) ctx->fill_v, mb_count << (4 - ctx->is_422), 16, is_interlaced, is_top_field); 589cabdff1aSopenharmony_ci 590cabdff1aSopenharmony_ci /* no need for interlaced special case, data already reorganized in subimage_with_fill */ 591cabdff1aSopenharmony_ci calc_plane_dct(fdsp, ctx->fill_y, blocks_y, mb_count << 5, mb_count, 0, 0); 592cabdff1aSopenharmony_ci calc_plane_dct(fdsp, ctx->fill_u, blocks_u, mb_count << (5 - ctx->is_422), mb_count, 1, ctx->is_422); 593cabdff1aSopenharmony_ci calc_plane_dct(fdsp, ctx->fill_v, blocks_v, mb_count << (5 - ctx->is_422), mb_count, 1, ctx->is_422); 594cabdff1aSopenharmony_ci 595cabdff1aSopenharmony_ci slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v, 596cabdff1aSopenharmony_ci mb_count, buf + hdr_size, data_size - hdr_size, 597cabdff1aSopenharmony_ci &y_data_size, &u_data_size, &v_data_size, 598cabdff1aSopenharmony_ci *qp); 599cabdff1aSopenharmony_ci } else { 600cabdff1aSopenharmony_ci if (!is_interlaced) { 601cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_y, blocks_y, luma_stride, mb_count, 0, 0); 602cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_u, blocks_u, chroma_stride, mb_count, 1, ctx->is_422); 603cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_v, blocks_v, chroma_stride, mb_count, 1, ctx->is_422); 604cabdff1aSopenharmony_ci } else { 605cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_y, blocks_y, luma_stride * 2, mb_count, 0, 0); 606cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_u, blocks_u, chroma_stride * 2, mb_count, 1, ctx->is_422); 607cabdff1aSopenharmony_ci calc_plane_dct(fdsp, dest_v, blocks_v, chroma_stride * 2, mb_count, 1, ctx->is_422); 608cabdff1aSopenharmony_ci } 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v, 611cabdff1aSopenharmony_ci mb_count, buf + hdr_size, data_size - hdr_size, 612cabdff1aSopenharmony_ci &y_data_size, &u_data_size, &v_data_size, 613cabdff1aSopenharmony_ci *qp); 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) { 616cabdff1aSopenharmony_ci do { 617cabdff1aSopenharmony_ci *qp += 1; 618cabdff1aSopenharmony_ci slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v, 619cabdff1aSopenharmony_ci mb_count, buf + hdr_size, data_size - hdr_size, 620cabdff1aSopenharmony_ci &y_data_size, &u_data_size, &v_data_size, 621cabdff1aSopenharmony_ci *qp); 622cabdff1aSopenharmony_ci } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]); 623cabdff1aSopenharmony_ci } else if (slice_size < low_bytes && *qp 624cabdff1aSopenharmony_ci > qp_start_table[avctx->profile]) { 625cabdff1aSopenharmony_ci do { 626cabdff1aSopenharmony_ci *qp -= 1; 627cabdff1aSopenharmony_ci slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v, 628cabdff1aSopenharmony_ci mb_count, buf + hdr_size, data_size - hdr_size, 629cabdff1aSopenharmony_ci &y_data_size, &u_data_size, &v_data_size, 630cabdff1aSopenharmony_ci *qp); 631cabdff1aSopenharmony_ci } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]); 632cabdff1aSopenharmony_ci } 633cabdff1aSopenharmony_ci } 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci buf[0] = hdr_size << 3; 636cabdff1aSopenharmony_ci buf[1] = *qp; 637cabdff1aSopenharmony_ci AV_WB16(buf + 2, y_data_size); 638cabdff1aSopenharmony_ci AV_WB16(buf + 4, u_data_size); 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci if (ctx->need_alpha) { 641cabdff1aSopenharmony_ci AV_WB16(buf + 6, v_data_size); /* write v data size only if there is alpha */ 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_ci subimage_alpha_with_fill((uint16_t *) pic->data[3], mb_x << 4, mb_y << 4, 644cabdff1aSopenharmony_ci alpha_stride, avctx->width, avctx->height, 645cabdff1aSopenharmony_ci (uint16_t *) ctx->fill_a, mb_count << 4, 16, is_interlaced, is_top_field); 646cabdff1aSopenharmony_ci ret = encode_alpha_slice_data(avctx, ctx->fill_a, mb_count, 647cabdff1aSopenharmony_ci buf + hdr_size + slice_size, 648cabdff1aSopenharmony_ci data_size - hdr_size - slice_size, &a_data_size); 649cabdff1aSopenharmony_ci } 650cabdff1aSopenharmony_ci 651cabdff1aSopenharmony_ci if (ret != 0) { 652cabdff1aSopenharmony_ci return ret; 653cabdff1aSopenharmony_ci } 654cabdff1aSopenharmony_ci return hdr_size + y_data_size + u_data_size + v_data_size + a_data_size; 655cabdff1aSopenharmony_ci} 656cabdff1aSopenharmony_ci 657cabdff1aSopenharmony_cistatic int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic, 658cabdff1aSopenharmony_ci uint8_t *buf, const int buf_size, const int picture_index, const int is_top_field) 659cabdff1aSopenharmony_ci{ 660cabdff1aSopenharmony_ci ProresContext *ctx = avctx->priv_data; 661cabdff1aSopenharmony_ci int mb_width = (avctx->width + 15) >> 4; 662cabdff1aSopenharmony_ci int hdr_size, sl_size, i; 663cabdff1aSopenharmony_ci int mb_y, sl_data_size, qp, mb_height, picture_height, unsafe_mb_height_limit; 664cabdff1aSopenharmony_ci int unsafe_bot, unsafe_right; 665cabdff1aSopenharmony_ci uint8_t *sl_data, *sl_data_sizes; 666cabdff1aSopenharmony_ci int slice_per_line = 0, rem = mb_width; 667cabdff1aSopenharmony_ci 668cabdff1aSopenharmony_ci if (!ctx->is_interlaced) { /* progressive encoding */ 669cabdff1aSopenharmony_ci mb_height = (avctx->height + 15) >> 4; 670cabdff1aSopenharmony_ci unsafe_mb_height_limit = mb_height; 671cabdff1aSopenharmony_ci } else { 672cabdff1aSopenharmony_ci if (is_top_field) { 673cabdff1aSopenharmony_ci picture_height = (avctx->height + 1) / 2; 674cabdff1aSopenharmony_ci } else { 675cabdff1aSopenharmony_ci picture_height = avctx->height / 2; 676cabdff1aSopenharmony_ci } 677cabdff1aSopenharmony_ci mb_height = (picture_height + 15) >> 4; 678cabdff1aSopenharmony_ci unsafe_mb_height_limit = mb_height; 679cabdff1aSopenharmony_ci } 680cabdff1aSopenharmony_ci 681cabdff1aSopenharmony_ci for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) { 682cabdff1aSopenharmony_ci slice_per_line += rem >> i; 683cabdff1aSopenharmony_ci rem &= (1 << i) - 1; 684cabdff1aSopenharmony_ci } 685cabdff1aSopenharmony_ci 686cabdff1aSopenharmony_ci qp = qp_start_table[avctx->profile]; 687cabdff1aSopenharmony_ci hdr_size = 8; sl_data_size = buf_size - hdr_size; 688cabdff1aSopenharmony_ci sl_data_sizes = buf + hdr_size; 689cabdff1aSopenharmony_ci sl_data = sl_data_sizes + (slice_per_line * mb_height * 2); 690cabdff1aSopenharmony_ci for (mb_y = 0; mb_y < mb_height; mb_y++) { 691cabdff1aSopenharmony_ci int mb_x = 0; 692cabdff1aSopenharmony_ci int slice_mb_count = DEFAULT_SLICE_MB_WIDTH; 693cabdff1aSopenharmony_ci while (mb_x < mb_width) { 694cabdff1aSopenharmony_ci while (mb_width - mb_x < slice_mb_count) 695cabdff1aSopenharmony_ci slice_mb_count >>= 1; 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_ci unsafe_bot = (avctx->height & 0xf) && (mb_y == unsafe_mb_height_limit - 1); 698cabdff1aSopenharmony_ci unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width); 699cabdff1aSopenharmony_ci 700cabdff1aSopenharmony_ci sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count, 701cabdff1aSopenharmony_ci sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp, ctx->is_interlaced, is_top_field); 702cabdff1aSopenharmony_ci if (sl_size < 0){ 703cabdff1aSopenharmony_ci return sl_size; 704cabdff1aSopenharmony_ci } 705cabdff1aSopenharmony_ci 706cabdff1aSopenharmony_ci bytestream_put_be16(&sl_data_sizes, sl_size); 707cabdff1aSopenharmony_ci sl_data += sl_size; 708cabdff1aSopenharmony_ci sl_data_size -= sl_size; 709cabdff1aSopenharmony_ci mb_x += slice_mb_count; 710cabdff1aSopenharmony_ci } 711cabdff1aSopenharmony_ci } 712cabdff1aSopenharmony_ci 713cabdff1aSopenharmony_ci buf[0] = hdr_size << 3; 714cabdff1aSopenharmony_ci AV_WB32(buf + 1, sl_data - buf); 715cabdff1aSopenharmony_ci AV_WB16(buf + 5, slice_per_line * mb_height); /* picture size */ 716cabdff1aSopenharmony_ci buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4; /* number of slices */ 717cabdff1aSopenharmony_ci 718cabdff1aSopenharmony_ci return sl_data - buf; 719cabdff1aSopenharmony_ci} 720cabdff1aSopenharmony_ci 721cabdff1aSopenharmony_cistatic int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt, 722cabdff1aSopenharmony_ci const AVFrame *pict, int *got_packet) 723cabdff1aSopenharmony_ci{ 724cabdff1aSopenharmony_ci ProresContext *ctx = avctx->priv_data; 725cabdff1aSopenharmony_ci int header_size = 148; 726cabdff1aSopenharmony_ci uint8_t *buf; 727cabdff1aSopenharmony_ci int compress_frame_size, pic_size, ret, is_top_field_first = 0; 728cabdff1aSopenharmony_ci uint8_t frame_flags; 729cabdff1aSopenharmony_ci int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + AV_INPUT_BUFFER_MIN_SIZE; //FIXME choose tighter limit 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci 732cabdff1aSopenharmony_ci if ((ret = ff_alloc_packet(avctx, pkt, frame_size + AV_INPUT_BUFFER_MIN_SIZE)) < 0) 733cabdff1aSopenharmony_ci return ret; 734cabdff1aSopenharmony_ci 735cabdff1aSopenharmony_ci buf = pkt->data; 736cabdff1aSopenharmony_ci compress_frame_size = 8 + header_size; 737cabdff1aSopenharmony_ci 738cabdff1aSopenharmony_ci bytestream_put_be32(&buf, compress_frame_size);/* frame size will be update after picture(s) encoding */ 739cabdff1aSopenharmony_ci bytestream_put_buffer(&buf, "icpf", 4); 740cabdff1aSopenharmony_ci 741cabdff1aSopenharmony_ci bytestream_put_be16(&buf, header_size); 742cabdff1aSopenharmony_ci bytestream_put_be16(&buf, 0); /* version */ 743cabdff1aSopenharmony_ci bytestream_put_buffer(&buf, ctx->vendor, 4); 744cabdff1aSopenharmony_ci bytestream_put_be16(&buf, avctx->width); 745cabdff1aSopenharmony_ci bytestream_put_be16(&buf, avctx->height); 746cabdff1aSopenharmony_ci frame_flags = 0x82; /* 422 not interlaced */ 747cabdff1aSopenharmony_ci if (avctx->profile >= FF_PROFILE_PRORES_4444) /* 4444 or 4444 Xq */ 748cabdff1aSopenharmony_ci frame_flags |= 0x40; /* 444 chroma */ 749cabdff1aSopenharmony_ci if (ctx->is_interlaced) { 750cabdff1aSopenharmony_ci if (pict->top_field_first || !pict->interlaced_frame) { /* tff frame or progressive frame interpret as tff */ 751cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "use interlaced encoding, top field first\n"); 752cabdff1aSopenharmony_ci frame_flags |= 0x04; /* interlaced tff */ 753cabdff1aSopenharmony_ci is_top_field_first = 1; 754cabdff1aSopenharmony_ci } else { 755cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "use interlaced encoding, bottom field first\n"); 756cabdff1aSopenharmony_ci frame_flags |= 0x08; /* interlaced bff */ 757cabdff1aSopenharmony_ci } 758cabdff1aSopenharmony_ci } else { 759cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "use progressive encoding\n"); 760cabdff1aSopenharmony_ci } 761cabdff1aSopenharmony_ci *buf++ = frame_flags; 762cabdff1aSopenharmony_ci *buf++ = 0; /* reserved */ 763cabdff1aSopenharmony_ci /* only write color properties, if valid value. set to unspecified otherwise */ 764cabdff1aSopenharmony_ci *buf++ = ff_int_from_list_or_default(avctx, "frame color primaries", pict->color_primaries, valid_primaries, 0); 765cabdff1aSopenharmony_ci *buf++ = ff_int_from_list_or_default(avctx, "frame color trc", pict->color_trc, valid_trc, 0); 766cabdff1aSopenharmony_ci *buf++ = ff_int_from_list_or_default(avctx, "frame colorspace", pict->colorspace, valid_colorspace, 0); 767cabdff1aSopenharmony_ci if (avctx->profile >= FF_PROFILE_PRORES_4444) { 768cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) { 769cabdff1aSopenharmony_ci *buf++ = 0xA0;/* src b64a and no alpha */ 770cabdff1aSopenharmony_ci } else { 771cabdff1aSopenharmony_ci *buf++ = 0xA2;/* src b64a and 16b alpha */ 772cabdff1aSopenharmony_ci } 773cabdff1aSopenharmony_ci } else { 774cabdff1aSopenharmony_ci *buf++ = 32;/* src v210 and no alpha */ 775cabdff1aSopenharmony_ci } 776cabdff1aSopenharmony_ci *buf++ = 0; /* reserved */ 777cabdff1aSopenharmony_ci *buf++ = 3; /* luma and chroma matrix present */ 778cabdff1aSopenharmony_ci 779cabdff1aSopenharmony_ci bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile], 64); 780cabdff1aSopenharmony_ci bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64); 781cabdff1aSopenharmony_ci 782cabdff1aSopenharmony_ci pic_size = prores_encode_picture(avctx, pict, buf, 783cabdff1aSopenharmony_ci pkt->size - compress_frame_size, 0, is_top_field_first);/* encode progressive or first field */ 784cabdff1aSopenharmony_ci if (pic_size < 0) { 785cabdff1aSopenharmony_ci return pic_size; 786cabdff1aSopenharmony_ci } 787cabdff1aSopenharmony_ci compress_frame_size += pic_size; 788cabdff1aSopenharmony_ci 789cabdff1aSopenharmony_ci if (ctx->is_interlaced) { /* encode second field */ 790cabdff1aSopenharmony_ci pic_size = prores_encode_picture(avctx, pict, pkt->data + compress_frame_size, 791cabdff1aSopenharmony_ci pkt->size - compress_frame_size, 1, !is_top_field_first); 792cabdff1aSopenharmony_ci if (pic_size < 0) { 793cabdff1aSopenharmony_ci return pic_size; 794cabdff1aSopenharmony_ci } 795cabdff1aSopenharmony_ci compress_frame_size += pic_size; 796cabdff1aSopenharmony_ci } 797cabdff1aSopenharmony_ci 798cabdff1aSopenharmony_ci AV_WB32(pkt->data, compress_frame_size);/* update frame size */ 799cabdff1aSopenharmony_ci pkt->size = compress_frame_size; 800cabdff1aSopenharmony_ci *got_packet = 1; 801cabdff1aSopenharmony_ci 802cabdff1aSopenharmony_ci return 0; 803cabdff1aSopenharmony_ci} 804cabdff1aSopenharmony_ci 805cabdff1aSopenharmony_cistatic void scale_mat(const uint8_t* src, int* dst, int scale) 806cabdff1aSopenharmony_ci{ 807cabdff1aSopenharmony_ci int i; 808cabdff1aSopenharmony_ci for (i = 0; i < 64; i++) 809cabdff1aSopenharmony_ci dst[i] = src[i] * scale; 810cabdff1aSopenharmony_ci} 811cabdff1aSopenharmony_ci 812cabdff1aSopenharmony_cistatic av_cold int prores_encode_init(AVCodecContext *avctx) 813cabdff1aSopenharmony_ci{ 814cabdff1aSopenharmony_ci int i; 815cabdff1aSopenharmony_ci ProresContext* ctx = avctx->priv_data; 816cabdff1aSopenharmony_ci 817cabdff1aSopenharmony_ci avctx->bits_per_raw_sample = 10; 818cabdff1aSopenharmony_ci ctx->need_alpha = 0; 819cabdff1aSopenharmony_ci ctx->is_interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT); 820cabdff1aSopenharmony_ci if (ctx->is_interlaced) { 821cabdff1aSopenharmony_ci ctx->scantable = ff_prores_interlaced_scan; 822cabdff1aSopenharmony_ci } else { 823cabdff1aSopenharmony_ci ctx->scantable = ff_prores_progressive_scan; 824cabdff1aSopenharmony_ci } 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci if (avctx->width & 0x1) { 827cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 828cabdff1aSopenharmony_ci "frame width needs to be multiple of 2\n"); 829cabdff1aSopenharmony_ci return AVERROR(EINVAL); 830cabdff1aSopenharmony_ci } 831cabdff1aSopenharmony_ci 832cabdff1aSopenharmony_ci if (avctx->width > 65534 || avctx->height > 65535) { 833cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 834cabdff1aSopenharmony_ci "The maximum dimensions are 65534x65535\n"); 835cabdff1aSopenharmony_ci return AVERROR(EINVAL); 836cabdff1aSopenharmony_ci } 837cabdff1aSopenharmony_ci 838cabdff1aSopenharmony_ci if (strlen(ctx->vendor) != 4) { 839cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n"); 840cabdff1aSopenharmony_ci return AVERROR(EINVAL); 841cabdff1aSopenharmony_ci } 842cabdff1aSopenharmony_ci 843cabdff1aSopenharmony_ci if (avctx->profile == FF_PROFILE_UNKNOWN) { 844cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) { 845cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_PRORES_STANDARD; 846cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, 847cabdff1aSopenharmony_ci "encoding with ProRes standard (apcn) profile\n"); 848cabdff1aSopenharmony_ci } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) { 849cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_PRORES_4444; 850cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, 851cabdff1aSopenharmony_ci "encoding with ProRes 4444 (ap4h) profile\n"); 852cabdff1aSopenharmony_ci } else if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) { 853cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_PRORES_4444; 854cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, 855cabdff1aSopenharmony_ci "encoding with ProRes 4444+ (ap4h) profile\n"); 856cabdff1aSopenharmony_ci } 857cabdff1aSopenharmony_ci } else if (avctx->profile < FF_PROFILE_PRORES_PROXY 858cabdff1aSopenharmony_ci || avctx->profile > FF_PROFILE_PRORES_XQ) { 859cabdff1aSopenharmony_ci av_log( 860cabdff1aSopenharmony_ci avctx, 861cabdff1aSopenharmony_ci AV_LOG_ERROR, 862cabdff1aSopenharmony_ci "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch, 4 - ap4h, 5 - ap4x]\n", 863cabdff1aSopenharmony_ci avctx->profile); 864cabdff1aSopenharmony_ci return AVERROR(EINVAL); 865cabdff1aSopenharmony_ci } else if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P10) && (avctx->profile > FF_PROFILE_PRORES_HQ)){ 866cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 867cabdff1aSopenharmony_ci "encoding with ProRes 444/Xq (ap4h/ap4x) profile, need YUV444P10 input\n"); 868cabdff1aSopenharmony_ci return AVERROR(EINVAL); 869cabdff1aSopenharmony_ci } else if ((avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) 870cabdff1aSopenharmony_ci && (avctx->profile < FF_PROFILE_PRORES_4444)){ 871cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 872cabdff1aSopenharmony_ci "encoding with ProRes Proxy/LT/422/422 HQ (apco, apcs, apcn, ap4h) profile, need YUV422P10 input\n"); 873cabdff1aSopenharmony_ci return AVERROR(EINVAL); 874cabdff1aSopenharmony_ci } 875cabdff1aSopenharmony_ci 876cabdff1aSopenharmony_ci if (avctx->profile < FF_PROFILE_PRORES_4444) { /* 422 versions */ 877cabdff1aSopenharmony_ci ctx->is_422 = 1; 878cabdff1aSopenharmony_ci if ((avctx->height & 0xf) || (avctx->width & 0xf)) { 879cabdff1aSopenharmony_ci ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8)); 880cabdff1aSopenharmony_ci if (!ctx->fill_y) 881cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 882cabdff1aSopenharmony_ci ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9); 883cabdff1aSopenharmony_ci ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8); 884cabdff1aSopenharmony_ci } 885cabdff1aSopenharmony_ci } else { /* 444 */ 886cabdff1aSopenharmony_ci ctx->is_422 = 0; 887cabdff1aSopenharmony_ci if ((avctx->height & 0xf) || (avctx->width & 0xf)) { 888cabdff1aSopenharmony_ci ctx->fill_y = av_malloc(3 * (DEFAULT_SLICE_MB_WIDTH << 9)); 889cabdff1aSopenharmony_ci if (!ctx->fill_y) 890cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 891cabdff1aSopenharmony_ci ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9); 892cabdff1aSopenharmony_ci ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 9); 893cabdff1aSopenharmony_ci } 894cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) { 895cabdff1aSopenharmony_ci ctx->need_alpha = 1; 896cabdff1aSopenharmony_ci ctx->fill_a = av_malloc(DEFAULT_SLICE_MB_WIDTH << 9); /* 8 blocks x 16px x 16px x sizeof (uint16) */ 897cabdff1aSopenharmony_ci if (!ctx->fill_a) 898cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 899cabdff1aSopenharmony_ci } 900cabdff1aSopenharmony_ci } 901cabdff1aSopenharmony_ci 902cabdff1aSopenharmony_ci ff_fdctdsp_init(&ctx->fdsp, avctx); 903cabdff1aSopenharmony_ci 904cabdff1aSopenharmony_ci avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name); 905cabdff1aSopenharmony_ci 906cabdff1aSopenharmony_ci for (i = 1; i <= 16; i++) { 907cabdff1aSopenharmony_ci scale_mat(QMAT_LUMA[avctx->profile] , ctx->qmat_luma[i - 1] , i); 908cabdff1aSopenharmony_ci scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i); 909cabdff1aSopenharmony_ci } 910cabdff1aSopenharmony_ci 911cabdff1aSopenharmony_ci return 0; 912cabdff1aSopenharmony_ci} 913cabdff1aSopenharmony_ci 914cabdff1aSopenharmony_cistatic av_cold int prores_encode_close(AVCodecContext *avctx) 915cabdff1aSopenharmony_ci{ 916cabdff1aSopenharmony_ci ProresContext* ctx = avctx->priv_data; 917cabdff1aSopenharmony_ci av_freep(&ctx->fill_y); 918cabdff1aSopenharmony_ci av_freep(&ctx->fill_a); 919cabdff1aSopenharmony_ci 920cabdff1aSopenharmony_ci return 0; 921cabdff1aSopenharmony_ci} 922cabdff1aSopenharmony_ci 923cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(ProresContext, x) 924cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 925cabdff1aSopenharmony_ci 926cabdff1aSopenharmony_cistatic const AVOption options[] = { 927cabdff1aSopenharmony_ci { "vendor", "vendor ID", OFFSET(vendor), AV_OPT_TYPE_STRING, { .str = "fmpg" }, 0, 0, VE }, 928cabdff1aSopenharmony_ci { NULL } 929cabdff1aSopenharmony_ci}; 930cabdff1aSopenharmony_ci 931cabdff1aSopenharmony_cistatic const AVClass prores_enc_class = { 932cabdff1aSopenharmony_ci .class_name = "ProRes encoder", 933cabdff1aSopenharmony_ci .item_name = av_default_item_name, 934cabdff1aSopenharmony_ci .option = options, 935cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 936cabdff1aSopenharmony_ci}; 937cabdff1aSopenharmony_ci 938cabdff1aSopenharmony_cistatic const enum AVPixelFormat pix_fmts[] = { 939cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, 940cabdff1aSopenharmony_ci AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE 941cabdff1aSopenharmony_ci}; 942cabdff1aSopenharmony_ci 943cabdff1aSopenharmony_ciconst FFCodec ff_prores_aw_encoder = { 944cabdff1aSopenharmony_ci .p.name = "prores_aw", 945cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), 946cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 947cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_PRORES, 948cabdff1aSopenharmony_ci .p.pix_fmts = pix_fmts, 949cabdff1aSopenharmony_ci .priv_data_size = sizeof(ProresContext), 950cabdff1aSopenharmony_ci .init = prores_encode_init, 951cabdff1aSopenharmony_ci .close = prores_encode_close, 952cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(prores_encode_frame), 953cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, 954cabdff1aSopenharmony_ci .p.priv_class = &prores_enc_class, 955cabdff1aSopenharmony_ci .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), 956cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 957cabdff1aSopenharmony_ci}; 958cabdff1aSopenharmony_ci 959cabdff1aSopenharmony_ciconst FFCodec ff_prores_encoder = { 960cabdff1aSopenharmony_ci .p.name = "prores", 961cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), 962cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 963cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_PRORES, 964cabdff1aSopenharmony_ci .p.pix_fmts = pix_fmts, 965cabdff1aSopenharmony_ci .priv_data_size = sizeof(ProresContext), 966cabdff1aSopenharmony_ci .init = prores_encode_init, 967cabdff1aSopenharmony_ci .close = prores_encode_close, 968cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(prores_encode_frame), 969cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, 970cabdff1aSopenharmony_ci .p.priv_class = &prores_enc_class, 971cabdff1aSopenharmony_ci .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), 972cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 973cabdff1aSopenharmony_ci}; 974