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