#include "player.h"
#include "film.h"
#include "ffmpeg_decoder.h"
+#include "audio_buffers.h"
#include "ffmpeg_content.h"
#include "image_decoder.h"
#include "image_content.h"
, _have_valid_pieces (false)
, _video_position (0)
, _audio_position (0)
- , _audio_merger (f->audio_channels(), bind (&Film::time_to_audio_frames, f.get(), _1), bind (&Film::audio_frames_to_time, f.get(), _1))
+ , _audio_merger (f->audio_channels(), f->audio_frame_rate ())
, _last_emit_was_black (false)
, _just_did_inaccurate_seek (false)
, _approximate_size (false)
_playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
_playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
_film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
- set_video_container_size (fit_ratio_within (_film->container()->ratio (), _film->full_frame ()));
+ set_video_container_size (_film->frame_size ());
}
void
shared_ptr<Piece> earliest_piece;
shared_ptr<Decoded> earliest_decoded;
- DCPTime earliest_time = TIME_MAX;
- DCPTime earliest_audio = TIME_MAX;
+ DCPTime earliest_time = DCPTime::max ();
+ DCPTime earliest_audio = DCPTime::max ();
for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
break;
}
- dec->set_dcp_times (_film->video_frame_rate(), _film->audio_frame_rate(), (*i)->frc, offset);
+ dec->set_dcp_times ((*i)->frc, offset);
DCPTime const t = dec->dcp_time - offset;
if (t >= ((*i)->content->full_length() - (*i)->content->trim_end ())) {
/* In the end-trimmed part; decoder has nothing else to give us */
return true;
}
- if (earliest_audio != TIME_MAX) {
- TimedAudioBuffers<DCPTime> tb = _audio_merger.pull (max (int64_t (0), earliest_audio));
+ if (earliest_audio != DCPTime::max ()) {
+ if (earliest_audio.get() < 0) {
+ earliest_audio = DCPTime ();
+ }
+ TimedAudioBuffers tb = _audio_merger.pull (earliest_audio);
Audio (tb.audio, tb.time);
- /* This assumes that the audio_frames_to_time conversion is exact
+ /* This assumes that the audio-frames-to-time conversion is exact
so that there are no accumulated errors caused by rounding.
*/
- _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
+ _audio_position += DCPTime::from_frames (tb.audio->frames(), _film->audio_frame_rate ());
}
/* Emit the earliest thing */
shared_ptr<DecodedImageSubtitle> dis = dynamic_pointer_cast<DecodedImageSubtitle> (earliest_decoded);
shared_ptr<DecodedTextSubtitle> dts = dynamic_pointer_cast<DecodedTextSubtitle> (earliest_decoded);
-#if 0
- if (dv) {
- cout << "Video @ " << dv->dcp_time << " " << (double(dv->dcp_time) / TIME_HZ) << ".\n";
- } else if (da) {
- cout << "Audio.\n";
- } else if (dis) {
- cout << "Image sub.\n";
- } else if (dts) {
- cout << "Text sub.\n";
- }
-#endif
-
/* Will be set to false if we shouldn't consume the peeked DecodedThing */
bool consume = true;
FrameRateChange frc (content->video_frame_rate(), _film->video_frame_rate());
- float const ratio = content->ratio() ? content->ratio()->ratio() : content->video_size_after_crop().ratio();
- dcp::Size image_size = fit_ratio_within (ratio, _video_container_size);
+ dcp::Size image_size = content->scale().size (content, _video_container_size);
if (_approximate_size) {
image_size.width &= ~3;
image_size.height &= ~3;
{
/* This is a bit of a hack; don't update _video_position if EYES_RIGHT is on its way */
if (video->eyes != EYES_LEFT) {
- /* This assumes that the video_frames_to_time conversion is exact
+ /* This assumes that the video-frames-to-time conversion is exact
so that there are no accumulated errors caused by rounding.
*/
- _video_position += _film->video_frames_to_time (1);
+ _video_position += DCPTime::from_frames (1, _film->video_frame_rate ());
}
}
audio->data = dcp_mapped;
/* Delay */
- 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;
+ audio->dcp_time += DCPTime::from_seconds (content->audio_delay() / 1000.0);
+ if (audio->dcp_time < DCPTime (0)) {
+ int const frames = - audio->dcp_time.frames (_film->audio_frame_rate());
if (frames >= audio->data->frames ()) {
return;
}
trimmed->copy_from (audio->data.get(), audio->data->frames() - frames, frames, 0);
audio->data = trimmed;
- audio->dcp_time = 0;
+ audio->dcp_time = DCPTime ();
}
_audio_merger.push (audio->data, audio->dcp_time);
void
Player::flush ()
{
- TimedAudioBuffers<DCPTime> tb = _audio_merger.flush ();
+ TimedAudioBuffers tb = _audio_merger.flush ();
if (_audio && tb.audio) {
Audio (tb.audio, tb.time);
- _audio_position += _film->audio_frames_to_time (tb.audio->frames ());
+ _audio_position += DCPTime::from_frames (tb.audio->frames (), _film->audio_frame_rate ());
}
while (_video && _video_position < _audio_position) {
while (_audio && _audio_position < _video_position) {
emit_silence (_video_position - _audio_position);
}
-
}
/** Seek so that the next pass() will yield (approximately) the requested frame.
s = min ((*i)->content->length_after_trim(), s);
/* Convert this to the content time */
- ContentTime ct = (s + (*i)->content->trim_start()) * (*i)->frc.speed_up;
+ ContentTime ct (s + (*i)->content->trim_start(), (*i)->frc);
/* And seek the decoder */
(*i)->decoder->seek (ct, accurate);
}
- _video_position = time_round_up (t, TIME_HZ / _film->video_frame_rate());
- _audio_position = time_round_up (t, TIME_HZ / _film->audio_frame_rate());
+ _video_position = t.round_up (_film->video_frame_rate());
+ _audio_position = t.round_up (_film->audio_frame_rate());
_audio_merger.clear (_audio_position);
optional<FrameRateChange> frc;
/* Work out a FrameRateChange for the best overlap video for this content, in case we need it below */
- DCPTime best_overlap_t = 0;
+ DCPTime best_overlap_t;
shared_ptr<VideoContent> best_overlap;
for (ContentList::iterator j = content.begin(); j != content.end(); ++j) {
shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*j);
/* FFmpeg */
shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
if (fc) {
- decoder.reset (new FFmpegDecoder (_film, fc, _video, _audio));
+ decoder.reset (new FFmpegDecoder (fc, _film->log(), _video, _audio, _film->with_subtitles ()));
frc = FrameRateChange (fc->video_frame_rate(), _film->video_frame_rate());
}
}
if (!decoder) {
- decoder.reset (new ImageDecoder (_film, ic));
+ decoder.reset (new ImageDecoder (ic));
}
frc = FrameRateChange (ic->video_frame_rate(), _film->video_frame_rate());
/* SndfileContent */
shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
if (sc) {
- decoder.reset (new SndfileDecoder (_film, sc));
+ decoder.reset (new SndfileDecoder (sc));
frc = best_overlap_frc;
}
/* SubRipContent */
shared_ptr<const SubRipContent> rc = dynamic_pointer_cast<const SubRipContent> (*i);
if (rc) {
- decoder.reset (new SubRipDecoder (_film, rc));
+ decoder.reset (new SubRipDecoder (rc));
frc = best_overlap_frc;
}
- ContentTime st = (*i)->trim_start() * frc->speed_up;
+ ContentTime st ((*i)->trim_start(), frc.get ());
decoder->seek (st, true);
_pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder, frc.get ())));
/* The Piece for the _last_incoming_video will no longer be valid */
_last_incoming_video.video.reset ();
- _video_position = _audio_position = 0;
+ _video_position = DCPTime ();
+ _audio_position = DCPTime ();
}
void
Changed (frequent);
} else if (
- property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO ||
+ property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_SCALE ||
property == VideoContentProperty::VIDEO_FRAME_RATE
) {
#endif
Video (_black_frame, EYES_BOTH, ColourConversion(), _last_emit_was_black, _video_position);
- _video_position += _film->video_frames_to_time (1);
+ _video_position += DCPTime::from_frames (1, _film->video_frame_rate ());
_last_emit_was_black = true;
}
void
Player::emit_silence (DCPTime most)
{
- if (most == 0) {
+ if (most == DCPTime ()) {
return;
}
- DCPTime t = min (most, TIME_HZ / 2);
- shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), t * _film->audio_frame_rate() / TIME_HZ));
+ DCPTime t = min (most, DCPTime::from_seconds (0.5));
+ shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), t.frames (_film->audio_frame_rate())));
silence->make_silent ();
Audio (silence, _audio_position);
PlayerStatistics::dump (shared_ptr<Log> log) const
{
log->log (String::compose ("Video: %1 good %2 skipped %3 black %4 repeat", video.good, video.skip, video.black, video.repeat));
- log->log (String::compose ("Audio: %1 good %2 skipped %3 silence", audio.good, audio.skip, audio.silence));
+ log->log (String::compose ("Audio: %1 good %2 skipped %3 silence", audio.good, audio.skip, audio.silence.seconds()));
}
PlayerStatistics const &