From 61fb35b79331041e980e726930f5ab3af2342f38 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 27 Oct 2022 22:22:07 +0200 Subject: [PATCH] wip: hacks --- src/lib/ffmpeg.cc | 5 ++-- src/lib/ffmpeg.h | 2 -- src/lib/ffmpeg_examiner.cc | 49 ++++++++++++++++++++++++++++------- src/lib/ffmpeg_examiner.h | 2 ++ src/lib/ffmpeg_video_stream.h | 36 +++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 src/lib/ffmpeg_video_stream.h diff --git a/src/lib/ffmpeg.cc b/src/lib/ffmpeg.cc index 6c8509b6c..14525c235 100644 --- a/src/lib/ffmpeg.cc +++ b/src/lib/ffmpeg.cc @@ -250,11 +250,12 @@ FFmpeg::setup_decoders () AVCodecContext * FFmpeg::video_codec_context () const { - if (!_video_stream) { + auto str = _ffmpeg_content->video_stream(); + if (!str) { return nullptr; } - return _codec_context[_video_stream.get()]; + return _codec_context[str->index(_format_context)]; } diff --git a/src/lib/ffmpeg.h b/src/lib/ffmpeg.h index 25d26e813..e407d5fb7 100644 --- a/src/lib/ffmpeg.h +++ b/src/lib/ffmpeg.h @@ -78,8 +78,6 @@ protected: /** AVFrame used for decoding video */ AVFrame* _video_frame = nullptr; - /** Index of video stream within AVFormatContext */ - boost::optional _video_stream; AVFrame* audio_frame (std::shared_ptr stream); diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index fdcacb465..2abeec493 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -66,12 +66,19 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrnb_streams; ++i) { auto s = _format_context->streams[i]; auto codec = _codec_context[i] ? _codec_context[i]->codec : nullptr; - if (s->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec) { + if (s->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + _video_streams.push_back( + make_shared( + stream_name(s), + s->id, + av_q2d(av_guess_frame_rate(_format_context, _format_context->streams[i], 0)) + )); + } else if (s->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec) { /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up, so bodge it here. No idea why we should have to do this. @@ -108,6 +115,30 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptr, int>; + vector streams_with_scores; + for (auto stream: _video_streams) { + auto s = stream->stream(_format_context); + auto const frame_rate = av_q2d(s->avg_frame_rate); + int score = 0; + if (1 < frame_rate && frame_rate < 1000) { + ++score; + } + if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) { + ++score; + } + streams_with_scores.push_back({stream, score}); + } + + streams_with_scores.sort([](ScoredStream const& a, ScoredStream const& b) { + return a.second > b.second; + }); + + if (!streams_with_scores.empty()) { + _best_video_stream = streams_with_scores[0].first; + } + if (job && _need_video_length) { job->sub (_("Finding length")); } @@ -143,7 +174,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrstream_index]; - if (_video_stream && packet->stream_index == _video_stream.get()) { + if (_best_video_stream && packet->stream_index == _best_video_stream->index(_format_context)) { video_packet (context, temporal_reference, packet); } @@ -166,8 +197,8 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrindex(_format_context)]; while (video_packet(context, temporal_reference, nullptr)) {} } @@ -176,9 +207,9 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptrstreams[*_video_stream]; + auto stream = _best_video_stream->stream(_format_context); auto rotate_tag = av_dict_get (stream->metadata, "rotate", 0, 0); uint8_t* displaymatrix = av_stream_get_side_data (stream, AV_PKT_DATA_DISPLAYMATRIX, 0); _rotation = 0; @@ -215,7 +246,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c, shared_ptr= (PULLDOWN_CHECK_FRAMES * 2)) { return false; @@ -467,7 +498,7 @@ FFmpegExaminer::yuv () const bool FFmpegExaminer::has_video () const { - return static_cast(_video_stream); + return !_video_streams.empty(); } diff --git a/src/lib/ffmpeg_examiner.h b/src/lib/ffmpeg_examiner.h index 10d060707..d129ca347 100644 --- a/src/lib/ffmpeg_examiner.h +++ b/src/lib/ffmpeg_examiner.h @@ -93,6 +93,8 @@ private: std::string subtitle_stream_name (AVStream* s) const; boost::optional frame_time (AVFrame* frame, AVStream* stream) const; + std::vector> _video_streams; + std::shared_ptr _best_video_stream; std::vector> _subtitle_streams; std::vector> _audio_streams; boost::optional _first_video; diff --git a/src/lib/ffmpeg_video_stream.h b/src/lib/ffmpeg_video_stream.h new file mode 100644 index 000000000..ea65388da --- /dev/null +++ b/src/lib/ffmpeg_video_stream.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2022 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "ffmpeg_stream.h" + + +class FFmpegVideoStream : public FFmpegStream +{ +public: + FFmpegVideoStream(std::string name, int id, float frame_rate) + : FFmpegStream(name, id) + , _frame_rate(frame_rate) + {} + +private: + float _frame_rate; +}; + -- 2.30.2