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 "imagemagick_decoder.h"
26 #include "imagemagick_content.h"
27 #include "sndfile_decoder.h"
28 #include "sndfile_content.h"
32 #include "null_content.h"
33 #include "black_decoder.h"
34 #include "silence_decoder.h"
36 #include "resampler.h"
45 using boost::shared_ptr;
46 using boost::weak_ptr;
47 using boost::dynamic_pointer_cast;
49 #define DEBUG_PLAYER 1
53 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
59 shared_ptr<Content> content;
60 shared_ptr<Decoder> decoder;
66 std::ostream& operator<<(std::ostream& s, Piece const & p)
68 if (dynamic_pointer_cast<NullContent> (p.content)) {
69 if (dynamic_pointer_cast<SilenceDecoder> (p.decoder)) {
74 } else if (dynamic_pointer_cast<FFmpegContent> (p.content)) {
76 } else if (dynamic_pointer_cast<ImageMagickContent> (p.content)) {
78 } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
82 s << " at " << p.content->start() << " until " << p.content->end();
88 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
93 , _have_valid_pieces (false)
95 , _audio_buffers (f->dcp_audio_channels(), 0)
98 _playlist->Changed.connect (bind (&Player::playlist_changed, this));
99 _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
103 Player::disable_video ()
109 Player::disable_audio ()
117 if (!_have_valid_pieces) {
119 _have_valid_pieces = true;
122 /* Here we are just finding the active decoder with the earliest last emission time, then
126 Time earliest_t = TIME_MAX;
127 shared_ptr<Piece> earliest;
129 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
130 if ((*i)->decoder->done ()) {
134 if ((*i)->last_emission < earliest_t) {
135 earliest_t = (*i)->last_emission;
145 earliest->decoder->pass ();
146 _position = earliest->last_emission;
152 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, bool same, VideoContent::Frame frame)
154 shared_ptr<Piece> piece = weak_piece.lock ();
159 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
162 FrameRateConversion frc (content->video_frame_rate(), _film->dcp_video_frame_rate());
163 if (frc.skip && (frame % 2) == 1) {
167 image = image->crop (content->crop(), true);
169 libdcp::Size const container_size = _video_container_size.get_value_or (_film->container()->size (_film->full_frame ()));
170 libdcp::Size const image_size = content->ratio()->size (container_size);
172 image = image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
175 if (film->with_subtitles ()) {
176 shared_ptr<Subtitle> sub;
177 if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
178 sub = _timed_subtitle->subtitle ();
182 dcpomatic::Rect const tx = subtitle_transformed_area (
183 float (image_size.width) / content->video_size().width,
184 float (image_size.height) / content->video_size().height,
185 sub->area(), film->subtitle_offset(), film->subtitle_scale()
188 shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true);
189 image->alpha_blend (im, tx.position());
194 if (image_size != container_size) {
195 assert (image_size.width <= container_size.width);
196 assert (image_size.height <= container_size.height);
197 shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, container_size, true));
199 im->copy (image, Position ((container_size.width - image_size.width) / 2, (container_size.height - image_size.height) / 2));
203 Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
205 Video (image, same, time);
208 time += TIME_HZ / _film->dcp_video_frame_rate();
209 Video (image, true, time);
212 piece->last_emission = min (piece->last_emission, time);
216 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
218 shared_ptr<Piece> piece = weak_piece.lock ();
223 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
226 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
227 audio = resampler(content)->run (audio);
231 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->dcp_audio_channels(), audio->frames()));
232 dcp_mapped->make_silent ();
233 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
234 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
235 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
238 /* The time of this audio may indicate that some of our buffered audio is not going to
239 be added to any more, so it can be emitted.
242 Time const time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate());
243 piece->last_emission = min (piece->last_emission, time);
245 cout << "Player gets " << dcp_mapped->frames() << " @ " << time << " cf " << _next_audio << "\n";
247 if (time > _next_audio) {
248 /* We can emit some audio from our buffers */
249 OutputAudioFrame const N = _film->time_to_audio_frames (time - _next_audio);
250 assert (N <= _audio_buffers.frames());
251 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
252 emit->copy_from (&_audio_buffers, N, 0, 0);
253 Audio (emit, _next_audio);
254 _next_audio += _film->audio_frames_to_time (N);
256 /* And remove it from our buffers */
257 if (_audio_buffers.frames() > N) {
258 _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
260 _audio_buffers.set_frames (_audio_buffers.frames() - N);
263 /* Now accumulate the new audio into our buffers */
264 _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
265 _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
266 _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
272 if (_audio_buffers.frames() > 0) {
273 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
274 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
275 Audio (emit, _next_audio);
276 _next_audio += _film->audio_frames_to_time (_audio_buffers.frames ());
277 _audio_buffers.set_frames (0);
281 /** @return true on error */
283 Player::seek (Time t)
285 if (!_have_valid_pieces) {
287 _have_valid_pieces = true;
290 if (_pieces.empty ()) {
294 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
295 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
300 Time s = t - vc->start ();
301 s = max (static_cast<Time> (0), s);
302 s = min (vc->length(), s);
304 FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
305 VideoContent::Frame f = s * _film->dcp_video_frame_rate() / (frc.factor() * TIME_HZ);
306 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f);
309 /* XXX: don't seek audio because we don't need to... */
320 Player::add_black_piece (Time s, Time len)
322 shared_ptr<NullContent> nc (new NullContent (_film, s, len));
323 nc->set_ratio (_film->container ());
324 shared_ptr<BlackDecoder> bd (new BlackDecoder (_film, nc));
325 shared_ptr<Piece> p (new Piece (nc, bd));
326 _pieces.push_back (p);
327 bd->Video.connect (bind (&Player::process_video, this, p, _1, _2, _3));
331 Player::add_silent_piece (Time s, Time len)
333 shared_ptr<NullContent> nc (new NullContent (_film, s, len));
334 shared_ptr<SilenceDecoder> sd (new SilenceDecoder (_film, nc));
335 shared_ptr<Piece> p (new Piece (nc, sd));
336 _pieces.push_back (p);
337 sd->Audio.connect (bind (&Player::process_audio, this, p, _1, _2));
342 Player::setup_pieces ()
344 list<shared_ptr<Piece> > old_pieces = _pieces;
348 Playlist::ContentList content = _playlist->content ();
349 sort (content.begin(), content.end(), ContentSorter ());
351 for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
353 shared_ptr<Decoder> decoder;
355 /* XXX: into content? */
357 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
359 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
361 fd->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3));
362 fd->Audio.connect (bind (&Player::process_audio, this, *i, _1, _2));
367 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
369 shared_ptr<ImageMagickDecoder> id;
371 /* See if we can re-use an old ImageMagickDecoder */
372 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
373 shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> ((*j)->decoder);
374 if (imd && imd->content() == ic) {
380 id.reset (new ImageMagickDecoder (_film, ic));
381 id->Video.connect (bind (&Player::process_video, this, *i, _1, _2, _3));
387 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
389 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
390 sd->Audio.connect (bind (&Player::process_audio, this, *i, _1, _2));
395 _pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder)));
398 /* Fill in visual gaps with black and audio gaps with silence */
402 list<shared_ptr<Piece> > pieces_copy = _pieces;
403 for (list<shared_ptr<Piece> >::iterator i = pieces_copy.begin(); i != pieces_copy.end(); ++i) {
404 if (dynamic_pointer_cast<VideoContent> ((*i)->content)) {
405 Time const diff = (*i)->content->start() - video_pos;
407 add_black_piece (video_pos, diff);
409 video_pos = (*i)->content->end();
412 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> ((*i)->content);
413 if (ac && ac->audio_channels()) {
414 Time const diff = (*i)->content->start() - audio_pos;
416 add_silent_piece (video_pos, diff);
418 audio_pos = (*i)->content->end();
422 if (video_pos < audio_pos) {
423 add_black_piece (video_pos, audio_pos - video_pos);
424 } else if (audio_pos < video_pos) {
425 add_silent_piece (audio_pos, video_pos - audio_pos);
429 cout << "=== Player setup:\n";
430 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
431 cout << *(i->get()) << "\n";
437 Player::content_changed (weak_ptr<Content> w, int p)
439 shared_ptr<Content> c = w.lock ();
444 if (p == ContentProperty::START || p == ContentProperty::LENGTH) {
445 _have_valid_pieces = false;
450 Player::playlist_changed ()
452 _have_valid_pieces = false;
456 Player::set_video_container_size (libdcp::Size s)
458 _video_container_size = s;
461 shared_ptr<Resampler>
462 Player::resampler (shared_ptr<AudioContent> c)
464 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
465 if (i != _resamplers.end ()) {
469 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));