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::process_video (shared_ptr<const Image> i, bool same, shared_ptr<Subtitle> s, double t)
127 Video (i, same, s, _video_start[_video_decoder] + t);
131 Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<const AudioBuffers> b, double t)
133 AudioMapping mapping = _film->audio_mapping ();
134 if (!_audio_buffers) {
135 _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ()));
136 _audio_buffers->make_silent ();
138 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
139 _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder];
143 for (int i = 0; i < b->channels(); ++i) {
144 list<libdcp::Channel> dcp = mapping.content_to_dcp (AudioMapping::Channel (c, i));
145 for (list<libdcp::Channel>::iterator j = dcp.begin(); j != dcp.end(); ++j) {
146 _audio_buffers->accumulate (b, i, static_cast<int> (*j));
150 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
151 /* We can just emit this audio now as it will all be here */
152 Audio (_audio_buffers, t);
153 _audio_buffers.reset ();
154 _audio_time = boost::none;
158 /** @return true on error */
160 Player::seek (double t)
162 if (!_have_valid_decoders) {
164 _have_valid_decoders = true;
167 if (_video_decoders.empty ()) {
171 /* Find the decoder that contains this position */
175 if (_video_decoder >= _video_decoders.size () || t < _video_start[_video_decoder]) {
177 t -= _video_start[_video_decoder];
182 if (_video_decoder < _video_decoders.size()) {
183 _video_decoders[_video_decoder]->seek (t);
188 /* XXX: don't seek audio because we don't need to... */
201 Player::seek_forward ()
208 Player::setup_decoders ()
210 vector<shared_ptr<VideoDecoder> > old_video_decoders = _video_decoders;
212 _video_decoders.clear ();
214 _audio_decoders.clear ();
215 _sequential_audio_decoder = 0;
217 _video_start.clear();
218 _audio_start.clear();
220 double video_so_far = 0;
221 double audio_so_far = 0;
223 for (int l = 0; l < _playlist->loop(); ++l) {
224 list<shared_ptr<const VideoContent> > vc = _playlist->video ();
225 for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
227 shared_ptr<const VideoContent> video_content;
228 shared_ptr<const AudioContent> audio_content;
229 shared_ptr<VideoDecoder> video_decoder;
230 shared_ptr<AudioDecoder> audio_decoder;
232 /* XXX: into content? */
234 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
236 shared_ptr<FFmpegDecoder> fd (
239 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
249 video_decoder->connect_video (shared_from_this ());
252 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
256 /* See if we can re-use an old ImageMagickDecoder */
257 for (vector<shared_ptr<VideoDecoder> >::const_iterator i = old_video_decoders.begin(); i != old_video_decoders.end(); ++i) {
258 shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> (*i);
259 if (imd && imd->content() == ic) {
264 if (!video_decoder) {
265 video_decoder.reset (new ImageMagickDecoder (_film, ic));
266 video_decoder->connect_video (shared_from_this ());
270 _video_decoders.push_back (video_decoder);
271 _video_start.push_back (video_so_far);
272 video_so_far += video_content->video_length() / video_content->video_frame_rate();
274 if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
275 audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
276 _audio_decoders.push_back (audio_decoder);
277 _audio_start.push_back (audio_so_far);
278 audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
283 _sequential_audio_decoder = 0;
285 if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
287 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
288 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
290 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
293 shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
294 d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
295 _audio_decoders.push_back (d);
296 _audio_start.push_back (audio_so_far);
303 Player::last_video_time () const
305 if (_video_decoder >= _video_decoders.size ()) {
309 return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
313 Player::content_changed (weak_ptr<Content> w, int p)
315 shared_ptr<Content> c = w.lock ();
320 if (p == VideoContentProperty::VIDEO_LENGTH) {
321 _have_valid_decoders = false;
326 Player::playlist_changed ()
328 _have_valid_decoders = false;