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 left hand side of the image to take care of that.
303 out->make_part_black (corner.x + inter_size.width, (out_size.width - inter_size.width) / 2);
306 video_range == VideoRange::VIDEO &&
307 out_video_range == VideoRange::FULL &&
308 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
310 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
311 out->video_range_to_full_range ();
319 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
321 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
325 /** @param out_size Size to scale to.
326 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
327 * @param out_format Output pixel format.
328 * @param out_aligment Output alignment.
329 * @param fast Try to be fast at the possible expense of quality; at present this means using
330 * fast bilinear rather than bicubic scaling.
333 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
335 /* Empirical testing suggests that sws_scale() will crash if
336 the input image alignment is not PADDED.
338 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
340 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
341 auto scale_context = sws_getContext (
342 size().width, size().height, pixel_format(),
343 out_size.width, out_size.height, out_format,
344 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
347 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
348 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
353 /* The 3rd parameter here is:
354 0 -> source range MPEG (i.e. "video", 16-235)
355 1 -> source range JPEG (i.e. "full", 0-255)
357 0 -> destination range MPEG (i.e. "video", 16-235)
358 1 -> destination range JPEG (i.e. "full", 0-255)
360 But remember: sws_setColorspaceDetails ignores these
361 parameters unless the corresponding image isYUV or isGray.
362 (If it's neither, it uses video range).
364 sws_setColorspaceDetails (
366 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
367 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
375 scaled->data(), scaled->stride()
378 sws_freeContext (scale_context);
384 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
386 Image::yuv_16_black (uint16_t v, bool alpha)
388 memset (data()[0], 0, sample_size(0).height * stride()[0]);
389 for (int i = 1; i < 3; ++i) {
390 auto p = reinterpret_cast<int16_t*> (data()[i]);
391 int const lines = sample_size(i).height;
392 for (int y = 0; y < lines; ++y) {
393 /* We divide by 2 here because we are writing 2 bytes at a time */
394 for (int x = 0; x < line_size()[i] / 2; ++x) {
397 p += stride()[i] / 2;
402 memset (data()[3], 0, sample_size(3).height * stride()[3]);
408 Image::swap_16 (uint16_t v)
410 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
415 Image::make_part_black (int const start, int const width)
417 auto y_part = [&]() {
418 int const bpp = bytes_per_pixel(0);
419 int const h = sample_size(0).height;
420 int const s = stride()[0];
422 for (int y = 0; y < h; ++y) {
423 memset (p + start * bpp, 0, width * bpp);
428 switch (_pixel_format) {
429 case AV_PIX_FMT_RGB24:
430 case AV_PIX_FMT_ARGB:
431 case AV_PIX_FMT_RGBA:
432 case AV_PIX_FMT_ABGR:
433 case AV_PIX_FMT_BGRA:
434 case AV_PIX_FMT_RGB555LE:
435 case AV_PIX_FMT_RGB48LE:
436 case AV_PIX_FMT_RGB48BE:
437 case AV_PIX_FMT_XYZ12LE:
439 int const h = sample_size(0).height;
440 int const bpp = bytes_per_pixel(0);
441 int const s = stride()[0];
442 uint8_t* p = data()[0];
443 for (int y = 0; y < h; y++) {
444 memset (p + start * bpp, 0, width * bpp);
449 case AV_PIX_FMT_YUV420P:
452 for (int i = 1; i < 3; ++i) {
454 int const h = sample_size(i).height;
455 for (int y = 0; y < h; ++y) {
456 for (int x = start / 2; x < (start + width) / 2; ++x) {
464 case AV_PIX_FMT_YUV422P10LE:
467 for (int i = 1; i < 3; ++i) {
468 auto p = reinterpret_cast<int16_t*>(data()[i]);
469 int const h = sample_size(i).height;
470 for (int y = 0; y < h; ++y) {
471 for (int x = start / 2; x < (start + width) / 2; ++x) {
474 p += stride()[i] / 2;
480 throw PixelFormatError ("make_part_black()", _pixel_format);
488 switch (_pixel_format) {
489 case AV_PIX_FMT_YUV420P:
490 case AV_PIX_FMT_YUV422P:
491 case AV_PIX_FMT_YUV444P:
492 case AV_PIX_FMT_YUV411P:
493 memset (data()[0], 0, sample_size(0).height * stride()[0]);
494 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
495 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
498 case AV_PIX_FMT_YUVJ420P:
499 case AV_PIX_FMT_YUVJ422P:
500 case AV_PIX_FMT_YUVJ444P:
501 memset (data()[0], 0, sample_size(0).height * stride()[0]);
502 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
503 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
506 case AV_PIX_FMT_YUV422P9LE:
507 case AV_PIX_FMT_YUV444P9LE:
508 yuv_16_black (nine_bit_uv, false);
511 case AV_PIX_FMT_YUV422P9BE:
512 case AV_PIX_FMT_YUV444P9BE:
513 yuv_16_black (swap_16 (nine_bit_uv), false);
516 case AV_PIX_FMT_YUV422P10LE:
517 case AV_PIX_FMT_YUV444P10LE:
518 yuv_16_black (ten_bit_uv, false);
521 case AV_PIX_FMT_YUV422P16LE:
522 case AV_PIX_FMT_YUV444P16LE:
523 yuv_16_black (sixteen_bit_uv, false);
526 case AV_PIX_FMT_YUV444P10BE:
527 case AV_PIX_FMT_YUV422P10BE:
528 yuv_16_black (swap_16 (ten_bit_uv), false);
531 case AV_PIX_FMT_YUVA420P9BE:
532 case AV_PIX_FMT_YUVA422P9BE:
533 case AV_PIX_FMT_YUVA444P9BE:
534 yuv_16_black (swap_16 (nine_bit_uv), true);
537 case AV_PIX_FMT_YUVA420P9LE:
538 case AV_PIX_FMT_YUVA422P9LE:
539 case AV_PIX_FMT_YUVA444P9LE:
540 yuv_16_black (nine_bit_uv, true);
543 case AV_PIX_FMT_YUVA420P10BE:
544 case AV_PIX_FMT_YUVA422P10BE:
545 case AV_PIX_FMT_YUVA444P10BE:
546 yuv_16_black (swap_16 (ten_bit_uv), true);
549 case AV_PIX_FMT_YUVA420P10LE:
550 case AV_PIX_FMT_YUVA422P10LE:
551 case AV_PIX_FMT_YUVA444P10LE:
552 yuv_16_black (ten_bit_uv, true);
555 case AV_PIX_FMT_YUVA420P16BE:
556 case AV_PIX_FMT_YUVA422P16BE:
557 case AV_PIX_FMT_YUVA444P16BE:
558 yuv_16_black (swap_16 (sixteen_bit_uv), true);
561 case AV_PIX_FMT_YUVA420P16LE:
562 case AV_PIX_FMT_YUVA422P16LE:
563 case AV_PIX_FMT_YUVA444P16LE:
564 yuv_16_black (sixteen_bit_uv, true);
567 case AV_PIX_FMT_RGB24:
568 case AV_PIX_FMT_ARGB:
569 case AV_PIX_FMT_RGBA:
570 case AV_PIX_FMT_ABGR:
571 case AV_PIX_FMT_BGRA:
572 case AV_PIX_FMT_RGB555LE:
573 case AV_PIX_FMT_RGB48LE:
574 case AV_PIX_FMT_RGB48BE:
575 case AV_PIX_FMT_XYZ12LE:
576 memset (data()[0], 0, sample_size(0).height * stride()[0]);
579 case AV_PIX_FMT_UYVY422:
581 int const Y = sample_size(0).height;
582 int const X = line_size()[0];
583 uint8_t* p = data()[0];
584 for (int y = 0; y < Y; ++y) {
585 for (int x = 0; x < X / 4; ++x) {
586 *p++ = eight_bit_uv; // Cb
588 *p++ = eight_bit_uv; // Cr
596 throw PixelFormatError ("make_black()", _pixel_format);
602 Image::make_transparent ()
604 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
605 throw PixelFormatError ("make_transparent()", _pixel_format);
608 memset (data()[0], 0, sample_size(0).height * stride()[0]);
613 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
615 /* We're blending RGBA or BGRA images */
616 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
617 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
618 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
620 int const other_bpp = 4;
622 int start_tx = position.x;
626 start_ox = -start_tx;
630 int start_ty = position.y;
634 start_oy = -start_ty;
638 switch (_pixel_format) {
639 case AV_PIX_FMT_RGB24:
641 /* Going onto RGB24. First byte is red, second green, third blue */
642 int const this_bpp = 3;
643 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
644 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
645 uint8_t* op = other->data()[0] + oy * other->stride()[0];
646 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
647 float const alpha = float (op[3]) / 255;
648 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
649 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
650 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
658 case AV_PIX_FMT_BGRA:
660 int const this_bpp = 4;
661 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
662 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
663 uint8_t* op = other->data()[0] + oy * other->stride()[0];
664 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
665 float const alpha = float (op[3]) / 255;
666 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
667 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
668 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
669 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
677 case AV_PIX_FMT_RGBA:
679 int const this_bpp = 4;
680 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
681 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
682 uint8_t* op = other->data()[0] + oy * other->stride()[0];
683 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
684 float const alpha = float (op[3]) / 255;
685 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
686 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
687 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
688 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
696 case AV_PIX_FMT_RGB48LE:
698 int const this_bpp = 6;
699 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
700 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
701 uint8_t* op = other->data()[0] + oy * other->stride()[0];
702 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
703 float const alpha = float (op[3]) / 255;
704 /* Blend high bytes */
705 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
706 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
707 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
715 case AV_PIX_FMT_XYZ12LE:
717 auto conv = dcp::ColourConversion::srgb_to_xyz();
718 double fast_matrix[9];
719 dcp::combined_rgb_to_xyz (conv, fast_matrix);
720 auto lut_in = conv.in()->lut(0, 1, 8, false);
721 auto lut_out = conv.out()->lut(0, 1, 16, true);
722 int const this_bpp = 6;
723 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
724 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
725 uint8_t* op = other->data()[0] + oy * other->stride()[0];
726 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
727 float const alpha = float (op[3]) / 255;
729 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
730 double const r = lut_in[op[red]];
731 double const g = lut_in[op[1]];
732 double const b = lut_in[op[blue]];
734 /* RGB to XYZ, including Bradford transform and DCI companding */
735 double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
736 double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
737 double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
739 /* Out gamma LUT and blend */
740 tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
741 tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
742 tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
750 case AV_PIX_FMT_YUV420P:
752 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
753 dcp::Size const ts = size();
754 dcp::Size const os = yuv->size();
755 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
756 int const hty = ty / 2;
757 int const hoy = oy / 2;
758 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
759 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
760 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
761 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
762 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
763 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
764 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
765 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
766 float const a = float(alpha[3]) / 255;
767 *tY = *oY * a + *tY * (1 - a);
768 *tU = *oU * a + *tU * (1 - a);
769 *tV = *oV * a + *tV * (1 - a);
785 case AV_PIX_FMT_YUV420P10:
787 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
788 dcp::Size const ts = size();
789 dcp::Size const os = yuv->size();
790 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
791 int const hty = ty / 2;
792 int const hoy = oy / 2;
793 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
794 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
795 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
796 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
797 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
798 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
799 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
800 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
801 float const a = float(alpha[3]) / 255;
802 *tY = *oY * a + *tY * (1 - a);
803 *tU = *oU * a + *tU * (1 - a);
804 *tV = *oV * a + *tV * (1 - a);
820 case AV_PIX_FMT_YUV422P10LE:
822 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
823 dcp::Size const ts = size();
824 dcp::Size const os = yuv->size();
825 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
826 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
827 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
828 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
829 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
830 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
831 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
832 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
833 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
834 float const a = float(alpha[3]) / 255;
835 *tY = *oY * a + *tY * (1 - a);
836 *tU = *oU * a + *tU * (1 - a);
837 *tV = *oV * a + *tV * (1 - a);
854 throw PixelFormatError ("alpha_blend()", _pixel_format);
860 Image::copy (shared_ptr<const Image> other, Position<int> position)
862 /* Only implemented for RGB24 onto RGB24 so far */
863 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
864 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
866 int const N = min (position.x + other->size().width, size().width) - position.x;
867 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
868 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
869 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
870 memcpy (tp, op, N * 3);
876 Image::read_from_socket (shared_ptr<Socket> socket)
878 for (int i = 0; i < planes(); ++i) {
879 uint8_t* p = data()[i];
880 int const lines = sample_size(i).height;
881 for (int y = 0; y < lines; ++y) {
882 socket->read (p, line_size()[i]);
890 Image::write_to_socket (shared_ptr<Socket> socket) const
892 for (int i = 0; i < planes(); ++i) {
893 uint8_t* p = data()[i];
894 int const lines = sample_size(i).height;
895 for (int y = 0; y < lines; ++y) {
896 socket->write (p, line_size()[i]);
904 Image::bytes_per_pixel (int c) const
906 auto d = av_pix_fmt_desc_get(_pixel_format);
908 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
915 float bpp[4] = { 0, 0, 0, 0 };
917 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
918 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
919 if (d->nb_components > 1) {
920 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
922 if (d->nb_components > 2) {
923 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
925 if (d->nb_components > 3) {
926 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
929 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
930 if (d->nb_components > 1) {
931 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
933 if (d->nb_components > 2) {
934 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
936 if (d->nb_components > 3) {
937 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
941 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
942 /* Not planar; sum them up */
943 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
950 /** Construct a Image of a given size and format, allocating memory
953 * @param p Pixel format.
954 * @param s Size in pixels.
955 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
957 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
960 , _alignment (alignment)
969 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
970 _data[0] = _data[1] = _data[2] = _data[3] = 0;
972 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
973 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
975 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
976 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
978 auto stride_round_up = [](int stride, int t) {
979 int const a = stride + (t - 1);
983 for (int i = 0; i < planes(); ++i) {
984 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
985 _stride[i] = stride_round_up (_line_size[i], _alignment == Alignment::PADDED ? ALIGNMENT : 1);
987 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
988 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
989 Hence on the last pixel of the last line it reads over the end of
990 the actual data by 1 byte. If the width of an image is a multiple
991 of the stride alignment there will be no padding at the end of image lines.
992 OS X crashes on this illegal read, though other operating systems don't
993 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
994 for that instruction to read safely.
996 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
997 over-reads by more then _avx. I can't follow the code to work out how much,
998 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
999 testing suggests that it works.
1001 In addition to these concerns, we may read/write as much as a whole extra line
1002 at the end of each plane in cases where we are messing with offsets in order to
1003 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
1005 As an example: we may write to images starting at an offset so we get some padding.
1006 Hence we want to write in the following pattern:
1008 block start write start line end
1009 |..(padding)..|<------line-size------------->|..(padding)..|
1010 |..(padding)..|<------line-size------------->|..(padding)..|
1011 |..(padding)..|<------line-size------------->|..(padding)..|
1013 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1014 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1015 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1016 specified *stride*. This does not matter until we get to the last line:
1018 block start write start line end
1019 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1020 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1021 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1024 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1025 #if HAVE_VALGRIND_MEMCHECK_H
1026 /* The data between the end of the line size and the stride is undefined but processed by
1027 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1029 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1035 Image::Image (Image const & other)
1036 : std::enable_shared_from_this<Image>(other)
1037 , _size (other._size)
1038 , _pixel_format (other._pixel_format)
1039 , _alignment (other._alignment)
1043 for (int i = 0; i < planes(); ++i) {
1044 uint8_t* p = _data[i];
1045 uint8_t* q = other._data[i];
1046 int const lines = sample_size(i).height;
1047 for (int j = 0; j < lines; ++j) {
1048 memcpy (p, q, _line_size[i]);
1050 q += other.stride()[i];
1056 Image::Image (AVFrame const * frame, Alignment alignment)
1057 : _size (frame->width, frame->height)
1058 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1059 , _alignment (alignment)
1061 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1065 for (int i = 0; i < planes(); ++i) {
1066 uint8_t* p = _data[i];
1067 uint8_t* q = frame->data[i];
1068 int const lines = sample_size(i).height;
1069 for (int j = 0; j < lines; ++j) {
1070 memcpy (p, q, _line_size[i]);
1072 /* AVFrame's linesize is what we call `stride' */
1073 q += frame->linesize[i];
1079 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1080 : _size (other->_size)
1081 , _pixel_format (other->_pixel_format)
1082 , _alignment (alignment)
1086 for (int i = 0; i < planes(); ++i) {
1087 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1088 uint8_t* p = _data[i];
1089 uint8_t* q = other->data()[i];
1090 int const lines = sample_size(i).height;
1091 for (int j = 0; j < lines; ++j) {
1092 memcpy (p, q, line_size()[i]);
1094 q += other->stride()[i];
1101 Image::operator= (Image const & other)
1103 if (this == &other) {
1114 Image::swap (Image & other)
1116 std::swap (_size, other._size);
1117 std::swap (_pixel_format, other._pixel_format);
1119 for (int i = 0; i < 4; ++i) {
1120 std::swap (_data[i], other._data[i]);
1121 std::swap (_line_size[i], other._line_size[i]);
1122 std::swap (_stride[i], other._stride[i]);
1125 std::swap (_alignment, other._alignment);
1131 for (int i = 0; i < planes(); ++i) {
1136 av_free (_line_size);
1142 Image::data () const
1149 Image::line_size () const
1156 Image::stride () const
1163 Image::size () const
1170 Image::alignment () const
1177 merge (list<PositionImage> images, Image::Alignment alignment)
1179 if (images.empty ()) {
1183 if (images.size() == 1) {
1184 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1185 return images.front();
1188 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1189 for (auto const& i: images) {
1190 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1193 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1194 merged->make_transparent ();
1195 for (auto const& i: images) {
1196 merged->alpha_blend (i.image, i.position - all.position());
1199 return PositionImage (merged, all.position ());
1204 operator== (Image const & a, Image const & b)
1206 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1210 for (int c = 0; c < a.planes(); ++c) {
1211 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]) {
1215 uint8_t* p = a.data()[c];
1216 uint8_t* q = b.data()[c];
1217 int const lines = a.sample_size(c).height;
1218 for (int y = 0; y < lines; ++y) {
1219 if (memcmp (p, q, a.line_size()[c]) != 0) {
1233 * @param f Amount to fade by; 0 is black, 1 is no fade.
1236 Image::fade (float f)
1238 /* U/V black value for 8-bit colour */
1239 static int const eight_bit_uv = (1 << 7) - 1;
1240 /* U/V black value for 10-bit colour */
1241 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1243 switch (_pixel_format) {
1244 case AV_PIX_FMT_YUV420P:
1247 uint8_t* p = data()[0];
1248 int const lines = sample_size(0).height;
1249 for (int y = 0; y < lines; ++y) {
1251 for (int x = 0; x < line_size()[0]; ++x) {
1252 *q = int(float(*q) * f);
1259 for (int c = 1; c < 3; ++c) {
1260 uint8_t* p = data()[c];
1261 int const lines = sample_size(c).height;
1262 for (int y = 0; y < lines; ++y) {
1264 for (int x = 0; x < line_size()[c]; ++x) {
1265 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1275 case AV_PIX_FMT_RGB24:
1278 uint8_t* p = data()[0];
1279 int const lines = sample_size(0).height;
1280 for (int y = 0; y < lines; ++y) {
1282 for (int x = 0; x < line_size()[0]; ++x) {
1283 *q = int (float (*q) * f);
1291 case AV_PIX_FMT_XYZ12LE:
1292 case AV_PIX_FMT_RGB48LE:
1293 /* 16-bit little-endian */
1294 for (int c = 0; c < 3; ++c) {
1295 int const stride_pixels = stride()[c] / 2;
1296 int const line_size_pixels = line_size()[c] / 2;
1297 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1298 int const lines = sample_size(c).height;
1299 for (int y = 0; y < lines; ++y) {
1301 for (int x = 0; x < line_size_pixels; ++x) {
1302 *q = int (float (*q) * f);
1310 case AV_PIX_FMT_YUV422P10LE:
1314 int const stride_pixels = stride()[0] / 2;
1315 int const line_size_pixels = line_size()[0] / 2;
1316 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1317 int const lines = sample_size(0).height;
1318 for (int y = 0; y < lines; ++y) {
1320 for (int x = 0; x < line_size_pixels; ++x) {
1321 *q = int(float(*q) * f);
1329 for (int c = 1; c < 3; ++c) {
1330 int const stride_pixels = stride()[c] / 2;
1331 int const line_size_pixels = line_size()[c] / 2;
1332 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1333 int const lines = sample_size(c).height;
1334 for (int y = 0; y < lines; ++y) {
1336 for (int x = 0; x < line_size_pixels; ++x) {
1337 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1348 throw PixelFormatError ("fade()", _pixel_format);
1353 shared_ptr<const Image>
1354 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1356 if (image->alignment() == alignment) {
1360 return make_shared<Image>(image, alignment);
1365 Image::memory_used () const
1368 for (int i = 0; i < planes(); ++i) {
1369 m += _stride[i] * sample_size(i).height;
1376 Image::video_range_to_full_range ()
1378 switch (_pixel_format) {
1379 case AV_PIX_FMT_RGB24:
1381 float const factor = 256.0 / 219.0;
1382 uint8_t* p = data()[0];
1383 int const lines = sample_size(0).height;
1384 for (int y = 0; y < lines; ++y) {
1386 for (int x = 0; x < line_size()[0]; ++x) {
1387 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1394 case AV_PIX_FMT_RGB48LE:
1396 float const factor = 65536.0 / 56064.0;
1397 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1398 int const lines = sample_size(0).height;
1399 for (int y = 0; y < lines; ++y) {
1401 int const line_size_pixels = line_size()[0] / 2;
1402 for (int x = 0; x < line_size_pixels; ++x) {
1403 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1406 p += stride()[0] / 2;
1410 case AV_PIX_FMT_GBRP12LE:
1412 float const factor = 4096.0 / 3504.0;
1413 for (int c = 0; c < 3; ++c) {
1414 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1415 int const lines = sample_size(c).height;
1416 for (int y = 0; y < lines; ++y) {
1418 int const line_size_pixels = line_size()[c] / 2;
1419 for (int x = 0; x < line_size_pixels; ++x) {
1420 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1428 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);