/src/ffmpeg/libavcodec/utvideoenc.c
Line | Count | Source |
1 | | /* |
2 | | * Ut Video encoder |
3 | | * Copyright (c) 2012 Jan Ekström |
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 | | /** |
23 | | * @file |
24 | | * Ut Video encoder |
25 | | */ |
26 | | |
27 | | #include "libavutil/avassert.h" |
28 | | #include "libavutil/imgutils.h" |
29 | | #include "libavutil/intreadwrite.h" |
30 | | #include "libavutil/mem.h" |
31 | | #include "libavutil/opt.h" |
32 | | |
33 | | #include "avcodec.h" |
34 | | #include "codec_internal.h" |
35 | | #include "encode.h" |
36 | | #include "bswapdsp.h" |
37 | | #include "bytestream.h" |
38 | | #include "lossless_videoencdsp.h" |
39 | | #include "put_bits.h" |
40 | | #include "utvideo.h" |
41 | | #include "huffman.h" |
42 | | |
43 | | typedef struct UtvideoContext { |
44 | | const AVClass *class; |
45 | | BswapDSPContext bdsp; |
46 | | LLVidEncDSPContext llvidencdsp; |
47 | | |
48 | | uint32_t frame_info_size, flags; |
49 | | int planes; |
50 | | int slices; |
51 | | int compression; |
52 | | int frame_pred; |
53 | | |
54 | | ptrdiff_t slice_stride; |
55 | | uint8_t *slice_bits, *slice_buffer[4]; |
56 | | int slice_bits_size; |
57 | | } UtvideoContext; |
58 | | |
59 | | typedef struct HuffEntry { |
60 | | uint16_t sym; |
61 | | uint8_t len; |
62 | | uint32_t code; |
63 | | } HuffEntry; |
64 | | |
65 | | /* Compare huffman tree nodes */ |
66 | | static int ut_huff_cmp_len(const void *a, const void *b) |
67 | 20.4M | { |
68 | 20.4M | const HuffEntry *aa = a, *bb = b; |
69 | 20.4M | return (aa->len - bb->len)*256 + aa->sym - bb->sym; |
70 | 20.4M | } |
71 | | |
72 | | /* Compare huffentry symbols */ |
73 | | static int huff_cmp_sym(const void *a, const void *b) |
74 | 22.3M | { |
75 | 22.3M | const HuffEntry *aa = a, *bb = b; |
76 | 22.3M | return aa->sym - bb->sym; |
77 | 22.3M | } |
78 | | |
79 | | static av_cold int utvideo_encode_close(AVCodecContext *avctx) |
80 | 410 | { |
81 | 410 | UtvideoContext *c = avctx->priv_data; |
82 | 410 | int i; |
83 | | |
84 | 410 | av_freep(&c->slice_bits); |
85 | 2.05k | for (i = 0; i < 4; i++) |
86 | 1.64k | av_freep(&c->slice_buffer[i]); |
87 | | |
88 | 410 | return 0; |
89 | 410 | } |
90 | | |
91 | | static av_cold int utvideo_encode_init(AVCodecContext *avctx) |
92 | 410 | { |
93 | 410 | UtvideoContext *c = avctx->priv_data; |
94 | 410 | int i, subsampled_height; |
95 | 410 | uint32_t original_format; |
96 | | |
97 | 410 | c->frame_info_size = 4; |
98 | 410 | c->slice_stride = FFALIGN(avctx->width, 32); |
99 | | |
100 | 410 | switch (avctx->pix_fmt) { |
101 | 150 | case AV_PIX_FMT_GBRP: |
102 | 150 | c->planes = 3; |
103 | 150 | avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); |
104 | 150 | original_format = UTVIDEO_RGB; |
105 | 150 | break; |
106 | 87 | case AV_PIX_FMT_GBRAP: |
107 | 87 | c->planes = 4; |
108 | 87 | avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); |
109 | 87 | original_format = UTVIDEO_RGBA; |
110 | 87 | avctx->bits_per_coded_sample = 32; |
111 | 87 | break; |
112 | 110 | case AV_PIX_FMT_YUV420P: |
113 | 110 | if (avctx->width & 1 || avctx->height & 1) { |
114 | 3 | av_log(avctx, AV_LOG_ERROR, |
115 | 3 | "4:2:0 video requires even width and height.\n"); |
116 | 3 | return AVERROR_INVALIDDATA; |
117 | 3 | } |
118 | 107 | c->planes = 3; |
119 | 107 | if (avctx->colorspace == AVCOL_SPC_BT709) |
120 | 0 | avctx->codec_tag = MKTAG('U', 'L', 'H', '0'); |
121 | 107 | else |
122 | 107 | avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); |
123 | 107 | original_format = UTVIDEO_420; |
124 | 107 | break; |
125 | 36 | case AV_PIX_FMT_YUV422P: |
126 | 36 | if (avctx->width & 1) { |
127 | 5 | av_log(avctx, AV_LOG_ERROR, |
128 | 5 | "4:2:2 video requires even width.\n"); |
129 | 5 | return AVERROR_INVALIDDATA; |
130 | 5 | } |
131 | 31 | c->planes = 3; |
132 | 31 | if (avctx->colorspace == AVCOL_SPC_BT709) |
133 | 0 | avctx->codec_tag = MKTAG('U', 'L', 'H', '2'); |
134 | 31 | else |
135 | 31 | avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); |
136 | 31 | original_format = UTVIDEO_422; |
137 | 31 | break; |
138 | 27 | case AV_PIX_FMT_YUV444P: |
139 | 27 | c->planes = 3; |
140 | 27 | if (avctx->colorspace == AVCOL_SPC_BT709) |
141 | 0 | avctx->codec_tag = MKTAG('U', 'L', 'H', '4'); |
142 | 27 | else |
143 | 27 | avctx->codec_tag = MKTAG('U', 'L', 'Y', '4'); |
144 | 27 | original_format = UTVIDEO_444; |
145 | 27 | break; |
146 | 0 | default: |
147 | 0 | av_unreachable("Already checked via CODEC_PIXFMTS"); |
148 | 410 | } |
149 | | |
150 | 402 | ff_bswapdsp_init(&c->bdsp); |
151 | 402 | ff_llvidencdsp_init(&c->llvidencdsp); |
152 | | |
153 | 402 | if (c->frame_pred == PRED_GRADIENT) { |
154 | 0 | av_log(avctx, AV_LOG_ERROR, "Gradient prediction is not supported.\n"); |
155 | 0 | return AVERROR_PATCHWELCOME; |
156 | 0 | } |
157 | | |
158 | | /* |
159 | | * Check the asked slice count for obviously invalid |
160 | | * values (> 256 or negative). |
161 | | */ |
162 | 402 | if (avctx->slices > 256 || avctx->slices < 0) { |
163 | 0 | av_log(avctx, AV_LOG_ERROR, |
164 | 0 | "Slice count %d is not supported in Ut Video (theoretical range is 0-256).\n", |
165 | 0 | avctx->slices); |
166 | 0 | return AVERROR(EINVAL); |
167 | 0 | } |
168 | | |
169 | | /* Check that the slice count is not larger than the subsampled height */ |
170 | 402 | subsampled_height = avctx->height >> av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_h; |
171 | 402 | if (avctx->slices > subsampled_height) { |
172 | 0 | av_log(avctx, AV_LOG_ERROR, |
173 | 0 | "Slice count %d is larger than the subsampling-applied height %d.\n", |
174 | 0 | avctx->slices, subsampled_height); |
175 | 0 | return AVERROR(EINVAL); |
176 | 0 | } |
177 | | |
178 | | /* extradata size is 4 * 32 bits */ |
179 | 402 | avctx->extradata_size = 16; |
180 | | |
181 | 402 | avctx->extradata = av_mallocz(avctx->extradata_size + |
182 | 402 | AV_INPUT_BUFFER_PADDING_SIZE); |
183 | | |
184 | 402 | if (!avctx->extradata) { |
185 | 0 | av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata.\n"); |
186 | 0 | return AVERROR(ENOMEM); |
187 | 0 | } |
188 | | |
189 | 1.69k | for (i = 0; i < c->planes; i++) { |
190 | 1.29k | c->slice_buffer[i] = av_malloc(c->slice_stride * (avctx->height + 2) + |
191 | 1.29k | AV_INPUT_BUFFER_PADDING_SIZE); |
192 | 1.29k | if (!c->slice_buffer[i]) { |
193 | 0 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 1.\n"); |
194 | 0 | return AVERROR(ENOMEM); |
195 | 0 | } |
196 | 1.29k | } |
197 | | |
198 | | /* |
199 | | * Set the version of the encoder. |
200 | | * Last byte is "implementation ID", which is |
201 | | * obtained from the creator of the format. |
202 | | * Libavcodec has been assigned with the ID 0xF0. |
203 | | */ |
204 | 402 | AV_WB32(avctx->extradata, MKTAG(1, 0, 0, 0xF0)); |
205 | | |
206 | | /* |
207 | | * Set the "original format" |
208 | | * Not used for anything during decoding. |
209 | | */ |
210 | 402 | AV_WL32(avctx->extradata + 4, original_format); |
211 | | |
212 | | /* Write 4 as the 'frame info size' */ |
213 | 402 | AV_WL32(avctx->extradata + 8, c->frame_info_size); |
214 | | |
215 | | /* |
216 | | * Set how many slices are going to be used. |
217 | | * By default uses multiple slices depending on the subsampled height. |
218 | | * This enables multithreading in the official decoder. |
219 | | */ |
220 | 402 | if (!avctx->slices) { |
221 | 402 | c->slices = subsampled_height / 120; |
222 | | |
223 | 402 | if (!c->slices) |
224 | 265 | c->slices = 1; |
225 | 137 | else if (c->slices > 256) |
226 | 31 | c->slices = 256; |
227 | 402 | } else { |
228 | 0 | c->slices = avctx->slices; |
229 | 0 | } |
230 | | |
231 | | /* Set compression mode */ |
232 | 402 | c->compression = COMP_HUFF; |
233 | | |
234 | | /* |
235 | | * Set the encoding flags: |
236 | | * - Slice count minus 1 |
237 | | * - Interlaced encoding mode flag, set to zero for now. |
238 | | * - Compression mode (none/huff) |
239 | | * And write the flags. |
240 | | */ |
241 | 402 | c->flags = (c->slices - 1U) << 24; |
242 | 402 | c->flags |= 0 << 11; // bit field to signal interlaced encoding mode |
243 | 402 | c->flags |= c->compression; |
244 | | |
245 | 402 | AV_WL32(avctx->extradata + 12, c->flags); |
246 | | |
247 | 402 | return 0; |
248 | 402 | } |
249 | | |
250 | | static void mangle_rgb_planes(uint8_t *dst[4], ptrdiff_t dst_stride, |
251 | | uint8_t *const src[4], int planes, const int stride[4], |
252 | | int width, int height) |
253 | 1.53k | { |
254 | 1.53k | int i, j; |
255 | 1.53k | int k = 2 * dst_stride; |
256 | 1.53k | const uint8_t *sg = src[0]; |
257 | 1.53k | const uint8_t *sb = src[1]; |
258 | 1.53k | const uint8_t *sr = src[2]; |
259 | 1.53k | const uint8_t *sa = src[3]; |
260 | 1.53k | unsigned int g; |
261 | | |
262 | 2.37M | for (j = 0; j < height; j++) { |
263 | 2.37M | if (planes == 3) { |
264 | 14.0M | for (i = 0; i < width; i++) { |
265 | 12.5M | g = sg[i]; |
266 | 12.5M | dst[0][k] = g; |
267 | 12.5M | g += 0x80; |
268 | 12.5M | dst[1][k] = sb[i] - g; |
269 | 12.5M | dst[2][k] = sr[i] - g; |
270 | 12.5M | k++; |
271 | 12.5M | } |
272 | 1.49M | } else { |
273 | 13.4M | for (i = 0; i < width; i++) { |
274 | 12.5M | g = sg[i]; |
275 | 12.5M | dst[0][k] = g; |
276 | 12.5M | g += 0x80; |
277 | 12.5M | dst[1][k] = sb[i] - g; |
278 | 12.5M | dst[2][k] = sr[i] - g; |
279 | 12.5M | dst[3][k] = sa[i]; |
280 | 12.5M | k++; |
281 | 12.5M | } |
282 | 880k | sa += stride[3]; |
283 | 880k | } |
284 | 2.37M | k += dst_stride - width; |
285 | 2.37M | sg += stride[0]; |
286 | 2.37M | sb += stride[1]; |
287 | 2.37M | sr += stride[2]; |
288 | 2.37M | } |
289 | 1.53k | } |
290 | | |
291 | | #undef A |
292 | | #undef B |
293 | | |
294 | | /* Write data to a plane with median prediction */ |
295 | | static void median_predict(UtvideoContext *c, const uint8_t *src, uint8_t *dst, |
296 | | ptrdiff_t stride, int width, int height) |
297 | 0 | { |
298 | 0 | int i, j; |
299 | 0 | int A, B; |
300 | 0 | uint8_t prev; |
301 | | |
302 | | /* First line uses left neighbour prediction */ |
303 | 0 | prev = 0x80; /* Set the initial value */ |
304 | 0 | for (i = 0; i < width; i++) { |
305 | 0 | *dst++ = src[i] - prev; |
306 | 0 | prev = src[i]; |
307 | 0 | } |
308 | |
|
309 | 0 | if (height == 1) |
310 | 0 | return; |
311 | | |
312 | 0 | src += stride; |
313 | | |
314 | | /* |
315 | | * Second line uses top prediction for the first sample, |
316 | | * and median for the rest. |
317 | | */ |
318 | 0 | A = B = 0; |
319 | | |
320 | | /* Rest of the coded part uses median prediction */ |
321 | 0 | for (j = 1; j < height; j++) { |
322 | 0 | c->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &A, &B); |
323 | 0 | dst += width; |
324 | 0 | src += stride; |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | /* Count the usage of values in a plane */ |
329 | | static void count_usage(uint8_t *src, int width, |
330 | | int height, uint64_t *counts) |
331 | 26.4k | { |
332 | 26.4k | int i, j; |
333 | | |
334 | 8.94M | for (j = 0; j < height; j++) { |
335 | 112M | for (i = 0; i < width; i++) { |
336 | 103M | counts[src[i]]++; |
337 | 103M | } |
338 | 8.91M | src += width; |
339 | 8.91M | } |
340 | 26.4k | } |
341 | | |
342 | | /* Calculate the actual huffman codes from the code lengths */ |
343 | | static void calculate_codes(HuffEntry *he) |
344 | 17.9k | { |
345 | 17.9k | int last, i; |
346 | 17.9k | uint32_t code; |
347 | | |
348 | 17.9k | qsort(he, 256, sizeof(*he), ut_huff_cmp_len); |
349 | | |
350 | 17.9k | last = 255; |
351 | 3.88M | while (he[last].len == 255 && last) |
352 | 3.86M | last--; |
353 | | |
354 | 17.9k | code = 0; |
355 | 736k | for (i = last; i >= 0; i--) { |
356 | 718k | he[i].code = code >> (32 - he[i].len); |
357 | 718k | code += 0x80000000u >> (he[i].len - 1); |
358 | 718k | } |
359 | | |
360 | 17.9k | qsort(he, 256, sizeof(*he), huff_cmp_sym); |
361 | 17.9k | } |
362 | | |
363 | | /* Write huffman bit codes to a memory block */ |
364 | | static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size, |
365 | | int width, int height, HuffEntry *he) |
366 | 56.2k | { |
367 | 56.2k | PutBitContext pb; |
368 | 56.2k | int i, j; |
369 | 56.2k | int count; |
370 | | |
371 | 56.2k | init_put_bits(&pb, dst, dst_size); |
372 | | |
373 | | /* Write the codes */ |
374 | 8.03M | for (j = 0; j < height; j++) { |
375 | 110M | for (i = 0; i < width; i++) |
376 | 102M | put_bits(&pb, he[src[i]].len, he[src[i]].code); |
377 | | |
378 | 7.97M | src += width; |
379 | 7.97M | } |
380 | | |
381 | | /* Pad output to a 32-bit boundary */ |
382 | 56.2k | count = put_bits_count(&pb) & 0x1F; |
383 | | |
384 | 56.2k | if (count) |
385 | 44.7k | put_bits(&pb, 32 - count, 0); |
386 | | |
387 | | /* Flush the rest with zeroes */ |
388 | 56.2k | flush_put_bits(&pb); |
389 | | |
390 | | /* Return the amount of bytes written */ |
391 | 56.2k | return put_bytes_output(&pb); |
392 | 56.2k | } |
393 | | |
394 | | static int encode_plane(AVCodecContext *avctx, const uint8_t *src, |
395 | | uint8_t *dst, ptrdiff_t stride, int plane_no, |
396 | | int width, int height, PutByteContext *pb) |
397 | 26.4k | { |
398 | 26.4k | UtvideoContext *c = avctx->priv_data; |
399 | 26.4k | uint8_t lengths[256]; |
400 | 26.4k | uint64_t counts[256] = { 0 }; |
401 | | |
402 | 26.4k | HuffEntry he[256]; |
403 | | |
404 | 26.4k | uint32_t offset = 0, slice_len = 0; |
405 | 26.4k | const int cmask = ~(!plane_no && avctx->pix_fmt == AV_PIX_FMT_YUV420P); |
406 | 26.4k | int i, sstart, send = 0; |
407 | 26.4k | int symbol; |
408 | 26.4k | int ret; |
409 | | |
410 | | /* Do prediction / make planes */ |
411 | 26.4k | switch (c->frame_pred) { |
412 | 0 | case PRED_NONE: |
413 | 0 | for (i = 0; i < c->slices; i++) { |
414 | 0 | sstart = send; |
415 | 0 | send = height * (i + 1) / c->slices & cmask; |
416 | 0 | av_image_copy_plane(dst + sstart * width, width, |
417 | 0 | src + sstart * stride, stride, |
418 | 0 | width, send - sstart); |
419 | 0 | } |
420 | 0 | break; |
421 | 26.4k | case PRED_LEFT: |
422 | 97.2k | for (i = 0; i < c->slices; i++) { |
423 | 70.7k | sstart = send; |
424 | 70.7k | send = height * (i + 1) / c->slices & cmask; |
425 | 70.7k | c->llvidencdsp.sub_left_predict(dst + sstart * width, src + sstart * stride, stride, width, send - sstart); |
426 | 70.7k | } |
427 | 26.4k | break; |
428 | 0 | case PRED_MEDIAN: |
429 | 0 | for (i = 0; i < c->slices; i++) { |
430 | 0 | sstart = send; |
431 | 0 | send = height * (i + 1) / c->slices & cmask; |
432 | 0 | median_predict(c, src + sstart * stride, dst + sstart * width, |
433 | 0 | stride, width, send - sstart); |
434 | 0 | } |
435 | 0 | break; |
436 | 0 | default: |
437 | 0 | av_log(avctx, AV_LOG_ERROR, "Unknown prediction mode: %d\n", |
438 | 0 | c->frame_pred); |
439 | 0 | return AVERROR_OPTION_NOT_FOUND; |
440 | 26.4k | } |
441 | | |
442 | | /* Count the usage of values */ |
443 | 26.4k | count_usage(dst, width, height, counts); |
444 | | |
445 | | /* Check for a special case where only one symbol was used */ |
446 | 1.26M | for (symbol = 0; symbol < 256; symbol++) { |
447 | | /* If non-zero count is found, see if it matches width * height */ |
448 | 1.26M | if (counts[symbol]) { |
449 | | /* Special case if only one symbol was used */ |
450 | 26.4k | if (counts[symbol] == width * (int64_t)height) { |
451 | | /* |
452 | | * Write a zero for the single symbol |
453 | | * used in the plane, else 0xFF. |
454 | | */ |
455 | 2.19M | for (i = 0; i < 256; i++) { |
456 | 2.18M | if (i == symbol) |
457 | 8.54k | bytestream2_put_byte(pb, 0); |
458 | 2.17M | else |
459 | 2.17M | bytestream2_put_byte(pb, 0xFF); |
460 | 2.18M | } |
461 | | |
462 | | /* Write zeroes for lengths */ |
463 | 23.0k | for (i = 0; i < c->slices; i++) |
464 | 14.5k | bytestream2_put_le32(pb, 0); |
465 | | |
466 | | /* And that's all for that plane folks */ |
467 | 8.54k | return 0; |
468 | 8.54k | } |
469 | 17.9k | break; |
470 | 26.4k | } |
471 | 1.26M | } |
472 | | |
473 | | /* Calculate huffman lengths */ |
474 | 17.9k | if ((ret = ff_huff_gen_len_table(lengths, counts, 256, 1)) < 0) |
475 | 0 | return ret; |
476 | | |
477 | | /* |
478 | | * Write the plane's header into the output packet: |
479 | | * - huffman code lengths (256 bytes) |
480 | | * - slice end offsets (gotten from the slice lengths) |
481 | | */ |
482 | 4.60M | for (i = 0; i < 256; i++) { |
483 | 4.58M | bytestream2_put_byte(pb, lengths[i]); |
484 | | |
485 | 4.58M | he[i].len = lengths[i]; |
486 | 4.58M | he[i].sym = i; |
487 | 4.58M | } |
488 | | |
489 | | /* Calculate the huffman codes themselves */ |
490 | 17.9k | calculate_codes(he); |
491 | | |
492 | 17.9k | send = 0; |
493 | 74.1k | for (i = 0; i < c->slices; i++) { |
494 | 56.2k | sstart = send; |
495 | 56.2k | send = height * (i + 1) / c->slices & cmask; |
496 | | |
497 | | /* |
498 | | * Write the huffman codes to a buffer, |
499 | | * get the offset in bytes. |
500 | | */ |
501 | 56.2k | offset += write_huff_codes(dst + sstart * width, c->slice_bits, |
502 | 56.2k | width * height + 4, width, |
503 | 56.2k | send - sstart, he); |
504 | | |
505 | 56.2k | slice_len = offset - slice_len; |
506 | | |
507 | | /* Byteswap the written huffman codes */ |
508 | 56.2k | c->bdsp.bswap_buf((uint32_t *) c->slice_bits, |
509 | 56.2k | (uint32_t *) c->slice_bits, |
510 | 56.2k | slice_len >> 2); |
511 | | |
512 | | /* Write the offset to the stream */ |
513 | 56.2k | bytestream2_put_le32(pb, offset); |
514 | | |
515 | | /* Seek to the data part of the packet */ |
516 | 56.2k | bytestream2_seek_p(pb, 4 * (c->slices - i - 1) + |
517 | 56.2k | offset - slice_len, SEEK_CUR); |
518 | | |
519 | | /* Write the slices' data into the output packet */ |
520 | 56.2k | bytestream2_put_buffer(pb, c->slice_bits, slice_len); |
521 | | |
522 | | /* Seek back to the slice offsets */ |
523 | 56.2k | bytestream2_seek_p(pb, -4 * (c->slices - i - 1) - offset, |
524 | 56.2k | SEEK_CUR); |
525 | | |
526 | 56.2k | slice_len = offset; |
527 | 56.2k | } |
528 | | |
529 | | /* And at the end seek to the end of written slice(s) */ |
530 | 17.9k | bytestream2_seek_p(pb, offset, SEEK_CUR); |
531 | | |
532 | 17.9k | return 0; |
533 | 17.9k | } |
534 | | |
535 | | static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
536 | | const AVFrame *pic, int *got_packet) |
537 | 8.54k | { |
538 | 8.54k | UtvideoContext *c = avctx->priv_data; |
539 | 8.54k | PutByteContext pb; |
540 | | |
541 | 8.54k | uint32_t frame_info; |
542 | | |
543 | 8.54k | uint8_t *dst; |
544 | | |
545 | 8.54k | int width = avctx->width, height = avctx->height; |
546 | 8.54k | int i, ret = 0; |
547 | | |
548 | | /* Allocate a new packet if needed, and set it to the pointer dst */ |
549 | 8.54k | ret = ff_alloc_packet(avctx, pkt, (256 + 4 * c->slices + width * height) |
550 | 8.54k | * c->planes + 4); |
551 | | |
552 | 8.54k | if (ret < 0) |
553 | 0 | return ret; |
554 | | |
555 | 8.54k | dst = pkt->data; |
556 | | |
557 | 8.54k | bytestream2_init_writer(&pb, dst, pkt->size); |
558 | | |
559 | 8.54k | av_fast_padded_malloc(&c->slice_bits, &c->slice_bits_size, width * height + 4); |
560 | | |
561 | 8.54k | if (!c->slice_bits) { |
562 | 0 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); |
563 | 0 | return AVERROR(ENOMEM); |
564 | 0 | } |
565 | | |
566 | | /* In case of RGB, mangle the planes to Ut Video's format */ |
567 | 8.54k | if (avctx->pix_fmt == AV_PIX_FMT_GBRAP || avctx->pix_fmt == AV_PIX_FMT_GBRP) |
568 | 1.53k | mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data, |
569 | 1.53k | c->planes, pic->linesize, width, height); |
570 | | |
571 | | /* Deal with the planes */ |
572 | 8.54k | switch (avctx->pix_fmt) { |
573 | 727 | case AV_PIX_FMT_GBRP: |
574 | 1.53k | case AV_PIX_FMT_GBRAP: |
575 | 6.95k | for (i = 0; i < c->planes; i++) { |
576 | 5.41k | ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride, |
577 | 5.41k | c->slice_buffer[i], c->slice_stride, i, |
578 | 5.41k | width, height, &pb); |
579 | | |
580 | 5.41k | if (ret) { |
581 | 0 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
582 | 0 | return ret; |
583 | 0 | } |
584 | 5.41k | } |
585 | 1.53k | break; |
586 | 1.53k | case AV_PIX_FMT_YUV444P: |
587 | 1.33k | for (i = 0; i < c->planes; i++) { |
588 | 999 | ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], |
589 | 999 | pic->linesize[i], i, width, height, &pb); |
590 | | |
591 | 999 | if (ret) { |
592 | 0 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
593 | 0 | return ret; |
594 | 0 | } |
595 | 999 | } |
596 | 333 | break; |
597 | 352 | case AV_PIX_FMT_YUV422P: |
598 | 1.40k | for (i = 0; i < c->planes; i++) { |
599 | 1.05k | ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], |
600 | 1.05k | pic->linesize[i], i, width >> !!i, height, &pb); |
601 | | |
602 | 1.05k | if (ret) { |
603 | 0 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
604 | 0 | return ret; |
605 | 0 | } |
606 | 1.05k | } |
607 | 352 | break; |
608 | 6.32k | case AV_PIX_FMT_YUV420P: |
609 | 25.3k | for (i = 0; i < c->planes; i++) { |
610 | 18.9k | ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], |
611 | 18.9k | pic->linesize[i], i, width >> !!i, height >> !!i, |
612 | 18.9k | &pb); |
613 | | |
614 | 18.9k | if (ret) { |
615 | 0 | av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); |
616 | 0 | return ret; |
617 | 0 | } |
618 | 18.9k | } |
619 | 6.32k | break; |
620 | 6.32k | default: |
621 | 0 | av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", |
622 | 0 | avctx->pix_fmt); |
623 | 0 | return AVERROR_INVALIDDATA; |
624 | 8.54k | } |
625 | | |
626 | | /* |
627 | | * Write frame information (LE 32-bit unsigned) |
628 | | * into the output packet. |
629 | | * Contains the prediction method. |
630 | | */ |
631 | 8.54k | frame_info = c->frame_pred << 8; |
632 | 8.54k | bytestream2_put_le32(&pb, frame_info); |
633 | | |
634 | 8.54k | pkt->size = bytestream2_tell_p(&pb); |
635 | | |
636 | | /* Packet should be done */ |
637 | 8.54k | *got_packet = 1; |
638 | | |
639 | 8.54k | return 0; |
640 | 8.54k | } |
641 | | |
642 | | #define OFFSET(x) offsetof(UtvideoContext, x) |
643 | | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
644 | | static const AVOption options[] = { |
645 | | { "pred", "Prediction method", OFFSET(frame_pred), AV_OPT_TYPE_INT, { .i64 = PRED_LEFT }, PRED_NONE, PRED_MEDIAN, VE, .unit = "pred" }, |
646 | | { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_NONE }, INT_MIN, INT_MAX, VE, .unit = "pred" }, |
647 | | { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_LEFT }, INT_MIN, INT_MAX, VE, .unit = "pred" }, |
648 | | { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRED_MEDIAN }, INT_MIN, INT_MAX, VE, .unit = "pred" }, |
649 | | |
650 | | { NULL}, |
651 | | }; |
652 | | |
653 | | static const AVClass utvideo_class = { |
654 | | .class_name = "utvideo", |
655 | | .item_name = av_default_item_name, |
656 | | .option = options, |
657 | | .version = LIBAVUTIL_VERSION_INT, |
658 | | }; |
659 | | |
660 | | const FFCodec ff_utvideo_encoder = { |
661 | | .p.name = "utvideo", |
662 | | CODEC_LONG_NAME("Ut Video"), |
663 | | .p.type = AVMEDIA_TYPE_VIDEO, |
664 | | .p.id = AV_CODEC_ID_UTVIDEO, |
665 | | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | |
666 | | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, |
667 | | .priv_data_size = sizeof(UtvideoContext), |
668 | | .p.priv_class = &utvideo_class, |
669 | | .init = utvideo_encode_init, |
670 | | FF_CODEC_ENCODE_CB(utvideo_encode_frame), |
671 | | .close = utvideo_encode_close, |
672 | | CODEC_PIXFMTS(AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
673 | | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P), |
674 | | .color_ranges = AVCOL_RANGE_MPEG, |
675 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
676 | | }; |