Basics of front-end 3D (as far as viewer, at least).
[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 "still_image_decoder.h"
26 #include "still_image_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<StillImageContent> (p.content)) {
78                 s << "\tstill image";
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, _3));
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, Eyes eyes, 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 #ifdef DCPOMATIC_DEBUG
242         _last_video = piece->content;
243 #endif  
244
245         Video (work_image, eyes, same, time);
246         time += TIME_HZ / _film->dcp_video_frame_rate();
247
248         if (frc.repeat) {
249                 Video (work_image, eyes, true, time);
250                 time += TIME_HZ / _film->dcp_video_frame_rate();
251         }
252
253         _video_position = piece->video_position = time;
254 }
255
256 void
257 Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
258 {
259         shared_ptr<Piece> piece = weak_piece.lock ();
260         if (!piece) {
261                 return;
262         }
263
264         shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
265         assert (content);
266
267         /* Resample */
268         if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
269                 shared_ptr<Resampler> r = resampler (content);
270                 audio = r->run (audio);
271         }
272
273         /* Remap channels */
274         shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->dcp_audio_channels(), audio->frames()));
275         dcp_mapped->make_silent ();
276         list<pair<int, libdcp::Channel> > map = content->audio_mapping().content_to_dcp ();
277         for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
278                 if (i->first < audio->channels() && i->second < dcp_mapped->channels()) {
279                         dcp_mapped->accumulate_channel (audio.get(), i->first, i->second);
280                 }
281         }
282
283         audio = dcp_mapped;
284
285         Time time = content->start() + (frame * TIME_HZ / _film->dcp_audio_frame_rate()) + (content->audio_delay() * TIME_HZ / 1000);
286
287         /* We must cut off anything that comes before the start of all time */
288         if (time < 0) {
289                 int const frames = - time * _film->dcp_audio_frame_rate() / TIME_HZ;
290                 if (frames >= audio->frames ()) {
291                         return;
292                 }
293
294                 shared_ptr<AudioBuffers> trimmed (new AudioBuffers (audio->channels(), audio->frames() - frames));
295                 trimmed->copy_from (audio.get(), audio->frames() - frames, frames, 0);
296
297                 audio = trimmed;
298                 time = 0;
299         }
300
301         /* The time of this audio may indicate that some of our buffered audio is not going to
302            be added to any more, so it can be emitted.
303         */
304
305         if (time > _audio_position) {
306                 /* We can emit some audio from our buffers */
307                 OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
308                 if (N > _audio_buffers.frames()) {
309                         /* We need some extra silence before whatever is in the buffers */
310                         _audio_buffers.ensure_size (N);
311                         _audio_buffers.move (0, N - _audio_buffers.frames(), _audio_buffers.frames ());
312                         _audio_buffers.make_silent (0, _audio_buffers.frames());
313                         _audio_buffers.set_frames (N);
314                 }
315                 assert (N <= _audio_buffers.frames());
316                 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
317                 emit->copy_from (&_audio_buffers, N, 0, 0);
318                 Audio (emit, _audio_position);
319                 _audio_position = piece->audio_position = time + _film->audio_frames_to_time (N);
320
321                 /* And remove it from our buffers */
322                 if (_audio_buffers.frames() > N) {
323                         _audio_buffers.move (N, 0, _audio_buffers.frames() - N);
324                 }
325                 _audio_buffers.set_frames (_audio_buffers.frames() - N);
326         }
327
328         /* Now accumulate the new audio into our buffers */
329         _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
330         _audio_buffers.accumulate_frames (audio.get(), 0, 0, audio->frames ());
331         _audio_buffers.set_frames (_audio_buffers.frames() + audio->frames());
332 }
333
334 void
335 Player::flush ()
336 {
337         if (_audio_buffers.frames() > 0) {
338                 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), _audio_buffers.frames()));
339                 emit->copy_from (&_audio_buffers, _audio_buffers.frames(), 0, 0);
340                 Audio (emit, _audio_position);
341                 _audio_position += _film->audio_frames_to_time (_audio_buffers.frames ());
342                 _audio_buffers.set_frames (0);
343         }
344
345         while (_video_position < _audio_position) {
346                 emit_black ();
347         }
348
349         while (_audio_position < _video_position) {
350                 emit_silence (_film->time_to_audio_frames (_video_position - _audio_position));
351         }
352         
353 }
354
355 /** Seek so that the next pass() will yield (approximately) the requested frame.
356  *  Pass accurate = true to try harder to get close to the request.
357  *  @return true on error
358  */
359 void
360 Player::seek (Time t, bool accurate)
361 {
362         if (!_have_valid_pieces) {
363                 setup_pieces ();
364                 _have_valid_pieces = true;
365         }
366
367         if (_pieces.empty ()) {
368                 return;
369         }
370
371         for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
372                 shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
373                 if (!vc) {
374                         continue;
375                 }
376                 
377                 Time s = t - vc->start ();
378                 s = max (static_cast<Time> (0), s);
379                 s = min (vc->length(), s);
380
381                 (*i)->video_position = (*i)->audio_position = vc->start() + s;
382
383                 FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
384                 /* Here we are converting from time (in the DCP) to a frame number in the content.
385                    Hence we need to use the DCP's frame rate and the double/skip correction, not
386                    the source's rate.
387                 */
388                 VideoContent::Frame f = s * _film->dcp_video_frame_rate() / (frc.factor() * TIME_HZ);
389                 dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
390         }
391
392         _video_position = _audio_position = t;
393         
394         /* XXX: don't seek audio because we don't need to... */
395 }
396
397 void
398 Player::setup_pieces ()
399 {
400         list<shared_ptr<Piece> > old_pieces = _pieces;
401
402         _pieces.clear ();
403
404         ContentList content = _playlist->content ();
405         sort (content.begin(), content.end(), ContentSorter ());
406
407         for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
408
409                 shared_ptr<Piece> piece (new Piece (*i));
410
411                 /* XXX: into content? */
412
413                 shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
414                 if (fc) {
415                         shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
416                         
417                         fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
418                         fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
419                         fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
420
421                         piece->decoder = fd;
422                 }
423                 
424                 shared_ptr<const StillImageContent> ic = dynamic_pointer_cast<const StillImageContent> (*i);
425                 if (ic) {
426                         shared_ptr<StillImageDecoder> id;
427                         
428                         /* See if we can re-use an old StillImageDecoder */
429                         for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
430                                 shared_ptr<StillImageDecoder> imd = dynamic_pointer_cast<StillImageDecoder> ((*j)->decoder);
431                                 if (imd && imd->content() == ic) {
432                                         id = imd;
433                                 }
434                         }
435
436                         if (!id) {
437                                 id.reset (new StillImageDecoder (_film, ic));
438                                 id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
439                         }
440
441                         piece->decoder = id;
442                 }
443
444                 shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
445                 if (sc) {
446                         shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
447                         sd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
448
449                         piece->decoder = sd;
450                 }
451
452                 _pieces.push_back (piece);
453         }
454
455 #ifdef DEBUG_PLAYER
456         cout << "=== Player setup:\n";
457         for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
458                 cout << *(i->get()) << "\n";
459         }
460 #endif  
461 }
462
463 void
464 Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
465 {
466         shared_ptr<Content> c = w.lock ();
467         if (!c) {
468                 return;
469         }
470
471         if (
472                 property == ContentProperty::START || property == ContentProperty::LENGTH ||
473                 property == VideoContentProperty::VIDEO_CROP || property == VideoContentProperty::VIDEO_RATIO
474                 ) {
475                 
476                 _have_valid_pieces = false;
477                 Changed (frequent);
478
479         } else if (property == SubtitleContentProperty::SUBTITLE_OFFSET || property == SubtitleContentProperty::SUBTITLE_SCALE) {
480                 update_subtitle ();
481                 Changed (frequent);
482         } else if (property == VideoContentProperty::VIDEO_FRAME_TYPE) {
483                 cout << "vft change.\n";
484                 Changed (frequent);
485         }
486 }
487
488 void
489 Player::playlist_changed ()
490 {
491         _have_valid_pieces = false;
492         Changed (false);
493 }
494
495 void
496 Player::set_video_container_size (libdcp::Size s)
497 {
498         _video_container_size = s;
499         _black_frame.reset (new Image (PIX_FMT_RGB24, _video_container_size, true));
500         _black_frame->make_black ();
501 }
502
503 shared_ptr<Resampler>
504 Player::resampler (shared_ptr<AudioContent> c)
505 {
506         map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
507         if (i != _resamplers.end ()) {
508                 return i->second;
509         }
510         
511         shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
512         _resamplers[c] = r;
513         return r;
514 }
515
516 void
517 Player::emit_black ()
518 {
519 #ifdef DCPOMATIC_DEBUG
520         _last_video.reset ();
521 #endif
522         
523         /* XXX: use same here */
524         Video (_black_frame, EYES_BOTH, false, _video_position);
525         _video_position += _film->video_frames_to_time (1);
526 }
527
528 void
529 Player::emit_silence (OutputAudioFrame most)
530 {
531         OutputAudioFrame N = min (most, _film->dcp_audio_frame_rate() / 2);
532         shared_ptr<AudioBuffers> silence (new AudioBuffers (_film->dcp_audio_channels(), N));
533         silence->make_silent ();
534         Audio (silence, _audio_position);
535         _audio_position += _film->audio_frames_to_time (N);
536 }
537
538 void
539 Player::film_changed (Film::Property p)
540 {
541         /* Here we should notice Film properties that affect our output, and
542            alert listeners that our output now would be different to how it was
543            last time we were run.
544         */
545
546         if (p == Film::SCALER || p == Film::WITH_SUBTITLES || p == Film::CONTAINER) {
547                 Changed (false);
548         }
549 }
550
551 void
552 Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<Image> image, dcpomatic::Rect<double> rect, Time from, Time to)
553 {
554         _in_subtitle.piece = weak_piece;
555         _in_subtitle.image = image;
556         _in_subtitle.rect = rect;
557         _in_subtitle.from = from;
558         _in_subtitle.to = to;
559
560         update_subtitle ();
561 }
562
563 void
564 Player::update_subtitle ()
565 {
566         shared_ptr<Piece> piece = _in_subtitle.piece.lock ();
567         if (!piece) {
568                 return;
569         }
570
571         if (!_in_subtitle.image) {
572                 _out_subtitle.image.reset ();
573                 return;
574         }
575
576         shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (piece->content);
577         assert (sc);
578
579         dcpomatic::Rect<double> in_rect = _in_subtitle.rect;
580         libdcp::Size scaled_size;
581
582         in_rect.y += sc->subtitle_offset ();
583
584         /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */
585         scaled_size.width = in_rect.width * _video_container_size.width * sc->subtitle_scale ();
586         scaled_size.height = in_rect.height * _video_container_size.height * sc->subtitle_scale ();
587
588         /* Then we need a corrective translation, consisting of two parts:
589          *
590          * 1.  that which is the result of the scaling of the subtitle by _video_container_size; this will be
591          *     rect.x * _video_container_size.width and rect.y * _video_container_size.height.
592          *
593          * 2.  that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be
594          *     (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and
595          *     (height_before_subtitle_scale * (1 - subtitle_scale) / 2).
596          *
597          * Combining these two translations gives these expressions.
598          */
599         
600         _out_subtitle.position.x = rint (_video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2)));
601         _out_subtitle.position.y = rint (_video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2)));
602         
603         _out_subtitle.image = _in_subtitle.image->scale (libdcp::Size (scaled_size.width, scaled_size.height), Scaler::from_id ("bicubic"), true);
604         _out_subtitle.from = _in_subtitle.from + piece->content->start ();
605         _out_subtitle.to = _in_subtitle.to + piece->content->start ();
606 }