From 2bfd531137f1a4874493186015046e33c5a07c1e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 12 May 2015 16:13:48 +0100 Subject: Assorted image subtitle fixes. --- src/lib/ffmpeg_decoder.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/lib/ffmpeg_decoder.h') diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 0334a30e2..b5bcdd358 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -27,6 +27,7 @@ #include "audio_decoder.h" #include "subtitle_decoder.h" #include "ffmpeg.h" +#include "rect.h" extern "C" { #include } @@ -66,7 +67,12 @@ private: void maybe_add_subtitle (); boost::shared_ptr deinterleave_audio (uint8_t** data, int size); - std::list subtitles_during (ContentTimePeriod, bool starting) const; + boost::optional _pending_subtitle_from; + boost::shared_ptr _pending_subtitle_image; + boost::optional > _pending_subtitle_rect; + + std::list image_subtitles_during (ContentTimePeriod, bool starting) const; + std::list text_subtitles_during (ContentTimePeriod, bool starting) const; boost::shared_ptr _log; -- cgit v1.2.3 From 83e5567530d0be24490abdda46d196e4279c5030 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 13 May 2015 00:41:50 +0100 Subject: Look up unknown subtitle end times from the data prepared by the examiner. --- src/lib/ffmpeg_content.cc | 15 +++---------- src/lib/ffmpeg_content.h | 2 +- src/lib/ffmpeg_decoder.cc | 46 +++++++++++++++------------------------ src/lib/ffmpeg_decoder.h | 4 ---- src/lib/ffmpeg_examiner.cc | 4 ++-- src/lib/ffmpeg_subtitle_stream.cc | 42 ++++++++++++++++++++++++++++++----- src/lib/ffmpeg_subtitle_stream.h | 9 ++++++-- src/lib/util.cc | 1 + 8 files changed, 68 insertions(+), 55 deletions(-) (limited to 'src/lib/ffmpeg_decoder.h') diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 3a42b169f..ad9096b92 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -377,21 +377,12 @@ FFmpegContent::audio_analysis_path () const list FFmpegContent::subtitles_during (ContentTimePeriod period, bool starting) const { - list d; - shared_ptr stream = subtitle_stream (); if (!stream) { - return d; - } - - /* XXX: inefficient */ - for (vector::const_iterator i = stream->periods.begin(); i != stream->periods.end(); ++i) { - if ((starting && period.contains (i->from)) || (!starting && period.overlaps (*i))) { - d.push_back (*i); - } + return list (); } - return d; + return stream->subtitles_during (period, starting); } bool diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 76ba43567..d6edb2bdb 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 5dc06fa8e..a3d647cde 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -426,35 +426,30 @@ FFmpegDecoder::decode_subtitle_packet () if (avcodec_decode_subtitle2 (subtitle_codec_context(), &sub, &got_subtitle, &_packet) < 0 || !got_subtitle) { return; } - - /* Subtitle PTS (within the source, not taking into account any of the - source that we may have chopped off for the DCP) - */ - FFmpegSubtitlePeriod period = subtitle_period (sub); - period.from += _pts_offset; - if (period.to) { - period.to = period.to.get() + _pts_offset; - } if (sub.num_rects <= 0) { /* Sometimes we get an empty AVSubtitle, which is used by some codecs to - indicate that the previous subtitle should stop. Emit the pending one. + indicate that the previous subtitle should stop. We can ignore it here. */ - if (_pending_subtitle_from && _pending_subtitle_image && _pending_subtitle_rect) { - image_subtitle ( - ContentTimePeriod (_pending_subtitle_from.get(), period.from), - _pending_subtitle_image, - _pending_subtitle_rect.get () - ); - _pending_subtitle_from = optional (); - _pending_subtitle_image.reset (); - _pending_subtitle_rect = optional > (); - } return; } else if (sub.num_rects > 1) { throw DecodeError (_("multi-part subtitles not yet supported")); } - + + /* Subtitle PTS (within the source, not taking into account any of the + source that we may have chopped off for the DCP). + */ + FFmpegSubtitlePeriod sub_period = subtitle_period (sub); + ContentTimePeriod period; + period.from = sub_period.from + _pts_offset; + if (sub_period.to) { + /* We already know the subtitle period `to' time */ + period.to = sub_period.to.get() + _pts_offset; + } else { + /* We have to look up the `to' time in the stream's records */ + period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (sub_period.from); + } + AVSubtitleRect const * rect = sub.rects[0]; if (rect->type != SUBTITLE_BITMAP) { @@ -494,14 +489,7 @@ FFmpegDecoder::decode_subtitle_packet () static_cast (rect->h) / vs.height ); - if (period.to) { - image_subtitle (ContentTimePeriod (period.from, period.to.get()), image, scaled_rect); - } else { - /* We don't know when this subtitle stops, so store it until we find out */ - _pending_subtitle_from = period.from; - _pending_subtitle_image = image; - _pending_subtitle_rect = scaled_rect; - } + image_subtitle (ContentTimePeriod (period.from, period.to), image, scaled_rect); avsubtitle_free (&sub); } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index b5bcdd358..0a0eea18a 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -67,10 +67,6 @@ private: void maybe_add_subtitle (); boost::shared_ptr deinterleave_audio (uint8_t** data, int size); - boost::optional _pending_subtitle_from; - boost::shared_ptr _pending_subtitle_image; - boost::optional > _pending_subtitle_rect; - std::list image_subtitles_during (ContentTimePeriod, bool starting) const; std::list text_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index e4f4e6f29..8afd4c164 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -152,11 +152,11 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr= 0 && frame_finished) { FFmpegSubtitlePeriod const period = subtitle_period (sub); if (sub.num_rects <= 0 && _last_subtitle_start) { - stream->periods.push_back (ContentTimePeriod (_last_subtitle_start.get (), period.from)); + stream->add_subtitle (ContentTimePeriod (_last_subtitle_start.get (), period.from)); _last_subtitle_start = optional (); } else if (sub.num_rects == 1) { if (period.to) { - stream->periods.push_back (ContentTimePeriod (period.from, period.to.get ())); + stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ())); } else { _last_subtitle_start = period.from; } diff --git a/src/lib/ffmpeg_subtitle_stream.cc b/src/lib/ffmpeg_subtitle_stream.cc index 66b587209..77a56e330 100644 --- a/src/lib/ffmpeg_subtitle_stream.cc +++ b/src/lib/ffmpeg_subtitle_stream.cc @@ -23,6 +23,8 @@ #include using std::string; +using std::map; +using std::list; /** Construct a SubtitleStream from a value returned from to_string(). * @param t String returned from to_string(). @@ -32,7 +34,7 @@ FFmpegSubtitleStream::FFmpegSubtitleStream (cxml::ConstNodePtr node) : FFmpegStream (node) { BOOST_FOREACH (cxml::NodePtr i, node->node_children ("Period")) { - periods.push_back ( + add_subtitle ( ContentTimePeriod ( ContentTime (node->number_child ("From")), ContentTime (node->number_child ("To")) @@ -46,9 +48,39 @@ FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const { FFmpegStream::as_xml (root); - BOOST_FOREACH (ContentTimePeriod const & i, periods) { - xmlpp::Node* node = root->add_child ("Period"); - node->add_child("From")->add_child_text (raw_convert (i.from.get ())); - node->add_child("To")->add_child_text (raw_convert (i.to.get ())); + for (map::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { + xmlpp::Node* node = root->add_child ("Subtitle"); + node->add_child("From")->add_child_text (raw_convert (i->first.get ())); + node->add_child("To")->add_child_text (raw_convert (i->second.get ())); } } + +void +FFmpegSubtitleStream::add_subtitle (ContentTimePeriod period) +{ + DCPOMATIC_ASSERT (_subtitles.find (period.from) == _subtitles.end ()); + _subtitles[period.from] = period.to; +} + +list +FFmpegSubtitleStream::subtitles_during (ContentTimePeriod period, bool starting) const +{ + list d; + + /* XXX: inefficient */ + for (map::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { + if ((starting && period.contains (i->first)) || (!starting && period.overlaps (ContentTimePeriod (i->first, i->second)))) { + d.push_back (ContentTimePeriod (i->first, i->second)); + } + } + + return d; +} + +ContentTime +FFmpegSubtitleStream::find_subtitle_to (ContentTime from) const +{ + map::const_iterator i = _subtitles.find (from); + DCPOMATIC_ASSERT (i != _subtitles.end ()); + return i->second; +} diff --git a/src/lib/ffmpeg_subtitle_stream.h b/src/lib/ffmpeg_subtitle_stream.h index b16b825e7..3ed931b8c 100644 --- a/src/lib/ffmpeg_subtitle_stream.h +++ b/src/lib/ffmpeg_subtitle_stream.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,11 @@ public: void as_xml (xmlpp::Node *) const; - std::vector periods; + void add_subtitle (ContentTimePeriod period); + std::list subtitles_during (ContentTimePeriod period, bool starting) const; + ContentTime find_subtitle_to (ContentTime from) const; + +private: + std::map _subtitles; }; diff --git a/src/lib/util.cc b/src/lib/util.cc index d8c754607..99d9ba2c4 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -670,3 +670,4 @@ write_frame_info (FILE* file, int frame, Eyes eyes, dcp::FrameInfo info) fwrite (&info.size, sizeof (info.size), 1, file); fwrite (info.hash.c_str(), 1, info.hash.size(), file); } + -- cgit v1.2.3 From 9922c1f2eaea674ba2ff6cce5f5853655fd8ad7a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 13 May 2015 10:15:26 +0100 Subject: Don't bother decoding video frames when we're seeking around trying to find subtitles. --- src/lib/audio_decoder.cc | 4 ++-- src/lib/dcp_decoder.cc | 2 +- src/lib/dcp_decoder.h | 3 ++- src/lib/dcp_subtitle_decoder.cc | 2 +- src/lib/dcp_subtitle_decoder.h | 2 +- src/lib/decoder.h | 12 ++++++++++-- src/lib/ffmpeg_decoder.cc | 9 +++++---- src/lib/ffmpeg_decoder.h | 2 +- src/lib/image_decoder.cc | 2 +- src/lib/image_decoder.h | 5 ++--- src/lib/sndfile_decoder.cc | 2 +- src/lib/sndfile_decoder.h | 5 ++--- src/lib/subrip_decoder.cc | 2 +- src/lib/subrip_decoder.h | 2 +- src/lib/subtitle_decoder.cc | 4 +++- src/lib/video_decoder.cc | 6 +++--- test/audio_decoder_test.cc | 2 +- 17 files changed, 38 insertions(+), 28 deletions(-) (limited to 'src/lib/ffmpeg_decoder.h') diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 22376e3e3..f6133947a 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -80,10 +80,10 @@ AudioDecoder::get_audio (AudioFrame frame, AudioFrame length, bool accurate) */ if (accurate) { /* Keep stuffing data into _decoded_audio until we have enough data, or the subclass does not want to give us any more */ - while ((_decoded_audio.frame > frame || (_decoded_audio.frame + _decoded_audio.audio->frames()) < end) && !pass ()) {} + while ((_decoded_audio.frame > frame || (_decoded_audio.frame + _decoded_audio.audio->frames()) < end) && !pass (PASS_REASON_AUDIO)) {} decoded_offset = frame - _decoded_audio.frame; } else { - while (_decoded_audio.audio->frames() < length && !pass ()) {} + while (_decoded_audio.audio->frames() < length && !pass (PASS_REASON_AUDIO)) {} /* Use decoded_offset of 0, as we don't really care what frames we return */ } diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index ab0df8a86..3bfbd7720 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -55,7 +55,7 @@ DCPDecoder::DCPDecoder (shared_ptr c) } bool -DCPDecoder::pass () +DCPDecoder::pass (PassReason) { if (_reel == _reels.end () || !_dcp_content->can_be_played ()) { return true; diff --git a/src/lib/dcp_decoder.h b/src/lib/dcp_decoder.h index 20ca2bb67..3a05325c7 100644 --- a/src/lib/dcp_decoder.h +++ b/src/lib/dcp_decoder.h @@ -38,8 +38,9 @@ public: DCPDecoder (boost::shared_ptr); private: + bool pass (PassReason); void seek (ContentTime t, bool accurate); - bool pass (); + std::list image_subtitles_during (ContentTimePeriod, bool starting) const; std::list text_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/dcp_subtitle_decoder.cc b/src/lib/dcp_subtitle_decoder.cc index 236e99996..93a122590 100644 --- a/src/lib/dcp_subtitle_decoder.cc +++ b/src/lib/dcp_subtitle_decoder.cc @@ -46,7 +46,7 @@ DCPSubtitleDecoder::seek (ContentTime time, bool accurate) } bool -DCPSubtitleDecoder::pass () +DCPSubtitleDecoder::pass (PassReason) { if (_next == _subtitles.end ()) { return true; diff --git a/src/lib/dcp_subtitle_decoder.h b/src/lib/dcp_subtitle_decoder.h index 9a16fb7c8..52e400416 100644 --- a/src/lib/dcp_subtitle_decoder.h +++ b/src/lib/dcp_subtitle_decoder.h @@ -28,8 +28,8 @@ public: DCPSubtitleDecoder (boost::shared_ptr); protected: + bool pass (PassReason); void seek (ContentTime time, bool accurate); - bool pass (); private: std::list image_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/decoder.h b/src/lib/decoder.h index c1b859865..0703a5426 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2013 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,6 +41,7 @@ public: virtual ~Decoder () {} protected: + /** Seek so that the next pass() will yield the next thing * (video/sound frame, subtitle etc.) at or after the requested * time. Pass accurate = true to try harder to ensure that, at worst, @@ -50,7 +51,14 @@ protected: * it may seek to just the right spot. */ virtual void seek (ContentTime time, bool accurate) = 0; - virtual bool pass () = 0; + + enum PassReason { + PASS_REASON_VIDEO, + PASS_REASON_AUDIO, + PASS_REASON_SUBTITLE + }; + + virtual bool pass (PassReason reason) = 0; }; #endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index a3d647cde..6122a547e 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -132,7 +132,7 @@ FFmpegDecoder::flush () } bool -FFmpegDecoder::pass () +FFmpegDecoder::pass (PassReason reason) { int r = av_read_frame (_format_context, &_packet); @@ -153,12 +153,13 @@ FFmpegDecoder::pass () } int const si = _packet.stream_index; + shared_ptr fc = _ffmpeg_content; - if (si == _video_stream && !_ignore_video) { + if (si == _video_stream && !_ignore_video && reason != PASS_REASON_SUBTITLE) { decode_video_packet (); - } else if (_ffmpeg_content->audio_stream() && _ffmpeg_content->audio_stream()->uses_index (_format_context, si)) { + } else if (fc->audio_stream() && fc->audio_stream()->uses_index (_format_context, si) && reason != PASS_REASON_SUBTITLE) { decode_audio_packet (); - } else if (_ffmpeg_content->subtitle_stream() && _ffmpeg_content->subtitle_stream()->uses_index (_format_context, si)) { + } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index (_format_context, si)) { decode_subtitle_packet (); } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 0a0eea18a..616fa88dd 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -53,8 +53,8 @@ public: private: friend struct ::ffmpeg_pts_offset_test; + bool pass (PassReason reason); void seek (ContentTime time, bool); - bool pass (); void flush (); AVSampleFormat audio_sample_format () const; diff --git a/src/lib/image_decoder.cc b/src/lib/image_decoder.cc index 78201fc23..250c8f845 100644 --- a/src/lib/image_decoder.cc +++ b/src/lib/image_decoder.cc @@ -43,7 +43,7 @@ ImageDecoder::ImageDecoder (shared_ptr c) } bool -ImageDecoder::pass () +ImageDecoder::pass (PassReason) { if (_video_position >= _image_content->video_length().frames (_image_content->video_frame_rate ())) { return true; diff --git a/src/lib/image_decoder.h b/src/lib/image_decoder.h index 242f69477..ec90051da 100644 --- a/src/lib/image_decoder.h +++ b/src/lib/image_decoder.h @@ -34,10 +34,9 @@ public: return _image_content; } - void seek (ContentTime, bool); - private: - bool pass (); + bool pass (PassReason); + void seek (ContentTime, bool); boost::shared_ptr _image_content; boost::shared_ptr _image; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 602014d58..09059a8b0 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -65,7 +65,7 @@ SndfileDecoder::~SndfileDecoder () } bool -SndfileDecoder::pass () +SndfileDecoder::pass (PassReason) { if (_remaining == 0) { return true; diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index 5ebe1da7b..68c8633a0 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -30,14 +30,13 @@ public: SndfileDecoder (boost::shared_ptr c); ~SndfileDecoder (); - void seek (ContentTime, bool); - int audio_channels () const; ContentTime audio_length () const; int audio_frame_rate () const; private: - bool pass (); + bool pass (PassReason); + void seek (ContentTime, bool); boost::shared_ptr _sndfile_content; SNDFILE* _sndfile; diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc index bef48ba78..6ed2e5254 100644 --- a/src/lib/subrip_decoder.cc +++ b/src/lib/subrip_decoder.cc @@ -48,7 +48,7 @@ SubRipDecoder::seek (ContentTime time, bool accurate) } bool -SubRipDecoder::pass () +SubRipDecoder::pass (PassReason) { if (_next >= _subtitles.size ()) { return true; diff --git a/src/lib/subrip_decoder.h b/src/lib/subrip_decoder.h index 876f763d3..264ca8899 100644 --- a/src/lib/subrip_decoder.h +++ b/src/lib/subrip_decoder.h @@ -32,7 +32,7 @@ public: protected: void seek (ContentTime time, bool accurate); - bool pass (); + bool pass (PassReason); private: std::list image_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc index ac9a67e33..edb291ab8 100644 --- a/src/lib/subtitle_decoder.cc +++ b/src/lib/subtitle_decoder.cc @@ -70,7 +70,7 @@ SubtitleDecoder::get (list const & subs, list const & sp, * (a) give us what we want, or * (b) hit the end of the decoder. */ - while (!pass() && (subs.empty() || (subs.back().period().to < sp.back().to))) {} + while (!pass(PASS_REASON_SUBTITLE) && (subs.empty() || (subs.back().period().to < sp.back().to))) {} /* Now look for what we wanted in the data we have collected */ /* XXX: inefficient */ @@ -82,6 +82,8 @@ SubtitleDecoder::get (list const & subs, list const & sp, } } + /* XXX: should clear out _decoded_* at some point */ + return out; } diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index b7cf1641b..31dc3cdc2 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -96,7 +96,7 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) break; } - if (pass ()) { + if (pass (PASS_REASON_VIDEO)) { /* The decoder has nothing more for us */ break; } @@ -113,7 +113,7 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) dec = decoded_video (frame); } else { /* Any frame will do: use the first one that comes out of pass() */ - while (_decoded_video.empty() && !pass ()) {} + while (_decoded_video.empty() && !pass (PASS_REASON_VIDEO)) {} if (!_decoded_video.empty ()) { dec.push_back (_decoded_video.front ()); } @@ -237,7 +237,7 @@ VideoDecoder::video (shared_ptr image, VideoFrame frame) if (_ignore_video) { return; } - + /* We may receive the same frame index twice for 3D, and we need to know when that happens. */ diff --git a/test/audio_decoder_test.cc b/test/audio_decoder_test.cc index a14e2f9be..b1f672356 100644 --- a/test/audio_decoder_test.cc +++ b/test/audio_decoder_test.cc @@ -40,7 +40,7 @@ public: , _position (0) {} - bool pass () + bool pass (PassReason) { AudioFrame const N = min ( AudioFrame (2000), -- cgit v1.2.3 From 419c025709132e21ce948c4a6051a323f06ee61d Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 13 May 2015 23:38:49 +0100 Subject: Token effort toward non-bitmap subtitles from FFmpegDecoder. --- src/lib/ffmpeg_decoder.cc | 53 ++++++++++++++++++++++++++++++----------------- src/lib/ffmpeg_decoder.h | 2 ++ 2 files changed, 36 insertions(+), 19 deletions(-) (limited to 'src/lib/ffmpeg_decoder.h') diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 6122a547e..35e15a331 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -453,15 +453,43 @@ FFmpegDecoder::decode_subtitle_packet () AVSubtitleRect const * rect = sub.rects[0]; - if (rect->type != SUBTITLE_BITMAP) { - throw DecodeError (_("non-bitmap subtitles not yet supported")); + switch (rect->type) { + case SUBTITLE_NONE: + break; + case SUBTITLE_BITMAP: + decode_bitmap_subtitle (rect, period); + break; + case SUBTITLE_TEXT: + cout << "XXX: SUBTITLE_TEXT " << rect->text << "\n"; + break; + case SUBTITLE_ASS: + cout << "XXX: SUBTITLE_ASS " << rect->ass << "\n"; + break; } + + avsubtitle_free (&sub); +} + +list +FFmpegDecoder::image_subtitles_during (ContentTimePeriod p, bool starting) const +{ + return _ffmpeg_content->subtitles_during (p, starting); +} +list +FFmpegDecoder::text_subtitles_during (ContentTimePeriod, bool) const +{ + return list (); +} + +void +FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTimePeriod period) +{ /* Note RGBA is expressed little-endian, so the first byte in the word is R, second G, third B, fourth A. */ shared_ptr image (new Image (PIX_FMT_RGBA, dcp::Size (rect->w, rect->h), true)); - + /* Start of the first line in the subtitle */ uint8_t* sub_p = rect->pict.data[0]; /* sub_p looks up into a BGRA palette which is here @@ -470,7 +498,7 @@ FFmpegDecoder::decode_subtitle_packet () uint32_t const * palette = (uint32_t *) rect->pict.data[1]; /* Start of the output data */ uint32_t* out_p = (uint32_t *) image->data()[0]; - + for (int y = 0; y < rect->h; ++y) { uint8_t* sub_line_p = sub_p; uint32_t* out_line_p = out_p; @@ -481,7 +509,7 @@ FFmpegDecoder::decode_subtitle_packet () sub_p += rect->pict.linesize[0]; out_p += image->stride()[0] / sizeof (uint32_t); } - + dcp::Size const vs = _ffmpeg_content->video_size (); dcpomatic::Rect const scaled_rect ( static_cast (rect->x) / vs.width, @@ -489,20 +517,7 @@ FFmpegDecoder::decode_subtitle_packet () static_cast (rect->w) / vs.width, static_cast (rect->h) / vs.height ); - - image_subtitle (ContentTimePeriod (period.from, period.to), image, scaled_rect); - avsubtitle_free (&sub); -} - -list -FFmpegDecoder::image_subtitles_during (ContentTimePeriod p, bool starting) const -{ - return _ffmpeg_content->subtitles_during (p, starting); + image_subtitle (period, image, scaled_rect); } -list -FFmpegDecoder::text_subtitles_during (ContentTimePeriod, bool) const -{ - return list (); -} diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 616fa88dd..6f027ce1c 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -64,6 +64,8 @@ private: void decode_audio_packet (); void decode_subtitle_packet (); + void decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTimePeriod period); + void maybe_add_subtitle (); boost::shared_ptr deinterleave_audio (uint8_t** data, int size); -- cgit v1.2.3