Basics of allowing video parts of FFmpegContent to be disabled (#1355 and others).
[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()).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                 shared_ptr<FFmpegAudioStream> s = dynamic_pointer_cast<FFmpegAudioStream> (_ffmpeg_content->audio->stream ());
368                 if (s) {
369                         stream = s->index (_format_context);
370                 }
371         }
372
373         DCPOMATIC_ASSERT (stream);
374
375         ContentTime u = time - _pts_offset;
376         if (u < ContentTime ()) {
377                 u = ContentTime ();
378         }
379         av_seek_frame (
380                 _format_context,
381                 stream.get(),
382                 u.seconds() / av_q2d (_format_context->streams[stream.get()]->time_base),
383                 AVSEEK_FLAG_BACKWARD
384                 );
385
386         {
387                 /* Force re-creation of filter graphs to reset them and hence to make sure
388                    they don't have any pre-seek frames knocking about.
389                 */
390                 boost::mutex::scoped_lock lm (_filter_graphs_mutex);
391                 _filter_graphs.clear ();
392         }
393
394         if (video_codec_context ()) {
395                 avcodec_flush_buffers (video_codec_context());
396         }
397
398         BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, ffmpeg_content()->ffmpeg_audio_streams()) {
399                 avcodec_flush_buffers (i->stream(_format_context)->codec);
400         }
401
402         if (subtitle_codec_context ()) {
403                 avcodec_flush_buffers (subtitle_codec_context ());
404         }
405
406         _have_current_subtitle = false;
407 }
408
409 void
410 FFmpegDecoder::decode_audio_packet ()
411 {
412         /* Audio packets can contain multiple frames, so we may have to call avcodec_decode_audio4
413            several times.
414         */
415
416         AVPacket copy_packet = _packet;
417         int const stream_index = copy_packet.stream_index;
418
419         /* XXX: inefficient */
420         vector<shared_ptr<FFmpegAudioStream> > streams = ffmpeg_content()->ffmpeg_audio_streams ();
421         vector<shared_ptr<FFmpegAudioStream> >::const_iterator stream = streams.begin ();
422         while (stream != streams.end () && !(*stream)->uses_index (_format_context, stream_index)) {
423                 ++stream;
424         }
425
426         if (stream == streams.end ()) {
427                 /* The packet's stream may not be an audio one; just ignore it in this method if so */
428                 return;
429         }
430
431         while (copy_packet.size > 0) {
432
433                 int frame_finished;
434                 int decode_result = avcodec_decode_audio4 ((*stream)->stream (_format_context)->codec, _frame, &frame_finished, &copy_packet);
435                 if (decode_result < 0) {
436                         /* avcodec_decode_audio4 can sometimes return an error even though it has decoded
437                            some valid data; for example dca_subframe_footer can return AVERROR_INVALIDDATA
438                            if it overreads the auxiliary data.  ffplay carries on if frame_finished is true,
439                            even in the face of such an error, so I think we should too.
440
441                            Returning from the method here caused mantis #352.
442                         */
443                         LOG_WARNING ("avcodec_decode_audio4 failed (%1)", decode_result);
444
445                         /* Fudge decode_result so that we come out of the while loop when
446                            we've processed this data.
447                         */
448                         decode_result = copy_packet.size;
449                 }
450
451                 if (frame_finished) {
452                         shared_ptr<AudioBuffers> data = deinterleave_audio (*stream);
453
454                         ContentTime ct;
455                         if (_frame->pts == AV_NOPTS_VALUE && _next_time[stream_index]) {
456                                 /* In some streams we see not every frame coming through with a timestamp; for those
457                                    that have AV_NOPTS_VALUE we need to work out the timestamp ourselves.  This is
458                                    particularly noticeable with TrueHD streams (see #1111).
459                                 */
460                                 ct = *_next_time[stream_index];
461                         } else {
462                                 ct = ContentTime::from_seconds (
463                                         av_frame_get_best_effort_timestamp (_frame) *
464                                         av_q2d ((*stream)->stream (_format_context)->time_base))
465                                         + _pts_offset;
466                         }
467
468                         _next_time[stream_index] = ct + ContentTime::from_frames(data->frames(), (*stream)->frame_rate());
469
470                         if (ct < ContentTime ()) {
471                                 /* Discard audio data that comes before time 0 */
472                                 Frame const remove = min (int64_t (data->frames()), (-ct).frames_ceil(double((*stream)->frame_rate ())));
473                                 data->move (data->frames() - remove, remove, 0);
474                                 data->set_frames (data->frames() - remove);
475                                 ct += ContentTime::from_frames (remove, (*stream)->frame_rate ());
476                         }
477
478                         if (ct < ContentTime()) {
479                                 LOG_WARNING (
480                                         "Crazy timestamp %1 for %2 samples in stream %3 packet pts %4 (ts=%5 tb=%6, off=%7)",
481                                         to_string(ct),
482                                         data->frames(),
483                                         copy_packet.stream_index,
484                                         copy_packet.pts,
485                                         av_frame_get_best_effort_timestamp(_frame),
486                                         av_q2d((*stream)->stream(_format_context)->time_base),
487                                         to_string(_pts_offset)
488                                         );
489                         }
490
491                         /* Give this data provided there is some, and its time is sane */
492                         if (ct >= ContentTime() && data->frames() > 0) {
493                                 audio->emit (film(), *stream, data, ct);
494                         }
495                 }
496
497                 copy_packet.data += decode_result;
498                 copy_packet.size -= decode_result;
499         }
500 }
501
502 bool
503 FFmpegDecoder::decode_video_packet ()
504 {
505         DCPOMATIC_ASSERT (_video_stream);
506
507         int frame_finished;
508         if (avcodec_decode_video2 (video_codec_context(), _frame, &frame_finished, &_packet) < 0 || !frame_finished) {
509                 return false;
510         }
511
512         boost::mutex::scoped_lock lm (_filter_graphs_mutex);
513
514         shared_ptr<VideoFilterGraph> graph;
515
516         list<shared_ptr<VideoFilterGraph> >::iterator i = _filter_graphs.begin();
517         while (i != _filter_graphs.end() && !(*i)->can_process (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) {
518                 ++i;
519         }
520
521         if (i == _filter_graphs.end ()) {
522                 dcp::Fraction vfr (lrint(_ffmpeg_content->video_frame_rate().get() * 1000), 1000);
523                 graph.reset (new VideoFilterGraph (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format, vfr));
524                 graph->setup (_ffmpeg_content->filters ());
525                 _filter_graphs.push_back (graph);
526                 LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format);
527         } else {
528                 graph = *i;
529         }
530
531         list<pair<shared_ptr<Image>, int64_t> > images = graph->process (_frame);
532
533         for (list<pair<shared_ptr<Image>, int64_t> >::iterator i = images.begin(); i != images.end(); ++i) {
534
535                 shared_ptr<Image> image = i->first;
536
537                 if (i->second != AV_NOPTS_VALUE) {
538                         double const pts = i->second * av_q2d (_format_context->streams[_video_stream.get()]->time_base) + _pts_offset.seconds ();
539
540                         video->emit (
541                                 film(),
542                                 shared_ptr<ImageProxy> (new RawImageProxy (image)),
543                                 llrint(pts * _ffmpeg_content->active_video_frame_rate(film()))
544                                 );
545                 } else {
546                         LOG_WARNING_NC ("Dropping frame without PTS");
547                 }
548         }
549
550         return true;
551 }
552
553 void
554 FFmpegDecoder::decode_subtitle_packet ()
555 {
556         int got_subtitle;
557         AVSubtitle sub;
558         if (avcodec_decode_subtitle2 (subtitle_codec_context(), &sub, &got_subtitle, &_packet) < 0 || !got_subtitle) {
559                 return;
560         }
561
562         /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
563         if (_have_current_subtitle) {
564                 if (_current_subtitle_to) {
565                         only_text()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset));
566                 } else {
567                         only_text()->emit_stop (subtitle_period(sub).from + _pts_offset);
568                 }
569                 _have_current_subtitle = false;
570         }
571
572         if (sub.num_rects <= 0) {
573                 /* Nothing new in this subtitle */
574                 return;
575         }
576
577         /* Subtitle PTS (within the source, not taking into account any of the
578            source that we may have chopped off for the DCP).
579         */
580         FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
581         ContentTime from;
582         from = sub_period.from + _pts_offset;
583         if (sub_period.to) {
584                 _current_subtitle_to = *sub_period.to + _pts_offset;
585         } else {
586                 _current_subtitle_to = optional<ContentTime>();
587                 _have_current_subtitle = true;
588         }
589
590         for (unsigned int i = 0; i < sub.num_rects; ++i) {
591                 AVSubtitleRect const * rect = sub.rects[i];
592
593                 switch (rect->type) {
594                 case SUBTITLE_NONE:
595                         break;
596                 case SUBTITLE_BITMAP:
597                         decode_bitmap_subtitle (rect, from);
598                         break;
599                 case SUBTITLE_TEXT:
600                         cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n";
601                         break;
602                 case SUBTITLE_ASS:
603                         decode_ass_subtitle (rect->ass, from);
604                         break;
605                 }
606         }
607
608         if (_current_subtitle_to) {
609                 only_text()->emit_stop (*_current_subtitle_to);
610         }
611
612         avsubtitle_free (&sub);
613 }
614
615 void
616 FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime from)
617 {
618         /* Note BGRA is expressed little-endian, so the first byte in the word is B, second
619            G, third R, fourth A.
620         */
621         shared_ptr<Image> image (new Image (AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), true));
622
623 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
624         /* Start of the first line in the subtitle */
625         uint8_t* sub_p = rect->pict.data[0];
626         /* sub_p looks up into a BGRA palette which is here
627            (i.e. first byte B, second G, third R, fourth A)
628         */
629         uint32_t const * palette = (uint32_t *) rect->pict.data[1];
630 #else
631         /* Start of the first line in the subtitle */
632         uint8_t* sub_p = rect->data[0];
633         /* sub_p looks up into a BGRA palette which is here
634            (i.e. first byte B, second G, third R, fourth A)
635         */
636         uint32_t const * palette = (uint32_t *) rect->data[1];
637 #endif
638         /* And the stream has a map of those palette colours to colours
639            chosen by the user; created a `mapped' palette from those settings.
640         */
641         map<RGBA, RGBA> colour_map = ffmpeg_content()->subtitle_stream()->colours ();
642         vector<RGBA> mapped_palette (rect->nb_colors);
643         for (int i = 0; i < rect->nb_colors; ++i) {
644                 RGBA c ((palette[i] & 0xff0000) >> 16, (palette[i] & 0xff00) >> 8, palette[i] & 0xff, (palette[i] & 0xff000000) >> 24);
645                 map<RGBA, RGBA>::const_iterator j = colour_map.find (c);
646                 if (j != colour_map.end ()) {
647                         mapped_palette[i] = j->second;
648                 } else {
649                         /* This colour was not found in the FFmpegSubtitleStream's colour map; probably because
650                            it is from a project that was created before this stuff was added.  Just use the
651                            colour straight from the original palette.
652                         */
653                         mapped_palette[i] = c;
654                 }
655         }
656
657         /* Start of the output data */
658         uint32_t* out_p = (uint32_t *) image->data()[0];
659
660         for (int y = 0; y < rect->h; ++y) {
661                 uint8_t* sub_line_p = sub_p;
662                 uint32_t* out_line_p = out_p;
663                 for (int x = 0; x < rect->w; ++x) {
664                         RGBA const p = mapped_palette[*sub_line_p++];
665                         /* XXX: this seems to be wrong to me (isn't the output image BGRA?) but it looks right on screen */
666                         *out_line_p++ = (p.a << 24) | (p.b << 16) | (p.g << 8) | p.r;
667                 }
668 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
669                 sub_p += rect->pict.linesize[0];
670 #else
671                 sub_p += rect->linesize[0];
672 #endif
673                 out_p += image->stride()[0] / sizeof (uint32_t);
674         }
675
676         int target_width = subtitle_codec_context()->width;
677         if (target_width == 0 && video_codec_context()) {
678                 /* subtitle_codec_context()->width == 0 has been seen in the wild but I don't
679                    know if it's supposed to mean something from FFmpeg's point of view.
680                 */
681                 target_width = video_codec_context()->width;
682         }
683         int target_height = subtitle_codec_context()->height;
684         if (target_height == 0 && video_codec_context()) {
685                 target_height = video_codec_context()->height;
686         }
687         DCPOMATIC_ASSERT (target_width);
688         DCPOMATIC_ASSERT (target_height);
689         dcpomatic::Rect<double> const scaled_rect (
690                 static_cast<double> (rect->x) / target_width,
691                 static_cast<double> (rect->y) / target_height,
692                 static_cast<double> (rect->w) / target_width,
693                 static_cast<double> (rect->h) / target_height
694                 );
695
696         only_text()->emit_bitmap_start (from, image, scaled_rect);
697 }
698
699 void
700 FFmpegDecoder::decode_ass_subtitle (string ass, ContentTime from)
701 {
702         /* We have no styles and no Format: line, so I'm assuming that FFmpeg
703            produces a single format of Dialogue: lines...
704         */
705
706         int commas = 0;
707         string text;
708         for (size_t i = 0; i < ass.length(); ++i) {
709                 if (commas < 9 && ass[i] == ',') {
710                         ++commas;
711                 } else if (commas == 9) {
712                         text += ass[i];
713                 }
714         }
715
716         if (text.empty ()) {
717                 return;
718         }
719
720         sub::RawSubtitle base;
721         list<sub::RawSubtitle> raw = sub::SSAReader::parse_line (
722                 base,
723                 text,
724                 _ffmpeg_content->video->size().width,
725                 _ffmpeg_content->video->size().height
726                 );
727
728         BOOST_FOREACH (sub::Subtitle const & i, sub::collect<list<sub::Subtitle> > (raw)) {
729                 only_text()->emit_plain_start (from, i);
730         }
731 }