2 Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /** @file src/image.cc
21 * @brief A class to describe a video image.
26 #include <libswscale/swscale.h>
27 #include <libavutil/pixfmt.h>
28 #include <libavutil/pixdesc.h>
29 #include <libpostproc/postprocess.h>
32 #include "exceptions.h"
38 using boost::shared_ptr;
42 Image::line_factor (int n) const
48 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
50 throw PixelFormatError ("lines()", _pixel_format);
53 return pow (2.0f, d->log2_chroma_h);
56 /** @param n Component index.
57 * @return Number of lines in the image for the given component.
60 Image::lines (int n) const
62 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
65 /** @return Number of components */
67 Image::components () const
69 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
71 throw PixelFormatError ("components()", _pixel_format);
74 if ((d->flags & PIX_FMT_PLANAR) == 0) {
78 return d->nb_components;
82 Image::scale (libdcp::Size out_size, Scaler const * scaler, AVPixelFormat result_format, bool result_aligned) const
85 /* Empirical testing suggests that sws_scale() will crash if
86 the input image is not aligned.
90 shared_ptr<Image> scaled (new Image (result_format, out_size, result_aligned));
92 struct SwsContext* scale_context = sws_getContext (
93 size().width, size().height, pixel_format(),
94 out_size.width, out_size.height, result_format,
95 scaler->ffmpeg_id (), 0, 0, 0
102 scaled->data(), scaled->stride()
105 sws_freeContext (scale_context);
110 /** Run a FFmpeg post-process on this image and return the processed version.
111 * @param pp Flags for the required set of post processes.
112 * @return Post-processed image.
115 Image::post_process (string pp, bool aligned) const
117 shared_ptr<Image> out (new Image (pixel_format(), size (), aligned));
120 switch (pixel_format()) {
121 case PIX_FMT_YUV420P:
122 pp_format = PP_FORMAT_420;
124 case PIX_FMT_YUV422P10LE:
125 case PIX_FMT_YUV422P:
126 case PIX_FMT_UYVY422:
127 pp_format = PP_FORMAT_422;
129 case PIX_FMT_YUV444P:
130 case PIX_FMT_YUV444P9BE:
131 case PIX_FMT_YUV444P9LE:
132 case PIX_FMT_YUV444P10BE:
133 case PIX_FMT_YUV444P10LE:
134 pp_format = PP_FORMAT_444;
136 throw PixelFormatError ("post_process", pixel_format());
139 pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
140 pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
143 (const uint8_t **) data(), stride(),
144 out->data(), out->stride(),
145 size().width, size().height,
146 0, 0, mode, context, 0
150 pp_free_context (context);
156 Image::crop (Crop crop, bool aligned) const
158 libdcp::Size cropped_size = size ();
159 cropped_size.width -= crop.left + crop.right;
160 cropped_size.height -= crop.top + crop.bottom;
162 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
164 for (int c = 0; c < components(); ++c) {
165 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
166 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
167 up, and we need to make sure that we copy over the width (up to the stride)
168 rather than short of the width; hence the ceil() here.
170 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
172 /* Start of the source line, cropped from the top but not the left */
173 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
174 uint8_t* out_p = out->data()[c];
176 for (int y = 0; y < out->lines(c); ++y) {
177 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
179 out_p += out->stride()[c];
186 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
188 Image::yuv_16_black (uint16_t v, bool alpha)
190 memset (data()[0], 0, lines(0) * stride()[0]);
191 for (int i = 1; i < 3; ++i) {
192 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
193 for (int y = 0; y < lines(i); ++y) {
194 /* We divide by 2 here because we are writing 2 bytes at a time */
195 for (int x = 0; x < line_size()[i] / 2; ++x) {
198 p += stride()[i] / 2;
203 memset (data()[3], 0, lines(3) * stride()[3]);
208 Image::swap_16 (uint16_t v)
210 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
216 /* U/V black value for 8-bit colour */
217 static uint8_t const eight_bit_uv = (1 << 7) - 1;
218 /* U/V black value for 9-bit colour */
219 static uint16_t const nine_bit_uv = (1 << 8) - 1;
220 /* U/V black value for 10-bit colour */
221 static uint16_t const ten_bit_uv = (1 << 9) - 1;
222 /* U/V black value for 16-bit colour */
223 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
225 switch (_pixel_format) {
226 case PIX_FMT_YUV420P:
227 case PIX_FMT_YUV422P:
228 case PIX_FMT_YUV444P:
229 memset (data()[0], 0, lines(0) * stride()[0]);
230 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
231 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
234 case PIX_FMT_YUVJ420P:
235 case PIX_FMT_YUVJ422P:
236 case PIX_FMT_YUVJ444P:
237 memset (data()[0], 0, lines(0) * stride()[0]);
238 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
239 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
242 case PIX_FMT_YUV422P9LE:
243 case PIX_FMT_YUV444P9LE:
244 yuv_16_black (nine_bit_uv, false);
247 case PIX_FMT_YUV422P9BE:
248 case PIX_FMT_YUV444P9BE:
249 yuv_16_black (swap_16 (nine_bit_uv), false);
252 case PIX_FMT_YUV422P10LE:
253 case PIX_FMT_YUV444P10LE:
254 yuv_16_black (ten_bit_uv, false);
257 case PIX_FMT_YUV422P16LE:
258 case PIX_FMT_YUV444P16LE:
259 yuv_16_black (sixteen_bit_uv, false);
262 case PIX_FMT_YUV444P10BE:
263 case PIX_FMT_YUV422P10BE:
264 yuv_16_black (swap_16 (ten_bit_uv), false);
267 case AV_PIX_FMT_YUVA420P9BE:
268 case AV_PIX_FMT_YUVA422P9BE:
269 case AV_PIX_FMT_YUVA444P9BE:
270 yuv_16_black (swap_16 (nine_bit_uv), true);
273 case AV_PIX_FMT_YUVA420P9LE:
274 case AV_PIX_FMT_YUVA422P9LE:
275 case AV_PIX_FMT_YUVA444P9LE:
276 yuv_16_black (nine_bit_uv, true);
279 case AV_PIX_FMT_YUVA420P10BE:
280 case AV_PIX_FMT_YUVA422P10BE:
281 case AV_PIX_FMT_YUVA444P10BE:
282 yuv_16_black (swap_16 (ten_bit_uv), true);
285 case AV_PIX_FMT_YUVA420P10LE:
286 case AV_PIX_FMT_YUVA422P10LE:
287 case AV_PIX_FMT_YUVA444P10LE:
288 yuv_16_black (ten_bit_uv, true);
291 case AV_PIX_FMT_YUVA420P16BE:
292 case AV_PIX_FMT_YUVA422P16BE:
293 case AV_PIX_FMT_YUVA444P16BE:
294 yuv_16_black (swap_16 (sixteen_bit_uv), true);
297 case AV_PIX_FMT_YUVA420P16LE:
298 case AV_PIX_FMT_YUVA422P16LE:
299 case AV_PIX_FMT_YUVA444P16LE:
300 yuv_16_black (sixteen_bit_uv, true);
304 memset (data()[0], 0, lines(0) * stride()[0]);
307 case PIX_FMT_UYVY422:
309 int const Y = lines(0);
310 int const X = line_size()[0];
311 uint8_t* p = data()[0];
312 for (int y = 0; y < Y; ++y) {
313 for (int x = 0; x < X / 4; ++x) {
314 *p++ = eight_bit_uv; // Cb
316 *p++ = eight_bit_uv; // Cr
324 throw PixelFormatError ("make_black()", _pixel_format);
329 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
331 /* Only implemented for RGBA onto RGB24 so far */
332 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
334 int start_tx = position.x;
338 start_ox = -start_tx;
342 int start_ty = position.y;
346 start_oy = -start_ty;
350 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
351 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
352 uint8_t* op = other->data()[0] + oy * other->stride()[0];
353 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
354 float const alpha = float (op[3]) / 255;
355 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
356 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
357 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
365 Image::copy (shared_ptr<const Image> other, Position<int> position)
367 /* Only implemented for RGB24 onto RGB24 so far */
368 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
369 assert (position.x >= 0 && position.y >= 0);
371 int const N = min (position.x + other->size().width, size().width) - position.x;
372 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
373 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
374 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
375 memcpy (tp, op, N * 3);
380 Image::read_from_socket (shared_ptr<Socket> socket)
382 for (int i = 0; i < components(); ++i) {
383 uint8_t* p = data()[i];
384 for (int y = 0; y < lines(i); ++y) {
385 socket->read (p, line_size()[i]);
392 Image::write_to_socket (shared_ptr<Socket> socket) const
394 for (int i = 0; i < components(); ++i) {
395 uint8_t* p = data()[i];
396 for (int y = 0; y < lines(i); ++y) {
397 socket->write (p, line_size()[i]);
405 Image::bytes_per_pixel (int c) const
407 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
409 throw PixelFormatError ("lines()", _pixel_format);
412 if (c >= components()) {
416 float bpp[4] = { 0, 0, 0, 0 };
418 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
419 if (d->nb_components > 1) {
420 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
422 if (d->nb_components > 2) {
423 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
425 if (d->nb_components > 3) {
426 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
429 if ((d->flags & PIX_FMT_PLANAR) == 0) {
430 /* Not planar; sum them up */
431 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
437 /** Construct a Image of a given size and format, allocating memory
440 * @param p Pixel format.
441 * @param s Size in pixels.
443 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
454 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
455 _data[0] = _data[1] = _data[2] = _data[3] = 0;
457 _line_size = (int *) av_malloc (4 * sizeof (int));
458 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
460 _stride = (int *) av_malloc (4 * sizeof (int));
461 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
463 for (int i = 0; i < components(); ++i) {
464 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
465 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
467 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
468 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
469 Hence on the last pixel of the last line it reads over the end of
470 the actual data by 1 byte. If the width of an image is a multiple
471 of the stride alignment there will be no padding at the end of image lines.
472 OS X crashes on this illegal read, though other operating systems don't
473 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
474 for that instruction to read safely.
476 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
480 Image::Image (Image const & other)
481 : libdcp::Image (other)
482 , _pixel_format (other._pixel_format)
483 , _aligned (other._aligned)
487 for (int i = 0; i < components(); ++i) {
488 uint8_t* p = _data[i];
489 uint8_t* q = other._data[i];
490 for (int j = 0; j < lines(i); ++j) {
491 memcpy (p, q, _line_size[i]);
493 q += other.stride()[i];
498 Image::Image (AVFrame* frame)
499 : libdcp::Image (libdcp::Size (frame->width, frame->height))
500 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
505 for (int i = 0; i < components(); ++i) {
506 uint8_t* p = _data[i];
507 uint8_t* q = frame->data[i];
508 for (int j = 0; j < lines(i); ++j) {
509 memcpy (p, q, _line_size[i]);
511 /* AVFrame's linesize is what we call `stride' */
512 q += frame->linesize[i];
517 Image::Image (shared_ptr<const Image> other, bool aligned)
518 : libdcp::Image (other)
519 , _pixel_format (other->_pixel_format)
524 for (int i = 0; i < components(); ++i) {
525 assert(line_size()[i] == other->line_size()[i]);
526 uint8_t* p = _data[i];
527 uint8_t* q = other->data()[i];
528 for (int j = 0; j < lines(i); ++j) {
529 memcpy (p, q, line_size()[i]);
531 q += other->stride()[i];
537 Image::operator= (Image const & other)
539 if (this == &other) {
549 Image::swap (Image & other)
551 libdcp::Image::swap (other);
553 std::swap (_pixel_format, other._pixel_format);
555 for (int i = 0; i < 4; ++i) {
556 std::swap (_data[i], other._data[i]);
557 std::swap (_line_size[i], other._line_size[i]);
558 std::swap (_stride[i], other._stride[i]);
561 std::swap (_aligned, other._aligned);
564 /** Destroy a Image */
567 for (int i = 0; i < components(); ++i) {
572 av_free (_line_size);
583 Image::line_size () const
589 Image::stride () const
601 Image::aligned () const