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