diff --git a/Source/Core/AudioStreamStats.cpp b/Source/Core/AudioStreamStats.cpp index 894e1d0e8..ebcfb6f31 100644 --- a/Source/Core/AudioStreamStats.cpp +++ b/Source/Core/AudioStreamStats.cpp @@ -59,15 +59,13 @@ AudioStreamStats::AudioStreamStats(XMLElement *streamElement) : CommonStreamStat bits_per_sample = std::stoi(bits_per_sample_value); } -AudioStreamStats::AudioStreamStats(QAVStream* stream, AVFormatContext *context) : CommonStreamStats(stream), +AudioStreamStats::AudioStreamStats(QAVStream* stream) : CommonStreamStats(stream), sample_fmt_string(""), sample_rate(stream != NULL ? stream->stream()->codecpar->sample_rate : 0), channels(stream != NULL ? stream->stream()->codecpar->channels : 0), channel_layout(""), bits_per_sample(stream != NULL ? av_get_bits_per_sample(stream->stream()->codecpar->codec_id) : 0) { - Q_UNUSED(context); - codec_type = "audio"; stream_type = AVMEDIA_TYPE_AUDIO; diff --git a/Source/Core/AudioStreamStats.h b/Source/Core/AudioStreamStats.h index dd7777367..14e10da1d 100644 --- a/Source/Core/AudioStreamStats.h +++ b/Source/Core/AudioStreamStats.h @@ -22,7 +22,7 @@ class AudioStreamStats : public CommonStreamStats { public: AudioStreamStats(tinyxml2::XMLElement* streamElement); - AudioStreamStats(QAVStream* stream, AVFormatContext *context); + AudioStreamStats(QAVStream* stream); virtual void writeStreamInfoToXML(QXmlStreamWriter* writer); diff --git a/Source/Core/CommonStreamStats.h b/Source/Core/CommonStreamStats.h index feae28494..958886247 100644 --- a/Source/Core/CommonStreamStats.h +++ b/Source/Core/CommonStreamStats.h @@ -17,7 +17,6 @@ namespace tinyxml2 { class XMLElement; } -struct AVFormatContext; class QAVStream; struct AVCodec; diff --git a/Source/Core/FileInformation.cpp b/Source/Core/FileInformation.cpp index 4b68071b9..7375b82ee 100644 --- a/Source/Core/FileInformation.cpp +++ b/Source/Core/FileInformation.cpp @@ -878,92 +878,70 @@ FileInformation::FileInformation (SignalServer* signalServer, const QString &Fil qDebug() << "m_mediaParser->currentVideoStreams(): " << m_mediaParser->currentVideoStreams().size(); qDebug() << "m_mediaParser->currentAudioStreams(): " << m_mediaParser->currentAudioStreams().size(); - auto streams = m_mediaParser->availableVideoStreams(); - streams.append(m_mediaParser->availableAudioStreams()); - - AVFormatContext* FormatContext = nullptr; - auto stdMediaFileName = mediaOrMkvReportFileName.toStdString(); - AVDictionary* options = nullptr; - if (dpxOffset != -1) { - auto dpxOffsetString = std::to_string(dpxOffset); - av_dict_set(&options, "f", "image2", 0); - av_dict_set(&options, "start_number", dpxOffsetString.c_str(), 0); - } - if (avformat_open_input(&FormatContext, stdMediaFileName.c_str(), nullptr, &options)>=0) - { - QVector orderedStreams; - if (avformat_find_stream_info(FormatContext, NULL)>=0) { - - containerFormat = FormatContext->iformat->long_name; - streamCount = FormatContext->nb_streams; - bitRate = FormatContext->bit_rate; - - size_t VideoPos=0; - size_t AudioPos=0; - - for(auto i = 0; i < FormatContext->nb_streams; ++i) { - auto codec_type = FormatContext->streams[i]->codecpar->codec_type; - if(codec_type != AVMEDIA_TYPE_VIDEO && codec_type != AVMEDIA_TYPE_AUDIO) - continue; - - auto streamIt = std::find_if(streams.begin(), streams.end(), [i](QAVStream& stream) { - return stream.stream()->index == i; - }); - - if(streamIt == streams.end()) { - qDebug() << "error: it should never happen"; - assert(false); - continue; - } + QVector streams; + streams.append(m_mediaParser->currentVideoStreams()); + streams.append(m_mediaParser->currentAudioStreams()); + + QVector orderedStreams; + for (int i = 0; i < streams.size(); ++i) { + if(streams[i].codec()->codec() == nullptr) { + qDebug() << "error: codec is null for stream" << streams[i].stream()->index << "... skipping"; + continue; + } - if(streamIt->codec()->codec() == nullptr) { - qDebug() << "error: codec is null for stream" << i << "... skipping"; - continue; - } - orderedStreams.append(&*streamIt); - - auto Duration = 0; - auto FrameCount = streamIt->stream()->nb_frames; - if (streamIt->stream()->duration != AV_NOPTS_VALUE) - Duration= ((double)streamIt->stream()->duration)*streamIt->stream()->time_base.num/streamIt->stream()->time_base.den; - - // If duration is not known, estimating it - if (Duration==0 && FormatContext->duration!=AV_NOPTS_VALUE) - Duration=((double)FormatContext->duration)/AV_TIME_BASE; - - // If frame count is not known, estimating it - if (FrameCount==0 && streamIt->stream()->avg_frame_rate.num && streamIt->stream()->avg_frame_rate.den && Duration) - FrameCount=Duration*streamIt->stream()->avg_frame_rate.num/streamIt->stream()->avg_frame_rate.den; - if (FrameCount==0 - && ((streamIt->stream()->time_base.num==1 && streamIt->stream()->time_base.den>=24 && streamIt->stream()->time_base.den<=60) - || (streamIt->stream()->time_base.num==1001 && streamIt->stream()->time_base.den>=24000 && streamIt->stream()->time_base.den<=60000))) - FrameCount=streamIt->stream()->duration; - - CommonStats* Stat = nullptr; - - if(streamIt->stream()->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (!VideoPos || ActiveAllTracks[Type_Video]) - Stat = new VideoStats(FrameCount, Duration, &*streamIt); - ++VideoPos; - } else if(streamIt->stream()->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (!AudioPos || ActiveAllTracks[Type_Audio]) - Stat = new AudioStats(FrameCount, Duration, &*streamIt); - ++AudioPos; - } + auto codec_type = streams[i].stream()->codecpar->codec_type; + if(codec_type != AVMEDIA_TYPE_VIDEO && codec_type != AVMEDIA_TYPE_AUDIO) + continue; - if (Stat) - Stats.push_back(Stat); - } + orderedStreams.append(&streams[i]); + } + std::sort(orderedStreams.begin(), orderedStreams.end(), [](QAVStream* a, QAVStream* b) { + return a->stream()->index < b->stream()->index; + }); - streamsStats = new StreamsStats(orderedStreams, FormatContext); - formatStats = new FormatStats(FormatContext); + containerFormat = m_mediaParser->avctx()->iformat->long_name; + streamCount = m_mediaParser->avctx()->nb_streams; + bitRate = m_mediaParser->avctx()->bit_rate; + + size_t VideoPos=0; + size_t AudioPos=0; + + for( auto streamIt = orderedStreams.begin(); streamIt != orderedStreams.end(); ++streamIt) { + auto Duration = 0; + auto FrameCount = (*streamIt)->stream()->nb_frames; + if ((*streamIt)->stream()->duration != AV_NOPTS_VALUE) + Duration= ((double)(*streamIt)->stream()->duration)*(*streamIt)->stream()->time_base.num/(*streamIt)->stream()->time_base.den; + + // If duration is not known, estimating it + if (Duration==0 && m_mediaParser->avctx()->duration!=AV_NOPTS_VALUE) + Duration=((double) m_mediaParser->avctx()->duration)/AV_TIME_BASE; + + // If frame count is not known, estimating it + if (FrameCount==0 && (*streamIt)->stream()->avg_frame_rate.num && (*streamIt)->stream()->avg_frame_rate.den && Duration) + FrameCount=Duration*(*streamIt)->stream()->avg_frame_rate.num/(*streamIt)->stream()->avg_frame_rate.den; + if (FrameCount==0 + && (((*streamIt)->stream()->time_base.num==1 && (*streamIt)->stream()->time_base.den>=24 && (*streamIt)->stream()->time_base.den<=60) + || ((*streamIt)->stream()->time_base.num==1001 && (*streamIt)->stream()->time_base.den>=24000 && (*streamIt)->stream()->time_base.den<=60000))) + FrameCount=(*streamIt)->stream()->duration; + + CommonStats* Stat = nullptr; + + if((*streamIt)->stream()->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (!VideoPos || ActiveAllTracks[Type_Video]) + Stat = new VideoStats(FrameCount, Duration, *streamIt); + ++VideoPos; + } else if((*streamIt)->stream()->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (!AudioPos || ActiveAllTracks[Type_Audio]) + Stat = new AudioStats(FrameCount, Duration, *streamIt); + ++AudioPos; } - avformat_close_input(&FormatContext); - } - if (options) { - av_dict_free(&options); + if (Stat) + Stats.push_back(Stat); } + + streamsStats = new StreamsStats(orderedStreams); + formatStats = new FormatStats(m_mediaParser->avctx()); } if(attachment.isEmpty()) { diff --git a/Source/Core/StreamsStats.cpp b/Source/Core/StreamsStats.cpp index 5da88ecb7..d9d06fd40 100644 --- a/Source/Core/StreamsStats.cpp +++ b/Source/Core/StreamsStats.cpp @@ -26,24 +26,21 @@ extern "C" using namespace tinyxml2; -StreamsStats::StreamsStats(QVector qavstreams, AVFormatContext *context) +StreamsStats::StreamsStats(QVector qavstreams) { - if(context != NULL) + for (size_t pos = 0; pos < qavstreams.count(); ++pos) { - for (size_t pos = 0; pos < qavstreams.count(); ++pos) + auto qavstream = qavstreams[pos]; + switch (qavstream->stream()->codecpar->codec_type) { - auto qavstream = qavstreams[pos]; - switch (qavstream->stream()->codecpar->codec_type) - { - case AVMEDIA_TYPE_VIDEO: - streams.push_back(std::unique_ptr(new VideoStreamStats(qavstream, context))); - break; - case AVMEDIA_TYPE_AUDIO: - streams.push_back(std::unique_ptr(new AudioStreamStats(qavstream, context))); - break; - default: - qDebug() << "only Audio / Video streams are supported for now.. skipping stream of index = " << pos << " and of type = " << context->streams[pos]->codecpar->codec_type; - } + case AVMEDIA_TYPE_VIDEO: + streams.push_back(std::unique_ptr(new VideoStreamStats(qavstream))); + break; + case AVMEDIA_TYPE_AUDIO: + streams.push_back(std::unique_ptr(new AudioStreamStats(qavstream))); + break; + default: + qDebug() << "only Audio / Video streams are supported for now.. skipping stream of index = " << pos << " and of type = " << qavstream->stream()->codecpar->codec_type; } } } diff --git a/Source/Core/StreamsStats.h b/Source/Core/StreamsStats.h index e3a4302eb..855372a29 100644 --- a/Source/Core/StreamsStats.h +++ b/Source/Core/StreamsStats.h @@ -16,7 +16,6 @@ #include "Core/CommonStreamStats.h" -struct AVFormatContext; class QXmlStreamWriter; class CommonStreamStats; class QAVStream; @@ -25,7 +24,7 @@ class StreamsStats { public: typedef std::unique_ptr CommonStreamStatsPtr; - StreamsStats(QVector streams = {}, AVFormatContext* context = NULL); + StreamsStats(QVector streams = {}); ~StreamsStats(); bool readFromXML(const char* data, size_t size); diff --git a/Source/Core/VideoStreamStats.cpp b/Source/Core/VideoStreamStats.cpp index a9e8aea59..4d6581d08 100644 --- a/Source/Core/VideoStreamStats.cpp +++ b/Source/Core/VideoStreamStats.cpp @@ -99,7 +99,7 @@ VideoStreamStats::VideoStreamStats(XMLElement *streamElement) : CommonStreamStat refs = refs_value; } -VideoStreamStats::VideoStreamStats(QAVStream* stream, AVFormatContext *context) : CommonStreamStats(stream), +VideoStreamStats::VideoStreamStats(QAVStream* stream) : CommonStreamStats(stream), width(stream != NULL ? std::to_string(stream->stream()->codecpar->width) : ""), height(stream != NULL ? std::to_string(stream->stream()->codecpar->height) : ""), coded_width(stream != NULL ? std::to_string(stream->codec()->avctx()->coded_width) : ""), @@ -114,13 +114,12 @@ VideoStreamStats::VideoStreamStats(QAVStream* stream, AVFormatContext *context) { if(stream != NULL) { - AVRational sar = av_guess_sample_aspect_ratio(context, stream->stream(), NULL); + AVRational sar = av_guess_sample_aspect_ratio(NULL, stream->stream(), NULL); // context is unused and can be null in current ffmpeg code sample_aspect_ratio = rational_to_string(sar, ':'); if(stream->codec()->avctx()->sample_aspect_ratio.den) { AVRational dar; - av_reduce(&dar.num, &dar.den, stream->stream()->codecpar->width * sar.num, stream->stream()->codecpar->height * sar.den, diff --git a/Source/Core/VideoStreamStats.h b/Source/Core/VideoStreamStats.h index f50caa7f6..ae3238f5c 100644 --- a/Source/Core/VideoStreamStats.h +++ b/Source/Core/VideoStreamStats.h @@ -18,7 +18,7 @@ class VideoStreamStats : public CommonStreamStats { public: VideoStreamStats(tinyxml2::XMLElement* streamElement); - VideoStreamStats(QAVStream* stream, AVFormatContext *context); + VideoStreamStats(QAVStream* stream); virtual void writeStreamInfoToXML(QXmlStreamWriter* writer);