Commit 458adc37 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: handle alternative streams

parent 69361064
......@@ -51,31 +51,37 @@ PlaylistManager::PlaylistManager( AbstractPlaylist *pl,
stream ( stream ),
nextPlaylistupdate ( 0 )
{
currentPeriod = playlist->getFirstPeriod();
}
PlaylistManager::~PlaylistManager ()
{
delete conManager;
delete streamOutputFactory;
unsetPeriod();
}
void PlaylistManager::unsetPeriod()
{
std::vector<Stream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
delete *it;
streams.clear();
}
bool PlaylistManager::start(demux_t *demux)
bool PlaylistManager::setupPeriod()
{
const BasePeriod *period = playlist->getFirstPeriod();
if(!period)
if(!currentPeriod)
return false;
for(int i=0; i<StreamTypeCount; i++)
std::vector<BaseAdaptationSet*> sets = currentPeriod->getAdaptationSets();
std::vector<BaseAdaptationSet*>::iterator it;
for(it=sets.begin();it!=sets.end();++it)
{
StreamType type = static_cast<StreamType>(i);
const BaseAdaptationSet *set = period->getAdaptationSet(type);
BaseAdaptationSet *set = *it;
if(set)
{
Stream *st = new (std::nothrow) Stream(demux, type, set->getStreamFormat());
Stream *st = new (std::nothrow) Stream(p_demux, set->getStreamFormat());
if(!st)
continue;
AbstractAdaptationLogic *logic = createLogic(logicType);
......@@ -85,7 +91,7 @@ bool PlaylistManager::start(demux_t *demux)
continue;
}
SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, playlist);
SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, set);
try
{
if(!tracker || !streamOutputFactory)
......@@ -101,6 +107,15 @@ bool PlaylistManager::start(demux_t *demux)
}
}
}
return true;
}
bool PlaylistManager::start(demux_t *demux_)
{
p_demux = demux_;
if(!setupPeriod())
return false;
conManager = new (std::nothrow) HTTPConnectionManager(VLC_OBJECT(stream));
if(!conManager)
......@@ -119,7 +134,17 @@ Stream::status PlaylistManager::demux(mtime_t nzdeadline, bool send)
std::vector<Stream *>::iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
{
Stream::status i_ret = (*it)->demux(conManager, nzdeadline, send);
Stream *st = *it;
if (st->isDisabled())
{
if(st->isSelected() && !st->isEOF())
st->reactivate(getPCR());
else
continue;
}
Stream::status i_ret = st->demux(conManager, nzdeadline, send);
if(i_ret == Stream::status_buffering)
{
......@@ -141,6 +166,8 @@ mtime_t PlaylistManager::getPCR() const
std::vector<Stream *>::const_iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
{
if ((*it)->isDisabled())
continue;
if(pcr == VLC_TS_INVALID || pcr > (*it)->getPCR())
pcr = (*it)->getPCR();
}
......@@ -153,6 +180,8 @@ mtime_t PlaylistManager::getFirstDTS() const
std::vector<Stream *>::const_iterator it;
for(it=streams.begin(); it!=streams.end(); ++it)
{
if ((*it)->isDisabled())
continue;
if(dts == VLC_TS_INVALID || dts > (*it)->getFirstDTS())
dts = (*it)->getFirstDTS();
}
......
......@@ -31,6 +31,7 @@ namespace adaptative
namespace playlist
{
class AbstractPlaylist;
class BasePeriod;
}
namespace http
......@@ -67,6 +68,8 @@ namespace adaptative
virtual bool updatePlaylist();
protected:
bool setupPeriod();
void unsetPeriod();
/* local factories */
virtual AbstractAdaptationLogic *createLogic(AbstractAdaptationLogic::LogicType);
......@@ -75,8 +78,10 @@ namespace adaptative
AbstractPlaylist *playlist;
AbstractStreamOutputFactory *streamOutputFactory;
stream_t *stream;
demux_t *p_demux;
std::vector<Stream *> streams;
mtime_t nextPlaylistupdate;
BasePeriod *currentPeriod;
};
}
......
......@@ -20,6 +20,7 @@
#include "SegmentTracker.hpp"
#include "playlist/AbstractPlaylist.hpp"
#include "playlist/BaseRepresentation.h"
#include "playlist/BaseAdaptationSet.h"
#include "playlist/Segment.h"
#include "logic/AbstractAdaptationLogic.h"
......@@ -27,15 +28,14 @@ using namespace adaptative;
using namespace adaptative::logic;
using namespace adaptative::playlist;
SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, AbstractPlaylist *playlist_)
SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSet *adaptSet)
{
count = 0;
initializing = true;
indexed = false;
prevRepresentation = NULL;
setAdaptationLogic(logic_);
playlist = playlist_;
currentPeriod = playlist->getFirstPeriod();
adaptationSet = adaptSet;
}
SegmentTracker::~SegmentTracker()
......@@ -54,19 +54,19 @@ void SegmentTracker::resetCounter()
prevRepresentation = NULL;
}
SegmentChunk * SegmentTracker::getNextChunk(StreamType type, bool switch_allowed)
SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed)
{
BaseRepresentation *rep;
ISegment *segment;
if(!currentPeriod)
if(!adaptationSet)
return NULL;
if( !switch_allowed ||
(prevRepresentation && prevRepresentation->getSwitchPolicy() == SegmentInformation::SWITCH_UNAVAILABLE) )
rep = prevRepresentation;
else
rep = logic->getCurrentRepresentation(type, currentPeriod);
rep = logic->getCurrentRepresentation(adaptationSet);
if ( rep == NULL )
return NULL;
......@@ -96,9 +96,8 @@ SegmentChunk * SegmentTracker::getNextChunk(StreamType type, bool switch_allowed
segment = rep->getSegment(BaseRepresentation::INFOTYPE_MEDIA, count);
if(!segment)
{
currentPeriod = playlist->getNextPeriod(currentPeriod);
resetCounter();
return getNextChunk(type, switch_allowed);
return NULL;
}
SegmentChunk *chunk = segment->toChunk(count, rep);
......@@ -135,6 +134,7 @@ mtime_t SegmentTracker::getSegmentStart() const
void SegmentTracker::pruneFromCurrent()
{
AbstractPlaylist *playlist = adaptationSet->getPlaylist();
if(playlist->isLive())
playlist->pruneBySegmentNumber(count);
}
......@@ -36,8 +36,7 @@ namespace adaptative
namespace playlist
{
class AbstractPlaylist;
class BasePeriod;
class BaseAdaptationSet;
class BaseRepresentation;
class SegmentChunk;
}
......@@ -48,12 +47,12 @@ namespace adaptative
class SegmentTracker
{
public:
SegmentTracker(AbstractAdaptationLogic *, AbstractPlaylist *);
SegmentTracker(AbstractAdaptationLogic *, BaseAdaptationSet *);
~SegmentTracker();
void setAdaptationLogic(AbstractAdaptationLogic *);
void resetCounter();
SegmentChunk* getNextChunk(StreamType, bool);
SegmentChunk* getNextChunk(bool);
bool setPosition(mtime_t, bool, bool);
mtime_t getSegmentStart() const;
void pruneFromCurrent();
......@@ -63,8 +62,7 @@ namespace adaptative
bool indexed;
uint64_t count;
AbstractAdaptationLogic *logic;
AbstractPlaylist *playlist;
BasePeriod *currentPeriod;
BaseAdaptationSet *adaptationSet;
BaseRepresentation *prevRepresentation;
};
}
......
......@@ -31,15 +31,16 @@ using namespace adaptative;
using namespace adaptative::http;
using namespace adaptative::logic;
Stream::Stream(demux_t * demux_,const StreamType type_, const StreamFormat &format_)
Stream::Stream(demux_t * demux_, const StreamFormat &format_)
{
p_demux = demux_;
type = type_;
type = StreamType::UNKNOWN;
format = format_;
output = NULL;
adaptationLogic = NULL;
currentChunk = NULL;
eof = false;
disabled = false;
segmentTracker = NULL;
streamOutputFactory = NULL;
}
......@@ -129,7 +130,12 @@ SegmentChunk * Stream::getChunk()
{
if (currentChunk == NULL && output)
{
currentChunk = segmentTracker->getNextChunk(type, output->switchAllowed());
if(esCount() && !isSelected())
{
disabled = true;
return NULL;
}
currentChunk = segmentTracker->getNextChunk(output->switchAllowed());
if (currentChunk == NULL)
eof = true;
}
......@@ -146,6 +152,25 @@ bool Stream::isSelected() const
return output && output->isSelected();
}
bool Stream::reactivate(mtime_t basetime)
{
if(setPosition(basetime, false))
{
disabled = false;
return true;
}
else
{
eof = true; /* can't reactivate */
return false;
}
}
bool Stream::isDisabled() const
{
return disabled;
}
Stream::status Stream::demux(HTTPConnectionManager *connManager, mtime_t nz_deadline, bool send)
{
if(!output)
......
......@@ -61,7 +61,7 @@ namespace adaptative
class Stream
{
public:
Stream(demux_t *, const StreamType, const StreamFormat &);
Stream(demux_t *, const StreamFormat &);
~Stream();
bool operator==(const Stream &) const;
static StreamType mimeToType(const std::string &mime);
......@@ -75,6 +75,8 @@ namespace adaptative
int esCount() const;
bool seekAble() const;
bool isSelected() const;
bool reactivate(mtime_t);
bool isDisabled() const;
typedef enum {status_eof, status_buffering, status_demuxed} status;
status demux(HTTPConnectionManager *, mtime_t, bool);
bool setPosition(mtime_t, bool);
......@@ -91,6 +93,7 @@ namespace adaptative
AbstractAdaptationLogic *adaptationLogic;
SegmentTracker *segmentTracker;
SegmentChunk *currentChunk;
bool disabled;
bool eof;
const AbstractStreamOutputFactory *streamOutputFactory;
......
......@@ -26,14 +26,13 @@
#define ABSTRACTADAPTATIONLOGIC_H_
#include "IDownloadRateObserver.h"
#include "../StreamsType.hpp"
namespace adaptative
{
namespace playlist
{
class BaseRepresentation;
class BasePeriod;
class BaseAdaptationSet;
}
namespace logic
......@@ -46,7 +45,7 @@ namespace adaptative
AbstractAdaptationLogic ();
virtual ~AbstractAdaptationLogic ();
virtual BaseRepresentation* getCurrentRepresentation(StreamType, BasePeriod *) const = 0;
virtual BaseRepresentation* getCurrentRepresentation(BaseAdaptationSet *) const = 0;
virtual void updateDownloadRate (size_t, mtime_t);
enum LogicType
......
......@@ -36,8 +36,8 @@ AlwaysBestAdaptationLogic::AlwaysBestAdaptationLogic () :
{
}
BaseRepresentation *AlwaysBestAdaptationLogic::getCurrentRepresentation(adaptative::StreamType type, BasePeriod *period) const
BaseRepresentation *AlwaysBestAdaptationLogic::getCurrentRepresentation(BaseAdaptationSet *adaptSet) const
{
RepresentationSelector selector;
return selector.select(period, type);
return selector.select(adaptSet);
}
......@@ -36,7 +36,7 @@ namespace adaptative
public:
AlwaysBestAdaptationLogic ();
virtual BaseRepresentation *getCurrentRepresentation(StreamType, BasePeriod *) const;
virtual BaseRepresentation *getCurrentRepresentation(BaseAdaptationSet *) const;
};
}
}
......
......@@ -28,8 +28,8 @@ AlwaysLowestAdaptationLogic::AlwaysLowestAdaptationLogic():
{
}
BaseRepresentation *AlwaysLowestAdaptationLogic::getCurrentRepresentation(adaptative::StreamType type, BasePeriod *period) const
BaseRepresentation *AlwaysLowestAdaptationLogic::getCurrentRepresentation(BaseAdaptationSet *adaptSet) const
{
RepresentationSelector selector;
return selector.select(period, type, 0);
return selector.select(adaptSet, 0);
}
......@@ -31,7 +31,7 @@ namespace adaptative
public:
AlwaysLowestAdaptationLogic();
virtual BaseRepresentation* getCurrentRepresentation(StreamType, BasePeriod *) const;
virtual BaseRepresentation* getCurrentRepresentation(BaseAdaptationSet *) const;
};
}
}
......
......@@ -47,16 +47,16 @@ RateBasedAdaptationLogic::RateBasedAdaptationLogic (int w, int h) :
stabilizer = 16;
}
BaseRepresentation *RateBasedAdaptationLogic::getCurrentRepresentation(adaptative::StreamType type, BasePeriod *period) const
BaseRepresentation *RateBasedAdaptationLogic::getCurrentRepresentation(BaseAdaptationSet *adaptSet) const
{
if(period == NULL)
if(adaptSet == NULL)
return NULL;
RepresentationSelector selector;
BaseRepresentation *rep = selector.select(period, type, currentBps, width, height);
BaseRepresentation *rep = selector.select(adaptSet, currentBps, width, height);
if ( rep == NULL )
{
rep = selector.select(period, type);
rep = selector.select(adaptSet);
if ( rep == NULL )
return NULL;
}
......@@ -98,16 +98,16 @@ FixedRateAdaptationLogic::FixedRateAdaptationLogic(size_t bps) :
currentBps = bps;
}
BaseRepresentation *FixedRateAdaptationLogic::getCurrentRepresentation(adaptative::StreamType type, BasePeriod *period) const
BaseRepresentation *FixedRateAdaptationLogic::getCurrentRepresentation(BaseAdaptationSet *adaptSet) const
{
if(period == NULL)
if(adaptSet == NULL)
return NULL;
RepresentationSelector selector;
BaseRepresentation *rep = selector.select(period, type, currentBps);
BaseRepresentation *rep = selector.select(adaptSet, currentBps);
if ( rep == NULL )
{
rep = selector.select(period, type);
rep = selector.select(adaptSet);
if ( rep == NULL )
return NULL;
}
......
......@@ -39,7 +39,7 @@ namespace adaptative
public:
RateBasedAdaptationLogic (int, int);
BaseRepresentation *getCurrentRepresentation(StreamType, BasePeriod *) const;
BaseRepresentation *getCurrentRepresentation(BaseAdaptationSet *) const;
virtual void updateDownloadRate(size_t, mtime_t);
private:
......@@ -57,7 +57,7 @@ namespace adaptative
public:
FixedRateAdaptationLogic(size_t);
BaseRepresentation *getCurrentRepresentation(StreamType, BasePeriod *) const;
BaseRepresentation *getCurrentRepresentation(BaseAdaptationSet *) const;
private:
size_t currentBps;
......
......@@ -29,22 +29,17 @@ RepresentationSelector::RepresentationSelector()
{
}
BaseRepresentation * RepresentationSelector::select(BasePeriod *period, adaptative::StreamType type) const
BaseRepresentation * RepresentationSelector::select(BaseAdaptationSet *adaptSet) const
{
return select(period, type, std::numeric_limits<uint64_t>::max());
return select(adaptSet, std::numeric_limits<uint64_t>::max());
}
BaseRepresentation * RepresentationSelector::select(BasePeriod *period, adaptative::StreamType type, uint64_t bitrate) const
BaseRepresentation * RepresentationSelector::select(BaseAdaptationSet *adaptSet, uint64_t bitrate) const
{
if (period == NULL)
if (adaptSet == NULL)
return NULL;
std::vector<BaseAdaptationSet *> adaptSets = period->getAdaptationSets(type);
BaseRepresentation *best = NULL;
std::vector<BaseAdaptationSet *>::const_iterator adaptIt;
for(adaptIt=adaptSets.begin(); adaptIt!=adaptSets.end(); ++adaptIt)
{
std::vector<BaseRepresentation *> reps = (*adaptIt)->getRepresentations();
std::vector<BaseRepresentation *> reps = adaptSet->getRepresentations();
BaseRepresentation *candidate = select(reps, (best)?best->getBandwidth():0, bitrate);
if (candidate)
{
......@@ -52,34 +47,29 @@ BaseRepresentation * RepresentationSelector::select(BasePeriod *period, adaptati
return candidate;
best = candidate;
}
}
return best;
}
BaseRepresentation * RepresentationSelector::select(BasePeriod *period, adaptative::StreamType type, uint64_t bitrate,
BaseRepresentation * RepresentationSelector::select(BaseAdaptationSet *adaptSet, uint64_t bitrate,
int width, int height) const
{
if(period == NULL)
if(adaptSet == NULL)
return NULL;
std::vector<BaseRepresentation *> resMatchReps;
/* subset matching WxH */
std::vector<BaseAdaptationSet *> adaptSets = period->getAdaptationSets(type);
std::vector<BaseAdaptationSet *>::const_iterator adaptIt;
for(adaptIt=adaptSets.begin(); adaptIt!=adaptSets.end(); ++adaptIt)
{
std::vector<BaseRepresentation *> reps = (*adaptIt)->getRepresentations();
std::vector<BaseRepresentation *> reps = adaptSet->getRepresentations();
std::vector<BaseRepresentation *>::const_iterator repIt;
for(repIt=reps.begin(); repIt!=reps.end(); ++repIt)
{
if((*repIt)->getWidth() == width && (*repIt)->getHeight() == height)
resMatchReps.push_back(*repIt);
}
}
if(resMatchReps.empty())
return select(period, type, bitrate);
return select(adaptSet, bitrate);
else
return select(resMatchReps, 0, bitrate);
}
......
......@@ -20,15 +20,15 @@
#ifndef REPRESENTATIONSELECTORS_HPP
#define REPRESENTATIONSELECTORS_HPP
#include "../Streams.hpp"
#include <vector>
#include <vlc_common.h>
namespace adaptative
{
namespace playlist
{
class BaseRepresentation;
class BasePeriod;
class BaseAdaptationSet;
}
namespace logic
......@@ -40,9 +40,9 @@ namespace adaptative
public:
RepresentationSelector();
virtual ~RepresentationSelector() {}
virtual BaseRepresentation * select(BasePeriod *period, StreamType) const;
virtual BaseRepresentation * select(BasePeriod *period, StreamType, uint64_t bitrate) const;
virtual BaseRepresentation * select(BasePeriod *period, StreamType, uint64_t bitrate,
virtual BaseRepresentation * select(BaseAdaptationSet *) const;
virtual BaseRepresentation * select(BaseAdaptationSet *, uint64_t bitrate) const;
virtual BaseRepresentation * select(BaseAdaptationSet *, uint64_t bitrate,
int width, int height) const;
protected:
virtual BaseRepresentation * select(std::vector<BaseRepresentation *>&reps,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment