Don't decode things if they are not enabled.
[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 <stdint.h>
21 #include "player.h"
22 #include "film.h"
23 #include "ffmpeg_decoder.h"
24 #include "ffmpeg_content.h"
25 #include "imagemagick_decoder.h"
26 #include "imagemagick_content.h"
27 #include "sndfile_decoder.h"
28 #include "sndfile_content.h"
29 #include "subtitle_content.h"
30 #include "playlist.h"
31 #include "job.h"
32 #include "image.h"
33 #include "ratio.h"
34 #include "resampler.h"
35 #include "scaler.h"
36
37 using std::list;
38 using std::cout;
39 using std::min;
40 using std::max;
41 using std::vector;
42 using std::pair;
43 using std::map;
44 using boost::shared_ptr;
45 using boost::weak_ptr;
46 using boost::dynamic_pointer_cast;
47
48 #define DEBUG_PLAYER 1
49
50 class Piece
51 {
52 public:
53         Piece (shared_ptr<Content> c)
54                 : content (c)
55                 , video_position (c->start ())
56                 , audio_position (c->start ())
57         {}
58         
59         Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
60                 : content (c)
61                 , decoder (d)
62                 , video_position (c->start ())
63                 , audio_position (c->start ())
64         {}
65         
66         shared_ptr<Content> content;
67         shared_ptr<Decoder> decoder;
68         Time video_position;
69         Time audio_position;
70 };
71
72 #ifdef DEBUG_PLAYER
73 std::ostream& operator<<(std::ostream& s, Piece const & p)
74 {
75         if (dynamic_pointer_cast<FFmpegContent> (p.content)) {
76                 s << "\tffmpeg     ";
77         } else if (dynamic_pointer_cast<ImageMagickContent> (p.content)) {
78                 s << "\timagemagick";
79         } else if (dynamic_pointer_cast<SndfileContent> (p.content)) {
80                 s << "\tsndfile    ";
81         }
82         
83         s << " at " << p.content->start() << " until " << p.content->end();
84         
85         return s;
86 }
87 #endif  
88
89 Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
90         : _film (f)
91         , _playlist (p)
92         , _video (true)
93         , _audio (true)
94         , _have_valid_pieces (false)
95         , _video_position (0)
96         , _audio_position (0)
97         , _audio_buffers (f->dcp_audio_channels(), 0)
98 {
99         _playlist->Changed.connect (bind (&Player::playlist_changed, this));
100         _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
101         _film->Changed.connect (bind (&Player::film_changed, this, _1));
102         set_video_container_size (_film->container()->size (_film->full_frame ()));
103 }
104
105 void
106 Player::disable_video ()
107 {
108         _video = false;
109 }
110
111 void
112 Player::disable_audio ()
113 {
114         _audio = false;
115 }
116
117 bool
118 Player::pass ()
119 {
120         if (!_have_valid_pieces) {
121                 setup_pieces ();
122                 _have_valid_pieces = true;
123         }
124
125 #ifdef DEBUG_PLAYER
126         cout << "= PASS\n";
127 #endif  
128
129         Time earliest_t = TIME_MAX;
130         shared_ptr<Piece> earliest;
131         enum {
132                 VIDEO,
133                 AUDIO
134         } type = VIDEO;
135
136         for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
137                 if ((*i)->decoder->done ()) {
138                         continue;
139                 }
140
141                 if (_video && dynamic_pointer_cast<VideoDecoder> ((*i)->decoder)) {
142                         if ((*i)->video_position < earliest_t) {
143                                 earliest_t = (*i)->video_position;
144                                 earliest = *i;
145                                 type = VIDEO;
146                         }
147                 }
148
149                 if (_audio && dynamic_pointer_cast<AudioDecoder> ((*i)->decoder)) {
150                         if ((*i)->audio_position < earliest_t) {
151                                 earliest_t = (*i)->audio_position;
152                                 earliest = *i;
153                                 type = AUDIO;
154                         }
155                 }
156         }
157
158         if (!earliest) {
159 #ifdef DEBUG_PLAYER
160                 cout << "no earliest piece.\n";
161 #endif          
162                 
163                 flush ();
164                 return true;
165         }
166
167         switch (type) {
168         case VIDEO:
169                 if (earliest_t > _video_position) {
170 #ifdef DEBUG_PLAYER
171                         cout << "no video here; emitting black frame (earliest=" << earliest_t << ", video_position=" << _video_position << ").\n";
172 #endif
173                         emit_black ();
174                 } else {
175 #ifdef DEBUG_PLAYER
176                         cout << "Pass " << *earliest << "\n";
177 #endif                  
178                         earliest->decoder->pass ();
179                 }
180                 break;
181
182         case AUDIO:
183                 if (earliest_t > _audio_position) {
184 #ifdef DEBUG_PLAYER
185                         cout << "no audio here; emitting silence.\n";
186 #endif
187                         emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
188                 } else {
189 #ifdef DEBUG_PLAYER
190                         cout << "Pass " << *earliest << "\n";
191 #endif                  
192                         earliest->decoder->pass ();
193                 }
194                 break;
195         }
196
197 #ifdef DEBUG_PLAYER
198         cout << "\tpost pass " << _video_position << " " << _audio_position << "\n";
199 #endif  
200
201         return false;
202 }
203
204 void
205 Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, bool same, VideoContent::Frame frame)
206 {
207         shared_ptr<Piece> piece = weak_piece.lock ();
208         if (!piece) {
209                 return;
210         }
211
212         shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
213         assert (content);
214
215         FrameRateConversion frc (content->video_frame_rate(), _film->dcp_video_frame_rate());
216         if (frc.skip && (frame % 2) == 1) {
217                 return;
218         }
219
220         shared_ptr<Image> work_image = image->crop (content->crop(), true);
221
222         libdcp::Size const image_size = content->ratio()->size (_video_container_size);
223         
224         work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
225
226         Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
227         
228         if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
229                 work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
230         }
231
232         if (image_size != _video_container_size) {
233                 assert (image_size.width <= _video_container_size.width);
234                 assert (image_size.height <= _video_container_size.height);
235                 shared_ptr<Image> im (new Image (PIX_FMT_RGB24, _video_container_size, true));
236                 im->make_black ();
237                 im->copy (work_image, Position<int> ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
238                 work_image = im;
239         }
240
241         Video (work_image, same, time);
242         time += TIME_HZ / _film->dcp_video_frame_rate();
243
244         if (frc.repeat) {
245                 Video (work_image, true, time);
246                 time += TIME_HZ / _film->dcp_video_frame_rate();
247         }
248
249         _video_position = piece->video_position = time;
250 }
251
252 void
253 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
254 {
255         shared_ptr<Piece> piece = weak_piece.lock ();
256         if (!piece) {
257                 return;
258         }
259
260         shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
261         assert (content);
262
263         /* Resample */
264         if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
265                 shared_ptr<Resampler> r = resampler (content);
266                 audio = r->run (audio);
267         }
268
269         /* Remap channels */
270         shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->dcp_audio_channels(), audio->frames()));
271         dcp_mapped->make_silent ();
272         list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
273         for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
274                 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
275                         dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
276                 }
277         }
278
279         audio = dcp_mapped;
280
281         Time time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate()) + (content->audio_delay() * TIME_HZ / 1000);
282
283         /* We must cut off anything that comes before the start of all time */
284         if (time < 0) {
285                 int const frames = - time * _film->dcp_audio_frame_rate() / TIME_HZ;
286                 if (frames >= audio->frames ()) {
287                         return;
288                 }
289
290                 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
291                 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
292
293                 audio = trimmed;
294                 time = 0;
295         }
296
297         /* The time of this audio may indicate that some of our buffered audio is not going to
298            be added to any more, so it can be emitted.
299         */
300
301         if (time > _audio_position) {
302                 /* We can emit some audio from our buffers */
303                 OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
304                 if (N > _audio_buffers.frames()) {
305                         /* We need some extra silence before whatever is in the buffers */
306                         _audio_buffers.ensure_size (N);
307                         _audio_buffers.move (0, N - _audio_buffers.frames(), _audio_buffers.frames ());
308                         _audio_buffers.make_silent (0, _audio_buffers.frames());
309                         _audio_buffers.set_frames (N);
310                 }
311                 assert (N <= _audio_buffers.frames());
312                 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
313                 emit->copy_from (&_audio_buffers, N, 0, 0);
314                 Audio (emit, _audio_position);
315                 _audio_position = piece->audio_position = time + _film->audio_frames_to_time (N);
316
317                 /* And remove it from our buffers */
318                 if (_audio_buffers.frames() > N) {
319                         _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
320                 }
321                 _audio_buffers.set_frames (_audio_buffers.frames() - N);
322         }
323
324         /* Now accumulate the new audio into our buffers */
325         _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
326         _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
327         _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
328 }
329
330 void
331 Player::flush ()
332 {
333         if (_audio_buffers.frames() > 0) {
334                 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
335                 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
336                 Audio (emit, _audio_position);
337                 _audio_position += _film->audio_frames_to_time (_audio_buffers.frames ());
338                 _audio_buffers.set_frames (0);
339         }
340
341         while (_video_position < _audio_position) {
342                 emit_black ();
343         }
344
345         while (_audio_position < _video_position) {
346                 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
347         }
348         
349 }
350
351 /** @return true on error */
352 void
353 Player::seek (Time t, bool accurate)
354 {
355         if (!_have_valid_pieces) {
356                 setup_pieces ();
357                 _have_valid_pieces = true;
358         }
359
360         if (_pieces.empty ()) {
361                 return;
362         }
363
364         for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
365                 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
366                 if (!vc) {
367                         continue;
368                 }
369                 
370                 Time s = t - vc->start ();
371                 s = max (static_cast<Time> (0), s);
372                 s = min (vc->length(), s);
373
374                 (*i)->video_position = (*i)->audio_position = vc->start() + s;
375
376                 FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
377                 VideoContent::Frame f = s * vc->video_frame_rate() / (frc.factor() * TIME_HZ);
378                 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
379         }
380
381         _video_position = _audio_position = t;
382         /* XXX: don't seek audio because we don't need to... */
383 }
384
385 void
386 Player::setup_pieces ()
387 {
388         list<shared_ptr<Piece> > old_pieces = _pieces;
389
390         _pieces.clear ();
391
392         Playlist::ContentList content = _playlist->content ();
393         sort (content.begin(), content.end(), ContentSorter ());
394
395         for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
396
397                 shared_ptr<Piece> piece (new Piece (*i));
398
399                 /* XXX: into content? */
400
401                 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
402                 if (fc) {
403                         shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
404                         
405                         fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
406                         fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
407                         fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
408
409                         piece->decoder = fd;
410                 }
411                 
412                 shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
413                 if (ic) {
414                         shared_ptr<ImageMagickDecoder> id;
415                         
416                         /* See if we can re-use an old ImageMagickDecoder */
417                         for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
418                                 shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> ((*j)->decoder);
419                                 if (imd && imd->content() == ic) {
420                                         id = imd;
421                                 }
422                         }
423
424                         if (!id) {
425                                 id.reset (new ImageMagickDecoder (_film, ic));
426                                 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
427                         }
428
429                         piece->decoder = id;
430                 }
431
432                 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
433                 if (sc) {
434                         shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
435                         sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
436
437                         piece->decoder = sd;
438                 }
439
440                 _pieces.push_back (piece);
441         }
442
443 #ifdef DEBUG_PLAYER
444         cout << "=== Player setup:\n";
445         for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
446                 cout << *(i->get()) << "\n";
447         }
448 #endif  
449 }
450
451 void
452 Player::content_changed (weak_ptr<Content> w, int p)
453 {
454         shared_ptr<Content> c = w.lock ();
455         if (!c) {
456                 return;
457         }
458
459         if (
460                 p == ContentProperty::START || p == ContentProperty::LENGTH ||
461                 p == VideoContentProperty::VIDEO_CROP || p == VideoContentProperty::VIDEO_RATIO
462                 ) {
463                 
464                 _have_valid_pieces = false;
465                 Changed ();
466
467         } else if (p == SubtitleContentProperty::SUBTITLE_OFFSET || p == SubtitleContentProperty::SUBTITLE_SCALE) {
468                 update_subtitle ();
469                 Changed ();
470         }
471 }
472
473 void
474 Player::playlist_changed ()
475 {
476         _have_valid_pieces = false;
477         Changed ();
478 }
479
480 void
481 Player::set_video_container_size (libdcp::Size s)
482 {
483         _video_container_size = s;
484         _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
485         _black_frame->make_black ();
486 }
487
488 shared_ptr<Resampler>
489 Player::resampler (shared_ptr<AudioContent> c)
490 {
491         map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
492         if (i != _resamplers.end ()) {
493                 return i->second;
494         }
495         
496         shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
497         _resamplers[c] = r;
498         return r;
499 }
500
501 void
502 Player::emit_black ()
503 {
504         /* XXX: use same here */
505         Video (_black_frame, false, _video_position);
506         _video_position += _film->video_frames_to_time (1);
507 }
508
509 void
510 Player::emit_silence (OutputAudioFrame most)
511 {
512         OutputAudioFrame N = min (most, _film->dcp_audio_frame_rate() / 2);
513         shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->dcp_audio_channels(), N));
514         silence->make_silent ();
515         Audio (silence, _audio_position);
516         _audio_position += _film->audio_frames_to_time (N);
517 }
518
519 void
520 Player::film_changed (Film::Property p)
521 {
522         /* Here we should notice Film properties that affect our output, and
523            alert listeners that our output now would be different to how it was
524            last time we were run.
525         */
526
527         if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
528                 Changed ();
529         }
530 }
531
532 void
533 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
534 {
535         _in_subtitle.piece = weak_piece;
536         _in_subtitle.image = image;
537         _in_subtitle.rect = rect;
538         _in_subtitle.from = from;
539         _in_subtitle.to = to;
540
541         update_subtitle ();
542 }
543
544 void
545 Player::update_subtitle ()
546 {
547         shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
548         if (!piece) {
549                 return;
550         }
551
552         if (!_in_subtitle.image) {
553                 _out_subtitle.image.reset ();
554                 return;
555         }
556
557         shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
558         assert (sc);
559
560         dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
561         libdcp::Size scaled_size;
562
563         in_rect.y += sc->subtitle_offset ();
564
565         /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
566         scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
567         scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
568
569         /* Then we need a corrective translation, consisting of two parts:
570          *
571          * 1.  that which is the result of the scaling of the subtitle by _video_container_size; this will be
572          *     rect.x * _video_container_size.width and rect.y * _video_container_size.height.
573          *
574          * 2.  that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
575          *     (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
576          *     (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
577          *
578          * Combining these two translations gives these expressions.
579          */
580         
581         _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
582         _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
583         
584         _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true);
585         _out_subtitle.from = _in_subtitle.from + piece->content->start ();
586         _out_subtitle.to = _in_subtitle.to + piece->content->start ();
587 }