Skip to content

Commit

Permalink
[session] add OnGetStream method
Browse files Browse the repository at this point in the history
  • Loading branch information
CastagnaIT committed Oct 14, 2024
1 parent e1fa4fb commit 4d51a66
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 30 deletions.
30 changes: 30 additions & 0 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,36 @@ void CSession::OnStreamChange(adaptive::AdaptiveStream* adStream)
}
}

bool SESSION::CSession::OnGetStream(int streamid, kodi::addon::InputstreamInfo& info)
{
CStream* stream(GetStream(streamid - GetPeriodId() * 1000));

if (stream)
{
const uint16_t psshSetPos = stream->m_adStream.getRepresentation()->m_psshSetPos;
if (psshSetPos != PSSHSET_POS_DEFAULT ||
stream->m_adStream.getPeriod()->GetEncryptionState() == EncryptionState::NOT_SUPPORTED)
{
if (!GetSingleSampleDecryptor(psshSetPos))
{
// If the stream is protected with a unsupported DRM, we have to stop the playback,
// since there are no ways to stop playback when Kodi request streams
// we are forced to delete all CStream's here, so that when demux reader will starts
// will have no data to process, and so stop the playback
// (other streams may have been requested/opened before this one)
LOG::Log(LOGERROR, "GetStream(%d): Decrypter for the stream not found");
DeleteStreams();
return false;
}
}

info = stream->m_info;
return true;
}

return false;
}

std::shared_ptr<Adaptive_CencSingleSampleDecrypter> CSession::GetSingleSampleDecrypter(std::string sessionId)
{
for (std::vector<CCdmSession>::iterator b(m_cdmSessions.begin() + 1), e(m_cdmSessions.end());
Expand Down
8 changes: 8 additions & 0 deletions src/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,14 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
*/
void OnStreamChange(adaptive::AdaptiveStream* adStream) override;

/*!
* \brief Callback from CInputStreamAdaptive::GetStream.
* \param streamid The requested stream id
* \param info The stream info object (can be updated)
* \return True to allow Kodi core to load the stream, otherwise false
*/
bool OnGetStream(int streamid, kodi::addon::InputstreamInfo& info);

protected:
/*! \brief Check for and load decrypter module matching the supplied key system
* \param key_system [OUT] Will be assigned to if a decrypter is found matching
Expand Down
35 changes: 5 additions & 30 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,38 +127,13 @@ void CInputStreamAdaptive::GetCapabilities(kodi::addon::InputstreamCapabilities&

bool CInputStreamAdaptive::GetStream(int streamid, kodi::addon::InputstreamInfo& info)
{
// GetStream is called by Kodi twice times, before and after OpenStream.
LOG::Log(LOGDEBUG, "GetStream(%d)", streamid);

CStream* stream(m_session->GetStream(streamid - m_session->GetPeriodId() * 1000));

if (stream)
{
// If the stream is encrypted, verify if the decrypter has been initialized
// this is important for HLS because the DRM it is initialized at later time
// so on the OpenStream, instead of CSession::Initialize->InitializePeriod->InitializeDRM
// Since kodi initialize one single stream at time, can happens that or another stream
// has been opened before this one, or another stream will be opened after this one (e.g. unencrypted)
// so if you dont delete all streams, the kodi demux reader still starts
// and a corrupted playback will starts.
// NOTE: GetStream is called by Kodi twice times, before and after OpenStream, on HLS
// the first time all streams are unencrypted because child manifest has not been downloaded
const uint16_t psshSetPos = stream->m_adStream.getRepresentation()->m_psshSetPos;
if (psshSetPos != PSSHSET_POS_DEFAULT ||
stream->m_adStream.getPeriod()->GetEncryptionState() == EncryptionState::NOT_SUPPORTED)
{
if (!m_session->GetSingleSampleDecryptor(psshSetPos))
{
LOG::Log(LOGERROR, "GetStream(%d): Decrypter for the stream not found");
m_session->DeleteStreams();
return false;
}
}

info = stream->m_info;
return true;
}

return false;
// Return false prevents this stream from loading, but does not stop playback,
// Kodi core will continue to request another stream of same type (a/v)
// as long as one is successful
return m_session->OnGetStream(streamid, info);
}

void CInputStreamAdaptive::UnlinkIncludedStreams(CStream* stream)
Expand Down

0 comments on commit 4d51a66

Please sign in to comment.