Commit eb141b28 authored by François Cartegnie's avatar François 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
else
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
mtime_t getPCR() const;
int getGroup() const;
int esCount() const;
bool setPosition(mtime_t);
bool seekAble() const;
private:
http::HTTPConnectionManager *conManager;
......
......@@ -95,3 +95,16 @@ Chunk * SegmentTracker::getNextChunk(Streams::Type type)
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
void setAdaptationLogic(logic::AbstractAdaptationLogic *);
void resetCounter();
http::Chunk* getNextChunk(Streams::Type);
bool setPosition(mtime_t, bool);
private:
bool initializing;
......
......@@ -141,6 +141,11 @@ Chunk * Stream::getChunk()
return currentChunk;
}
bool Stream::seekAble() const
{
return (output && output->seekAble());
}
size_t Stream::read(HTTPConnectionManager *connManager)
{
Chunk *chunk = getChunk();
......@@ -210,6 +215,14 @@ size_t Stream::read(HTTPConnectionManager *connManager)
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)
{
realdemux = demux;
......@@ -217,6 +230,7 @@ AbstractStreamOutput::AbstractStreamOutput(demux_t *demux)
pcr = VLC_TS_0;
group = -1;
escount = 0;
seekable = true;
fakeesout = new es_out_t;
if (!fakeesout)
......@@ -257,6 +271,17 @@ void AbstractStreamOutput::pushBlock(block_t *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 */
es_out_id_t * AbstractStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt)
{
......
......@@ -53,7 +53,9 @@ namespace dash
mtime_t getPCR() const;
int getGroup() const;
int esCount() const;
bool seekAble() const;
size_t read(http::HTTPConnectionManager *);
bool setPosition(mtime_t, bool);
private:
http::Chunk *getChunk();
......@@ -77,6 +79,8 @@ namespace dash
mtime_t getPCR() const;
int getGroup() const;
int esCount() const;
bool seekAble() const;
void setPosition(mtime_t);
protected:
mtime_t pcr;
......@@ -84,6 +88,7 @@ namespace dash
int escount;
es_out_t *fakeesout; /* to intercept/proxy what is sent from demuxstream */
stream_t *demuxstream;
bool seekable;
private:
demux_t *realdemux;
......
......@@ -195,7 +195,7 @@ static int Control (demux_t *p_demux, int i_query, va_list args)
switch (i_query)
{
case DEMUX_CAN_SEEK:
*(va_arg (args, bool *)) = false;
*(va_arg (args, bool *)) = p_sys->p_dashManager->seekAble();
break;
case DEMUX_CAN_CONTROL_PACE:
......@@ -222,6 +222,17 @@ static int Control (demux_t *p_demux, int i_query, va_list args)
/ p_sys->p_dashManager->getDuration();
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:
*va_arg (args, int64_t *) = INT64_C(1000) *
var_InheritInteger(p_demux, "network-caching");
......
......@@ -280,6 +280,9 @@ size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation
if(segListNode->hasAttribute("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;
for(it = segments.begin(); it != segments.end(); it++)
{
......
......@@ -59,35 +59,58 @@ SegmentInformation::~SegmentInformation()
delete segmentTemplate[i];
}
vector<ISegment *> SegmentInformation::getSegments() const
vector<ISegment *> SegmentInformation::getSegments(SegmentInfoType type) const
{
vector<ISegment *> retSegments;
SegmentList *segList = inheritSegmentList();
/* init segments are always single segment */
ISegment *segment = getSegment( INFOTYPE_INIT );
if( segment )
retSegments.push_back( segment );
if( inheritSegmentTemplate(INFOTYPE_MEDIA) )
switch (type)
{
retSegments.push_back( inheritSegmentTemplate(INFOTYPE_MEDIA) );
}
else if ( segList && !segList->getSegments().empty() )
{
std::vector<Segment *>::const_iterator it;
for(it=segList->getSegments().begin();
it!=segList->getSegments().end(); it++)
case INFOTYPE_INIT:
{
std::vector<ISegment *> list = (*it)->subSegments();
retSegments.insert( retSegments.end(), list.begin(), list.end() );
/* init segments are always single segment */
ISegment *segment = getSegment( INFOTYPE_INIT );
if( segment )
retSegments.push_back( segment );
}
break;
case INFOTYPE_MEDIA:
{
SegmentList *segList = inheritSegmentList();
if( inheritSegmentTemplate(INFOTYPE_MEDIA) )
{
retSegments.push_back( inheritSegmentTemplate(INFOTYPE_MEDIA) );
}
else if ( segList && !segList->getSegments().empty() )
{
std::vector<Segment *>::const_iterator it;
for(it=segList->getSegments().begin();
it!=segList->getSegments().end(); it++)
{
std::vector<ISegment *> list = (*it)->subSegments();
retSegments.insert( retSegments.end(), list.begin(), list.end() );
}
}
}
default:
break;
}
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
{
SegmentBase *segBase = inheritSegmentBase();
......@@ -134,6 +157,20 @@ ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) co
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
{
if(bitswitch_policy == BITSWITCH_INHERIT)
......
......@@ -48,7 +48,6 @@ namespace dash
SegmentInformation( SegmentInformation * = 0 );
explicit SegmentInformation( ICanonicalUrl * );
virtual ~SegmentInformation();
std::vector<ISegment *> getSegments() const;
bool canBitswitch() const;
uint64_t getTimescale() const;
virtual mtime_t getPeriodStart() const;
......@@ -70,6 +69,11 @@ namespace dash
static const int InfoTypeCount = INFOTYPE_INDEX + 1;
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:
void setSegmentList(SegmentList *);
......
......@@ -34,7 +34,7 @@ using namespace dash::mpd;
SegmentList::SegmentList( ICanonicalUrl *parent ):
SegmentInfoCommon( parent )
{
timescale.Set(0);
}
SegmentList::~SegmentList()
{
......
......@@ -25,8 +25,15 @@
#ifndef SEGMENTLIST_H_
#define SEGMENTLIST_H_
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "mpd/SegmentInfoCommon.h"
#include "mpd/ICanonicalUrl.hpp"
#include "Properties.hpp"
#include <vlc_common.h>
namespace dash
{
......@@ -41,6 +48,8 @@ namespace dash
const std::vector<Segment *>& getSegments() const;
void addSegment(Segment *seg);
Property<uint64_t> timescale;
private:
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