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