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));
110 /** @param n Component index.
111 * @return Number of samples (i.e. pixels, unless sub-sampled) in each direction for this component.
114 Image::sample_size (int n) const
117 lrint (ceil(static_cast<double>(size().width) / horizontal_factor(n))),
118 lrint (ceil(static_cast<double>(size().height) / vertical_factor(n)))
123 /** @return Number of planes */
125 Image::planes () const
127 if (_pixel_format == AV_PIX_FMT_PAL8) {
131 auto d = av_pix_fmt_desc_get(_pixel_format);
133 throw PixelFormatError ("planes()", _pixel_format);
136 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
140 return d->nb_components;
146 round_width_for_subsampling (int p, AVPixFmtDescriptor const * desc)
148 return p & ~ ((1 << desc->log2_chroma_w) - 1);
154 round_height_for_subsampling (int p, AVPixFmtDescriptor const * desc)
156 return p & ~ ((1 << desc->log2_chroma_h) - 1);
160 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size'.
161 * @param crop Amount to crop by.
162 * @param inter_size Size to scale the cropped image to.
163 * @param out_size Size of output frame; if this is larger than inter_size there will be black padding.
164 * @param yuv_to_rgb YUV to RGB transformation to use, if required.
165 * @param video_range Video range of the image.
166 * @param out_format Output pixel format.
167 * @param out_aligned true to make the output image aligned.
168 * @param out_video_range Video range to use for the output image.
169 * @param fast Try to be fast at the possible expense of quality; at present this means using
170 * fast bilinear rather than bicubic scaling.
173 Image::crop_scale_window (
175 dcp::Size inter_size,
177 dcp::YUVToRGB yuv_to_rgb,
178 VideoRange video_range,
179 AVPixelFormat out_format,
180 VideoRange out_video_range,
181 Alignment out_alignment,
185 /* Empirical testing suggests that sws_scale() will crash if
186 the input image is not padded.
188 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
190 DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
191 DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
193 auto out = make_shared<Image>(out_format, out_size, out_alignment);
196 auto in_desc = av_pix_fmt_desc_get (_pixel_format);
198 throw PixelFormatError ("crop_scale_window()", _pixel_format);
201 /* Round down so that we crop only the number of pixels that is straightforward
202 * considering any subsampling.
205 round_width_for_subsampling(crop.left, in_desc),
206 round_width_for_subsampling(crop.right, in_desc),
207 round_height_for_subsampling(crop.top, in_desc),
208 round_height_for_subsampling(crop.bottom, in_desc)
211 /* Also check that we aren't cropping more image than there actually is */
212 if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
213 corrected_crop.left = 0;
214 corrected_crop.right = size().width - 4;
217 if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
218 corrected_crop.top = 0;
219 corrected_crop.bottom = size().height - 4;
222 /* Size of the image after any crop */
223 auto const cropped_size = corrected_crop.apply (size());
225 /* Scale context for a scale from cropped_size to inter_size */
226 auto scale_context = sws_getContext (
227 cropped_size.width, cropped_size.height, pixel_format(),
228 inter_size.width, inter_size.height, out_format,
229 fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
232 if (!scale_context) {
233 throw runtime_error (N_("Could not allocate SwsContext"));
236 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
237 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
242 /* The 3rd parameter here is:
243 0 -> source range MPEG (i.e. "video", 16-235)
244 1 -> source range JPEG (i.e. "full", 0-255)
246 0 -> destination range MPEG (i.e. "video", 16-235)
247 1 -> destination range JPEG (i.e. "full", 0-255)
249 But remember: sws_setColorspaceDetails ignores these
250 parameters unless the both source and destination images
251 are isYUV or isGray. (If either is not, it uses video range).
253 sws_setColorspaceDetails (
255 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VideoRange::VIDEO ? 0 : 1,
256 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VideoRange::VIDEO ? 0 : 1,
260 /* Prepare input data pointers with crop */
261 uint8_t* scale_in_data[planes()];
262 for (int c = 0; c < planes(); ++c) {
263 int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
264 scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
267 auto out_desc = av_pix_fmt_desc_get (out_format);
269 throw PixelFormatError ("crop_scale_window()", out_format);
272 /* Corner of the image within out_size */
273 Position<int> const corner (
274 round_width_for_subsampling((out_size.width - inter_size.width) / 2, out_desc),
275 round_height_for_subsampling((out_size.height - inter_size.height) / 2, out_desc)
278 uint8_t* scale_out_data[out->planes()];
279 for (int c = 0; c < out->planes(); ++c) {
280 int const x = lrintf(out->bytes_per_pixel(c) * corner.x);
281 scale_out_data[c] = out->data()[c] + x + out->stride()[c] * (corner.y / out->vertical_factor(c));
286 scale_in_data, stride(),
287 0, cropped_size.height,
288 scale_out_data, out->stride()
291 sws_freeContext (scale_context);
293 if (corrected_crop != Crop() && cropped_size == inter_size) {
294 /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
295 data behind in our image. Clear it out. It may get to the point where we should just stop
296 trying to be clever with cropping.
298 out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
302 video_range == VideoRange::VIDEO &&
303 out_video_range == VideoRange::FULL &&
304 av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
306 /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
307 out->video_range_to_full_range ();
315 Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
317 return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
321 /** @param out_size Size to scale to.
322 * @param yuv_to_rgb YUVToRGB transform transform to use, if required.
323 * @param out_format Output pixel format.
324 * @param out_aligment Output alignment.
325 * @param fast Try to be fast at the possible expense of quality; at present this means using
326 * fast bilinear rather than bicubic scaling.
329 Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
331 /* Empirical testing suggests that sws_scale() will crash if
332 the input image alignment is not PADDED.
334 DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
336 auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
337 auto scale_context = sws_getContext (
338 size().width, size().height, pixel_format(),
339 out_size.width, out_size.height, out_format,
340 (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
343 DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
344 int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
349 /* The 3rd parameter here is:
350 0 -> source range MPEG (i.e. "video", 16-235)
351 1 -> source range JPEG (i.e. "full", 0-255)
353 0 -> destination range MPEG (i.e. "video", 16-235)
354 1 -> destination range JPEG (i.e. "full", 0-255)
356 But remember: sws_setColorspaceDetails ignores these
357 parameters unless the corresponding image isYUV or isGray.
358 (If it's neither, it uses video range).
360 sws_setColorspaceDetails (
362 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
363 sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
371 scaled->data(), scaled->stride()
374 sws_freeContext (scale_context);
380 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
382 Image::yuv_16_black (uint16_t v, bool alpha)
384 memset (data()[0], 0, sample_size(0).height * stride()[0]);
385 for (int i = 1; i < 3; ++i) {
386 auto p = reinterpret_cast<int16_t*> (data()[i]);
387 int const lines = sample_size(i).height;
388 for (int y = 0; y < lines; ++y) {
389 /* We divide by 2 here because we are writing 2 bytes at a time */
390 for (int x = 0; x < line_size()[i] / 2; ++x) {
393 p += stride()[i] / 2;
398 memset (data()[3], 0, sample_size(3).height * stride()[3]);
404 Image::swap_16 (uint16_t v)
406 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
411 Image::make_part_black (int const start, int const width)
413 auto y_part = [&]() {
414 int const bpp = bytes_per_pixel(0);
415 int const h = sample_size(0).height;
416 int const s = stride()[0];
418 for (int y = 0; y < h; ++y) {
419 memset (p + start * bpp, 0, width * bpp);
424 switch (_pixel_format) {
425 case AV_PIX_FMT_RGB24:
426 case AV_PIX_FMT_ARGB:
427 case AV_PIX_FMT_RGBA:
428 case AV_PIX_FMT_ABGR:
429 case AV_PIX_FMT_BGRA:
430 case AV_PIX_FMT_RGB555LE:
431 case AV_PIX_FMT_RGB48LE:
432 case AV_PIX_FMT_RGB48BE:
433 case AV_PIX_FMT_XYZ12LE:
435 int const h = sample_size(0).height;
436 int const bpp = bytes_per_pixel(0);
437 int const s = stride()[0];
438 uint8_t* p = data()[0];
439 for (int y = 0; y < h; y++) {
440 memset (p + start * bpp, 0, width * bpp);
445 case AV_PIX_FMT_YUV420P:
448 for (int i = 1; i < 3; ++i) {
450 int const h = sample_size(i).height;
451 for (int y = 0; y < h; ++y) {
452 for (int x = start / 2; x < (start + width) / 2; ++x) {
460 case AV_PIX_FMT_YUV422P10LE:
463 for (int i = 1; i < 3; ++i) {
464 auto p = reinterpret_cast<int16_t*>(data()[i]);
465 int const h = sample_size(i).height;
466 for (int y = 0; y < h; ++y) {
467 for (int x = start / 2; x < (start + width) / 2; ++x) {
470 p += stride()[i] / 2;
476 throw PixelFormatError ("make_part_black()", _pixel_format);
484 switch (_pixel_format) {
485 case AV_PIX_FMT_YUV420P:
486 case AV_PIX_FMT_YUV422P:
487 case AV_PIX_FMT_YUV444P:
488 case AV_PIX_FMT_YUV411P:
489 memset (data()[0], 0, sample_size(0).height * stride()[0]);
490 memset (data()[1], eight_bit_uv, sample_size(1).height * stride()[1]);
491 memset (data()[2], eight_bit_uv, sample_size(2).height * stride()[2]);
494 case AV_PIX_FMT_YUVJ420P:
495 case AV_PIX_FMT_YUVJ422P:
496 case AV_PIX_FMT_YUVJ444P:
497 memset (data()[0], 0, sample_size(0).height * stride()[0]);
498 memset (data()[1], eight_bit_uv + 1, sample_size(1).height * stride()[1]);
499 memset (data()[2], eight_bit_uv + 1, sample_size(2).height * stride()[2]);
502 case AV_PIX_FMT_YUV422P9LE:
503 case AV_PIX_FMT_YUV444P9LE:
504 yuv_16_black (nine_bit_uv, false);
507 case AV_PIX_FMT_YUV422P9BE:
508 case AV_PIX_FMT_YUV444P9BE:
509 yuv_16_black (swap_16 (nine_bit_uv), false);
512 case AV_PIX_FMT_YUV422P10LE:
513 case AV_PIX_FMT_YUV444P10LE:
514 yuv_16_black (ten_bit_uv, false);
517 case AV_PIX_FMT_YUV422P16LE:
518 case AV_PIX_FMT_YUV444P16LE:
519 yuv_16_black (sixteen_bit_uv, false);
522 case AV_PIX_FMT_YUV444P10BE:
523 case AV_PIX_FMT_YUV422P10BE:
524 yuv_16_black (swap_16 (ten_bit_uv), false);
527 case AV_PIX_FMT_YUVA420P9BE:
528 case AV_PIX_FMT_YUVA422P9BE:
529 case AV_PIX_FMT_YUVA444P9BE:
530 yuv_16_black (swap_16 (nine_bit_uv), true);
533 case AV_PIX_FMT_YUVA420P9LE:
534 case AV_PIX_FMT_YUVA422P9LE:
535 case AV_PIX_FMT_YUVA444P9LE:
536 yuv_16_black (nine_bit_uv, true);
539 case AV_PIX_FMT_YUVA420P10BE:
540 case AV_PIX_FMT_YUVA422P10BE:
541 case AV_PIX_FMT_YUVA444P10BE:
542 yuv_16_black (swap_16 (ten_bit_uv), true);
545 case AV_PIX_FMT_YUVA420P10LE:
546 case AV_PIX_FMT_YUVA422P10LE:
547 case AV_PIX_FMT_YUVA444P10LE:
548 yuv_16_black (ten_bit_uv, true);
551 case AV_PIX_FMT_YUVA420P16BE:
552 case AV_PIX_FMT_YUVA422P16BE:
553 case AV_PIX_FMT_YUVA444P16BE:
554 yuv_16_black (swap_16 (sixteen_bit_uv), true);
557 case AV_PIX_FMT_YUVA420P16LE:
558 case AV_PIX_FMT_YUVA422P16LE:
559 case AV_PIX_FMT_YUVA444P16LE:
560 yuv_16_black (sixteen_bit_uv, true);
563 case AV_PIX_FMT_RGB24:
564 case AV_PIX_FMT_ARGB:
565 case AV_PIX_FMT_RGBA:
566 case AV_PIX_FMT_ABGR:
567 case AV_PIX_FMT_BGRA:
568 case AV_PIX_FMT_RGB555LE:
569 case AV_PIX_FMT_RGB48LE:
570 case AV_PIX_FMT_RGB48BE:
571 case AV_PIX_FMT_XYZ12LE:
572 memset (data()[0], 0, sample_size(0).height * stride()[0]);
575 case AV_PIX_FMT_UYVY422:
577 int const Y = sample_size(0).height;
578 int const X = line_size()[0];
579 uint8_t* p = data()[0];
580 for (int y = 0; y < Y; ++y) {
581 for (int x = 0; x < X / 4; ++x) {
582 *p++ = eight_bit_uv; // Cb
584 *p++ = eight_bit_uv; // Cr
592 throw PixelFormatError ("make_black()", _pixel_format);
598 Image::make_transparent ()
600 if (_pixel_format != AV_PIX_FMT_BGRA && _pixel_format != AV_PIX_FMT_RGBA) {
601 throw PixelFormatError ("make_transparent()", _pixel_format);
604 memset (data()[0], 0, sample_size(0).height * stride()[0]);
609 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
611 /* We're blending RGBA or BGRA images */
612 DCPOMATIC_ASSERT (other->pixel_format() == AV_PIX_FMT_BGRA || other->pixel_format() == AV_PIX_FMT_RGBA);
613 int const blue = other->pixel_format() == AV_PIX_FMT_BGRA ? 0 : 2;
614 int const red = other->pixel_format() == AV_PIX_FMT_BGRA ? 2 : 0;
616 int const other_bpp = 4;
618 int start_tx = position.x;
622 start_ox = -start_tx;
626 int start_ty = position.y;
630 start_oy = -start_ty;
634 switch (_pixel_format) {
635 case AV_PIX_FMT_RGB24:
637 /* Going onto RGB24. First byte is red, second green, third blue */
638 int const this_bpp = 3;
639 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
640 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
641 uint8_t* op = other->data()[0] + oy * other->stride()[0];
642 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
643 float const alpha = float (op[3]) / 255;
644 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
645 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
646 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
654 case AV_PIX_FMT_BGRA:
656 int const this_bpp = 4;
657 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
658 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
659 uint8_t* op = other->data()[0] + oy * other->stride()[0];
660 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
661 float const alpha = float (op[3]) / 255;
662 tp[0] = op[blue] * alpha + tp[0] * (1 - alpha);
663 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
664 tp[2] = op[red] * alpha + tp[2] * (1 - alpha);
665 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
673 case AV_PIX_FMT_RGBA:
675 int const this_bpp = 4;
676 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
677 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
678 uint8_t* op = other->data()[0] + oy * other->stride()[0];
679 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
680 float const alpha = float (op[3]) / 255;
681 tp[0] = op[red] * alpha + tp[0] * (1 - alpha);
682 tp[1] = op[1] * alpha + tp[1] * (1 - alpha);
683 tp[2] = op[blue] * alpha + tp[2] * (1 - alpha);
684 tp[3] = op[3] * alpha + tp[3] * (1 - alpha);
692 case AV_PIX_FMT_RGB48LE:
694 int const this_bpp = 6;
695 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
696 uint8_t* tp = data()[0] + ty * stride()[0] + start_tx * this_bpp;
697 uint8_t* op = other->data()[0] + oy * other->stride()[0];
698 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
699 float const alpha = float (op[3]) / 255;
700 /* Blend high bytes */
701 tp[1] = op[red] * alpha + tp[1] * (1 - alpha);
702 tp[3] = op[1] * alpha + tp[3] * (1 - alpha);
703 tp[5] = op[blue] * alpha + tp[5] * (1 - alpha);
711 case AV_PIX_FMT_XYZ12LE:
713 auto conv = dcp::ColourConversion::srgb_to_xyz();
714 double fast_matrix[9];
715 dcp::combined_rgb_to_xyz (conv, fast_matrix);
716 double const * lut_in = conv.in()->lut (8, false);
717 double const * lut_out = conv.out()->lut (16, true);
718 int const this_bpp = 6;
719 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
720 uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
721 uint8_t* op = other->data()[0] + oy * other->stride()[0];
722 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
723 float const alpha = float (op[3]) / 255;
725 /* Convert sRGB to XYZ; op is BGRA. First, input gamma LUT */
726 double const r = lut_in[op[red]];
727 double const g = lut_in[op[1]];
728 double const b = lut_in[op[blue]];
730 /* RGB to XYZ, including Bradford transform and DCI companding */
731 double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
732 double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
733 double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
735 /* Out gamma LUT and blend */
736 tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
737 tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
738 tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
746 case AV_PIX_FMT_YUV420P:
748 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
749 dcp::Size const ts = size();
750 dcp::Size const os = yuv->size();
751 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
752 int const hty = ty / 2;
753 int const hoy = oy / 2;
754 uint8_t* tY = data()[0] + (ty * stride()[0]) + start_tx;
755 uint8_t* tU = data()[1] + (hty * stride()[1]) + start_tx / 2;
756 uint8_t* tV = data()[2] + (hty * stride()[2]) + start_tx / 2;
757 uint8_t* oY = yuv->data()[0] + (oy * yuv->stride()[0]) + start_ox;
758 uint8_t* oU = yuv->data()[1] + (hoy * yuv->stride()[1]) + start_ox / 2;
759 uint8_t* oV = yuv->data()[2] + (hoy * yuv->stride()[2]) + start_ox / 2;
760 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
761 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
762 float const a = float(alpha[3]) / 255;
763 *tY = *oY * a + *tY * (1 - a);
764 *tU = *oU * a + *tU * (1 - a);
765 *tV = *oV * a + *tV * (1 - a);
781 case AV_PIX_FMT_YUV420P10:
783 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
784 dcp::Size const ts = size();
785 dcp::Size const os = yuv->size();
786 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
787 int const hty = ty / 2;
788 int const hoy = oy / 2;
789 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
790 uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
791 uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
792 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
793 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
794 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
795 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
796 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
797 float const a = float(alpha[3]) / 255;
798 *tY = *oY * a + *tY * (1 - a);
799 *tU = *oU * a + *tU * (1 - a);
800 *tV = *oV * a + *tV * (1 - a);
816 case AV_PIX_FMT_YUV422P10LE:
818 auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
819 dcp::Size const ts = size();
820 dcp::Size const os = yuv->size();
821 for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
822 uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
823 uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
824 uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
825 uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
826 uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
827 uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
828 uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
829 for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
830 float const a = float(alpha[3]) / 255;
831 *tY = *oY * a + *tY * (1 - a);
832 *tU = *oU * a + *tU * (1 - a);
833 *tV = *oV * a + *tV * (1 - a);
850 throw PixelFormatError ("alpha_blend()", _pixel_format);
856 Image::copy (shared_ptr<const Image> other, Position<int> position)
858 /* Only implemented for RGB24 onto RGB24 so far */
859 DCPOMATIC_ASSERT (_pixel_format == AV_PIX_FMT_RGB24 && other->pixel_format() == AV_PIX_FMT_RGB24);
860 DCPOMATIC_ASSERT (position.x >= 0 && position.y >= 0);
862 int const N = min (position.x + other->size().width, size().width) - position.x;
863 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
864 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
865 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
866 memcpy (tp, op, N * 3);
872 Image::read_from_socket (shared_ptr<Socket> socket)
874 for (int i = 0; i < planes(); ++i) {
875 uint8_t* p = data()[i];
876 int const lines = sample_size(i).height;
877 for (int y = 0; y < lines; ++y) {
878 socket->read (p, line_size()[i]);
886 Image::write_to_socket (shared_ptr<Socket> socket) const
888 for (int i = 0; i < planes(); ++i) {
889 uint8_t* p = data()[i];
890 int const lines = sample_size(i).height;
891 for (int y = 0; y < lines; ++y) {
892 socket->write (p, line_size()[i]);
900 Image::bytes_per_pixel (int c) const
902 auto d = av_pix_fmt_desc_get(_pixel_format);
904 throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
911 float bpp[4] = { 0, 0, 0, 0 };
913 #ifdef DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1
914 bpp[0] = floor ((d->comp[0].depth_minus1 + 8) / 8);
915 if (d->nb_components > 1) {
916 bpp[1] = floor ((d->comp[1].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
918 if (d->nb_components > 2) {
919 bpp[2] = floor ((d->comp[2].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
921 if (d->nb_components > 3) {
922 bpp[3] = floor ((d->comp[3].depth_minus1 + 8) / 8) / pow (2.0f, d->log2_chroma_w);
925 bpp[0] = floor ((d->comp[0].depth + 7) / 8);
926 if (d->nb_components > 1) {
927 bpp[1] = floor ((d->comp[1].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
929 if (d->nb_components > 2) {
930 bpp[2] = floor ((d->comp[2].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
932 if (d->nb_components > 3) {
933 bpp[3] = floor ((d->comp[3].depth + 7) / 8) / pow (2.0f, d->log2_chroma_w);
937 if ((d->flags & AV_PIX_FMT_FLAG_PLANAR) == 0) {
938 /* Not planar; sum them up */
939 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
946 /** Construct a Image of a given size and format, allocating memory
949 * @param p Pixel format.
950 * @param s Size in pixels.
951 * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
953 Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
956 , _alignment (alignment)
965 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
966 _data[0] = _data[1] = _data[2] = _data[3] = 0;
968 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
969 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
971 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
972 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
974 for (int i = 0; i < planes(); ++i) {
975 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
976 _stride[i] = stride_round_up (i, _line_size, _alignment == Alignment::PADDED ? ALIGNMENT : 1);
978 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
979 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
980 Hence on the last pixel of the last line it reads over the end of
981 the actual data by 1 byte. If the width of an image is a multiple
982 of the stride alignment there will be no padding at the end of image lines.
983 OS X crashes on this illegal read, though other operating systems don't
984 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
985 for that instruction to read safely.
987 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
988 over-reads by more then _avx. I can't follow the code to work out how much,
989 so I'll just over-allocate by ALIGNMENT bytes and have done with it. Empirical
990 testing suggests that it works.
992 In addition to these concerns, we may read/write as much as a whole extra line
993 at the end of each plane in cases where we are messing with offsets in order to
994 do pad or crop. To solve this we over-allocate by an extra _stride[i] bytes.
996 As an example: we may write to images starting at an offset so we get some padding.
997 Hence we want to write in the following pattern:
999 block start write start line end
1000 |..(padding)..|<------line-size------------->|..(padding)..|
1001 |..(padding)..|<------line-size------------->|..(padding)..|
1002 |..(padding)..|<------line-size------------->|..(padding)..|
1004 where line-size is of the smaller (inter_size) image and the full padded line length is that of
1005 out_size. To get things to work we have to tell FFmpeg that the stride is that of out_size.
1006 However some parts of FFmpeg (notably rgb48Toxyz12 in swscale.c) process data for the full
1007 specified *stride*. This does not matter until we get to the last line:
1009 block start write start line end
1010 |..(padding)..|<------line-size------------->|XXXwrittenXXX|
1011 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXX|
1012 |XXXwrittenXXX|<------line-size------------->|XXXwrittenXXXXXXwrittenXXX
1015 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1016 #if HAVE_VALGRIND_MEMCHECK_H
1017 /* The data between the end of the line size and the stride is undefined but processed by
1018 libswscale, causing lots of valgrind errors. Mark it all defined to quell these errors.
1020 VALGRIND_MAKE_MEM_DEFINED (_data[i], _stride[i] * (sample_size(i).height + 1) + ALIGNMENT);
1026 Image::Image (Image const & other)
1027 : std::enable_shared_from_this<Image>(other)
1028 , _size (other._size)
1029 , _pixel_format (other._pixel_format)
1030 , _alignment (other._alignment)
1034 for (int i = 0; i < planes(); ++i) {
1035 uint8_t* p = _data[i];
1036 uint8_t* q = other._data[i];
1037 int const lines = sample_size(i).height;
1038 for (int j = 0; j < lines; ++j) {
1039 memcpy (p, q, _line_size[i]);
1041 q += other.stride()[i];
1047 Image::Image (AVFrame const * frame, Alignment alignment)
1048 : _size (frame->width, frame->height)
1049 , _pixel_format (static_cast<AVPixelFormat>(frame->format))
1050 , _alignment (alignment)
1052 DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
1056 for (int i = 0; i < planes(); ++i) {
1057 uint8_t* p = _data[i];
1058 uint8_t* q = frame->data[i];
1059 int const lines = sample_size(i).height;
1060 for (int j = 0; j < lines; ++j) {
1061 memcpy (p, q, _line_size[i]);
1063 /* AVFrame's linesize is what we call `stride' */
1064 q += frame->linesize[i];
1070 Image::Image (shared_ptr<const Image> other, Alignment alignment)
1071 : _size (other->_size)
1072 , _pixel_format (other->_pixel_format)
1073 , _alignment (alignment)
1077 for (int i = 0; i < planes(); ++i) {
1078 DCPOMATIC_ASSERT (line_size()[i] == other->line_size()[i]);
1079 uint8_t* p = _data[i];
1080 uint8_t* q = other->data()[i];
1081 int const lines = sample_size(i).height;
1082 for (int j = 0; j < lines; ++j) {
1083 memcpy (p, q, line_size()[i]);
1085 q += other->stride()[i];
1092 Image::operator= (Image const & other)
1094 if (this == &other) {
1105 Image::swap (Image & other)
1107 std::swap (_size, other._size);
1108 std::swap (_pixel_format, other._pixel_format);
1110 for (int i = 0; i < 4; ++i) {
1111 std::swap (_data[i], other._data[i]);
1112 std::swap (_line_size[i], other._line_size[i]);
1113 std::swap (_stride[i], other._stride[i]);
1116 std::swap (_alignment, other._alignment);
1122 for (int i = 0; i < planes(); ++i) {
1127 av_free (_line_size);
1133 Image::data () const
1140 Image::line_size () const
1147 Image::stride () const
1154 Image::size () const
1161 Image::alignment () const
1168 merge (list<PositionImage> images, Image::Alignment alignment)
1170 if (images.empty ()) {
1174 if (images.size() == 1) {
1175 images.front().image = Image::ensure_alignment(images.front().image, alignment);
1176 return images.front();
1179 dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
1180 for (auto const& i: images) {
1181 all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
1184 auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
1185 merged->make_transparent ();
1186 for (auto const& i: images) {
1187 merged->alpha_blend (i.image, i.position - all.position());
1190 return PositionImage (merged, all.position ());
1195 operator== (Image const & a, Image const & b)
1197 if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
1201 for (int c = 0; c < a.planes(); ++c) {
1202 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]) {
1206 uint8_t* p = a.data()[c];
1207 uint8_t* q = b.data()[c];
1208 int const lines = a.sample_size(c).height;
1209 for (int y = 0; y < lines; ++y) {
1210 if (memcmp (p, q, a.line_size()[c]) != 0) {
1224 * @param f Amount to fade by; 0 is black, 1 is no fade.
1227 Image::fade (float f)
1229 /* U/V black value for 8-bit colour */
1230 static int const eight_bit_uv = (1 << 7) - 1;
1231 /* U/V black value for 10-bit colour */
1232 static uint16_t const ten_bit_uv = (1 << 9) - 1;
1234 switch (_pixel_format) {
1235 case AV_PIX_FMT_YUV420P:
1238 uint8_t* p = data()[0];
1239 int const lines = sample_size(0).height;
1240 for (int y = 0; y < lines; ++y) {
1242 for (int x = 0; x < line_size()[0]; ++x) {
1243 *q = int(float(*q) * f);
1250 for (int c = 1; c < 3; ++c) {
1251 uint8_t* p = data()[c];
1252 int const lines = sample_size(c).height;
1253 for (int y = 0; y < lines; ++y) {
1255 for (int x = 0; x < line_size()[c]; ++x) {
1256 *q = eight_bit_uv + int((int(*q) - eight_bit_uv) * f);
1266 case AV_PIX_FMT_RGB24:
1269 uint8_t* p = data()[0];
1270 int const lines = sample_size(0).height;
1271 for (int y = 0; y < lines; ++y) {
1273 for (int x = 0; x < line_size()[0]; ++x) {
1274 *q = int (float (*q) * f);
1282 case AV_PIX_FMT_XYZ12LE:
1283 case AV_PIX_FMT_RGB48LE:
1284 /* 16-bit little-endian */
1285 for (int c = 0; c < 3; ++c) {
1286 int const stride_pixels = stride()[c] / 2;
1287 int const line_size_pixels = line_size()[c] / 2;
1288 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1289 int const lines = sample_size(c).height;
1290 for (int y = 0; y < lines; ++y) {
1292 for (int x = 0; x < line_size_pixels; ++x) {
1293 *q = int (float (*q) * f);
1301 case AV_PIX_FMT_YUV422P10LE:
1305 int const stride_pixels = stride()[0] / 2;
1306 int const line_size_pixels = line_size()[0] / 2;
1307 uint16_t* p = reinterpret_cast<uint16_t*> (data()[0]);
1308 int const lines = sample_size(0).height;
1309 for (int y = 0; y < lines; ++y) {
1311 for (int x = 0; x < line_size_pixels; ++x) {
1312 *q = int(float(*q) * f);
1320 for (int c = 1; c < 3; ++c) {
1321 int const stride_pixels = stride()[c] / 2;
1322 int const line_size_pixels = line_size()[c] / 2;
1323 uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
1324 int const lines = sample_size(c).height;
1325 for (int y = 0; y < lines; ++y) {
1327 for (int x = 0; x < line_size_pixels; ++x) {
1328 *q = ten_bit_uv + int((int(*q) - ten_bit_uv) * f);
1339 throw PixelFormatError ("fade()", _pixel_format);
1344 shared_ptr<const Image>
1345 Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
1347 if (image->alignment() == alignment) {
1351 return make_shared<Image>(image, alignment);
1356 Image::memory_used () const
1359 for (int i = 0; i < planes(); ++i) {
1360 m += _stride[i] * sample_size(i).height;
1367 Image::video_range_to_full_range ()
1369 switch (_pixel_format) {
1370 case AV_PIX_FMT_RGB24:
1372 float const factor = 256.0 / 219.0;
1373 uint8_t* p = data()[0];
1374 int const lines = sample_size(0).height;
1375 for (int y = 0; y < lines; ++y) {
1377 for (int x = 0; x < line_size()[0]; ++x) {
1378 *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
1385 case AV_PIX_FMT_RGB48LE:
1387 float const factor = 65536.0 / 56064.0;
1388 uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
1389 int const lines = sample_size(0).height;
1390 for (int y = 0; y < lines; ++y) {
1392 int const line_size_pixels = line_size()[0] / 2;
1393 for (int x = 0; x < line_size_pixels; ++x) {
1394 *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
1397 p += stride()[0] / 2;
1401 case AV_PIX_FMT_GBRP12LE:
1403 float const factor = 4096.0 / 3504.0;
1404 for (int c = 0; c < 3; ++c) {
1405 uint16_t* p = reinterpret_cast<uint16_t*>(data()[c]);
1406 int const lines = sample_size(c).height;
1407 for (int y = 0; y < lines; ++y) {
1409 int const line_size_pixels = line_size()[c] / 2;
1410 for (int x = 0; x < line_size_pixels; ++x) {
1411 *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
1419 throw PixelFormatError ("video_range_to_full_range()", _pixel_format);