Replace aligned bool with enum Alignment.
[dcpomatic.git] / src / lib / ffmpeg_decoder.cc
1 /*
2     Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 /** @file  src/ffmpeg_decoder.cc
23  *  @brief A decoder using FFmpeg to decode content.
24  */
25
26
27 #include "audio_buffers.h"
28 #include "audio_content.h"
29 #include "audio_decoder.h"
30 #include "compose.hpp"
31 #include "dcpomatic_log.h"
32 #include "exceptions.h"
33 #include "ffmpeg_audio_stream.h"
34 #include "ffmpeg_content.h"
35 #include "ffmpeg_decoder.h"
36 #include "ffmpeg_subtitle_stream.h"
37 #include "film.h"
38 #include "filter.h"
39 #include "frame_interval_checker.h"
40 #include "image.h"
41 #include "log.h"
42 #include "raw_image_proxy.h"
43 #include "text_content.h"
44 #include "text_decoder.h"
45 #include "util.h"
46 #include "video_decoder.h"
47 #include "video_filter_graph.h"
48 #include <dcp/subtitle_string.h>
49 #include <sub/ssa_reader.h>
50 #include <sub/subtitle.h>
51 #include <sub/collect.h>
52 extern "C" {
53 #include <libavcodec/avcodec.h>
54 #include <libavformat/avformat.h>
55 }
56 #include <boost/algorithm/string.hpp>
57 #include <iomanip>
58 #include <iostream>
59 #include <vector>
60 #include <stdint.h>
61
62 #include "i18n.h"
63
64
65 using std::cout;
66 using std::dynamic_pointer_cast;
67 using std::make_shared;
68 using std::min;
69 using std::shared_ptr;
70 using std::string;
71 using std::vector;
72 using boost::optional;
73 using dcp::Size;
74 using namespace dcpomatic;
75
76
77 FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> film, shared_ptr<const FFmpegContent> c, bool fast)
78         : FFmpeg (c)
79         , Decoder (film)
80 {
81         if (c->video && c->video->use()) {
82                 video = make_shared<VideoDecoder>(this, c);
83                 _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film));
84                 /* It doesn't matter what size or pixel format this is, it just needs to be black */
85                 _black_image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (128, 128), Image::Alignment::PADDED);
86                 _black_image->make_black ();
87         } else {
88                 _pts_offset = {};
89         }
90
91         if (c->audio) {
92                 audio = make_shared<AudioDecoder>(this, c->audio, fast);
93         }
94
95         if (c->only_text()) {
96                 /* XXX: this time here should be the time of the first subtitle, not 0 */
97                 text.push_back (make_shared<TextDecoder>(this, c->only_text(), ContentTime()));
98         }
99
100         for (auto i: c->ffmpeg_audio_streams()) {
101                 _next_time[i] = boost::optional<dcpomatic::ContentTime>();
102         }
103 }
104
105
106 bool
107 FFmpegDecoder::flush ()
108 {
109         /* Flush video and audio once */
110
111         bool did_something = false;
112         if (video) {
113                 if (decode_and_process_video_packet(nullptr)) {
114                         did_something = true;
115                 }
116         }
117
118         for (auto i: ffmpeg_content()->ffmpeg_audio_streams()) {
119                 auto context = _codec_context[i->index(_format_context)];
120                 int r = avcodec_send_packet (context, nullptr);
121                 if (r < 0 && r != AVERROR_EOF) {
122                         /* EOF can happen if we've already sent a flush packet */
123                         throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::flush"), r);
124                 }
125                 r = avcodec_receive_frame (context, _frame);
126                 if (r >= 0) {
127                         process_audio_frame (i);
128                         did_something = true;
129                 }
130         }
131
132         if (did_something) {
133                 /* We want to be called again */
134                 return false;
135         }
136
137         /* Make sure all streams are the same length and round up to the next video frame */
138
139         auto const frc = film()->active_frame_rate_change(_ffmpeg_content->position());
140         ContentTime full_length (_ffmpeg_content->full_length(film()), frc);
141         full_length = full_length.ceil (frc.source);
142         if (video) {
143                 double const vfr = _ffmpeg_content->video_frame_rate().get();
144                 auto const f = full_length.frames_round (vfr);
145                 auto v = video->position(film()).get_value_or(ContentTime()).frames_round(vfr) + 1;
146                 while (v < f) {
147                         video->emit (film(), shared_ptr<const ImageProxy> (new RawImageProxy (_black_image)), v);
148                         ++v;
149                 }
150         }
151
152         for (auto i: _ffmpeg_content->ffmpeg_audio_streams ()) {
153                 auto a = audio->stream_position(film(), i);
154                 /* Unfortunately if a is 0 that really means that we don't know the stream position since
155                    there has been no data on it since the last seek.  In this case we'll just do nothing
156                    here.  I'm not sure if that's the right idea.
157                 */
158                 if (a > ContentTime()) {
159                         while (a < full_length) {
160                                 auto to_do = min (full_length - a, ContentTime::from_seconds (0.1));
161                                 auto silence = make_shared<AudioBuffers>(i->channels(), to_do.frames_ceil (i->frame_rate()));
162                                 silence->make_silent ();
163                                 audio->emit (film(), i, silence, a, true);
164                                 a += to_do;
165                         }
166                 }
167         }
168
169         if (audio) {
170                 audio->flush ();
171         }
172
173         return true;
174 }
175
176
177 bool
178 FFmpegDecoder::pass ()
179 {
180         auto packet = av_packet_alloc();
181         DCPOMATIC_ASSERT (packet);
182
183         int r = av_read_frame (_format_context, packet);
184
185         /* AVERROR_INVALIDDATA can apparently be returned sometimes even when av_read_frame
186            has pretty-much succeeded (and hence generated data which should be processed).
187            Hence it makes sense to continue here in that case.
188         */
189         if (r < 0 && r != AVERROR_INVALIDDATA) {
190                 if (r != AVERROR_EOF) {
191                         /* Maybe we should fail here, but for now we'll just finish off instead */
192                         char buf[256];
193                         av_strerror (r, buf, sizeof(buf));
194                         LOG_ERROR (N_("error on av_read_frame (%1) (%2)"), &buf[0], r);
195                 }
196
197                 av_packet_free (&packet);
198                 return flush ();
199         }
200
201         int const si = packet->stream_index;
202         auto fc = _ffmpeg_content;
203
204         if (_video_stream && si == _video_stream.get() && video && !video->ignore()) {
205                 decode_and_process_video_packet (packet);
206         } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !only_text()->ignore()) {
207                 decode_and_process_subtitle_packet (packet);
208         } else {
209                 decode_and_process_audio_packet (packet);
210         }
211
212         av_packet_free (&packet);
213         return false;
214 }
215
216
217 /** @param data pointer to array of pointers to buffers.
218  *  Only the first buffer will be used for non-planar data, otherwise there will be one per channel.
219  */
220 shared_ptr<AudioBuffers>
221 FFmpegDecoder::deinterleave_audio (AVFrame* frame)
222 {
223         auto format = static_cast<AVSampleFormat>(frame->format);
224
225         /* XXX: can't we use swr_convert() to do the format conversion? */
226
227         int const channels = frame->channels;
228         int const frames = frame->nb_samples;
229         int const total_samples = frames * channels;
230         auto audio = make_shared<AudioBuffers>(channels, frames);
231         auto data = audio->data();
232
233         switch (format) {
234         case AV_SAMPLE_FMT_U8:
235         {
236                 auto p = reinterpret_cast<uint8_t *> (frame->data[0]);
237                 int sample = 0;
238                 int channel = 0;
239                 for (int i = 0; i < total_samples; ++i) {
240                         data[channel][sample] = float(*p++) / (1 << 23);
241
242                         ++channel;
243                         if (channel == channels) {
244                                 channel = 0;
245                                 ++sample;
246                         }
247                 }
248         }
249         break;
250
251         case AV_SAMPLE_FMT_S16:
252         {
253                 auto p = reinterpret_cast<int16_t *> (frame->data[0]);
254                 int sample = 0;
255                 int channel = 0;
256                 for (int i = 0; i < total_samples; ++i) {
257                         data[channel][sample] = float(*p++) / (1 << 15);
258
259                         ++channel;
260                         if (channel == channels) {
261                                 channel = 0;
262                                 ++sample;
263                         }
264                 }
265         }
266         break;
267
268         case AV_SAMPLE_FMT_S16P:
269         {
270                 auto p = reinterpret_cast<int16_t **> (frame->data);
271                 for (int i = 0; i < channels; ++i) {
272                         for (int j = 0; j < frames; ++j) {
273                                 data[i][j] = static_cast<float>(p[i][j]) / (1 << 15);
274                         }
275                 }
276         }
277         break;
278
279         case AV_SAMPLE_FMT_S32:
280         {
281                 auto p = reinterpret_cast<int32_t *> (frame->data[0]);
282                 int sample = 0;
283                 int channel = 0;
284                 for (int i = 0; i < total_samples; ++i) {
285                         data[channel][sample] = static_cast<float>(*p++) / 2147483648;
286
287                         ++channel;
288                         if (channel == channels) {
289                                 channel = 0;
290                                 ++sample;
291                         }
292                 }
293         }
294         break;
295
296         case AV_SAMPLE_FMT_S32P:
297         {
298                 auto p = reinterpret_cast<int32_t **> (frame->data);
299                 for (int i = 0; i < channels; ++i) {
300                         for (int j = 0; j < frames; ++j) {
301                                 data[i][j] = static_cast<float>(p[i][j]) / 2147483648;
302                         }
303                 }
304         }
305         break;
306
307         case AV_SAMPLE_FMT_FLT:
308         {
309                 auto p = reinterpret_cast<float*> (frame->data[0]);
310                 int sample = 0;
311                 int channel = 0;
312                 for (int i = 0; i < total_samples; ++i) {
313                         data[channel][sample] = *p++;
314
315                         ++channel;
316                         if (channel == channels) {
317                                 channel = 0;
318                                 ++sample;
319                         }
320                 }
321         }
322         break;
323
324         case AV_SAMPLE_FMT_FLTP:
325         {
326                 auto p = reinterpret_cast<float**> (frame->data);
327                 DCPOMATIC_ASSERT (frame->channels <= channels);
328                 /* Sometimes there aren't as many channels in the frame as in the stream */
329                 for (int i = 0; i < frame->channels; ++i) {
330                         memcpy (data[i], p[i], frames * sizeof(float));
331                 }
332                 for (int i = frame->channels; i < channels; ++i) {
333                         audio->make_silent (i);
334                 }
335         }
336         break;
337
338         default:
339                 throw DecodeError (String::compose(_("Unrecognised audio sample format (%1)"), static_cast<int>(format)));
340         }
341
342         return audio;
343 }
344
345
346 AVSampleFormat
347 FFmpegDecoder::audio_sample_format (shared_ptr<FFmpegAudioStream> stream) const
348 {
349         return static_cast<AVSampleFormat>(stream->stream(_format_context)->codecpar->format);
350 }
351
352
353 int
354 FFmpegDecoder::bytes_per_audio_sample (shared_ptr<FFmpegAudioStream> stream) const
355 {
356         return av_get_bytes_per_sample (audio_sample_format (stream));
357 }
358
359
360 void
361 FFmpegDecoder::seek (ContentTime time, bool accurate)
362 {
363         Decoder::seek (time, accurate);
364
365         /* If we are doing an `accurate' seek, we need to use pre-roll, as
366            we don't really know what the seek will give us.
367         */
368
369         auto pre_roll = accurate ? ContentTime::from_seconds (2) : ContentTime (0);
370         time -= pre_roll;
371
372         /* XXX: it seems debatable whether PTS should be used here...
373            http://www.mjbshaw.com/2012/04/seeking-in-ffmpeg-know-your-timestamp.html
374         */
375
376         optional<int> stream;
377
378         if (_video_stream) {
379                 stream = _video_stream;
380         } else {
381                 DCPOMATIC_ASSERT (_ffmpeg_content->audio);
382                 auto s = dynamic_pointer_cast<FFmpegAudioStream>(_ffmpeg_content->audio->stream());
383                 if (s) {
384                         stream = s->index (_format_context);
385                 }
386         }
387
388         DCPOMATIC_ASSERT (stream);
389
390         auto u = time - _pts_offset;
391         if (u < ContentTime ()) {
392                 u = ContentTime ();
393         }
394         av_seek_frame (
395                 _format_context,
396                 stream.get(),
397                 u.seconds() / av_q2d (_format_context->streams[stream.get()]->time_base),
398                 AVSEEK_FLAG_BACKWARD
399                 );
400
401         {
402                 /* Force re-creation of filter graphs to reset them and hence to make sure
403                    they don't have any pre-seek frames knocking about.
404                 */
405                 boost::mutex::scoped_lock lm (_filter_graphs_mutex);
406                 _filter_graphs.clear ();
407         }
408
409         if (video_codec_context ()) {
410                 avcodec_flush_buffers (video_codec_context());
411         }
412
413         for (auto i: ffmpeg_content()->ffmpeg_audio_streams()) {
414                 avcodec_flush_buffers (_codec_context[i->index(_format_context)]);
415         }
416
417         if (subtitle_codec_context ()) {
418                 avcodec_flush_buffers (subtitle_codec_context ());
419         }
420
421         _have_current_subtitle = false;
422
423         for (auto& i: _next_time) {
424                 i.second = boost::optional<dcpomatic::ContentTime>();
425         }
426
427         /* We find that we get some errors from av_send_packet after a seek.  Perhaps we should ignore
428          * all of them (which seems risky), or perhaps we should have some proper fix.  But instead
429          * let's ignore the next 2 errors.
430          */
431         _errors_to_ignore = 2;
432 }
433
434
435 shared_ptr<FFmpegAudioStream>
436 FFmpegDecoder::audio_stream_from_index (int index) const
437 {
438         /* XXX: inefficient */
439         auto streams = ffmpeg_content()->ffmpeg_audio_streams();
440         auto stream = streams.begin();
441         while (stream != streams.end() && !(*stream)->uses_index(_format_context, index)) {
442                 ++stream;
443         }
444
445         if (stream == streams.end ()) {
446                 return {};
447         }
448
449         return *stream;
450 }
451
452
453 void
454 FFmpegDecoder::process_audio_frame (shared_ptr<FFmpegAudioStream> stream)
455 {
456         auto data = deinterleave_audio (_frame);
457
458         ContentTime ct;
459         if (_frame->pts == AV_NOPTS_VALUE) {
460                 /* In some streams we see not every frame coming through with a timestamp; for those
461                    that have AV_NOPTS_VALUE we need to work out the timestamp ourselves.  This is
462                    particularly noticeable with TrueHD streams (see #1111).
463                    */
464                 if (_next_time[stream]) {
465                         ct = *_next_time[stream];
466                 }
467         } else {
468                 ct = ContentTime::from_seconds (
469                         _frame->best_effort_timestamp *
470                         av_q2d (stream->stream(_format_context)->time_base))
471                         + _pts_offset;
472         }
473
474         _next_time[stream] = ct + ContentTime::from_frames(data->frames(), stream->frame_rate());
475
476         if (ct < ContentTime()) {
477                 /* Discard audio data that comes before time 0 */
478                 auto const remove = min (int64_t(data->frames()), (-ct).frames_ceil(double(stream->frame_rate())));
479                 data->move (data->frames() - remove, remove, 0);
480                 data->set_frames (data->frames() - remove);
481                 ct += ContentTime::from_frames (remove, stream->frame_rate());
482         }
483
484         if (ct < ContentTime()) {
485                 LOG_WARNING (
486                         "Crazy timestamp %1 for %2 samples in stream %3 (ts=%4 tb=%5, off=%6)",
487                         to_string(ct),
488                         data->frames(),
489                         stream->id(),
490                         _frame->best_effort_timestamp,
491                         av_q2d(stream->stream(_format_context)->time_base),
492                         to_string(_pts_offset)
493                         );
494         }
495
496         /* Give this data provided there is some, and its time is sane */
497         if (ct >= ContentTime() && data->frames() > 0) {
498                 audio->emit (film(), stream, data, ct);
499         }
500 }
501
502
503 void
504 FFmpegDecoder::decode_and_process_audio_packet (AVPacket* packet)
505 {
506         auto stream = audio_stream_from_index (packet->stream_index);
507         if (!stream) {
508                 return;
509         }
510
511         auto context = _codec_context[stream->index(_format_context)];
512
513         int r = avcodec_send_packet (context, packet);
514         if (r < 0) {
515                 /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen.
516                  * Likewise I think AVERROR_EOF should not happen.
517                  */
518                 if (_errors_to_ignore > 0) {
519                         /* We see errors here after a seek, which is hopefully to be nothing to worry about */
520                         --_errors_to_ignore;
521                         LOG_GENERAL("Ignoring error %1 avcodec_send_packet after seek; will ignore %2 more", r, _errors_to_ignore);
522                         return;
523                 }
524                 throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_audio_packet"), r);
525         }
526
527         while (r >= 0) {
528                 r = avcodec_receive_frame (context, _frame);
529                 if (r == AVERROR(EAGAIN)) {
530                         /* More input is required */
531                         return;
532                 }
533
534                 /* We choose to be relaxed here about other errors; it seems that there may be valid
535                  * data to decode even if an error occurred.  #352 may be related (though this was
536                  * when we were using an old version of the FFmpeg API).
537                  */
538                 process_audio_frame (stream);
539         }
540 }
541
542
543 bool
544 FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet)
545 {
546         DCPOMATIC_ASSERT (_video_stream);
547
548         auto context = video_codec_context();
549
550         int r = avcodec_send_packet (context, packet);
551         if (r < 0 && !(r == AVERROR_EOF && !packet)) {
552                 /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen.
553                  * AVERROR_EOF can happen during flush if we've already sent a flush packet.
554                  */
555                 throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_video_packet"), r);
556         }
557
558         r = avcodec_receive_frame (context, _frame);
559         if (r == AVERROR(EAGAIN) || r == AVERROR_EOF || (r < 0 && !packet)) {
560                 /* More input is required, no more frames are coming, or we are flushing and there was
561                  * some error which we just want to ignore.
562                  */
563                 return false;
564         } else if (r < 0) {
565                 throw DecodeError (N_("avcodec_receive_frame"), N_("FFmpeg::decode_and_process_video_packet"), r);
566         }
567
568         /* We assume we'll only get one frame here, which I think is safe */
569
570         boost::mutex::scoped_lock lm (_filter_graphs_mutex);
571
572         shared_ptr<VideoFilterGraph> graph;
573
574         auto i = _filter_graphs.begin();
575         while (i != _filter_graphs.end() && !(*i)->can_process (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
576                 ++i;
577         }
578
579         if (i == _filter_graphs.end ()) {
580                 dcp::Fraction vfr (lrint(_ffmpeg_content->video_frame_rate().get() * 1000), 1000);
581                 graph = make_shared<VideoFilterGraph>(dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format, vfr);
582                 graph->setup (_ffmpeg_content->filters ());
583                 _filter_graphs.push_back (graph);
584                 LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format);
585         } else {
586                 graph = *i;
587         }
588
589         auto images = graph->process (_frame);
590
591         for (auto const& i: images) {
592
593                 auto image = i.first;
594
595                 if (i.second != AV_NOPTS_VALUE) {
596                         double const pts = i.second * av_q2d(_format_context->streams[_video_stream.get()]->time_base) + _pts_offset.seconds();
597
598                         video->emit (
599                                 film(),
600                                 make_shared<RawImageProxy>(image),
601                                 llrint(pts * _ffmpeg_content->active_video_frame_rate(film()))
602                                 );
603                 } else {
604                         LOG_WARNING_NC ("Dropping frame without PTS");
605                 }
606         }
607
608         return true;
609 }
610
611
612 void
613 FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet)
614 {
615         int got_subtitle;
616         AVSubtitle sub;
617         if (avcodec_decode_subtitle2 (subtitle_codec_context(), &sub, &got_subtitle, packet) < 0 || !got_subtitle) {
618                 return;
619         }
620
621         auto sub_period = subtitle_period (packet, ffmpeg_content()->subtitle_stream()->stream(_format_context), sub);
622
623         /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
624         if (_have_current_subtitle) {
625                 if (_current_subtitle_to) {
626                         only_text()->emit_stop (min(*_current_subtitle_to, sub_period.from + _pts_offset));
627                 } else {
628                         only_text()->emit_stop (sub_period.from + _pts_offset);
629                 }
630                 _have_current_subtitle = false;
631         }
632
633         if (sub.num_rects <= 0) {
634                 /* Nothing new in this subtitle */
635                 avsubtitle_free (&sub);
636                 return;
637         }
638
639         /* Subtitle PTS (within the source, not taking into account any of the
640            source that we may have chopped off for the DCP).
641         */
642         ContentTime from;
643         from = sub_period.from + _pts_offset;
644         if (sub_period.to) {
645                 _current_subtitle_to = *sub_period.to + _pts_offset;
646         } else {
647                 _current_subtitle_to = optional<ContentTime>();
648                 _have_current_subtitle = true;
649         }
650
651         for (unsigned int i = 0; i < sub.num_rects; ++i) {
652                 auto const rect = sub.rects[i];
653
654                 switch (rect->type) {
655                 case SUBTITLE_NONE:
656                         break;
657                 case SUBTITLE_BITMAP:
658                         process_bitmap_subtitle (rect, from);
659                         break;
660                 case SUBTITLE_TEXT:
661                         cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n";
662                         break;
663                 case SUBTITLE_ASS:
664                         process_ass_subtitle (rect->ass, from);
665                         break;
666                 }
667         }
668
669         if (_current_subtitle_to) {
670                 only_text()->emit_stop (*_current_subtitle_to);
671         }
672
673         avsubtitle_free (&sub);
674 }
675
676
677 void
678 FFmpegDecoder::process_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime from)
679 {
680         /* Note BGRA is expressed little-endian, so the first byte in the word is B, second
681            G, third R, fourth A.
682         */
683         auto image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), Image::Alignment::PADDED);
684
685 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
686         /* Start of the first line in the subtitle */
687         auto sub_p = rect->pict.data[0];
688         /* sub_p looks up into a BGRA palette which is at rect->pict.data[1];
689            (i.e. first byte B, second G, third R, fourth A)
690         */
691         auto const palette = rect->pict.data[1];
692 #else
693         /* Start of the first line in the subtitle */
694         auto sub_p = rect->data[0];
695         /* sub_p looks up into a BGRA palette which is at rect->data[1].
696            (first byte B, second G, third R, fourth A)
697         */
698         auto const* palette = rect->data[1];
699 #endif
700         /* And the stream has a map of those palette colours to colours
701            chosen by the user; created a `mapped' palette from those settings.
702         */
703         auto colour_map = ffmpeg_content()->subtitle_stream()->colours();
704         vector<RGBA> mapped_palette (rect->nb_colors);
705         for (int i = 0; i < rect->nb_colors; ++i) {
706                 RGBA c (palette[2], palette[1], palette[0], palette[3]);
707                 auto j = colour_map.find (c);
708                 if (j != colour_map.end ()) {
709                         mapped_palette[i] = j->second;
710                 } else {
711                         /* This colour was not found in the FFmpegSubtitleStream's colour map; probably because
712                            it is from a project that was created before this stuff was added.  Just use the
713                            colour straight from the original palette.
714                         */
715                         mapped_palette[i] = c;
716                 }
717                 palette += 4;
718         }
719
720         /* Start of the output data */
721         auto out_p = image->data()[0];
722
723         for (int y = 0; y < rect->h; ++y) {
724                 auto sub_line_p = sub_p;
725                 auto out_line_p = out_p;
726                 for (int x = 0; x < rect->w; ++x) {
727                         auto const p = mapped_palette[*sub_line_p++];
728                         *out_line_p++ = p.b;
729                         *out_line_p++ = p.g;
730                         *out_line_p++ = p.r;
731                         *out_line_p++ = p.a;
732                 }
733 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
734                 sub_p += rect->pict.linesize[0];
735 #else
736                 sub_p += rect->linesize[0];
737 #endif
738                 out_p += image->stride()[0];
739         }
740
741         int target_width = subtitle_codec_context()->width;
742         if (target_width == 0 && video_codec_context()) {
743                 /* subtitle_codec_context()->width == 0 has been seen in the wild but I don't
744                    know if it's supposed to mean something from FFmpeg's point of view.
745                 */
746                 target_width = video_codec_context()->width;
747         }
748         int target_height = subtitle_codec_context()->height;
749         if (target_height == 0 && video_codec_context()) {
750                 target_height = video_codec_context()->height;
751         }
752         DCPOMATIC_ASSERT (target_width);
753         DCPOMATIC_ASSERT (target_height);
754         dcpomatic::Rect<double> const scaled_rect (
755                 static_cast<double>(rect->x) / target_width,
756                 static_cast<double>(rect->y) / target_height,
757                 static_cast<double>(rect->w) / target_width,
758                 static_cast<double>(rect->h) / target_height
759                 );
760
761         only_text()->emit_bitmap_start (from, image, scaled_rect);
762 }
763
764
765 void
766 FFmpegDecoder::process_ass_subtitle (string ass, ContentTime from)
767 {
768         /* We have no styles and no Format: line, so I'm assuming that FFmpeg
769            produces a single format of Dialogue: lines...
770         */
771
772         int commas = 0;
773         string text;
774         for (size_t i = 0; i < ass.length(); ++i) {
775                 if (commas < 9 && ass[i] == ',') {
776                         ++commas;
777                 } else if (commas == 9) {
778                         text += ass[i];
779                 }
780         }
781
782         if (text.empty ()) {
783                 return;
784         }
785
786         sub::RawSubtitle base;
787         auto raw = sub::SSAReader::parse_line (
788                 base,
789                 text,
790                 _ffmpeg_content->video->size().width,
791                 _ffmpeg_content->video->size().height
792                 );
793
794         for (auto const& i: sub::collect<vector<sub::Subtitle>>(raw)) {
795                 only_text()->emit_plain_start (from, i);
796         }
797 }