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