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)
58 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
64 shared_ptr<Content> content;
65 shared_ptr<Decoder> decoder;
71 std::ostream& operator<<(std::ostream& s, Piece const & p)
73 if (dynamic_pointer_cast<NullContent> (p.content)) {
74 if (dynamic_pointer_cast<SilenceDecoder> (p.decoder)) {
79 } else if (dynamic_pointer_cast<FFmpegContent> (p.content)) {
81 } else if (dynamic_pointer_cast<ImageMagickContent> (p.content)) {
83 } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
87 s << " at " << p.content->start() << " until " << p.content->end();
93 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
98 , _have_valid_pieces (false)
100 , _audio_buffers (f->dcp_audio_channels(), 0)
103 _playlist->Changed.connect (bind (&Player::playlist_changed, this));
104 _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
108 Player::disable_video ()
114 Player::disable_audio ()
122 if (!_have_valid_pieces) {
124 _have_valid_pieces = true;
127 /* Here we are just finding the active decoder with the earliest last emission time, then
131 Time earliest_t = TIME_MAX;
132 shared_ptr<Piece> earliest;
134 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
135 if ((*i)->decoder->done ()) {
139 if ((*i)->last_emission < earliest_t) {
140 earliest_t = (*i)->last_emission;
150 earliest->decoder->pass ();
151 _position = earliest->last_emission;
157 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, bool same, VideoContent::Frame frame)
159 shared_ptr<Piece> piece = weak_piece.lock ();
164 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
167 FrameRateConversion frc (content->video_frame_rate(), _film->dcp_video_frame_rate());
168 if (frc.skip && (frame % 2) == 1) {
172 image = image->crop (content->crop(), true);
174 libdcp::Size const container_size = _video_container_size.get_value_or (_film->container()->size (_film->full_frame ()));
175 libdcp::Size const image_size = content->ratio()->size (container_size);
177 image = image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
180 if (film->with_subtitles ()) {
181 shared_ptr<Subtitle> sub;
182 if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
183 sub = _timed_subtitle->subtitle ();
187 dcpomatic::Rect const tx = subtitle_transformed_area (
188 float (image_size.width) / content->video_size().width,
189 float (image_size.height) / content->video_size().height,
190 sub->area(), film->subtitle_offset(), film->subtitle_scale()
193 shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true);
194 image->alpha_blend (im, tx.position());
199 if (image_size != container_size) {
200 assert (image_size.width <= container_size.width);
201 assert (image_size.height <= container_size.height);
202 shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, container_size, true));
204 im->copy (image, Position ((container_size.width - image_size.width) / 2, (container_size.height - image_size.height) / 2));
208 Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
210 Video (image, same, time);
213 time += TIME_HZ / _film->dcp_video_frame_rate();
214 Video (image, true, time);
217 piece->last_emission = min (piece->last_emission, time);
221 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
223 shared_ptr<Piece> piece = weak_piece.lock ();
228 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
231 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
232 audio = resampler(content)->run (audio);
236 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->dcp_audio_channels(), audio->frames()));
237 dcp_mapped->make_silent ();
238 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
239 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
240 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
243 /* The time of this audio may indicate that some of our buffered audio is not going to
244 be added to any more, so it can be emitted.
247 Time const time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate());
248 piece->last_emission = min (piece->last_emission, time);
250 cout << "Player gets " << dcp_mapped->frames() << " @ " << time << " cf " << _next_audio << "\n";
252 if (time > _next_audio) {
253 /* We can emit some audio from our buffers */
254 OutputAudioFrame const N = _film->time_to_audio_frames (time - _next_audio);
255 assert (N <= _audio_buffers.frames());
256 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
257 emit->copy_from (&_audio_buffers, N, 0, 0);
258 Audio (emit, _next_audio);
259 _next_audio += _film->audio_frames_to_time (N);
261 /* And remove it from our buffers */
262 if (_audio_buffers.frames() > N) {
263 _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
265 _audio_buffers.set_frames (_audio_buffers.frames() - N);
268 /* Now accumulate the new audio into our buffers */
269 _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
270 _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
271 _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
277 if (_audio_buffers.frames() > 0) {
278 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
279 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
280 Audio (emit, _next_audio);
281 _next_audio += _film->audio_frames_to_time (_audio_buffers.frames ());
282 _audio_buffers.set_frames (0);
286 /** @return true on error */
288 Player::seek (Time t)
290 if (!_have_valid_pieces) {
292 _have_valid_pieces = true;
295 if (_pieces.empty ()) {
299 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
300 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
305 Time s = t - vc->start ();
306 s = max (static_cast<Time> (0), s);
307 s = min (vc->length(), s);
309 FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
310 VideoContent::Frame f = s * _film->dcp_video_frame_rate() / (frc.factor() * TIME_HZ);
311 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f);
314 /* XXX: don't seek audio because we don't need to... */
325 Player::add_black_piece (Time s, Time len)
327 shared_ptr<NullContent> nc (new NullContent (_film, s, len));
328 nc->set_ratio (_film->container ());
329 shared_ptr<BlackDecoder> bd (new BlackDecoder (_film, nc));
330 shared_ptr<Piece> p (new Piece (nc, bd));
331 _pieces.push_back (p);
332 bd->Video.connect (bind (&Player::process_video, this, p, _1, _2, _3));
336 Player::add_silent_piece (Time s, Time len)
338 shared_ptr<NullContent> nc (new NullContent (_film, s, len));
339 shared_ptr<SilenceDecoder> sd (new SilenceDecoder (_film, nc));
340 shared_ptr<Piece> p (new Piece (nc, sd));
341 _pieces.push_back (p);
342 sd->Audio.connect (bind (&Player::process_audio, this, p, _1, _2));
347 Player::setup_pieces ()
349 list<shared_ptr<Piece> > old_pieces = _pieces;
353 Playlist::ContentList content = _playlist->content ();
354 sort (content.begin(), content.end(), ContentSorter ());
356 for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
358 shared_ptr<Piece> piece (new Piece (*i));
360 /* XXX: into content? */
362 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
364 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
366 fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
367 fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
372 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
374 shared_ptr<ImageMagickDecoder> id;
376 /* See if we can re-use an old ImageMagickDecoder */
377 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
378 shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> ((*j)->decoder);
379 if (imd && imd->content() == ic) {
385 id.reset (new ImageMagickDecoder (_film, ic));
386 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
392 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
394 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
395 sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
400 _pieces.push_back (piece);
403 /* Fill in visual gaps with black and audio gaps with silence */
407 list<shared_ptr<Piece> > pieces_copy = _pieces;
408 for (list<shared_ptr<Piece> >::iterator i = pieces_copy.begin(); i != pieces_copy.end(); ++i) {
409 if (dynamic_pointer_cast<VideoContent> ((*i)->content)) {
410 Time const diff = (*i)->content->start() - video_pos;
412 add_black_piece (video_pos, diff);
414 video_pos = (*i)->content->end();
417 shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> ((*i)->content);
418 if (ac && ac->audio_channels()) {
419 Time const diff = (*i)->content->start() - audio_pos;
421 add_silent_piece (video_pos, diff);
423 audio_pos = (*i)->content->end();
427 if (video_pos < audio_pos) {
428 add_black_piece (video_pos, audio_pos - video_pos);
429 } else if (audio_pos < video_pos) {
430 add_silent_piece (audio_pos, video_pos - audio_pos);
434 cout << "=== Player setup:\n";
435 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
436 cout << *(i->get()) << "\n";
442 Player::content_changed (weak_ptr<Content> w, int p)
444 shared_ptr<Content> c = w.lock ();
449 if (p == ContentProperty::START || p == ContentProperty::LENGTH) {
450 _have_valid_pieces = false;
455 Player::playlist_changed ()
457 _have_valid_pieces = false;
461 Player::set_video_container_size (libdcp::Size s)
463 _video_container_size = s;
466 shared_ptr<Resampler>
467 Player::resampler (shared_ptr<AudioContent> c)
469 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
470 if (i != _resamplers.end ()) {
474 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));