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