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);
305 memset (data()[0], 0, lines(0) * stride()[0]);
308 case PIX_FMT_UYVY422:
310 int const Y = lines(0);
311 int const X = line_size()[0];
312 uint8_t* p = data()[0];
313 for (int y = 0; y < Y; ++y) {
314 for (int x = 0; x < X / 4; ++x) {
315 *p++ = eight_bit_uv; // Cb
317 *p++ = eight_bit_uv; // Cr
325 throw PixelFormatError ("make_black()", _pixel_format);
330 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
332 /* Only implemented for RGBA onto RGB24 so far */
333 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
335 int start_tx = position.x;
339 start_ox = -start_tx;
343 int start_ty = position.y;
347 start_oy = -start_ty;
351 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
352 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
353 uint8_t* op = other->data()[0] + oy * other->stride()[0];
354 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
355 float const alpha = float (op[3]) / 255;
356 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
357 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
358 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
366 Image::copy (shared_ptr<const Image> other, Position<int> position)
368 /* Only implemented for RGB24 onto RGB24 so far */
369 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
370 assert (position.x >= 0 && position.y >= 0);
372 int const N = min (position.x + other->size().width, size().width) - position.x;
373 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
374 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
375 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
376 memcpy (tp, op, N * 3);
381 Image::read_from_socket (shared_ptr<Socket> socket)
383 for (int i = 0; i < components(); ++i) {
384 uint8_t* p = data()[i];
385 for (int y = 0; y < lines(i); ++y) {
386 socket->read (p, line_size()[i]);
393 Image::write_to_socket (shared_ptr<Socket> socket) const
395 for (int i = 0; i < components(); ++i) {
396 uint8_t* p = data()[i];
397 for (int y = 0; y < lines(i); ++y) {
398 socket->write (p, line_size()[i]);
406 Image::bytes_per_pixel (int c) const
408 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
410 throw PixelFormatError ("lines()", _pixel_format);
413 if (c >= components()) {
417 float bpp[4] = { 0, 0, 0, 0 };
419 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
420 if (d->nb_components > 1) {
421 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
423 if (d->nb_components > 2) {
424 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
426 if (d->nb_components > 3) {
427 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
430 if ((d->flags & PIX_FMT_PLANAR) == 0) {
431 /* Not planar; sum them up */
432 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
438 /** Construct a Image of a given size and format, allocating memory
441 * @param p Pixel format.
442 * @param s Size in pixels.
444 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
455 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
456 _data[0] = _data[1] = _data[2] = _data[3] = 0;
458 _line_size = (int *) av_malloc (4 * sizeof (int));
459 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
461 _stride = (int *) av_malloc (4 * sizeof (int));
462 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
464 for (int i = 0; i < components(); ++i) {
465 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
466 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
468 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
469 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
470 Hence on the last pixel of the last line it reads over the end of
471 the actual data by 1 byte. If the width of an image is a multiple
472 of the stride alignment there will be no padding at the end of image lines.
473 OS X crashes on this illegal read, though other operating systems don't
474 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
475 for that instruction to read safely.
477 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
481 Image::Image (Image const & other)
482 : libdcp::Image (other)
483 , _pixel_format (other._pixel_format)
484 , _aligned (other._aligned)
488 for (int i = 0; i < components(); ++i) {
489 uint8_t* p = _data[i];
490 uint8_t* q = other._data[i];
491 for (int j = 0; j < lines(i); ++j) {
492 memcpy (p, q, _line_size[i]);
494 q += other.stride()[i];
499 Image::Image (AVFrame* frame)
500 : libdcp::Image (libdcp::Size (frame->width, frame->height))
501 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
506 for (int i = 0; i < components(); ++i) {
507 uint8_t* p = _data[i];
508 uint8_t* q = frame->data[i];
509 for (int j = 0; j < lines(i); ++j) {
510 memcpy (p, q, _line_size[i]);
512 /* AVFrame's linesize is what we call `stride' */
513 q += frame->linesize[i];
518 Image::Image (shared_ptr<const Image> other, bool aligned)
519 : libdcp::Image (other)
520 , _pixel_format (other->_pixel_format)
525 for (int i = 0; i < components(); ++i) {
526 assert(line_size()[i] == other->line_size()[i]);
527 uint8_t* p = _data[i];
528 uint8_t* q = other->data()[i];
529 for (int j = 0; j < lines(i); ++j) {
530 memcpy (p, q, line_size()[i]);
532 q += other->stride()[i];
538 Image::operator= (Image const & other)
540 if (this == &other) {
550 Image::swap (Image & other)
552 libdcp::Image::swap (other);
554 std::swap (_pixel_format, other._pixel_format);
556 for (int i = 0; i < 4; ++i) {
557 std::swap (_data[i], other._data[i]);
558 std::swap (_line_size[i], other._line_size[i]);
559 std::swap (_stride[i], other._stride[i]);
562 std::swap (_aligned, other._aligned);
565 /** Destroy a Image */
568 for (int i = 0; i < components(); ++i) {
573 av_free (_line_size);
584 Image::line_size () const
590 Image::stride () const
602 Image::aligned () const