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 "exceptions.h"
32 #include "maths_util.h"
33 #include "memory_util.h"
36 #include <dcp/rgb_xyz.h>
37 #include <dcp/transfer_function.h>
38 #include <dcp/warnings.h>
39 LIBDCP_DISABLE_WARNINGS
41 #include <libavutil/frame.h>
42 #include <libavutil/pixdesc.h>
43 #include <libavutil/pixfmt.h>
44 #include <libswscale/swscale.h>
46 LIBDCP_ENABLE_WARNINGS
47 #if HAVE_VALGRIND_MEMCHECK_H
48 #include <valgrind/memcheck.h>
59 using std::make_shared;
62 using std::runtime_error;
63 using std::shared_ptr;
68 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
69 int constexpr ALIGNMENT = 64;
71 /* U/V black value for 8-bit colour */
72 static uint8_t const eight_bit_uv = (1 << 7) - 1;
73 /* U/V black value for 9-bit colour */
74 static uint16_t const nine_bit_uv = (1 << 8) - 1;
75 /* U/V black value for 10-bit colour */
76 static uint16_t const ten_bit_uv = (1 << 9) - 1;
77 /* U/V black value for 16-bit colour */
78 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
82 Image::vertical_factor (int n) const
88 auto d = av_pix_fmt_desc_get(_pixel_format);
90 throw PixelFormatError ("line_factor()", _pixel_format);
93 return lrintf(powf(2.0f, d->log2_chroma_h));
97 Image::horizontal_factor (int n) const
103 auto d = av_pix_fmt_desc_get(_pixel_format);
105 throw PixelFormatError ("sample_size()", _pixel_format);
108 return lrintf(powf(2.0f, d->log2_chroma_w));
112 /** @param n Component index.
113 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
116 Image::sample_size (int n) const
119 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
120 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
125 /** @return Number of planes */
127 Image::planes () const
129 if (_pixel_format == AV_PIX_FMT_PAL8) {
133 auto d = av_pix_fmt_desc_get(_pixel_format);
135 throw PixelFormatError ("planes()", _pixel_format);
138 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
142 return d->nb_components;
148 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
150 return p & ~ ((1 << desc->log2_chroma_w) - 1);
156 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
158 return p & ~ ((1 << desc->log2_chroma_h) - 1);
162 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
163 * @param crop Amount to crop by.
164 * @param inter_size Size to scale the cropped image to.
165 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
166 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
167 * @param video_range Video range of the image.
168 * @param out_format Output pixel format.
169 * @param out_aligned true to make the output image aligned.
170 * @param out_video_range Video range to use for the output image.
171 * @param fast Try to be fast at the possible expense of quality; at present this means using
172 * fast bilinear rather than bicubic scaling.
175 Image::crop_scale_window (
177 dcp::Size inter_size,
179 dcp::YUVToRGB yuv_to_rgb,
180 VideoRange video_range,
181 AVPixelFormat out_format,
182 VideoRange out_video_range,
183 Alignment out_alignment,
187 /* Empirical testing suggests that sws_scale() will crash if
188 the input image is not padded.
190 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
192 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
193 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
195 auto out = make_shared<Image>(out_format, out_size, out_alignment);
198 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
200 throw PixelFormatError ("crop_scale_window()", _pixel_format);
203 /* Round down so that we crop only the number of pixels that is straightforward
204 * considering any subsampling.
207 round_width_for_subsampling(crop.left, in_desc),
208 round_width_for_subsampling(crop.right, in_desc),
209 round_height_for_subsampling(crop.top, in_desc),
210 round_height_for_subsampling(crop.bottom, in_desc)
213 /* Also check that we aren't cropping more image than there actually is */
214 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
215 corrected_crop.left = 0;
216 corrected_crop.right = size().width - 4;
219 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
220 corrected_crop.top = 0;
221 corrected_crop.bottom = size().height - 4;
224 /* Size of the image after any crop */
225 auto const cropped_size = corrected_crop.apply (size());
227 /* Scale context for a scale from cropped_size to inter_size */
228 auto scale_context = sws_getContext (
229 cropped_size.width, cropped_size.height, pixel_format(),
230 inter_size.width, inter_size.height, out_format,
231 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
234 if (!scale_context) {
235 throw runtime_error (N_("Could not allocate SwsContext"));
238 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
239 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
244 /* The 3rd parameter here is:
245 0 -> source range MPEG (i.e. "video", 16-235)
246 1 -> source range JPEG (i.e. "full", 0-255)
248 0 -> destination range MPEG (i.e. "video", 16-235)
249 1 -> destination range JPEG (i.e. "full", 0-255)
251 But remember: sws_setColorspaceDetails ignores these
252 parameters unless both source and destination images
253 are isYUV or isGray. (If either is not, it uses video range).
255 sws_setColorspaceDetails (
257 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
258 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
262 /* Prepare input data pointers with crop */
263 uint8_t* scale_in_data[planes()];
264 for (int c = 0; c < planes(); ++c) {
265 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
266 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
269 auto out_desc = av_pix_fmt_desc_get (out_format);
271 throw PixelFormatError ("crop_scale_window()", out_format);
274 /* Corner of the image within out_size */
275 Position<int> const corner (
276 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
277 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
280 uint8_t* scale_out_data[out->planes()];
281 for (int c = 0; c < out->planes(); ++c) {
282 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
283 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
288 scale_in_data, stride(),
289 0, cropped_size.height,
290 scale_out_data, out->stride()
293 sws_freeContext (scale_context);
295 /* There are some cases where there will be unwanted image data left in the image at this point:
297 * 1. When we are cropping without any scaling or pixel format conversion.
298 * 2. When we are scaling to certain sizes and placing the result into a larger
301 * Clear out the sides of the image to take care of those cases.
303 auto const pad = (out_size.width - inter_size.width) / 2;
304 out->make_part_black(0, pad);
305 out->make_part_black(corner.x + inter_size.width, pad);
308 video_range == VideoRange::VIDEO &&
309 out_video_range == VideoRange::FULL &&
310 ((av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB) ||
311 (av_pix_fmt_desc_get(out_format)->flags & AV_PIX_FMT_FLAG_RGB))
313 /* libswscale will not convert video range if input or output is RGB, as far as I can see,
314 * so we have to do it ourselves.
316 out->video_range_to_full_range ();
324 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
326 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
330 /** @param out_size Size to scale to.
331 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
332 * @param out_format Output pixel format.
333 * @param out_aligment Output alignment.
334 * @param fast Try to be fast at the possible expense of quality; at present this means using
335 * fast bilinear rather than bicubic scaling.
338 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
340 /* Empirical testing suggests that sws_scale() will crash if
341 the input image alignment is not PADDED.
343 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
345 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
346 auto scale_context = sws_getContext (
347 size().width, size().height, pixel_format(),
348 out_size.width, out_size.height, out_format,
349 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
352 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
353 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
358 /* The 3rd parameter here is:
359 0 -> source range MPEG (i.e. "video", 16-235)
360 1 -> source range JPEG (i.e. "full", 0-255)
362 0 -> destination range MPEG (i.e. "video", 16-235)
363 1 -> destination range JPEG (i.e. "full", 0-255)
365 But remember: sws_setColorspaceDetails ignores these
366 parameters unless the corresponding image isYUV or isGray.
367 (If it's neither, it uses video range).
369 sws_setColorspaceDetails (
371 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
372 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
380 scaled->data(), scaled->stride()
383 sws_freeContext (scale_context);
389 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
391 Image::yuv_16_black (uint16_t v, bool alpha)
393 memset (data()[0], 0, sample_size(0).height * stride()[0]);
394 for (int i = 1; i < 3; ++i) {
395 auto p = reinterpret_cast<int16_t*> (data()[i]);
396 int const lines = sample_size(i).height;
397 for (int y = 0; y < lines; ++y) {
398 /* We divide by 2 here because we are writing 2 bytes at a time */
399 for (int x = 0; x < line_size()[i] / 2; ++x) {
402 p += stride()[i] / 2;
407 memset (data()[3], 0, sample_size(3).height * stride()[3]);
413 Image::swap_16 (uint16_t v)
415 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
420 Image::make_part_black (int const start, int const width)
422 auto y_part = [&]() {
423 int const bpp = bytes_per_pixel(0);
424 int const h = sample_size(0).height;
425 int const s = stride()[0];
427 for (int y = 0; y < h; ++y) {
428 memset (p + start * bpp, 0, width * bpp);
433 switch (_pixel_format) {
434 case AV_PIX_FMT_RGB24:
435 case AV_PIX_FMT_ARGB:
436 case AV_PIX_FMT_RGBA:
437 case AV_PIX_FMT_ABGR:
438 case AV_PIX_FMT_BGRA:
439 case AV_PIX_FMT_RGB555LE:
440 case AV_PIX_FMT_RGB48LE:
441 case AV_PIX_FMT_RGB48BE:
442 case AV_PIX_FMT_XYZ12LE:
444 int const h = sample_size(0).height;
445 int const bpp = bytes_per_pixel(0);
446 int const s = stride()[0];
447 uint8_t* p = data()[0];
448 for (int y = 0; y < h; y++) {
449 memset (p + start * bpp, 0, width * bpp);
454 case AV_PIX_FMT_YUV420P:
457 for (int i = 1; i < 3; ++i) {
459 int const h = sample_size(i).height;
460 for (int y = 0; y < h; ++y) {
461 for (int x = start / 2; x < (start + width) / 2; ++x) {
469 case AV_PIX_FMT_YUV422P10LE:
472 for (int i = 1; i < 3; ++i) {
473 auto p = reinterpret_cast<int16_t*>(data()[i]);
474 int const h = sample_size(i).height;
475 for (int y = 0; y < h; ++y) {
476 for (int x = start / 2; x < (start + width) / 2; ++x) {
479 p += stride()[i] / 2;
485 throw PixelFormatError ("make_part_black()", _pixel_format);
493 switch (_pixel_format) {
494 case AV_PIX_FMT_YUV420P:
495 case AV_PIX_FMT_YUV422P:
496 case AV_PIX_FMT_YUV444P:
497 case AV_PIX_FMT_YUV411P:
498 memset (data()[0], 0, sample_size(0).height * stride()[0]);
499 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
500 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
503 case AV_PIX_FMT_YUVJ420P:
504 case AV_PIX_FMT_YUVJ422P:
505 case AV_PIX_FMT_YUVJ444P:
506 memset (data()[0], 0, sample_size(0).height * stride()[0]);
507 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
508 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
511 case AV_PIX_FMT_YUV422P9LE:
512 case AV_PIX_FMT_YUV444P9LE:
513 yuv_16_black (nine_bit_uv, false);
516 case AV_PIX_FMT_YUV422P9BE:
517 case AV_PIX_FMT_YUV444P9BE:
518 yuv_16_black (swap_16 (nine_bit_uv), false);
521 case AV_PIX_FMT_YUV422P10LE:
522 case AV_PIX_FMT_YUV444P10LE:
523 yuv_16_black (ten_bit_uv, false);
526 case AV_PIX_FMT_YUV422P16LE:
527 case AV_PIX_FMT_YUV444P16LE:
528 yuv_16_black (sixteen_bit_uv, false);
531 case AV_PIX_FMT_YUV444P10BE:
532 case AV_PIX_FMT_YUV422P10BE:
533 yuv_16_black (swap_16 (ten_bit_uv), false);
536 case AV_PIX_FMT_YUVA420P9BE:
537 case AV_PIX_FMT_YUVA422P9BE:
538 case AV_PIX_FMT_YUVA444P9BE:
539 yuv_16_black (swap_16 (nine_bit_uv), true);
542 case AV_PIX_FMT_YUVA420P9LE:
543 case AV_PIX_FMT_YUVA422P9LE:
544 case AV_PIX_FMT_YUVA444P9LE:
545 yuv_16_black (nine_bit_uv, true);
548 case AV_PIX_FMT_YUVA420P10BE:
549 case AV_PIX_FMT_YUVA422P10BE:
550 case AV_PIX_FMT_YUVA444P10BE:
551 yuv_16_black (swap_16 (ten_bit_uv), true);
554 case AV_PIX_FMT_YUVA420P10LE:
555 case AV_PIX_FMT_YUVA422P10LE:
556 case AV_PIX_FMT_YUVA444P10LE:
557 yuv_16_black (ten_bit_uv, true);
560 case AV_PIX_FMT_YUVA420P16BE:
561 case AV_PIX_FMT_YUVA422P16BE:
562 case AV_PIX_FMT_YUVA444P16BE:
563 yuv_16_black (swap_16 (sixteen_bit_uv), true);
566 case AV_PIX_FMT_YUVA420P16LE:
567 case AV_PIX_FMT_YUVA422P16LE:
568 case AV_PIX_FMT_YUVA444P16LE:
569 yuv_16_black (sixteen_bit_uv, true);
572 case AV_PIX_FMT_RGB24:
573 case AV_PIX_FMT_ARGB:
574 case AV_PIX_FMT_RGBA:
575 case AV_PIX_FMT_ABGR:
576 case AV_PIX_FMT_BGRA:
577 case AV_PIX_FMT_RGB555LE:
578 case AV_PIX_FMT_RGB48LE:
579 case AV_PIX_FMT_RGB48BE:
580 case AV_PIX_FMT_XYZ12LE:
581 memset (data()[0], 0, sample_size(0).height * stride()[0]);
584 case AV_PIX_FMT_UYVY422:
586 int const Y = sample_size(0).height;
587 int const X = line_size()[0];
588 uint8_t* p = data()[0];
589 for (int y = 0; y < Y; ++y) {
590 for (int x = 0; x < X / 4; ++x) {
591 *p++ = eight_bit_uv; // Cb
593 *p++ = eight_bit_uv; // Cr
601 throw PixelFormatError ("make_black()", _pixel_format);
607 Image::make_transparent ()
609 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
610 throw PixelFormatError ("make_transparent()", _pixel_format);
613 memset (data()[0], 0, sample_size(0).height * stride()[0]);
618 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
620 /* We're blending RGBA or BGRA images */
621 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
622 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
623 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
625 int const other_bpp = 4;
627 int start_tx = position.x;
631 start_ox = -start_tx;
635 int start_ty = position.y;
639 start_oy = -start_ty;
643 switch (_pixel_format) {
644 case AV_PIX_FMT_RGB24:
646 /* Going onto RGB24. First byte is red, second green, third blue */
647 int const this_bpp = 3;
648 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
649 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
650 uint8_t* op = other->data()[0] + oy * other->stride()[0];
651 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
652 float const alpha = float (op[3]) / 255;
653 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
654 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
655 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
663 case AV_PIX_FMT_BGRA:
665 int const this_bpp = 4;
666 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
667 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
668 uint8_t* op = other->data()[0] + oy * other->stride()[0];
669 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
670 float const alpha = float (op[3]) / 255;
671 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
672 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
673 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
674 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
682 case AV_PIX_FMT_RGBA:
684 int const this_bpp = 4;
685 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
686 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
687 uint8_t* op = other->data()[0] + oy * other->stride()[0];
688 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
689 float const alpha = float (op[3]) / 255;
690 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
691 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
692 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
693 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
701 case AV_PIX_FMT_RGB48LE:
703 int const this_bpp = 6;
704 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
705 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
706 uint8_t* op = other->data()[0] + oy * other->stride()[0];
707 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
708 float const alpha = float (op[3]) / 255;
709 /* Blend high bytes */
710 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
711 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
712 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
720 case AV_PIX_FMT_XYZ12LE:
722 auto conv = dcp::ColourConversion::srgb_to_xyz();
723 double fast_matrix[9];
724 dcp::combined_rgb_to_xyz (conv, fast_matrix);
725 auto lut_in = conv.in()->lut(0, 1, 8, false);
726 auto lut_out = conv.out()->lut(0, 1, 16, true);
727 int const this_bpp = 6;
728 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
729 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
730 uint8_t* op = other->data()[0] + oy * other->stride()[0];
731 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
732 float const alpha = float (op[3]) / 255;
734 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
735 double const r = lut_in[op[red]];
736 double const g = lut_in[op[1]];
737 double const b = lut_in[op[blue]];
739 /* RGB to XYZ, including Bradford transform and DCI companding */
740 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
741 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
742 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
744 /* Out gamma LUT and blend */
745 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
746 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
747 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
755 case AV_PIX_FMT_YUV420P:
757 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
758 dcp::Size const ts = size();
759 dcp::Size const os = yuv->size();
760 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
761 int const hty = ty / 2;
762 int const hoy = oy / 2;
763 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
764 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
765 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
766 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
767 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
768 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
769 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
770 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
771 float const a = float(alpha[3]) / 255;
772 *tY = *oY * a + *tY * (1 - a);
773 *tU = *oU * a + *tU * (1 - a);
774 *tV = *oV * a + *tV * (1 - a);
790 case AV_PIX_FMT_YUV420P10:
792 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
793 dcp::Size const ts = size();
794 dcp::Size const os = yuv->size();
795 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
796 int const hty = ty / 2;
797 int const hoy = oy / 2;
798 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
799 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
800 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
801 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
802 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
803 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
804 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
805 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
806 float const a = float(alpha[3]) / 255;
807 *tY = *oY * a + *tY * (1 - a);
808 *tU = *oU * a + *tU * (1 - a);
809 *tV = *oV * a + *tV * (1 - a);
825 case AV_PIX_FMT_YUV422P10LE:
827 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
828 dcp::Size const ts = size();
829 dcp::Size const os = yuv->size();
830 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
831 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
832 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
833 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
834 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
835 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
836 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
837 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
838 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
839 float const a = float(alpha[3]) / 255;
840 *tY = *oY * a + *tY * (1 - a);
841 *tU = *oU * a + *tU * (1 - a);
842 *tV = *oV * a + *tV * (1 - a);
859 throw PixelFormatError ("alpha_blend()", _pixel_format);
865 Image::copy (shared_ptr<const Image> other, Position<int> position)
867 /* Only implemented for RGB24 onto RGB24 so far */
868 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
869 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
871 int const N = min (position.x + other->size().width, size().width) - position.x;
872 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
873 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
874 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
875 memcpy (tp, op, N * 3);
881 Image::read_from_socket (shared_ptr<Socket> socket)
883 for (int i = 0; i < planes(); ++i) {
884 uint8_t* p = data()[i];
885 int const lines = sample_size(i).height;
886 for (int y = 0; y < lines; ++y) {
887 socket->read (p, line_size()[i]);
895 Image::write_to_socket (shared_ptr<Socket> socket) const
897 for (int i = 0; i < planes(); ++i) {
898 uint8_t* p = data()[i];
899 int const lines = sample_size(i).height;
900 for (int y = 0; y < lines; ++y) {
901 socket->write (p, line_size()[i]);
909 Image::bytes_per_pixel (int c) const
911 auto d = av_pix_fmt_desc_get(_pixel_format);
913 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
920 float bpp[4] = { 0, 0, 0, 0 };
922 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
923 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
924 if (d->nb_components > 1) {
925 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
927 if (d->nb_components > 2) {
928 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
930 if (d->nb_components > 3) {
931 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
934 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
935 if (d->nb_components > 1) {
936 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
938 if (d->nb_components > 2) {
939 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
941 if (d->nb_components > 3) {
942 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
946 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
947 /* Not planar; sum them up */
948 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
955 /** Construct a Image of a given size and format, allocating memory
958 * @param p Pixel format.
959 * @param s Size in pixels.
960 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
962 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
965 , _alignment (alignment)
974 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
975 _data[0] = _data[1] = _data[2] = _data[3] = 0;
977 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
978 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
980 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
981 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
983 auto stride_round_up = [](int stride, int t) {
984 int const a = stride + (t - 1);
988 for (int i = 0; i < planes(); ++i) {
989 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
990 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
992 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
993 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
994 Hence on the last pixel of the last line it reads over the end of
995 the actual data by 1 byte. If the width of an image is a multiple
996 of the stride alignment there will be no padding at the end of image lines.
997 OS X crashes on this illegal read, though other operating systems don't
998 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
999 for that instruction to read safely.
1001 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
1002 over-reads by more then _avx. I can't follow the code to work out how much,
1003 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1004 testing suggests that it works.
1006 In addition to these concerns, we may read/write as much as a whole extra line
1007 at the end of each plane in cases where we are messing with offsets in order to
1008 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1010 As an example: we may write to images starting at an offset so we get some padding.
1011 Hence we want to write in the following pattern:
1013 block start write start line end
1014 |..(padding)..|<------line-size------------->|..(padding)..|
1015 |..(padding)..|<------line-size------------->|..(padding)..|
1016 |..(padding)..|<------line-size------------->|..(padding)..|
1018 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1019 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1020 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1021 specified *stride*. This does not matter until we get to the last line:
1023 block start write start line end
1024 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1025 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1026 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1029 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1030 #if HAVE_VALGRIND_MEMCHECK_H
1031 /* The data between the end of the line size and the stride is undefined but processed by
1032 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1034 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1040 Image::Image (Image const & other)
1041 : std::enable_shared_from_this<Image>(other)
1042 , _size (other._size)
1043 , _pixel_format (other._pixel_format)
1044 , _alignment (other._alignment)
1048 for (int i = 0; i < planes(); ++i) {
1049 uint8_t* p = _data[i];
1050 uint8_t* q = other._data[i];
1051 int const lines = sample_size(i).height;
1052 for (int j = 0; j < lines; ++j) {
1053 memcpy (p, q, _line_size[i]);
1055 q += other.stride()[i];
1061 Image::Image (AVFrame const * frame, Alignment alignment)
1062 : _size (frame->width, frame->height)
1063 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1064 , _alignment (alignment)
1066 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1070 for (int i = 0; i < planes(); ++i) {
1071 uint8_t* p = _data[i];
1072 uint8_t* q = frame->data[i];
1073 int const lines = sample_size(i).height;
1074 for (int j = 0; j < lines; ++j) {
1075 memcpy (p, q, _line_size[i]);
1077 /* AVFrame's linesize is what we call `stride' */
1078 q += frame->linesize[i];
1084 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1085 : _size (other->_size)
1086 , _pixel_format (other->_pixel_format)
1087 , _alignment (alignment)
1091 for (int i = 0; i < planes(); ++i) {
1092 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1093 uint8_t* p = _data[i];
1094 uint8_t* q = other->data()[i];
1095 int const lines = sample_size(i).height;
1096 for (int j = 0; j < lines; ++j) {
1097 memcpy (p, q, line_size()[i]);
1099 q += other->stride()[i];
1106 Image::operator= (Image const & other)
1108 if (this == &other) {
1119 Image::swap (Image & other)
1121 std::swap (_size, other._size);
1122 std::swap (_pixel_format, other._pixel_format);
1124 for (int i = 0; i < 4; ++i) {
1125 std::swap (_data[i], other._data[i]);
1126 std::swap (_line_size[i], other._line_size[i]);
1127 std::swap (_stride[i], other._stride[i]);
1130 std::swap (_alignment, other._alignment);
1136 for (int i = 0; i < planes(); ++i) {
1141 av_free (_line_size);
1147 Image::data () const
1154 Image::line_size () const
1161 Image::stride () const
1168 Image::size () const
1175 Image::alignment () const
1182 merge (list<PositionImage> images, Image::Alignment alignment)
1184 if (images.empty ()) {
1188 if (images.size() == 1) {
1189 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1190 return images.front();
1193 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1194 for (auto const& i: images) {
1195 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1198 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1199 merged->make_transparent ();
1200 for (auto const& i: images) {
1201 merged->alpha_blend (i.image, i.position - all.position());
1204 return PositionImage (merged, all.position ());
1209 operator== (Image const & a, Image const & b)
1211 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1215 for (int c = 0; c < a.planes(); ++c) {
1216 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]) {
1220 uint8_t* p = a.data()[c];
1221 uint8_t* q = b.data()[c];
1222 int const lines = a.sample_size(c).height;
1223 for (int y = 0; y < lines; ++y) {
1224 if (memcmp (p, q, a.line_size()[c]) != 0) {
1238 * @param f Amount to fade by; 0 is black, 1 is no fade.
1241 Image::fade (float f)
1243 /* U/V black value for 8-bit colour */
1244 static int const eight_bit_uv = (1 << 7) - 1;
1245 /* U/V black value for 10-bit colour */
1246 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1248 switch (_pixel_format) {
1249 case AV_PIX_FMT_YUV420P:
1252 uint8_t* p = data()[0];
1253 int const lines = sample_size(0).height;
1254 for (int y = 0; y < lines; ++y) {
1256 for (int x = 0; x < line_size()[0]; ++x) {
1257 *q = int(float(*q) * f);
1264 for (int c = 1; c < 3; ++c) {
1265 uint8_t* p = data()[c];
1266 int const lines = sample_size(c).height;
1267 for (int y = 0; y < lines; ++y) {
1269 for (int x = 0; x < line_size()[c]; ++x) {
1270 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1280 case AV_PIX_FMT_RGB24:
1283 uint8_t* p = data()[0];
1284 int const lines = sample_size(0).height;
1285 for (int y = 0; y < lines; ++y) {
1287 for (int x = 0; x < line_size()[0]; ++x) {
1288 *q = int (float (*q) * f);
1296 case AV_PIX_FMT_XYZ12LE:
1297 case AV_PIX_FMT_RGB48LE:
1298 /* 16-bit little-endian */
1299 for (int c = 0; c < 3; ++c) {
1300 int const stride_pixels = stride()[c] / 2;
1301 int const line_size_pixels = line_size()[c] / 2;
1302 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1303 int const lines = sample_size(c).height;
1304 for (int y = 0; y < lines; ++y) {
1306 for (int x = 0; x < line_size_pixels; ++x) {
1307 *q = int (float (*q) * f);
1315 case AV_PIX_FMT_YUV422P10LE:
1319 int const stride_pixels = stride()[0] / 2;
1320 int const line_size_pixels = line_size()[0] / 2;
1321 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1322 int const lines = sample_size(0).height;
1323 for (int y = 0; y < lines; ++y) {
1325 for (int x = 0; x < line_size_pixels; ++x) {
1326 *q = int(float(*q) * f);
1334 for (int c = 1; c < 3; ++c) {
1335 int const stride_pixels = stride()[c] / 2;
1336 int const line_size_pixels = line_size()[c] / 2;
1337 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1338 int const lines = sample_size(c).height;
1339 for (int y = 0; y < lines; ++y) {
1341 for (int x = 0; x < line_size_pixels; ++x) {
1342 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1353 throw PixelFormatError ("fade()", _pixel_format);
1358 shared_ptr<const Image>
1359 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1361 if (image->alignment() == alignment) {
1365 return make_shared<Image>(image, alignment);
1370 Image::memory_used () const
1373 for (int i = 0; i < planes(); ++i) {
1374 m += _stride[i] * sample_size(i).height;
1381 Image::video_range_to_full_range ()
1383 switch (_pixel_format) {
1384 case AV_PIX_FMT_RGB24:
1386 float const factor = 256.0 / 219.0;
1387 uint8_t* p = data()[0];
1388 int const lines = sample_size(0).height;
1389 for (int y = 0; y < lines; ++y) {
1391 for (int x = 0; x < line_size()[0]; ++x) {
1392 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1399 case AV_PIX_FMT_RGB48LE:
1401 float const factor = 65536.0 / 56064.0;
1402 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1403 int const lines = sample_size(0).height;
1404 for (int y = 0; y < lines; ++y) {
1406 int const line_size_pixels = line_size()[0] / 2;
1407 for (int x = 0; x < line_size_pixels; ++x) {
1408 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1411 p += stride()[0] / 2;
1415 case AV_PIX_FMT_GBRP12LE:
1417 float const factor = 4096.0 / 3504.0;
1418 for (int c = 0; c < 3; ++c) {
1419 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1420 int const lines = sample_size(c).height;
1421 for (int y = 0; y < lines; ++y) {
1423 int const line_size_pixels = line_size()[c] / 2;
1424 for (int x = 0; x < line_size_pixels; ++x) {
1425 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1433 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);