From cc4a67b7eb8ecaed076e261960848f70e3e741af Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 10 Oct 2012 15:47:06 +0100 Subject: Subs successfully exported with thumbs. --- src/lib/server.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/lib/server.cc') diff --git a/src/lib/server.cc b/src/lib/server.cc index 28236e3e0..76989d078 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -114,17 +114,15 @@ Server::process (shared_ptr socket) shared_ptr image (new SimpleImage (pixel_format, in_size)); - for (int i = 0; i < image->components(); ++i) { - int line_size; - s >> line_size; - image->set_line_size (i, line_size); - } - for (int i = 0; i < image->components(); ++i) { socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); } + + /* XXX: subtitle */ + DCPVideoFrame dcp_video_frame ( + image, shared_ptr (), out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log + ); - DCPVideoFrame dcp_video_frame (image, out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log); shared_ptr encoded = dcp_video_frame.encode_locally (); encoded->send (socket); -- cgit v1.2.3 From 27fac0b4c6d42cb3b47bc1240d50ce11923fb66a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 14 Oct 2012 13:22:47 +0100 Subject: Simplify use of Image hierarchy a bit. --- src/lib/image.cc | 12 ++++++------ src/lib/image.h | 4 ++-- src/lib/server.cc | 2 +- src/lib/subtitle.h | 6 +++--- test/test.cc | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/lib/server.cc') diff --git a/src/lib/image.cc b/src/lib/image.cc index 98c5228a9..602b20842 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -88,7 +88,7 @@ Image::scale (Size out_size, Scaler const * scaler) const { assert (scaler); - shared_ptr scaled (new SimpleImage (pixel_format(), out_size)); + shared_ptr scaled (new SimpleImage (pixel_format(), out_size)); struct SwsContext* scale_context = sws_getContext ( size().width, size().height, pixel_format(), @@ -112,7 +112,7 @@ Image::scale (Size out_size, Scaler const * scaler) const * @param out_size Output image size in pixels. * @param scaler Scaler to use. */ -shared_ptr +shared_ptr Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scaler) const { assert (scaler); @@ -120,7 +120,7 @@ Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scal Size content_size = out_size; content_size.width -= (padding * 2); - shared_ptr rgb (new RGBFrameImage (content_size)); + shared_ptr rgb (new SimpleImage (PIX_FMT_RGB24, content_size)); struct SwsContext* scale_context = sws_getContext ( size().width, size().height, pixel_format(), @@ -141,7 +141,7 @@ Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scal scheme of things. */ if (padding > 0) { - shared_ptr padded_rgb (new RGBFrameImage (out_size)); + shared_ptr padded_rgb (new SimpleImage (PIX_FMT_RGB24, out_size)); padded_rgb->make_black (); /* XXX: we are cheating a bit here; we know the frame is RGB so we can @@ -167,10 +167,10 @@ Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scal * @param pp Flags for the required set of post processes. * @return Post-processed image. */ -shared_ptr +shared_ptr Image::post_process (string pp) const { - shared_ptr out (new SimpleImage (PIX_FMT_YUV420P, size ())); + shared_ptr out (new SimpleImage (PIX_FMT_YUV420P, size ())); pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX); pp_context* context = pp_get_context (size().width, size().height, PP_FORMAT_420 | PP_CPU_CAPS_MMX2); diff --git a/src/lib/image.h b/src/lib/image.h index e06a82b7f..970750719 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -65,9 +65,9 @@ public: int components () const; int lines (int) const; - boost::shared_ptr scale_and_convert_to_rgb (Size, int, Scaler const *) const; + boost::shared_ptr scale_and_convert_to_rgb (Size, int, Scaler const *) const; boost::shared_ptr scale (Size, Scaler const *) const; - boost::shared_ptr post_process (std::string) const; + boost::shared_ptr post_process (std::string) const; void make_black (); diff --git a/src/lib/server.cc b/src/lib/server.cc index 76989d078..2fda5952f 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -112,7 +112,7 @@ Server::process (shared_ptr socket) post_process = ""; } - shared_ptr image (new SimpleImage (pixel_format, in_size)); + shared_ptr image (new SimpleImage (pixel_format, in_size)); for (int i = 0; i < image->components(); ++i) { socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h index 0b82320a1..d9717564e 100644 --- a/src/lib/subtitle.h +++ b/src/lib/subtitle.h @@ -23,7 +23,7 @@ struct AVSubtitle; class SubtitleImage; -class SimpleImage; +class Image; class FilmState; class Subtitle @@ -64,11 +64,11 @@ public: return _position; } - boost::shared_ptr image () const { + boost::shared_ptr image () const { return _image; } private: Position _position; - boost::shared_ptr _image; + boost::shared_ptr _image; }; diff --git a/test/test.cc b/test/test.cc index 5a7625dd7..789724b53 100644 --- a/test/test.cc +++ b/test/test.cc @@ -270,7 +270,7 @@ do_remote_encode (shared_ptr frame, ServerDescription* descriptio BOOST_AUTO_TEST_CASE (client_server_test) { - shared_ptr image (new SimpleImage (PIX_FMT_RGB24, Size (1998, 1080))); + shared_ptr image (new SimpleImage (PIX_FMT_RGB24, Size (1998, 1080))); uint8_t* p = image->data()[0]; -- cgit v1.2.3 From a066feba1b455a72fe10b7baa79f17f69cd24ba9 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 14 Oct 2012 16:50:08 +0100 Subject: Various fixes to subtitling. --- run/dvdomatic | 6 ++++-- src/lib/dcp_video_frame.cc | 30 +++++++++++++++++++++++++----- src/lib/dcp_video_frame.h | 4 +++- src/lib/decoder.cc | 24 +++++++++++++++++------- src/lib/decoder.h | 5 ++++- src/lib/ffmpeg_decoder.cc | 18 ++++-------------- src/lib/ffmpeg_decoder.h | 1 - src/lib/film.cc | 1 + src/lib/image.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- src/lib/image.h | 1 + src/lib/imagemagick_decoder.cc | 2 +- src/lib/j2k_still_encoder.cc | 2 +- src/lib/j2k_wav_encoder.cc | 3 ++- src/lib/options.h | 2 ++ src/lib/server.cc | 7 ++++++- src/lib/subtitle.cc | 25 +++++++++++++++---------- src/lib/subtitle.h | 5 +++-- src/lib/tiff_decoder.cc | 2 +- src/wx/film_viewer.cc | 3 ++- test/test.cc | 2 ++ 20 files changed, 134 insertions(+), 51 deletions(-) (limited to 'src/lib/server.cc') diff --git a/run/dvdomatic b/run/dvdomatic index eeb2c7b44..125fd9d27 100755 --- a/run/dvdomatic +++ b/run/dvdomatic @@ -2,9 +2,11 @@ export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH if [ "$1" == "--debug" ]; then - gdb --args build/src/tools/dvdomatic $2 + shift + gdb --args build/src/tools/dvdomatic "$1" elif [ "$1" == "--valgrind" ]; then - valgrind --tool="memcheck" build/src/tools/dvdomatic $2 + shift + valgrind --tool="memcheck" build/src/tools/dvdomatic "$1" else build/src/tools/dvdomatic "$1" fi diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 13d3efcbf..ce660add5 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -55,6 +55,7 @@ #include "scaler.h" #include "image.h" #include "log.h" +#include "subtitle.h" using namespace std; using namespace boost; @@ -72,11 +73,16 @@ using namespace boost; * @param l Log to write to. */ DCPVideoFrame::DCPVideoFrame ( - shared_ptr yuv, shared_ptr sub, Size out, int p, Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l) + shared_ptr yuv, shared_ptr sub, + Size out, int p, int subtitle_offset, float subtitle_scale, + Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l + ) : _input (yuv) , _subtitle (sub) , _out_size (out) , _padding (p) + , _subtitle_offset (subtitle_offset) + , _subtitle_scale (subtitle_scale) , _scaler (s) , _frame (f) /* we round here; not sure if this is right */ @@ -148,13 +154,25 @@ DCPVideoFrame::~DCPVideoFrame () shared_ptr DCPVideoFrame::encode_locally () { - shared_ptr prepared = _input; - if (!_post_process.empty ()) { - prepared = prepared->post_process (_post_process); + _input = _input->post_process (_post_process); } - prepared = prepared->scale_and_convert_to_rgb (_out_size, _padding, _scaler); + shared_ptr prepared = _input->scale_and_convert_to_rgb (_out_size, _padding, _scaler); + + if (_subtitle) { + list > subs = _subtitle->images (); + for (list >::iterator i = subs.begin(); i != subs.end(); ++i) { + Rectangle tx = transformed_subtitle_area ( + float (_out_size.width) / _input->size().width, + float (_out_size.height) / _input->size().height, + (*i)->area(), _subtitle_offset, _subtitle_scale + ); + + shared_ptr im = (*i)->image()->scale (Size (tx.w, tx.h), _scaler); + prepared->alpha_blend (im, Position (tx.x, tx.y)); + } + } create_openjpeg_container (); @@ -290,6 +308,8 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) << _input->pixel_format() << " " << _out_size.width << " " << _out_size.height << " " << _padding << " " + << _subtitle_offset << " " + << _subtitle_scale << " " << _scaler->id () << " " << _frame << " " << _frames_per_second << " " diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index fe2e27966..4e9a777bd 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -106,7 +106,7 @@ public: class DCPVideoFrame { public: - DCPVideoFrame (boost::shared_ptr, boost::shared_ptr, Size, int, Scaler const *, int, float, std::string, int, int, Log *); + DCPVideoFrame (boost::shared_ptr, boost::shared_ptr, Size, int, int, float, Scaler const *, int, float, std::string, int, int, Log *); virtual ~DCPVideoFrame (); boost::shared_ptr encode_locally (); @@ -124,6 +124,8 @@ private: boost::shared_ptr _subtitle; ///< any subtitle that should be on the image Size _out_size; ///< the required size of the output, in pixels int _padding; + int _subtitle_offset; + float _subtitle_scale; Scaler const * _scaler; ///< scaler to use int _frame; ///< frame index within the Film int _frames_per_second; ///< Frames per second that we will use for the DCP (rounded) diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index c4759a872..1f771da2d 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -229,7 +229,7 @@ Decoder::process_audio (uint8_t* data, int size) * @param frame to decode; caller manages memory. */ void -Decoder::process_video (AVFrame* frame, shared_ptr sub) +Decoder::process_video (AVFrame* frame) { if (_minimal) { ++_video_frame; @@ -304,12 +304,9 @@ Decoder::process_video (AVFrame* frame, shared_ptr sub) image->make_black (); } - if (sub && _opt->apply_crop) { - list > im = sub->images (); - for (list >::iterator i = im.begin(); i != im.end(); ++i) { - Position p = (*i)->position (); - (*i)->set_position (Position (p.x - _fs->crop.left, p.y - _fs->crop.top)); - } + shared_ptr sub; + if (_subtitle && _subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { + sub = _subtitle; } TIMING ("Decoder emits %1", _video_frame); @@ -414,3 +411,16 @@ Decoder::setup_video_filters () /* XXX: leaking `inputs' / `outputs' ? */ } +void +Decoder::process_subtitle (shared_ptr s) +{ + _subtitle = s; + + if (_opt->apply_crop) { + list > im = _subtitle->images (); + for (list >::iterator i = im.begin(); i != im.end(); ++i) { + Position const p = (*i)->position (); + (*i)->set_position (Position (p.x - _fs->crop.left, p.y - _fs->crop.top)); + } + } +} diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 5cb44b8d9..805955b9d 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -101,8 +101,9 @@ protected: virtual int sample_aspect_ratio_numerator () const = 0; virtual int sample_aspect_ratio_denominator () const = 0; - void process_video (AVFrame *, boost::shared_ptr); + void process_video (AVFrame *); void process_audio (uint8_t *, int); + void process_subtitle (boost::shared_ptr); /** our FilmState */ boost::shared_ptr _fs; @@ -138,6 +139,8 @@ private: (at the DCP sample rate). */ int64_t _audio_frames_processed; + + boost::shared_ptr _subtitle; }; #endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index c2ee9297b..e01405191 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -205,12 +205,7 @@ FFmpegDecoder::do_pass () int frame_finished; while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - shared_ptr s; - if (_subtitle && _subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { - s = _subtitle; - } - - process_video (_frame, s); + process_video (_frame); } if (_audio_stream >= 0 && _opt->decode_audio) { @@ -231,12 +226,7 @@ FFmpegDecoder::do_pass () int frame_finished; if (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - shared_ptr s; - if (_subtitle && _subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { - s = _subtitle; - } - - process_video (_frame, s); + process_video (_frame); } } else if (_audio_stream >= 0 && _packet.stream_index == _audio_stream && _opt->decode_audio) { @@ -253,12 +243,12 @@ FFmpegDecoder::do_pass () process_audio (_frame->data[0], data_size); } - } else if (_subtitle_stream >= 0 && _packet.stream_index == _subtitle_stream) { + } else if (_subtitle_stream >= 0 && _packet.stream_index == _subtitle_stream && _opt->decode_subtitles) { int got_subtitle; AVSubtitle sub; if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) && got_subtitle) { - _subtitle.reset (new Subtitle (sub)); + process_subtitle (shared_ptr (new Subtitle (sub))); avsubtitle_free (&sub); } } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index e92b326b8..d34c22785 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -96,5 +96,4 @@ private: AVCodec* _subtitle_codec; ///< may be 0 if there is no subtitle AVPacket _packet; - boost::shared_ptr _subtitle; }; diff --git a/src/lib/film.cc b/src/lib/film.cc index e4155c9f6..31af2f1c2 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -535,6 +535,7 @@ Film::make_dcp (bool transcode, int freq) o->decode_video_frequency = freq; o->padding = format()->dcp_padding (this); o->ratio = format()->ratio_as_float (this); + o->decode_subtitles = with_subtitles (); shared_ptr r; diff --git a/src/lib/image.cc b/src/lib/image.cc index 602b20842..ce44ec95b 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -207,6 +207,42 @@ Image::make_black () } } +void +Image::alpha_blend (shared_ptr other, Position position) +{ + /* Only implemented for RGBA onto RGB24 so far */ + assert (_pixel_format == PIX_FMT_RGB24 && other->pixel_format() == PIX_FMT_RGBA); + + int start_tx = position.x; + int start_ox = 0; + + if (start_tx < 0) { + start_ox = -start_tx; + start_tx = 0; + } + + int start_ty = position.y; + int start_oy = 0; + + if (start_ty < 0) { + start_oy = -start_ty; + start_ty = 0; + } + + for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) { + uint8_t* tp = data()[0] + ty * line_size()[0] + position.x * 3; + uint8_t* op = other->data()[0] + oy * other->line_size()[0]; + for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) { + float const alpha = float (op[3]) / 255; + tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha; + tp[1] = (tp[1] * (1 - alpha)) + op[1] * alpha; + tp[2] = (tp[2] * (1 - alpha)) + op[2] * alpha; + tp += 3; + op += 4; + } + } +} + /** Construct a SimpleImage of a given size and format, allocating memory * as required. * @@ -217,8 +253,10 @@ SimpleImage::SimpleImage (PixelFormat p, Size s) : Image (p) , _size (s) { - _data = (uint8_t **) av_malloc (components() * sizeof (uint8_t *)); - _line_size = (int *) av_malloc (components() * sizeof (int)); + _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *)); + _data[0] = _data[1] = _data[2] = _data[3] = 0; + _line_size = (int *) av_malloc (4); + _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0; switch (p) { case PIX_FMT_RGB24: diff --git a/src/lib/image.h b/src/lib/image.h index 970750719..ea35fa0b9 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -68,6 +68,7 @@ public: boost::shared_ptr scale_and_convert_to_rgb (Size, int, Scaler const *) const; boost::shared_ptr scale (Size, Scaler const *) const; boost::shared_ptr post_process (std::string) const; + void alpha_blend (boost::shared_ptr image, Position pos); void make_black (); diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index df20479c9..32c433d09 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -61,7 +61,7 @@ ImageMagickDecoder::do_pass () } - process_video (image.frame (), shared_ptr ()); + process_video (image.frame ()); _done = true; return false; diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc index a241dd6e3..2b8aca649 100644 --- a/src/lib/j2k_still_encoder.cc +++ b/src/lib/j2k_still_encoder.cc @@ -52,7 +52,7 @@ J2KStillEncoder::process_video (shared_ptr yuv, int frame, shared_ptr const s = Filter::ffmpeg_strings (_fs->filters); DCPVideoFrame* f = new DCPVideoFrame ( - yuv, sub, _opt->out_size, _opt->padding, _fs->scaler, 0, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset, _fs->subtitle_scale, _fs->scaler, 0, _fs->frames_per_second, s.second, Config::instance()->colour_lut_index(), Config::instance()->j2k_bandwidth(), _log ); diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc index 7bcac483b..e2a3a5ed7 100644 --- a/src/lib/j2k_wav_encoder.cc +++ b/src/lib/j2k_wav_encoder.cc @@ -126,7 +126,8 @@ J2KWAVEncoder::process_video (shared_ptr yuv, int frame, shared_ptr ( new DCPVideoFrame ( - yuv, sub, _opt->out_size, _opt->padding, _fs->scaler, frame, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->subtitle_offset, _fs->subtitle_scale, + _fs->scaler, frame, _fs->frames_per_second, s.second, Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (), _log ) diff --git a/src/lib/options.h b/src/lib/options.h index 2fc5f77ff..86db35210 100644 --- a/src/lib/options.h +++ b/src/lib/options.h @@ -42,6 +42,7 @@ public: , black_after (0) , decode_video_frequency (0) , decode_audio (true) + , decode_subtitles (false) , _frame_out_path (f) , _frame_out_extension (e) , _multichannel_audio_out_path (m) @@ -99,6 +100,7 @@ public: int black_after; ///< first frame for which to output a black frame, rather than the actual video content, or 0 for none int decode_video_frequency; ///< skip frames so that this many are decoded in all (or 0) (for generating thumbnails) bool decode_audio; ///< true to decode audio, otherwise false + bool decode_subtitles; private: /** Path of the directory to write video frames to */ diff --git a/src/lib/server.cc b/src/lib/server.cc index 2fda5952f..26b2be7c7 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -88,6 +88,8 @@ Server::process (shared_ptr socket) int pixel_format_int; Size out_size; int padding; + int subtitle_offset; + int subtitle_scale; string scaler_id; int frame; float frames_per_second; @@ -99,6 +101,8 @@ Server::process (shared_ptr socket) >> pixel_format_int >> out_size.width >> out_size.height >> padding + >> subtitle_offset + >> subtitle_scale >> scaler_id >> frame >> frames_per_second @@ -120,7 +124,8 @@ Server::process (shared_ptr socket) /* XXX: subtitle */ DCPVideoFrame dcp_video_frame ( - image, shared_ptr (), out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log + image, shared_ptr (), out_size, padding, subtitle_offset, subtitle_scale, + scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log ); shared_ptr encoded = dcp_video_frame.encode_locally (); diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc index 0ea5a72d5..f0d77c511 100644 --- a/src/lib/subtitle.cc +++ b/src/lib/subtitle.cc @@ -73,34 +73,39 @@ SubtitleImage::SubtitleImage (AVSubtitleRect const * rect) Rectangle transformed_subtitle_area ( float target_x_scale, float target_y_scale, - Rectangle sub_area, - shared_ptr fs + Rectangle sub_area, int subtitle_offset, float subtitle_scale ) { Rectangle tx; - sub_area.y += fs->subtitle_offset; + sub_area.y += subtitle_offset; /* We will scale the subtitle by the same amount as the video frame, and also by the additional subtitle_scale */ - tx.w = sub_area.w * target_x_scale * fs->subtitle_scale; - tx.h = sub_area.h * target_y_scale * fs->subtitle_scale; + tx.w = sub_area.w * target_x_scale * subtitle_scale; + tx.h = sub_area.h * target_y_scale * subtitle_scale; /* Then we need a corrective translation, consisting of two parts: * * 1. that which is the result of the scaling of the subtitle by target_x_scale and target_y_scale; this will be * sub_area.x * target_x_scale and sub_area.y * target_y_scale. * - * 2. that to shift the origin of the scale by fs->subtitle_scale to the centre of the subtitle; this will be - * (width_before_subtitle_scale * (1 - fs->subtitle_scale) / 2) and - * (height_before_subtitle_scale * (1 - fs->subtitle_scale) / 2). + * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be + * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and + * (height_before_subtitle_scale * (1 - subtitle_scale) / 2). * * Combining these two translations gives these expressions. */ - tx.x = target_x_scale * (sub_area.x + (sub_area.w * (1 - fs->subtitle_scale) / 2)); - tx.y = target_y_scale * (sub_area.y + (sub_area.h * (1 - fs->subtitle_scale) / 2)); + tx.x = target_x_scale * (sub_area.x + (sub_area.w * (1 - subtitle_scale) / 2)); + tx.y = target_y_scale * (sub_area.y + (sub_area.h * (1 - subtitle_scale) / 2)); return tx; } + +Rectangle +SubtitleImage::area () const +{ + return Rectangle (_position.x, _position.y, _image->size().width, _image->size().height); +} diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h index d9717564e..6fd0d8772 100644 --- a/src/lib/subtitle.h +++ b/src/lib/subtitle.h @@ -47,8 +47,7 @@ private: extern Rectangle transformed_subtitle_area ( float target_x_scale, float target_y_scale, - Rectangle sub_area, - boost::shared_ptr fs + Rectangle sub_area, int subtitle_offset, float subtitle_scale ); class SubtitleImage @@ -68,6 +67,8 @@ public: return _image; } + Rectangle area () const; + private: Position _position; boost::shared_ptr _image; diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc index 116c65f7b..101e0c047 100644 --- a/src/lib/tiff_decoder.cc +++ b/src/lib/tiff_decoder.cc @@ -179,7 +179,7 @@ TIFFDecoder::do_pass () _TIFFfree (raster); TIFFClose (t); - process_video (image.frame (), shared_ptr ()); + process_video (image.frame ()); ++_iter; return false; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index bfeb44cb9..bf082adc2 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -179,7 +179,7 @@ private: for (list::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { i->transformed_area = transformed_subtitle_area ( - x_scale, y_scale, i->base_area, _film->state_copy() + x_scale, y_scale, i->base_area, _film->subtitle_offset(), _film->subtitle_scale() ); i->transformed_image = i->base_image; @@ -328,6 +328,7 @@ FilmViewer::update_thumbs () o->apply_crop = false; o->decode_audio = false; o->decode_video_frequency = 128; + o->decode_subtitles = true; shared_ptr j (new ThumbsJob (s, o, _film->log(), shared_ptr ())); j->Finished.connect (sigc::mem_fun (_film, &Film::update_thumbs_post_gui)); diff --git a/test/test.cc b/test/test.cc index 789724b53..aaa911b32 100644 --- a/test/test.cc +++ b/test/test.cc @@ -290,6 +290,8 @@ BOOST_AUTO_TEST_CASE (client_server_test) shared_ptr (), Size (1998, 1080), 0, + 0, + 0, Scaler::from_id ("bicubic"), 0, 24, -- cgit v1.2.3 From ade28a703b15af710161faa017cddf95d66c4118 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 14 Oct 2012 20:51:43 +0100 Subject: Try to clarify the difference between line size and stride. --- src/lib/ab_transcoder.cc | 5 ++-- src/lib/dcp_video_frame.cc | 4 +-- src/lib/image.cc | 66 +++++++++++++++++++++++++++++++--------------- src/lib/image.h | 12 +++++++-- src/lib/server.cc | 2 +- 5 files changed, 61 insertions(+), 28 deletions(-) (limited to 'src/lib/server.cc') diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index a32d82c54..54153ec76 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -80,14 +80,15 @@ ABTranscoder::process_video (shared_ptr yuv, int frame, shared_ptrcomponents(); ++i) { int const line_size = yuv->line_size()[i]; int const half_line_size = line_size / 2; + int const stride = yuv->stride()[i]; uint8_t* p = _image->data()[i]; uint8_t* q = yuv->data()[i]; for (int j = 0; j < yuv->lines (i); ++j) { memcpy (p + half_line_size, q + half_line_size, half_line_size); - p += line_size; - q += line_size; + p += stride; + q += stride; } } diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 3e5c4b3aa..04735269c 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -188,7 +188,7 @@ DCPVideoFrame::encode_locally () int jn = 0; for (int y = 0; y < _out_size.height; ++y) { - uint8_t* p = prepared->data()[0] + y * prepared->line_size()[0]; + uint8_t* p = prepared->data()[0] + y * prepared->stride()[0]; for (int x = 0; x < _out_size.width; ++x) { /* In gamma LUT (converting 8-bit input to 12-bit) */ @@ -332,7 +332,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) socket.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); for (int i = 0; i < _input->components(); ++i) { - socket.write (_input->data()[i], _input->line_size()[i] * _input->lines(i), 30); + socket.write (_input->data()[i], _input->stride()[i] * _input->lines(i), 30); } char buffer[32]; diff --git a/src/lib/image.cc b/src/lib/image.cc index c8849303c..2c0338b53 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -98,9 +98,9 @@ Image::scale (Size out_size, Scaler const * scaler) const sws_scale ( scale_context, - data(), line_size(), + data(), stride(), 0, size().height, - scaled->data (), scaled->line_size () + scaled->data(), scaled->stride() ); sws_freeContext (scale_context); @@ -131,9 +131,9 @@ Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scal /* Scale and convert to RGB from whatever its currently in (which may be RGB) */ sws_scale ( scale_context, - data(), line_size(), + data(), stride(), 0, size().height, - rgb->data (), rgb->line_size () + rgb->data(), rgb->stride() ); /* Put the image in the right place in a black frame if are padding; this is @@ -151,8 +151,8 @@ Image::scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scal uint8_t* q = rgb->data()[0]; for (int j = 0; j < rgb->lines(0); ++j) { memcpy (p, q, rgb->line_size()[0]); - p += padded_rgb->line_size()[0]; - q += rgb->line_size()[0]; + p += padded_rgb->stride()[0]; + q += rgb->stride()[0]; } rgb = padded_rgb; @@ -176,8 +176,8 @@ Image::post_process (string pp) const pp_context* context = pp_get_context (size().width, size().height, PP_FORMAT_420 | PP_CPU_CAPS_MMX2); pp_postprocess ( - (const uint8_t **) data(), line_size(), - out->data(), out->line_size(), + (const uint8_t **) data(), stride(), + out->data(), out->stride(), size().width, size().height, 0, 0, mode, context, 0 ); @@ -193,13 +193,13 @@ Image::make_black () { switch (_pixel_format) { case PIX_FMT_YUV420P: - memset (data()[0], 0, lines(0) * line_size()[0]); - memset (data()[1], 0x80, lines(1) * line_size()[1]); - memset (data()[2], 0x80, lines(2) * line_size()[2]); + memset (data()[0], 0, lines(0) * stride()[0]); + memset (data()[1], 0x80, lines(1) * stride()[1]); + memset (data()[2], 0x80, lines(2) * stride()[2]); break; case PIX_FMT_RGB24: - memset (data()[0], 0, lines(0) * line_size()[0]); + memset (data()[0], 0, lines(0) * stride()[0]); break; default: @@ -230,8 +230,8 @@ Image::alpha_blend (shared_ptr other, Position position) } for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) { - uint8_t* tp = data()[0] + ty * line_size()[0] + position.x * 3; - uint8_t* op = other->data()[0] + oy * other->line_size()[0]; + uint8_t* tp = data()[0] + ty * stride()[0] + position.x * 3; + uint8_t* op = other->data()[0] + oy * other->stride()[0]; for (int tx = start_tx, ox = start_ox; tx < size().width && ox < other->size().width; ++tx, ++ox) { float const alpha = float (op[3]) / 255; tp[0] = (tp[0] * (1 - alpha)) + op[0] * alpha; @@ -257,25 +257,28 @@ SimpleImage::SimpleImage (PixelFormat p, Size s) _data[0] = _data[1] = _data[2] = _data[3] = 0; _line_size = (int *) av_malloc (4); _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0; + _stride = (int *) av_malloc (4); + _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0; switch (p) { case PIX_FMT_RGB24: - _line_size[0] = round_up (s.width * 3, 32); + _line_size[0] = s.width * 3; break; case PIX_FMT_RGBA: - _line_size[0] = round_up (s.width * 4, 32); + _line_size[0] = s.width * 4; break; case PIX_FMT_YUV420P: - _line_size[0] = round_up (s.width, 32); - _line_size[1] = round_up (s.width / 2, 32); - _line_size[2] = round_up (s.width / 2, 32); + _line_size[0] = s.width; + _line_size[1] = s.width / 2; + _line_size[2] = s.width / 2; break; default: assert (false); } - + for (int i = 0; i < components(); ++i) { - _data[i] = (uint8_t *) av_malloc (_line_size[i] * lines (i)); + _stride[i] = round_up (_line_size[i], 32); + _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i)); } } @@ -288,6 +291,7 @@ SimpleImage::~SimpleImage () av_free (_data); av_free (_line_size); + av_free (_stride); } uint8_t ** @@ -302,6 +306,12 @@ SimpleImage::line_size () const return _line_size; } +int * +SimpleImage::stride () const +{ + return _stride; +} + Size SimpleImage::size () const { @@ -333,6 +343,13 @@ FilterBufferImage::line_size () const return _buffer->linesize; } +int * +FilterBufferImage::stride () const +{ + /* XXX? */ + return _buffer->linesize; +} + Size FilterBufferImage::size () const { @@ -377,6 +394,13 @@ RGBFrameImage::line_size () const return _frame->linesize; } +int * +RGBFrameImage::stride () const +{ + /* XXX? */ + return line_size (); +} + Size RGBFrameImage::size () const { diff --git a/src/lib/image.h b/src/lib/image.h index ea35fa0b9..3e16d43bf 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -57,9 +57,12 @@ public: /** @return Array of pointers to arrays of the component data */ virtual uint8_t ** data () const = 0; - /** @return Array of sizes of each line, in pixels */ + /** @return Array of sizes of the data in each line, in bytes (without any alignment padding bytes) */ virtual int * line_size () const = 0; + /** @return Array of strides for each line (including any alignment padding bytes) */ + virtual int * stride () const = 0; + /** @return Size of the image, in pixels */ virtual Size size () const = 0; @@ -91,6 +94,7 @@ public: uint8_t ** data () const; int * line_size () const; + int * stride () const; Size size () const; private: @@ -108,12 +112,15 @@ public: uint8_t ** data () const; int * line_size () const; + int * stride () const; Size size () const; private: Size _size; ///< size in pixels uint8_t** _data; ///< array of pointers to components - int* _line_size; ///< array of widths of each line, in bytes + int* _line_size; ///< array of sizes of the data in each line, in pixels (without any alignment padding bytes) + int* _stride; ///< array of strides for each line (including any alignment padding bytes) + }; /** @class RGBFrameImage @@ -127,6 +134,7 @@ public: uint8_t ** data () const; int * line_size () const; + int * stride () const; Size size () const; AVFrame * frame () const { return _frame; diff --git a/src/lib/server.cc b/src/lib/server.cc index 26b2be7c7..659418b8f 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -119,7 +119,7 @@ Server::process (shared_ptr socket) shared_ptr image (new SimpleImage (pixel_format, in_size)); for (int i = 0; i < image->components(); ++i) { - socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); + socket->read_definite_and_consume (image->data()[i], image->stride()[i] * image->lines(i), 30); } /* XXX: subtitle */ -- cgit v1.2.3