Add missing files.
[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 "ffmpeg_content.h"
24 #include "imagemagick_decoder.h"
25 #include "imagemagick_content.h"
26 #include "sndfile_decoder.h"
27 #include "sndfile_content.h"
28 #include "playlist.h"
29 #include "job.h"
30
31 using std::list;
32 using std::cout;
33 using std::vector;
34 using boost::shared_ptr;
35 using boost::weak_ptr;
36 using boost::dynamic_pointer_cast;
37
38 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
39         : _film (f)
40         , _playlist (p)
41         , _video (true)
42         , _audio (true)
43         , _subtitles (true)
44         , _have_valid_decoders (false)
45 {
46         _playlist->Changed.connect (bind (&Player::playlist_changed, this));
47         _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
48 }
49
50 void
51 Player::disable_video ()
52 {
53         _video = false;
54 }
55
56 void
57 Player::disable_audio ()
58 {
59         _audio = false;
60 }
61
62 void
63 Player::disable_subtitles ()
64 {
65         _subtitles = false;
66 }
67
68 bool
69 Player::pass ()
70 {
71         if (!_have_valid_decoders) {
72                 setup_decoders ();
73                 _have_valid_decoders = true;
74         }
75         
76         bool done = true;
77         
78         if (_video && _video_decoder < _video_decoders.size ()) {
79
80                 /* Run video decoder; this may also produce audio */
81                 
82                 if (_video_decoders[_video_decoder]->pass ()) {
83                         _video_decoder++;
84                 }
85                 
86                 if (_video_decoder < _video_decoders.size ()) {
87                         done = false;
88                 }
89                 
90         }
91
92         if (!_video && _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) {
93
94                 /* We're not producing video, so we may need to run FFmpeg content to get the audio */
95                 
96                 if (_audio_decoders[_sequential_audio_decoder]->pass ()) {
97                         _sequential_audio_decoder++;
98                 }
99                 
100                 if (_sequential_audio_decoder < _audio_decoders.size ()) {
101                         done = false;
102                 }
103                 
104         }
105
106         if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
107                 
108                 /* We're getting audio from SndfileContent */
109                 
110                 for (vector<shared_ptr<AudioDecoder> >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) {
111                         if (!(*i)->pass ()) {
112                                 done = false;
113                         }
114                 }
115
116                 Audio (_audio_buffers, _audio_time.get());
117                 _audio_buffers.reset ();
118                 _audio_time = boost::none;
119         }
120
121         return done;
122 }
123
124 void
125 Player::set_progress (shared_ptr<Job> job)
126 {
127         /* Assume progress can be divined from how far through the video we are */
128
129         if (_video_decoder >= _video_decoders.size() || !_playlist->video_length()) {
130                 return;
131         }
132
133         job->set_progress ((_video_start[_video_decoder] + _video_decoders[_video_decoder]->video_frame()) / _playlist->video_length ());
134 }
135
136 void
137 Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s, double t)
138 {
139         Video (i, same, s, _video_start[_video_decoder] + t);
140 }
141
142 void
143 Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<AudioBuffers> b, double t)
144 {
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 ();
149                 _audio_time = t;
150                 if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
151                         _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder];
152                 }
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                         _audio_buffers->accumulate (b, i, static_cast<int> (*j));
159                 }
160         }
161
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;
167         }
168 }
169
170 /** @return true on error */
171 bool
172 Player::seek (double t)
173 {
174         if (!_have_valid_decoders) {
175                 setup_decoders ();
176                 _have_valid_decoders = true;
177         }
178
179         /* Find the decoder that contains this position */
180         _video_decoder = 0;
181         while (1) {
182                 ++_video_decoder;
183                 if (_video_decoder >= _video_decoders.size () || t < _video_start[_video_decoder]) {
184                         --_video_decoder;
185                         t -= _video_start[_video_decoder];
186                         break;
187                 }
188         }
189
190         if (_video_decoder < _video_decoders.size()) {
191                 _video_decoders[_video_decoder]->seek (t);
192         } else {
193                 return true;
194         }
195
196         /* XXX: don't seek audio because we don't need to... */
197
198         return false;
199 }
200
201
202 void
203 Player::seek_back ()
204 {
205         /* XXX */
206 }
207
208 void
209 Player::seek_forward ()
210 {
211         /* XXX */
212 }
213
214
215 void
216 Player::setup_decoders ()
217 {
218         _video_decoders.clear ();
219         _video_decoder = 0;
220         _audio_decoders.clear ();
221         _sequential_audio_decoder = 0;
222
223         _video_start.clear();
224         _audio_start.clear();
225
226         double video_so_far = 0;
227         double audio_so_far = 0;
228         
229         list<shared_ptr<const VideoContent> > vc = _playlist->video ();
230         for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
231                 
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;
236                 
237                 /* XXX: into content? */
238                 
239                 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
240                 if (fc) {
241                         shared_ptr<FFmpegDecoder> fd (
242                                 new FFmpegDecoder (
243                                         _film, fc, _video,
244                                         _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
245                                         _subtitles
246                                         )
247                                 );
248                         
249                         video_content = fc;
250                         audio_content = fc;
251                         video_decoder = fd;
252                         audio_decoder = fd;
253                 }
254                 
255                 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
256                 if (ic) {
257                         video_content = ic;
258                         video_decoder.reset (new ImageMagickDecoder (_film, ic));
259                 }
260                 
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();
265
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();
271                 }
272         }
273         
274         _video_decoder = 0;
275         _sequential_audio_decoder = 0;
276
277         if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
278                 
279                 list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
280                 for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
281                         
282                         shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
283                         assert (sc);
284                         
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);
289                 }
290         }
291 }
292
293 double
294 Player::last_video_time () const
295 {
296         return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
297 }
298
299 void
300 Player::content_changed (weak_ptr<Content> w, int p)
301 {
302         shared_ptr<Content> c = w.lock ();
303         if (!c) {
304                 return;
305         }
306
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;
311                 }
312         }
313 }
314
315 void
316 Player::playlist_changed ()
317 {
318         _have_valid_decoders = false;
319 }