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 ());
212 cout << "\tpost pass " << _video_position << " " << _audio_position << "\n";
219 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame)
221 shared_ptr<Piece> piece = weak_piece.lock ();
226 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
229 FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
230 if (frc.skip && (frame % 2) == 1) {
234 shared_ptr<Image> work_image = image->crop (content->crop(), true);
236 libdcp::Size const image_size = content->ratio()->size (_video_container_size);
238 work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
240 Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->video_frame_rate());
242 if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
243 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
246 if (image_size != _video_container_size) {
247 assert (image_size.width <= _video_container_size.width);
248 assert (image_size.height <= _video_container_size.height);
249 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
251 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
255 #ifdef DCPOMATIC_DEBUG
256 _last_video = piece->content;
259 Video (work_image, eyes, same, time);
260 time += TIME_HZ / _film->video_frame_rate();
263 Video (work_image, eyes, true, time);
264 time += TIME_HZ / _film->video_frame_rate();
267 _video_position = piece->video_position = time;
271 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
273 shared_ptr<Piece> piece = weak_piece.lock ();
278 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
282 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
283 shared_ptr<Resampler> r = resampler (content, true);
284 pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
290 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
291 dcp_mapped->make_silent ();
292 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
293 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
294 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
295 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
301 Time time = content->start()
302 + _film->audio_frames_to_time (frame)
303 + (content->audio_delay() * TIME_HZ / 1000);
305 /* We must cut off anything that comes before the start of all time */
307 int const frames = - time * _film->audio_frame_rate() / TIME_HZ;
308 if (frames >= audio->frames ()) {
312 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
313 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
319 /* The time of this audio may indicate that some of our buffered audio is not going to
320 be added to any more, so it can be emitted.
323 if (time > _audio_position) {
324 /* We can emit some audio from our buffers; this is how many frames */
325 OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
326 if (N > _audio_buffers.frames()) {
327 /* We need some extra silence before whatever is in the buffers */
328 _audio_buffers.ensure_size (N);
329 _audio_buffers.move (0, N - _audio_buffers.frames(), _audio_buffers.frames ());
330 _audio_buffers.make_silent (0, _audio_buffers.frames());
331 _audio_buffers.set_frames (N);
333 assert (N <= _audio_buffers.frames());
335 /* XXX: not convinced that a copy is necessary here */
336 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
337 emit->copy_from (&_audio_buffers, N, 0, 0);
338 Audio (emit, _audio_position);
340 _audio_position = piece->audio_position = _audio_position + _film->audio_frames_to_time (N);
342 /* And remove it from our buffers */
343 if (_audio_buffers.frames() > N) {
344 _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
346 _audio_buffers.set_frames (_audio_buffers.frames() - N);
349 /* Now accumulate the new audio into our buffers */
350 _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
351 _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
352 _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
358 if (_audio_buffers.frames() > 0) {
359 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
360 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
361 Audio (emit, _audio_position);
362 _audio_position += _film->audio_frames_to_time (_audio_buffers.frames ());
363 _audio_buffers.set_frames (0);
366 while (_video_position < _audio_position) {
370 while (_audio_position < _video_position) {
371 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
376 /** Seek so that the next pass() will yield (approximately) the requested frame.
377 * Pass accurate = true to try harder to get close to the request.
378 * @return true on error
381 Player::seek (Time t, bool accurate)
383 if (!_have_valid_pieces) {
385 _have_valid_pieces = true;
388 if (_pieces.empty ()) {
392 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
393 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
398 Time s = t - vc->start ();
399 s = max (static_cast<Time> (0), s);
400 s = min (vc->length(), s);
402 (*i)->video_position = (*i)->audio_position = vc->start() + s;
404 FrameRateConversion frc (vc->video_frame_rate(), _film->video_frame_rate());
405 /* Here we are converting from time (in the DCP) to a frame number in the content.
406 Hence we need to use the DCP's frame rate and the double/skip correction, not
409 VideoContent::Frame f = s * _film->video_frame_rate() / (frc.factor() * TIME_HZ);
410 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
413 _video_position = _audio_position = t;
415 /* XXX: don't seek audio because we don't need to... */
419 Player::setup_pieces ()
421 list<shared_ptr<Piece> > old_pieces = _pieces;
425 ContentList content = _playlist->content ();
426 sort (content.begin(), content.end(), ContentSorter ());
428 for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
430 shared_ptr<Piece> piece (new Piece (*i));
432 /* XXX: into content? */
434 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
436 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
438 fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
439 fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
440 fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
445 shared_ptr<const StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
447 shared_ptr<StillImageDecoder> id;
449 /* See if we can re-use an old StillImageDecoder */
450 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
451 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
452 if (imd && imd->content() == ic) {
458 id.reset (new StillImageDecoder (_film, ic));
459 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
465 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
467 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
468 sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
473 _pieces.push_back (piece);
477 cout << "=== Player setup:\n";
478 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
479 cout << *(i->get()) << "\n";
485 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
487 shared_ptr<Content> c = w.lock ();
493 property == ContentProperty::START || property == ContentProperty::LENGTH ||
494 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO
497 _have_valid_pieces = false;
500 } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
503 } else if (property == VideoContentProperty::VIDEO_FRAME_TYPE) {
509 Player::playlist_changed ()
511 _have_valid_pieces = false;
516 Player::set_video_container_size (libdcp::Size s)
518 _video_container_size = s;
519 _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
520 _black_frame->make_black ();
523 shared_ptr<Resampler>
524 Player::resampler (shared_ptr<AudioContent> c, bool create)
526 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
527 if (i != _resamplers.end ()) {
532 return shared_ptr<Resampler> ();
535 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
541 Player::emit_black ()
543 #ifdef DCPOMATIC_DEBUG
544 _last_video.reset ();
547 /* XXX: use same here */
548 Video (_black_frame, EYES_BOTH, false, _video_position);
549 _video_position += _film->video_frames_to_time (1);
553 Player::emit_silence (OutputAudioFrame most)
555 OutputAudioFrame N = min (most, _film->audio_frame_rate() / 2);
556 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->audio_channels(), N));
557 silence->make_silent ();
558 Audio (silence, _audio_position);
559 _audio_position += _film->audio_frames_to_time (N);
563 Player::film_changed (Film::Property p)
565 /* Here we should notice Film properties that affect our output, and
566 alert listeners that our output now would be different to how it was
567 last time we were run.
570 if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
576 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
578 _in_subtitle.piece = weak_piece;
579 _in_subtitle.image = image;
580 _in_subtitle.rect = rect;
581 _in_subtitle.from = from;
582 _in_subtitle.to = to;
588 Player::update_subtitle ()
590 shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
595 if (!_in_subtitle.image) {
596 _out_subtitle.image.reset ();
600 shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
603 dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
604 libdcp::Size scaled_size;
606 in_rect.y += sc->subtitle_offset ();
608 /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
609 scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
610 scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
612 /* Then we need a corrective translation, consisting of two parts:
614 * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be
615 * rect.x * _video_container_size.width and rect.y * _video_container_size.height.
617 * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
618 * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
619 * (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
621 * Combining these two translations gives these expressions.
624 _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
625 _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
627 _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true);
628 _out_subtitle.from = _in_subtitle.from + piece->content->start ();
629 _out_subtitle.to = _in_subtitle.to + piece->content->start ();