2 Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "ffmpeg_decoder.h"
24 #include "ffmpeg_content.h"
25 #include "still_image_decoder.h"
26 #include "still_image_content.h"
27 #include "sndfile_decoder.h"
28 #include "sndfile_content.h"
29 #include "subtitle_content.h"
34 #include "resampler.h"
45 using boost::shared_ptr;
46 using boost::weak_ptr;
47 using boost::dynamic_pointer_cast;
49 //#define DEBUG_PLAYER 1
54 Piece (shared_ptr<Content> c)
56 , video_position (c->start ())
57 , audio_position (c->start ())
60 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
63 , video_position (c->start ())
64 , audio_position (c->start ())
67 shared_ptr<Content> content;
68 shared_ptr<Decoder> decoder;
74 std::ostream& operator<<(std::ostream& s, Piece const & p)
76 if (dynamic_pointer_cast<FFmpegContent> (p.content)) {
78 } else if (dynamic_pointer_cast<StillImageContent> (p.content)) {
80 } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
84 s << " at " << p.content->start() << " until " << p.content->end();
90 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
95 , _have_valid_pieces (false)
98 , _audio_buffers (f->audio_channels(), 0)
100 _playlist->Changed.connect (bind (&Player::playlist_changed, this));
101 _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
102 _film->Changed.connect (bind (&Player::film_changed, this, _1));
103 set_video_container_size (_film->container()->size (_film->full_frame ()));
107 Player::disable_video ()
113 Player::disable_audio ()
121 if (!_have_valid_pieces) {
123 _have_valid_pieces = true;
130 Time earliest_t = TIME_MAX;
131 shared_ptr<Piece> earliest;
137 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
138 if ((*i)->decoder->done ()) {
142 if (_video && dynamic_pointer_cast<VideoDecoder> ((*i)->decoder)) {
143 if ((*i)->video_position < earliest_t) {
144 earliest_t = (*i)->video_position;
150 if (_audio && dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
151 if ((*i)->audio_position < earliest_t) {
152 earliest_t = (*i)->audio_position;
161 cout << "no earliest piece.\n";
170 if (earliest_t > _video_position) {
172 cout << "no video here; emitting black frame (earliest=" << earliest_t << ", video_position=" << _video_position << ").\n";
177 cout << "Pass " << *earliest << "\n";
179 earliest->decoder->pass ();
184 if (earliest_t > _audio_position) {
186 cout << "no audio here; emitting silence.\n";
188 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
191 cout << "Pass " << *earliest << "\n";
193 earliest->decoder->pass ();
195 if (earliest->decoder->done()) {
196 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
198 shared_ptr<Resampler> re = resampler (ac, false);
200 shared_ptr<const AudioBuffers> b = re->flush ();
202 process_audio (earliest, b, ac->audio_length ());
211 cout << "\tpost pass " << _video_position << " " << _audio_position << "\n";
218 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame)
220 shared_ptr<Piece> piece = weak_piece.lock ();
225 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
228 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
229 if (frc.skip && (frame % 2) == 1) {
233 shared_ptr<Image> work_image = image->crop (content->crop(), true);
235 libdcp::Size const image_size = content->ratio()->size (_video_container_size);
237 work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
239 Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
241 if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
242 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
245 if (image_size != _video_container_size) {
246 assert (image_size.width <= _video_container_size.width);
247 assert (image_size.height <= _video_container_size.height);
248 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
250 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
254 #ifdef DCPOMATIC_DEBUG
255 _last_video = piece->content;
258 Video (work_image, eyes, same, time);
259 time += TIME_HZ / _film->video_frame_rate();
262 Video (work_image, eyes, true, time);
263 time += TIME_HZ / _film->video_frame_rate();
266 _video_position = piece->video_position = time;
270 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
272 shared_ptr<Piece> piece = weak_piece.lock ();
277 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
281 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
282 shared_ptr<Resampler> r = resampler (content, true);
283 audio = r->run (audio);
287 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
288 dcp_mapped->make_silent ();
289 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
290 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
291 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
292 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
298 /* Convert frame to time. After resampling, the frame time (in the DCP rate) will be T_D where
299 T_D = frame * DCP_rate / original_rate. Hence the time in seconds is T_D / DCP_rate.
301 Time time = content->start() + (frame * TIME_HZ / _film->audio_frame_rate()) + (content->audio_delay() * TIME_HZ / 1000);
303 /* We must cut off anything that comes before the start of all time */
305 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
306 if (frames >= audio->frames ()) {
310 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
311 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
317 /* The time of this audio may indicate that some of our buffered audio is not going to
318 be added to any more, so it can be emitted.
321 if (time > _audio_position) {
322 /* We can emit some audio from our buffers */
323 OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
324 if (N > _audio_buffers.frames()) {
325 /* We need some extra silence before whatever is in the buffers */
326 _audio_buffers.ensure_size (N);
327 _audio_buffers.move (0, N - _audio_buffers.frames(), _audio_buffers.frames ());
328 _audio_buffers.make_silent (0, _audio_buffers.frames());
329 _audio_buffers.set_frames (N);
331 assert (N <= _audio_buffers.frames());
332 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
333 emit->copy_from (&_audio_buffers, N, 0, 0);
334 Audio (emit, _audio_position);
335 _audio_position = piece->audio_position = time + _film->audio_frames_to_time (N);
337 /* And remove it from our buffers */
338 if (_audio_buffers.frames() > N) {
339 _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
341 _audio_buffers.set_frames (_audio_buffers.frames() - N);
344 /* Now accumulate the new audio into our buffers */
345 _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
346 _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
347 _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
353 if (_audio_buffers.frames() > 0) {
354 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
355 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
356 Audio (emit, _audio_position);
357 _audio_position += _film->audio_frames_to_time (_audio_buffers.frames ());
358 _audio_buffers.set_frames (0);
361 while (_video_position < _audio_position) {
365 while (_audio_position < _video_position) {
366 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
371 /** Seek so that the next pass() will yield (approximately) the requested frame.
372 * Pass accurate = true to try harder to get close to the request.
373 * @return true on error
376 Player::seek (Time t, bool accurate)
378 if (!_have_valid_pieces) {
380 _have_valid_pieces = true;
383 if (_pieces.empty ()) {
387 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
388 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
393 Time s = t - vc->start ();
394 s = max (static_cast<Time> (0), s);
395 s = min (vc->length(), s);
397 (*i)->video_position = (*i)->audio_position = vc->start() + s;
399 FrameRateConversion frc (vc->video_frame_rate(), _film->video_frame_rate());
400 /* Here we are converting from time (in the DCP) to a frame number in the content.
401 Hence we need to use the DCP's frame rate and the double/skip correction, not
404 VideoContent::Frame f = s * _film->video_frame_rate() / (frc.factor() * TIME_HZ);
405 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
408 _video_position = _audio_position = t;
410 /* XXX: don't seek audio because we don't need to... */
414 Player::setup_pieces ()
416 list<shared_ptr<Piece> > old_pieces = _pieces;
420 ContentList content = _playlist->content ();
421 sort (content.begin(), content.end(), ContentSorter ());
423 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
425 shared_ptr<Piece> piece (new Piece (*i));
427 /* XXX: into content? */
429 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
431 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
433 fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
434 fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
435 fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
440 shared_ptr<const StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
442 shared_ptr<StillImageDecoder> id;
444 /* See if we can re-use an old StillImageDecoder */
445 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
446 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
447 if (imd && imd->content() == ic) {
453 id.reset (new StillImageDecoder (_film, ic));
454 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
460 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
462 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
463 sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
468 _pieces.push_back (piece);
472 cout << "=== Player setup:\n";
473 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
474 cout << *(i->get()) << "\n";
480 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
482 shared_ptr<Content> c = w.lock ();
488 property == ContentProperty::START || property == ContentProperty::LENGTH ||
489 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO
492 _have_valid_pieces = false;
495 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
498 } else if (property == VideoContentProperty::VIDEO_FRAME_TYPE) {
504 Player::playlist_changed ()
506 _have_valid_pieces = false;
511 Player::set_video_container_size (libdcp::Size s)
513 _video_container_size = s;
514 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
515 _black_frame->make_black ();
518 shared_ptr<Resampler>
519 Player::resampler (shared_ptr<AudioContent> c, bool create)
521 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
522 if (i != _resamplers.end ()) {
527 return shared_ptr<Resampler> ();
530 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
536 Player::emit_black ()
538 #ifdef DCPOMATIC_DEBUG
539 _last_video.reset ();
542 /* XXX: use same here */
543 Video (_black_frame, EYES_BOTH, false, _video_position);
544 _video_position += _film->video_frames_to_time (1);
548 Player::emit_silence (OutputAudioFrame most)
550 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
551 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
552 silence->make_silent ();
553 Audio (silence, _audio_position);
554 _audio_position += _film->audio_frames_to_time (N);
558 Player::film_changed (Film::Property p)
560 /* Here we should notice Film properties that affect our output, and
561 alert listeners that our output now would be different to how it was
562 last time we were run.
565 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
571 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
573 _in_subtitle.piece = weak_piece;
574 _in_subtitle.image = image;
575 _in_subtitle.rect = rect;
576 _in_subtitle.from = from;
577 _in_subtitle.to = to;
583 Player::update_subtitle ()
585 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
590 if (!_in_subtitle.image) {
591 _out_subtitle.image.reset ();
595 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
598 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
599 libdcp::Size scaled_size;
601 in_rect.y += sc->subtitle_offset ();
603 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
604 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
605 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
607 /* Then we need a corrective translation, consisting of two parts:
609 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
610 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
612 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
613 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
614 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
616 * Combining these two translations gives these expressions.
619 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
620 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
622 _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true);
623 _out_subtitle.from = _in_subtitle.from + piece->content->start ();
624 _out_subtitle.to = _in_subtitle.to + piece->content->start ();