Commit db1c4aa7 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen Committed by Jean-Baptiste Kempf

dash: Adding an implementation for UrlTemplate

Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent d3086fea
......@@ -55,9 +55,9 @@ DASHManager::~DASHManager ()
delete this->mpdManager;
}
int DASHManager::read (void *p_buffer, size_t len)
int DASHManager::read( void *p_buffer, size_t len )
{
if(this->currentChunk == NULL)
if ( this->currentChunk == NULL )
{
try
{
......@@ -70,19 +70,19 @@ int DASHManager::read (void *p_buffer, size_t len)
}
}
int ret = this->conManager->read(this->currentChunk, p_buffer, len);
if(ret <= 0)
int ret = this->conManager->read( this->currentChunk, p_buffer, len );
if ( ret == 0 )
{
this->currentChunk = NULL;
return this->read(p_buffer, len);
return this->read(p_buffer, len );
}
return ret;
}
int DASHManager::peek (const uint8_t **pp_peek, size_t i_peek)
int DASHManager::peek( const uint8_t **pp_peek, size_t i_peek )
{
if(this->currentChunk == NULL)
if ( this->currentChunk == NULL )
{
try
{
......@@ -94,7 +94,7 @@ int DASHManager::peek (const uint8_t **pp_peek, size_t i_peek)
}
}
int ret = this->conManager->peek(this->currentChunk, pp_peek, i_peek);
int ret = this->conManager->peek( this->currentChunk, pp_peek, i_peek );
return ret;
}
......
......@@ -43,8 +43,8 @@ namespace dash
logic::IAdaptationLogic::LogicType type );
virtual ~DASHManager ();
int read (void *p_buffer, size_t len);
int peek (const uint8_t **pp_peek, size_t i_peek);
int read( void *p_buffer, size_t len );
int peek( const uint8_t **pp_peek, size_t i_peek );
const mpd::IMPDManager* getMpdManager() const;
private:
......
......@@ -49,6 +49,8 @@ SOURCES_stream_filter_dash = \
mpd/SegmentInfoCommon.h \
mpd/SegmentInfoDefault.cpp \
mpd/SegmentInfoDefault.h \
mpd/SegmentTemplate.cpp \
mpd/SegmentTemplate.h \
mpd/SegmentTimeline.cpp \
mpd/SegmentTimeline.h \
mpd/TrickModeType.cpp \
......
......@@ -45,7 +45,6 @@ namespace dash
AbstractAdaptationLogic (dash::mpd::IMPDManager *mpdManager);
virtual ~AbstractAdaptationLogic ();
virtual dash::http::Chunk* getNextChunk () throw(dash::exception::EOFException) = 0;
virtual void downloadRateChanged (long bpsAvg, long bpsLastChunk);
long getBpsAvg ();
......
......@@ -31,7 +31,8 @@ using namespace dash::logic;
using namespace dash::xml;
using namespace dash::mpd;
IAdaptationLogic* AdaptationLogicFactory::create (IAdaptationLogic::LogicType logic, IMPDManager *mpdManager)
IAdaptationLogic* AdaptationLogicFactory::create ( IAdaptationLogic::LogicType logic,
IMPDManager *mpdManager )
{
switch(logic)
{
......
......@@ -43,7 +43,7 @@ AlwaysBestAdaptationLogic::~AlwaysBestAdaptationLogic ()
{
}
Chunk* AlwaysBestAdaptationLogic::getNextChunk () throw(EOFException)
Chunk* AlwaysBestAdaptationLogic::getNextChunk() throw(EOFException)
{
if(this->schedule.size() == 0)
throw EOFException();
......@@ -75,7 +75,7 @@ void AlwaysBestAdaptationLogic::initSchedule ()
if(best != NULL)
{
std::vector<const Segment *> segments = this->mpdManager->getSegments(best);
std::vector<Segment *> segments = this->mpdManager->getSegments(best);
for(size_t j = 0; j < segments.size(); j++)
{
this->schedule.push_back(segments.at(j));
......
......@@ -45,10 +45,10 @@ namespace dash
AlwaysBestAdaptationLogic (dash::mpd::IMPDManager *mpdManager);
virtual ~AlwaysBestAdaptationLogic ();
dash::http::Chunk* getNextChunk () throw(dash::exception::EOFException);
dash::http::Chunk* getNextChunk() throw(dash::exception::EOFException);
private:
std::vector<const mpd::Segment *> schedule;
std::vector<mpd::Segment *> schedule;
dash::mpd::IMPDManager *mpdManager;
size_t count;
......
......@@ -42,7 +42,7 @@ namespace dash
Default,
AlwaysBest,
AlwaysLowest,
RateBased,
RateBased
};
virtual dash::http::Chunk* getNextChunk() throw(dash::exception::EOFException) = 0;
......
......@@ -41,7 +41,7 @@ namespace dash
NullAdaptationLogic (dash::mpd::IMPDManager *mpdManager) : AbstractAdaptationLogic(mpdManager) {}
virtual ~NullAdaptationLogic() {}
dash::http::Chunk* getNextChunk () throw(dash::exception::EOFException) { throw dash::exception::EOFException(); }
dash::http::Chunk* getNextChunk() throw(dash::exception::EOFException) { throw dash::exception::EOFException(); }
};
}
}
......
......@@ -41,7 +41,7 @@ RateBasedAdaptationLogic::RateBasedAdaptationLogic (IMPDManager *mpdManager) :
{
}
Chunk* RateBasedAdaptationLogic::getNextChunk () throw(EOFException)
Chunk* RateBasedAdaptationLogic::getNextChunk() throw(EOFException)
{
if(this->mpdManager == NULL)
throw EOFException();
......@@ -53,12 +53,12 @@ Chunk* RateBasedAdaptationLogic::getNextChunk () throw(EOFException)
Representation *rep = this->mpdManager->getRepresentation(this->currentPeriod, bitrate);
if(rep == NULL)
if ( rep == NULL )
throw EOFException();
std::vector<const Segment *> segments = this->mpdManager->getSegments(rep);
std::vector<Segment *> segments = this->mpdManager->getSegments(rep);
if(this->count == segments.size())
if ( this->count == segments.size() )
{
this->currentPeriod = this->mpdManager->getNextPeriod(this->currentPeriod);
this->count = 0;
......@@ -67,9 +67,13 @@ Chunk* RateBasedAdaptationLogic::getNextChunk () throw(EOFException)
if ( segments.size() > this->count )
{
Segment *seg = segments.at( this->count );
Chunk *chunk = new Chunk;
chunk->setUrl( segments.at( this->count )->getSourceUrl() );
chunk->setUrl( seg->getSourceUrl() );
//In case of UrlTemplate, we must stay on the same segment.
if ( seg->isSingleShot() == true )
this->count++;
seg->done();
return chunk;
}
return NULL;
......
......@@ -41,7 +41,7 @@ namespace dash
public:
RateBasedAdaptationLogic (dash::mpd::IMPDManager *mpdManager);
dash::http::Chunk* getNextChunk () throw(dash::exception::EOFException);
dash::http::Chunk* getNextChunk() throw(dash::exception::EOFException);
private:
dash::mpd::IMPDManager *mpdManager;
......
......@@ -153,7 +153,7 @@ static int Read (stream_t *p_stream, void *p_buffer, unsigned int i_
dash::DASHManager *p_dashManager = p_sys->p_dashManager;
int i_ret = 0;
i_ret = p_dashManager->read(p_buffer, i_len);
i_ret = p_dashManager->read(p_buffer, i_len );
if (i_ret < 0)
{
......@@ -173,13 +173,15 @@ static int Read (stream_t *p_stream, void *p_buffer, unsigned int i_
return i_ret;
}
static int Peek (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek)
{
stream_sys_t *p_sys = (stream_sys_t *) p_stream->p_sys;
dash::DASHManager *p_dashManager = p_sys->p_dashManager;
return p_dashManager->peek(pp_peek, i_peek);
return p_dashManager->peek( pp_peek, i_peek );
}
static int Control (stream_t *p_stream, int i_query, va_list args)
{
stream_sys_t *p_sys = p_stream->p_sys;
......
......@@ -34,6 +34,7 @@ HTTPConnection::HTTPConnection (const std::string& url, stream_t *stream)
this->url = url;
this->stream = stream;
}
HTTPConnection::~HTTPConnection ()
{
......@@ -66,6 +67,7 @@ void HTTPConnection::parseURL ()
this->request = "GET " + this->path + " HTTP/1.1\r\n" +
"Host: " + this->hostname + "\r\nConnection: close\r\n\r\n";
}
bool HTTPConnection::init()
{
this->urlStream = stream_UrlNew( this->stream, this->url.c_str() );
......
......@@ -46,9 +46,10 @@ HTTPConnectionManager::~HTTPConnectionManager ()
this->closeAllConnections();
}
bool HTTPConnectionManager::closeConnection (IHTTPConnection *con)
bool HTTPConnectionManager::closeConnection( IHTTPConnection *con )
{
for(std::vector<HTTPConnection *>::iterator it = this->connections.begin(); it != this->connections.end(); ++it)
for(std::vector<HTTPConnection *>::iterator it = this->connections.begin();
it != this->connections.end(); ++it)
{
if(*it == con)
{
......@@ -60,7 +61,8 @@ bool HTTPConnectionManager::closeConnection (IHTTPConnec
}
return false;
}
bool HTTPConnectionManager::closeConnection (Chunk *chunk)
bool HTTPConnectionManager::closeConnection( Chunk *chunk )
{
HTTPConnection *con = this->chunkMap[chunk];
bool ret = this->closeConnection(con);
......@@ -68,6 +70,7 @@ bool HTTPConnectionManager::closeConnection (Chunk *chun
delete(chunk);
return ret;
}
void HTTPConnectionManager::closeAllConnections ()
{
for(std::vector<HTTPConnection *>::iterator it = this->connections.begin(); it != this->connections.end(); ++it)
......@@ -103,7 +106,6 @@ int HTTPConnectionManager::read( Chunk *chunk, void *p_buffer, s
int ret = this->chunkMap[chunk]->read(p_buffer, len);
mtime_t end = mdate();
std::cout << "ret: " << ret << std::endl;
if( ret <= 0 )
this->closeConnection( chunk );
else
......
......@@ -40,11 +40,11 @@ BasicCMManager::~BasicCMManager ()
delete this->mpd;
}
std::vector<const Segment*> BasicCMManager::getSegments( Representation *rep )
std::vector<Segment*> BasicCMManager::getSegments( Representation *rep )
{
std::vector<const Segment *> retSegments;
std::vector<Segment *> retSegments;
SegmentInfo* info = rep->getSegmentInfo();
const Segment* initSegment = info->getInitialisationSegment();
Segment* initSegment = info->getInitialisationSegment();
if ( initSegment )
retSegments.push_back( initSegment );
......
......@@ -51,7 +51,7 @@ namespace dash
Period* getFirstPeriod();
Period* getNextPeriod( Period *period );
Representation* getBestRepresentation( Period *period );
std::vector<const Segment *> getSegments( Representation *rep );
std::vector<Segment *> getSegments( Representation *rep );
Representation* getRepresentation( Period *period, int bitrate );
const MPD* getMPD() const;
......
......@@ -521,7 +521,7 @@ bool BasicCMParser::resolveUrlTemplates( std::string &url, bool &containRunti
}
else
{
std::cout << "Unhandled token " << token << std::endl;
std::cerr << "Unhandled token " << token << std::endl;
return false;
}
}
......
......@@ -31,7 +31,7 @@ namespace dash
virtual Period* getFirstPeriod () = 0;
virtual Period* getNextPeriod (Period *period) = 0;
virtual Representation* getBestRepresentation (Period *period) = 0;
virtual std::vector<const Segment *> getSegments (Representation *rep) = 0;
virtual std::vector<Segment *> getSegments(Representation *rep ) = 0;
virtual Representation* getRepresentation (Period *period, int bitrate) = 0;
virtual const MPD* getMPD () const = 0;
virtual ~IMPDManager(){}
......
......@@ -29,7 +29,7 @@
using namespace dash::mpd;
const std::string& Segment::getSourceUrl () const
std::string Segment::getSourceUrl() const
{
return this->sourceUrl;
}
......@@ -39,3 +39,13 @@ void Segment::setSourceUrl( const std::string &url )
if ( url.empty() == false )
this->sourceUrl = url;
}
bool Segment::isSingleShot() const
{
return true;
}
void Segment::done()
{
//Only used for a SegmentTemplate.
}
......@@ -35,10 +35,17 @@ namespace dash
{
public:
virtual ~Segment(){}
const std::string& getSourceUrl() const;
void setSourceUrl( const std::string &url );
virtual std::string getSourceUrl() const;
virtual void setSourceUrl( const std::string &url );
/**
* @return true if the segment should be dropped after being read.
* That is basically true when using an Url, and false
* when using an UrlTemplate
*/
virtual bool isSingleShot() const;
virtual void done();
private:
protected:
std::string sourceUrl;
};
}
......
......@@ -64,12 +64,12 @@ void SegmentInfoCommon::setStartIndex(int startIndex)
this->startIndex = startIndex;
}
const Segment* SegmentInfoCommon::getInitialisationSegment() const
Segment* SegmentInfoCommon::getInitialisationSegment() const
{
return this->initialisationSegment;
}
void SegmentInfoCommon::setInitialisationSegment(const Segment *seg)
void SegmentInfoCommon::setInitialisationSegment(Segment *seg)
{
if ( seg != NULL )
this->initialisationSegment = seg;
......
......@@ -44,8 +44,8 @@ namespace dash
void setDuration( time_t duration );
int getStartIndex() const;
void setStartIndex( int startIndex );
const Segment* getInitialisationSegment() const;
void setInitialisationSegment( const Segment* seg );
Segment* getInitialisationSegment() const;
void setInitialisationSegment( Segment* seg );
const std::list<std::string>& getBaseURL() const;
void appendBaseURL( const std::string& url );
const SegmentTimeline* getSegmentTimeline() const;
......@@ -54,7 +54,7 @@ namespace dash
private:
time_t duration;
int startIndex;
const Segment* initialisationSegment;
Segment* initialisationSegment;
std::list<std::string> baseURLs;
const SegmentTimeline* segmentTimeline;
};
......
/*****************************************************************************
* SegmentTemplate.cpp: Implement the UrlTemplate element.
*****************************************************************************
* Copyright (C) 1998-2007 VLC authors and VideoLAN
* $Id$
*
* Authors: Hugo Beauzée-Luyssen <beauze.h@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "SegmentTemplate.h"
#include "SegmentTimeline.h"
#include "Representation.h"
#include "Group.h"
#include "SegmentInfoDefault.h"
#include <cassert>
#include <cstring>
#include <iostream>
#include <sstream>
using namespace dash::mpd;
SegmentTemplate::SegmentTemplate( bool containRuntimeIdentifier,
Representation* representation ) :
containRuntimeIdentifier( containRuntimeIdentifier ),
representation( representation ),
beginTime( std::string::npos ),
beginIndex( std::string::npos ),
currentSegmentIndex( 0 )
{
}
std::string SegmentTemplate::getSourceUrl() const
{
std::string res = this->sourceUrl;
if ( this->containRuntimeIdentifier == false )
return Segment::getSourceUrl();
if ( this->beginIndex != std::string::npos )
std::cerr << "Unhandled identifier \"$Index$\"" << std::endl;
if ( this->beginTime != std::string::npos )
{
//FIXME: This should use the current representation SegmentInfo
//which "inherits" the SegmentInfoDefault values.
if ( this->representation->getParentGroup()->getSegmentInfoDefault() != NULL &&
this->representation->getParentGroup()->getSegmentInfoDefault()->getSegmentTimeline() != NULL )
{
const SegmentTimeline::Element *el = this->representation->getParentGroup()->
getSegmentInfoDefault()->getSegmentTimeline()->getElement( this->currentSegmentIndex );
if ( el != NULL )
{
std::ostringstream oss;
oss << el->t;
res.replace( this->beginTime, strlen("$Time$"), oss.str() );
}
}
}
return res;
}
void SegmentTemplate::setSourceUrl( const std::string &url )
{
if ( this->containRuntimeIdentifier == true )
{
this->beginTime = url.find( "$Time$" );
this->beginIndex = url.find( "$Index$" );
}
Segment::setSourceUrl( url );
}
bool SegmentTemplate::isSingleShot() const
{
return false;
}
void SegmentTemplate::done()
{
this->currentSegmentIndex++;
}
/*****************************************************************************
* SegmentTemplate.cpp: Implement the UrlTemplate element.
*****************************************************************************
* Copyright (C) 1998-2007 VLC authors and VideoLAN
* $Id$
*
* Authors: Hugo Beauzée-Luyssen <beauze.h@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef SEGMENTTEMPLATE_H
#define SEGMENTTEMPLATE_H
#include "mpd/Segment.h"
namespace dash
{
namespace mpd
{
class Representation;
class SegmentTemplate : public Segment
{
public:
SegmentTemplate( bool containRuntimeIdentifier, Representation *rep );
virtual std::string getSourceUrl() const;
virtual void setSourceUrl( const std::string & url );
virtual bool isSingleShot() const;
virtual void done();
private:
bool containRuntimeIdentifier;
Representation* representation;
size_t beginTime;
size_t beginIndex;
int currentSegmentIndex;
};
}
}
#endif // SEGMENTTEMPLATE_H
......@@ -52,28 +52,33 @@ void dash::mpd::SegmentTimeline::setTimescale(int timescale)
void dash::mpd::SegmentTimeline::addElement(dash::mpd::SegmentTimeline::Element *e)
{
int64_t offset = 0;
for ( int i = 0; i <= e->r; ++i )
{
this->elements.push_back( e );
if ( i < e->r )
{
e = new SegmentTimeline::Element( *e );
offset += e->d;
e->t += offset;
}
}
}
const SegmentTimeline::Element* SegmentTimeline::getElement( mtime_t dts ) const
const SegmentTimeline::Element* SegmentTimeline::getElement( unsigned int index ) const
{
if ( this->elements.size() == 0 )
if ( this->elements.size() <= index )
return NULL;
int64_t targetT = dts * this->timescale / 1000000;
targetT -= this->elements.front()->t;
std::list<Element*>::const_iterator it = this->elements.begin();
std::list<Element*>::const_iterator end = this->elements.end();
const Element* res = NULL;
unsigned int i = 0;
while ( it != end )
{
if ( (*it)->t > targetT )
return res;
res = *it;
if ( i == index )
return *it;
++it;
++i;
}
std::cerr << "No more element to be used." << std::endl;
return NULL;
}
......@@ -81,3 +86,10 @@ dash::mpd::SegmentTimeline::Element::Element() :
r( 0 )
{
}
SegmentTimeline::Element::Element(const SegmentTimeline::Element &e) :
t( e.t ),
d( e.d ),
r( 0 )
{
}
......@@ -27,7 +27,6 @@
#include <sys/types.h>
#include <list>
#include <stdint.h>
#include <vlc_common.h>
namespace dash
{
......@@ -39,6 +38,7 @@ namespace dash
struct Element
{
Element();
Element( const Element& e );
int64_t t;
int64_t d;
int r;
......@@ -48,7 +48,7 @@ namespace dash
int getTimescale() const;
void setTimescale( int timescale );
void addElement( Element* e );
const Element* getElement( mtime_t dts ) const;
const Element* getElement( unsigned int index ) const;
private:
int timescale;
......
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