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 = crop.apply (size ());
159 shared_ptr<Image> out (new Image (pixel_format(), cropped_size, aligned));
161 for (int c = 0; c < components(); ++c) {
162 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
163 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
164 up, and we need to make sure that we copy over the width (up to the stride)
165 rather than short of the width; hence the ceil() here.
167 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
169 /* Start of the source line, cropped from the top but not the left */
170 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
171 uint8_t* out_p = out->data()[c];
173 for (int y = 0; y < out->lines(c); ++y) {
174 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
176 out_p += out->stride()[c];
183 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
185 Image::yuv_16_black (uint16_t v, bool alpha)
187 memset (data()[0], 0, lines(0) * stride()[0]);
188 for (int i = 1; i < 3; ++i) {
189 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
190 for (int y = 0; y < lines(i); ++y) {
191 /* We divide by 2 here because we are writing 2 bytes at a time */
192 for (int x = 0; x < line_size()[i] / 2; ++x) {
195 p += stride()[i] / 2;
200 memset (data()[3], 0, lines(3) * stride()[3]);
205 Image::swap_16 (uint16_t v)
207 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
213 /* U/V black value for 8-bit colour */
214 static uint8_t const eight_bit_uv = (1 << 7) - 1;
215 /* U/V black value for 9-bit colour */
216 static uint16_t const nine_bit_uv = (1 << 8) - 1;
217 /* U/V black value for 10-bit colour */
218 static uint16_t const ten_bit_uv = (1 << 9) - 1;
219 /* U/V black value for 16-bit colour */
220 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
222 switch (_pixel_format) {
223 case PIX_FMT_YUV420P:
224 case PIX_FMT_YUV422P:
225 case PIX_FMT_YUV444P:
226 memset (data()[0], 0, lines(0) * stride()[0]);
227 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
228 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
231 case PIX_FMT_YUVJ420P:
232 case PIX_FMT_YUVJ422P:
233 case PIX_FMT_YUVJ444P:
234 memset (data()[0], 0, lines(0) * stride()[0]);
235 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
236 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
239 case PIX_FMT_YUV422P9LE:
240 case PIX_FMT_YUV444P9LE:
241 yuv_16_black (nine_bit_uv, false);
244 case PIX_FMT_YUV422P9BE:
245 case PIX_FMT_YUV444P9BE:
246 yuv_16_black (swap_16 (nine_bit_uv), false);
249 case PIX_FMT_YUV422P10LE:
250 case PIX_FMT_YUV444P10LE:
251 yuv_16_black (ten_bit_uv, false);
254 case PIX_FMT_YUV422P16LE:
255 case PIX_FMT_YUV444P16LE:
256 yuv_16_black (sixteen_bit_uv, false);
259 case PIX_FMT_YUV444P10BE:
260 case PIX_FMT_YUV422P10BE:
261 yuv_16_black (swap_16 (ten_bit_uv), false);
264 case AV_PIX_FMT_YUVA420P9BE:
265 case AV_PIX_FMT_YUVA422P9BE:
266 case AV_PIX_FMT_YUVA444P9BE:
267 yuv_16_black (swap_16 (nine_bit_uv), true);
270 case AV_PIX_FMT_YUVA420P9LE:
271 case AV_PIX_FMT_YUVA422P9LE:
272 case AV_PIX_FMT_YUVA444P9LE:
273 yuv_16_black (nine_bit_uv, true);
276 case AV_PIX_FMT_YUVA420P10BE:
277 case AV_PIX_FMT_YUVA422P10BE:
278 case AV_PIX_FMT_YUVA444P10BE:
279 yuv_16_black (swap_16 (ten_bit_uv), true);
282 case AV_PIX_FMT_YUVA420P10LE:
283 case AV_PIX_FMT_YUVA422P10LE:
284 case AV_PIX_FMT_YUVA444P10LE:
285 yuv_16_black (ten_bit_uv, true);
288 case AV_PIX_FMT_YUVA420P16BE:
289 case AV_PIX_FMT_YUVA422P16BE:
290 case AV_PIX_FMT_YUVA444P16BE:
291 yuv_16_black (swap_16 (sixteen_bit_uv), true);
294 case AV_PIX_FMT_YUVA420P16LE:
295 case AV_PIX_FMT_YUVA422P16LE:
296 case AV_PIX_FMT_YUVA444P16LE:
297 yuv_16_black (sixteen_bit_uv, true);
301 memset (data()[0], 0, lines(0) * stride()[0]);
304 case PIX_FMT_UYVY422:
306 int const Y = lines(0);
307 int const X = line_size()[0];
308 uint8_t* p = data()[0];
309 for (int y = 0; y < Y; ++y) {
310 for (int x = 0; x < X / 4; ++x) {
311 *p++ = eight_bit_uv; // Cb
313 *p++ = eight_bit_uv; // Cr
321 throw PixelFormatError ("make_black()", _pixel_format);
326 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
328 /* Only implemented for RGBA onto RGB24 so far */
329 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
331 int start_tx = position.x;
335 start_ox = -start_tx;
339 int start_ty = position.y;
343 start_oy = -start_ty;
347 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
348 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
349 uint8_t* op = other->data()[0] + oy * other->stride()[0];
350 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
351 float const alpha = float (op[3]) / 255;
352 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
353 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
354 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
362 Image::copy (shared_ptr<const Image> other, Position<int> position)
364 /* Only implemented for RGB24 onto RGB24 so far */
365 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
366 assert (position.x >= 0 && position.y >= 0);
368 int const N = min (position.x + other->size().width, size().width) - position.x;
369 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
370 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
371 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
372 memcpy (tp, op, N * 3);
377 Image::read_from_socket (shared_ptr<Socket> socket)
379 for (int i = 0; i < components(); ++i) {
380 uint8_t* p = data()[i];
381 for (int y = 0; y < lines(i); ++y) {
382 socket->read (p, line_size()[i]);
389 Image::write_to_socket (shared_ptr<Socket> socket) const
391 for (int i = 0; i < components(); ++i) {
392 uint8_t* p = data()[i];
393 for (int y = 0; y < lines(i); ++y) {
394 socket->write (p, line_size()[i]);
402 Image::bytes_per_pixel (int c) const
404 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
406 throw PixelFormatError ("lines()", _pixel_format);
409 if (c >= components()) {
413 float bpp[4] = { 0, 0, 0, 0 };
415 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
416 if (d->nb_components > 1) {
417 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
419 if (d->nb_components > 2) {
420 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
422 if (d->nb_components > 3) {
423 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
426 if ((d->flags & PIX_FMT_PLANAR) == 0) {
427 /* Not planar; sum them up */
428 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
434 /** Construct a Image of a given size and format, allocating memory
437 * @param p Pixel format.
438 * @param s Size in pixels.
440 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
451 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
452 _data[0] = _data[1] = _data[2] = _data[3] = 0;
454 _line_size = (int *) av_malloc (4 * sizeof (int));
455 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
457 _stride = (int *) av_malloc (4 * sizeof (int));
458 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
460 for (int i = 0; i < components(); ++i) {
461 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
462 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
464 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
465 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
466 Hence on the last pixel of the last line it reads over the end of
467 the actual data by 1 byte. If the width of an image is a multiple
468 of the stride alignment there will be no padding at the end of image lines.
469 OS X crashes on this illegal read, though other operating systems don't
470 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
471 for that instruction to read safely.
473 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
477 Image::Image (Image const & other)
478 : libdcp::Image (other)
479 , _pixel_format (other._pixel_format)
480 , _aligned (other._aligned)
484 for (int i = 0; i < components(); ++i) {
485 uint8_t* p = _data[i];
486 uint8_t* q = other._data[i];
487 for (int j = 0; j < lines(i); ++j) {
488 memcpy (p, q, _line_size[i]);
490 q += other.stride()[i];
495 Image::Image (AVFrame* frame)
496 : libdcp::Image (libdcp::Size (frame->width, frame->height))
497 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
502 for (int i = 0; i < components(); ++i) {
503 uint8_t* p = _data[i];
504 uint8_t* q = frame->data[i];
505 for (int j = 0; j < lines(i); ++j) {
506 memcpy (p, q, _line_size[i]);
508 /* AVFrame's linesize is what we call `stride' */
509 q += frame->linesize[i];
514 Image::Image (shared_ptr<const Image> other, bool aligned)
515 : libdcp::Image (other)
516 , _pixel_format (other->_pixel_format)
521 for (int i = 0; i < components(); ++i) {
522 assert(line_size()[i] == other->line_size()[i]);
523 uint8_t* p = _data[i];
524 uint8_t* q = other->data()[i];
525 for (int j = 0; j < lines(i); ++j) {
526 memcpy (p, q, line_size()[i]);
528 q += other->stride()[i];
534 Image::operator= (Image const & other)
536 if (this == &other) {
546 Image::swap (Image & other)
548 libdcp::Image::swap (other);
550 std::swap (_pixel_format, other._pixel_format);
552 for (int i = 0; i < 4; ++i) {
553 std::swap (_data[i], other._data[i]);
554 std::swap (_line_size[i], other._line_size[i]);
555 std::swap (_stride[i], other._stride[i]);
558 std::swap (_aligned, other._aligned);
561 /** Destroy a Image */
564 for (int i = 0; i < components(); ++i) {
569 av_free (_line_size);
580 Image::line_size () const
586 Image::stride () const
598 Image::aligned () const