X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fvideo_decoder.cc;h=cba21d280aae20a51fff025cb470fde6d3f5cb10;hb=f385ef03e5ea27519a31c0839447735a7fba0602;hp=0fa16bc325b8b6ee8a309098c54a066359d99e1a;hpb=32fc1ddb0ee004d18c36155ddcf4d9b3998a7061;p=dcpomatic.git diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 0fa16bc32..cba21d280 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -21,81 +21,94 @@ #include "subtitle.h" #include "film.h" #include "image.h" -#include "log.h" -#include "options.h" -#include "job.h" +#include "ratio.h" +#include "i18n.h" + +using std::cout; using boost::shared_ptr; -using boost::optional; -VideoDecoder::VideoDecoder (shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) - , _video_frame (0) - , _last_source_time (0) +VideoDecoder::VideoDecoder (shared_ptr f, shared_ptr c) + : Decoder (f) + , _next_video (0) + , _video_content (c) + , _frame_rate_conversion (c->video_frame_rate(), f->dcp_video_frame_rate()) + , _odd (false) { } -/** Called by subclasses to tell the world that some video data is ready. - * We find a subtitle then emit it for listeners. +/** Called by subclasses when some video is ready. * @param image frame to emit. - * @param t Time of the frame within the source, in seconds. + * @param same true if this frame is the same as the last one passed to this call. + * @param t Time of the frame within the source. */ void -VideoDecoder::emit_video (shared_ptr image, double t) +VideoDecoder::video (shared_ptr image, bool same, Time t) { + if (_frame_rate_conversion.skip && _odd) { + _odd = !_odd; + return; + } + + image->crop (_video_content->crop(), true); + + shared_ptr film = _film.lock (); + assert (film); + + libdcp::Size const container_size = film->container()->size (film->full_frame ()); + libdcp::Size const image_size = _video_content->ratio()->size (container_size); + + shared_ptr out = image->scale_and_convert_to_rgb (image_size, film->scaler(), true); + shared_ptr sub; if (_timed_subtitle && _timed_subtitle->displayed_at (t)) { sub = _timed_subtitle->subtitle (); } - signal_video (image, false, sub); - _last_source_time = t; -} + if (sub) { + Rect const tx = subtitle_transformed_area ( + float (image_size.width) / video_size().width, + float (image_size.height) / video_size().height, + sub->area(), film->subtitle_offset(), film->subtitle_scale() + ); -void -VideoDecoder::repeat_last_video () -{ - if (!_last_image) { - _last_image.reset (new SimpleImage (pixel_format(), native_size(), true)); - _last_image->make_black (); + shared_ptr im = sub->image()->scale (tx.size(), film->scaler(), true); + out->alpha_blend (im, tx.position()); } - signal_video (_last_image, true, _last_subtitle); -} - -void -VideoDecoder::signal_video (shared_ptr image, bool same, shared_ptr sub) -{ - TIMING ("Decoder emits %1", _video_frame); - Video (image, same, sub); - ++_video_frame; + if (image_size != container_size) { + assert (image_size.width <= container_size.width); + assert (image_size.height <= container_size.height); + shared_ptr im (new SimpleImage (PIX_FMT_RGB24, container_size, true)); + im->make_black (); + im->copy (out, Position ((container_size.width - image_size.width) / 2, (container_size.height - image_size.height) / 2)); + out = im; + } + + Video (out, same, t); + + if (_frame_rate_conversion.repeat) { + Video (image, true, t + film->video_frames_to_time (1)); + _next_video = t + film->video_frames_to_time (2); + } else { + _next_video = t + film->video_frames_to_time (1); + } - _last_image = image; - _last_subtitle = sub; + _odd = !_odd; } +/** Called by subclasses when a subtitle is ready. + * s may be 0 to say that there is no current subtitle. + * @param s New current subtitle, or 0. + */ void -VideoDecoder::emit_subtitle (shared_ptr s) +VideoDecoder::subtitle (shared_ptr s) { _timed_subtitle = s; if (_timed_subtitle) { Position const p = _timed_subtitle->subtitle()->position (); - _timed_subtitle->subtitle()->set_position (Position (p.x - _film->crop().left, p.y - _film->crop().top)); - } -} - -void -VideoDecoder::set_subtitle_stream (shared_ptr s) -{ - _subtitle_stream = s; -} - -void -VideoDecoder::set_progress () const -{ - if (_job && _film->length()) { - _job->set_progress (float (_video_frame) / _film->length().get()); + _timed_subtitle->subtitle()->set_position (Position (p.x - _video_content->crop().left, p.y - _video_content->crop().top)); } }