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