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 && _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 ()) {
92 if (!_video && _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) {
94 /* We're not producing video, so we may need to run FFmpeg content to get the audio */
96 if (_audio_decoders[_sequential_audio_decoder]->pass ()) {
97 _sequential_audio_decoder++;
100 if (_sequential_audio_decoder < _audio_decoders.size ()) {
106 if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
108 /* We're getting audio from SndfileContent */
110 for (vector<shared_ptr<AudioDecoder> >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) {
111 if (!(*i)->pass ()) {
116 Audio (_audio_buffers, _audio_time.get());
117 _audio_buffers.reset ();
118 _audio_time = boost::none;
125 Player::set_progress (shared_ptr<Job> job)
127 /* Assume progress can be divined from how far through the video we are */
129 if (_video_decoder >= _video_decoders.size() || !_playlist->video_length()) {
133 job->set_progress ((_video_start[_video_decoder] + _video_decoders[_video_decoder]->video_frame()) / _playlist->video_length ());
137 Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s, double t)
139 Video (i, same, s, _video_start[_video_decoder] + t);
143 Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<AudioBuffers> b, double t)
145 AudioMapping mapping = _film->audio_mapping ();
146 if (!_audio_buffers) {
147 _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ()));
148 _audio_buffers->make_silent ();
150 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
151 _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder];
155 for (int i = 0; i < b->channels(); ++i) {
156 list<libdcp::Channel> dcp = mapping.content_to_dcp (AudioMapping::Channel (c, i));
157 for (list<libdcp::Channel>::iterator j = dcp.begin(); j != dcp.end(); ++j) {
158 _audio_buffers->accumulate (b, i, static_cast<int> (*j));
162 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
163 /* We can just emit this audio now as it will all be here */
164 Audio (_audio_buffers, t);
165 _audio_buffers.reset ();
166 _audio_time = boost::none;
170 /** @return true on error */
172 Player::seek (double t)
174 if (!_have_valid_decoders) {
176 _have_valid_decoders = true;
179 /* Find the decoder that contains this position */
183 if (_video_decoder >= _video_decoders.size () || t < _video_start[_video_decoder]) {
185 t -= _video_start[_video_decoder];
190 if (_video_decoder < _video_decoders.size()) {
191 _video_decoders[_video_decoder]->seek (t);
196 /* XXX: don't seek audio because we don't need to... */
209 Player::seek_forward ()
216 Player::setup_decoders ()
218 _video_decoders.clear ();
220 _audio_decoders.clear ();
221 _sequential_audio_decoder = 0;
223 _video_start.clear();
224 _audio_start.clear();
226 double video_so_far = 0;
227 double audio_so_far = 0;
229 list<shared_ptr<const VideoContent> > vc = _playlist->video ();
230 for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
232 shared_ptr<const VideoContent> video_content;
233 shared_ptr<const AudioContent> audio_content;
234 shared_ptr<VideoDecoder> video_decoder;
235 shared_ptr<AudioDecoder> audio_decoder;
237 /* XXX: into content? */
239 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
241 shared_ptr<FFmpegDecoder> fd (
244 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
255 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
258 video_decoder.reset (new ImageMagickDecoder (_film, ic));
261 video_decoder->connect_video (shared_from_this ());
262 _video_decoders.push_back (video_decoder);
263 _video_start.push_back (video_so_far);
264 video_so_far += video_content->video_length() / video_content->video_frame_rate();
266 if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
267 audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
268 _audio_decoders.push_back (audio_decoder);
269 _audio_start.push_back (audio_so_far);
270 audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
275 _sequential_audio_decoder = 0;
277 if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
279 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
280 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
282 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
285 shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
286 d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
287 _audio_decoders.push_back (d);
288 _audio_start.push_back (audio_so_far);
294 Player::last_video_time () const
296 return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
300 Player::content_changed (weak_ptr<Content> w, int p)
302 shared_ptr<Content> c = w.lock ();
307 if (p == VideoContentProperty::VIDEO_LENGTH) {
308 if (dynamic_pointer_cast<FFmpegContent> (c)) {
309 /* FFmpeg content length changes are serious; we need new decoders */
310 _have_valid_decoders = false;
316 Player::playlist_changed ()
318 _have_valid_decoders = false;