Skip to content

Commit

Permalink
[DemuxClient] Parse for mid stream changes (optional)
Browse files Browse the repository at this point in the history
  • Loading branch information
peak3d committed Sep 22, 2019
1 parent bf90ec9 commit b3b0c49
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 86 deletions.
5 changes: 5 additions & 0 deletions xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
Expand Up @@ -235,6 +235,11 @@ class CDVDVideoCodec
*/
virtual void Reopen() {};

/**
* Return true, if codec parses stream to detect mid stream changes
* If false, demuxer tries to parse the stream and notifies VideoPlayer on changes.
*/
virtual bool HasCodecParser() const { return true; }
protected:
CProcessInfo &m_processInfo;
};
Expand Down
Expand Up @@ -1445,13 +1445,17 @@ void CDVDVideoCodecAndroidMediaCodec::ReleaseSurfaceTexture(void)

void CDVDVideoCodecAndroidMediaCodec::UpdateFpsDuration()
{
if (m_hints.fpsrate > 0 && m_hints.fpsscale > 0)
m_fpsDuration = static_cast<uint32_t>(static_cast<uint64_t>(DVD_TIME_BASE) * m_hints.fpsscale / m_hints.fpsrate);
int fpsRate = m_hints.fpsrate;
if (m_hints.fieldOrder > AV_FIELD_PROGRESSIVE)
fpsRate *= 2;

if (fpsrate > 0 && m_hints.fpsscale > 0)
{
m_fpsDuration = static_cast<uint32_t>(static_cast<uint64_t>(DVD_TIME_BASE) * m_hints.fpsscale / fpsrate);
m_processInfo.SetVideoFps(static_cast<float>(fpsrate) / m_hints.fpsscale);
}
else
m_fpsDuration = 1;

m_processInfo.SetVideoFps(static_cast<float>(m_hints.fpsrate) / m_hints.fpsscale);

CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::UpdateFpsDuration fpsRate:%u fpsscale:%u, fpsDur:%u", m_hints.fpsrate, m_hints.fpsscale, m_fpsDuration);
}

Expand Down
Expand Up @@ -141,6 +141,7 @@ class CDVDVideoCodecAndroidMediaCodec : public CDVDVideoCodec, public CJNISurfac
virtual const char* GetName() override { return m_formatname.c_str(); };
virtual void SetCodecControl(int flags) override;
virtual unsigned GetAllowedReferences() override;
bool HasCodecParser() const override { return false; }

protected:
void Dispose();
Expand Down
66 changes: 28 additions & 38 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h
Expand Up @@ -69,53 +69,37 @@ enum StreamSource
class CDemuxStream
{
public:
CDemuxStream()
{
uniqueId = 0;
dvdNavId = 0;
demuxerId = -1;
codec = (AVCodecID)0; // AV_CODEC_ID_NONE
codec_fourcc = 0;
profile = FF_PROFILE_UNKNOWN;
level = FF_LEVEL_UNKNOWN;
type = STREAM_NONE;
source = STREAM_SOURCE_NONE;
iDuration = 0;
pPrivate = NULL;
ExtraData = NULL;
ExtraSize = 0;
disabled = false;
changes = 0;
flags = StreamFlags::FLAG_NONE;
}

CDemuxStream() = default;
virtual ~CDemuxStream() { delete[] ExtraData; }

virtual std::string GetStreamName();

int uniqueId; // unique stream id
int dvdNavId;
int64_t demuxerId; // id of the associated demuxer
AVCodecID codec;
unsigned int codec_fourcc; // if available
int profile; // encoder profile of the stream reported by the decoder. used to qualify hw decoders.
int level; // encoder level of the stream reported by the decoder. used to qualify hw decoders.
StreamType type;
int source;

int iDuration; // in mseconds
void* pPrivate; // private pointer for the demuxer
uint8_t* ExtraData; // extra data for codec to use
unsigned int ExtraSize; // size of extra data

StreamFlags flags;
int uniqueId = 0; // unique stream id
int dvdNavId = 0;
int64_t demuxerId = -1; // id of the associated demuxer
AVCodecID codec = AV_CODEC_ID_NONE;
unsigned int codec_fourcc = 0; // if available
int profile =
FF_PROFILE_UNKNOWN; // encoder profile of the stream reported by the decoder. used to qualify hw decoders.
int level =
FF_LEVEL_UNKNOWN; // encoder level of the stream reported by the decoder. used to qualify hw decoders.
StreamType type = STREAM_NONE;
int source = STREAM_SOURCE_NONE;

int iDuration = 0; // in mseconds
void* pPrivate = nullptr; // private pointer for the demuxer
uint8_t* ExtraData = nullptr; // extra data for codec to use
unsigned int ExtraSize = 0; // size of extra data

StreamFlags flags = StreamFlags::FLAG_NONE;
std::string language; // RFC 5646 language code (empty string if undefined)
bool disabled; // set when stream is disabled. (when no decoder exists)
bool disabled = false; // set when stream is disabled. (when no decoder exists)

std::string name;
std::string codecName;

int changes; // increment on change which player may need to know about
bool checkStreamChange = false;
int changes = 0; // increment on change which player may need to know about

std::shared_ptr<DemuxCryptoSession> cryptoSession;
std::shared_ptr<ADDON::IAddonProvider> externalInterfaces;
Expand All @@ -138,6 +122,7 @@ class CDemuxStreamVideo : public CDemuxStream
int iOrientation = 0; // orientation of the video in degrees counter clockwise
int iBitsPerPixel = 0;
int iBitRate = 0;
AVFieldOrder fieldOrder = AV_FIELD_UNKNOWN;

AVColorSpace colorSpace = AVCOL_SPC_UNSPECIFIED;
AVColorRange colorRange = AVCOL_RANGE_UNSPECIFIED;
Expand Down Expand Up @@ -349,6 +334,11 @@ class CDVDDemux
*/
virtual void SetVideoResolution(int width, int height){};

/*
* Enable ParsePacket to detect mid stream changes
*/
virtual void EnableParsePacket(int64_t demuxerId, bool enable){};

/*
* return the id of the demuxer
*/
Expand Down
83 changes: 54 additions & 29 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp
Expand Up @@ -35,11 +35,14 @@ class CDemuxStreamClientInternal
avcodec_free_context(&m_context);
m_context = nullptr;
}
m_parser_split = false;
m_parser_keep_running = false;
}

AVCodecParserContext *m_parser = nullptr;
AVCodecContext *m_context = nullptr;
bool m_parser_split = false;
bool m_parser_keep_running = false;
};

template <class T>
Expand Down Expand Up @@ -119,13 +122,12 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt)
bool change = false;

CDemuxStream* st = GetStream(pkt->iStreamId);
if (st == nullptr || st->changes < 0 || st->ExtraSize || !CodecHasExtraData(st->codec))
if (!st || !CodecHasExtraData(st->codec))
return change;

CDemuxStreamClientInternal* stream = dynamic_cast<CDemuxStreamClientInternal*>(st);

if (stream == nullptr ||
stream->m_parser == nullptr)
if (!stream || !stream->m_parser || !stream->m_parser_split)
return change;

if (stream->m_context == nullptr)
Expand Down Expand Up @@ -154,29 +156,34 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt)
int len = stream->m_parser->parser->split(stream->m_context, pkt->pData, pkt->iSize);
if (len > 0 && len < FF_MAX_EXTRADATA_SIZE)
{
if (st->ExtraData)
delete[] st->ExtraData;
st->changes++;
st->disabled = false;
st->ExtraSize = len;
st->ExtraData = new uint8_t[len+AV_INPUT_BUFFER_PADDING_SIZE];
memcpy(st->ExtraData, pkt->pData, len);
memset(st->ExtraData + len, 0 , AV_INPUT_BUFFER_PADDING_SIZE);
stream->m_parser_split = false;
change = true;
CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata");

// Allow ffmpeg to transport codec information to stream->m_context
if (!avcodec_open2(stream->m_context, stream->m_context->codec, nullptr))
if (len != st->ExtraSize || memcmp(pkt->pData, st->ExtraData, st->ExtraSize) != 0)
{
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = pkt->pData;
avpkt.size = pkt->iSize;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
avcodec_send_packet(stream->m_context, &avpkt);
avcodec_close(stream->m_context);
if (st->ExtraData)
delete[] st->ExtraData;
st->changes++;
st->disabled = false;
st->ExtraSize = len;
st->ExtraData = new uint8_t[len + AV_INPUT_BUFFER_PADDING_SIZE];
memcpy(st->ExtraData, pkt->pData, len);
memset(st->ExtraData + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
stream->m_parser_split = false;
change = true;
CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata");

// Allow ffmpeg to transport codec information to stream->m_context
if (!avcodec_open2(stream->m_context, stream->m_context->codec, nullptr))
{
AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = pkt->pData;
avpkt.size = pkt->iSize;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
avcodec_send_packet(stream->m_context, &avpkt);
avcodec_close(stream->m_context);
}
}
if (!stream->m_parser_keep_running)
stream->m_parser_split = false;
}
}

Expand Down Expand Up @@ -230,8 +237,8 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt)
sta->changes++;
sta->disabled = false;
}
if (stream->m_context->channels)
st->changes = -1; // stop parsing
if (stream->m_context->channels && !stream->m_parser_keep_running)
stream->m_parser_split = false;
break;
}
case STREAM_VIDEO:
Expand Down Expand Up @@ -267,7 +274,7 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt)
stv->disabled = false;
}
}
if (stream->m_context->framerate.num &&
if (stream->m_context->framerate.num && !stv->iFpsRate &&
(stv->iFpsRate != stream->m_context->framerate.num ||
stv->iFpsScale != stream->m_context->framerate.den))
{
Expand All @@ -279,10 +286,14 @@ bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt)
stv->changes++;
stv->disabled = false;
}

if (stream->m_context->field_order != stv->fieldOrder)
{
stv->fieldOrder = stream->m_context->field_order;
stv->changes++;
stv->disabled = false;
}
break;
}

default:
break;
}
Expand Down Expand Up @@ -463,6 +474,7 @@ void CDVDDemuxClient::SetStreamProps(CDemuxStream *stream, std::map<int, std::sh
streamVideo->fAspect = source->fAspect;
streamVideo->iFpsScale = source->iFpsScale;
streamVideo->iFpsRate = source->iFpsRate;
streamVideo->fieldOrder = source->fieldOrder;
}
streamVideo->iBitRate = source->iBitRate;
if (source->ExtraSize > 0 && source->ExtraData)
Expand Down Expand Up @@ -585,6 +597,7 @@ void CDVDDemuxClient::SetStreamProps(CDemuxStream *stream, std::map<int, std::sh
toStream->cryptoSession = stream->cryptoSession;
toStream->externalInterfaces = stream->externalInterfaces;
toStream->language = stream->language;
toStream->checkStreamChange = stream->checkStreamChange;

CLog::Log(LOGDEBUG,"CDVDDemuxClient::RequestStream(): added/updated stream %d with codec_id %d",
toStream->uniqueId,
Expand Down Expand Up @@ -718,6 +731,18 @@ void CDVDDemuxClient::SetVideoResolution(int width, int height)
}
}

void CDVDDemuxClient::EnableParsePacket(int64_t demuxerId, bool enable)
{
std::shared_ptr<CDemuxStream> stream = GetStreamInternal(demuxerId);
if (stream && stream->checkStreamChange)
{
std::shared_ptr<CDemuxStreamClientInternalTpl<CDemuxStream>> streamCI =
std::dynamic_pointer_cast<CDemuxStreamClientInternalTpl<CDemuxStream>>(stream);
if (streamCI)
streamCI->m_parser_keep_running = enable;
}
}

bool CDVDDemuxClient::CodecHasExtraData(AVCodecID id)
{
switch (id)
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h
Expand Up @@ -43,6 +43,7 @@ class CDVDDemuxClient : public CDVDDemux
void EnableStream(int id, bool enable) override;
void OpenStream(int id) override;
void SetVideoResolution(int width, int height) override;
void EnableParsePacket(int64_t demuxerId, bool enable) override;

protected:
void RequestStreams();
Expand Down
3 changes: 3 additions & 0 deletions xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.cpp
Expand Up @@ -344,6 +344,9 @@ void CInputStreamPVRBase::UpdateStreamMap()
dStream = std::make_shared<CDemuxStream>();

dStream->codec = (AVCodecID)stream.iCodecId;
if (dStream->codec == AV_CODEC_ID_MPEG2VIDEO)
dStream->checkStreamChange = true;

dStream->uniqueId = stream.iPID;
dStream->language = stream.strLanguage;

Expand Down
6 changes: 5 additions & 1 deletion xbmc/cores/VideoPlayer/DVDStreamInfo.cpp
Expand Up @@ -55,6 +55,7 @@ void CDVDStreamInfo::Clear()
ptsinvalid = false;
forced_aspect = false;
bitsperpixel = 0;
fieldOrder = AV_FIELD_UNKNOWN;
colorSpace = AVCOL_SPC_UNSPECIFIED;
colorRange = AVCOL_RANGE_UNSPECIFIED;
colorPrimaries = AVCOL_PRI_UNSPECIFIED;
Expand Down Expand Up @@ -93,7 +94,7 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata)
}

// VIDEO
if( fpsscale != right.fpsscale
if (fpsscale != right.fpsscale
|| fpsrate != right.fpsrate
|| height != right.height
|| width != right.width
Expand All @@ -103,6 +104,7 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata)
|| ptsinvalid != right.ptsinvalid
|| forced_aspect != right.forced_aspect
|| bitsperpixel != right.bitsperpixel
|| fieldOrder != right.fieldOrder
|| vfr != right.vfr
|| colorSpace != right.colorSpace
|| colorRange != right.colorRange
Expand Down Expand Up @@ -219,6 +221,7 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata)
forced_aspect = right.forced_aspect;
orientation = right.orientation;
bitsperpixel = right.bitsperpixel;
fieldOrder = right.fieldOrder;
vfr = right.vfr;
codecOptions = right.codecOptions;
colorSpace = right.colorSpace;
Expand Down Expand Up @@ -288,6 +291,7 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata)
forced_aspect = stream->bForcedAspect;
orientation = stream->iOrientation;
bitsperpixel = stream->iBitsPerPixel;
fieldOrder = stream->fieldOrder;
colorSpace = stream->colorSpace;
colorRange = stream->colorRange;
colorPrimaries = stream->colorPrimaries;
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/DVDStreamInfo.h
Expand Up @@ -59,6 +59,7 @@ class CDVDStreamInfo
bool forced_aspect; // aspect is forced from container
int orientation; // orientation of the video in degrees counter clockwise
int bitsperpixel;
AVFieldOrder fieldOrder;
AVColorSpace colorSpace;
AVColorRange colorRange;
AVColorPrimaries colorPrimaries;
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/IVideoPlayer.h
Expand Up @@ -44,6 +44,7 @@ class IDVDStreamPlayer
virtual bool IsInited() const = 0;
virtual bool AcceptsData() const = 0;
virtual bool IsStalled() const = 0;
virtual bool HasCodecParser() const { return true; }

enum ESyncState
{
Expand Down

0 comments on commit b3b0c49

Please sign in to comment.