Clarify one log message and add another.
[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
22 /** @file  src/ffmpeg_decoder.cc
23  *  @brief A decoder using FFmpeg to decode content.
24  */
25
26
27 #include "audio_buffers.h"
28 #include "audio_content.h"
29 #include "audio_decoder.h"
30 #include "compose.hpp"
31 #include "dcpomatic_log.h"
32 #include "exceptions.h"
33 #include "ffmpeg_audio_stream.h"
34 #include "ffmpeg_content.h"
35 #include "ffmpeg_decoder.h"
36 #include "ffmpeg_subtitle_stream.h"
37 #include "film.h"
38 #include "filter.h"
39 #include "frame_interval_checker.h"
40 #include "image.h"
41 #include "log.h"
42 #include "raw_image_proxy.h"
43 #include "text_content.h"
44 #include "text_decoder.h"
45 #include "util.h"
46 #include "video_decoder.h"
47 #include "video_filter_graph.h"
48 #include <dcp/subtitle_string.h>
49 #include <sub/ssa_reader.h>
50 #include <sub/subtitle.h>
51 #include <sub/collect.h>
52 extern "C" {
53 #include <libavcodec/avcodec.h>
54 #include <libavformat/avformat.h>
55 }
56 #include <boost/algorithm/string.hpp>
57 #include <iomanip>
58 #include <iostream>
59 #include <vector>
60 #include <stdint.h>
61
62 #include "i18n.h"
63
64
65 using std::cout;
66 using std::dynamic_pointer_cast;
67 using std::make_shared;
68 using std::min;
69 using std::shared_ptr;
70 using std::string;
71 using std::vector;
72 using boost::optional;
73 using dcp::Size;
74 using namespace dcpomatic;
75
76
77 FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> film, shared_ptr<const FFmpegContent> c, bool fast)
78         : FFmpeg (c)
79         , Decoder (film)
80         , _filter_graphs(c->filters(), dcp::Fraction(lrint(_ffmpeg_content->video_frame_rate().get_value_or(24) * 1000), 1000))
81 {
82         if (c->video && c->video->use()) {
83                 video = make_shared<VideoDecoder>(this, c);
84                 _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film));
85                 /* It doesn't matter what size or pixel format this is, it just needs to be black */
86                 _black_image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (128, 128), Image::Alignment::PADDED);
87                 _black_image->make_black ();
88         } else {
89                 _pts_offset = {};
90         }
91
92         if (c->audio) {
93                 audio = make_shared<AudioDecoder>(this, c->audio, fast);
94         }
95
96         if (c->only_text()) {
97                 text.push_back (make_shared<TextDecoder>(this, c->only_text()));
98                 /* XXX: we should be calling maybe_set_position() on this TextDecoder, but we can't easily find
99                  * the time of the first subtitle at this point.
100                  */
101         }
102
103         for (auto i: c->ffmpeg_audio_streams()) {
104                 _next_time[i] = boost::optional<dcpomatic::ContentTime>();
105         }
106 }
107
108
109 bool
110 FFmpegDecoder::flush ()
111 {
112         /* Flush video and audio once */
113
114         bool did_something = false;
115         if (video) {
116                 if (decode_and_process_video_packet(nullptr)) {
117                         did_something = true;
118                 }
119         }
120
121         for (auto i: ffmpeg_content()->ffmpeg_audio_streams()) {
122                 auto context = _codec_context[i->index(_format_context)];
123                 int r = avcodec_send_packet (context, nullptr);
124                 if (r < 0 && r != AVERROR_EOF) {
125                         /* EOF can happen if we've already sent a flush packet */
126                         throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::flush"), r);
127                 }
128                 r = avcodec_receive_frame (context, audio_frame(i));
129                 if (r >= 0) {
130                         process_audio_frame (i);
131                         did_something = true;
132                 }
133         }
134
135         if (did_something) {
136                 /* We want to be called again */
137                 return false;
138         }
139
140         /* Make sure all streams are the same length and round up to the next video frame */
141
142         auto const frc = film()->active_frame_rate_change(_ffmpeg_content->position());
143         ContentTime full_length (_ffmpeg_content->full_length(film()), frc);
144         full_length = full_length.ceil (frc.source);
145         if (video) {
146                 double const vfr = _ffmpeg_content->video_frame_rate().get();
147                 auto const f = full_length.frames_round (vfr);
148                 auto v = video->position(film()).get_value_or(ContentTime()).frames_round(vfr) + 1;
149                 while (v < f) {
150                         video->emit (film(), make_shared<const RawImageProxy>(_black_image), v);
151                         ++v;
152                 }
153         }
154
155         for (auto i: _ffmpeg_content->ffmpeg_audio_streams ()) {
156                 auto a = audio->stream_position(film(), i);
157                 /* Unfortunately if a is 0 that really means that we don't know the stream position since
158                    there has been no data on it since the last seek.  In this case we'll just do nothing
159                    here.  I'm not sure if that's the right idea.
160                 */
161                 if (a > ContentTime()) {
162                         while (a < full_length) {
163                                 auto to_do = min (full_length - a, ContentTime::from_seconds (0.1));
164                                 auto silence = make_shared<AudioBuffers>(i->channels(), to_do.frames_ceil (i->frame_rate()));
165                                 silence->make_silent ();
166                                 audio->emit (film(), i, silence, a, true);
167                                 a += to_do;
168                         }
169                 }
170         }
171
172         if (audio) {
173                 audio->flush ();
174         }
175
176         return true;
177 }
178
179
180 bool
181 FFmpegDecoder::pass ()
182 {
183         auto packet = av_packet_alloc();
184         DCPOMATIC_ASSERT (packet);
185
186         int r = av_read_frame (_format_context, packet);
187
188         /* AVERROR_INVALIDDATA can apparently be returned sometimes even when av_read_frame
189            has pretty-much succeeded (and hence generated data which should be processed).
190            Hence it makes sense to continue here in that case.
191         */
192         if (r < 0 && r != AVERROR_INVALIDDATA) {
193                 LOG_DEBUG_PLAYER("FFpmegDecoder::pass flushes because av_read_frame returned %1", r);
194                 if (r != AVERROR_EOF) {
195                         /* Maybe we should fail here, but for now we'll just finish off instead */
196                         char buf[256];
197                         av_strerror (r, buf, sizeof(buf));
198                         LOG_ERROR (N_("error on av_read_frame (%1) (%2)"), &buf[0], r);
199                 }
200
201                 av_packet_free (&packet);
202                 return flush ();
203         }
204
205         int const si = packet->stream_index;
206         auto fc = _ffmpeg_content;
207
208         if (_video_stream && si == _video_stream.get() && video && !video->ignore()) {
209                 decode_and_process_video_packet (packet);
210         } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !only_text()->ignore()) {
211                 decode_and_process_subtitle_packet (packet);
212         } else {
213                 decode_and_process_audio_packet (packet);
214         }
215
216         av_packet_free (&packet);
217         return false;
218 }
219
220
221 /** @param data pointer to array of pointers to buffers.
222  *  Only the first buffer will be used for non-planar data, otherwise there will be one per channel.
223  */
224 static
225 shared_ptr<AudioBuffers>
226 deinterleave_audio(shared_ptr<FFmpegAudioStream> stream, AVFrame* frame)
227 {
228         auto format = static_cast<AVSampleFormat>(frame->format);
229
230         /* XXX: can't we use swr_convert() to do the format conversion? */
231
232         int const channels = frame->channels;
233         int const frames = frame->nb_samples;
234         int const total_samples = frames * channels;
235         auto audio = make_shared<AudioBuffers>(channels, frames);
236         auto data = audio->data();
237
238         switch (format) {
239         case AV_SAMPLE_FMT_U8:
240         {
241                 auto p = reinterpret_cast<uint8_t *> (frame->data[0]);
242                 int sample = 0;
243                 int channel = 0;
244                 for (int i = 0; i < total_samples; ++i) {
245                         data[channel][sample] = float(*p++) / (1 << 23);
246
247                         ++channel;
248                         if (channel == channels) {
249                                 channel = 0;
250                                 ++sample;
251                         }
252                 }
253         }
254         break;
255
256         case AV_SAMPLE_FMT_S16:
257         {
258                 auto p = reinterpret_cast<int16_t *> (frame->data[0]);
259                 int sample = 0;
260                 int channel = 0;
261                 for (int i = 0; i < total_samples; ++i) {
262                         data[channel][sample] = float(*p++) / (1 << 15);
263
264                         ++channel;
265                         if (channel == channels) {
266                                 channel = 0;
267                                 ++sample;
268                         }
269                 }
270         }
271         break;
272
273         case AV_SAMPLE_FMT_S16P:
274         {
275                 auto p = reinterpret_cast<int16_t **> (frame->data);
276                 for (int i = 0; i < channels; ++i) {
277                         for (int j = 0; j < frames; ++j) {
278                                 data[i][j] = static_cast<float>(p[i][j]) / (1 << 15);
279                         }
280                 }
281         }
282         break;
283
284         case AV_SAMPLE_FMT_S32:
285         {
286                 auto p = reinterpret_cast<int32_t *> (frame->data[0]);
287                 int sample = 0;
288                 int channel = 0;
289                 for (int i = 0; i < total_samples; ++i) {
290                         data[channel][sample] = static_cast<float>(*p++) / 2147483648;
291
292                         ++channel;
293                         if (channel == channels) {
294                                 channel = 0;
295                                 ++sample;
296                         }
297                 }
298         }
299         break;
300
301         case AV_SAMPLE_FMT_S32P:
302         {
303                 auto p = reinterpret_cast<int32_t **> (frame->data);
304                 for (int i = 0; i < channels; ++i) {
305                         for (int j = 0; j < frames; ++j) {
306                                 data[i][j] = static_cast<float>(p[i][j]) / 2147483648;
307                         }
308                 }
309         }
310         break;
311
312         case AV_SAMPLE_FMT_FLT:
313         {
314                 auto p = reinterpret_cast<float*> (frame->data[0]);
315                 int sample = 0;
316                 int channel = 0;
317                 for (int i = 0; i < total_samples; ++i) {
318                         data[channel][sample] = *p++;
319
320                         ++channel;
321                         if (channel == channels) {
322                                 channel = 0;
323                                 ++sample;
324                         }
325                 }
326         }
327         break;
328
329         case AV_SAMPLE_FMT_FLTP:
330         {
331                 auto p = reinterpret_cast<float**> (frame->data);
332                 DCPOMATIC_ASSERT(channels <= stream->channels());
333                 /* Sometimes there aren't as many channels in the frame as in the stream */
334                 for (int i = 0; i < channels; ++i) {
335                         memcpy (data[i], p[i], frames * sizeof(float));
336                 }
337                 for (int i = channels; i < stream->channels(); ++i) {
338                         audio->make_silent (i);
339                 }
340         }
341         break;
342
343         default:
344                 throw DecodeError (String::compose(_("Unrecognised audio sample format (%1)"), static_cast<int>(format)));
345         }
346
347         return audio;
348 }
349
350
351 AVSampleFormat
352 FFmpegDecoder::audio_sample_format (shared_ptr<FFmpegAudioStream> stream) const
353 {
354         return static_cast<AVSampleFormat>(stream->stream(_format_context)->codecpar->format);
355 }
356
357
358 int
359 FFmpegDecoder::bytes_per_audio_sample (shared_ptr<FFmpegAudioStream> stream) const
360 {
361         return av_get_bytes_per_sample (audio_sample_format (stream));
362 }
363
364
365 void
366 FFmpegDecoder::seek (ContentTime time, bool accurate)
367 {
368         Decoder::seek (time, accurate);
369
370         /* If we are doing an `accurate' seek, we need to use pre-roll, as
371            we don't really know what the seek will give us.
372         */
373
374         auto pre_roll = accurate ? ContentTime::from_seconds (2) : ContentTime (0);
375         time -= pre_roll;
376
377         /* XXX: it seems debatable whether PTS should be used here...
378            http://www.mjbshaw.com/2012/04/seeking-in-ffmpeg-know-your-timestamp.html
379         */
380
381         optional<int> stream;
382
383         if (_video_stream) {
384                 stream = _video_stream;
385         } else {
386                 DCPOMATIC_ASSERT (_ffmpeg_content->audio);
387                 auto s = dynamic_pointer_cast<FFmpegAudioStream>(_ffmpeg_content->audio->stream());
388                 if (s) {
389                         stream = s->index (_format_context);
390                 }
391         }
392
393         DCPOMATIC_ASSERT (stream);
394
395         auto u = time - _pts_offset;
396         if (u < ContentTime ()) {
397                 u = ContentTime ();
398         }
399         av_seek_frame (
400                 _format_context,
401                 stream.get(),
402                 u.seconds() / av_q2d (_format_context->streams[stream.get()]->time_base),
403                 AVSEEK_FLAG_BACKWARD
404                 );
405
406         /* Force re-creation of filter graphs to reset them and hence to make sure
407            they don't have any pre-seek frames knocking about.
408         */
409         _filter_graphs.clear();
410
411         if (video_codec_context ()) {
412                 avcodec_flush_buffers (video_codec_context());
413         }
414
415         for (auto i: ffmpeg_content()->ffmpeg_audio_streams()) {
416                 avcodec_flush_buffers (_codec_context[i->index(_format_context)]);
417         }
418
419         if (subtitle_codec_context ()) {
420                 avcodec_flush_buffers (subtitle_codec_context ());
421         }
422
423         _have_current_subtitle = false;
424
425         for (auto& i: _next_time) {
426                 i.second = boost::optional<dcpomatic::ContentTime>();
427         }
428 }
429
430
431 shared_ptr<FFmpegAudioStream>
432 FFmpegDecoder::audio_stream_from_index (int index) const
433 {
434         /* XXX: inefficient */
435         auto streams = ffmpeg_content()->ffmpeg_audio_streams();
436         auto stream = streams.begin();
437         while (stream != streams.end() && !(*stream)->uses_index(_format_context, index)) {
438                 ++stream;
439         }
440
441         if (stream == streams.end ()) {
442                 return {};
443         }
444
445         return *stream;
446 }
447
448
449 void
450 FFmpegDecoder::process_audio_frame (shared_ptr<FFmpegAudioStream> stream)
451 {
452         auto frame = audio_frame (stream);
453         auto data = deinterleave_audio(stream, frame);
454
455         auto const time_base = stream->stream(_format_context)->time_base;
456
457         ContentTime ct;
458         if (frame->pts == AV_NOPTS_VALUE) {
459                 /* In some streams we see not every frame coming through with a timestamp; for those
460                    that have AV_NOPTS_VALUE we need to work out the timestamp ourselves.  This is
461                    particularly noticeable with TrueHD streams (see #1111).
462                    */
463                 if (_next_time[stream]) {
464                         ct = *_next_time[stream];
465                 }
466         } else {
467                 ct = ContentTime::from_seconds (
468                         frame->best_effort_timestamp *
469                         av_q2d(time_base))
470                         + _pts_offset;
471                 LOG_DEBUG_PLAYER(
472                         "Process audio with timestamp %1 (BET %2, timebase %3/%4, (PTS offset %5)",
473                         to_string(ct),
474                         frame->best_effort_timestamp,
475                         time_base.num,
476                         time_base.den,
477                         to_string(_pts_offset)
478                         );
479         }
480
481         _next_time[stream] = ct + ContentTime::from_frames(data->frames(), stream->frame_rate());
482
483         if (ct < ContentTime()) {
484                 /* Discard audio data that comes before time 0 */
485                 auto const remove = min (int64_t(data->frames()), (-ct).frames_ceil(double(stream->frame_rate())));
486                 data->move (data->frames() - remove, remove, 0);
487                 data->set_frames (data->frames() - remove);
488                 ct += ContentTime::from_frames (remove, stream->frame_rate());
489         }
490
491         if (ct < ContentTime()) {
492                 LOG_WARNING (
493                         "Crazy timestamp %1 for %2 samples in stream %3 (ts=%4 tb=%5, off=%6)",
494                         to_string(ct),
495                         data->frames(),
496                         stream->id(),
497                         frame->best_effort_timestamp,
498                         av_q2d(time_base),
499                         to_string(_pts_offset)
500                         );
501         }
502
503         /* Give this data provided there is some, and its time is sane */
504         if (ct >= ContentTime() && data->frames() > 0) {
505                 audio->emit (film(), stream, data, ct);
506         }
507 }
508
509
510 void
511 FFmpegDecoder::decode_and_process_audio_packet (AVPacket* packet)
512 {
513         auto stream = audio_stream_from_index (packet->stream_index);
514         if (!stream) {
515                 return;
516         }
517
518         auto context = _codec_context[stream->index(_format_context)];
519         auto frame = audio_frame (stream);
520
521         LOG_DEBUG_PLAYER("Send audio packet on stream %1", stream->index(_format_context));
522         int r = avcodec_send_packet (context, packet);
523         if (r < 0) {
524                 LOG_WARNING("avcodec_send_packet returned %1 for an audio packet", r);
525         }
526         while (r >= 0) {
527                 r = avcodec_receive_frame (context, frame);
528                 if (r == AVERROR(EAGAIN)) {
529                         /* More input is required */
530                         LOG_DEBUG_PLAYER_NC("EAGAIN after trying to receive audio frame");
531                         return;
532                 }
533
534                 /* We choose to be relaxed here about other errors; it seems that there may be valid
535                  * data to decode even if an error occurred.  #352 may be related (though this was
536                  * when we were using an old version of the FFmpeg API).
537                  */
538                 process_audio_frame (stream);
539         }
540 }
541
542
543 bool
544 FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet)
545 {
546         DCPOMATIC_ASSERT (_video_stream);
547
548         auto context = video_codec_context();
549
550         bool pending = false;
551         do {
552                 int r = avcodec_send_packet (context, packet);
553                 if (r < 0) {
554                         LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r);
555                 }
556
557                 /* EAGAIN means we should call avcodec_receive_frame and then re-send the same packet */
558                 pending = r == AVERROR(EAGAIN);
559
560                 while (true) {
561                         r = avcodec_receive_frame (context, _video_frame);
562                         if (r == AVERROR(EAGAIN) || r == AVERROR_EOF || (r < 0 && !packet)) {
563                                 /* More input is required, no more frames are coming, or we are flushing and there was
564                                  * some error which we just want to ignore.
565                                  */
566                                 return false;
567                         } else if (r < 0) {
568                                 throw DecodeError (N_("avcodec_receive_frame"), N_("FFmpeg::decode_and_process_video_packet"), r);
569                         }
570
571                         process_video_frame ();
572                 }
573         } while (pending);
574
575         return true;
576 }
577
578
579 void
580 FFmpegDecoder::process_video_frame ()
581 {
582         auto graph = _filter_graphs.get(dcp::Size(_video_frame->width, _video_frame->height), static_cast<AVPixelFormat>(_video_frame->format));
583         auto images = graph->process (_video_frame);
584
585         for (auto const& i: images) {
586
587                 auto image = i.first;
588
589                 if (i.second != AV_NOPTS_VALUE) {
590                         double const pts = i.second * av_q2d(_format_context->streams[_video_stream.get()]->time_base) + _pts_offset.seconds();
591
592                         video->emit (
593                                 film(),
594                                 make_shared<RawImageProxy>(image),
595                                 llrint(pts * _ffmpeg_content->active_video_frame_rate(film()))
596                                 );
597                 } else {
598                         LOG_WARNING_NC ("Dropping frame without PTS");
599                 }
600         }
601 }
602
603
604 void
605 FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet)
606 {
607         int got_subtitle;
608         AVSubtitle sub;
609         if (avcodec_decode_subtitle2 (subtitle_codec_context(), &sub, &got_subtitle, packet) < 0 || !got_subtitle) {
610                 return;
611         }
612
613         auto sub_period = subtitle_period (packet, ffmpeg_content()->subtitle_stream()->stream(_format_context), sub);
614
615         /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
616         if (_have_current_subtitle) {
617                 if (_current_subtitle_to) {
618                         only_text()->emit_stop (min(*_current_subtitle_to, sub_period.from + _pts_offset));
619                 } else {
620                         only_text()->emit_stop (sub_period.from + _pts_offset);
621                 }
622                 _have_current_subtitle = false;
623         }
624
625         if (sub.num_rects <= 0) {
626                 /* Nothing new in this subtitle */
627                 avsubtitle_free (&sub);
628                 return;
629         }
630
631         /* Subtitle PTS (within the source, not taking into account any of the
632            source that we may have chopped off for the DCP).
633         */
634         ContentTime from;
635         from = sub_period.from + _pts_offset;
636         if (sub_period.to) {
637                 _current_subtitle_to = *sub_period.to + _pts_offset;
638         } else {
639                 _current_subtitle_to = optional<ContentTime>();
640                 _have_current_subtitle = true;
641         }
642
643         ContentBitmapText bitmap_text(from);
644         for (unsigned int i = 0; i < sub.num_rects; ++i) {
645                 auto const rect = sub.rects[i];
646
647                 switch (rect->type) {
648                 case SUBTITLE_NONE:
649                         break;
650                 case SUBTITLE_BITMAP:
651                         bitmap_text.subs.push_back(process_bitmap_subtitle(rect));
652                         break;
653                 case SUBTITLE_TEXT:
654                         cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n";
655                         break;
656                 case SUBTITLE_ASS:
657                         process_ass_subtitle (rect->ass, from);
658                         break;
659                 }
660         }
661
662         if (!bitmap_text.subs.empty()) {
663                 only_text()->emit_bitmap_start(bitmap_text);
664         }
665
666         if (_current_subtitle_to) {
667                 only_text()->emit_stop (*_current_subtitle_to);
668         }
669
670         avsubtitle_free (&sub);
671 }
672
673
674 BitmapText
675 FFmpegDecoder::process_bitmap_subtitle (AVSubtitleRect const * rect)
676 {
677         /* Note BGRA is expressed little-endian, so the first byte in the word is B, second
678            G, third R, fourth A.
679         */
680         auto image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), Image::Alignment::PADDED);
681
682 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
683         /* Start of the first line in the subtitle */
684         auto sub_p = rect->pict.data[0];
685         /* sub_p looks up into a BGRA palette which is at rect->pict.data[1];
686            (i.e. first byte B, second G, third R, fourth A)
687         */
688         auto const palette = rect->pict.data[1];
689 #else
690         /* Start of the first line in the subtitle */
691         auto sub_p = rect->data[0];
692         /* sub_p looks up into a BGRA palette which is at rect->data[1].
693            (first byte B, second G, third R, fourth A)
694         */
695         auto const* palette = rect->data[1];
696 #endif
697         /* And the stream has a map of those palette colours to colours
698            chosen by the user; created a `mapped' palette from those settings.
699         */
700         auto colour_map = ffmpeg_content()->subtitle_stream()->colours();
701         vector<RGBA> mapped_palette (rect->nb_colors);
702         for (int i = 0; i < rect->nb_colors; ++i) {
703                 RGBA c (palette[2], palette[1], palette[0], palette[3]);
704                 auto j = colour_map.find (c);
705                 if (j != colour_map.end ()) {
706                         mapped_palette[i] = j->second;
707                 } else {
708                         /* This colour was not found in the FFmpegSubtitleStream's colour map; probably because
709                            it is from a project that was created before this stuff was added.  Just use the
710                            colour straight from the original palette.
711                         */
712                         mapped_palette[i] = c;
713                 }
714                 palette += 4;
715         }
716
717         /* Start of the output data */
718         auto out_p = image->data()[0];
719
720         for (int y = 0; y < rect->h; ++y) {
721                 auto sub_line_p = sub_p;
722                 auto out_line_p = out_p;
723                 for (int x = 0; x < rect->w; ++x) {
724                         auto const p = mapped_palette[*sub_line_p++];
725                         *out_line_p++ = p.b;
726                         *out_line_p++ = p.g;
727                         *out_line_p++ = p.r;
728                         *out_line_p++ = p.a;
729                 }
730 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
731                 sub_p += rect->pict.linesize[0];
732 #else
733                 sub_p += rect->linesize[0];
734 #endif
735                 out_p += image->stride()[0];
736         }
737
738         int target_width = subtitle_codec_context()->width;
739         if (target_width == 0 && video_codec_context()) {
740                 /* subtitle_codec_context()->width == 0 has been seen in the wild but I don't
741                    know if it's supposed to mean something from FFmpeg's point of view.
742                 */
743                 target_width = video_codec_context()->width;
744         }
745         int target_height = subtitle_codec_context()->height;
746         if (target_height == 0 && video_codec_context()) {
747                 target_height = video_codec_context()->height;
748         }
749         DCPOMATIC_ASSERT (target_width);
750         DCPOMATIC_ASSERT (target_height);
751         dcpomatic::Rect<double> const scaled_rect (
752                 static_cast<double>(rect->x) / target_width,
753                 static_cast<double>(rect->y) / target_height,
754                 static_cast<double>(rect->w) / target_width,
755                 static_cast<double>(rect->h) / target_height
756                 );
757
758         return { image, scaled_rect };
759 }
760
761
762 void
763 FFmpegDecoder::process_ass_subtitle (string ass, ContentTime from)
764 {
765         /* We have no styles and no Format: line, so I'm assuming that FFmpeg
766            produces a single format of Dialogue: lines...
767         */
768
769         int commas = 0;
770         string text;
771         for (size_t i = 0; i < ass.length(); ++i) {
772                 if (commas < 9 && ass[i] == ',') {
773                         ++commas;
774                 } else if (commas == 9) {
775                         text += ass[i];
776                 }
777         }
778
779         if (text.empty ()) {
780                 return;
781         }
782
783         sub::RawSubtitle base;
784         auto raw = sub::SSAReader::parse_line (
785                 base,
786                 text,
787                 _ffmpeg_content->video->size().width,
788                 _ffmpeg_content->video->size().height,
789                 sub::Colour(1, 1, 1)
790                 );
791
792         for (auto const& i: sub::collect<vector<sub::Subtitle>>(raw)) {
793                 only_text()->emit_plain_start (from, i);
794         }
795 }