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