Merge master.
[dcpomatic.git] / src / lib / player.cc
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
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.
8
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.
13
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.
17
18 */
19
20 #include "player.h"
21 #include "film.h"
22 #include "ffmpeg_decoder.h"
23 #include "imagemagick_decoder.h"
24 #include "sndfile_decoder.h"
25 #include "sndfile_content.h"
26 #include "playlist.h"
27 #include "job.h"
28
29 using std::list;
30 using std::cout;
31 using boost::shared_ptr;
32 using boost::weak_ptr;
33 using boost::dynamic_pointer_cast;
34
35 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
36         : _film (f)
37         , _playlist (p)
38         , _video (true)
39         , _audio (true)
40         , _subtitles (true)
41         , _have_valid_decoders (false)
42         , _ffmpeg_decoder_done (false)
43         , _video_sync (true)
44 {
45         _playlist->Changed.connect (bind (&Player::playlist_changed, this));
46         _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
47 }
48
49 void
50 Player::disable_video ()
51 {
52         _video = false;
53 }
54
55 void
56 Player::disable_audio ()
57 {
58         _audio = false;
59 }
60
61 void
62 Player::disable_subtitles ()
63 {
64         _subtitles = false;
65 }
66
67 bool
68 Player::pass ()
69 {
70         if (!_have_valid_decoders) {
71                 setup_decoders ();
72                 _have_valid_decoders = true;
73         }
74         
75         bool done = true;
76         
77         if (_playlist->video_from() == Playlist::VIDEO_FFMPEG || _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
78                 if (!_ffmpeg_decoder_done) {
79                         if (_ffmpeg_decoder->pass ()) {
80                                 _ffmpeg_decoder_done = true;
81                         } else {
82                                 done = false;
83                         }
84                 }
85         }
86
87         if (_playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
88                 if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
89                         if ((*_imagemagick_decoder)->pass ()) {
90                                 _imagemagick_decoder++;
91                         }
92
93                         if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
94                                 done = false;
95                         }
96                 }
97         }
98
99         if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
100                 for (list<shared_ptr<SndfileDecoder> >::iterator i = _sndfile_decoders.begin(); i != _sndfile_decoders.end(); ++i) {
101                         if (!(*i)->pass ()) {
102                                 done = false;
103                         }
104                 }
105
106                 Audio (_sndfile_buffers);
107                 _sndfile_buffers.reset ();
108         }
109
110         return done;
111 }
112
113 void
114 Player::set_progress (shared_ptr<Job> job)
115 {
116         /* Assume progress can be divined from how far through the video we are */
117         switch (_playlist->video_from ()) {
118         case Playlist::VIDEO_NONE:
119                 break;
120         case Playlist::VIDEO_FFMPEG:
121                 if (_playlist->video_length ()) {
122                         job->set_progress (float(_ffmpeg_decoder->video_frame()) / _playlist->video_length ());
123                 }
124                 break;
125         case Playlist::VIDEO_IMAGEMAGICK:
126         {
127                 int n = 0;
128                 for (list<shared_ptr<ImageMagickDecoder> >::iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoders.end(); ++i) {
129                         if (_imagemagick_decoder == i) {
130                                 job->set_progress (float (n) / _imagemagick_decoders.size ());
131                         }
132                         ++n;
133                 }
134                 break;
135         }
136         }
137 }
138
139 void
140 Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s)
141 {
142         Video (i, same, s);
143 }
144
145 void
146 Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<AudioBuffers> b)
147 {
148         if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
149                 AudioMapping mapping = _film->audio_mapping ();
150                 if (!_sndfile_buffers) {
151                         _sndfile_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ()));
152                         _sndfile_buffers->make_silent ();
153                 }
154
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                                 _sndfile_buffers->accumulate (b, i, static_cast<int> (*j));
159                         }
160                 }
161
162         } else {
163                 Audio (b);
164         }
165 }
166
167 /** @return true on error */
168 bool
169 Player::seek (double t)
170 {
171         if (!_have_valid_decoders) {
172                 setup_decoders ();
173                 _have_valid_decoders = true;
174         }
175         
176         bool r = false;
177
178         switch (_playlist->video_from()) {
179         case Playlist::VIDEO_NONE:
180                 break;
181         case Playlist::VIDEO_FFMPEG:
182                 if (!_ffmpeg_decoder || _ffmpeg_decoder->seek (t)) {
183                         r = true;
184                 }
185                 /* We're seeking, so all `all done' bets are off */
186                 _ffmpeg_decoder_done = false;
187                 break;
188         case Playlist::VIDEO_IMAGEMAGICK:
189                 /* Find the decoder that contains this position */
190                 _imagemagick_decoder = _imagemagick_decoders.begin ();
191                 while (_imagemagick_decoder != _imagemagick_decoders.end ()) {
192                         double const this_length = (*_imagemagick_decoder)->video_length() / _film->video_frame_rate ();
193                         if (t < this_length) {
194                                 break;
195                         }
196                         t -= this_length;
197                         ++_imagemagick_decoder;
198                 }
199
200                 if (_imagemagick_decoder != _imagemagick_decoders.end()) {
201                         (*_imagemagick_decoder)->seek (t);
202                 } else {
203                         r = true;
204                 }
205                 break;
206         }
207
208         /* XXX: don't seek audio because we don't need to... */
209
210         return r;
211 }
212
213 bool
214 Player::seek_to_last ()
215 {
216         if (!_have_valid_decoders) {
217                 setup_decoders ();
218                 _have_valid_decoders = true;
219         }
220
221         bool r = false;
222         
223         switch (_playlist->video_from ()) {
224         case Playlist::VIDEO_NONE:
225                 break;
226         case Playlist::VIDEO_FFMPEG:
227                 if (!_ffmpeg_decoder || _ffmpeg_decoder->seek_to_last ()) {
228                         r = true;
229                 }
230
231                 /* We're seeking, so all `all done' bets are off */
232                 _ffmpeg_decoder_done = false;
233                 break;
234         case Playlist::VIDEO_IMAGEMAGICK:
235                 if ((*_imagemagick_decoder)->seek_to_last ()) {
236                         r = true;
237                 }
238                 break;
239         }
240
241         /* XXX: don't seek audio because we don't need to... */
242
243         return r;
244 }
245
246 void
247 Player::setup_decoders ()
248 {
249         if ((_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) || (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG)) {
250                 _ffmpeg_decoder.reset (
251                         new FFmpegDecoder (
252                                 _film,
253                                 _playlist->ffmpeg(),
254                                 _video && _playlist->video_from() == Playlist::VIDEO_FFMPEG,
255                                 _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
256                                 _subtitles && _film->with_subtitles(),
257                                 _video_sync
258                                 )
259                         );
260         }
261         
262         if (_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) {
263                 _ffmpeg_decoder->connect_video (shared_from_this ());
264         }
265
266         if (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
267                 _ffmpeg_decoder->Audio.connect (bind (&Player::process_audio, this, _playlist->ffmpeg (), _1));
268         }
269
270         if (_video && _playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
271                 list<shared_ptr<const ImageMagickContent> > ic = _playlist->imagemagick ();
272                 for (list<shared_ptr<const ImageMagickContent> >::iterator i = ic.begin(); i != ic.end(); ++i) {
273                         shared_ptr<ImageMagickDecoder> d (new ImageMagickDecoder (_film, *i));
274                         _imagemagick_decoders.push_back (d);
275                         d->connect_video (shared_from_this ());
276                 }
277
278                 _imagemagick_decoder = _imagemagick_decoders.begin ();
279         }
280
281         if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
282                 list<shared_ptr<const SndfileContent> > sc = _playlist->sndfile ();
283                 for (list<shared_ptr<const SndfileContent> >::iterator i = sc.begin(); i != sc.end(); ++i) {
284                         shared_ptr<SndfileDecoder> d (new SndfileDecoder (_film, *i));
285                         _sndfile_decoders.push_back (d);
286                         d->Audio.connect (bind (&Player::process_audio, this, *i, _1));
287                 }
288         }
289 }
290
291 void
292 Player::disable_video_sync ()
293 {
294         _video_sync = false;
295 }
296
297 double
298 Player::last_video_time () const
299 {
300         switch (_playlist->video_from ()) {
301         case Playlist::VIDEO_NONE:
302                 return 0;
303         case Playlist::VIDEO_FFMPEG:
304                 return _ffmpeg_decoder->last_source_time ();
305         case Playlist::VIDEO_IMAGEMAGICK:
306         {
307                 double t = 0;
308                 for (list<shared_ptr<ImageMagickDecoder> >::const_iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoder; ++i) {
309                         t += (*i)->video_length() / (*i)->video_frame_rate ();
310                 }
311
312                 return t + (*_imagemagick_decoder)->last_source_time ();
313         }
314         }
315
316         return 0;
317 }
318
319 void
320 Player::content_changed (weak_ptr<Content> w, int p)
321 {
322         shared_ptr<Content> c = w.lock ();
323         if (!c) {
324                 return;
325         }
326
327         if (p == VideoContentProperty::VIDEO_LENGTH) {
328                 if (dynamic_pointer_cast<FFmpegContent> (c)) {
329                         _have_valid_decoders = false;
330                 }
331         }
332 }
333
334 void
335 Player::playlist_changed ()
336 {
337         _have_valid_decoders = false;
338 }