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)
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 < size().height; ++y) {
194 for (int x = 0; x < line_size()[i] / 2; ++x) {
197 p += stride()[i] / 2;
203 Image::swap_16 (uint16_t v)
205 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
211 /* U/V black value for 8-bit colour */
212 static uint8_t const eight_bit_uv = (1 << 7) - 1;
213 /* U/V black value for 9-bit colour */
214 static uint16_t const nine_bit_uv = (1 << 8) - 1;
215 /* U/V black value for 10-bit colour */
216 static uint16_t const ten_bit_uv = (1 << 9) - 1;
217 /* U/V black value for 16-bit colour */
218 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
220 switch (_pixel_format) {
221 case PIX_FMT_YUV420P:
222 case PIX_FMT_YUV422P:
223 case PIX_FMT_YUV444P:
224 memset (data()[0], 0, lines(0) * stride()[0]);
225 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
226 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
229 case PIX_FMT_YUVJ420P:
230 case PIX_FMT_YUVJ422P:
231 case PIX_FMT_YUVJ444P:
232 memset (data()[0], 0, lines(0) * stride()[0]);
233 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
234 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
237 case PIX_FMT_YUV422P9LE:
238 case PIX_FMT_YUV444P9LE:
239 yuv_16_black (nine_bit_uv);
242 case PIX_FMT_YUV422P9BE:
243 case PIX_FMT_YUV444P9BE:
244 yuv_16_black (swap_16 (nine_bit_uv));
247 case PIX_FMT_YUV422P10LE:
248 case PIX_FMT_YUV444P10LE:
249 yuv_16_black (ten_bit_uv);
252 case PIX_FMT_YUV422P16LE:
253 case PIX_FMT_YUV444P16LE:
254 yuv_16_black (sixteen_bit_uv);
257 case PIX_FMT_YUV444P10BE:
258 case PIX_FMT_YUV422P10BE:
259 yuv_16_black (swap_16 (ten_bit_uv));
263 memset (data()[0], 0, lines(0) * stride()[0]);
266 case PIX_FMT_UYVY422:
268 int const Y = lines(0);
269 int const X = line_size()[0];
270 uint8_t* p = data()[0];
271 for (int y = 0; y < Y; ++y) {
272 for (int x = 0; x < X / 4; ++x) {
273 *p++ = eight_bit_uv; // Cb
275 *p++ = eight_bit_uv; // Cr
283 throw PixelFormatError ("make_black()", _pixel_format);
288 Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
290 /* Only implemented for RGBA onto RGB24 so far */
291 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
293 int start_tx = position.x;
297 start_ox = -start_tx;
301 int start_ty = position.y;
305 start_oy = -start_ty;
309 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
310 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
311 uint8_t* op = other->data()[0] + oy * other->stride()[0];
312 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
313 float const alpha = float (op[3]) / 255;
314 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
315 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
316 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
324 Image::copy (shared_ptr<const Image> other, Position<int> position)
326 /* Only implemented for RGB24 onto RGB24 so far */
327 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
328 assert (position.x >= 0 && position.y >= 0);
330 int const N = min (position.x + other->size().width, size().width) - position.x;
331 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
332 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
333 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
334 memcpy (tp, op, N * 3);
339 Image::read_from_socket (shared_ptr<Socket> socket)
341 for (int i = 0; i < components(); ++i) {
342 uint8_t* p = data()[i];
343 for (int y = 0; y < lines(i); ++y) {
344 socket->read (p, line_size()[i]);
351 Image::write_to_socket (shared_ptr<Socket> socket) const
353 for (int i = 0; i < components(); ++i) {
354 uint8_t* p = data()[i];
355 for (int y = 0; y < lines(i); ++y) {
356 socket->write (p, line_size()[i]);
364 Image::bytes_per_pixel (int c) const
366 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
368 throw PixelFormatError ("lines()", _pixel_format);
371 if (c >= components()) {
375 float bpp[4] = { 0, 0, 0, 0 };
377 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
378 if (d->nb_components > 1) {
379 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
381 if (d->nb_components > 2) {
382 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
384 if (d->nb_components > 3) {
385 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
388 if ((d->flags & PIX_FMT_PLANAR) == 0) {
389 /* Not planar; sum them up */
390 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
396 /** Construct a Image of a given size and format, allocating memory
399 * @param p Pixel format.
400 * @param s Size in pixels.
402 Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
413 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
414 _data[0] = _data[1] = _data[2] = _data[3] = 0;
416 _line_size = (int *) av_malloc (4 * sizeof (int));
417 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
419 _stride = (int *) av_malloc (4 * sizeof (int));
420 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
422 for (int i = 0; i < components(); ++i) {
423 _line_size[i] = ceil (_size.width * bytes_per_pixel(i));
424 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
426 /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
427 uses a 16-byte fetch to read three bytes (R/G/B) of image data.
428 Hence on the last pixel of the last line it reads over the end of
429 the actual data by 1 byte. If the width of an image is a multiple
430 of the stride alignment there will be no padding at the end of image lines.
431 OS X crashes on this illegal read, though other operating systems don't
432 seem to mind. The nasty + 1 in this malloc makes sure there is always a byte
433 for that instruction to read safely.
435 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
439 Image::Image (Image const & other)
440 : libdcp::Image (other)
441 , _pixel_format (other._pixel_format)
442 , _aligned (other._aligned)
446 for (int i = 0; i < components(); ++i) {
447 uint8_t* p = _data[i];
448 uint8_t* q = other._data[i];
449 for (int j = 0; j < lines(i); ++j) {
450 memcpy (p, q, _line_size[i]);
452 q += other.stride()[i];
457 Image::Image (AVFrame* frame)
458 : libdcp::Image (libdcp::Size (frame->width, frame->height))
459 , _pixel_format (static_cast<AVPixelFormat> (frame->format))
464 for (int i = 0; i < components(); ++i) {
465 uint8_t* p = _data[i];
466 uint8_t* q = frame->data[i];
467 for (int j = 0; j < lines(i); ++j) {
468 memcpy (p, q, _line_size[i]);
470 /* AVFrame's linesize is what we call `stride' */
471 q += frame->linesize[i];
476 Image::Image (shared_ptr<const Image> other, bool aligned)
477 : libdcp::Image (other)
478 , _pixel_format (other->_pixel_format)
483 for (int i = 0; i < components(); ++i) {
484 assert(line_size()[i] == other->line_size()[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];
496 Image::operator= (Image const & other)
498 if (this == &other) {
508 Image::swap (Image & other)
510 libdcp::Image::swap (other);
512 std::swap (_pixel_format, other._pixel_format);
514 for (int i = 0; i < 4; ++i) {
515 std::swap (_data[i], other._data[i]);
516 std::swap (_line_size[i], other._line_size[i]);
517 std::swap (_stride[i], other._stride[i]);
520 std::swap (_aligned, other._aligned);
523 /** Destroy a Image */
526 for (int i = 0; i < components(); ++i) {
531 av_free (_line_size);
542 Image::line_size () const
548 Image::stride () const
560 Image::aligned () const