X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=b050fc594a76f97ab72833c38792f62daf4f100d;hb=a5d004b0773f633401528392fc28e66d70e13ac8;hp=2f92b9b7c34aaa0ecd917c35693f4caf5015342e;hpb=0d786493ef12f2d9a6d8a27d2c47b67f2e00c333;p=dcpomatic.git diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 2f92b9b7c..b050fc594 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -42,6 +42,7 @@ #include "compose.hpp" #include "text_content.h" #include "audio_content.h" +#include "frame_interval_checker.h" #include #include #include @@ -50,7 +51,6 @@ extern "C" { #include #include } -#include #include #include #include @@ -67,11 +67,11 @@ using std::min; using std::pair; using std::max; using std::map; -using boost::shared_ptr; +using std::shared_ptr; using boost::is_any_of; using boost::split; using boost::optional; -using boost::dynamic_pointer_cast; +using std::dynamic_pointer_cast; using dcp::Size; using namespace dcpomatic; @@ -133,7 +133,7 @@ FFmpegDecoder::flush () } } - BOOST_FOREACH (shared_ptr i, _ffmpeg_content->ffmpeg_audio_streams ()) { + for (auto i: _ffmpeg_content->ffmpeg_audio_streams ()) { ContentTime a = audio->stream_position(film(), i); /* Unfortunately if a is 0 that really means that we don't know the stream position since there has been no data on it since the last seek. In this case we'll just do nothing @@ -144,7 +144,7 @@ FFmpegDecoder::flush () ContentTime to_do = min (full_length - a, ContentTime::from_seconds (0.1)); shared_ptr silence (new AudioBuffers (i->channels(), to_do.frames_ceil (i->frame_rate()))); silence->make_silent (); - audio->emit (film(), i, silence, a); + audio->emit (film(), i, silence, a, true); a += to_do; } } @@ -158,12 +158,6 @@ FFmpegDecoder::flush () bool FFmpegDecoder::pass () { -#ifdef DCPOMATIC_VARIANT_SWAROOP - if (_ffmpeg_content->encrypted() && !_ffmpeg_content->kdm()) { - return true; - } -#endif - int r = av_read_frame (_format_context, &_packet); /* AVERROR_INVALIDDATA can apparently be returned sometimes even when av_read_frame @@ -205,9 +199,14 @@ FFmpegDecoder::deinterleave_audio (shared_ptr stream) const { DCPOMATIC_ASSERT (bytes_per_audio_sample (stream)); +DCPOMATIC_DISABLE_WARNINGS int const size = av_samples_get_buffer_size ( 0, stream->stream(_format_context)->codec->channels, _frame->nb_samples, audio_sample_format (stream), 1 ); +DCPOMATIC_ENABLE_WARNINGS + + /* XXX: can't we just use _frame->nb_samples directly here? */ + /* XXX: can't we use swr_convert() to do the format conversion? */ /* Deinterleave and convert to float */ @@ -335,7 +334,9 @@ FFmpegDecoder::deinterleave_audio (shared_ptr stream) const AVSampleFormat FFmpegDecoder::audio_sample_format (shared_ptr stream) const { +DCPOMATIC_DISABLE_WARNINGS return stream->stream (_format_context)->codec->sample_fmt; +DCPOMATIC_ENABLE_WARNINGS } int @@ -397,15 +398,21 @@ FFmpegDecoder::seek (ContentTime time, bool accurate) avcodec_flush_buffers (video_codec_context()); } - BOOST_FOREACH (shared_ptr i, ffmpeg_content()->ffmpeg_audio_streams()) { +DCPOMATIC_DISABLE_WARNINGS + for (auto i: ffmpeg_content()->ffmpeg_audio_streams()) { avcodec_flush_buffers (i->stream(_format_context)->codec); } +DCPOMATIC_ENABLE_WARNINGS if (subtitle_codec_context ()) { avcodec_flush_buffers (subtitle_codec_context ()); } _have_current_subtitle = false; + + for (auto& i: _next_time) { + i = optional(); + } } void @@ -430,6 +437,7 @@ FFmpegDecoder::decode_audio_packet () return; } +DCPOMATIC_DISABLE_WARNINGS while (copy_packet.size > 0) { int frame_finished; @@ -454,12 +462,14 @@ FFmpegDecoder::decode_audio_packet () shared_ptr data = deinterleave_audio (*stream); ContentTime ct; - if (_frame->pts == AV_NOPTS_VALUE && _next_time[stream_index]) { + if (_frame->pts == AV_NOPTS_VALUE) { /* In some streams we see not every frame coming through with a timestamp; for those that have AV_NOPTS_VALUE we need to work out the timestamp ourselves. This is particularly noticeable with TrueHD streams (see #1111). */ - ct = *_next_time[stream_index]; + if (_next_time[stream_index]) { + ct = *_next_time[stream_index]; + } } else { ct = ContentTime::from_seconds ( av_frame_get_best_effort_timestamp (_frame) * @@ -489,6 +499,7 @@ FFmpegDecoder::decode_audio_packet () to_string(_pts_offset) ); } +DCPOMATIC_ENABLE_WARNINGS /* Give this data provided there is some, and its time is sane */ if (ct >= ContentTime() && data->frames() > 0) { @@ -507,9 +518,11 @@ FFmpegDecoder::decode_video_packet () DCPOMATIC_ASSERT (_video_stream); int frame_finished; +DCPOMATIC_DISABLE_WARNINGS if (avcodec_decode_video2 (video_codec_context(), _frame, &frame_finished, &_packet) < 0 || !frame_finished) { return false; } +DCPOMATIC_ENABLE_WARNINGS boost::mutex::scoped_lock lm (_filter_graphs_mutex); @@ -625,23 +638,23 @@ FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT /* 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 + /* sub_p looks up into a BGRA palette which is at rect->pict.data[1]; (i.e. first byte B, second G, third R, fourth A) */ - uint32_t const * palette = (uint32_t *) rect->pict.data[1]; + uint8_t const * palette = rect->pict.data[1]; #else /* Start of the first line in the subtitle */ uint8_t* sub_p = rect->data[0]; /* sub_p looks up into a BGRA palette which is at rect->data[1]. (first byte B, second G, third R, fourth A) */ + uint8_t const * palette = rect->data[1]; #endif /* And the stream has a map of those palette colours to colours chosen by the user; created a `mapped' palette from those settings. */ map colour_map = ffmpeg_content()->subtitle_stream()->colours (); vector mapped_palette (rect->nb_colors); - uint8_t const * palette = rect->data[1]; for (int i = 0; i < rect->nb_colors; ++i) { RGBA c (palette[2], palette[1], palette[0], palette[3]); map::const_iterator j = colour_map.find (c); @@ -730,7 +743,7 @@ FFmpegDecoder::decode_ass_subtitle (string ass, ContentTime from) _ffmpeg_content->video->size().height ); - BOOST_FOREACH (sub::Subtitle const & i, sub::collect > (raw)) { + for (auto const& i: sub::collect > (raw)) { only_text()->emit_plain_start (from, i); } }