diff options
Diffstat (limited to 'src/lib/video_decoder.cc')
| -rw-r--r-- | src/lib/video_decoder.cc | 101 |
1 files changed, 65 insertions, 36 deletions
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 16a076698..a5147f42e 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -21,74 +21,103 @@ #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<Film> f, DecodeOptions o) - : Decoder (f, o) - , _video_frame (0) - , _last_source_time (0) +VideoDecoder::VideoDecoder (shared_ptr<const Film> f, shared_ptr<const VideoContent> 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> image, bool same, double t) +VideoDecoder::video (shared_ptr<Image> image, bool same, Time t) { + if (_frame_rate_conversion.skip && _odd) { + _odd = !_odd; + return; + } + + image->crop (_video_content->crop(), true); + + shared_ptr<const Film> 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<Image> out = image->scale_and_convert_to_rgb (image_size, film->scaler(), true); + shared_ptr<Subtitle> sub; if (_timed_subtitle && _timed_subtitle->displayed_at (t)) { sub = _timed_subtitle->subtitle (); } - Video (image, same, sub, t); - ++_video_frame; - - _last_source_time = t; + if (sub) { + dcpomatic::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() + ); + + shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true); + out->alpha_blend (im, tx.position()); + } + + if (image_size != container_size) { + assert (image_size.width <= container_size.width); + assert (image_size.height <= container_size.height); + shared_ptr<Image> 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); + } + + _odd = !_odd; } -/** Set up the current subtitle. This will be put onto frames that - * fit within its time specification. s may be 0 to say that there - * is no current subtitle. +/** 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<TimedSubtitle> s) +VideoDecoder::subtitle (shared_ptr<TimedSubtitle> 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)); + _timed_subtitle->subtitle()->set_position (Position (p.x - _video_content->crop().left, p.y - _video_content->crop().top)); } } -/** Set which stream of subtitles we should use from our source. - * @param s Stream to use. - */ -void -VideoDecoder::set_subtitle_stream (shared_ptr<SubtitleStream> s) -{ - _subtitle_stream = s; -} - -void -VideoDecoder::set_progress (Job* j) const +bool +VideoDecoder::video_done () const { - assert (j); + shared_ptr<const Film> film = _film.lock (); + assert (film); - if (_film->length()) { - j->set_progress (float (_video_frame) / _film->length().get()); - } + return (_video_content->length() - _next_video) < film->video_frames_to_time (1); } |
