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>
31 #include "exceptions.h"
33 #include "md5_digester.h"
41 using std::stringstream;
42 using boost::shared_ptr;
46 Image::line_factor (int n) const
52 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
54 throw PixelFormatError ("lines()", _pixel_format);
57 return pow (2.0f, d->log2_chroma_h);
60 /** @param n Component index.
61 * @return Number of lines in the image for the given component.
64 Image::lines (int n) const
66 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
69 /** @return Number of components */
71 Image::components () const
73 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
75 throw PixelFormatError ("components()", _pixel_format);
78 if ((d->flags & PIX_FMT_PLANAR) == 0) {
82 return d->nb_components;
85 /** Crop this image, scale it to `inter_size' and then place it in a black frame of `out_size' */
87 Image::crop_scale_window (Crop crop, libdcp::Size inter_size, libdcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
90 /* Empirical testing suggests that sws_scale() will crash if
91 the input image is not aligned.
95 assert (out_size.width >= inter_size.width);
96 assert (out_size.height >= inter_size.height);
98 /* Here's an image of out_size */
99 shared_ptr<Image> out (new Image (out_format, out_size, out_aligned));
102 /* Size of the image after any crop */
103 libdcp::Size const cropped_size = crop.apply (size ());
105 /* Scale context for a scale from cropped_size to inter_size */
106 struct SwsContext* scale_context = sws_getContext (
107 cropped_size.width, cropped_size.height, pixel_format(),
108 inter_size.width, inter_size.height, out_format,
109 scaler->ffmpeg_id (), 0, 0, 0
112 if (!scale_context) {
113 throw StringError (N_("Could not allocate SwsContext"));
116 /* Prepare input data pointers with crop */
117 uint8_t* scale_in_data[components()];
118 for (int c = 0; c < components(); ++c) {
119 scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c));
122 /* Corner of the image within out_size */
123 Position<int> const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2);
125 uint8_t* scale_out_data[out->components()];
126 for (int c = 0; c < out->components(); ++c) {
127 scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y;
132 scale_in_data, stride(),
133 0, cropped_size.height,
134 scale_out_data, out->stride()
137 sws_freeContext (scale_context);
143 Image::scale (libdcp::Size out_size, Scaler const * scaler, AVPixelFormat out_format, bool out_aligned) const
146 /* Empirical testing suggests that sws_scale() will crash if
147 the input image is not aligned.
151 shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
153 struct SwsContext* scale_context = sws_getContext (
154 size().width, size().height, pixel_format(),
155 out_size.width, out_size.height, out_format,
156 scaler->ffmpeg_id (), 0, 0, 0
163 scaled->data(), scaled->stride()
166 sws_freeContext (scale_context);
172 Image::crop (Crop crop, bool aligned) const
174 libdcp::Size cropped_size = crop.apply (size ());
175 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
177 for (int c = 0; c < components(); ++c) {
178 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
179 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
180 up, and we need to make sure that we copy over the width (up to the stride)
181 rather than short of the width; hence the ceil() here.
183 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
185 /* Start of the source line, cropped from the top but not the left */
186 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
187 uint8_t* out_p = out->data()[c];
189 for (int y = 0; y < out->lines(c); ++y) {
190 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
192 out_p += out->stride()[c];
199 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
201 Image::yuv_16_black (uint16_t v, bool alpha)
203 memset (data()[0], 0, lines(0) * stride()[0]);
204 for (int i = 1; i < 3; ++i) {
205 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
206 for (int y = 0; y < lines(i); ++y) {
207 /* We divide by 2 here because we are writing 2 bytes at a time */
208 for (int x = 0; x < line_size()[i] / 2; ++x) {
211 p += stride()[i] / 2;
216 memset (data()[3], 0, lines(3) * stride()[3]);
221 Image::swap_16 (uint16_t v)
223 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
229 /* U/V black value for 8-bit colour */
230 static uint8_t const eight_bit_uv = (1 << 7) - 1;
231 /* U/V black value for 9-bit colour */
232 static uint16_t const nine_bit_uv = (1 << 8) - 1;
233 /* U/V black value for 10-bit colour */
234 static uint16_t const ten_bit_uv = (1 << 9) - 1;
235 /* U/V black value for 16-bit colour */
236 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
238 switch (_pixel_format) {
239 case PIX_FMT_YUV420P:
240 case PIX_FMT_YUV422P:
241 case PIX_FMT_YUV444P:
242 case PIX_FMT_YUV411P:
243 memset (data()[0], 0, lines(0) * stride()[0]);
244 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
245 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
248 case PIX_FMT_YUVJ420P:
249 case PIX_FMT_YUVJ422P:
250 case PIX_FMT_YUVJ444P:
251 memset (data()[0], 0, lines(0) * stride()[0]);
252 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
253 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
256 case PIX_FMT_YUV422P9LE:
257 case PIX_FMT_YUV444P9LE:
258 yuv_16_black (nine_bit_uv, false);
261 case PIX_FMT_YUV422P9BE:
262 case PIX_FMT_YUV444P9BE:
263 yuv_16_black (swap_16 (nine_bit_uv), false);
266 case PIX_FMT_YUV422P10LE:
267 case PIX_FMT_YUV444P10LE:
268 yuv_16_black (ten_bit_uv, false);
271 case PIX_FMT_YUV422P16LE:
272 case PIX_FMT_YUV444P16LE:
273 yuv_16_black (sixteen_bit_uv, false);
276 case PIX_FMT_YUV444P10BE:
277 case PIX_FMT_YUV422P10BE:
278 yuv_16_black (swap_16 (ten_bit_uv), false);
281 case AV_PIX_FMT_YUVA420P9BE:
282 case AV_PIX_FMT_YUVA422P9BE:
283 case AV_PIX_FMT_YUVA444P9BE:
284 yuv_16_black (swap_16 (nine_bit_uv), true);
287 case AV_PIX_FMT_YUVA420P9LE:
288 case AV_PIX_FMT_YUVA422P9LE:
289 case AV_PIX_FMT_YUVA444P9LE:
290 yuv_16_black (nine_bit_uv, true);
293 case AV_PIX_FMT_YUVA420P10BE:
294 case AV_PIX_FMT_YUVA422P10BE:
295 case AV_PIX_FMT_YUVA444P10BE:
296 yuv_16_black (swap_16 (ten_bit_uv), true);
299 case AV_PIX_FMT_YUVA420P10LE:
300 case AV_PIX_FMT_YUVA422P10LE:
301 case AV_PIX_FMT_YUVA444P10LE:
302 yuv_16_black (ten_bit_uv, true);
305 case AV_PIX_FMT_YUVA420P16BE:
306 case AV_PIX_FMT_YUVA422P16BE:
307 case AV_PIX_FMT_YUVA444P16BE:
308 yuv_16_black (swap_16 (sixteen_bit_uv), true);
311 case AV_PIX_FMT_YUVA420P16LE:
312 case AV_PIX_FMT_YUVA422P16LE:
313 case AV_PIX_FMT_YUVA444P16LE:
314 yuv_16_black (sixteen_bit_uv, true);
322 case PIX_FMT_RGB555LE:
323 case PIX_FMT_RGB48LE:
324 case PIX_FMT_RGB48BE:
325 memset (data()[0], 0, lines(0) * stride()[0]);
328 case PIX_FMT_UYVY422:
330 int const Y = lines(0);
331 int const X = line_size()[0];
332 uint8_t* p = data()[0];
333 for (int y = 0; y < Y; ++y) {
334 for (int x = 0; x < X / 4; ++x) {
335 *p++ = eight_bit_uv; // Cb
337 *p++ = eight_bit_uv; // Cr
345 throw PixelFormatError ("make_black()", _pixel_format);
350 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
352 /* Only implemented for RGBA onto RGB24 so far */
353 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
355 int start_tx = position.x;
359 start_ox = -start_tx;
363 int start_ty = position.y;
367 start_oy = -start_ty;
371 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
372 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
373 uint8_t* op = other->data()[0] + oy * other->stride()[0];
374 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
375 float const alpha = float (op[3]) / 255;
376 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
377 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
378 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
386 Image::copy (shared_ptr<const Image> other, Position<int> position)
388 /* Only implemented for RGB24 onto RGB24 so far */
389 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
390 assert (position.x >= 0 && position.y >= 0);
392 int const N = min (position.x + other->size().width, size().width) - position.x;
393 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
394 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
395 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
396 memcpy (tp, op, N * 3);
401 Image::read_from_socket (shared_ptr<Socket> socket)
403 for (int i = 0; i < components(); ++i) {
404 uint8_t* p = data()[i];
405 for (int y = 0; y < lines(i); ++y) {
406 socket->read (p, line_size()[i]);
413 Image::write_to_socket (shared_ptr<Socket> socket) const
415 for (int i = 0; i < components(); ++i) {
416 uint8_t* p = data()[i];
417 for (int y = 0; y < lines(i); ++y) {
418 socket->write (p, line_size()[i]);
426 Image::bytes_per_pixel (int c) const
428 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
430 throw PixelFormatError ("lines()", _pixel_format);
433 if (c >= components()) {
437 float bpp[4] = { 0, 0, 0, 0 };
439 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
440 if (d->nb_components > 1) {
441 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
443 if (d->nb_components > 2) {
444 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
446 if (d->nb_components > 3) {
447 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
450 if ((d->flags & PIX_FMT_PLANAR) == 0) {
451 /* Not planar; sum them up */
452 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
458 /** Construct a Image of a given size and format, allocating memory
461 * @param p Pixel format.
462 * @param s Size in pixels.
464 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
475 _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
476 _data[0] = _data[1] = _data[2] = _data[3] = 0;
478 _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
479 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
481 _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
482 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
484 for (int i = 0; i < components(); ++i) {
485 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
486 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
488 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
489 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
490 Hence on the last pixel of the last line it reads over the end of
491 the actual data by 1 byte. If the width of an image is a multiple
492 of the stride alignment there will be no padding at the end of image lines.
493 OS X crashes on this illegal read, though other operating systems don't
494 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
495 for that instruction to read safely.
497 Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3
498 over-reads by more then _avx. I can't follow the code to work out how much,
499 so I'll just over-allocate by 32 bytes and have done with it. Empirical
500 testing suggests that it works.
502 _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 32);
506 Image::Image (Image const & other)
507 : libdcp::Image (other)
508 , _pixel_format (other._pixel_format)
509 , _aligned (other._aligned)
513 for (int i = 0; i < components(); ++i) {
514 uint8_t* p = _data[i];
515 uint8_t* q = other._data[i];
516 for (int j = 0; j < lines(i); ++j) {
517 memcpy (p, q, _line_size[i]);
519 q += other.stride()[i];
524 Image::Image (AVFrame* frame)
525 : libdcp::Image (libdcp::Size (frame->width, frame->height))
526 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
531 for (int i = 0; i < components(); ++i) {
532 uint8_t* p = _data[i];
533 uint8_t* q = frame->data[i];
534 for (int j = 0; j < lines(i); ++j) {
535 memcpy (p, q, _line_size[i]);
537 /* AVFrame's linesize is what we call `stride' */
538 q += frame->linesize[i];
543 Image::Image (shared_ptr<const Image> other, bool aligned)
544 : libdcp::Image (other)
545 , _pixel_format (other->_pixel_format)
550 for (int i = 0; i < components(); ++i) {
551 assert(line_size()[i] == other->line_size()[i]);
552 uint8_t* p = _data[i];
553 uint8_t* q = other->data()[i];
554 for (int j = 0; j < lines(i); ++j) {
555 memcpy (p, q, line_size()[i]);
557 q += other->stride()[i];
563 Image::operator= (Image const & other)
565 if (this == &other) {
575 Image::swap (Image & other)
577 libdcp::Image::swap (other);
579 std::swap (_pixel_format, other._pixel_format);
581 for (int i = 0; i < 4; ++i) {
582 std::swap (_data[i], other._data[i]);
583 std::swap (_line_size[i], other._line_size[i]);
584 std::swap (_stride[i], other._stride[i]);
587 std::swap (_aligned, other._aligned);
590 /** Destroy a Image */
593 for (int i = 0; i < components(); ++i) {
598 av_free (_line_size);
609 Image::line_size () const
615 Image::stride () const
627 Image::aligned () const
633 Image::digest () const
635 MD5Digester digester;
637 for (int i = 0; i < components(); ++i) {
638 digester.add (data()[i], line_size()[i]);
641 return digester.get ();