Skip to content

Commit

Permalink
Merge pull request #1594 from CastagnaIT/spin_cache
Browse files Browse the repository at this point in the history
[Cleanups] Get rid of CSpinCache / new segment container
  • Loading branch information
CastagnaIT authored Jul 5, 2024
2 parents 79a5036 + 0e5d21d commit 70b0bba
Show file tree
Hide file tree
Showing 22 changed files with 429 additions and 452 deletions.
2 changes: 1 addition & 1 deletion src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ void CSession::PrepareStream(CStream* stream)

// Prepare the representation when the period change usually its not needed,
// because the timeline is always already updated
if ((!m_adaptiveTree->IsChangingPeriod() || !repr->HasSegmentTimeline()) &&
if ((!m_adaptiveTree->IsChangingPeriod() || repr->Timeline().IsEmpty()) &&
(startEvent == EVENT_TYPE::STREAM_START || startEvent == EVENT_TYPE::STREAM_ENABLE))
{
m_adaptiveTree->PrepareRepresentation(stream->m_adStream.getPeriod(),
Expand Down
3 changes: 2 additions & 1 deletion src/common/AdaptationSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "utils/Utils.h"

#include <algorithm> // any_of
#include <iterator> // back_inserter

using namespace PLAYLIST;
using namespace UTILS;
Expand Down Expand Up @@ -53,7 +54,7 @@ void PLAYLIST::CAdaptationSet::AddRepresentation(
std::vector<CRepresentation*> PLAYLIST::CAdaptationSet::GetRepresentationsPtr()
{
std::vector<CRepresentation*> ptrReprs;
std::transform(m_representations.begin(), m_representations.end(), back_inserter(ptrReprs),
std::transform(m_representations.begin(), m_representations.end(), std::back_inserter(ptrReprs),
[](const std::unique_ptr<CRepresentation>& r) { return r.get(); });
return ptrReprs;
}
Expand Down
6 changes: 3 additions & 3 deletions src/common/AdaptationSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class ATTR_DLL_LOCAL CAdaptationSet : public CCommonSegAttribs, public CCommonAt
void AddSwitchingIds(std::string_view switchingIds);
const std::vector<std::string>& GetSwitchingIds() { return m_switchingIds; }

CSpinCache<uint32_t>& SegmentTimelineDuration() { return m_segmentTimelineDuration; }
bool HasSegmentTimelineDuration() { return !m_segmentTimelineDuration.IsEmpty(); }
std::vector<uint32_t>& SegmentTimelineDuration() { return m_segmentTimelineDuration; }
bool HasSegmentTimelineDuration() { return !m_segmentTimelineDuration.empty(); }

/*!
* \brief Get the timescale of segment durations tag.
Expand Down Expand Up @@ -175,7 +175,7 @@ class ATTR_DLL_LOCAL CAdaptationSet : public CCommonSegAttribs, public CCommonAt
std::string m_language;
std::vector<std::string> m_switchingIds;

CSpinCache<uint32_t> m_segmentTimelineDuration;
std::vector<uint32_t> m_segmentTimelineDuration;
uint64_t m_segDurationsTimescale{NO_VALUE};

// Custom ISAdaptive attributes (used on DASH only)
Expand Down
110 changes: 48 additions & 62 deletions src/common/AdaptiveStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,15 +476,10 @@ bool AdaptiveStream::parseIndexRange(PLAYLIST::CRepresentation* rep,
seg.m_time = cue.pts;
seg.range_begin_ = cue.pos_start;
seg.range_end_ = cue.pos_end;
rep->SegmentTimeline().GetData().emplace_back(seg);

//! todo: use SegmentTimelineDuration should not be needed
if (adpSet->SegmentTimelineDuration().GetSize() < rep->SegmentTimeline().GetSize())
{
adpSet->SegmentTimelineDuration().GetData().emplace_back(
static_cast<uint32_t>(cue.duration));
}
rep->Timeline().Add(seg);
}

rep->SetDuration(rep->Timeline().GetDuration());
return true;
}
}
Expand All @@ -502,7 +497,6 @@ bool AdaptiveStream::parseIndexRange(PLAYLIST::CRepresentation* rep,

bool isMoovFound{false};
AP4_Cardinal sidxCount{1};
uint64_t reprDuration{0};

CSegment seg;
seg.startPTS_ = 0;
Expand Down Expand Up @@ -548,18 +542,11 @@ bool AdaptiveStream::parseIndexRange(PLAYLIST::CRepresentation* rep,
{
seg.range_begin_ = seg.range_end_ + 1;
seg.range_end_ = seg.range_begin_ + refs[i].m_ReferencedSize - 1;
rep->SegmentTimeline().GetData().emplace_back(seg);

//! todo: use SegmentTimelineDuration should not be needed
if (adpSet->SegmentTimelineDuration().GetSize() < rep->SegmentTimeline().GetSize())
{
adpSet->SegmentTimelineDuration().GetData().emplace_back(refs[i].m_SubsegmentDuration);
}
rep->Timeline().Add(seg);

seg.startPTS_ += refs[i].m_SubsegmentDuration;
seg.m_endPts = seg.startPTS_ + refs[i].m_SubsegmentDuration;
seg.m_time += refs[i].m_SubsegmentDuration;
reprDuration += refs[i].m_SubsegmentDuration;
}

sidxCount--;
Expand Down Expand Up @@ -589,7 +576,7 @@ bool AdaptiveStream::parseIndexRange(PLAYLIST::CRepresentation* rep,
rep->SetInitSegment(initSeg);
}

rep->SetDuration(reprDuration);
rep->SetDuration(rep->Timeline().GetDuration());

return true;
}
Expand Down Expand Up @@ -644,7 +631,7 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
thread_data_->signal_dl_.wait(lckdl);
}

if (current_rep_->SegmentTimeline().IsEmpty())
if (current_rep_->Timeline().IsEmpty())
{
// GenerateSidxSegments assumes mutex_dl locked
std::lock_guard<std::mutex> lck(thread_data_->mutex_dl_);
Expand Down Expand Up @@ -679,12 +666,12 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
{
if (m_startEvent == EVENT_TYPE::STREAM_START && m_tree->IsLive() &&
!m_tree->IsChangingPeriod() && !CSrvBroker::GetKodiProps().IsPlayTimeshift() &&
!current_rep_->SegmentTimeline().IsEmpty())
!current_rep_->Timeline().IsEmpty())
{
size_t segPos = current_rep_->SegmentTimeline().GetSize() - 1;
size_t segPos = current_rep_->Timeline().GetSize() - 1;
//! @todo: segment duration is not fixed for each segment, this can calculate a wrong delay
uint64_t segDur = current_rep_->get_segment(segPos)->m_endPts -
current_rep_->get_segment(segPos)->startPTS_;
const CSegment* lastSeg = current_rep_->Timeline().GetBack();
uint64_t segDur = lastSeg->m_endPts - lastSeg->startPTS_;

size_t segPosDelay =
static_cast<size_t>((m_tree->m_liveDelay * current_rep_->GetTimescale()) / segDur);
Expand All @@ -698,16 +685,16 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
segPos = 0;
}

current_rep_->current_segment_ = current_rep_->get_segment(segPos);
current_rep_->current_segment_ = current_rep_->Timeline().Get(segPos);
}
else if (m_startEvent == EVENT_TYPE::REP_CHANGE) // switching streams, align new stream segment no.
{
uint64_t segmentId = segment_buffers_[0]->segment_number;
if (segmentId >= current_rep_->GetStartNumber() + current_rep_->SegmentTimeline().GetSize())
if (segmentId >= current_rep_->GetStartNumber() + current_rep_->Timeline().GetSize())
{
segmentId = current_rep_->GetStartNumber() + current_rep_->SegmentTimeline().GetSize() - 1;
segmentId = current_rep_->GetStartNumber() + current_rep_->Timeline().GetSize() - 1;
}
current_rep_->current_segment_ = current_rep_->get_segment(
current_rep_->current_segment_ = current_rep_->Timeline().Get(
static_cast<size_t>(segmentId - current_rep_->GetStartNumber()));
}
else
Expand All @@ -719,8 +706,7 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
// Reset the event for the next one
m_startEvent = EVENT_TYPE::NONE;

const CSegment* next_segment =
current_rep_->get_next_segment(current_rep_->current_segment_);
const CSegment* next_segment = current_rep_->GetNextSegment();

if (!next_segment && current_adp_->GetStreamType() != StreamType::SUBTITLE)
{
Expand Down Expand Up @@ -765,7 +751,7 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
valid_segment_buffers_ = valid_segment_buffers + 1;
}

if (!current_rep_->SegmentTimeline().Get(0))
if (!current_rep_->Timeline().Get(0))
{
LOG::LogF(LOGERROR, "[AS-%u] Segment at position 0 not found from representation id: %s",
clsId, current_rep_->GetId().data());
Expand All @@ -777,7 +763,7 @@ bool AdaptiveStream::start_stream(const uint64_t startPts)
currentPTSOffset_ =
(next_segment->startPTS_ * current_rep_->timescale_ext_) / current_rep_->timescale_int_;
absolutePTSOffset_ =
(current_rep_->SegmentTimeline().Get(0)->startPTS_ * current_rep_->timescale_ext_) /
(current_rep_->Timeline().Get(0)->startPTS_ * current_rep_->timescale_ext_) /
current_rep_->timescale_int_;
}

Expand Down Expand Up @@ -823,7 +809,7 @@ bool AdaptiveStream::ensureSegment()
if (m_fixateInitialization)
return false;

CSegment* nextSegment{nullptr};
const CSegment* nextSegment{nullptr};

if (valid_segment_buffers_ > 0)
{
Expand Down Expand Up @@ -857,11 +843,11 @@ bool AdaptiveStream::ensureSegment()
if (!segment_buffers_[0]->segment.IsInitialization())
{
// Search the same segment on the timeline (which in the meantime may have been updated)
nextSegment = current_rep_->GetSegment(segment_buffers_[0]->segment);
nextSegment = current_rep_->Timeline().Find(segment_buffers_[0]->segment);
}
}
else
nextSegment = current_rep_->get_next_segment(current_rep_->current_segment_);
nextSegment = current_rep_->GetNextSegment();

if (!nextSegment && (m_tree->HasManifestUpdates() || m_tree->HasManifestUpdatesSegs()) &&
!m_tree->IsLastSegment(current_period_, current_rep_, current_rep_->current_segment_))
Expand All @@ -873,7 +859,7 @@ bool AdaptiveStream::ensureSegment()
getSegmentPos()))
{
//! @todo: seem to be possible get the segment from InsertLiveSegment and then avoid call get_next_segment
nextSegment = current_rep_->get_next_segment(current_rep_->current_segment_);
nextSegment = current_rep_->GetNextSegment();
}

if (!nextSegment && !current_rep_->IsWaitForSegment())
Expand All @@ -892,7 +878,7 @@ bool AdaptiveStream::ensureSegment()
(nextSegment->startPTS_ * current_rep_->timescale_ext_) / current_rep_->timescale_int_;

absolutePTSOffset_ =
(current_rep_->SegmentTimeline().Get(0)->startPTS_ * current_rep_->timescale_ext_) /
(current_rep_->Timeline().Get(0)->startPTS_ * current_rep_->timescale_ext_) /
current_rep_->timescale_int_;

current_rep_->current_segment_ = nextSegment;
Expand All @@ -904,7 +890,7 @@ bool AdaptiveStream::ensureSegment()
observer_->OnSegmentChanged(this);
}

const size_t nextSegPos = current_rep_->get_segment_pos(nextSegment);
const size_t nextSegPos = current_rep_->Timeline().GetPos(nextSegment);

CRepresentation* newRep = current_rep_;
bool isBufferFull = valid_segment_buffers_ >= max_buffer_length_;
Expand All @@ -916,7 +902,7 @@ bool AdaptiveStream::ensureSegment()
CRepresentation* prevRep = segment_buffers_[available_segment_buffers_ - 1]->rep;

bool isLastSegment = nextSegPos + available_segment_buffers_ ==
current_rep_->SegmentTimeline().GetSize() - 1;
current_rep_->Timeline().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
Expand All @@ -937,24 +923,24 @@ bool AdaptiveStream::ensureSegment()
m_tree->OnStreamChange(current_period_, current_adp_, current_rep_, newRep);

// If the representation has been changed, segments may have to be generated (DASH)
if (newRep->SegmentTimeline().IsEmpty())
if (newRep->Timeline().IsEmpty())
GenerateSidxSegments(newRep);
}
}

// Add to the buffer next segment (and the next following segments, if available)

const size_t maxPos = newRep->SegmentTimeline().GetSize();
const size_t maxPos = newRep->Timeline().GetSize();
size_t segPos;

if (available_segment_buffers_ == 0) // Buffer empty, add the current segment
segPos = nextSegPos;
else // Continue adding segments that follow the last one added in to the buffer
{
CSegment* followSeg =
current_rep_->GetNextSegment(segment_buffers_[available_segment_buffers_ - 1]->segment);
const CSegment* followSeg =
current_rep_->Timeline().GetNext(&segment_buffers_[available_segment_buffers_ - 1]->segment);
if (followSeg)
segPos = current_rep_->get_segment_pos(followSeg);
segPos = current_rep_->Timeline().GetPos(followSeg);
else // No segment, EOS or you need to wait next manifest update
segPos = maxPos;
}
Expand All @@ -964,10 +950,10 @@ bool AdaptiveStream::ensureSegment()
//! this can cause a bad initial buffering because the stream dont fit the bandwidth.
for (size_t index = available_segment_buffers_; index < max_buffer_length_; ++index)
{
if (segPos == maxPos) // To avoid out-of-range log prints with get_segment
if (segPos == maxPos) // To avoid out-of-range log prints with Timeline().Get
break;

const CSegment* futureSegment = newRep->get_segment(segPos);
const CSegment* futureSegment = newRep->Timeline().Get(segPos);
if (futureSegment)
{
segment_buffers_[index]->segment = *futureSegment;
Expand Down Expand Up @@ -1108,19 +1094,19 @@ bool AdaptiveStream::retrieveCurrentSegmentBufferSize(size_t& size)

uint64_t AdaptiveStream::getMaxTimeMs()
{
if (current_rep_->SegmentTimeline().IsEmpty())
if (current_rep_->Timeline().IsEmpty())
return 0;

uint64_t duration{0};
if (current_rep_->SegmentTimeline().GetSize() > 1)
if (current_rep_->Timeline().GetSize() > 1)
{
duration =
current_rep_->SegmentTimeline().Get(current_rep_->SegmentTimeline().GetSize() - 1)->startPTS_ -
current_rep_->SegmentTimeline().Get(current_rep_->SegmentTimeline().GetSize() - 2)->startPTS_;
current_rep_->Timeline().Get(current_rep_->Timeline().GetSize() - 1)->startPTS_ -
current_rep_->Timeline().Get(current_rep_->Timeline().GetSize() - 2)->startPTS_;
}

uint64_t timeExt = ((current_rep_->SegmentTimeline()
.Get(current_rep_->SegmentTimeline().GetSize() - 1)
uint64_t timeExt = ((current_rep_->Timeline()
.Get(current_rep_->Timeline().GetSize() - 1)
->startPTS_ +
duration) *
current_rep_->timescale_ext_) /
Expand All @@ -1145,7 +1131,7 @@ void AdaptiveStream::ResetCurrentSegment(const PLAYLIST::CSegment* newSegment)
WaitWorker();
// EnsureSegment loads always the next segment, so go back 1
current_rep_->current_segment_ =
current_rep_->get_segment(current_rep_->get_segment_pos(newSegment) - 1);
current_rep_->Timeline().Get(current_rep_->Timeline().GetPos(newSegment) - 1);
// TODO: if new segment is already prefetched, don't ResetActiveBuffer;
ResetActiveBuffer(false);
}
Expand Down Expand Up @@ -1199,43 +1185,43 @@ bool AdaptiveStream::seek_time(double seek_seconds, bool preceeding, bool& needR
//Skip initialization
size_t choosen_seg{0};

while (choosen_seg < current_rep_->SegmentTimeline().GetSize() &&
sec_in_ts > current_rep_->get_segment(choosen_seg)->startPTS_)
while (choosen_seg < current_rep_->Timeline().GetSize() &&
sec_in_ts > current_rep_->Timeline().Get(choosen_seg)->startPTS_)
{
++choosen_seg;
}

if (choosen_seg == current_rep_->SegmentTimeline().GetSize())
if (choosen_seg == current_rep_->Timeline().GetSize())
{
if (!current_rep_->SegmentTimeline().Get(0))
if (!current_rep_->Timeline().Get(0))
{
LOG::LogF(LOGERROR, "[AS-%u] Segment at position 0 not found from representation id: %s",
clsId, current_rep_->GetId().data());
return false;
}

if (sec_in_ts < current_rep_->SegmentTimeline().Get(0)->startPTS_ + current_rep_->GetDuration())
if (sec_in_ts < current_rep_->Timeline().Get(0)->startPTS_ + current_rep_->GetDuration())
--choosen_seg;
else
return false;
}

if (choosen_seg && current_rep_->get_segment(choosen_seg)->startPTS_ > sec_in_ts)
if (choosen_seg && current_rep_->Timeline().Get(choosen_seg)->startPTS_ > sec_in_ts)
--choosen_seg;

// Never seek into expired segments.....
if (choosen_seg < current_rep_->expired_segments_)
choosen_seg = current_rep_->expired_segments_;

if (!preceeding && sec_in_ts > current_rep_->get_segment(choosen_seg)->startPTS_ &&
if (!preceeding && sec_in_ts > current_rep_->Timeline().Get(choosen_seg)->startPTS_ &&
current_adp_->GetStreamType() == StreamType::VIDEO)
{
//Assume that we have I-Frames only at segment start
++choosen_seg;
}

CSegment* old_seg = current_rep_->current_segment_;
const CSegment* newSeg = current_rep_->get_segment(choosen_seg);
const CSegment* old_seg = current_rep_->current_segment_;
const CSegment* newSeg = current_rep_->Timeline().Get(choosen_seg);

if (newSeg)
{
Expand Down Expand Up @@ -1267,7 +1253,7 @@ bool AdaptiveStream::seek_time(double seek_seconds, bool preceeding, bool& needR

size_t adaptive::AdaptiveStream::getSegmentPos()
{
return current_rep_->getCurrentSegmentPos();
return current_rep_->Timeline().GetPos(current_rep_->current_segment_);
}

bool AdaptiveStream::waitingForSegment() const
Expand Down
Loading

0 comments on commit 70b0bba

Please sign in to comment.