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;
227 list<shared_ptr<const VideoContent> > vc = _playlist->video ();
228 for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
230 shared_ptr<const VideoContent> video_content;
231 shared_ptr<const AudioContent> audio_content;
232 shared_ptr<VideoDecoder> video_decoder;
233 shared_ptr<AudioDecoder> audio_decoder;
235 /* XXX: into content? */
237 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
239 shared_ptr<FFmpegDecoder> fd (
242 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
253 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
256 video_decoder.reset (new ImageMagickDecoder (_film, ic));
259 video_decoder->connect_video (shared_from_this ());
260 _video_decoders.push_back (video_decoder);
261 _video_start.push_back (video_so_far);
262 video_so_far += video_content->video_length() / video_content->video_frame_rate();
264 if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
265 audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
266 _audio_decoders.push_back (audio_decoder);
267 _audio_start.push_back (audio_so_far);
268 audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
273 _sequential_audio_decoder = 0;
275 if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
277 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
278 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
280 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
283 shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
284 d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
285 _audio_decoders.push_back (d);
286 _audio_start.push_back (audio_so_far);
292 Player::last_video_time () const
294 return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
298 Player::content_changed (weak_ptr<Content> w, int p)
300 shared_ptr<Content> c = w.lock ();
305 if (p == VideoContentProperty::VIDEO_LENGTH) {
306 if (dynamic_pointer_cast<FFmpegContent> (c)) {
307 /* FFmpeg content length changes are serious; we need new decoders */
308 _have_valid_decoders = false;
314 Player::playlist_changed ()
316 _have_valid_decoders = false;