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 the 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
312 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
313 out->video_range_to_full_range ();
321 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
323 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
327 /** @param out_size Size to scale to.
328 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
329 * @param out_format Output pixel format.
330 * @param out_aligment Output alignment.
331 * @param fast Try to be fast at the possible expense of quality; at present this means using
332 * fast bilinear rather than bicubic scaling.
335 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
337 /* Empirical testing suggests that sws_scale() will crash if
338 the input image alignment is not PADDED.
340 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
342 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
343 auto scale_context = sws_getContext (
344 size().width, size().height, pixel_format(),
345 out_size.width, out_size.height, out_format,
346 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
349 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
350 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
355 /* The 3rd parameter here is:
356 0 -> source range MPEG (i.e. "video", 16-235)
357 1 -> source range JPEG (i.e. "full", 0-255)
359 0 -> destination range MPEG (i.e. "video", 16-235)
360 1 -> destination range JPEG (i.e. "full", 0-255)
362 But remember: sws_setColorspaceDetails ignores these
363 parameters unless the corresponding image isYUV or isGray.
364 (If it's neither, it uses video range).
366 sws_setColorspaceDetails (
368 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
369 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
377 scaled->data(), scaled->stride()
380 sws_freeContext (scale_context);
386 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
388 Image::yuv_16_black (uint16_t v, bool alpha)
390 memset (data()[0], 0, sample_size(0).height * stride()[0]);
391 for (int i = 1; i < 3; ++i) {
392 auto p = reinterpret_cast<int16_t*> (data()[i]);
393 int const lines = sample_size(i).height;
394 for (int y = 0; y < lines; ++y) {
395 /* We divide by 2 here because we are writing 2 bytes at a time */
396 for (int x = 0; x < line_size()[i] / 2; ++x) {
399 p += stride()[i] / 2;
404 memset (data()[3], 0, sample_size(3).height * stride()[3]);
410 Image::swap_16 (uint16_t v)
412 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
417 Image::make_part_black (int const start, int const width)
419 auto y_part = [&]() {
420 int const bpp = bytes_per_pixel(0);
421 int const h = sample_size(0).height;
422 int const s = stride()[0];
424 for (int y = 0; y < h; ++y) {
425 memset (p + start * bpp, 0, width * bpp);
430 switch (_pixel_format) {
431 case AV_PIX_FMT_RGB24:
432 case AV_PIX_FMT_ARGB:
433 case AV_PIX_FMT_RGBA:
434 case AV_PIX_FMT_ABGR:
435 case AV_PIX_FMT_BGRA:
436 case AV_PIX_FMT_RGB555LE:
437 case AV_PIX_FMT_RGB48LE:
438 case AV_PIX_FMT_RGB48BE:
439 case AV_PIX_FMT_XYZ12LE:
441 int const h = sample_size(0).height;
442 int const bpp = bytes_per_pixel(0);
443 int const s = stride()[0];
444 uint8_t* p = data()[0];
445 for (int y = 0; y < h; y++) {
446 memset (p + start * bpp, 0, width * bpp);
451 case AV_PIX_FMT_YUV420P:
454 for (int i = 1; i < 3; ++i) {
456 int const h = sample_size(i).height;
457 for (int y = 0; y < h; ++y) {
458 for (int x = start / 2; x < (start + width) / 2; ++x) {
466 case AV_PIX_FMT_YUV422P10LE:
469 for (int i = 1; i < 3; ++i) {
470 auto p = reinterpret_cast<int16_t*>(data()[i]);
471 int const h = sample_size(i).height;
472 for (int y = 0; y < h; ++y) {
473 for (int x = start / 2; x < (start + width) / 2; ++x) {
476 p += stride()[i] / 2;
482 throw PixelFormatError ("make_part_black()", _pixel_format);
490 switch (_pixel_format) {
491 case AV_PIX_FMT_YUV420P:
492 case AV_PIX_FMT_YUV422P:
493 case AV_PIX_FMT_YUV444P:
494 case AV_PIX_FMT_YUV411P:
495 memset (data()[0], 0, sample_size(0).height * stride()[0]);
496 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
497 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
500 case AV_PIX_FMT_YUVJ420P:
501 case AV_PIX_FMT_YUVJ422P:
502 case AV_PIX_FMT_YUVJ444P:
503 memset (data()[0], 0, sample_size(0).height * stride()[0]);
504 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
505 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
508 case AV_PIX_FMT_YUV422P9LE:
509 case AV_PIX_FMT_YUV444P9LE:
510 yuv_16_black (nine_bit_uv, false);
513 case AV_PIX_FMT_YUV422P9BE:
514 case AV_PIX_FMT_YUV444P9BE:
515 yuv_16_black (swap_16 (nine_bit_uv), false);
518 case AV_PIX_FMT_YUV422P10LE:
519 case AV_PIX_FMT_YUV444P10LE:
520 yuv_16_black (ten_bit_uv, false);
523 case AV_PIX_FMT_YUV422P16LE:
524 case AV_PIX_FMT_YUV444P16LE:
525 yuv_16_black (sixteen_bit_uv, false);
528 case AV_PIX_FMT_YUV444P10BE:
529 case AV_PIX_FMT_YUV422P10BE:
530 yuv_16_black (swap_16 (ten_bit_uv), false);
533 case AV_PIX_FMT_YUVA420P9BE:
534 case AV_PIX_FMT_YUVA422P9BE:
535 case AV_PIX_FMT_YUVA444P9BE:
536 yuv_16_black (swap_16 (nine_bit_uv), true);
539 case AV_PIX_FMT_YUVA420P9LE:
540 case AV_PIX_FMT_YUVA422P9LE:
541 case AV_PIX_FMT_YUVA444P9LE:
542 yuv_16_black (nine_bit_uv, true);
545 case AV_PIX_FMT_YUVA420P10BE:
546 case AV_PIX_FMT_YUVA422P10BE:
547 case AV_PIX_FMT_YUVA444P10BE:
548 yuv_16_black (swap_16 (ten_bit_uv), true);
551 case AV_PIX_FMT_YUVA420P10LE:
552 case AV_PIX_FMT_YUVA422P10LE:
553 case AV_PIX_FMT_YUVA444P10LE:
554 yuv_16_black (ten_bit_uv, true);
557 case AV_PIX_FMT_YUVA420P16BE:
558 case AV_PIX_FMT_YUVA422P16BE:
559 case AV_PIX_FMT_YUVA444P16BE:
560 yuv_16_black (swap_16 (sixteen_bit_uv), true);
563 case AV_PIX_FMT_YUVA420P16LE:
564 case AV_PIX_FMT_YUVA422P16LE:
565 case AV_PIX_FMT_YUVA444P16LE:
566 yuv_16_black (sixteen_bit_uv, true);
569 case AV_PIX_FMT_RGB24:
570 case AV_PIX_FMT_ARGB:
571 case AV_PIX_FMT_RGBA:
572 case AV_PIX_FMT_ABGR:
573 case AV_PIX_FMT_BGRA:
574 case AV_PIX_FMT_RGB555LE:
575 case AV_PIX_FMT_RGB48LE:
576 case AV_PIX_FMT_RGB48BE:
577 case AV_PIX_FMT_XYZ12LE:
578 memset (data()[0], 0, sample_size(0).height * stride()[0]);
581 case AV_PIX_FMT_UYVY422:
583 int const Y = sample_size(0).height;
584 int const X = line_size()[0];
585 uint8_t* p = data()[0];
586 for (int y = 0; y < Y; ++y) {
587 for (int x = 0; x < X / 4; ++x) {
588 *p++ = eight_bit_uv; // Cb
590 *p++ = eight_bit_uv; // Cr
598 throw PixelFormatError ("make_black()", _pixel_format);
604 Image::make_transparent ()
606 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
607 throw PixelFormatError ("make_transparent()", _pixel_format);
610 memset (data()[0], 0, sample_size(0).height * stride()[0]);
615 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
617 /* We're blending RGBA or BGRA images */
618 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
619 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
620 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
622 int const other_bpp = 4;
624 int start_tx = position.x;
628 start_ox = -start_tx;
632 int start_ty = position.y;
636 start_oy = -start_ty;
640 switch (_pixel_format) {
641 case AV_PIX_FMT_RGB24:
643 /* Going onto RGB24. First byte is red, second green, third blue */
644 int const this_bpp = 3;
645 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
646 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
647 uint8_t* op = other->data()[0] + oy * other->stride()[0];
648 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
649 float const alpha = float (op[3]) / 255;
650 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
651 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
652 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
660 case AV_PIX_FMT_BGRA:
662 int const this_bpp = 4;
663 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
664 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
665 uint8_t* op = other->data()[0] + oy * other->stride()[0];
666 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
667 float const alpha = float (op[3]) / 255;
668 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
669 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
670 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
671 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
679 case AV_PIX_FMT_RGBA:
681 int const this_bpp = 4;
682 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
683 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
684 uint8_t* op = other->data()[0] + oy * other->stride()[0];
685 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
686 float const alpha = float (op[3]) / 255;
687 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
688 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
689 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
690 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
698 case AV_PIX_FMT_RGB48LE:
700 int const this_bpp = 6;
701 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
702 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
703 uint8_t* op = other->data()[0] + oy * other->stride()[0];
704 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
705 float const alpha = float (op[3]) / 255;
706 /* Blend high bytes */
707 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
708 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
709 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
717 case AV_PIX_FMT_XYZ12LE:
719 auto conv = dcp::ColourConversion::srgb_to_xyz();
720 double fast_matrix[9];
721 dcp::combined_rgb_to_xyz (conv, fast_matrix);
722 auto lut_in = conv.in()->lut(0, 1, 8, false);
723 auto lut_out = conv.out()->lut(0, 1, 16, true);
724 int const this_bpp = 6;
725 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
726 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
727 uint8_t* op = other->data()[0] + oy * other->stride()[0];
728 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
729 float const alpha = float (op[3]) / 255;
731 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
732 double const r = lut_in[op[red]];
733 double const g = lut_in[op[1]];
734 double const b = lut_in[op[blue]];
736 /* RGB to XYZ, including Bradford transform and DCI companding */
737 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
738 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
739 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
741 /* Out gamma LUT and blend */
742 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
743 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
744 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
752 case AV_PIX_FMT_YUV420P:
754 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
755 dcp::Size const ts = size();
756 dcp::Size const os = yuv->size();
757 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
758 int const hty = ty / 2;
759 int const hoy = oy / 2;
760 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
761 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
762 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
763 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
764 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
765 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
766 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
767 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
768 float const a = float(alpha[3]) / 255;
769 *tY = *oY * a + *tY * (1 - a);
770 *tU = *oU * a + *tU * (1 - a);
771 *tV = *oV * a + *tV * (1 - a);
787 case AV_PIX_FMT_YUV420P10:
789 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
790 dcp::Size const ts = size();
791 dcp::Size const os = yuv->size();
792 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
793 int const hty = ty / 2;
794 int const hoy = oy / 2;
795 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
796 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
797 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
798 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
799 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
800 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
801 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
802 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
803 float const a = float(alpha[3]) / 255;
804 *tY = *oY * a + *tY * (1 - a);
805 *tU = *oU * a + *tU * (1 - a);
806 *tV = *oV * a + *tV * (1 - a);
822 case AV_PIX_FMT_YUV422P10LE:
824 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
825 dcp::Size const ts = size();
826 dcp::Size const os = yuv->size();
827 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
828 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
829 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
830 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
831 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
832 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
833 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
834 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
835 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
836 float const a = float(alpha[3]) / 255;
837 *tY = *oY * a + *tY * (1 - a);
838 *tU = *oU * a + *tU * (1 - a);
839 *tV = *oV * a + *tV * (1 - a);
856 throw PixelFormatError ("alpha_blend()", _pixel_format);
862 Image::copy (shared_ptr<const Image> other, Position<int> position)
864 /* Only implemented for RGB24 onto RGB24 so far */
865 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
866 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
868 int const N = min (position.x + other->size().width, size().width) - position.x;
869 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
870 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
871 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
872 memcpy (tp, op, N * 3);
878 Image::read_from_socket (shared_ptr<Socket> socket)
880 for (int i = 0; i < planes(); ++i) {
881 uint8_t* p = data()[i];
882 int const lines = sample_size(i).height;
883 for (int y = 0; y < lines; ++y) {
884 socket->read (p, line_size()[i]);
892 Image::write_to_socket (shared_ptr<Socket> socket) const
894 for (int i = 0; i < planes(); ++i) {
895 uint8_t* p = data()[i];
896 int const lines = sample_size(i).height;
897 for (int y = 0; y < lines; ++y) {
898 socket->write (p, line_size()[i]);
906 Image::bytes_per_pixel (int c) const
908 auto d = av_pix_fmt_desc_get(_pixel_format);
910 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
917 float bpp[4] = { 0, 0, 0, 0 };
919 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
920 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
921 if (d->nb_components > 1) {
922 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
924 if (d->nb_components > 2) {
925 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
927 if (d->nb_components > 3) {
928 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
931 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
932 if (d->nb_components > 1) {
933 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
935 if (d->nb_components > 2) {
936 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
938 if (d->nb_components > 3) {
939 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
943 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
944 /* Not planar; sum them up */
945 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
952 /** Construct a Image of a given size and format, allocating memory
955 * @param p Pixel format.
956 * @param s Size in pixels.
957 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
959 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
962 , _alignment (alignment)
971 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
972 _data[0] = _data[1] = _data[2] = _data[3] = 0;
974 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
975 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
977 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
978 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
980 auto stride_round_up = [](int stride, int t) {
981 int const a = stride + (t - 1);
985 for (int i = 0; i < planes(); ++i) {
986 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
987 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
989 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
990 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
991 Hence on the last pixel of the last line it reads over the end of
992 the actual data by 1 byte. If the width of an image is a multiple
993 of the stride alignment there will be no padding at the end of image lines.
994 OS X crashes on this illegal read, though other operating systems don't
995 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
996 for that instruction to read safely.
998 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
999 over-reads by more then _avx. I can't follow the code to work out how much,
1000 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
1001 testing suggests that it works.
1003 In addition to these concerns, we may read/write as much as a whole extra line
1004 at the end of each plane in cases where we are messing with offsets in order to
1005 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1007 As an example: we may write to images starting at an offset so we get some padding.
1008 Hence we want to write in the following pattern:
1010 block start write start line end
1011 |..(padding)..|<------line-size------------->|..(padding)..|
1012 |..(padding)..|<------line-size------------->|..(padding)..|
1013 |..(padding)..|<------line-size------------->|..(padding)..|
1015 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1016 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1017 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1018 specified *stride*. This does not matter until we get to the last line:
1020 block start write start line end
1021 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1022 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1023 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1026 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1027 #if HAVE_VALGRIND_MEMCHECK_H
1028 /* The data between the end of the line size and the stride is undefined but processed by
1029 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1031 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1037 Image::Image (Image const & other)
1038 : std::enable_shared_from_this<Image>(other)
1039 , _size (other._size)
1040 , _pixel_format (other._pixel_format)
1041 , _alignment (other._alignment)
1045 for (int i = 0; i < planes(); ++i) {
1046 uint8_t* p = _data[i];
1047 uint8_t* q = other._data[i];
1048 int const lines = sample_size(i).height;
1049 for (int j = 0; j < lines; ++j) {
1050 memcpy (p, q, _line_size[i]);
1052 q += other.stride()[i];
1058 Image::Image (AVFrame const * frame, Alignment alignment)
1059 : _size (frame->width, frame->height)
1060 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1061 , _alignment (alignment)
1063 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1067 for (int i = 0; i < planes(); ++i) {
1068 uint8_t* p = _data[i];
1069 uint8_t* q = frame->data[i];
1070 int const lines = sample_size(i).height;
1071 for (int j = 0; j < lines; ++j) {
1072 memcpy (p, q, _line_size[i]);
1074 /* AVFrame's linesize is what we call `stride' */
1075 q += frame->linesize[i];
1081 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1082 : _size (other->_size)
1083 , _pixel_format (other->_pixel_format)
1084 , _alignment (alignment)
1088 for (int i = 0; i < planes(); ++i) {
1089 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1090 uint8_t* p = _data[i];
1091 uint8_t* q = other->data()[i];
1092 int const lines = sample_size(i).height;
1093 for (int j = 0; j < lines; ++j) {
1094 memcpy (p, q, line_size()[i]);
1096 q += other->stride()[i];
1103 Image::operator= (Image const & other)
1105 if (this == &other) {
1116 Image::swap (Image & other)
1118 std::swap (_size, other._size);
1119 std::swap (_pixel_format, other._pixel_format);
1121 for (int i = 0; i < 4; ++i) {
1122 std::swap (_data[i], other._data[i]);
1123 std::swap (_line_size[i], other._line_size[i]);
1124 std::swap (_stride[i], other._stride[i]);
1127 std::swap (_alignment, other._alignment);
1133 for (int i = 0; i < planes(); ++i) {
1138 av_free (_line_size);
1144 Image::data () const
1151 Image::line_size () const
1158 Image::stride () const
1165 Image::size () const
1172 Image::alignment () const
1179 merge (list<PositionImage> images, Image::Alignment alignment)
1181 if (images.empty ()) {
1185 if (images.size() == 1) {
1186 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1187 return images.front();
1190 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1191 for (auto const& i: images) {
1192 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1195 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1196 merged->make_transparent ();
1197 for (auto const& i: images) {
1198 merged->alpha_blend (i.image, i.position - all.position());
1201 return PositionImage (merged, all.position ());
1206 operator== (Image const & a, Image const & b)
1208 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1212 for (int c = 0; c < a.planes(); ++c) {
1213 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]) {
1217 uint8_t* p = a.data()[c];
1218 uint8_t* q = b.data()[c];
1219 int const lines = a.sample_size(c).height;
1220 for (int y = 0; y < lines; ++y) {
1221 if (memcmp (p, q, a.line_size()[c]) != 0) {
1235 * @param f Amount to fade by; 0 is black, 1 is no fade.
1238 Image::fade (float f)
1240 /* U/V black value for 8-bit colour */
1241 static int const eight_bit_uv = (1 << 7) - 1;
1242 /* U/V black value for 10-bit colour */
1243 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1245 switch (_pixel_format) {
1246 case AV_PIX_FMT_YUV420P:
1249 uint8_t* p = data()[0];
1250 int const lines = sample_size(0).height;
1251 for (int y = 0; y < lines; ++y) {
1253 for (int x = 0; x < line_size()[0]; ++x) {
1254 *q = int(float(*q) * f);
1261 for (int c = 1; c < 3; ++c) {
1262 uint8_t* p = data()[c];
1263 int const lines = sample_size(c).height;
1264 for (int y = 0; y < lines; ++y) {
1266 for (int x = 0; x < line_size()[c]; ++x) {
1267 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1277 case AV_PIX_FMT_RGB24:
1280 uint8_t* p = data()[0];
1281 int const lines = sample_size(0).height;
1282 for (int y = 0; y < lines; ++y) {
1284 for (int x = 0; x < line_size()[0]; ++x) {
1285 *q = int (float (*q) * f);
1293 case AV_PIX_FMT_XYZ12LE:
1294 case AV_PIX_FMT_RGB48LE:
1295 /* 16-bit little-endian */
1296 for (int c = 0; c < 3; ++c) {
1297 int const stride_pixels = stride()[c] / 2;
1298 int const line_size_pixels = line_size()[c] / 2;
1299 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1300 int const lines = sample_size(c).height;
1301 for (int y = 0; y < lines; ++y) {
1303 for (int x = 0; x < line_size_pixels; ++x) {
1304 *q = int (float (*q) * f);
1312 case AV_PIX_FMT_YUV422P10LE:
1316 int const stride_pixels = stride()[0] / 2;
1317 int const line_size_pixels = line_size()[0] / 2;
1318 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1319 int const lines = sample_size(0).height;
1320 for (int y = 0; y < lines; ++y) {
1322 for (int x = 0; x < line_size_pixels; ++x) {
1323 *q = int(float(*q) * f);
1331 for (int c = 1; c < 3; ++c) {
1332 int const stride_pixels = stride()[c] / 2;
1333 int const line_size_pixels = line_size()[c] / 2;
1334 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1335 int const lines = sample_size(c).height;
1336 for (int y = 0; y < lines; ++y) {
1338 for (int x = 0; x < line_size_pixels; ++x) {
1339 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1350 throw PixelFormatError ("fade()", _pixel_format);
1355 shared_ptr<const Image>
1356 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1358 if (image->alignment() == alignment) {
1362 return make_shared<Image>(image, alignment);
1367 Image::memory_used () const
1370 for (int i = 0; i < planes(); ++i) {
1371 m += _stride[i] * sample_size(i).height;
1378 Image::video_range_to_full_range ()
1380 switch (_pixel_format) {
1381 case AV_PIX_FMT_RGB24:
1383 float const factor = 256.0 / 219.0;
1384 uint8_t* p = data()[0];
1385 int const lines = sample_size(0).height;
1386 for (int y = 0; y < lines; ++y) {
1388 for (int x = 0; x < line_size()[0]; ++x) {
1389 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1396 case AV_PIX_FMT_RGB48LE:
1398 float const factor = 65536.0 / 56064.0;
1399 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1400 int const lines = sample_size(0).height;
1401 for (int y = 0; y < lines; ++y) {
1403 int const line_size_pixels = line_size()[0] / 2;
1404 for (int x = 0; x < line_size_pixels; ++x) {
1405 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1408 p += stride()[0] / 2;
1412 case AV_PIX_FMT_GBRP12LE:
1414 float const factor = 4096.0 / 3504.0;
1415 for (int c = 0; c < 3; ++c) {
1416 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1417 int const lines = sample_size(c).height;
1418 for (int y = 0; y < lines; ++y) {
1420 int const line_size_pixels = line_size()[c] / 2;
1421 for (int x = 0; x < line_size_pixels; ++x) {
1422 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1430 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);