2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 /** @file src/image.cc
23 * @brief A class to describe a video image.
27 #include "compose.hpp"
28 #include "dcpomatic_assert.h"
29 #include "dcpomatic_socket.h"
30 #include "enum_indexed_vector.h"
31 #include "exceptions.h"
33 #include "maths_util.h"
34 #include "memory_util.h"
37 #include <dcp/rgb_xyz.h>
38 #include <dcp/transfer_function.h>
39 #include <dcp/warnings.h>
40 LIBDCP_DISABLE_WARNINGS
42 #include <libavutil/frame.h>
43 #include <libavutil/pixdesc.h>
44 #include <libavutil/pixfmt.h>
45 #include <libswscale/swscale.h>
47 LIBDCP_ENABLE_WARNINGS
48 #if HAVE_VALGRIND_MEMCHECK_H
49 #include <valgrind/memcheck.h>
60 using std::make_shared;
63 using std::runtime_error;
64 using std::shared_ptr;
69 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
70 int constexpr ALIGNMENT = 64;
72 /* U/V black value for 8-bit colour */
73 static uint8_t const eight_bit_uv = (1 << 7) - 1;
74 /* U/V black value for 9-bit colour */
75 static uint16_t const nine_bit_uv = (1 << 8) - 1;
76 /* U/V black value for 10-bit colour */
77 static uint16_t const ten_bit_uv = (1 << 9) - 1;
78 /* U/V black value for 16-bit colour */
79 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
83 Image::vertical_factor (int n) const
89 auto d = av_pix_fmt_desc_get(_pixel_format);
91 throw PixelFormatError ("line_factor()", _pixel_format);
94 return lrintf(powf(2.0f, d->log2_chroma_h));
98 Image::horizontal_factor (int n) const
104 auto d = av_pix_fmt_desc_get(_pixel_format);
106 throw PixelFormatError ("sample_size()", _pixel_format);
109 return lrintf(powf(2.0f, d->log2_chroma_w));
113 /** @param n Component index.
114 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
117 Image::sample_size (int n) const
120 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
121 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
126 /** @return Number of planes */
128 Image::planes () const
130 if (_pixel_format == AV_PIX_FMT_PAL8) {
134 auto d = av_pix_fmt_desc_get(_pixel_format);
136 throw PixelFormatError ("planes()", _pixel_format);
139 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
143 return d->nb_components;
149 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
151 return p & ~ ((1 << desc->log2_chroma_w) - 1);
157 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
159 return p & ~ ((1 << desc->log2_chroma_h) - 1);
163 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
164 * @param crop Amount to crop by.
165 * @param inter_size Size to scale the cropped image to.
166 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
167 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
168 * @param video_range Video range of the image.
169 * @param out_format Output pixel format.
170 * @param out_aligned true to make the output image aligned.
171 * @param out_video_range Video range to use for the output image.
172 * @param fast Try to be fast at the possible expense of quality; at present this means using
173 * fast bilinear rather than bicubic scaling.
176 Image::crop_scale_window (
178 dcp::Size inter_size,
180 dcp::YUVToRGB yuv_to_rgb,
181 VideoRange video_range,
182 AVPixelFormat out_format,
183 VideoRange out_video_range,
184 Alignment out_alignment,
188 /* Empirical testing suggests that sws_scale() will crash if
189 the input image is not padded.
191 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
193 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
194 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
196 auto out = make_shared<Image>(out_format, out_size, out_alignment);
199 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
201 throw PixelFormatError ("crop_scale_window()", _pixel_format);
204 /* Round down so that we crop only the number of pixels that is straightforward
205 * considering any subsampling.
208 round_width_for_subsampling(crop.left, in_desc),
209 round_width_for_subsampling(crop.right, in_desc),
210 round_height_for_subsampling(crop.top, in_desc),
211 round_height_for_subsampling(crop.bottom, in_desc)
214 /* Also check that we aren't cropping more image than there actually is */
215 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
216 corrected_crop.left = 0;
217 corrected_crop.right = size().width - 4;
220 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
221 corrected_crop.top = 0;
222 corrected_crop.bottom = size().height - 4;
225 /* Size of the image after any crop */
226 auto const cropped_size = corrected_crop.apply (size());
228 /* Scale context for a scale from cropped_size to inter_size */
229 auto scale_context = sws_getContext (
230 cropped_size.width, cropped_size.height, pixel_format(),
231 inter_size.width, inter_size.height, out_format,
232 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
235 if (!scale_context) {
236 throw runtime_error (N_("Could not allocate SwsContext"));
239 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
240 EnumIndexedVector<int, dcp::YUVToRGB> lut;
241 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
242 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
243 lut[dcp::YUVToRGB::REC2020] = SWS_CS_BT2020;
245 /* The 3rd parameter here is:
246 0 -> source range MPEG (i.e. "video", 16-235)
247 1 -> source range JPEG (i.e. "full", 0-255)
249 0 -> destination range MPEG (i.e. "video", 16-235)
250 1 -> destination range JPEG (i.e. "full", 0-255)
252 But remember: sws_setColorspaceDetails ignores these
253 parameters unless the both source and destination images
254 are isYUV or isGray. (If either is not, it uses video range).
256 sws_setColorspaceDetails (
258 sws_getCoefficients(lut[yuv_to_rgb]), video_range == VideoRange::VIDEO ? 0 : 1,
259 sws_getCoefficients(lut[yuv_to_rgb]), out_video_range == VideoRange::VIDEO ? 0 : 1,
263 /* Prepare input data pointers with crop */
264 uint8_t* scale_in_data[planes()];
265 for (int c = 0; c < planes(); ++c) {
266 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
267 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
270 auto out_desc = av_pix_fmt_desc_get (out_format);
272 throw PixelFormatError ("crop_scale_window()", out_format);
275 /* Corner of the image within out_size */
276 Position<int> const corner (
277 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
278 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
281 uint8_t* scale_out_data[out->planes()];
282 for (int c = 0; c < out->planes(); ++c) {
283 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
284 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
289 scale_in_data, stride(),
290 0, cropped_size.height,
291 scale_out_data, out->stride()
294 sws_freeContext (scale_context);
296 /* There are some cases where there will be unwanted image data left in the image at this point:
298 * 1. When we are cropping without any scaling or pixel format conversion.
299 * 2. When we are scaling to certain sizes and placing the result into a larger
302 * Clear out the sides of the image to take care of those cases.
304 auto const pad = (out_size.width - inter_size.width) / 2;
305 out->make_part_black(0, pad);
306 out->make_part_black(corner.x + inter_size.width, pad);
309 video_range == VideoRange::VIDEO &&
310 out_video_range == VideoRange::FULL &&
311 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
313 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
314 out->video_range_to_full_range ();
322 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
324 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
328 /** @param out_size Size to scale to.
329 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
330 * @param out_format Output pixel format.
331 * @param out_alignment Output alignment.
332 * @param fast Try to be fast at the possible expense of quality; at present this means using
333 * fast bilinear rather than bicubic scaling.
336 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
338 /* Empirical testing suggests that sws_scale() will crash if
339 the input image alignment is not PADDED.
341 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
343 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
344 auto scale_context = sws_getContext (
345 size().width, size().height, pixel_format(),
346 out_size.width, out_size.height, out_format,
347 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
350 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
351 EnumIndexedVector<int, dcp::YUVToRGB> lut;
352 lut[dcp::YUVToRGB::REC601] = SWS_CS_ITU601;
353 lut[dcp::YUVToRGB::REC709] = SWS_CS_ITU709;
354 lut[dcp::YUVToRGB::REC2020] = SWS_CS_BT2020;
356 /* The 3rd parameter here is:
357 0 -> source range MPEG (i.e. "video", 16-235)
358 1 -> source range JPEG (i.e. "full", 0-255)
360 0 -> destination range MPEG (i.e. "video", 16-235)
361 1 -> destination range JPEG (i.e. "full", 0-255)
363 But remember: sws_setColorspaceDetails ignores these
364 parameters unless the corresponding image isYUV or isGray.
365 (If it's neither, it uses video range).
367 sws_setColorspaceDetails (
369 sws_getCoefficients(lut[yuv_to_rgb]), 0,
370 sws_getCoefficients(lut[yuv_to_rgb]), 0,
378 scaled->data(), scaled->stride()
381 sws_freeContext (scale_context);
387 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
389 Image::yuv_16_black (uint16_t v, bool alpha)
391 memset (data()[0], 0, sample_size(0).height * stride()[0]);
392 for (int i = 1; i < 3; ++i) {
393 auto p = reinterpret_cast<int16_t*> (data()[i]);
394 int const lines = sample_size(i).height;
395 for (int y = 0; y < lines; ++y) {
396 /* We divide by 2 here because we are writing 2 bytes at a time */
397 for (int x = 0; x < line_size()[i] / 2; ++x) {
400 p += stride()[i] / 2;
405 memset (data()[3], 0, sample_size(3).height * stride()[3]);
411 Image::swap_16 (uint16_t v)
413 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
418 Image::make_part_black (int const start, int const width)
420 auto y_part = [&]() {
421 int const bpp = bytes_per_pixel(0);
422 int const h = sample_size(0).height;
423 int const s = stride()[0];
425 for (int y = 0; y < h; ++y) {
426 memset (p + start * bpp, 0, width * bpp);
431 switch (_pixel_format) {
432 case AV_PIX_FMT_RGB24:
433 case AV_PIX_FMT_ARGB:
434 case AV_PIX_FMT_RGBA:
435 case AV_PIX_FMT_ABGR:
436 case AV_PIX_FMT_BGRA:
437 case AV_PIX_FMT_RGB555LE:
438 case AV_PIX_FMT_RGB48LE:
439 case AV_PIX_FMT_RGB48BE:
440 case AV_PIX_FMT_XYZ12LE:
442 int const h = sample_size(0).height;
443 int const bpp = bytes_per_pixel(0);
444 int const s = stride()[0];
445 uint8_t* p = data()[0];
446 for (int y = 0; y < h; y++) {
447 memset (p + start * bpp, 0, width * bpp);
452 case AV_PIX_FMT_YUV420P:
455 for (int i = 1; i < 3; ++i) {
457 int const h = sample_size(i).height;
458 for (int y = 0; y < h; ++y) {
459 for (int x = start / 2; x < (start + width) / 2; ++x) {
467 case AV_PIX_FMT_YUV422P10LE:
470 for (int i = 1; i < 3; ++i) {
471 auto p = reinterpret_cast<int16_t*>(data()[i]);
472 int const h = sample_size(i).height;
473 for (int y = 0; y < h; ++y) {
474 for (int x = start / 2; x < (start + width) / 2; ++x) {
477 p += stride()[i] / 2;
482 case AV_PIX_FMT_YUV444P10LE:
485 for (int i = 1; i < 3; ++i) {
486 auto p = reinterpret_cast<int16_t*>(data()[i]);
487 int const h = sample_size(i).height;
488 for (int y = 0; y < h; ++y) {
489 for (int x = start; x < (start + width); ++x) {
492 p += stride()[i] / 2;
498 throw PixelFormatError ("make_part_black()", _pixel_format);
506 switch (_pixel_format) {
507 case AV_PIX_FMT_YUV420P:
508 case AV_PIX_FMT_YUV422P:
509 case AV_PIX_FMT_YUV444P:
510 case AV_PIX_FMT_YUV411P:
511 memset (data()[0], 0, sample_size(0).height * stride()[0]);
512 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
513 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
516 case AV_PIX_FMT_YUVJ420P:
517 case AV_PIX_FMT_YUVJ422P:
518 case AV_PIX_FMT_YUVJ444P:
519 memset (data()[0], 0, sample_size(0).height * stride()[0]);
520 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
521 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
524 case AV_PIX_FMT_YUV422P9LE:
525 case AV_PIX_FMT_YUV444P9LE:
526 yuv_16_black (nine_bit_uv, false);
529 case AV_PIX_FMT_YUV422P9BE:
530 case AV_PIX_FMT_YUV444P9BE:
531 yuv_16_black (swap_16 (nine_bit_uv), false);
534 case AV_PIX_FMT_YUV422P10LE:
535 case AV_PIX_FMT_YUV444P10LE:
536 yuv_16_black (ten_bit_uv, false);
539 case AV_PIX_FMT_YUV422P16LE:
540 case AV_PIX_FMT_YUV444P16LE:
541 yuv_16_black (sixteen_bit_uv, false);
544 case AV_PIX_FMT_YUV444P10BE:
545 case AV_PIX_FMT_YUV422P10BE:
546 yuv_16_black (swap_16 (ten_bit_uv), false);
549 case AV_PIX_FMT_YUVA420P9BE:
550 case AV_PIX_FMT_YUVA422P9BE:
551 case AV_PIX_FMT_YUVA444P9BE:
552 yuv_16_black (swap_16 (nine_bit_uv), true);
555 case AV_PIX_FMT_YUVA420P9LE:
556 case AV_PIX_FMT_YUVA422P9LE:
557 case AV_PIX_FMT_YUVA444P9LE:
558 yuv_16_black (nine_bit_uv, true);
561 case AV_PIX_FMT_YUVA420P10BE:
562 case AV_PIX_FMT_YUVA422P10BE:
563 case AV_PIX_FMT_YUVA444P10BE:
564 yuv_16_black (swap_16 (ten_bit_uv), true);
567 case AV_PIX_FMT_YUVA420P10LE:
568 case AV_PIX_FMT_YUVA422P10LE:
569 case AV_PIX_FMT_YUVA444P10LE:
570 yuv_16_black (ten_bit_uv, true);
573 case AV_PIX_FMT_YUVA420P16BE:
574 case AV_PIX_FMT_YUVA422P16BE:
575 case AV_PIX_FMT_YUVA444P16BE:
576 yuv_16_black (swap_16 (sixteen_bit_uv), true);
579 case AV_PIX_FMT_YUVA420P16LE:
580 case AV_PIX_FMT_YUVA422P16LE:
581 case AV_PIX_FMT_YUVA444P16LE:
582 yuv_16_black (sixteen_bit_uv, true);
585 case AV_PIX_FMT_RGB24:
586 case AV_PIX_FMT_ARGB:
587 case AV_PIX_FMT_RGBA:
588 case AV_PIX_FMT_ABGR:
589 case AV_PIX_FMT_BGRA:
590 case AV_PIX_FMT_RGB555LE:
591 case AV_PIX_FMT_RGB48LE:
592 case AV_PIX_FMT_RGB48BE:
593 case AV_PIX_FMT_XYZ12LE:
594 memset (data()[0], 0, sample_size(0).height * stride()[0]);
597 case AV_PIX_FMT_UYVY422:
599 int const Y = sample_size(0).height;
600 int const X = line_size()[0];
601 uint8_t* p = data()[0];
602 for (int y = 0; y < Y; ++y) {
603 for (int x = 0; x < X / 4; ++x) {
604 *p++ = eight_bit_uv; // Cb
606 *p++ = eight_bit_uv; // Cr
614 throw PixelFormatError ("make_black()", _pixel_format);
620 Image::make_transparent ()
622 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
623 throw PixelFormatError ("make_transparent()", _pixel_format);
626 memset (data()[0], 0, sample_size(0).height * stride()[0]);
635 uint8_t* const* data;
639 uint8_t* line_pointer(int y) const {
640 return data[0] + y * stride[0] + start_x * bpp;
650 uint8_t* const* data;
654 uint8_t* line_pointer(int y) const {
655 return data[0] + y * stride[0];
662 alpha_blend_onto_rgb24(TargetParams const& target, OtherParams const& other, int red, int blue)
664 /* Going onto RGB24. First byte is red, second green, third blue */
665 for (int ty = target.start_y, oy = other.start_y; ty < target.size.height && oy < other.size.height; ++ty, ++oy) {
666 uint8_t* tp = target.line_pointer(ty);
667 uint8_t* op = other.line_pointer(oy);
668 for (int tx = target.start_x, ox = other.start_x; tx < target.size.width && ox < other.size.width; ++tx, ++ox) {
669 float const alpha = float (op[3]) / 255;
670 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
671 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
672 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
683 alpha_blend_onto_bgra(TargetParams const& target, OtherParams const& other, int red, int blue)
685 for (int ty = target.start_y, oy = other.start_y; ty < target.size.height && oy < other.size.height; ++ty, ++oy) {
686 uint8_t* tp = target.line_pointer(ty);
687 uint8_t* op = other.line_pointer(oy);
688 for (int tx = target.start_x, ox = other.start_x; tx < target.size.width && ox < other.size.width; ++tx, ++ox) {
689 float const alpha = float (op[3]) / 255;
690 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
691 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
692 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
693 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
704 alpha_blend_onto_rgba(TargetParams const& target, OtherParams const& other, int red, int blue)
706 for (int ty = target.start_y, oy = other.start_y; ty < target.size.height && oy < other.size.height; ++ty, ++oy) {
707 uint8_t* tp = target.line_pointer(ty);
708 uint8_t* op = other.line_pointer(oy);
709 for (int tx = target.start_x, ox = other.start_x; tx < target.size.width && ox < other.size.width; ++tx, ++ox) {
710 float const alpha = float (op[3]) / 255;
711 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
712 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
713 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
714 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
725 alpha_blend_onto_rgb48le(TargetParams const& target, OtherParams const& other, int red, int blue)
727 for (int ty = target.start_y, oy = other.start_y; ty < target.size.height && oy < other.size.height; ++ty, ++oy) {
728 uint8_t* tp = target.line_pointer(ty);
729 uint8_t* op = other.line_pointer(oy);
730 for (int tx = target.start_x, ox = other.start_x; tx < target.size.width && ox < other.size.width; ++tx, ++ox) {
731 float const alpha = float (op[3]) / 255;
732 /* Blend high bytes */
733 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
734 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
735 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
746 alpha_blend_onto_xyz12le(TargetParams const& target, OtherParams const& other, int red, int blue)
748 auto conv = dcp::ColourConversion::srgb_to_xyz();
749 double fast_matrix[9];
750 dcp::combined_rgb_to_xyz(conv, fast_matrix);
751 auto lut_in = conv.in()->lut(0, 1, 8, false);
752 auto lut_out = conv.out()->lut(0, 1, 16, true);
753 for (int ty = target.start_y, oy = other.start_y; ty < target.size.height && oy < other.size.height; ++ty, ++oy) {
754 uint16_t* tp = reinterpret_cast<uint16_t*>(target.data[0] + ty * target.stride[0] + target.start_x * target.bpp);
755 uint8_t* op = other.data[0] + oy * other.stride[0];
756 for (int tx = target.start_x, ox = other.start_x; tx < target.size.width && ox < other.size.width; ++tx, ++ox) {
757 float const alpha = float (op[3]) / 255;
759 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
760 double const r = lut_in[op[red]];
761 double const g = lut_in[op[1]];
762 double const b = lut_in[op[blue]];
764 /* RGB to XYZ, including Bradford transform and DCI companding */
765 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
766 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
767 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
769 /* Out gamma LUT and blend */
770 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
771 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
772 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
774 tp += target.bpp / 2;
783 alpha_blend_onto_yuv420p(TargetParams const& target, OtherParams const& other, uint8_t* const* alpha_data, int const* alpha_stride)
785 auto const ts = target.size;
786 auto const os = other.size;
787 for (int ty = target.start_y, oy = other.start_y; ty < ts.height && oy < os.height; ++ty, ++oy) {
788 int const hty = ty / 2;
789 int const hoy = oy / 2;
790 uint8_t* tY = target.data[0] + (ty * target.stride[0]) + target.start_x;
791 uint8_t* tU = target.data[1] + (hty * target.stride[1]) + target.start_x / 2;
792 uint8_t* tV = target.data[2] + (hty * target.stride[2]) + target.start_x / 2;
793 uint8_t* oY = other.data[0] + (oy * other.stride[0]) + other.start_x;
794 uint8_t* oU = other.data[1] + (hoy * other.stride[1]) + other.start_x / 2;
795 uint8_t* oV = other.data[2] + (hoy * other.stride[2]) + other.start_x / 2;
796 uint8_t* alpha = alpha_data[0] + (oy * alpha_stride[0]) + other.start_x * 4;
797 for (int tx = target.start_x, ox = other.start_x; tx < ts.width && ox < os.width; ++tx, ++ox) {
798 float const a = float(alpha[3]) / 255;
799 *tY = *oY * a + *tY * (1 - a);
800 *tU = *oU * a + *tU * (1 - a);
801 *tV = *oV * a + *tV * (1 - a);
820 alpha_blend_onto_yuv420p10(TargetParams const& target, OtherParams const& other, uint8_t* const* alpha_data, int const* alpha_stride)
822 auto const ts = target.size;
823 auto const os = other.size;
824 for (int ty = target.start_y, oy = other.start_y; ty < ts.height && oy < os.height; ++ty, ++oy) {
825 int const hty = ty / 2;
826 int const hoy = oy / 2;
827 uint16_t* tY = reinterpret_cast<uint16_t*>(target.data[0] + (ty * target.stride[0])) + target.start_x;
828 uint16_t* tU = reinterpret_cast<uint16_t*>(target.data[1] + (hty * target.stride[1])) + target.start_x / 2;
829 uint16_t* tV = reinterpret_cast<uint16_t*>(target.data[2] + (hty * target.stride[2])) + target.start_x / 2;
830 uint16_t* oY = reinterpret_cast<uint16_t*>(other.data[0] + (oy * other.stride[0])) + other.start_x;
831 uint16_t* oU = reinterpret_cast<uint16_t*>(other.data[1] + (hoy * other.stride[1])) + other.start_x / 2;
832 uint16_t* oV = reinterpret_cast<uint16_t*>(other.data[2] + (hoy * other.stride[2])) + other.start_x / 2;
833 uint8_t* alpha = alpha_data[0] + (oy * alpha_stride[0]) + other.start_x * 4;
834 for (int tx = target.start_x, ox = other.start_x; tx < ts.width && ox < os.width; ++tx, ++ox) {
835 float const a = float(alpha[3]) / 255;
836 *tY = *oY * a + *tY * (1 - a);
837 *tU = *oU * a + *tU * (1 - a);
838 *tV = *oV * a + *tV * (1 - a);
857 alpha_blend_onto_yuv422p10le(TargetParams const& target, OtherParams const& other, uint8_t* const* alpha_data, int const* alpha_stride)
859 auto const ts = target.size;
860 auto const os = other.size;
861 for (int ty = target.start_y, oy = other.start_y; ty < ts.height && oy < os.height; ++ty, ++oy) {
862 uint16_t* tY = reinterpret_cast<uint16_t*>(target.data[0] + (ty * target.stride[0])) + target.start_x;
863 uint16_t* tU = reinterpret_cast<uint16_t*>(target.data[1] + (ty * target.stride[1])) + target.start_x / 2;
864 uint16_t* tV = reinterpret_cast<uint16_t*>(target.data[2] + (ty * target.stride[2])) + target.start_x / 2;
865 uint16_t* oY = reinterpret_cast<uint16_t*>(other.data[0] + (oy * other.stride[0])) + other.start_x;
866 uint16_t* oU = reinterpret_cast<uint16_t*>(other.data[1] + (oy * other.stride[1])) + other.start_x / 2;
867 uint16_t* oV = reinterpret_cast<uint16_t*>(other.data[2] + (oy * other.stride[2])) + other.start_x / 2;
868 uint8_t* alpha = alpha_data[0] + (oy * alpha_stride[0]) + other.start_x * 4;
869 for (int tx = target.start_x, ox = other.start_x; tx < ts.width && ox < os.width; ++tx, ++ox) {
870 float const a = float(alpha[3]) / 255;
871 *tY = *oY * a + *tY * (1 - a);
872 *tU = *oU * a + *tU * (1 - a);
873 *tV = *oV * a + *tV * (1 - a);
891 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
893 /* We're blending RGBA or BGRA images */
894 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
895 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
896 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
898 int start_tx = position.x;
902 start_ox = -start_tx;
906 int start_ty = position.y;
910 start_oy = -start_ty;
914 TargetParams target_params = {
923 OtherParams other_params = {
932 switch (_pixel_format) {
933 case AV_PIX_FMT_RGB24:
934 target_params.bpp = 3;
935 alpha_blend_onto_rgb24(target_params, other_params, red, blue);
937 case AV_PIX_FMT_BGRA:
938 target_params.bpp = 4;
939 alpha_blend_onto_bgra(target_params, other_params, red, blue);
941 case AV_PIX_FMT_RGBA:
942 target_params.bpp = 4;
943 alpha_blend_onto_rgba(target_params, other_params, red, blue);
945 case AV_PIX_FMT_RGB48LE:
946 target_params.bpp = 6;
947 alpha_blend_onto_rgb48le(target_params, other_params, red, blue);
949 case AV_PIX_FMT_XYZ12LE:
950 target_params.bpp = 6;
951 alpha_blend_onto_xyz12le(target_params, other_params, red, blue);
953 case AV_PIX_FMT_YUV420P:
955 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
956 other_params.data = yuv->data();
957 other_params.stride = yuv->stride();
958 alpha_blend_onto_yuv420p(target_params, other_params, other->data(), other->stride());
961 case AV_PIX_FMT_YUV420P10:
963 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
964 other_params.data = yuv->data();
965 other_params.stride = yuv->stride();
966 alpha_blend_onto_yuv420p10(target_params, other_params, other->data(), other->stride());
969 case AV_PIX_FMT_YUV422P10LE:
971 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
972 other_params.data = yuv->data();
973 other_params.stride = yuv->stride();
974 alpha_blend_onto_yuv422p10le(target_params, other_params, other->data(), other->stride());
978 throw PixelFormatError ("alpha_blend()", _pixel_format);
984 Image::copy (shared_ptr<const Image> other, Position<int> position)
986 /* Only implemented for RGB24 onto RGB24 so far */
987 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
988 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
990 int const N = min (position.x + other->size().width, size().width) - position.x;
991 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
992 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
993 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
994 memcpy (tp, op, N * 3);
1000 Image::read_from_socket (shared_ptr<Socket> socket)
1002 for (int i = 0; i < planes(); ++i) {
1003 uint8_t* p = data()[i];
1004 int const lines = sample_size(i).height;
1005 for (int y = 0; y < lines; ++y) {
1006 socket->read (p, line_size()[i]);
1014 Image::write_to_socket (shared_ptr<Socket> socket) const
1016 for (int i = 0; i < planes(); ++i) {
1017 uint8_t* p = data()[i];
1018 int const lines = sample_size(i).height;
1019 for (int y = 0; y < lines; ++y) {
1020 socket->write (p, line_size()[i]);
1028 Image::bytes_per_pixel (int c) const
1030 auto d = av_pix_fmt_desc_get(_pixel_format);
1032 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
1035 if (c >= planes()) {
1039 float bpp[4] = { 0, 0, 0, 0 };
1041 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
1042 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
1043 if (d->nb_components > 1) {
1044 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
1046 if (d->nb_components > 2) {
1047 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
1049 if (d->nb_components > 3) {
1050 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
1053 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
1054 if (d->nb_components > 1) {
1055 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
1057 if (d->nb_components > 2) {
1058 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
1060 if (d->nb_components > 3) {
1061 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
1065 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
1066 /* Not planar; sum them up */
1067 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
1074 /** Construct a Image of a given size and format, allocating memory
1077 * @param p Pixel format.
1078 * @param s Size in pixels.
1079 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
1081 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
1084 , _alignment (alignment)
1093 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
1094 _data[0] = _data[1] = _data[2] = _data[3] = 0;
1096 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
1097 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
1099 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
1100 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
1102 auto stride_round_up = [](int stride, int t) {
1103 int const a = stride + (t - 1);
1107 for (int i = 0; i < planes(); ++i) {
1108 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
1109 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
1111 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
1112 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
1113 Hence on the last pixel of the last line it reads over the end of
1114 the actual data by 1 byte. If the width of an image is a multiple
1115 of the stride alignment there will be no padding at the end of image lines.
1116 OS X crashes on this illegal read, though other operating systems don't
1117 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
1118 for that instruction to read safely.
1120 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
1121 over-reads by more then _avx. I can't follow the code to work out how much,
1122 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1123 testing suggests that it works.
1125 In addition to these concerns, we may read/write as much as a whole extra line
1126 at the end of each plane in cases where we are messing with offsets in order to
1127 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1129 As an example: we may write to images starting at an offset so we get some padding.
1130 Hence we want to write in the following pattern:
1132 block start write start line end
1133 |..(padding)..|<------line-size------------->|..(padding)..|
1134 |..(padding)..|<------line-size------------->|..(padding)..|
1135 |..(padding)..|<------line-size------------->|..(padding)..|
1137 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1138 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1139 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1140 specified *stride*. This does not matter until we get to the last line:
1142 block start write start line end
1143 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1144 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1145 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1148 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1149 #if HAVE_VALGRIND_MEMCHECK_H
1150 /* The data between the end of the line size and the stride is undefined but processed by
1151 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1153 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1159 Image::Image (Image const & other)
1160 : std::enable_shared_from_this<Image>(other)
1161 , _size (other._size)
1162 , _pixel_format (other._pixel_format)
1163 , _alignment (other._alignment)
1167 for (int i = 0; i < planes(); ++i) {
1168 uint8_t* p = _data[i];
1169 uint8_t* q = other._data[i];
1170 int const lines = sample_size(i).height;
1171 for (int j = 0; j < lines; ++j) {
1172 memcpy (p, q, _line_size[i]);
1174 q += other.stride()[i];
1180 Image::Image (AVFrame const * frame, Alignment alignment)
1181 : _size (frame->width, frame->height)
1182 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1183 , _alignment (alignment)
1185 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1189 for (int i = 0; i < planes(); ++i) {
1190 uint8_t* p = _data[i];
1191 uint8_t* q = frame->data[i];
1192 int const lines = sample_size(i).height;
1193 for (int j = 0; j < lines; ++j) {
1194 memcpy (p, q, _line_size[i]);
1196 /* AVFrame's linesize is what we call `stride' */
1197 q += frame->linesize[i];
1203 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1204 : _size (other->_size)
1205 , _pixel_format (other->_pixel_format)
1206 , _alignment (alignment)
1210 for (int i = 0; i < planes(); ++i) {
1211 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1212 uint8_t* p = _data[i];
1213 uint8_t* q = other->data()[i];
1214 int const lines = sample_size(i).height;
1215 for (int j = 0; j < lines; ++j) {
1216 memcpy (p, q, line_size()[i]);
1218 q += other->stride()[i];
1225 Image::operator= (Image const & other)
1227 if (this == &other) {
1238 Image::swap (Image & other)
1240 std::swap (_size, other._size);
1241 std::swap (_pixel_format, other._pixel_format);
1243 for (int i = 0; i < 4; ++i) {
1244 std::swap (_data[i], other._data[i]);
1245 std::swap (_line_size[i], other._line_size[i]);
1246 std::swap (_stride[i], other._stride[i]);
1249 std::swap (_alignment, other._alignment);
1255 for (int i = 0; i < planes(); ++i) {
1260 av_free (_line_size);
1266 Image::data () const
1273 Image::line_size () const
1280 Image::stride () const
1287 Image::size () const
1294 Image::alignment () const
1301 merge (list<PositionImage> images, Image::Alignment alignment)
1303 if (images.empty ()) {
1307 if (images.size() == 1) {
1308 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1309 return images.front();
1312 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1313 for (auto const& i: images) {
1314 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1317 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1318 merged->make_transparent ();
1319 for (auto const& i: images) {
1320 merged->alpha_blend (i.image, i.position - all.position());
1323 return PositionImage (merged, all.position ());
1328 operator== (Image const & a, Image const & b)
1330 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1334 for (int c = 0; c < a.planes(); ++c) {
1335 if (a.sample_size(c).height != b.sample_size(c).height || a.line_size()[c] != b.line_size()[c] || a.stride()[c] != b.stride()[c]) {
1339 uint8_t* p = a.data()[c];
1340 uint8_t* q = b.data()[c];
1341 int const lines = a.sample_size(c).height;
1342 for (int y = 0; y < lines; ++y) {
1343 if (memcmp (p, q, a.line_size()[c]) != 0) {
1357 * @param f Amount to fade by; 0 is black, 1 is no fade.
1360 Image::fade (float f)
1362 /* U/V black value for 8-bit colour */
1363 static int const eight_bit_uv = (1 << 7) - 1;
1364 /* U/V black value for 10-bit colour */
1365 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1367 switch (_pixel_format) {
1368 case AV_PIX_FMT_YUV420P:
1371 uint8_t* p = data()[0];
1372 int const lines = sample_size(0).height;
1373 for (int y = 0; y < lines; ++y) {
1375 for (int x = 0; x < line_size()[0]; ++x) {
1376 *q = int(float(*q) * f);
1383 for (int c = 1; c < 3; ++c) {
1384 uint8_t* p = data()[c];
1385 int const lines = sample_size(c).height;
1386 for (int y = 0; y < lines; ++y) {
1388 for (int x = 0; x < line_size()[c]; ++x) {
1389 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1399 case AV_PIX_FMT_RGB24:
1402 uint8_t* p = data()[0];
1403 int const lines = sample_size(0).height;
1404 for (int y = 0; y < lines; ++y) {
1406 for (int x = 0; x < line_size()[0]; ++x) {
1407 *q = int (float (*q) * f);
1415 case AV_PIX_FMT_XYZ12LE:
1416 case AV_PIX_FMT_RGB48LE:
1417 /* 16-bit little-endian */
1418 for (int c = 0; c < 3; ++c) {
1419 int const stride_pixels = stride()[c] / 2;
1420 int const line_size_pixels = line_size()[c] / 2;
1421 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1422 int const lines = sample_size(c).height;
1423 for (int y = 0; y < lines; ++y) {
1425 for (int x = 0; x < line_size_pixels; ++x) {
1426 *q = int (float (*q) * f);
1434 case AV_PIX_FMT_YUV422P10LE:
1438 int const stride_pixels = stride()[0] / 2;
1439 int const line_size_pixels = line_size()[0] / 2;
1440 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1441 int const lines = sample_size(0).height;
1442 for (int y = 0; y < lines; ++y) {
1444 for (int x = 0; x < line_size_pixels; ++x) {
1445 *q = int(float(*q) * f);
1453 for (int c = 1; c < 3; ++c) {
1454 int const stride_pixels = stride()[c] / 2;
1455 int const line_size_pixels = line_size()[c] / 2;
1456 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1457 int const lines = sample_size(c).height;
1458 for (int y = 0; y < lines; ++y) {
1460 for (int x = 0; x < line_size_pixels; ++x) {
1461 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1472 throw PixelFormatError ("fade()", _pixel_format);
1477 shared_ptr<const Image>
1478 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1480 if (image->alignment() == alignment) {
1484 return make_shared<Image>(image, alignment);
1489 Image::memory_used () const
1492 for (int i = 0; i < planes(); ++i) {
1493 m += _stride[i] * sample_size(i).height;
1500 Image::video_range_to_full_range ()
1502 switch (_pixel_format) {
1503 case AV_PIX_FMT_RGB24:
1505 float const factor = 256.0 / 219.0;
1506 uint8_t* p = data()[0];
1507 int const lines = sample_size(0).height;
1508 for (int y = 0; y < lines; ++y) {
1510 for (int x = 0; x < line_size()[0]; ++x) {
1511 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1518 case AV_PIX_FMT_RGB48LE:
1520 float const factor = 65536.0 / 56064.0;
1521 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1522 int const lines = sample_size(0).height;
1523 for (int y = 0; y < lines; ++y) {
1525 int const line_size_pixels = line_size()[0] / 2;
1526 for (int x = 0; x < line_size_pixels; ++x) {
1527 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1530 p += stride()[0] / 2;
1534 case AV_PIX_FMT_GBRP12LE:
1536 float const factor = 4096.0 / 3504.0;
1537 for (int c = 0; c < 3; ++c) {
1538 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1539 int const lines = sample_size(c).height;
1540 for (int y = 0; y < lines; ++y) {
1542 int const line_size_pixels = line_size()[c] / 2;
1543 for (int x = 0; x < line_size_pixels; ++x) {
1544 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1552 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);