X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fplayer.cc;h=ab0d8f3566ecb484ec491ba6314ff9cbbdd5f24b;hb=39bc73fe192f932ed6695eb87b19de446e8b4f55;hp=2450ace2e4ed0bd8d3c269e32e24b4db6cf68457;hpb=16b279646ca4e921aa6ea06c59256e3bca7e5a61;p=dcpomatic.git diff --git a/src/lib/player.cc b/src/lib/player.cc index 2450ace2e..ab0d8f356 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -34,13 +34,14 @@ #include "playlist.h" #include "job.h" #include "image.h" +#include "image_proxy.h" #include "ratio.h" #include "log.h" #include "scaler.h" #include "render_subtitles.h" -#include "dcp_video.h" #include "config.h" #include "content_video.h" +#include "player_video_frame.h" using std::list; using std::cout; @@ -218,7 +219,7 @@ Player::film_changed (Film::Property p) } list -Player::process_content_image_subtitles (shared_ptr content, list > subs) +Player::process_content_image_subtitles (shared_ptr content, list > subs) const { list all; @@ -269,7 +270,7 @@ Player::process_content_image_subtitles (shared_ptr content, li } list -Player::process_content_text_subtitles (list > sub) +Player::process_content_text_subtitles (list > sub) const { list all; for (list >::const_iterator i = sub.begin(); i != sub.end(); ++i) { @@ -287,74 +288,50 @@ Player::set_approximate_size () _approximate_size = true; } -shared_ptr -Player::black_dcp_video (DCPTime time) const +shared_ptr +Player::black_player_video_frame () const { - return shared_ptr ( - new DCPVideo ( - _black_image, - EYES_BOTH, + return shared_ptr ( + new PlayerVideoFrame ( + shared_ptr (new RawImageProxy (_black_image)), Crop (), _video_container_size, _video_container_size, Scaler::from_id ("bicubic"), - Config::instance()->colour_conversions().front().conversion, - time + EYES_BOTH, + PART_WHOLE, + Config::instance()->colour_conversions().front().conversion ) ); } -shared_ptr -Player::get_video (DCPTime time, bool accurate) +shared_ptr +Player::content_to_player_video_frame ( + shared_ptr content, + ContentVideo content_video, + list > subs, + DCPTime time, + dcp::Size image_size) const { - if (!_have_valid_pieces) { - setup_pieces (); - } - - list > ov = overlaps (time); - if (ov.empty ()) { - /* No video content at this time */ - return black_dcp_video (time); - } - - /* Create a DCPVideo from the content's video at this time */ - - shared_ptr piece = ov.back (); - shared_ptr decoder = dynamic_pointer_cast (piece->decoder); - assert (decoder); - shared_ptr content = dynamic_pointer_cast (piece->content); - assert (content); - - optional dec = decoder->get_video (dcp_to_content_video (piece, time), accurate); - if (!dec) { - return black_dcp_video (time); - } - - dcp::Size image_size = content->scale().size (content, _video_container_size, _film->frame_size ()); - if (_approximate_size) { - image_size.width &= ~3; - image_size.height &= ~3; - } - - shared_ptr dcp_video ( - new DCPVideo ( - dec->image, - dec->eyes, + shared_ptr pvf ( + new PlayerVideoFrame ( + content_video.image, content->crop (), image_size, _video_container_size, _film->scaler(), - content->colour_conversion (), - time + content_video.eyes, + content_video.part, + content->colour_conversion () ) ); - + + /* Add subtitles */ - - ov = overlaps (time); + list sub_images; - for (list >::const_iterator i = ov.begin(); i != ov.end(); ++i) { + for (list >::const_iterator i = subs.begin(); i != subs.end(); ++i) { shared_ptr subtitle_decoder = dynamic_pointer_cast ((*i)->decoder); shared_ptr subtitle_content = dynamic_pointer_cast ((*i)->content); ContentTime const from = dcp_to_content_subtitle (*i, time); @@ -366,10 +343,10 @@ Player::get_video (DCPTime time, bool accurate) subtitle_content, image_subtitles ); - + copy (im.begin(), im.end(), back_inserter (sub_images)); } - + if (_burn_subtitles) { list > text_subtitles = subtitle_decoder->get_text_subtitles (from, to); if (!text_subtitles.empty ()) { @@ -378,12 +355,65 @@ Player::get_video (DCPTime time, bool accurate) } } } - + if (!sub_images.empty ()) { - dcp_video->set_subtitle (merge (sub_images)); + pvf->set_subtitle (merge (sub_images)); } - return dcp_video; + return pvf; +} + +/** @return All PlayerVideoFrames at the given time (there may be two frames for 3D) */ +list > +Player::get_video (DCPTime time, bool accurate) +{ + if (!_have_valid_pieces) { + setup_pieces (); + } + + list > ov = overlaps ( + time, + time + DCPTime::from_frames (1, _film->video_frame_rate ()) + ); + + list > pvf; + + if (ov.empty ()) { + /* No video content at this time */ + pvf.push_back (black_player_video_frame ()); + return pvf; + } + + /* Create a PlayerVideoFrame from the content's video at this time */ + + shared_ptr piece = ov.back (); + shared_ptr decoder = dynamic_pointer_cast (piece->decoder); + assert (decoder); + shared_ptr content = dynamic_pointer_cast (piece->content); + assert (content); + + list content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate); + if (content_video.empty ()) { + pvf.push_back (black_player_video_frame ()); + return pvf; + } + + dcp::Size image_size = content->scale().size (content, _video_container_size, _film->frame_size ()); + if (_approximate_size) { + image_size.width &= ~3; + image_size.height &= ~3; + } + + for (list::const_iterator i = content_video.begin(); i != content_video.end(); ++i) { + list > subs = overlaps ( + time, + time + DCPTime::from_frames (1, _film->video_frame_rate ()) + ); + + pvf.push_back (content_to_player_video_frame (content, *i, subs, time, image_size)); + } + + return pvf; } shared_ptr @@ -398,7 +428,7 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate) shared_ptr audio (new AudioBuffers (_film->audio_channels(), length_frames)); audio->make_silent (); - list > ov = overlaps (time); + list > ov = overlaps (time, time + length); if (ov.empty ()) { return audio; } @@ -410,17 +440,28 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate) shared_ptr decoder = dynamic_pointer_cast ((*i)->decoder); assert (decoder); - if (content->content_audio_frame_rate() == 0) { + if (content->audio_frame_rate() == 0) { /* This AudioContent has no audio (e.g. if it is an FFmpegContent with no * audio stream). */ continue; } - AudioFrame const content_time = dcp_to_content_audio (*i, time); + /* The time that we should request from the content */ + DCPTime request = time - DCPTime::from_seconds (content->audio_delay() / 1000.0); + DCPTime offset; + if (request < DCPTime ()) { + /* We went off the start of the content, so we will need to offset + the stuff we get back. + */ + offset = -request; + request = DCPTime (); + } + + AudioFrame const content_frame = dcp_to_content_audio (*i, request); - /* Audio from this piece's decoder (which might be more than what we asked for) */ - shared_ptr all = decoder->get_audio (content_time, length_frames, accurate); + /* Audio from this piece's decoder (which might be more or less than what we asked for) */ + shared_ptr all = decoder->get_audio (content_frame, length_frames, accurate); /* Gain */ if (content->audio_gain() != 0) { @@ -447,25 +488,13 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate) } all->audio = dcp_mapped; - - /* Delay */ - /* XXX - audio->dcp_time += content->audio_delay() * TIME_HZ / 1000; - if (audio->dcp_time < 0) { - int const frames = - audio->dcp_time * _film->audio_frame_rate() / TIME_HZ; - if (frames >= audio->audio->frames ()) { - return; - } - - shared_ptr trimmed (new AudioBuffers (audio->audio->channels(), audio->audio->frames() - frames)); - trimmed->copy_from (audio->audio.get(), audio->audio->frames() - frames, frames, 0); - - audio->audio = trimmed; - audio->dcp_time = 0; - } - */ - audio->accumulate_frames (all->audio.get(), all->frame - content_time, 0, min (AudioFrame (all->audio->frames()), length_frames)); + audio->accumulate_frames ( + all->audio.get(), + content_frame - all->frame, + offset.frames (_film->audio_frame_rate()), + min (AudioFrame (all->audio->frames()), length_frames) - offset.frames (_film->audio_frame_rate ()) + ); } return audio;