Commit ed2fe051 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: restart on seek

parent f801e7d7
...@@ -54,7 +54,7 @@ void SegmentTracker::resetCounter() ...@@ -54,7 +54,7 @@ void SegmentTracker::resetCounter()
prevRepresentation = NULL; prevRepresentation = NULL;
} }
Chunk * SegmentTracker::getNextChunk(StreamType type) Chunk * SegmentTracker::getNextChunk(StreamType type, bool switch_allowed)
{ {
BaseRepresentation *rep; BaseRepresentation *rep;
ISegment *segment; ISegment *segment;
...@@ -62,7 +62,8 @@ Chunk * SegmentTracker::getNextChunk(StreamType type) ...@@ -62,7 +62,8 @@ Chunk * SegmentTracker::getNextChunk(StreamType type)
if(!currentPeriod) if(!currentPeriod)
return NULL; return NULL;
if(prevRepresentation && prevRepresentation->getSwitchPolicy() == SegmentInformation::SWITCH_UNAVAILABLE) if( !switch_allowed ||
(prevRepresentation && prevRepresentation->getSwitchPolicy() == SegmentInformation::SWITCH_UNAVAILABLE) )
rep = prevRepresentation; rep = prevRepresentation;
else else
rep = logic->getCurrentRepresentation(type, currentPeriod); rep = logic->getCurrentRepresentation(type, currentPeriod);
...@@ -97,7 +98,7 @@ Chunk * SegmentTracker::getNextChunk(StreamType type) ...@@ -97,7 +98,7 @@ Chunk * SegmentTracker::getNextChunk(StreamType type)
{ {
currentPeriod = playlist->getNextPeriod(currentPeriod); currentPeriod = playlist->getNextPeriod(currentPeriod);
resetCounter(); resetCounter();
return getNextChunk(type); return getNextChunk(type, switch_allowed);
} }
Chunk *chunk = segment->toChunk(count, rep); Chunk *chunk = segment->toChunk(count, rep);
......
...@@ -58,7 +58,7 @@ namespace adaptative ...@@ -58,7 +58,7 @@ namespace adaptative
void setAdaptationLogic(AbstractAdaptationLogic *); void setAdaptationLogic(AbstractAdaptationLogic *);
void resetCounter(); void resetCounter();
Chunk* getNextChunk(StreamType); Chunk* getNextChunk(StreamType, bool);
bool setPosition(mtime_t, bool, bool); bool setPosition(mtime_t, bool, bool);
mtime_t getSegmentStart() const; mtime_t getSegmentStart() const;
void pruneFromCurrent(); void pruneFromCurrent();
......
...@@ -127,7 +127,7 @@ Chunk * Stream::getChunk() ...@@ -127,7 +127,7 @@ Chunk * Stream::getChunk()
{ {
if (currentChunk == NULL) if (currentChunk == NULL)
{ {
currentChunk = segmentTracker->getNextChunk(type); currentChunk = segmentTracker->getNextChunk(type, output->switchAllowed());
if (currentChunk == NULL) if (currentChunk == NULL)
eof = true; eof = true;
} }
...@@ -280,6 +280,7 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) : ...@@ -280,6 +280,7 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
{ {
this->name = name; this->name = name;
seekable = true; seekable = true;
restarting = false;
demuxstream = NULL; demuxstream = NULL;
fakeesout = new es_out_t; fakeesout = new es_out_t;
...@@ -295,7 +296,8 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) : ...@@ -295,7 +296,8 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
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()) demuxstream = stream_DemuxNew(realdemux, name.c_str(), fakeesout);
if(!demuxstream)
throw VLC_EGENERIC; throw VLC_EGENERIC;
} }
...@@ -303,14 +305,14 @@ BaseStreamOutput::~BaseStreamOutput() ...@@ -303,14 +305,14 @@ BaseStreamOutput::~BaseStreamOutput()
{ {
if (demuxstream) if (demuxstream)
stream_Delete(demuxstream); stream_Delete(demuxstream);
delete fakeesout;
vlc_mutex_destroy(&lock);
/* shouldn't be any */ /* shouldn't be any */
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)
delete *it; delete *it;
delete fakeesout;
vlc_mutex_destroy(&lock);
} }
int BaseStreamOutput::esCount() const int BaseStreamOutput::esCount() const
...@@ -325,7 +327,8 @@ void BaseStreamOutput::pushBlock(block_t *block) ...@@ -325,7 +327,8 @@ void BaseStreamOutput::pushBlock(block_t *block)
bool BaseStreamOutput::seekAble() const bool BaseStreamOutput::seekAble() const
{ {
return (demuxstream && seekable); bool b_canswitch = switchAllowed();
return (demuxstream && seekable && b_canswitch);
} }
void BaseStreamOutput::setPosition(mtime_t nztime) void BaseStreamOutput::setPosition(mtime_t nztime)
...@@ -353,6 +356,7 @@ bool BaseStreamOutput::restart() ...@@ -353,6 +356,7 @@ bool BaseStreamOutput::restart()
return false; return false;
vlc_mutex_lock(&lock); vlc_mutex_lock(&lock);
restarting = true;
stream_t *olddemuxstream = demuxstream; stream_t *olddemuxstream = demuxstream;
demuxstream = newdemuxstream; demuxstream = newdemuxstream;
vlc_mutex_unlock(&lock); vlc_mutex_unlock(&lock);
...@@ -365,7 +369,16 @@ bool BaseStreamOutput::restart() ...@@ -365,7 +369,16 @@ bool BaseStreamOutput::restart()
bool BaseStreamOutput::reinitsOnSeek() const bool BaseStreamOutput::reinitsOnSeek() const
{ {
return false; return true;
}
bool BaseStreamOutput::switchAllowed() const
{
bool b_allowed;
vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
b_allowed = !restarting;
vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
return b_allowed;
} }
void BaseStreamOutput::sendToDecoder(mtime_t nzdeadline) void BaseStreamOutput::sendToDecoder(mtime_t nzdeadline)
...@@ -395,15 +408,18 @@ void BaseStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline) ...@@ -395,15 +408,18 @@ void BaseStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline)
} }
} }
BaseStreamOutput::Demuxed::Demuxed() BaseStreamOutput::Demuxed::Demuxed(es_out_id_t *id, const es_format_t *fmt)
{ {
p_queue = NULL; p_queue = NULL;
pp_queue_last = &p_queue; pp_queue_last = &p_queue;
es_id = NULL; es_id = id;
es_format_Init(&fmtcpy, UNKNOWN_ES, 0);
es_format_Copy(&fmtcpy, fmt);
} }
BaseStreamOutput::Demuxed::~Demuxed() BaseStreamOutput::Demuxed::~Demuxed()
{ {
es_format_Clean(&fmtcpy);
drop(); drop();
} }
...@@ -418,18 +434,52 @@ void BaseStreamOutput::Demuxed::drop() ...@@ -418,18 +434,52 @@ void BaseStreamOutput::Demuxed::drop()
es_out_id_t * BaseStreamOutput::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)
{ {
BaseStreamOutput *me = (BaseStreamOutput *) 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);
if(p_es) es_out_id_t *p_es = NULL;
vlc_mutex_lock(&me->lock);
std::list<Demuxed *>::iterator it;
bool b_hasestorecyle = false;
for(it=me->queues.begin(); it!=me->queues.end();++it)
{
Demuxed *pair = *it;
b_hasestorecyle |= pair->recycle;
if( p_es )
continue;
if( me->restarting )
{
/* If we're recycling from same format */
if( es_format_IsSimilar(p_fmt, &pair->fmtcpy) &&
p_fmt->i_extra == pair->fmtcpy.i_extra &&
!memcmp(p_fmt->p_extra, pair->fmtcpy.p_extra, p_fmt->i_extra) )
{
msg_Err(me->realdemux, "using recycled");
pair->recycle = false;
p_es = pair->es_id;
}
}
}
if(!b_hasestorecyle)
{
me->restarting = false;
}
if(!p_es)
{ {
vlc_mutex_lock(&me->lock); p_es = me->realdemux->out->pf_add(me->realdemux->out, p_fmt);
Demuxed *pair = new (std::nothrow) Demuxed(); if(p_es)
if(pair)
{ {
pair->es_id = p_es; Demuxed *pair = new (std::nothrow) Demuxed(p_es, p_fmt);
me->queues.push_back(pair); if(pair)
me->queues.push_back(pair);
} }
vlc_mutex_unlock(&me->lock);
} }
vlc_mutex_unlock(&me->lock);
return p_es; return p_es;
} }
...@@ -461,13 +511,27 @@ void BaseStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es) ...@@ -461,13 +511,27 @@ void BaseStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es)
if((*it)->es_id == p_es) if((*it)->es_id == p_es)
{ {
me->sendToDecoderUnlocked(INT64_MAX - VLC_TS_0); me->sendToDecoderUnlocked(INT64_MAX - VLC_TS_0);
break;
}
}
if(it != me->queues.end())
{
if(me->restarting)
{
(*it)->recycle = true;
}
else
{
delete *it; delete *it;
me->queues.erase(it); me->queues.erase(it);
break;
} }
} }
if(!me->restarting)
me->realdemux->out->pf_del(me->realdemux->out, p_es);
vlc_mutex_unlock(&me->lock); vlc_mutex_unlock(&me->lock);
me->realdemux->out->pf_del(me->realdemux->out, p_es);
} }
int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args) int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args)
...@@ -484,6 +548,17 @@ int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args) ...@@ -484,6 +548,17 @@ int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args)
me->pcr = (int64_t)va_arg( args, int64_t ); me->pcr = (int64_t)va_arg( args, int64_t );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
else if( i_query == ES_OUT_GET_ES_STATE )
{
va_arg( args, es_out_id_t * );
bool *pb = va_arg( args, bool * );
*pb = true;
return VLC_SUCCESS;
}
else if( me->restarting )
{
return VLC_EGENERIC;
}
return me->realdemux->out->pf_control(me->realdemux->out, i_query, args); return me->realdemux->out->pf_control(me->realdemux->out, i_query, args);
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_es.h>
#include "StreamsType.hpp" #include "StreamsType.hpp"
namespace adaptative namespace adaptative
...@@ -100,6 +101,7 @@ namespace adaptative ...@@ -100,6 +101,7 @@ namespace adaptative
virtual void setPosition(mtime_t) = 0; virtual void setPosition(mtime_t) = 0;
virtual void sendToDecoder(mtime_t) = 0; virtual void sendToDecoder(mtime_t) = 0;
virtual bool reinitsOnSeek() const = 0; virtual bool reinitsOnSeek() const = 0;
virtual bool switchAllowed() const = 0;
protected: protected:
demux_t *realdemux; demux_t *realdemux;
...@@ -130,12 +132,14 @@ namespace adaptative ...@@ -130,12 +132,14 @@ namespace adaptative
virtual void setPosition(mtime_t); /* reimpl */ virtual void setPosition(mtime_t); /* reimpl */
virtual void sendToDecoder(mtime_t); /* reimpl */ virtual void sendToDecoder(mtime_t); /* reimpl */
virtual bool reinitsOnSeek() const; /* reimpl */ virtual bool reinitsOnSeek() const; /* reimpl */
virtual bool switchAllowed() const; /* reimpl */
protected: 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; std::string name;
bool restarting;
private: private:
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 *);
...@@ -147,12 +151,14 @@ namespace adaptative ...@@ -147,12 +151,14 @@ namespace adaptative
class Demuxed class Demuxed
{ {
friend class BaseStreamOutput; friend class BaseStreamOutput;
Demuxed(); Demuxed(es_out_id_t *, const es_format_t *);
~Demuxed(); ~Demuxed();
void drop(); void drop();
es_out_id_t *es_id; es_out_id_t *es_id;
block_t *p_queue; block_t *p_queue;
block_t **pp_queue_last; block_t **pp_queue_last;
bool recycle;
es_format_t fmtcpy;
}; };
std::list<Demuxed *> queues; std::list<Demuxed *> queues;
vlc_mutex_t lock; vlc_mutex_t lock;
......
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