X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_examiner.cc;h=bcc5a86a68dbe2b093b95f76702de22df1b64e2e;hb=4a4725e41bf4070969223f9c40885063c50e61d0;hp=4409526dc4872015897357ffa385a28259a6acf2;hpb=68f662ac50a00ad986e3bd258c3f7daac374ab26;p=dcpomatic.git diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 4409526dc..bcc5a86a6 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -20,6 +20,8 @@ extern "C" { #include #include +#include +#include } #include "ffmpeg_examiner.h" #include "ffmpeg_content.h" @@ -40,6 +42,7 @@ using boost::optional; /** @param job job that the examiner is operating in, or 0 */ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptr job) : FFmpeg (c) + , _video_length (0) , _need_video_length (false) { /* Find audio and subtitle streams */ @@ -55,7 +58,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrcodec->channel_layout == 0) { s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels); } - + _audio_streams.push_back ( shared_ptr ( new FFmpegAudioStream (audio_stream_name (s), s->id, s->codec->sample_rate, s->codec->channels) @@ -70,12 +73,16 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrduration == AV_NOPTS_VALUE; if (!_need_video_length) { - _video_length = ContentTime::from_seconds (double (_format_context->duration) / AV_TIME_BASE); + _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get (); } else if (job) { job->sub (_("Finding length")); job->set_progress_unknown (); } + if (job) { + job->sub (_("Finding subtitles")); + } + /* Run through until we find: * - the first video. * - the first audio for each stream. @@ -91,12 +98,16 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrset_progress_unknown (); + } + AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec; if (_packet.stream_index == _video_stream) { video_packet (context); } - + for (size_t i = 0; i < _audio_streams.size(); ++i) { if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) { audio_packet (context, _audio_streams[i]); @@ -126,7 +137,9 @@ FFmpegExaminer::video_packet (AVCodecContext* context) _first_video = frame_time (_format_context->streams[_video_stream]); } if (_need_video_length) { - _video_length = frame_time (_format_context->streams[_video_stream]).get_value_or (ContentTime ()); + _video_length = frame_time ( + _format_context->streams[_video_stream] + ).get_value_or (ContentTime ()).frames (video_frame_rate().get ()); } } } @@ -150,13 +163,18 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr= 0 && frame_finished) { - ContentTimePeriod const period = subtitle_period (sub); - if (sub.num_rects == 0 && !stream->periods.empty () && stream->periods.back().to > period.from) { - /* Finish the last subtitle */ - stream->periods.back().to = period.from; + FFmpegSubtitlePeriod const period = subtitle_period (sub); + if (sub.num_rects <= 0 && _last_subtitle_start) { + stream->add_subtitle (ContentTimePeriod (_last_subtitle_start.get (), period.from)); + _last_subtitle_start = optional (); } else if (sub.num_rects == 1) { - stream->periods.push_back (period); + if (period.to) { + stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ())); + } else { + _last_subtitle_start = period.from; + } } + avsubtitle_free (&sub); } } @@ -164,7 +182,7 @@ optional FFmpegExaminer::frame_time (AVStream* s) const { optional t; - + int64_t const bet = av_frame_get_best_effort_timestamp (_frame); if (bet != AV_NOPTS_VALUE) { t = ContentTime::from_seconds (bet * av_q2d (s->time_base)); @@ -173,7 +191,7 @@ FFmpegExaminer::frame_time (AVStream* s) const return t; } -optional +optional FFmpegExaminer::video_frame_rate () const { /* This use of r_frame_rate is debateable; there's a few different @@ -190,22 +208,21 @@ FFmpegExaminer::video_size () const } /** @return Length according to our content's header */ -ContentTime +Frame FFmpegExaminer::video_length () const { - ContentTime const length = ContentTime::from_seconds (double (_format_context->duration) / AV_TIME_BASE); - return ContentTime (max (ContentTime (1), _video_length)); + return max (Frame (1), _video_length); } -optional +optional FFmpegExaminer::sample_aspect_ratio () const { AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream], 0); if (sar.num == 0) { /* I assume this means that we don't know */ - return optional (); + return optional (); } - return float (sar.num) / sar.den; + return double (sar.num) / sar.den; } string @@ -248,7 +265,7 @@ FFmpegExaminer::stream_name (AVStream* s) const if (lang) { n << lang->value; } - + AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0); if (title) { if (!n.str().empty()) { @@ -260,3 +277,9 @@ FFmpegExaminer::stream_name (AVStream* s) const return n.str (); } + +int +FFmpegExaminer::bits_per_pixel () const +{ + return av_get_bits_per_pixel (av_pix_fmt_desc_get (video_codec_context()->pix_fmt)); +}