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.
22 #include "ffmpeg_decoder.h"
23 #include "ffmpeg_content.h"
24 #include "imagemagick_decoder.h"
25 #include "imagemagick_content.h"
26 #include "sndfile_decoder.h"
27 #include "sndfile_content.h"
34 using boost::shared_ptr;
35 using boost::weak_ptr;
36 using boost::dynamic_pointer_cast;
38 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
44 , _have_valid_decoders (false)
46 _playlist->Changed.connect (bind (&Player::playlist_changed, this));
47 _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
51 Player::disable_video ()
57 Player::disable_audio ()
63 Player::disable_subtitles ()
71 if (!_have_valid_decoders) {
73 _have_valid_decoders = true;
78 if (_video_decoder < _video_decoders.size ()) {
80 /* Run video decoder; this may also produce audio */
82 if (_video_decoders[_video_decoder]->pass ()) {
86 if (_video_decoder < _video_decoders.size ()) {
90 } else if (!_video && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) {
92 /* We're not producing video, so we may need to run FFmpeg content to get the audio */
94 if (_audio_decoders[_sequential_audio_decoder]->pass ()) {
95 _sequential_audio_decoder++;
98 if (_sequential_audio_decoder < _audio_decoders.size ()) {
102 } else if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
104 /* We're getting audio from SndfileContent */
106 for (vector<shared_ptr<AudioDecoder> >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) {
107 if (!(*i)->pass ()) {
112 Audio (_audio_buffers, _audio_time.get());
113 _audio_buffers.reset ();
114 _audio_time = boost::none;
121 Player::set_progress (shared_ptr<Job> job)
123 /* Assume progress can be divined from how far through the video we are */
125 if (_video_decoder >= _video_decoders.size() || !_playlist->video_length()) {
129 job->set_progress ((_video_start[_video_decoder] + _video_decoders[_video_decoder]->video_frame()) / _playlist->video_length ());
133 Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s, double t)
135 Video (i, same, s, _video_start[_video_decoder] + t);
139 Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<AudioBuffers> b, double t)
141 AudioMapping mapping = _film->audio_mapping ();
142 if (!_audio_buffers) {
143 _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ()));
144 _audio_buffers->make_silent ();
146 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
147 _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder];
151 for (int i = 0; i < b->channels(); ++i) {
152 list<libdcp::Channel> dcp = mapping.content_to_dcp (AudioMapping::Channel (c, i));
153 for (list<libdcp::Channel>::iterator j = dcp.begin(); j != dcp.end(); ++j) {
154 _audio_buffers->accumulate (b, i, static_cast<int> (*j));
158 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
159 /* We can just emit this audio now as it will all be here */
160 Audio (_audio_buffers, t);
161 _audio_buffers.reset ();
162 _audio_time = boost::none;
166 /** @return true on error */
168 Player::seek (double t)
170 if (!_have_valid_decoders) {
172 _have_valid_decoders = true;
175 /* Find the decoder that contains this position */
177 while (_video_decoder < _video_decoders.size ()) {
178 if (t < _video_start[_video_decoder]) {
179 assert (_video_decoder);
184 t -= _video_start[_video_decoder];
188 if (_video_decoder < _video_decoders.size()) {
189 _video_decoders[_video_decoder]->seek (t);
194 /* XXX: don't seek audio because we don't need to... */
207 Player::seek_forward ()
214 Player::setup_decoders ()
216 _video_decoders.clear ();
218 _audio_decoders.clear ();
219 _sequential_audio_decoder = 0;
221 _video_start.clear();
222 _audio_start.clear();
224 double video_so_far = 0;
225 double audio_so_far = 0;
228 list<shared_ptr<const VideoContent> > vc = _playlist->video ();
229 for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
231 shared_ptr<const VideoContent> c;
232 shared_ptr<VideoDecoder> d;
234 /* XXX: into content? */
236 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
238 shared_ptr<FFmpegDecoder> fd (
241 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
246 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
247 fd->Audio.connect (bind (&Player::process_audio, this, fc, _1, _2));
254 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
257 d.reset (new ImageMagickDecoder (_film, ic));
260 d->connect_video (shared_from_this ());
261 _video_decoders.push_back (d);
262 _video_start.push_back (video_so_far);
263 video_so_far += c->video_length() / c->video_frame_rate();
269 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG && !_video) {
271 /* If we're getting audio from FFmpegContent but not the video, we need a set
272 of decoders for the audio.
275 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
276 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
278 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
281 shared_ptr<AudioDecoder> d (
284 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
289 d->Audio.connect (bind (&Player::process_audio, this, fc, _1, _2));
290 _audio_decoders.push_back (d);
291 _audio_start.push_back (audio_so_far);
292 audio_so_far += fc->audio_length() / fc->audio_frame_rate();
295 _sequential_audio_decoder = 0;
298 if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
300 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
301 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
303 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
306 shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
307 d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
308 _audio_decoders.push_back (d);
309 _audio_start.push_back (audio_so_far);
310 audio_so_far += sc->audio_length () / sc->audio_frame_rate();
316 Player::last_video_time () const
318 return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
322 Player::content_changed (weak_ptr<Content> w, int p)
324 shared_ptr<Content> c = w.lock ();
329 if (p == VideoContentProperty::VIDEO_LENGTH) {
330 if (dynamic_pointer_cast<FFmpegContent> (c)) {
331 /* FFmpeg content length changes are serious; we need new decoders */
332 _have_valid_decoders = false;
338 Player::playlist_changed ()
340 _have_valid_decoders = false;