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"
33 #include "resampler.h"
42 using boost::shared_ptr;
43 using boost::weak_ptr;
44 using boost::dynamic_pointer_cast;
46 #define DEBUG_PLAYER 1
51 Piece (shared_ptr<Content> c)
53 , video_position (c->start ())
54 , audio_position (c->start ())
57 Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
60 , video_position (c->start ())
61 , audio_position (c->start ())
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<FFmpegContent> (p.content)) {
75 } else if (dynamic_pointer_cast<ImageMagickContent> (p.content)) {
77 } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
81 s << " at " << p.content->start() << " until " << p.content->end();
87 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
92 , _have_valid_pieces (false)
95 , _audio_buffers (f->dcp_audio_channels(), 0)
97 _playlist->Changed.connect (bind (&Player::playlist_changed, this));
98 _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
99 set_video_container_size (_film->container()->size (_film->full_frame ()));
103 Player::disable_video ()
109 Player::disable_audio ()
117 if (!_have_valid_pieces) {
119 _have_valid_pieces = true;
126 Time earliest_t = TIME_MAX;
127 shared_ptr<Piece> earliest;
133 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
134 if ((*i)->decoder->done ()) {
138 if (dynamic_pointer_cast<VideoDecoder> ((*i)->decoder)) {
139 if ((*i)->video_position < earliest_t) {
140 earliest_t = (*i)->video_position;
146 if (dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
147 if ((*i)->audio_position < earliest_t) {
148 earliest_t = (*i)->audio_position;
157 cout << "no earliest piece.\n";
166 if (earliest_t > _video_position) {
168 cout << "no video here; emitting black frame.\n";
173 cout << "Pass " << *earliest << "\n";
175 earliest->decoder->pass ();
180 if (earliest_t > _audio_position) {
182 cout << "no audio here; emitting silence.\n";
184 emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
187 cout << "Pass " << *earliest << "\n";
189 earliest->decoder->pass ();
195 cout << "\tpost pass " << _video_position << " " << _audio_position << "\n";
202 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, bool same, VideoContent::Frame frame)
204 shared_ptr<Piece> piece = weak_piece.lock ();
209 shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
212 FrameRateConversion frc (content->video_frame_rate(), _film->dcp_video_frame_rate());
213 if (frc.skip && (frame % 2) == 1) {
217 image = image->crop (content->crop(), true);
219 libdcp::Size const image_size = content->ratio()->size (_video_container_size);
221 image = image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
224 if (film->with_subtitles ()) {
225 shared_ptr<Subtitle> sub;
226 if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
227 sub = _timed_subtitle->subtitle ();
231 dcpomatic::Rect const tx = subtitle_transformed_area (
232 float (image_size.width) / content->video_size().width,
233 float (image_size.height) / content->video_size().height,
234 sub->area(), film->subtitle_offset(), film->subtitle_scale()
237 shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true);
238 image->alpha_blend (im, tx.position());
243 if (image_size != _video_container_size) {
244 assert (image_size.width <= _video_container_size.width);
245 assert (image_size.height <= _video_container_size.height);
246 shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, _video_container_size, true));
248 im->copy (image, Position ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
252 Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
254 Video (image, same, time);
255 time += TIME_HZ / _film->dcp_video_frame_rate();
258 Video (image, true, time);
259 time += TIME_HZ / _film->dcp_video_frame_rate();
262 _video_position = piece->video_position = time;
266 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
268 shared_ptr<Piece> piece = weak_piece.lock ();
273 shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
276 if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
277 audio = resampler(content)->run (audio);
281 shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->dcp_audio_channels(), audio->frames()));
282 dcp_mapped->make_silent ();
283 list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
284 for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
285 dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
288 /* The time of this audio may indicate that some of our buffered audio is not going to
289 be added to any more, so it can be emitted.
292 Time const time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate());
294 if (time > _audio_position) {
295 /* We can emit some audio from our buffers */
296 OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
297 assert (N <= _audio_buffers.frames());
298 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
299 emit->copy_from (&_audio_buffers, N, 0, 0);
300 Audio (emit, _audio_position);
301 _audio_position = piece->audio_position = time + _film->audio_frames_to_time (N);
303 /* And remove it from our buffers */
304 if (_audio_buffers.frames() > N) {
305 _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
307 _audio_buffers.set_frames (_audio_buffers.frames() - N);
310 /* Now accumulate the new audio into our buffers */
311 _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
312 _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
313 _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
319 if (_audio_buffers.frames() > 0) {
320 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
321 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
322 Audio (emit, _audio_position);
323 _audio_position += _film->audio_frames_to_time (_audio_buffers.frames ());
324 _audio_buffers.set_frames (0);
327 while (_video_position < _audio_position) {
331 while (_audio_position < _video_position) {
332 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
337 /** @return true on error */
339 Player::seek (Time t)
341 if (!_have_valid_pieces) {
343 _have_valid_pieces = true;
346 if (_pieces.empty ()) {
350 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
351 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
356 Time s = t - vc->start ();
357 s = max (static_cast<Time> (0), s);
358 s = min (vc->length(), s);
360 FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
361 VideoContent::Frame f = s * _film->dcp_video_frame_rate() / (frc.factor() * TIME_HZ);
362 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f);
365 /* XXX: don't seek audio because we don't need to... */
376 Player::setup_pieces ()
378 list<shared_ptr<Piece> > old_pieces = _pieces;
382 Playlist::ContentList content = _playlist->content ();
383 sort (content.begin(), content.end(), ContentSorter ());
385 for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
387 shared_ptr<Piece> piece (new Piece (*i));
389 /* XXX: into content? */
391 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
393 shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
395 fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
396 fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
401 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
403 shared_ptr<ImageMagickDecoder> id;
405 /* See if we can re-use an old ImageMagickDecoder */
406 for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
407 shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> ((*j)->decoder);
408 if (imd && imd->content() == ic) {
414 id.reset (new ImageMagickDecoder (_film, ic));
415 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
421 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
423 shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
424 sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
429 _pieces.push_back (piece);
433 cout << "=== Player setup:\n";
434 for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
435 cout << *(i->get()) << "\n";
441 Player::content_changed (weak_ptr<Content> w, int p)
443 shared_ptr<Content> c = w.lock ();
448 if (p == ContentProperty::START || p == ContentProperty::LENGTH) {
449 _have_valid_pieces = false;
454 Player::playlist_changed ()
456 _have_valid_pieces = false;
460 Player::set_video_container_size (libdcp::Size s)
462 _video_container_size = s;
463 _black_frame.reset (new SimpleImage (PIX_FMT_RGB24, _video_container_size, true));
464 _black_frame->make_black ();
467 shared_ptr<Resampler>
468 Player::resampler (shared_ptr<AudioContent> c)
470 map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
471 if (i != _resamplers.end ()) {
475 shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
481 Player::emit_black ()
483 /* XXX: use same here */
484 Video (_black_frame, false, _video_position);
485 _video_position += _film->video_frames_to_time (1);
489 Player::emit_silence (OutputAudioFrame most)
491 OutputAudioFrame N = min (most, _film->dcp_audio_frame_rate() / 2);
492 shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->dcp_audio_channels(), N));
493 silence->make_silent ();
494 Audio (silence, _audio_position);
495 _audio_position += _film->audio_frames_to_time (N);