Skip to content

Commit

Permalink
[HLS] rework multi-period / encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
peak3d committed Apr 25, 2020
1 parent ca2fd36 commit 36a2cff
Show file tree
Hide file tree
Showing 15 changed files with 1,611 additions and 1,134 deletions.
2 changes: 1 addition & 1 deletion src/SSD_dll.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace SSD
virtual bool CURLOpen(void* file) = 0;
virtual size_t ReadFile(void* file, void* lpBuf, size_t uiBufSize) = 0;
virtual void CloseFile(void* file) = 0;
virtual bool CreateDirectory(const char *dir) = 0;
virtual bool CreateDir(const char* dir) = 0;
virtual bool GetBuffer(void* instance, SSD_PICTURE &picture) = 0;
virtual void ReleaseBuffer(void* instance, void *buffer) = 0;

Expand Down
40 changes: 34 additions & 6 deletions src/common/AdaptiveStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int AdaptiveStream::SecondsSinceUpdate() const
return static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - tPoint).count());
}

int AdaptiveStream::SecondsSinceMediaRenewal() const
uint32_t AdaptiveStream::SecondsSinceMediaRenewal() const
{
const std::chrono::time_point<std::chrono::system_clock> &tPoint(lastMediaRenewal_ > tree_.GetLastMediaRenewal() ? lastMediaRenewal_ : tree_.GetLastMediaRenewal());
return static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - tPoint).count());
Expand Down Expand Up @@ -132,10 +132,15 @@ bool AdaptiveStream::write_data(const void *buffer, size_t buffer_size)
return true;
}

bool AdaptiveStream::prepare_stream(const AdaptiveTree::AdaptationSet *adp,
const uint32_t width, const uint32_t height, uint32_t hdcpLimit, uint16_t hdcpVersion,
uint32_t min_bandwidth, uint32_t max_bandwidth, unsigned int repId,
const std::map<std::string, std::string> &media_headers)
bool AdaptiveStream::prepare_stream(AdaptiveTree::AdaptationSet* adp,
const uint32_t width,
const uint32_t height,
uint32_t hdcpLimit,
uint16_t hdcpVersion,
uint32_t min_bandwidth,
uint32_t max_bandwidth,
unsigned int repId,
const std::map<std::string, std::string>& media_headers)
{
width_ = type_ == AdaptiveTree::VIDEO ? width : 0;
height_ = type_ == AdaptiveTree::VIDEO ? height : 0;
Expand Down Expand Up @@ -359,7 +364,7 @@ bool AdaptiveStream::ensureSegment()

if (tree_.HasUpdateThread() && SecondsSinceUpdate() > 1)
{
tree_.RefreshSegments(current_rep_, current_adp_->type_);
tree_.RefreshSegments(current_period_, current_adp_, current_rep_, current_adp_->type_);
lastUpdated_ = std::chrono::system_clock::now();
}

Expand Down Expand Up @@ -456,6 +461,29 @@ bool AdaptiveStream::seek(uint64_t const pos)
return false;
}

bool AdaptiveStream::getSize(unsigned long long& sz)
{
if (stopped_)
return false;

std::unique_lock<std::mutex> lckrw(thread_data_->mutex_rw_);

if (ensureSegment())
{
while (true)
{
if (!download_url_.empty())
{
thread_data_->signal_rw_.wait(lckrw);
continue;
}
sz = segment_buffer_.size();
return true;
}
}
return false;
}

uint64_t AdaptiveStream::getMaxTimeMs()
{
if (current_rep_->flags_ & AdaptiveTree::Representation::SUBTITLESTREAM)
Expand Down
25 changes: 16 additions & 9 deletions src/common/AdaptiveStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ namespace adaptive
AdaptiveStream(AdaptiveTree &tree, AdaptiveTree::StreamType type);
virtual ~AdaptiveStream();
void set_observer(AdaptiveStreamObserver *observer){ observer_ = observer; };
bool prepare_stream(const AdaptiveTree::AdaptationSet *adp,
const uint32_t width, const uint32_t height, uint32_t hdcpLimit, uint16_t hdcpVersion,
uint32_t min_bandwidth, uint32_t max_bandwidth, unsigned int repId,
const std::map<std::string, std::string> &media_headers);
bool prepare_stream(AdaptiveTree::AdaptationSet* adp,
const uint32_t width,
const uint32_t height,
uint32_t hdcpLimit,
uint16_t hdcpVersion,
uint32_t min_bandwidth,
uint32_t max_bandwidth,
unsigned int repId,
const std::map<std::string, std::string>& media_headers);
bool start_stream(const uint32_t seg_offset, uint16_t width, uint16_t height, bool play_timeshift_buffer);
bool restart_stream();
bool select_stream(bool force = false, bool justInit = false, unsigned int repId = 0);
Expand All @@ -64,9 +69,11 @@ namespace adaptive
uint32_t read(void* buffer, uint32_t bytesToRead);
uint64_t tell(){ read(0, 0); return absolute_position_; };
bool seek(uint64_t const pos);
bool getSize(unsigned long long& sz);
bool seek_time(double seek_seconds, bool preceeding, bool &needReset);
AdaptiveTree::AdaptationSet const *getAdaptationSet() { return current_adp_; };
AdaptiveTree::Representation const *getRepresentation(){ return current_rep_; };
AdaptiveTree::Period* getPeriod() { return current_period_; };
AdaptiveTree::AdaptationSet* getAdaptationSet() { return current_adp_; };
AdaptiveTree::Representation* getRepresentation() { return current_rep_; };
double get_download_speed() const { return tree_.get_download_speed(); };
void set_download_speed(double speed) { tree_.set_download_speed(speed); };
size_t getSegmentPos() { return current_rep_->getCurrentSegmentPos(); };
Expand All @@ -84,7 +91,7 @@ namespace adaptive
const std::string& getMediaRenewalUrl() const { return tree_.media_renewal_url_; };
const uint32_t& getMediaRenewalTime() const { return tree_.media_renewal_time_; };
std::string buildDownloadUrl(const std::string &url);
int SecondsSinceMediaRenewal() const;
uint32_t SecondsSinceMediaRenewal() const;
void UpdateSecondsSinceMediaRenewal();
private:
// Segment download section
Expand Down Expand Up @@ -125,8 +132,8 @@ namespace adaptive
AdaptiveTree::StreamType type_;
AdaptiveStreamObserver *observer_;
// Active configuration
const AdaptiveTree::Period *current_period_;
const AdaptiveTree::AdaptationSet *current_adp_;
AdaptiveTree::Period* current_period_;
AdaptiveTree::AdaptationSet* current_adp_;
AdaptiveTree::Representation *current_rep_;
std::string download_url_;
//We assume that a single segment can build complete frames
Expand Down
93 changes: 88 additions & 5 deletions src/common/AdaptiveTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,26 +176,109 @@ namespace adaptive
memcpy(dst + dstOffset, src, dataSize);
}

uint16_t AdaptiveTree::insert_psshset(StreamType type)
uint16_t AdaptiveTree::insert_psshset(StreamType type,
AdaptiveTree::Period* period,
AdaptiveTree::AdaptationSet* adp)
{
if (!period)
period = current_period_;
if (!adp)
adp = current_adaptationset_;

if (!current_pssh_.empty())
{
Period::PSSH pssh;
pssh.pssh_ = current_pssh_;
pssh.defaultKID_ = current_defaultKID_;
pssh.iv = current_iv_;
pssh.adaptation_set_ = current_adaptationset_;
pssh.adaptation_set_ = adp;
switch (type)
{
case VIDEO: pssh.media_ = Period::PSSH::MEDIA_VIDEO; break;
case AUDIO: pssh.media_ = Period::PSSH::MEDIA_AUDIO; break;
case STREAM_TYPE_COUNT: pssh.media_ = Period::PSSH::MEDIA_VIDEO | Period::PSSH::MEDIA_AUDIO; break;
default: pssh.media_ = 0; break;
}
return current_period_->InsertPSSHSet(&pssh);
return period->InsertPSSHSet(&pssh);
}
else
return current_period_->InsertPSSHSet(nullptr);
return period->InsertPSSHSet(nullptr);
}

void AdaptiveTree::Representation::CopyBasicData(Representation* src)
{
url_ = src->url_;
id = src->id;
codecs_ = src->codecs_;
codec_private_data_ = src->codec_private_data_;
source_url_ = src->source_url_;
bandwidth_ = src->bandwidth_;
samplingRate_ = src->samplingRate_;
width_ = src->width_;
height_ = src->height_;
fpsRate_ = src->fpsRate_;
aspect_ = src->aspect_;
flags_ = src->flags_;
hdcpVersion_ = src->hdcpVersion_;
channelCount_ = src->channelCount_;
nalLengthSize_ = src->nalLengthSize_;
containerType_ = src->containerType_;
timescale_ = src->timescale_;
timescale_ext_ = src->timescale_ext_;
timescale_int_ = src->timescale_int_;
}

void AdaptiveTree::AdaptationSet::CopyBasicData(AdaptiveTree::AdaptationSet* src)
{
representations_.resize(src->representations_.size());
auto itRep = src->representations_.begin();
for (Representation*& rep : representations_)
{
rep = new Representation();
rep->CopyBasicData(*itRep++);
}

type_ = src->type_;
timescale_ = src->timescale_;
duration_ = src->duration_;
startPTS_ = src->startPTS_;
startNumber_ = src->startNumber_;
impaired_ = src->impaired_;
original_ = src->original_;
default_ = src->default_;
forced_ = src->forced_;
language_ = src->language_;
mimeType_ = src->mimeType_;
base_url_ = src->base_url_;
id_ = src->id_;
group_ = src->group_;
codecs_ = src->codecs_;
audio_track_id_ = src->audio_track_id_;
name_ = src->name_;
}

// Create a HLS master playlist copy (no representations)
void AdaptiveTree::Period::CopyBasicData(AdaptiveTree::Period* period)
{
adaptationSets_.resize(period->adaptationSets_.size());
auto itAdp = period->adaptationSets_.begin();
for (AdaptationSet*& adp : adaptationSets_)
{
adp = new AdaptationSet();
adp->CopyBasicData(*itAdp++);
}

base_url_ = period->base_url_;
id_ = period->id_;
timescale_ = period->timescale_;
startNumber_ = period->startNumber_;

start_ = period->start_;
startPTS_ = period->startPTS_;
duration_ = period->duration_;
encryptionState_ = period->encryptionState_;
included_types_ = period->included_types_;
need_secure_decoder_ = period->need_secure_decoder_;
}

uint16_t AdaptiveTree::Period::InsertPSSHSet(PSSH* pssh)
Expand Down Expand Up @@ -347,7 +430,7 @@ namespace adaptive
{
std::lock_guard<std::mutex> lck(treeMutex_);
lastUpdated_ = std::chrono::system_clock::now();
RefreshSegments();
RefreshLiveSegments();
}
}
}
Expand Down
36 changes: 31 additions & 5 deletions src/common/AdaptiveTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class AdaptiveTree
CONTAINERTYPE_ADTS,
CONTAINERTYPE_WEBM,
CONTAINERTYPE_MATROSKA,
CONTAINERTYPE_TEXT,
};

enum
Expand All @@ -119,6 +120,13 @@ class AdaptiveTree
ENCRYTIONSTATE_SUPPORTED = 2
};

enum PREPARE_RESULT
{
PREPARE_RESULT_FAILURE,
PREPARE_RESULT_OK,
PREPARE_RESULT_DRMCHANGED,
};

// Node definition
struct Segment
{
Expand Down Expand Up @@ -147,6 +155,7 @@ class AdaptiveTree
initialization_.range_begin_ = initialization_.range_end_ = ~0ULL;
initialization_.url = nullptr;
};
void CopyBasicData(Representation* src);
~Representation() {
if (flags_ & Representation::URLSEGMENTS)
{
Expand Down Expand Up @@ -263,6 +272,7 @@ class AdaptiveTree
{
AdaptationSet() :type_(NOTYPE), timescale_(0), duration_(0), startPTS_(0), startNumber_(1), impaired_(false), original_(false), default_(false), forced_(false){ language_ = "unk"; };
~AdaptationSet() { for (std::vector<Representation* >::const_iterator b(representations_.begin()), e(representations_.end()); b != e; ++b) delete *b; };
void CopyBasicData(AdaptationSet* src);
StreamType type_;
uint32_t timescale_;
uint64_t duration_;
Expand Down Expand Up @@ -380,7 +390,9 @@ class AdaptiveTree

Period() { psshSets_.push_back(PSSH()); };
~Period() { for (std::vector<AdaptationSet* >::const_iterator b(adaptationSets_.begin()), e(adaptationSets_.end()); b != e; ++b) delete *b; };
void CopyBasicData(Period*);
uint16_t InsertPSSHSet(PSSH* pssh);
void InsertPSSHSet(uint16_t pssh_set) { ++psshSets_[pssh_set].use_count_; };
void RemovePSSHSet(uint16_t pssh_set);

std::vector<AdaptationSet*> adaptationSets_;
Expand Down Expand Up @@ -436,9 +448,18 @@ class AdaptiveTree
virtual ~AdaptiveTree();

virtual bool open(const std::string &url, const std::string &manifestUpdateParam) = 0;
virtual bool prepareRepresentation(Representation *rep, bool update = false) { return true; };
virtual PREPARE_RESULT prepareRepresentation(Period* period,
AdaptationSet* adp,
Representation* rep,
bool update = false)
{
return PREPARE_RESULT_OK;
};
virtual void OnDataArrived(unsigned int segNum, uint16_t psshSet, uint8_t iv[16], const uint8_t *src, uint8_t *dst, size_t dstOffset, size_t dataSize);
virtual void RefreshSegments(Representation *rep, StreamType type) {};
virtual void RefreshSegments(Period* period,
AdaptationSet* adp,
Representation* rep,
StreamType type){};

bool has_type(StreamType t);
void FreeSegments(Representation *rep);
Expand All @@ -447,10 +468,15 @@ class AdaptiveTree
double get_average_download_speed() const { return average_download_speed_; };
void set_download_speed(double speed);
void SetFragmentDuration(const AdaptationSet* adp, const Representation* rep, size_t pos, uint64_t timestamp, uint32_t fragmentDuration, uint32_t movie_timescale);
uint16_t insert_psshset(StreamType type);
uint16_t insert_psshset(StreamType type, Period* period = nullptr, AdaptationSet* adp = nullptr);

bool empty(){ return periods_.empty(); };
const AdaptationSet *GetAdaptationSet(unsigned int pos) const { return current_period_ && pos < current_period_->adaptationSets_.size() ? current_period_->adaptationSets_[pos] : 0; };
AdaptationSet* GetAdaptationSet(unsigned int pos) const
{
return current_period_ && pos < current_period_->adaptationSets_.size()
? current_period_->adaptationSets_[pos]
: 0;
};
std::mutex &GetTreeMutex() { return treeMutex_; };
bool HasUpdateThread() const { return updateThread_ != 0 && has_timeshift_buffer_ && updateInterval_ && !update_parameter_.empty(); };
void RefreshUpdateThread();
Expand All @@ -465,7 +491,7 @@ class AdaptiveTree

// Live segment update section
virtual void StartUpdateThread();
virtual void RefreshSegments() {};
virtual void RefreshLiveSegments(){};

uint32_t updateInterval_;
std::mutex treeMutex_, updateMutex_;
Expand Down
Loading

0 comments on commit 36a2cff

Please sign in to comment.