Commit eb141b28 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: dash: add basic seeking using next segment

Still doesn't control streamDemux
parent ecfe1e53
...@@ -156,3 +156,33 @@ mtime_t DASHManager::getDuration() const ...@@ -156,3 +156,33 @@ mtime_t DASHManager::getDuration() const
else else
return CLOCK_FREQ * mpd->getDuration(); return CLOCK_FREQ * mpd->getDuration();
} }
bool DASHManager::setPosition(mtime_t time)
{
bool ret = true;
for(int real = 0; real < 2; real++)
{
/* Always probe if we can seek first */
for(int type=0; type<Streams::count; type++)
{
if(!streams[type])
continue;
ret &= streams[type]->setPosition(time, !real);
}
if(!ret)
break;
}
return ret;
}
bool DASHManager::seekAble() const
{
for(int type=0; type<Streams::count; type++)
{
if(!streams[type])
continue;
if(!streams[type]->seekAble())
return false;
}
return true;
}
...@@ -44,6 +44,8 @@ namespace dash ...@@ -44,6 +44,8 @@ namespace dash
mtime_t getPCR() const; mtime_t getPCR() const;
int getGroup() const; int getGroup() const;
int esCount() const; int esCount() const;
bool setPosition(mtime_t);
bool seekAble() const;
private: private:
http::HTTPConnectionManager *conManager; http::HTTPConnectionManager *conManager;
......
...@@ -95,3 +95,16 @@ Chunk * SegmentTracker::getNextChunk(Streams::Type type) ...@@ -95,3 +95,16 @@ Chunk * SegmentTracker::getNextChunk(Streams::Type type)
return chunk; return chunk;
} }
bool SegmentTracker::setPosition(mtime_t time, bool tryonly)
{
uint64_t segcount;
if(prevRepresentation &&
prevRepresentation->getSegmentNumberByTime(time, &segcount))
{
if(!tryonly)
count = segcount;
return true;
}
return false;
}
...@@ -56,6 +56,7 @@ namespace dash ...@@ -56,6 +56,7 @@ namespace dash
void setAdaptationLogic(logic::AbstractAdaptationLogic *); void setAdaptationLogic(logic::AbstractAdaptationLogic *);
void resetCounter(); void resetCounter();
http::Chunk* getNextChunk(Streams::Type); http::Chunk* getNextChunk(Streams::Type);
bool setPosition(mtime_t, bool);
private: private:
bool initializing; bool initializing;
......
...@@ -141,6 +141,11 @@ Chunk * Stream::getChunk() ...@@ -141,6 +141,11 @@ Chunk * Stream::getChunk()
return currentChunk; return currentChunk;
} }
bool Stream::seekAble() const
{
return (output && output->seekAble());
}
size_t Stream::read(HTTPConnectionManager *connManager) size_t Stream::read(HTTPConnectionManager *connManager)
{ {
Chunk *chunk = getChunk(); Chunk *chunk = getChunk();
...@@ -210,6 +215,14 @@ size_t Stream::read(HTTPConnectionManager *connManager) ...@@ -210,6 +215,14 @@ size_t Stream::read(HTTPConnectionManager *connManager)
return readsize; return readsize;
} }
bool Stream::setPosition(mtime_t time, bool tryonly)
{
bool ret = segmentTracker->setPosition(time, tryonly);
if(!tryonly && ret)
output->setPosition(time);
return ret;
}
AbstractStreamOutput::AbstractStreamOutput(demux_t *demux) AbstractStreamOutput::AbstractStreamOutput(demux_t *demux)
{ {
realdemux = demux; realdemux = demux;
...@@ -217,6 +230,7 @@ AbstractStreamOutput::AbstractStreamOutput(demux_t *demux) ...@@ -217,6 +230,7 @@ AbstractStreamOutput::AbstractStreamOutput(demux_t *demux)
pcr = VLC_TS_0; pcr = VLC_TS_0;
group = -1; group = -1;
escount = 0; escount = 0;
seekable = true;
fakeesout = new es_out_t; fakeesout = new es_out_t;
if (!fakeesout) if (!fakeesout)
...@@ -257,6 +271,17 @@ void AbstractStreamOutput::pushBlock(block_t *block) ...@@ -257,6 +271,17 @@ void AbstractStreamOutput::pushBlock(block_t *block)
stream_DemuxSend(demuxstream, block); stream_DemuxSend(demuxstream, block);
} }
bool AbstractStreamOutput::seekAble() const
{
return (demuxstream && seekable);
}
void AbstractStreamOutput::setPosition(mtime_t nztime)
{
es_out_Control(realdemux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
VLC_TS_0 + nztime);
}
/* Static callbacks */ /* Static callbacks */
es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt) es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt)
{ {
......
...@@ -53,7 +53,9 @@ namespace dash ...@@ -53,7 +53,9 @@ namespace dash
mtime_t getPCR() const; mtime_t getPCR() const;
int getGroup() const; int getGroup() const;
int esCount() const; int esCount() const;
bool seekAble() const;
size_t read(http::HTTPConnectionManager *); size_t read(http::HTTPConnectionManager *);
bool setPosition(mtime_t, bool);
private: private:
http::Chunk *getChunk(); http::Chunk *getChunk();
...@@ -77,6 +79,8 @@ namespace dash ...@@ -77,6 +79,8 @@ namespace dash
mtime_t getPCR() const; mtime_t getPCR() const;
int getGroup() const; int getGroup() const;
int esCount() const; int esCount() const;
bool seekAble() const;
void setPosition(mtime_t);
protected: protected:
mtime_t pcr; mtime_t pcr;
...@@ -84,6 +88,7 @@ namespace dash ...@@ -84,6 +88,7 @@ namespace dash
int escount; int escount;
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;
private: private:
demux_t *realdemux; demux_t *realdemux;
......
...@@ -195,7 +195,7 @@ static int Control (demux_t *p_demux, int i_query, va_list args) ...@@ -195,7 +195,7 @@ static int Control (demux_t *p_demux, int i_query, va_list args)
switch (i_query) switch (i_query)
{ {
case DEMUX_CAN_SEEK: case DEMUX_CAN_SEEK:
*(va_arg (args, bool *)) = false; *(va_arg (args, bool *)) = p_sys->p_dashManager->seekAble();
break; break;
case DEMUX_CAN_CONTROL_PACE: case DEMUX_CAN_CONTROL_PACE:
...@@ -222,6 +222,17 @@ static int Control (demux_t *p_demux, int i_query, va_list args) ...@@ -222,6 +222,17 @@ static int Control (demux_t *p_demux, int i_query, va_list args)
/ p_sys->p_dashManager->getDuration(); / p_sys->p_dashManager->getDuration();
break; break;
case DEMUX_SET_POSITION:
if(!p_sys->p_dashManager->getDuration() ||
!p_sys->p_dashManager->setPosition( p_sys->p_dashManager->getDuration() * va_arg(args, double)))
return VLC_EGENERIC;
break;
case DEMUX_SET_TIME:
if(!p_sys->p_dashManager->setPosition(va_arg(args, int64_t)))
return VLC_EGENERIC;
break;
case DEMUX_GET_PTS_DELAY: case DEMUX_GET_PTS_DELAY:
*va_arg (args, int64_t *) = INT64_C(1000) * *va_arg (args, int64_t *) = INT64_C(1000) *
var_InheritInteger(p_demux, "network-caching"); var_InheritInteger(p_demux, "network-caching");
......
...@@ -280,6 +280,9 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation ...@@ -280,6 +280,9 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
if(segListNode->hasAttribute("duration")) if(segListNode->hasAttribute("duration"))
list->setDuration(Integer<mtime_t>(segListNode->getAttributeValue("duration"))); list->setDuration(Integer<mtime_t>(segListNode->getAttributeValue("duration")));
if(segListNode->hasAttribute("timescale"))
list->timescale.Set(Integer<uint64_t>(segListNode->getAttributeValue("timescale")));
std::vector<Node *>::const_iterator it; std::vector<Node *>::const_iterator it;
for(it = segments.begin(); it != segments.end(); it++) for(it = segments.begin(); it != segments.end(); it++)
{ {
......
...@@ -59,17 +59,24 @@ SegmentInformation::~SegmentInformation() ...@@ -59,17 +59,24 @@ SegmentInformation::~SegmentInformation()
delete segmentTemplate[i]; delete segmentTemplate[i];
} }
vector<ISegment *> SegmentInformation::getSegments() const vector<ISegment *> SegmentInformation::getSegments(SegmentInfoType type) const
{ {
vector<ISegment *> retSegments; vector<ISegment *> retSegments;
SegmentList *segList = inheritSegmentList(); switch (type)
{
case INFOTYPE_INIT:
{
/* init segments are always single segment */ /* init segments are always single segment */
ISegment *segment = getSegment( INFOTYPE_INIT ); ISegment *segment = getSegment( INFOTYPE_INIT );
if( segment ) if( segment )
retSegments.push_back( segment ); retSegments.push_back( segment );
}
break;
case INFOTYPE_MEDIA:
{
SegmentList *segList = inheritSegmentList();
if( inheritSegmentTemplate(INFOTYPE_MEDIA) ) if( inheritSegmentTemplate(INFOTYPE_MEDIA) )
{ {
retSegments.push_back( inheritSegmentTemplate(INFOTYPE_MEDIA) ); retSegments.push_back( inheritSegmentTemplate(INFOTYPE_MEDIA) );
...@@ -84,10 +91,26 @@ vector<ISegment *> SegmentInformation::getSegments() const ...@@ -84,10 +91,26 @@ vector<ISegment *> SegmentInformation::getSegments() const
retSegments.insert( retSegments.end(), list.begin(), list.end() ); retSegments.insert( retSegments.end(), list.begin(), list.end() );
} }
} }
}
default:
break;
}
return retSegments; return retSegments;
} }
vector<ISegment *> SegmentInformation::getSegments() const
{
vector<ISegment *> retSegments;
for(int i=0; i<InfoTypeCount; i++)
{
vector<ISegment *> segs = getSegments(static_cast<SegmentInfoType>(i));
retSegments.insert( retSegments.end(), segs.begin(), segs.end() );
}
return retSegments;
}
ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const
{ {
SegmentBase *segBase = inheritSegmentBase(); SegmentBase *segBase = inheritSegmentBase();
...@@ -134,6 +157,20 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co ...@@ -134,6 +157,20 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co
return segment; return segment;
} }
bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) const
{
SegmentList *segList = inheritSegmentList();
if ( segList->getDuration() )
{
uint64_t timescale = segList->timescale.Get();
if(!timescale)
timescale = getTimescale();
*ret = time / (CLOCK_FREQ * segList->getDuration() / timescale);
return true;
}
return false;
}
bool SegmentInformation::canBitswitch() const bool SegmentInformation::canBitswitch() const
{ {
if(bitswitch_policy == BITSWITCH_INHERIT) if(bitswitch_policy == BITSWITCH_INHERIT)
......
...@@ -48,7 +48,6 @@ namespace dash ...@@ -48,7 +48,6 @@ namespace dash
SegmentInformation( SegmentInformation * = 0 ); SegmentInformation( SegmentInformation * = 0 );
explicit SegmentInformation( ICanonicalUrl * ); explicit SegmentInformation( ICanonicalUrl * );
virtual ~SegmentInformation(); virtual ~SegmentInformation();
std::vector<ISegment *> getSegments() const;
bool canBitswitch() const; bool canBitswitch() const;
uint64_t getTimescale() const; uint64_t getTimescale() const;
virtual mtime_t getPeriodStart() const; virtual mtime_t getPeriodStart() const;
...@@ -70,6 +69,11 @@ namespace dash ...@@ -70,6 +69,11 @@ namespace dash
static const int InfoTypeCount = INFOTYPE_INDEX + 1; static const int InfoTypeCount = INFOTYPE_INDEX + 1;
ISegment * getSegment(SegmentInfoType, uint64_t = 0) const; ISegment * getSegment(SegmentInfoType, uint64_t = 0) const;
bool getSegmentNumberByTime(mtime_t, uint64_t *) const;
protected:
std::vector<ISegment *> getSegments() const;
std::vector<ISegment *> getSegments(SegmentInfoType) const;
private: private:
void setSegmentList(SegmentList *); void setSegmentList(SegmentList *);
......
...@@ -34,7 +34,7 @@ using namespace dash::mpd; ...@@ -34,7 +34,7 @@ using namespace dash::mpd;
SegmentList::SegmentList( ICanonicalUrl *parent ): SegmentList::SegmentList( ICanonicalUrl *parent ):
SegmentInfoCommon( parent ) SegmentInfoCommon( parent )
{ {
timescale.Set(0);
} }
SegmentList::~SegmentList() SegmentList::~SegmentList()
{ {
......
...@@ -25,8 +25,15 @@ ...@@ -25,8 +25,15 @@
#ifndef SEGMENTLIST_H_ #ifndef SEGMENTLIST_H_
#define SEGMENTLIST_H_ #define SEGMENTLIST_H_
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "mpd/SegmentInfoCommon.h" #include "mpd/SegmentInfoCommon.h"
#include "mpd/ICanonicalUrl.hpp" #include "mpd/ICanonicalUrl.hpp"
#include "Properties.hpp"
#include <vlc_common.h>
namespace dash namespace dash
{ {
...@@ -41,6 +48,8 @@ namespace dash ...@@ -41,6 +48,8 @@ namespace dash
const std::vector<Segment *>& getSegments() const; const std::vector<Segment *>& getSegments() const;
void addSegment(Segment *seg); void addSegment(Segment *seg);
Property<uint64_t> timescale;
private: private:
std::vector<Segment *> segments; std::vector<Segment *> segments;
}; };
......
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