Skip to content

Commit

Permalink
Merge pull request #849 from MediaArea/pipe
Browse files Browse the repository at this point in the history
Support piped input with QtAVPlayer
  • Loading branch information
dericed authored Dec 23, 2024
2 parents 28dbe85 + 0a27a77 commit 80ed24f
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 106 deletions.
4 changes: 1 addition & 3 deletions Source/Core/AudioStreamStats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/AudioStreamStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 0 additions & 1 deletion Source/Core/CommonStreamStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace tinyxml2 {
class XMLElement;
}

struct AVFormatContext;
class QAVStream;
struct AVCodec;

Expand Down
138 changes: 58 additions & 80 deletions Source/Core/FileInformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<QAVStream*> 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;
}
QList<QAVStream> streams;
streams.append(m_mediaParser->currentVideoStreams());
streams.append(m_mediaParser->currentAudioStreams());

QVector<QAVStream*> 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()) {
Expand Down
27 changes: 12 additions & 15 deletions Source/Core/StreamsStats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,21 @@ extern "C"

using namespace tinyxml2;

StreamsStats::StreamsStats(QVector<QAVStream*> qavstreams, AVFormatContext *context)
StreamsStats::StreamsStats(QVector<QAVStream*> 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<VideoStreamStats>(new VideoStreamStats(qavstream, context)));
break;
case AVMEDIA_TYPE_AUDIO:
streams.push_back(std::unique_ptr<AudioStreamStats>(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<VideoStreamStats>(new VideoStreamStats(qavstream)));
break;
case AVMEDIA_TYPE_AUDIO:
streams.push_back(std::unique_ptr<AudioStreamStats>(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;
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/StreamsStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include "Core/CommonStreamStats.h"

struct AVFormatContext;
class QXmlStreamWriter;
class CommonStreamStats;
class QAVStream;
Expand All @@ -25,7 +24,7 @@ class StreamsStats {
public:
typedef std::unique_ptr<CommonStreamStats> CommonStreamStatsPtr;

StreamsStats(QVector<QAVStream*> streams = {}, AVFormatContext* context = NULL);
StreamsStats(QVector<QAVStream*> streams = {});
~StreamsStats();

bool readFromXML(const char* data, size_t size);
Expand Down
5 changes: 2 additions & 3 deletions Source/Core/VideoStreamStats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) : ""),
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoStreamStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 80ed24f

Please sign in to comment.