Skip to content

Commit

Permalink
[HLSTree] Add new params to manifest_config property
Browse files Browse the repository at this point in the history
hls_ignore_endlist: allow to ignore EXT-X-ENDLIST
hls_fix_mediasequence: try correct a malformed EXT-X-MEDIA-SEQUENCE
hls_fix_discsequence: try correct a malformed EXT-X-DISCONTINUITY-SEQUENCE
  • Loading branch information
CastagnaIT committed Apr 24, 2024
1 parent 444f978 commit 15865fc
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 111 deletions.
12 changes: 12 additions & 0 deletions src/CompKodiProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ void ADP::KODI_PROPS::CCompKodiProps::ParseManifestConfig(const std::string& dat
if (jDictVal.GetUint() > 0)
m_manifestConfig.timeShiftBufferLimit = jDictVal.GetUint();
}
else if (configName == "hls_ignore_endlist" && jDictVal.IsBool())
{
m_manifestConfig.hlsIgnoreEndList = jDictVal.GetBool();
}
else if (configName == "hls_fix_mediasequence" && jDictVal.IsBool())
{
m_manifestConfig.hlsFixMediaSequence = jDictVal.GetBool();
}
else if (configName == "hls_fix_discsequence" && jDictVal.IsBool())
{
m_manifestConfig.hlsFixDiscontSequence = jDictVal.GetBool();
}
else
{
LOG::LogF(LOGERROR, "Unsupported \"%s\" config or wrong data type on \"%s\" property",
Expand Down
12 changes: 11 additions & 1 deletion src/CompKodiProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,17 @@ struct ChooserProps

struct ManifestConfig
{
std::optional<uint32_t> timeShiftBufferLimit; // Limit the timeshift buffer depth, in seconds
// Limit the timeshift buffer depth, in seconds
std::optional<uint32_t> timeShiftBufferLimit;
// Faulty HLS live services can send manifest updates with inconsistent EXT-X-ENDLIST
// when the stream is not finished, enabling this will ignore EXT-X-ENDLIST tags
bool hlsIgnoreEndList{false};
// Faulty HLS live services can send manifest updates with inconsistent EXT-X-MEDIA-SEQUENCE
// enabling this will correct the value by using EXT-X-PROGRAM-DATE-TIME tags
bool hlsFixMediaSequence{false};
// Faulty HLS live services can send manifest updates with inconsistent EXT-X-DISCONTINUITY-SEQUENCE
// enabling this will correct the value by using EXT-X-PROGRAM-DATE-TIME tags
bool hlsFixDiscontSequence{false};
};

class ATTR_DLL_LOCAL CCompKodiProps
Expand Down
26 changes: 12 additions & 14 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -938,26 +938,24 @@ void CSession::PrepareStream(CStream* stream)
return;

CRepresentation* repr = stream->m_adStream.getRepresentation();
const EVENT_TYPE startEvent = stream->m_adStream.GetStartEvent();

if (stream->m_adStream.StreamChanged())
// Download the manifest only at first start of the stream
if (startEvent == EVENT_TYPE::STREAM_START)
{
// For HLS case when stream (representation) quality has been changed
// its not needed to update again the child manifest by calling ParseChildManifest
// because its already been done by AdaptiveStream thread worker or AdaptiveStream::ensureSegment
stream->m_isEncrypted = repr->GetPsshSetPos() != PSSHSET_POS_DEFAULT;
return;
bool noop;
m_adaptiveTree->PrepareRepresentation(stream->m_adStream.getPeriod(),
stream->m_adStream.getAdaptationSet(), repr, noop,
SEGMENT_NO_NUMBER);
}

bool isDrmChanged{false};
if (m_adaptiveTree->PrepareRepresentation(stream->m_adStream.getPeriod(),
stream->m_adStream.getAdaptationSet(), repr,
isDrmChanged, SEGMENT_NO_NUMBER))
if (startEvent != EVENT_TYPE::REP_CHANGE &&
stream->m_adStream.getPeriod()->GetEncryptionState() == EncryptionState::ENCRYPTED_SUPPORTED)
{
if (isDrmChanged)
InitializeDRM();

stream->m_isEncrypted = repr->GetPsshSetPos() != PSSHSET_POS_DEFAULT;
InitializeDRM();
}

stream->m_isEncrypted = repr->GetPsshSetPos() != PSSHSET_POS_DEFAULT;
}

void CSession::EnableStream(CStream* stream, bool enable)
Expand Down
1 change: 1 addition & 0 deletions src/common/AdaptiveStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ enum class EVENT_TYPE
void Disable();

void SetStartEvent(const EVENT_TYPE eventType) { m_startEvent = eventType; }
EVENT_TYPE GetStartEvent() const { return m_startEvent; }

/*!
* \brief Set the current segment to the one specified, and reset
Expand Down
8 changes: 8 additions & 0 deletions src/common/AdaptiveTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ namespace adaptive
const PLAYLIST::CRepresentation* segRep,
const PLAYLIST::CSegment* segment) const
{
if (segRep->SegmentTimeline().IsEmpty())
return true;

if (!segment || !segPeriod || !segRep)
return false;

Expand Down Expand Up @@ -280,6 +283,11 @@ namespace adaptive
break;

updLck.lock();

// Reset interval value to allow forced update from manifest
if (m_resetInterval)
m_tree->m_updateInterval = PLAYLIST::NO_VALUE;

m_tree->RefreshLiveSegments();
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/common/AdaptiveTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ class ATTR_DLL_LOCAL AdaptiveTree
// \brief Reset start time (make exit the condition variable m_cvUpdInterval and re-start the timeout)
void ResetStartTime() { m_cvUpdInterval.notify_all(); }

// \brief At next update reset the interval value to NO_VALUE, before make RefreshLiveSegments callback
void ResetInterval() { m_resetInterval = true; }

// \brief As "std::mutex" lock, but put in pause the manifest updates (support std::lock_guard).
// If an update is in progress, block the code until the update is finished.
void lock() { Pause(); }
Expand Down Expand Up @@ -281,6 +284,7 @@ class ATTR_DLL_LOCAL AdaptiveTree
std::mutex m_waitMutex;
std::condition_variable m_cvWait;
bool m_threadStop{false};
bool m_resetInterval{false};
};

/*!
Expand Down
1 change: 0 additions & 1 deletion src/common/Period.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ void PLAYLIST::CPeriod::CopyHLSData(const CPeriod* other)
m_baseUrl = other->m_baseUrl;
m_id = other->m_id;
m_timescale = other->m_timescale;
m_start = other->m_start;
m_encryptionState = other->m_encryptionState;
m_includedStreamType = other->m_includedStreamType;
m_isSecureDecoderNeeded = other->m_isSecureDecoderNeeded;
Expand Down
Loading

0 comments on commit 15865fc

Please sign in to comment.