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