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