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_socket.h"
29 #include "exceptions.h"
35 #include <dcp/rgb_xyz.h>
36 #include <dcp/transfer_function.h>
37 DCPOMATIC_DISABLE_WARNINGS
39 #include <libavutil/frame.h>
40 #include <libavutil/pixdesc.h>
41 #include <libavutil/pixfmt.h>
42 #include <libswscale/swscale.h>
44 DCPOMATIC_ENABLE_WARNINGS
45 #if HAVE_VALGRIND_MEMCHECK_H
46 #include <valgrind/memcheck.h>
57 using std::make_shared;
60 using std::runtime_error;
61 using std::shared_ptr;
66 /** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
67 int constexpr ALIGNMENT = 64;
69 /* U/V black value for 8-bit colour */
70 static uint8_t const eight_bit_uv = (1 << 7) - 1;
71 /* U/V black value for 9-bit colour */
72 static uint16_t const nine_bit_uv = (1 << 8) - 1;
73 /* U/V black value for 10-bit colour */
74 static uint16_t const ten_bit_uv = (1 << 9) - 1;
75 /* U/V black value for 16-bit colour */
76 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
80 Image::vertical_factor (int n) const
86 auto d = av_pix_fmt_desc_get(_pixel_format);
88 throw PixelFormatError ("line_factor()", _pixel_format);
91 return lrintf(powf(2.0f, d->log2_chroma_h));
95 Image::horizontal_factor (int n) const
101 auto d = av_pix_fmt_desc_get(_pixel_format);
103 throw PixelFormatError ("sample_size()", _pixel_format);
106 return lrintf(powf(2.0f, d->log2_chroma_w));
109 /** @param n Component index.
110 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
113 Image::sample_size (int n) const
116 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
117 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
121 /** @return Number of planes */
123 Image::planes () const
125 auto d = av_pix_fmt_desc_get(_pixel_format);
127 throw PixelFormatError ("planes()", _pixel_format);
130 if (_pixel_format == AV_PIX_FMT_PAL8) {
134 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
138 return d->nb_components;
144 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
146 return p & ~ ((1 << desc->log2_chroma_w) - 1);
152 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
154 return p & ~ ((1 << desc->log2_chroma_h) - 1);
158 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
159 * @param crop Amount to crop by.
160 * @param inter_size Size to scale the cropped image to.
161 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
162 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
163 * @param video_range Video range of the image.
164 * @param out_format Output pixel format.
165 * @param out_aligned true to make the output image aligned.
166 * @param out_video_range Video range to use for the output image.
167 * @param fast Try to be fast at the possible expense of quality; at present this means using
168 * fast bilinear rather than bicubic scaling.
171 Image::crop_scale_window (
173 dcp::Size inter_size,
175 dcp::YUVToRGB yuv_to_rgb,
176 VideoRange video_range,
177 AVPixelFormat out_format,
178 VideoRange out_video_range,
179 Alignment out_alignment,
183 /* Empirical testing suggests that sws_scale() will crash if
184 the input image is not padded.
186 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
188 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
189 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
191 auto out = make_shared<Image>(out_format, out_size, out_alignment);
194 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
196 throw PixelFormatError ("crop_scale_window()", _pixel_format);
199 /* Round down so that we crop only the number of pixels that is straightforward
200 * considering any subsampling.
203 round_width_for_subsampling(crop.left, in_desc),
204 round_width_for_subsampling(crop.right, in_desc),
205 round_height_for_subsampling(crop.top, in_desc),
206 round_height_for_subsampling(crop.bottom, in_desc)
209 /* Also check that we aren't cropping more image than there actually is */
210 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
211 corrected_crop.left = 0;
212 corrected_crop.right = size().width - 4;
215 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
216 corrected_crop.top = 0;
217 corrected_crop.bottom = size().height - 4;
220 /* Size of the image after any crop */
221 auto const cropped_size = corrected_crop.apply (size());
223 /* Scale context for a scale from cropped_size to inter_size */
224 auto scale_context = sws_getContext (
225 cropped_size.width, cropped_size.height, pixel_format(),
226 inter_size.width, inter_size.height, out_format,
227 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
230 if (!scale_context) {
231 throw runtime_error (N_("Could not allocate SwsContext"));
234 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
235 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
240 /* The 3rd parameter here is:
241 0 -> source range MPEG (i.e. "video", 16-235)
242 1 -> source range JPEG (i.e. "full", 0-255)
244 0 -> destination range MPEG (i.e. "video", 16-235)
245 1 -> destination range JPEG (i.e. "full", 0-255)
247 But remember: sws_setColorspaceDetails ignores these
248 parameters unless the both source and destination images
249 are isYUV or isGray. (If either is not, it uses video range).
251 sws_setColorspaceDetails (
253 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
254 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
258 /* Prepare input data pointers with crop */
259 uint8_t* scale_in_data[planes()];
260 for (int c = 0; c < planes(); ++c) {
261 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
262 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
265 auto out_desc = av_pix_fmt_desc_get (out_format);
267 throw PixelFormatError ("crop_scale_window()", out_format);
270 /* Corner of the image within out_size */
271 Position<int> const corner (
272 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
273 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
276 uint8_t* scale_out_data[out->planes()];
277 for (int c = 0; c < out->planes(); ++c) {
278 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
279 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
284 scale_in_data, stride(),
285 0, cropped_size.height,
286 scale_out_data, out->stride()
289 sws_freeContext (scale_context);
291 if (corrected_crop != Crop() && cropped_size == inter_size) {
292 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
293 data behind in our image. Clear it out. It may get to the point where we should just stop
294 trying to be clever with cropping.
296 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
300 video_range == VideoRange::VIDEO &&
301 out_video_range == VideoRange::FULL &&
302 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
304 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
305 out->video_range_to_full_range ();
312 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
314 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
317 /** @param out_size Size to scale to.
318 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
319 * @param out_format Output pixel format.
320 * @param out_aligment Output alignment.
321 * @param fast Try to be fast at the possible expense of quality; at present this means using
322 * fast bilinear rather than bicubic scaling.
325 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
327 /* Empirical testing suggests that sws_scale() will crash if
328 the input image alignment is not PADDED.
330 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
332 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
333 auto scale_context = sws_getContext (
334 size().width, size().height, pixel_format(),
335 out_size.width, out_size.height, out_format,
336 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
339 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
340 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
345 /* The 3rd parameter here is:
346 0 -> source range MPEG (i.e. "video", 16-235)
347 1 -> source range JPEG (i.e. "full", 0-255)
349 0 -> destination range MPEG (i.e. "video", 16-235)
350 1 -> destination range JPEG (i.e. "full", 0-255)
352 But remember: sws_setColorspaceDetails ignores these
353 parameters unless the corresponding image isYUV or isGray.
354 (If it's neither, it uses video range).
356 sws_setColorspaceDetails (
358 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
359 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
367 scaled->data(), scaled->stride()
370 sws_freeContext (scale_context);
375 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
377 Image::yuv_16_black (uint16_t v, bool alpha)
379 memset (data()[0], 0, sample_size(0).height * stride()[0]);
380 for (int i = 1; i < 3; ++i) {
381 auto p = reinterpret_cast<int16_t*> (data()[i]);
382 int const lines = sample_size(i).height;
383 for (int y = 0; y < lines; ++y) {
384 /* We divide by 2 here because we are writing 2 bytes at a time */
385 for (int x = 0; x < line_size()[i] / 2; ++x) {
388 p += stride()[i] / 2;
393 memset (data()[3], 0, sample_size(3).height * stride()[3]);
398 Image::swap_16 (uint16_t v)
400 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
404 Image::make_part_black (int const start, int const width)
406 auto y_part = [&]() {
407 int const bpp = bytes_per_pixel(0);
408 int const h = sample_size(0).height;
409 int const s = stride()[0];
411 for (int y = 0; y < h; ++y) {
412 memset (p + start * bpp, 0, width * bpp);
417 switch (_pixel_format) {
418 case AV_PIX_FMT_RGB24:
419 case AV_PIX_FMT_ARGB:
420 case AV_PIX_FMT_RGBA:
421 case AV_PIX_FMT_ABGR:
422 case AV_PIX_FMT_BGRA:
423 case AV_PIX_FMT_RGB555LE:
424 case AV_PIX_FMT_RGB48LE:
425 case AV_PIX_FMT_RGB48BE:
426 case AV_PIX_FMT_XYZ12LE:
428 int const h = sample_size(0).height;
429 int const bpp = bytes_per_pixel(0);
430 int const s = stride()[0];
431 uint8_t* p = data()[0];
432 for (int y = 0; y < h; y++) {
433 memset (p + start * bpp, 0, width * bpp);
438 case AV_PIX_FMT_YUV420P:
441 for (int i = 1; i < 3; ++i) {
443 int const h = sample_size(i).height;
444 for (int y = 0; y < h; ++y) {
445 for (int x = start / 2; x < (start + width) / 2; ++x) {
453 case AV_PIX_FMT_YUV422P10LE:
456 for (int i = 1; i < 3; ++i) {
457 auto p = reinterpret_cast<int16_t*>(data()[i]);
458 int const h = sample_size(i).height;
459 for (int y = 0; y < h; ++y) {
460 for (int x = start / 2; x < (start + width) / 2; ++x) {
463 p += stride()[i] / 2;
469 throw PixelFormatError ("make_part_black()", _pixel_format);
476 switch (_pixel_format) {
477 case AV_PIX_FMT_YUV420P:
478 case AV_PIX_FMT_YUV422P:
479 case AV_PIX_FMT_YUV444P:
480 case AV_PIX_FMT_YUV411P:
481 memset (data()[0], 0, sample_size(0).height * stride()[0]);
482 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
483 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
486 case AV_PIX_FMT_YUVJ420P:
487 case AV_PIX_FMT_YUVJ422P:
488 case AV_PIX_FMT_YUVJ444P:
489 memset (data()[0], 0, sample_size(0).height * stride()[0]);
490 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
491 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
494 case AV_PIX_FMT_YUV422P9LE:
495 case AV_PIX_FMT_YUV444P9LE:
496 yuv_16_black (nine_bit_uv, false);
499 case AV_PIX_FMT_YUV422P9BE:
500 case AV_PIX_FMT_YUV444P9BE:
501 yuv_16_black (swap_16 (nine_bit_uv), false);
504 case AV_PIX_FMT_YUV422P10LE:
505 case AV_PIX_FMT_YUV444P10LE:
506 yuv_16_black (ten_bit_uv, false);
509 case AV_PIX_FMT_YUV422P16LE:
510 case AV_PIX_FMT_YUV444P16LE:
511 yuv_16_black (sixteen_bit_uv, false);
514 case AV_PIX_FMT_YUV444P10BE:
515 case AV_PIX_FMT_YUV422P10BE:
516 yuv_16_black (swap_16 (ten_bit_uv), false);
519 case AV_PIX_FMT_YUVA420P9BE:
520 case AV_PIX_FMT_YUVA422P9BE:
521 case AV_PIX_FMT_YUVA444P9BE:
522 yuv_16_black (swap_16 (nine_bit_uv), true);
525 case AV_PIX_FMT_YUVA420P9LE:
526 case AV_PIX_FMT_YUVA422P9LE:
527 case AV_PIX_FMT_YUVA444P9LE:
528 yuv_16_black (nine_bit_uv, true);
531 case AV_PIX_FMT_YUVA420P10BE:
532 case AV_PIX_FMT_YUVA422P10BE:
533 case AV_PIX_FMT_YUVA444P10BE:
534 yuv_16_black (swap_16 (ten_bit_uv), true);
537 case AV_PIX_FMT_YUVA420P10LE:
538 case AV_PIX_FMT_YUVA422P10LE:
539 case AV_PIX_FMT_YUVA444P10LE:
540 yuv_16_black (ten_bit_uv, true);
543 case AV_PIX_FMT_YUVA420P16BE:
544 case AV_PIX_FMT_YUVA422P16BE:
545 case AV_PIX_FMT_YUVA444P16BE:
546 yuv_16_black (swap_16 (sixteen_bit_uv), true);
549 case AV_PIX_FMT_YUVA420P16LE:
550 case AV_PIX_FMT_YUVA422P16LE:
551 case AV_PIX_FMT_YUVA444P16LE:
552 yuv_16_black (sixteen_bit_uv, true);
555 case AV_PIX_FMT_RGB24:
556 case AV_PIX_FMT_ARGB:
557 case AV_PIX_FMT_RGBA:
558 case AV_PIX_FMT_ABGR:
559 case AV_PIX_FMT_BGRA:
560 case AV_PIX_FMT_RGB555LE:
561 case AV_PIX_FMT_RGB48LE:
562 case AV_PIX_FMT_RGB48BE:
563 case AV_PIX_FMT_XYZ12LE:
564 memset (data()[0], 0, sample_size(0).height * stride()[0]);
567 case AV_PIX_FMT_UYVY422:
569 int const Y = sample_size(0).height;
570 int const X = line_size()[0];
571 uint8_t* p = data()[0];
572 for (int y = 0; y < Y; ++y) {
573 for (int x = 0; x < X / 4; ++x) {
574 *p++ = eight_bit_uv; // Cb
576 *p++ = eight_bit_uv; // Cr
584 throw PixelFormatError ("make_black()", _pixel_format);
589 Image::make_transparent ()
591 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
592 throw PixelFormatError ("make_transparent()", _pixel_format);
595 memset (data()[0], 0, sample_size(0).height * stride()[0]);
599 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
601 /* We're blending RGBA or BGRA images */
602 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
603 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
604 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
606 int const other_bpp = 4;
608 int start_tx = position.x;
612 start_ox = -start_tx;
616 int start_ty = position.y;
620 start_oy = -start_ty;
624 switch (_pixel_format) {
625 case AV_PIX_FMT_RGB24:
627 /* Going onto RGB24. First byte is red, second green, third blue */
628 int const this_bpp = 3;
629 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
630 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
631 uint8_t* op = other->data()[0] + oy * other->stride()[0];
632 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
633 float const alpha = float (op[3]) / 255;
634 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
635 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
636 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
644 case AV_PIX_FMT_BGRA:
646 int const this_bpp = 4;
647 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
648 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
649 uint8_t* op = other->data()[0] + oy * other->stride()[0];
650 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
651 float const alpha = float (op[3]) / 255;
652 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
653 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
654 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
655 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
663 case AV_PIX_FMT_RGBA:
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[red] * alpha + tp[0] * (1 - alpha);
672 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
673 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
674 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
682 case AV_PIX_FMT_RGB48LE:
684 int const this_bpp = 6;
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 /* Blend high bytes */
691 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
692 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
693 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
701 case AV_PIX_FMT_XYZ12LE:
703 auto conv = dcp::ColourConversion::srgb_to_xyz();
704 double fast_matrix[9];
705 dcp::combined_rgb_to_xyz (conv, fast_matrix);
706 double const * lut_in = conv.in()->lut (8, false);
707 double const * lut_out = conv.out()->lut (16, true);
708 int const this_bpp = 6;
709 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
710 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
711 uint8_t* op = other->data()[0] + oy * other->stride()[0];
712 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
713 float const alpha = float (op[3]) / 255;
715 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
716 double const r = lut_in[op[red]];
717 double const g = lut_in[op[1]];
718 double const b = lut_in[op[blue]];
720 /* RGB to XYZ, including Bradford transform and DCI companding */
721 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
722 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
723 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
725 /* Out gamma LUT and blend */
726 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
727 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
728 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
736 case AV_PIX_FMT_YUV420P:
738 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
739 dcp::Size const ts = size();
740 dcp::Size const os = yuv->size();
741 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
742 int const hty = ty / 2;
743 int const hoy = oy / 2;
744 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
745 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
746 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
747 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
748 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
749 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
750 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
751 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
752 float const a = float(alpha[3]) / 255;
753 *tY = *oY * a + *tY * (1 - a);
754 *tU = *oU * a + *tU * (1 - a);
755 *tV = *oV * a + *tV * (1 - a);
771 case AV_PIX_FMT_YUV420P10:
773 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
774 dcp::Size const ts = size();
775 dcp::Size const os = yuv->size();
776 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
777 int const hty = ty / 2;
778 int const hoy = oy / 2;
779 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
780 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
781 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
782 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
783 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
784 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
785 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
786 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
787 float const a = float(alpha[3]) / 255;
788 *tY = *oY * a + *tY * (1 - a);
789 *tU = *oU * a + *tU * (1 - a);
790 *tV = *oV * a + *tV * (1 - a);
806 case AV_PIX_FMT_YUV422P10LE:
808 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
809 dcp::Size const ts = size();
810 dcp::Size const os = yuv->size();
811 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
812 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
813 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
814 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
815 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
816 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
817 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
818 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
819 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
820 float const a = float(alpha[3]) / 255;
821 *tY = *oY * a + *tY * (1 - a);
822 *tU = *oU * a + *tU * (1 - a);
823 *tV = *oV * a + *tV * (1 - a);
840 throw PixelFormatError ("alpha_blend()", _pixel_format);
845 Image::copy (shared_ptr<const Image> other, Position<int> position)
847 /* Only implemented for RGB24 onto RGB24 so far */
848 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
849 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
851 int const N = min (position.x + other->size().width, size().width) - position.x;
852 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
853 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
854 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
855 memcpy (tp, op, N * 3);
860 Image::read_from_socket (shared_ptr<Socket> socket)
862 for (int i = 0; i < planes(); ++i) {
863 uint8_t* p = data()[i];
864 int const lines = sample_size(i).height;
865 for (int y = 0; y < lines; ++y) {
866 socket->read (p, line_size()[i]);
873 Image::write_to_socket (shared_ptr<Socket> socket) const
875 for (int i = 0; i < planes(); ++i) {
876 uint8_t* p = data()[i];
877 int const lines = sample_size(i).height;
878 for (int y = 0; y < lines; ++y) {
879 socket->write (p, line_size()[i]);
886 Image::bytes_per_pixel (int c) const
888 auto d = av_pix_fmt_desc_get(_pixel_format);
890 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
897 float bpp[4] = { 0, 0, 0, 0 };
899 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
900 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
901 if (d->nb_components > 1) {
902 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
904 if (d->nb_components > 2) {
905 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
907 if (d->nb_components > 3) {
908 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
911 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
912 if (d->nb_components > 1) {
913 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
915 if (d->nb_components > 2) {
916 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
918 if (d->nb_components > 3) {
919 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
923 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
924 /* Not planar; sum them up */
925 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
931 /** Construct a Image of a given size and format, allocating memory
934 * @param p Pixel format.
935 * @param s Size in pixels.
936 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
938 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
941 , _alignment (alignment)
950 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
951 _data[0] = _data[1] = _data[2] = _data[3] = 0;
953 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
954 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
956 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
957 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
959 for (int i = 0; i < planes(); ++i) {
960 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
961 _stride[i] = stride_round_up (i, _line_size, _alignment == Alignment::PADDED ? ALIGNMENT : 1);
963 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
964 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
965 Hence on the last pixel of the last line it reads over the end of
966 the actual data by 1 byte. If the width of an image is a multiple
967 of the stride alignment there will be no padding at the end of image lines.
968 OS X crashes on this illegal read, though other operating systems don't
969 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
970 for that instruction to read safely.
972 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
973 over-reads by more then _avx. I can't follow the code to work out how much,
974 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
975 testing suggests that it works.
977 In addition to these concerns, we may read/write as much as a whole extra line
978 at the end of each plane in cases where we are messing with offsets in order to
979 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
981 As an example: we may write to images starting at an offset so we get some padding.
982 Hence we want to write in the following pattern:
984 block start write start line end
985 |..(padding)..|<------line-size------------->|..(padding)..|
986 |..(padding)..|<------line-size------------->|..(padding)..|
987 |..(padding)..|<------line-size------------->|..(padding)..|
989 where line-size is of the smaller (inter_size) image and the full padded line length is that of
990 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
991 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
992 specified *stride*. This does not matter until we get to the last line:
994 block start write start line end
995 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
996 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
997 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1000 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1001 #if HAVE_VALGRIND_MEMCHECK_H
1002 /* The data between the end of the line size and the stride is undefined but processed by
1003 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1005 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1010 Image::Image (Image const & other)
1011 : std::enable_shared_from_this<Image>(other)
1012 , _size (other._size)
1013 , _pixel_format (other._pixel_format)
1014 , _alignment (other._alignment)
1018 for (int i = 0; i < planes(); ++i) {
1019 uint8_t* p = _data[i];
1020 uint8_t* q = other._data[i];
1021 int const lines = sample_size(i).height;
1022 for (int j = 0; j < lines; ++j) {
1023 memcpy (p, q, _line_size[i]);
1025 q += other.stride()[i];
1030 Image::Image (AVFrame const * frame, Alignment alignment)
1031 : _size (frame->width, frame->height)
1032 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1033 , _alignment (alignment)
1035 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1039 for (int i = 0; i < planes(); ++i) {
1040 uint8_t* p = _data[i];
1041 uint8_t* q = frame->data[i];
1042 int const lines = sample_size(i).height;
1043 for (int j = 0; j < lines; ++j) {
1044 memcpy (p, q, _line_size[i]);
1046 /* AVFrame's linesize is what we call `stride' */
1047 q += frame->linesize[i];
1052 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1053 : _size (other->_size)
1054 , _pixel_format (other->_pixel_format)
1055 , _alignment (alignment)
1059 for (int i = 0; i < planes(); ++i) {
1060 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1061 uint8_t* p = _data[i];
1062 uint8_t* q = other->data()[i];
1063 int const lines = sample_size(i).height;
1064 for (int j = 0; j < lines; ++j) {
1065 memcpy (p, q, line_size()[i]);
1067 q += other->stride()[i];
1073 Image::operator= (Image const & other)
1075 if (this == &other) {
1085 Image::swap (Image & other)
1087 std::swap (_size, other._size);
1088 std::swap (_pixel_format, other._pixel_format);
1090 for (int i = 0; i < 4; ++i) {
1091 std::swap (_data[i], other._data[i]);
1092 std::swap (_line_size[i], other._line_size[i]);
1093 std::swap (_stride[i], other._stride[i]);
1096 std::swap (_alignment, other._alignment);
1101 for (int i = 0; i < planes(); ++i) {
1106 av_free (_line_size);
1111 Image::data () const
1117 Image::line_size () const
1123 Image::stride () const
1129 Image::size () const
1135 Image::alignment () const
1142 merge (list<PositionImage> images, Image::Alignment alignment)
1144 if (images.empty ()) {
1148 if (images.size() == 1) {
1149 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1150 return images.front();
1153 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1154 for (auto const& i: images) {
1155 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1158 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1159 merged->make_transparent ();
1160 for (auto const& i: images) {
1161 merged->alpha_blend (i.image, i.position - all.position());
1164 return PositionImage (merged, all.position ());
1169 operator== (Image const & a, Image const & b)
1171 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1175 for (int c = 0; c < a.planes(); ++c) {
1176 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]) {
1180 uint8_t* p = a.data()[c];
1181 uint8_t* q = b.data()[c];
1182 int const lines = a.sample_size(c).height;
1183 for (int y = 0; y < lines; ++y) {
1184 if (memcmp (p, q, a.line_size()[c]) != 0) {
1197 * @param f Amount to fade by; 0 is black, 1 is no fade.
1200 Image::fade (float f)
1202 /* U/V black value for 8-bit colour */
1203 static int const eight_bit_uv = (1 << 7) - 1;
1204 /* U/V black value for 10-bit colour */
1205 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1207 switch (_pixel_format) {
1208 case AV_PIX_FMT_YUV420P:
1211 uint8_t* p = data()[0];
1212 int const lines = sample_size(0).height;
1213 for (int y = 0; y < lines; ++y) {
1215 for (int x = 0; x < line_size()[0]; ++x) {
1216 *q = int(float(*q) * f);
1223 for (int c = 1; c < 3; ++c) {
1224 uint8_t* p = data()[c];
1225 int const lines = sample_size(c).height;
1226 for (int y = 0; y < lines; ++y) {
1228 for (int x = 0; x < line_size()[c]; ++x) {
1229 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1239 case AV_PIX_FMT_RGB24:
1242 uint8_t* p = data()[0];
1243 int const lines = sample_size(0).height;
1244 for (int y = 0; y < lines; ++y) {
1246 for (int x = 0; x < line_size()[0]; ++x) {
1247 *q = int (float (*q) * f);
1255 case AV_PIX_FMT_XYZ12LE:
1256 case AV_PIX_FMT_RGB48LE:
1257 /* 16-bit little-endian */
1258 for (int c = 0; c < 3; ++c) {
1259 int const stride_pixels = stride()[c] / 2;
1260 int const line_size_pixels = line_size()[c] / 2;
1261 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1262 int const lines = sample_size(c).height;
1263 for (int y = 0; y < lines; ++y) {
1265 for (int x = 0; x < line_size_pixels; ++x) {
1266 *q = int (float (*q) * f);
1274 case AV_PIX_FMT_YUV422P10LE:
1278 int const stride_pixels = stride()[0] / 2;
1279 int const line_size_pixels = line_size()[0] / 2;
1280 uint16_t* p = reinterpret_cast<uint16_t*> (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_pixels; ++x) {
1285 *q = int(float(*q) * f);
1293 for (int c = 1; c < 3; ++c) {
1294 int const stride_pixels = stride()[c] / 2;
1295 int const line_size_pixels = line_size()[c] / 2;
1296 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1297 int const lines = sample_size(c).height;
1298 for (int y = 0; y < lines; ++y) {
1300 for (int x = 0; x < line_size_pixels; ++x) {
1301 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1312 throw PixelFormatError ("fade()", _pixel_format);
1317 shared_ptr<const Image>
1318 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1320 if (image->alignment() == alignment) {
1324 return make_shared<Image>(image, alignment);
1329 Image::memory_used () const
1332 for (int i = 0; i < planes(); ++i) {
1333 m += _stride[i] * sample_size(i).height;
1340 Image::video_range_to_full_range ()
1342 switch (_pixel_format) {
1343 case AV_PIX_FMT_RGB24:
1345 float const factor = 256.0 / 219.0;
1346 uint8_t* p = data()[0];
1347 int const lines = sample_size(0).height;
1348 for (int y = 0; y < lines; ++y) {
1350 for (int x = 0; x < line_size()[0]; ++x) {
1351 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1358 case AV_PIX_FMT_RGB48LE:
1360 float const factor = 65536.0 / 56064.0;
1361 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1362 int const lines = sample_size(0).height;
1363 for (int y = 0; y < lines; ++y) {
1365 int const line_size_pixels = line_size()[0] / 2;
1366 for (int x = 0; x < line_size_pixels; ++x) {
1367 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1370 p += stride()[0] / 2;
1374 case AV_PIX_FMT_GBRP12LE:
1376 float const factor = 4096.0 / 3504.0;
1377 for (int c = 0; c < 3; ++c) {
1378 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1379 int const lines = sample_size(c).height;
1380 for (int y = 0; y < lines; ++y) {
1382 int const line_size_pixels = line_size()[c] / 2;
1383 for (int x = 0; x < line_size_pixels; ++x) {
1384 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1392 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);