Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some cleanup to AdaptiveStream and Session #1351

Merged
merged 11 commits into from
Aug 15, 2023
31 changes: 17 additions & 14 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ bool CSession::Initialize()

m_adaptiveTree->PostOpen(m_kodiProps);

return InitializePeriod(isSessionOpened);
bool isPeriodInit = InitializePeriod(isSessionOpened);
m_reprChooser->PostInit();
return isPeriodInit;
}

void CSession::CheckHDCP()
Expand Down Expand Up @@ -353,7 +355,7 @@ bool CSession::PreInitializeDRM(std::string& challengeB64,
}

m_cdmSessions.resize(2);
memset(&m_cdmSessions.front(), 0, sizeof(CCdmSession));

// Try to initialize an SingleSampleDecryptor
LOG::LogF(LOGDEBUG, "Entering encryption section");

Expand Down Expand Up @@ -423,7 +425,6 @@ bool CSession::InitializeDRM(bool addDefaultKID /* = false */)
{
bool isSecureVideoSession{false};
m_cdmSessions.resize(m_adaptiveTree->m_currentPeriod->GetPSSHSets().size());
memset(&m_cdmSessions.front(), 0, sizeof(CCdmSession));

// Try to initialize an SingleSampleDecryptor
if (m_adaptiveTree->m_currentPeriod->GetEncryptionState() !=
Expand Down Expand Up @@ -485,8 +486,7 @@ bool CSession::InitializeDRM(bool addDefaultKID /* = false */)
{
auto initialRepr{m_reprChooser->GetRepresentation(sessionPsshset.adaptation_set_)};

CStream stream{*m_adaptiveTree, sessionPsshset.adaptation_set_, initialRepr, m_kodiProps,
false};
CStream stream{*m_adaptiveTree, sessionPsshset.adaptation_set_, initialRepr, m_kodiProps};

stream.m_isEnabled = true;
stream.m_adStream.start_stream();
Expand Down Expand Up @@ -682,18 +682,20 @@ bool CSession::InitializeDRM(bool addDefaultKID /* = false */)
CheckHDCP();

m_reprChooser->SetSecureSession(isSecureVideoSession);
m_reprChooser->PostInit();

return true;
}

bool CSession::InitializePeriod(bool isSessionOpened /* = false */)
{
bool psshChanged{true};
bool isPsshChanged{true};
bool isReusePssh{true};
if (m_adaptiveTree->m_nextPeriod)
{
psshChanged =
isPsshChanged =
!(m_adaptiveTree->m_currentPeriod->GetPSSHSets() == m_adaptiveTree->m_nextPeriod->GetPSSHSets());
isReusePssh = !isPsshChanged && m_adaptiveTree->m_nextPeriod->GetEncryptionState() ==
EncryptionState::ENCRYPTED_SUPPORTED;
m_adaptiveTree->m_currentPeriod = m_adaptiveTree->m_nextPeriod;
m_adaptiveTree->m_nextPeriod = nullptr;
}
Expand All @@ -709,8 +711,11 @@ bool CSession::InitializePeriod(bool isSessionOpened /* = false */)
// create SESSION::STREAM objects. One for each AdaptationSet
m_streams.clear();

if (!psshChanged)
LOG::Log(LOGDEBUG, "Reusing DRM psshSets for new period!");
if (!isPsshChanged)
{
if (isReusePssh)
LOG::Log(LOGDEBUG, "Reusing DRM psshSets for new period!");
}
else
{
if (isSessionOpened)
Expand Down Expand Up @@ -771,7 +776,6 @@ bool CSession::InitializePeriod(bool isSessionOpened /* = false */)
}
}

m_firstPeriodInitialized = true;
return true;
}

Expand All @@ -780,8 +784,7 @@ void CSession::AddStream(PLAYLIST::CAdaptationSet* adp,
bool isDefaultRepr,
uint32_t uniqueId)
{
m_streams.push_back(std::make_unique<CStream>(*m_adaptiveTree, adp, initialRepr, m_kodiProps,
m_firstPeriodInitialized));
m_streams.push_back(std::make_unique<CStream>(*m_adaptiveTree, adp, initialRepr, m_kodiProps));

CStream& stream{*m_streams.back()};

Expand Down Expand Up @@ -1225,7 +1228,7 @@ bool CSession::GetNextSample(ISampleReader*& sampleReader)
{
// Once the start PTS has been acquired for the timing stream, set this value
// to the other stream readers
if (stream.get() != timingStream &&
if (timingStream && stream.get() != timingStream &&
timingStream->GetReader()->GetStartPTS() != STREAM_NOPTS_VALUE &&
streamReader->GetStartPTS() == STREAM_NOPTS_VALUE)
{
Expand Down
7 changes: 3 additions & 4 deletions src/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,9 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver

struct CCdmSession
{
SSD::SSD_DECRYPTER::SSD_CAPS m_decrypterCaps;
Adaptive_CencSingleSampleDecrypter* m_cencSingleSampleDecrypter;
const char* m_cdmSessionStr = nullptr;
SSD::SSD_DECRYPTER::SSD_CAPS m_decrypterCaps{};
Adaptive_CencSingleSampleDecrypter* m_cencSingleSampleDecrypter{nullptr};
const char* m_cdmSessionStr{nullptr};
bool m_sharedCencSsd{false};
};
std::vector<CCdmSession> m_cdmSessions;
Expand All @@ -385,7 +385,6 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
uint8_t m_drmConfig{0};
bool m_settingNoSecureDecoder{false};
bool m_settingIsHdcpOverride{false};
bool m_firstPeriodInitialized{false};
std::unique_ptr<CKodiHost> m_KodiHost;
};
} // namespace SESSION
5 changes: 2 additions & 3 deletions src/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ class ATTR_DLL_LOCAL CStream
CStream(adaptive::AdaptiveTree& tree,
PLAYLIST::CAdaptationSet* adp,
PLAYLIST::CRepresentation* initialRepr,
const UTILS::PROPERTIES::KodiProperties& kodiProps,
bool chooseRep)
const UTILS::PROPERTIES::KodiProperties& kodiProps)
: m_isEnabled{false},
m_isEncrypted{false},
m_mainId{0},
m_adStream{tree, adp, initialRepr, kodiProps, chooseRep},
m_adStream{tree, adp, initialRepr, kodiProps},
m_hasSegmentChanged{false},
m_isValid{true} {};

Expand Down
82 changes: 26 additions & 56 deletions src/common/AdaptiveStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ uint32_t AdaptiveStream::globalClsId = 0;
AdaptiveStream::AdaptiveStream(AdaptiveTree& tree,
PLAYLIST::CAdaptationSet* adp,
PLAYLIST::CRepresentation* initialRepr,
const UTILS::PROPERTIES::KodiProperties& kodiProps,
bool choose_rep)
const UTILS::PROPERTIES::KodiProperties& kodiProps)
: thread_data_(nullptr),
tree_(tree),
observer_(nullptr),
Expand All @@ -53,9 +52,6 @@ AdaptiveStream::AdaptiveStream(AdaptiveTree& tree,
m_fixateInitialization(false),
m_segmentFileOffset(0),
play_timeshift_buffer_(kodiProps.m_playTimeshiftBuffer),
choose_rep_(choose_rep),
rep_counter_(1),
prev_rep_(0),
last_rep_(0)
{
current_rep_->current_segment_ = nullptr;
Expand Down Expand Up @@ -583,17 +579,6 @@ bool AdaptiveStream::start_stream()
if (!current_rep_)
return false;

if (choose_rep_)
{
choose_rep_ = false;
current_rep_ = tree_.GetRepChooser()->GetRepresentation(current_adp_);
}

if (!current_rep_->IsPrepared())
{
tree_.prepareRepresentation(current_period_, current_adp_, current_rep_, false);
}

//! @todo: the assured_buffer_duration_ and max_buffer_duration_
//! isnt implemeted correctly and need to be reworked,
//! these properties are intended to determine the amount of buffer
Expand Down Expand Up @@ -807,14 +792,16 @@ bool AdaptiveStream::ensureSegment()
stream_changed_ = false;
CSegment* nextSegment{nullptr};
last_rep_ = current_rep_;
if (valid_segment_buffers_)

if (valid_segment_buffers_ > 0)
{
// rotate element 0 to the end
// Move the segment at initial position 0 to the end, because consumed
std::rotate(segment_buffers_.begin(), segment_buffers_.begin() + 1,
segment_buffers_.begin() + available_segment_buffers_);
--valid_segment_buffers_;
--available_segment_buffers_;

// Check if next segment use same representation of previous one
// if not, update the current representation
if (segment_buffers_[0]->rep != current_rep_)
{
current_rep_->SetIsEnabled(false);
Expand All @@ -823,7 +810,7 @@ bool AdaptiveStream::ensureSegment()
stream_changed_ = true;
}
}
if (valid_segment_buffers_)
if (valid_segment_buffers_ > 0)
{
if (!segment_buffers_[0]->segment.IsInitialization())
{
Expand All @@ -834,14 +821,6 @@ bool AdaptiveStream::ensureSegment()
else
nextSegment = current_rep_->get_next_segment(current_rep_->current_segment_);

if(prev_rep_== current_rep_)
rep_counter_++;
else
{
rep_counter_=1;
prev_rep_=current_rep_;
}

if (nextSegment)
{
currentPTSOffset_ =
Expand All @@ -862,37 +841,26 @@ bool AdaptiveStream::ensureSegment()

size_t nextsegmentPosold = current_rep_->get_segment_pos(nextSegment);
uint64_t nextsegno = current_rep_->getSegmentNumber(nextSegment);
CRepresentation* newRep{nullptr};

bool lastSeg{false};
if (current_period_ != tree_.m_periods.back().get())
{
if (nextsegmentPosold + available_segment_buffers_ ==
current_rep_->SegmentTimeline().GetSize() - 1)
{
lastSeg = true;
}
}

if (segment_buffers_[0]->segment.IsInitialization() ||
valid_segment_buffers_ == 0 ||
current_adp_->GetStreamType() != StreamType::VIDEO)
{
newRep = current_rep_;
}
else if (lastSeg) // Don't change reps on last segment of period, use the rep of preceeding seg
{
newRep = segment_buffers_[valid_segment_buffers_ - 1]->rep;
}
else
CRepresentation* newRep = current_rep_;
bool isBufferFull = valid_segment_buffers_ >= max_buffer_length_;

if (!segment_buffers_[0]->segment.IsInitialization() && available_segment_buffers_ > 0 &&
!isBufferFull) // Defer until we have some free buffer
{
// Defer until we have some free buffer
if (available_segment_buffers_ < max_buffer_length_) {
newRep = tree_.GetRepChooser()->GetNextRepresentation(
current_adp_, segment_buffers_[available_segment_buffers_ - 1]->rep);
}
// The representation from the last added segment buffer
CRepresentation* prevRep = segment_buffers_[available_segment_buffers_ - 1]->rep;

bool isLastSegment = nextsegmentPosold + available_segment_buffers_ ==
current_rep_->SegmentTimeline().GetSize() - 1;
// Dont change representation if it is the last segment of a period otherwise when it comes
// the time to play the last segment in a period, AdaptiveStream wasn't able to insert the
// initialization segment (in the case of fMP4) and you would get corrupted or blank video
// for the last segment
if (isLastSegment)
newRep = prevRep;
else
newRep = current_rep_;
newRep = tree_.GetRepChooser()->GetNextRepresentation(current_adp_, prevRep);
}

// If the representation has been changed, segments may have to be generated (DASH)
Expand All @@ -905,6 +873,8 @@ bool AdaptiveStream::ensureSegment()
current_period_, current_adp_, newRep, tree_.IsLive());
}

// Add to the buffer next future segment

size_t nextsegmentPos = static_cast<size_t>(nextsegno - newRep->GetStartNumber());
if (nextsegmentPos + available_segment_buffers_ >= newRep->SegmentTimeline().GetSize())
{
Expand Down
14 changes: 6 additions & 8 deletions src/common/AdaptiveStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class AdaptiveStream;
AdaptiveStream(AdaptiveTree& tree,
PLAYLIST::CAdaptationSet* adpSet,
PLAYLIST::CRepresentation* initialRepr,
const UTILS::PROPERTIES::KodiProperties& kodiProps,
bool choose_rep_);
const UTILS::PROPERTIES::KodiProperties& kodiProps);
virtual ~AdaptiveStream();
void set_observer(AdaptiveStreamObserver *observer){ observer_ = observer; };
void Reset();
Expand Down Expand Up @@ -224,14 +223,14 @@ class AdaptiveStream;
// We need to store here because linked to representation
uint8_t m_decrypterIv[16];

// number of segmentbuffers whith valid segment, always >= valid_segment_buffers_
size_t available_segment_buffers_{0};
// number of segment_buffers which are downloaded / downloading
// Minimum segment buffer size (segment_buffers_)
uint32_t assured_buffer_length_{0};
// The segment buffer size (segment_buffers_), so the max number of segments that can be downloaded and stored in memory
uint32_t max_buffer_length_{0};
// Number of segments stored in segment buffer (segment_buffers_) queued for downloading, always >= valid_segment_buffers_
size_t available_segment_buffers_{0};
// Number of segments stored in segment buffer (segment_buffers_) currently in download and downloaded
size_t valid_segment_buffers_{0};
uint32_t rep_counter_;
PLAYLIST::CRepresentation* prev_rep_; // used for rep_counter_
PLAYLIST::CRepresentation* last_rep_; // used to align new live rep with old

std::size_t segment_read_pos_;
Expand All @@ -243,7 +242,6 @@ class AdaptiveStream;
uint64_t m_segmentFileOffset;
bool play_timeshift_buffer_;
bool stream_changed_ = false;
bool choose_rep_;

// Class ID for debug log purpose, allow the LOG prints of each AdaptiveStream to be distinguished
uint32_t clsId;
Expand Down
4 changes: 2 additions & 2 deletions src/common/Chooser.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ATTR_DLL_LOCAL IRepresentationChooser
virtual void Initialize(const UTILS::PROPERTIES::ChooserProps& props) {}

/*!
* \brief Post initialization, will be called just after DRM initialization
* \brief Post initialization, will be called after the session initialization
*/
virtual void PostInit() {}

Expand Down Expand Up @@ -72,7 +72,7 @@ class ATTR_DLL_LOCAL IRepresentationChooser
}

/*!
* \brief Set if the DRM use a secure session
* \brief Called at each DRM initialization to set if the secure session is currently being used.
* \param isSecureSession Set true if a secure session is in use
*/
virtual void SetSecureSession(const bool isSecureSession) { m_isSecureSession = isSecureSession; }
Expand Down
Loading
Loading