Commit 5f49de18 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: refactor and allow restart on seek

Since we have no real way to drain stream demux fifo,
we should have a way to reset demuxer before switching to
a new segment.
parent eb92562d
...@@ -107,14 +107,18 @@ Chunk * SegmentTracker::getNextChunk(StreamType type) ...@@ -107,14 +107,18 @@ Chunk * SegmentTracker::getNextChunk(StreamType type)
return chunk; return chunk;
} }
bool SegmentTracker::setPosition(mtime_t time, bool tryonly) bool SegmentTracker::setPosition(mtime_t time, bool restarted, bool tryonly)
{ {
uint64_t segcount; uint64_t segcount;
if(prevRepresentation && if(prevRepresentation &&
prevRepresentation->getSegmentNumberByTime(time, &segcount)) prevRepresentation->getSegmentNumberByTime(time, &segcount))
{ {
if(!tryonly) if(!tryonly)
{
if(restarted)
initializing = true;
count = segcount; count = segcount;
}
return true; return true;
} }
return false; return false;
......
...@@ -59,7 +59,7 @@ namespace adaptative ...@@ -59,7 +59,7 @@ namespace adaptative
void setAdaptationLogic(AbstractAdaptationLogic *); void setAdaptationLogic(AbstractAdaptationLogic *);
void resetCounter(); void resetCounter();
Chunk* getNextChunk(StreamType); Chunk* getNextChunk(StreamType);
bool setPosition(mtime_t, bool); bool setPosition(mtime_t, bool, bool);
mtime_t getSegmentStart() const; mtime_t getSegmentStart() const;
private: private:
......
...@@ -227,9 +227,20 @@ size_t Stream::read(HTTPConnectionManager *connManager) ...@@ -227,9 +227,20 @@ size_t Stream::read(HTTPConnectionManager *connManager)
bool Stream::setPosition(mtime_t time, bool tryonly) bool Stream::setPosition(mtime_t time, bool tryonly)
{ {
bool ret = segmentTracker->setPosition(time, tryonly); bool ret = segmentTracker->setPosition(time, output->reinitsOnSeek(), tryonly);
if(!tryonly && ret) if(!tryonly && ret)
{
output->setPosition(time); output->setPosition(time);
if(output->reinitsOnSeek())
{
if(currentChunk)
{
currentChunk->getConnection()->releaseChunk();
delete currentChunk;
}
currentChunk = NULL;
}
}
return ret; return ret;
} }
...@@ -241,10 +252,30 @@ mtime_t Stream::getPosition() const ...@@ -241,10 +252,30 @@ mtime_t Stream::getPosition() const
AbstractStreamOutput::AbstractStreamOutput(demux_t *demux) AbstractStreamOutput::AbstractStreamOutput(demux_t *demux)
{ {
realdemux = demux; realdemux = demux;
demuxstream = NULL;
pcr = VLC_TS_0; pcr = VLC_TS_0;
group = 0; group = 0;
}
AbstractStreamOutput::~AbstractStreamOutput()
{
}
mtime_t AbstractStreamOutput::getPCR() const
{
return pcr;
}
int AbstractStreamOutput::getGroup() const
{
return group;
}
BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
AbstractStreamOutput(demux)
{
this->name = name;
seekable = true; seekable = true;
demuxstream = NULL;
fakeesout = new es_out_t; fakeesout = new es_out_t;
if (!fakeesout) if (!fakeesout)
...@@ -258,9 +289,12 @@ AbstractStreamOutput::AbstractStreamOutput(demux_t *demux) ...@@ -258,9 +289,12 @@ AbstractStreamOutput::AbstractStreamOutput(demux_t *demux)
fakeesout->pf_destroy = esOutDestroy; fakeesout->pf_destroy = esOutDestroy;
fakeesout->pf_send = esOutSend; fakeesout->pf_send = esOutSend;
fakeesout->p_sys = (es_out_sys_t*) this; fakeesout->p_sys = (es_out_sys_t*) this;
if(!restart())
throw VLC_EGENERIC;
} }
AbstractStreamOutput::~AbstractStreamOutput() BaseStreamOutput::~BaseStreamOutput()
{ {
if (demuxstream) if (demuxstream)
stream_Delete(demuxstream); stream_Delete(demuxstream);
...@@ -274,32 +308,22 @@ AbstractStreamOutput::~AbstractStreamOutput() ...@@ -274,32 +308,22 @@ AbstractStreamOutput::~AbstractStreamOutput()
delete *it; delete *it;
} }
mtime_t AbstractStreamOutput::getPCR() const int BaseStreamOutput::esCount() const
{
return pcr;
}
int AbstractStreamOutput::getGroup() const
{
return group;
}
int AbstractStreamOutput::esCount() const
{ {
return queues.size(); return queues.size();
} }
void AbstractStreamOutput::pushBlock(block_t *block) void BaseStreamOutput::pushBlock(block_t *block)
{ {
stream_DemuxSend(demuxstream, block); stream_DemuxSend(demuxstream, block);
} }
bool AbstractStreamOutput::seekAble() const bool BaseStreamOutput::seekAble() const
{ {
return (demuxstream && seekable); return (demuxstream && seekable);
} }
void AbstractStreamOutput::setPosition(mtime_t nztime) void BaseStreamOutput::setPosition(mtime_t nztime)
{ {
vlc_mutex_lock(&lock); vlc_mutex_lock(&lock);
std::list<Demuxed *>::const_iterator it; std::list<Demuxed *>::const_iterator it;
...@@ -309,20 +333,44 @@ void AbstractStreamOutput::setPosition(mtime_t nztime) ...@@ -309,20 +333,44 @@ void AbstractStreamOutput::setPosition(mtime_t nztime)
if(pair->p_queue && pair->p_queue->i_dts > VLC_TS_0 + nztime) if(pair->p_queue && pair->p_queue->i_dts > VLC_TS_0 + nztime)
pair->drop(); pair->drop();
} }
pcr = VLC_TS_0; pcr = VLC_TS_INVALID;
vlc_mutex_unlock(&lock); vlc_mutex_unlock(&lock);
es_out_Control(realdemux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, es_out_Control(realdemux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
VLC_TS_0 + nztime); VLC_TS_0 + nztime);
if(reinitsOnSeek())
restart();
} }
void AbstractStreamOutput::sendToDecoder(mtime_t nzdeadline) bool BaseStreamOutput::restart()
{
stream_t *newdemuxstream = stream_DemuxNew(realdemux, name.c_str(), fakeesout);
if(!newdemuxstream)
return false;
vlc_mutex_lock(&lock);
stream_t *olddemuxstream = demuxstream;
demuxstream = newdemuxstream;
vlc_mutex_unlock(&lock);
if(olddemuxstream)
stream_Delete(olddemuxstream);
return true;
}
bool BaseStreamOutput::reinitsOnSeek() const
{
return false;
}
void BaseStreamOutput::sendToDecoder(mtime_t nzdeadline)
{ {
vlc_mutex_lock(&lock); vlc_mutex_lock(&lock);
sendToDecoderUnlocked(nzdeadline); sendToDecoderUnlocked(nzdeadline);
vlc_mutex_unlock(&lock); vlc_mutex_unlock(&lock);
} }
void AbstractStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline) void BaseStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline)
{ {
std::list<Demuxed *>::const_iterator it; std::list<Demuxed *>::const_iterator it;
for(it=queues.begin(); it!=queues.end();++it) for(it=queues.begin(); it!=queues.end();++it)
...@@ -342,19 +390,19 @@ void AbstractStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline) ...@@ -342,19 +390,19 @@ void AbstractStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline)
} }
} }
AbstractStreamOutput::Demuxed::Demuxed() BaseStreamOutput::Demuxed::Demuxed()
{ {
p_queue = NULL; p_queue = NULL;
pp_queue_last = &p_queue; pp_queue_last = &p_queue;
es_id = NULL; es_id = NULL;
} }
AbstractStreamOutput::Demuxed::~Demuxed() BaseStreamOutput::Demuxed::~Demuxed()
{ {
drop(); drop();
} }
void AbstractStreamOutput::Demuxed::drop() void BaseStreamOutput::Demuxed::drop()
{ {
block_ChainRelease(p_queue); block_ChainRelease(p_queue);
p_queue = NULL; p_queue = NULL;
...@@ -362,9 +410,9 @@ void AbstractStreamOutput::Demuxed::drop() ...@@ -362,9 +410,9 @@ void AbstractStreamOutput::Demuxed::drop()
} }
/* Static callbacks */ /* Static callbacks */
es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt) es_out_id_t * BaseStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt)
{ {
AbstractStreamOutput *me = (AbstractStreamOutput *) fakees->p_sys; BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
es_out_id_t *p_es = me->realdemux->out->pf_add(me->realdemux->out, p_fmt); es_out_id_t *p_es = me->realdemux->out->pf_add(me->realdemux->out, p_fmt);
if(p_es) if(p_es)
{ {
...@@ -380,9 +428,9 @@ es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t ...@@ -380,9 +428,9 @@ es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t
return p_es; return p_es;
} }
int AbstractStreamOutput::esOutSend(es_out_t *fakees, es_out_id_t *p_es, block_t *p_block) int BaseStreamOutput::esOutSend(es_out_t *fakees, es_out_id_t *p_es, block_t *p_block)
{ {
AbstractStreamOutput *me = (AbstractStreamOutput *) fakees->p_sys; BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
vlc_mutex_lock(&me->lock); vlc_mutex_lock(&me->lock);
std::list<Demuxed *>::const_iterator it; std::list<Demuxed *>::const_iterator it;
for(it=me->queues.begin(); it!=me->queues.end();++it) for(it=me->queues.begin(); it!=me->queues.end();++it)
...@@ -398,9 +446,9 @@ int AbstractStreamOutput::esOutSend(es_out_t *fakees, es_out_id_t *p_es, block_t ...@@ -398,9 +446,9 @@ int AbstractStreamOutput::esOutSend(es_out_t *fakees, es_out_id_t *p_es, block_t
return VLC_SUCCESS; return VLC_SUCCESS;
} }
void AbstractStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es) void BaseStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es)
{ {
AbstractStreamOutput *me = (AbstractStreamOutput *) fakees->p_sys; BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
vlc_mutex_lock(&me->lock); vlc_mutex_lock(&me->lock);
std::list<Demuxed *>::iterator it; std::list<Demuxed *>::iterator it;
for(it=me->queues.begin(); it!=me->queues.end();++it) for(it=me->queues.begin(); it!=me->queues.end();++it)
...@@ -417,9 +465,9 @@ void AbstractStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es) ...@@ -417,9 +465,9 @@ void AbstractStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es)
me->realdemux->out->pf_del(me->realdemux->out, p_es); me->realdemux->out->pf_del(me->realdemux->out, p_es);
} }
int AbstractStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args) int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args)
{ {
AbstractStreamOutput *me = (AbstractStreamOutput *) fakees->p_sys; BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
if (i_query == ES_OUT_SET_PCR ) if (i_query == ES_OUT_SET_PCR )
{ {
me->pcr = (int64_t)va_arg( args, int64_t ); me->pcr = (int64_t)va_arg( args, int64_t );
...@@ -435,9 +483,9 @@ int AbstractStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list ar ...@@ -435,9 +483,9 @@ int AbstractStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list ar
return me->realdemux->out->pf_control(me->realdemux->out, i_query, args); return me->realdemux->out->pf_control(me->realdemux->out, i_query, args);
} }
void AbstractStreamOutput::esOutDestroy(es_out_t *fakees) void BaseStreamOutput::esOutDestroy(es_out_t *fakees)
{ {
AbstractStreamOutput *me = (AbstractStreamOutput *) fakees->p_sys; BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
me->realdemux->out->pf_destroy(me->realdemux->out); me->realdemux->out->pf_destroy(me->realdemux->out);
} }
/* !Static callbacks */ /* !Static callbacks */
...@@ -459,11 +507,3 @@ AbstractStreamOutput *DefaultStreamOutputFactory::create(demux_t *demux, int for ...@@ -459,11 +507,3 @@ AbstractStreamOutput *DefaultStreamOutputFactory::create(demux_t *demux, int for
return NULL; return NULL;
} }
BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
AbstractStreamOutput(demux)
{
demuxstream = stream_DemuxNew(demux, name.c_str(), fakeesout);
if(!demuxstream)
throw VLC_EGENERIC;
}
...@@ -91,23 +91,52 @@ namespace adaptative ...@@ -91,23 +91,52 @@ namespace adaptative
AbstractStreamOutput(demux_t *); AbstractStreamOutput(demux_t *);
virtual ~AbstractStreamOutput(); virtual ~AbstractStreamOutput();
virtual void pushBlock(block_t *); virtual void pushBlock(block_t *) = 0;
mtime_t getPCR() const; virtual mtime_t getPCR() const;
int getGroup() const; virtual int getGroup() const;
int esCount() const; virtual int esCount() const = 0;
bool seekAble() const; virtual bool seekAble() const = 0;
void setPosition(mtime_t); virtual void setPosition(mtime_t) = 0;
void sendToDecoder(mtime_t); virtual void sendToDecoder(mtime_t) = 0;
virtual bool reinitsOnSeek() const = 0;
protected: protected:
demux_t *realdemux;
mtime_t pcr; mtime_t pcr;
int group; int group;
};
class AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const = 0;
};
class DefaultStreamOutputFactory : public AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const;
};
class BaseStreamOutput : public AbstractStreamOutput
{
public:
BaseStreamOutput(demux_t *, const std::string &);
virtual ~BaseStreamOutput();
virtual void pushBlock(block_t *); /* reimpl */
virtual int esCount() const; /* reimpl */
virtual bool seekAble() const; /* reimpl */
virtual void setPosition(mtime_t); /* reimpl */
virtual void sendToDecoder(mtime_t); /* reimpl */
virtual bool reinitsOnSeek() const; /* reimpl */
protected:
es_out_t *fakeesout; /* to intercept/proxy what is sent from demuxstream */ es_out_t *fakeesout; /* to intercept/proxy what is sent from demuxstream */
stream_t *demuxstream; stream_t *demuxstream;
bool seekable; bool seekable;
std::string name;
private: private:
demux_t *realdemux;
static es_out_id_t *esOutAdd(es_out_t *, const es_format_t *); static es_out_id_t *esOutAdd(es_out_t *, const es_format_t *);
static int esOutSend(es_out_t *, es_out_id_t *, block_t *); static int esOutSend(es_out_t *, es_out_id_t *, block_t *);
static void esOutDel(es_out_t *, es_out_id_t *); static void esOutDel(es_out_t *, es_out_id_t *);
...@@ -116,7 +145,7 @@ namespace adaptative ...@@ -116,7 +145,7 @@ namespace adaptative
class Demuxed class Demuxed
{ {
friend class AbstractStreamOutput; friend class BaseStreamOutput;
Demuxed(); Demuxed();
~Demuxed(); ~Demuxed();
void drop(); void drop();
...@@ -127,25 +156,7 @@ namespace adaptative ...@@ -127,25 +156,7 @@ namespace adaptative
std::list<Demuxed *> queues; std::list<Demuxed *> queues;
vlc_mutex_t lock; vlc_mutex_t lock;
void sendToDecoderUnlocked(mtime_t); void sendToDecoderUnlocked(mtime_t);
}; bool restart();
class AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const = 0;
};
class DefaultStreamOutputFactory : public AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const;
};
class BaseStreamOutput : public AbstractStreamOutput
{
public:
BaseStreamOutput(demux_t *, const std::string &);
virtual ~BaseStreamOutput(){}
}; };
} }
......
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