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 set of classes to describe video images.
28 #include <boost/algorithm/string.hpp>
29 #include <boost/bind.hpp>
32 #include <libavcodec/avcodec.h>
33 #include <libavformat/avformat.h>
34 #include <libswscale/swscale.h>
35 #include <libavfilter/avfiltergraph.h>
36 #include <libpostproc/postprocess.h>
37 #include <libavutil/pixfmt.h>
38 #include <libavutil/pixdesc.h>
41 #include "exceptions.h"
49 using boost::shared_ptr;
53 Image::swap (Image& other)
55 std::swap (_pixel_format, other._pixel_format);
59 Image::line_factor (int n) const
65 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
67 throw PixelFormatError (N_("lines()"), _pixel_format);
70 return pow (2.0f, d->log2_chroma_h);
73 /** @param n Component index.
74 * @return Number of lines in the image for the given component.
77 Image::lines (int n) const
79 return rint (ceil (static_cast<double>(size().height) / line_factor (n)));
82 /** @return Number of components */
84 Image::components () const
86 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
88 throw PixelFormatError (N_("components()"), _pixel_format);
91 if ((d->flags & PIX_FMT_PLANAR) == 0) {
95 return d->nb_components;
99 Image::scale (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
102 /* Empirical testing suggests that sws_scale() will crash if
103 the input image is not aligned.
107 shared_ptr<Image> scaled (new SimpleImage (pixel_format(), out_size, result_aligned));
109 struct SwsContext* scale_context = sws_getContext (
110 size().width, size().height, pixel_format(),
111 out_size.width, out_size.height, pixel_format(),
112 scaler->ffmpeg_id (), 0, 0, 0
119 scaled->data(), scaled->stride()
122 sws_freeContext (scale_context);
127 /** Scale this image to a given size and convert it to RGB.
128 * @param out_size Output image size in pixels.
129 * @param scaler Scaler to use.
132 Image::scale_and_convert_to_rgb (libdcp::Size out_size, Scaler const * scaler, bool result_aligned) const
135 /* Empirical testing suggests that sws_scale() will crash if
136 the input image is not aligned.
140 shared_ptr<Image> rgb (new SimpleImage (PIX_FMT_RGB24, out_size, result_aligned));
142 struct SwsContext* scale_context = sws_getContext (
143 size().width, size().height, pixel_format(),
144 out_size.width, out_size.height, PIX_FMT_RGB24,
145 scaler->ffmpeg_id (), 0, 0, 0
148 /* Scale and convert to RGB from whatever its currently in (which may be RGB) */
153 rgb->data(), rgb->stride()
156 sws_freeContext (scale_context);
161 /** Run a FFmpeg post-process on this image and return the processed version.
162 * @param pp Flags for the required set of post processes.
163 * @return Post-processed image.
166 Image::post_process (string pp, bool aligned) const
168 shared_ptr<Image> out (new SimpleImage (pixel_format(), size (), aligned));
171 switch (pixel_format()) {
172 case PIX_FMT_YUV420P:
173 pp_format = PP_FORMAT_420;
175 case PIX_FMT_YUV422P10LE:
176 case PIX_FMT_YUV422P:
177 case PIX_FMT_UYVY422:
178 pp_format = PP_FORMAT_422;
180 case PIX_FMT_YUV444P:
181 case PIX_FMT_YUV444P9BE:
182 case PIX_FMT_YUV444P9LE:
183 case PIX_FMT_YUV444P10BE:
184 case PIX_FMT_YUV444P10LE:
185 pp_format = PP_FORMAT_444;
187 throw PixelFormatError (N_("post_process"), pixel_format());
190 pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX);
191 pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2);
194 (const uint8_t **) data(), stride(),
195 out->data(), out->stride(),
196 size().width, size().height,
197 0, 0, mode, context, 0
201 pp_free_context (context);
207 Image::crop (Crop crop, bool aligned) const
209 libdcp::Size cropped_size = size ();
210 cropped_size.width -= crop.left + crop.right;
211 cropped_size.height -= crop.top + crop.bottom;
213 shared_ptr<Image> out (new SimpleImage (pixel_format(), cropped_size, aligned));
215 for (int c = 0; c < components(); ++c) {
216 int const crop_left_in_bytes = bytes_per_pixel(c) * crop.left;
217 /* bytes_per_pixel() could be a fraction; in this case the stride will be rounded
218 up, and we need to make sure that we copy over the width (up to the stride)
219 rather than short of the width; hence the ceil() here.
221 int const cropped_width_in_bytes = ceil (bytes_per_pixel(c) * cropped_size.width);
223 /* Start of the source line, cropped from the top but not the left */
224 uint8_t* in_p = data()[c] + (crop.top / out->line_factor(c)) * stride()[c];
225 uint8_t* out_p = out->data()[c];
227 for (int y = 0; y < out->lines(c); ++y) {
228 memcpy (out_p, in_p + crop_left_in_bytes, cropped_width_in_bytes);
230 out_p += out->stride()[c];
237 /** Blacken a YUV image whose bits per pixel is rounded up to 16 */
239 Image::yuv_16_black (uint16_t v)
241 memset (data()[0], 0, lines(0) * stride()[0]);
242 for (int i = 1; i < 3; ++i) {
243 int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
244 for (int y = 0; y < size().height; ++y) {
245 for (int x = 0; x < line_size()[i] / 2; ++x) {
248 p += stride()[i] / 2;
254 Image::swap_16 (uint16_t v)
256 return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
262 /* U/V black value for 8-bit colour */
263 static uint8_t const eight_bit_uv = (1 << 7) - 1;
264 /* U/V black value for 9-bit colour */
265 static uint16_t const nine_bit_uv = (1 << 8) - 1;
266 /* U/V black value for 10-bit colour */
267 static uint16_t const ten_bit_uv = (1 << 9) - 1;
268 /* U/V black value for 16-bit colour */
269 static uint16_t const sixteen_bit_uv = (1 << 15) - 1;
271 switch (_pixel_format) {
272 case PIX_FMT_YUV420P:
273 case PIX_FMT_YUV422P:
274 case PIX_FMT_YUV444P:
275 memset (data()[0], 0, lines(0) * stride()[0]);
276 memset (data()[1], eight_bit_uv, lines(1) * stride()[1]);
277 memset (data()[2], eight_bit_uv, lines(2) * stride()[2]);
280 case PIX_FMT_YUVJ420P:
281 case PIX_FMT_YUVJ422P:
282 case PIX_FMT_YUVJ444P:
283 memset (data()[0], 0, lines(0) * stride()[0]);
284 memset (data()[1], eight_bit_uv + 1, lines(1) * stride()[1]);
285 memset (data()[2], eight_bit_uv + 1, lines(2) * stride()[2]);
288 case PIX_FMT_YUV422P9LE:
289 case PIX_FMT_YUV444P9LE:
290 yuv_16_black (nine_bit_uv);
293 case PIX_FMT_YUV422P9BE:
294 case PIX_FMT_YUV444P9BE:
295 yuv_16_black (swap_16 (nine_bit_uv));
298 case PIX_FMT_YUV422P10LE:
299 case PIX_FMT_YUV444P10LE:
300 yuv_16_black (ten_bit_uv);
303 case PIX_FMT_YUV422P16LE:
304 case PIX_FMT_YUV444P16LE:
305 yuv_16_black (sixteen_bit_uv);
308 case PIX_FMT_YUV444P10BE:
309 case PIX_FMT_YUV422P10BE:
310 yuv_16_black (swap_16 (ten_bit_uv));
314 memset (data()[0], 0, lines(0) * stride()[0]);
317 case PIX_FMT_UYVY422:
319 int const Y = lines(0);
320 int const X = line_size()[0];
321 uint8_t* p = data()[0];
322 for (int y = 0; y < Y; ++y) {
323 for (int x = 0; x < X / 4; ++x) {
324 *p++ = eight_bit_uv; // Cb
326 *p++ = eight_bit_uv; // Cr
334 throw PixelFormatError (N_("make_black()"), _pixel_format);
339 Image::alpha_blend (shared_ptr<const Image> other, Position position)
341 /* Only implemented for RGBA onto RGB24 so far */
342 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA);
344 int start_tx = position.x;
348 start_ox = -start_tx;
352 int start_ty = position.y;
356 start_oy = -start_ty;
360 for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
361 uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3;
362 uint8_t* op = other->data()[0] + oy * other->stride()[0];
363 for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) {
364 float const alpha = float (op[3]) / 255;
365 tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha;
366 tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha;
367 tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha;
375 Image::copy (shared_ptr<const Image> other, Position position)
377 /* Only implemented for RGB24 onto RGB24 so far */
378 assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGB24);
379 assert (position.x >= 0 && position.y >= 0);
381 int const N = min (position.x + other->size().width, size().width) - position.x;
382 for (int ty = position.y, oy = 0; ty < size().height && oy < other->size().height; ++ty, ++oy) {
383 uint8_t * const tp = data()[0] + ty * stride()[0] + position.x * 3;
384 uint8_t * const op = other->data()[0] + oy * other->stride()[0];
385 memcpy (tp, op, N * 3);
390 Image::read_from_socket (shared_ptr<Socket> socket)
392 for (int i = 0; i < components(); ++i) {
393 uint8_t* p = data()[i];
394 for (int y = 0; y < lines(i); ++y) {
395 socket->read (p, line_size()[i]);
402 Image::write_to_socket (shared_ptr<Socket> socket) const
404 for (int i = 0; i < components(); ++i) {
405 uint8_t* p = data()[i];
406 for (int y = 0; y < lines(i); ++y) {
407 socket->write (p, line_size()[i]);
415 Image::bytes_per_pixel (int c) const
417 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
419 throw PixelFormatError (N_("lines()"), _pixel_format);
422 if (c >= components()) {
426 float bpp[4] = { 0, 0, 0, 0 };
428 bpp[0] = floor ((d->comp[0].depth_minus1 + 1 + 7) / 8);
429 if (d->nb_components > 1) {
430 bpp[1] = floor ((d->comp[1].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
432 if (d->nb_components > 2) {
433 bpp[2] = floor ((d->comp[2].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
435 if (d->nb_components > 3) {
436 bpp[3] = floor ((d->comp[3].depth_minus1 + 1 + 7) / 8) / pow (2.0f, d->log2_chroma_w);
439 if ((d->flags & PIX_FMT_PLANAR) == 0) {
440 /* Not planar; sum them up */
441 return bpp[0] + bpp[1] + bpp[2] + bpp[3];
447 /** Construct a SimpleImage of a given size and format, allocating memory
450 * @param p Pixel format.
451 * @param s Size in pixels.
453 SimpleImage::SimpleImage (AVPixelFormat p, libdcp::Size s, bool aligned)
462 SimpleImage::allocate ()
464 _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
465 _data[0] = _data[1] = _data[2] = _data[3] = 0;
467 _line_size = (int *) av_malloc (4 * sizeof (int));
468 _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
470 _stride = (int *) av_malloc (4 * sizeof (int));
471 _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
473 for (int i = 0; i < components(); ++i) {
474 _line_size[i] = _size.width * bytes_per_pixel(i);
475 _stride[i] = stride_round_up (i, _line_size, _aligned ? 32 : 1);
476 _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i));
480 SimpleImage::SimpleImage (SimpleImage const & other)
482 , _size (other._size)
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 SimpleImage::SimpleImage (AVFrame* frame)
499 : Image (static_cast<AVPixelFormat> (frame->format))
500 , _size (frame->width, frame->height)
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 SimpleImage::SimpleImage (shared_ptr<const Image> other, bool aligned)
518 : Image (*other.get())
519 , _size (other->size())
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 SimpleImage::operator= (SimpleImage const & other)
539 if (this == &other) {
543 SimpleImage tmp (other);
549 SimpleImage::swap (SimpleImage & other)
553 std::swap (_size, other._size);
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 SimpleImage */
565 SimpleImage::~SimpleImage ()
567 for (int i = 0; i < components(); ++i) {
572 av_free (_line_size);
577 SimpleImage::data () const
583 SimpleImage::line_size () const
589 SimpleImage::stride () const
595 SimpleImage::size () const
601 SimpleImage::aligned () const
606 RGBPlusAlphaImage::RGBPlusAlphaImage (shared_ptr<const Image> im)
607 : SimpleImage (im->pixel_format(), im->size(), false)
609 assert (im->pixel_format() == PIX_FMT_RGBA);
611 _alpha = (uint8_t *) av_malloc (im->size().width * im->size().height);
613 uint8_t* in = im->data()[0];
614 uint8_t* out = data()[0];
615 uint8_t* out_alpha = _alpha;
616 for (int y = 0; y < im->size().height; ++y) {
618 for (int x = 0; x < im->size().width; ++x) {
622 *out_alpha++ = *in_r++;
625 in += im->stride()[0];
629 RGBPlusAlphaImage::~RGBPlusAlphaImage ()