/src/ffmpeg/libavcodec/magicyuvenc.c
Line | Count | Source |
1 | | /* |
2 | | * MagicYUV encoder |
3 | | * Copyright (c) 2017 Paul B Mahol |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | |
25 | | #include "libavutil/cpu.h" |
26 | | #include "libavutil/mem.h" |
27 | | #include "libavutil/opt.h" |
28 | | #include "libavutil/pixdesc.h" |
29 | | #include "libavutil/qsort.h" |
30 | | |
31 | | #include "avcodec.h" |
32 | | #include "bytestream.h" |
33 | | #include "codec_internal.h" |
34 | | #include "encode.h" |
35 | | #include "put_bits.h" |
36 | | #include "lossless_videoencdsp.h" |
37 | | |
38 | 786 | #define MAGICYUV_EXTRADATA_SIZE 32 |
39 | | |
40 | | typedef enum Prediction { |
41 | | LEFT = 1, |
42 | | GRADIENT, |
43 | | MEDIAN, |
44 | | } Prediction; |
45 | | |
46 | | typedef struct HuffEntry { |
47 | | uint8_t len; |
48 | | uint32_t code; |
49 | | } HuffEntry; |
50 | | |
51 | | typedef struct PTable { |
52 | | int value; ///< input value |
53 | | int64_t prob; ///< number of occurrences of this value in input |
54 | | } PTable; |
55 | | |
56 | | typedef struct Slice { |
57 | | int width; |
58 | | int height; |
59 | | int encode_raw; |
60 | | unsigned pos; |
61 | | unsigned size; |
62 | | uint8_t *slice; |
63 | | uint8_t *dst; |
64 | | int64_t counts[256]; |
65 | | } Slice; |
66 | | |
67 | | typedef struct MagicYUVContext { |
68 | | const AVClass *class; |
69 | | int frame_pred; |
70 | | int planes; |
71 | | uint8_t format; |
72 | | int slice_height; |
73 | | int nb_slices; |
74 | | int correlate; |
75 | | int hshift[4]; |
76 | | int vshift[4]; |
77 | | uint8_t *decorrelate_buf[2]; |
78 | | Slice *slices; |
79 | | HuffEntry he[4][256]; |
80 | | LLVidEncDSPContext llvidencdsp; |
81 | | void (*predict)(struct MagicYUVContext *s, const uint8_t *src, uint8_t *dst, |
82 | | ptrdiff_t stride, int width, int height); |
83 | | } MagicYUVContext; |
84 | | |
85 | | static void left_predict(MagicYUVContext *s, |
86 | | const uint8_t *src, uint8_t *dst, ptrdiff_t stride, |
87 | | int width, int height) |
88 | 13.8k | { |
89 | 13.8k | uint8_t prev = 0; |
90 | 13.8k | int i, j; |
91 | | |
92 | 10.7M | for (i = 0; i < width; i++) { |
93 | 10.7M | dst[i] = src[i] - prev; |
94 | 10.7M | prev = src[i]; |
95 | 10.7M | } |
96 | 13.8k | dst += width; |
97 | 13.8k | src += stride; |
98 | 5.05M | for (j = 1; j < height; j++) { |
99 | 5.03M | prev = src[-stride]; |
100 | 59.3M | for (i = 0; i < width; i++) { |
101 | 54.3M | dst[i] = src[i] - prev; |
102 | 54.3M | prev = src[i]; |
103 | 54.3M | } |
104 | 5.03M | dst += width; |
105 | 5.03M | src += stride; |
106 | 5.03M | } |
107 | 13.8k | } |
108 | | |
109 | | static void gradient_predict(MagicYUVContext *s, |
110 | | const uint8_t *src, uint8_t *dst, ptrdiff_t stride, |
111 | | int width, int height) |
112 | 0 | { |
113 | 0 | int left = 0, top, lefttop; |
114 | 0 | int i, j; |
115 | |
|
116 | 0 | for (i = 0; i < width; i++) { |
117 | 0 | dst[i] = src[i] - left; |
118 | 0 | left = src[i]; |
119 | 0 | } |
120 | 0 | dst += width; |
121 | 0 | src += stride; |
122 | 0 | for (j = 1; j < height; j++) { |
123 | 0 | top = src[-stride]; |
124 | 0 | left = src[0] - top; |
125 | 0 | dst[0] = left; |
126 | 0 | for (i = 1; i < width; i++) { |
127 | 0 | top = src[i - stride]; |
128 | 0 | lefttop = src[i - (stride + 1)]; |
129 | 0 | left = src[i-1]; |
130 | 0 | dst[i] = (src[i] - top) - left + lefttop; |
131 | 0 | } |
132 | 0 | dst += width; |
133 | 0 | src += stride; |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | | static void median_predict(MagicYUVContext *s, |
138 | | const uint8_t *src, uint8_t *dst, ptrdiff_t stride, |
139 | | int width, int height) |
140 | 0 | { |
141 | 0 | int left = 0, lefttop; |
142 | 0 | int i, j; |
143 | |
|
144 | 0 | for (i = 0; i < width; i++) { |
145 | 0 | dst[i] = src[i] - left; |
146 | 0 | left = src[i]; |
147 | 0 | } |
148 | 0 | dst += width; |
149 | 0 | src += stride; |
150 | 0 | for (j = 1; j < height; j++) { |
151 | 0 | left = lefttop = src[-stride]; |
152 | 0 | s->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &left, &lefttop); |
153 | 0 | dst += width; |
154 | 0 | src += stride; |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | | static av_cold int magy_encode_init(AVCodecContext *avctx) |
159 | 393 | { |
160 | 393 | MagicYUVContext *s = avctx->priv_data; |
161 | 393 | PutByteContext pb; |
162 | | |
163 | 393 | switch (avctx->pix_fmt) { |
164 | 107 | case AV_PIX_FMT_GBRP: |
165 | 107 | avctx->codec_tag = MKTAG('M', '8', 'R', 'G'); |
166 | 107 | s->correlate = 1; |
167 | 107 | s->format = 0x65; |
168 | 107 | break; |
169 | 59 | case AV_PIX_FMT_GBRAP: |
170 | 59 | avctx->codec_tag = MKTAG('M', '8', 'R', 'A'); |
171 | 59 | s->correlate = 1; |
172 | 59 | s->format = 0x66; |
173 | 59 | break; |
174 | 55 | case AV_PIX_FMT_YUV420P: |
175 | 55 | avctx->codec_tag = MKTAG('M', '8', 'Y', '0'); |
176 | 55 | s->hshift[1] = |
177 | 55 | s->vshift[1] = |
178 | 55 | s->hshift[2] = |
179 | 55 | s->vshift[2] = 1; |
180 | 55 | s->format = 0x69; |
181 | 55 | break; |
182 | 39 | case AV_PIX_FMT_YUV422P: |
183 | 39 | avctx->codec_tag = MKTAG('M', '8', 'Y', '2'); |
184 | 39 | s->hshift[1] = |
185 | 39 | s->hshift[2] = 1; |
186 | 39 | s->format = 0x68; |
187 | 39 | break; |
188 | 6 | case AV_PIX_FMT_YUV444P: |
189 | 6 | avctx->codec_tag = MKTAG('M', '8', 'Y', '4'); |
190 | 6 | s->format = 0x67; |
191 | 6 | break; |
192 | 10 | case AV_PIX_FMT_YUVA444P: |
193 | 10 | avctx->codec_tag = MKTAG('M', '8', 'Y', 'A'); |
194 | 10 | s->format = 0x6a; |
195 | 10 | break; |
196 | 117 | case AV_PIX_FMT_GRAY8: |
197 | 117 | avctx->codec_tag = MKTAG('M', '8', 'G', '0'); |
198 | 117 | s->format = 0x6b; |
199 | 117 | break; |
200 | 393 | } |
201 | | |
202 | 393 | ff_llvidencdsp_init(&s->llvidencdsp); |
203 | | |
204 | 393 | s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); |
205 | | |
206 | 393 | s->nb_slices = avctx->slices > 0 ? avctx->slices : avctx->thread_count; |
207 | 393 | s->nb_slices = FFMIN(s->nb_slices, avctx->height >> s->vshift[1]); |
208 | 393 | s->nb_slices = FFMAX(1, s->nb_slices); |
209 | 393 | s->slice_height = FFALIGN((avctx->height + s->nb_slices - 1) / s->nb_slices, 1 << s->vshift[1]); |
210 | 393 | s->nb_slices = (avctx->height + s->slice_height - 1) / s->slice_height; |
211 | 393 | s->nb_slices = FFMIN(256U / s->planes, s->nb_slices); |
212 | 393 | s->slices = av_calloc(s->nb_slices * s->planes, sizeof(*s->slices)); |
213 | 393 | if (!s->slices) |
214 | 0 | return AVERROR(ENOMEM); |
215 | | |
216 | 393 | if (s->correlate) { |
217 | 166 | size_t max_align = av_cpu_max_align(); |
218 | 166 | size_t aligned_width = FFALIGN(avctx->width, max_align); |
219 | 166 | s->decorrelate_buf[0] = av_calloc(2U * (s->nb_slices * s->slice_height), |
220 | 166 | aligned_width); |
221 | 166 | if (!s->decorrelate_buf[0]) |
222 | 0 | return AVERROR(ENOMEM); |
223 | 166 | s->decorrelate_buf[1] = s->decorrelate_buf[0] + (s->nb_slices * s->slice_height) * aligned_width; |
224 | 166 | } |
225 | | |
226 | 786 | for (int n = 0; n < s->nb_slices; n++) { |
227 | 1.40k | for (int i = 0; i < s->planes; i++) { |
228 | 1.01k | Slice *sl = &s->slices[n * s->planes + i]; |
229 | | |
230 | 1.01k | sl->height = n == s->nb_slices - 1 ? avctx->height - n * s->slice_height : s->slice_height; |
231 | 1.01k | sl->height = AV_CEIL_RSHIFT(sl->height, s->vshift[i]); |
232 | 1.01k | sl->width = AV_CEIL_RSHIFT(avctx->width, s->hshift[i]); |
233 | | |
234 | 1.01k | sl->slice = av_malloc(avctx->width * (s->slice_height + 2) + |
235 | 1.01k | AV_INPUT_BUFFER_PADDING_SIZE); |
236 | 1.01k | if (!sl->slice) |
237 | 0 | return AVERROR(ENOMEM); |
238 | 1.01k | } |
239 | 393 | } |
240 | | |
241 | 393 | switch (s->frame_pred) { |
242 | 393 | case LEFT: s->predict = left_predict; break; |
243 | 0 | case GRADIENT: s->predict = gradient_predict; break; |
244 | 0 | case MEDIAN: s->predict = median_predict; break; |
245 | 393 | } |
246 | | |
247 | 393 | avctx->extradata_size = MAGICYUV_EXTRADATA_SIZE; |
248 | | |
249 | 393 | avctx->extradata = av_mallocz(avctx->extradata_size + |
250 | 393 | AV_INPUT_BUFFER_PADDING_SIZE); |
251 | 393 | if (!avctx->extradata) |
252 | 0 | return AVERROR(ENOMEM); |
253 | | |
254 | 393 | bytestream2_init_writer(&pb, avctx->extradata, MAGICYUV_EXTRADATA_SIZE); |
255 | 393 | bytestream2_put_le32u(&pb, MKTAG('M', 'A', 'G', 'Y')); |
256 | 393 | bytestream2_put_le32u(&pb, 32); |
257 | 393 | bytestream2_put_byteu(&pb, 7); |
258 | 393 | bytestream2_put_byteu(&pb, s->format); |
259 | 393 | bytestream2_put_byteu(&pb, 12); |
260 | 393 | bytestream2_put_byteu(&pb, 0); |
261 | | |
262 | 393 | bytestream2_put_byteu(&pb, 0); |
263 | 393 | bytestream2_put_byteu(&pb, 0); |
264 | 393 | bytestream2_put_byteu(&pb, 32); |
265 | 393 | bytestream2_put_byteu(&pb, 0); |
266 | | |
267 | 393 | bytestream2_put_le32u(&pb, avctx->width); |
268 | 393 | bytestream2_put_le32u(&pb, avctx->height); |
269 | 393 | bytestream2_put_le32u(&pb, avctx->width); |
270 | 393 | bytestream2_put_le32u(&pb, avctx->height); |
271 | | |
272 | 393 | return 0; |
273 | 393 | } |
274 | | |
275 | | static void calculate_codes(HuffEntry *he, uint16_t codes_count[33]) |
276 | 13.8k | { |
277 | 457k | for (unsigned i = 32, nb_codes = 0; i > 0; i--) { |
278 | 443k | uint16_t curr = codes_count[i]; // # of leafs of length i |
279 | 443k | codes_count[i] = nb_codes / 2; // # of non-leaf nodes on level i |
280 | 443k | nb_codes = codes_count[i] + curr; // # of nodes on level i |
281 | 443k | } |
282 | | |
283 | 3.56M | for (unsigned i = 0; i < 256; i++) { |
284 | 3.54M | he[i].code = codes_count[he[i].len]; |
285 | 3.54M | codes_count[he[i].len]++; |
286 | 3.54M | } |
287 | 13.8k | } |
288 | | |
289 | | static void count_usage(const uint8_t *src, int width, |
290 | | int height, int64_t *counts) |
291 | 13.8k | { |
292 | 5.06M | for (int j = 0; j < height; j++) { |
293 | 70.1M | for (int i = 0; i < width; i++) |
294 | 65.0M | counts[src[i]]++; |
295 | 5.05M | src += width; |
296 | 5.05M | } |
297 | 13.8k | } |
298 | | |
299 | | typedef struct PackageMergerList { |
300 | | int nitems; ///< number of items in the list and probability ex. 4 |
301 | | int item_idx[515]; ///< index range for each item in items 0, 2, 5, 9, 13 |
302 | | int probability[514]; ///< probability of each item 3, 8, 18, 46 |
303 | | int items[257 * 16]; ///< chain of all individual values that make up items A, B, A, B, C, A, B, C, D, C, D, D, E |
304 | | } PackageMergerList; |
305 | | |
306 | | static int compare_by_prob(const void *a, const void *b) |
307 | 15.5M | { |
308 | 15.5M | const PTable *a2 = a; |
309 | 15.5M | const PTable *b2 = b; |
310 | 15.5M | return a2->prob - b2->prob; |
311 | 15.5M | } |
312 | | |
313 | | static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts, |
314 | | uint16_t codes_counts[33], |
315 | | int size, int max_length) |
316 | 13.8k | { |
317 | 13.8k | PackageMergerList list_a, list_b, *to = &list_a, *from = &list_b, *temp; |
318 | 13.8k | int times, i, j, k; |
319 | 13.8k | int nbits[257] = {0}; |
320 | 13.8k | int min; |
321 | | |
322 | 13.8k | av_assert0(max_length > 0); |
323 | | |
324 | 13.8k | to->nitems = 0; |
325 | 13.8k | from->nitems = 0; |
326 | 13.8k | to->item_idx[0] = 0; |
327 | 13.8k | from->item_idx[0] = 0; |
328 | 13.8k | AV_QSORT(prob_table, size, PTable, compare_by_prob); |
329 | | |
330 | 194k | for (times = 0; times <= max_length; times++) { |
331 | 180k | to->nitems = 0; |
332 | 180k | to->item_idx[0] = 0; |
333 | | |
334 | 180k | j = 0; |
335 | 180k | k = 0; |
336 | | |
337 | 180k | if (times < max_length) { |
338 | 166k | i = 0; |
339 | 166k | } |
340 | 81.7M | while (i < size || j + 1 < from->nitems) { |
341 | 81.5M | to->nitems++; |
342 | 81.5M | to->item_idx[to->nitems] = to->item_idx[to->nitems - 1]; |
343 | 81.5M | if (i < size && |
344 | 65.4M | (j + 1 >= from->nitems || |
345 | 61.8M | prob_table[i].prob < |
346 | 61.8M | from->probability[j] + from->probability[j + 1])) { |
347 | 42.5M | to->items[to->item_idx[to->nitems]++] = prob_table[i].value; |
348 | 42.5M | to->probability[to->nitems - 1] = prob_table[i].prob; |
349 | 42.5M | i++; |
350 | 42.5M | } else { |
351 | 282M | for (k = from->item_idx[j]; k < from->item_idx[j + 2]; k++) { |
352 | 243M | to->items[to->item_idx[to->nitems]++] = from->items[k]; |
353 | 243M | } |
354 | 38.9M | to->probability[to->nitems - 1] = |
355 | 38.9M | from->probability[j] + from->probability[j + 1]; |
356 | 38.9M | j += 2; |
357 | 38.9M | } |
358 | 81.5M | } |
359 | 180k | temp = to; |
360 | 180k | to = from; |
361 | 180k | from = temp; |
362 | 180k | } |
363 | | |
364 | 13.8k | min = (size - 1 < from->nitems) ? size - 1 : from->nitems; |
365 | 28.9M | for (i = 0; i < from->item_idx[min]; i++) { |
366 | 28.9M | nbits[from->items[i]]++; |
367 | 28.9M | } |
368 | | |
369 | 3.56M | for (i = 0; i < size; i++) { |
370 | 3.54M | distincts[i].len = nbits[i]; |
371 | 3.54M | codes_counts[nbits[i]]++; |
372 | 3.54M | } |
373 | 13.8k | } |
374 | | |
375 | | static int count_plane_slice(AVCodecContext *avctx, int n, int plane) |
376 | 13.8k | { |
377 | 13.8k | MagicYUVContext *s = avctx->priv_data; |
378 | 13.8k | Slice *sl = &s->slices[n * s->planes + plane]; |
379 | 13.8k | const uint8_t *dst = sl->slice; |
380 | 13.8k | int64_t *counts = sl->counts; |
381 | | |
382 | 13.8k | memset(counts, 0, sizeof(sl->counts)); |
383 | | |
384 | 13.8k | count_usage(dst, sl->width, sl->height, counts); |
385 | | |
386 | 13.8k | return 0; |
387 | 13.8k | } |
388 | | |
389 | | static void generate_codes(AVCodecContext *avctx, |
390 | | HuffEntry *he, int plane) |
391 | 13.8k | { |
392 | 13.8k | MagicYUVContext *s = avctx->priv_data; |
393 | 13.8k | PTable counts[256]; |
394 | 13.8k | uint16_t codes_counts[33] = { 0 }; |
395 | | |
396 | 3.56M | for (size_t i = 0; i < FF_ARRAY_ELEMS(counts); i++) { |
397 | 3.54M | counts[i].prob = 1; |
398 | 3.54M | counts[i].value = i; |
399 | 3.54M | } |
400 | | |
401 | 27.7k | for (int n = 0; n < s->nb_slices; n++) { |
402 | 13.8k | Slice *sl = &s->slices[n * s->planes + plane]; |
403 | 13.8k | int64_t *slice_counts = sl->counts; |
404 | | |
405 | 3.56M | for (int i = 0; i < 256; i++) |
406 | 3.54M | counts[i].prob += slice_counts[i]; |
407 | 13.8k | } |
408 | | |
409 | 13.8k | magy_huffman_compute_bits(counts, he, codes_counts, 256, 12); |
410 | | |
411 | 13.8k | calculate_codes(he, codes_counts); |
412 | 13.8k | } |
413 | | |
414 | | static void output_codes(PutByteContext *pb, const HuffEntry he[256]) |
415 | 13.8k | { |
416 | 3.56M | for (int i = 0; i < 256; i++) { |
417 | | // The seven low bits are len; the top bit means the run of |
418 | | // codes of this length has length one. |
419 | 3.54M | bytestream2_put_byteu(pb, he[i].len); |
420 | 3.54M | } |
421 | 13.8k | } |
422 | | |
423 | | static void encode_plane_slice_raw(const uint8_t *src, uint8_t *dst, |
424 | | int width, int height, int prediction) |
425 | 8.30k | { |
426 | 8.30k | unsigned count = width * height; |
427 | | |
428 | 8.30k | dst[0] = 1; |
429 | 8.30k | dst[1] = prediction; |
430 | | |
431 | 8.30k | memcpy(dst + 2, src, count); |
432 | 8.30k | } |
433 | | |
434 | | static void encode_plane_slice(const uint8_t *src, uint8_t *dst, unsigned dst_size, |
435 | | int width, int height, HuffEntry *he, int prediction) |
436 | 5.56k | { |
437 | 5.56k | PutBitContext pb; |
438 | | |
439 | 5.56k | init_put_bits(&pb, dst, dst_size); |
440 | | |
441 | 5.56k | put_bits(&pb, 8, 0); |
442 | 5.56k | put_bits(&pb, 8, prediction); |
443 | | |
444 | 5.03M | for (int j = 0; j < height; j++) { |
445 | 69.9M | for (int i = 0; i < width; i++) { |
446 | 64.9M | const int idx = src[i]; |
447 | 64.9M | const int len = he[idx].len; |
448 | 64.9M | put_bits(&pb, len, he[idx].code); |
449 | 64.9M | } |
450 | | |
451 | 5.02M | src += width; |
452 | 5.02M | } |
453 | | |
454 | 5.56k | flush_put_bits(&pb); |
455 | 5.56k | av_assert1(put_bytes_left(&pb, 0) <= 3); |
456 | 5.56k | } |
457 | | |
458 | | static int encode_slice(AVCodecContext *avctx, void *tdata, |
459 | | int n, int threadnr) |
460 | 9.35k | { |
461 | 9.35k | MagicYUVContext *s = avctx->priv_data; |
462 | | |
463 | 23.2k | for (int i = 0; i < s->planes; i++) { |
464 | 13.8k | Slice *sl = &s->slices[n * s->planes + i]; |
465 | | |
466 | | // Zero the padding now |
467 | 13.8k | AV_WN32(sl->dst + sl->size - 4, 0); |
468 | | |
469 | 13.8k | if (sl->encode_raw) |
470 | 8.30k | encode_plane_slice_raw(sl->slice, sl->dst, |
471 | 8.30k | sl->width, sl->height, s->frame_pred); |
472 | 5.56k | else |
473 | 5.56k | encode_plane_slice(sl->slice, |
474 | 5.56k | sl->dst, |
475 | 5.56k | sl->size, |
476 | 5.56k | sl->width, sl->height, |
477 | 5.56k | s->he[i], s->frame_pred); |
478 | 13.8k | } |
479 | | |
480 | 9.35k | return 0; |
481 | 9.35k | } |
482 | | |
483 | | static int predict_slice(AVCodecContext *avctx, void *tdata, |
484 | | int n, int threadnr) |
485 | 9.35k | { |
486 | 9.35k | size_t max_align = av_cpu_max_align(); |
487 | 9.35k | const int aligned_width = FFALIGN(avctx->width, max_align); |
488 | 9.35k | MagicYUVContext *s = avctx->priv_data; |
489 | 9.35k | const int slice_height = s->slice_height; |
490 | 9.35k | const int last_height = FFMIN(slice_height, avctx->height - n * slice_height); |
491 | 9.35k | const int height = (n < (s->nb_slices - 1)) ? slice_height : last_height; |
492 | 9.35k | const int width = avctx->width; |
493 | 9.35k | AVFrame *frame = tdata; |
494 | | |
495 | 9.35k | if (s->correlate) { |
496 | 849 | uint8_t *decorrelated[2] = { s->decorrelate_buf[0] + n * slice_height * aligned_width, |
497 | 849 | s->decorrelate_buf[1] + n * slice_height * aligned_width }; |
498 | 849 | const int decorrelate_linesize = aligned_width; |
499 | 849 | const uint8_t *const data[4] = { decorrelated[0], frame->data[0] + n * slice_height * frame->linesize[0], |
500 | 849 | decorrelated[1], s->planes == 4 ? frame->data[3] + n * slice_height * frame->linesize[3] : NULL }; |
501 | 849 | const uint8_t *r, *g, *b; |
502 | 849 | const int linesize[4] = { decorrelate_linesize, frame->linesize[0], |
503 | 849 | decorrelate_linesize, frame->linesize[3] }; |
504 | | |
505 | 849 | g = frame->data[0] + n * slice_height * frame->linesize[0]; |
506 | 849 | b = frame->data[1] + n * slice_height * frame->linesize[1]; |
507 | 849 | r = frame->data[2] + n * slice_height * frame->linesize[2]; |
508 | | |
509 | 1.04M | for (int i = 0; i < height; i++) { |
510 | 1.04M | s->llvidencdsp.diff_bytes(decorrelated[0], b, g, width); |
511 | 1.04M | s->llvidencdsp.diff_bytes(decorrelated[1], r, g, width); |
512 | 1.04M | g += frame->linesize[0]; |
513 | 1.04M | b += frame->linesize[1]; |
514 | 1.04M | r += frame->linesize[2]; |
515 | 1.04M | decorrelated[0] += decorrelate_linesize; |
516 | 1.04M | decorrelated[1] += decorrelate_linesize; |
517 | 1.04M | } |
518 | | |
519 | 3.93k | for (int i = 0; i < s->planes; i++) { |
520 | 3.08k | Slice *sl = &s->slices[n * s->planes + i]; |
521 | | |
522 | 3.08k | s->predict(s, data[i], sl->slice, linesize[i], |
523 | 3.08k | frame->width, height); |
524 | 3.08k | } |
525 | 8.51k | } else { |
526 | 19.2k | for (int i = 0; i < s->planes; i++) { |
527 | 10.7k | Slice *sl = &s->slices[n * s->planes + i]; |
528 | | |
529 | 10.7k | s->predict(s, frame->data[i] + n * (slice_height >> s->vshift[i]) * frame->linesize[i], |
530 | 10.7k | sl->slice, |
531 | 10.7k | frame->linesize[i], |
532 | 10.7k | sl->width, sl->height); |
533 | 10.7k | } |
534 | 8.51k | } |
535 | | |
536 | 23.2k | for (int p = 0; p < s->planes; p++) |
537 | 13.8k | count_plane_slice(avctx, n, p); |
538 | | |
539 | 9.35k | return 0; |
540 | 9.35k | } |
541 | | |
542 | | static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
543 | | const AVFrame *frame, int *got_packet) |
544 | 9.35k | { |
545 | 9.35k | MagicYUVContext *s = avctx->priv_data; |
546 | 9.35k | PutByteContext pb; |
547 | 9.35k | int header_size = 32 + (4 + 1) * (s->planes * s->nb_slices + 1) |
548 | 9.35k | + 256 * s->planes /* Hufftables */; |
549 | 9.35k | int64_t pkt_size = header_size; |
550 | 9.35k | int ret; |
551 | | |
552 | 9.35k | avctx->execute2(avctx, predict_slice, (void *)frame, NULL, s->nb_slices); |
553 | | |
554 | 23.2k | for (int i = 0; i < s->planes; i++) |
555 | 13.8k | generate_codes(avctx, s->he[i], i); |
556 | | |
557 | 18.7k | for (int i = 0; i < s->nb_slices; ++i) { |
558 | 23.2k | for (int j = 0; j < s->planes; ++j) { |
559 | 13.8k | Slice *const sl = &s->slices[i * s->planes + j]; |
560 | 13.8k | int64_t size = 0; |
561 | | |
562 | 3.56M | for (size_t k = 0; k < FF_ARRAY_ELEMS(sl->counts); ++k) |
563 | 3.54M | size += sl->counts[k] * s->he[j][k].len; |
564 | 13.8k | size = AV_CEIL_RSHIFT(size, 3); |
565 | 13.8k | sl->encode_raw = size >= sl->width * sl->height; |
566 | 13.8k | if (sl->encode_raw) |
567 | 8.30k | size = sl->width * sl->height; |
568 | 13.8k | sl->size = FFALIGN(size + 2, 4); |
569 | 13.8k | sl->pos = pkt_size; |
570 | 13.8k | pkt_size += sl->size; |
571 | 13.8k | } |
572 | 9.35k | } |
573 | | |
574 | 9.35k | ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0); |
575 | 9.35k | if (ret < 0) |
576 | 0 | return ret; |
577 | | |
578 | 9.35k | bytestream2_init_writer(&pb, pkt->data, pkt->size); |
579 | 9.35k | bytestream2_put_le32u(&pb, MKTAG('M', 'A', 'G', 'Y')); |
580 | 9.35k | bytestream2_put_le32u(&pb, 32); // header size |
581 | 9.35k | bytestream2_put_byteu(&pb, 7); // version |
582 | 9.35k | bytestream2_put_byteu(&pb, s->format); |
583 | 9.35k | bytestream2_put_byteu(&pb, 12); // max huffman length |
584 | 9.35k | bytestream2_put_byteu(&pb, 0); |
585 | | |
586 | 9.35k | bytestream2_put_byteu(&pb, 0); |
587 | 9.35k | bytestream2_put_byteu(&pb, 0); |
588 | 9.35k | bytestream2_put_byteu(&pb, 32); // coder type |
589 | 9.35k | bytestream2_put_byteu(&pb, 0); |
590 | | |
591 | 9.35k | bytestream2_put_le32u(&pb, avctx->width); |
592 | 9.35k | bytestream2_put_le32u(&pb, avctx->height); |
593 | 9.35k | bytestream2_put_le32u(&pb, avctx->width); |
594 | 9.35k | bytestream2_put_le32u(&pb, s->slice_height); |
595 | | |
596 | | // Slice position is relative to the current position (i.e. 32) |
597 | 9.35k | bytestream2_put_le32u(&pb, header_size - 32); |
598 | | |
599 | 23.2k | for (int i = 0; i < s->planes; ++i) { |
600 | 27.7k | for (int j = 0; j < s->nb_slices; ++j) { |
601 | 13.8k | Slice *const sl = &s->slices[j * s->planes + i]; |
602 | 13.8k | bytestream2_put_le32u(&pb, sl->pos - 32); |
603 | 13.8k | sl->dst = pkt->data + sl->pos; |
604 | 13.8k | } |
605 | 13.8k | } |
606 | | |
607 | 9.35k | bytestream2_put_byteu(&pb, s->planes); |
608 | | |
609 | 23.2k | for (int i = 0; i < s->planes; i++) { |
610 | 27.7k | for (int n = 0; n < s->nb_slices; n++) |
611 | 13.8k | bytestream2_put_byteu(&pb, n * s->planes + i); |
612 | 13.8k | } |
613 | | |
614 | 23.2k | for (int i = 0; i < s->planes; ++i) |
615 | 13.8k | output_codes(&pb, s->he[i]); |
616 | | |
617 | 9.35k | avctx->execute2(avctx, encode_slice, NULL, NULL, s->nb_slices); |
618 | | |
619 | 9.35k | *got_packet = 1; |
620 | | |
621 | 9.35k | return 0; |
622 | 9.35k | } |
623 | | |
624 | | static av_cold int magy_encode_close(AVCodecContext *avctx) |
625 | 393 | { |
626 | 393 | MagicYUVContext *s = avctx->priv_data; |
627 | | |
628 | 393 | if (s->slices) { |
629 | 1.40k | for (int i = 0; i < s->planes * s->nb_slices; i++) { |
630 | 1.01k | Slice *sl = &s->slices[i]; |
631 | | |
632 | 1.01k | av_freep(&sl->slice); |
633 | 1.01k | } |
634 | 393 | av_freep(&s->slices); |
635 | 393 | } |
636 | 393 | av_freep(&s->decorrelate_buf); |
637 | | |
638 | 393 | return 0; |
639 | 393 | } |
640 | | |
641 | | #define OFFSET(x) offsetof(MagicYUVContext, x) |
642 | | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
643 | | static const AVOption options[] = { |
644 | | { "pred", "Prediction method", OFFSET(frame_pred), AV_OPT_TYPE_INT, {.i64=LEFT}, LEFT, MEDIAN, VE, .unit = "pred" }, |
645 | | { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LEFT }, 0, 0, VE, .unit = "pred" }, |
646 | | { "gradient", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = GRADIENT }, 0, 0, VE, .unit = "pred" }, |
647 | | { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MEDIAN }, 0, 0, VE, .unit = "pred" }, |
648 | | { NULL}, |
649 | | }; |
650 | | |
651 | | static const AVClass magicyuv_class = { |
652 | | .class_name = "magicyuv", |
653 | | .item_name = av_default_item_name, |
654 | | .option = options, |
655 | | .version = LIBAVUTIL_VERSION_INT, |
656 | | }; |
657 | | |
658 | | const FFCodec ff_magicyuv_encoder = { |
659 | | .p.name = "magicyuv", |
660 | | CODEC_LONG_NAME("MagicYUV video"), |
661 | | .p.type = AVMEDIA_TYPE_VIDEO, |
662 | | .p.id = AV_CODEC_ID_MAGICYUV, |
663 | | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | |
664 | | AV_CODEC_CAP_SLICE_THREADS | |
665 | | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, |
666 | | .priv_data_size = sizeof(MagicYUVContext), |
667 | | .p.priv_class = &magicyuv_class, |
668 | | .init = magy_encode_init, |
669 | | .close = magy_encode_close, |
670 | | FF_CODEC_ENCODE_CB(magy_encode_frame), |
671 | | CODEC_PIXFMTS(AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, |
672 | | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, |
673 | | AV_PIX_FMT_GRAY8), |
674 | | .color_ranges = AVCOL_RANGE_MPEG, /* FIXME: implement tagging */ |
675 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
676 | | }; |