Commit 4e6acd5b authored by François Cartegnie's avatar François Cartegnie 🤞

demux: dash: track segment/periods outside of adaptation logic

Allows switching logic, and fixes startSegment handling.
parent 11008861
......@@ -246,7 +246,6 @@ libdash_plugin_la_SOURCES = \
demux/dash/adaptationlogic/AlwaysBestAdaptationLogic.h \
demux/dash/adaptationlogic/AlwaysLowestAdaptationLogic.cpp \
demux/dash/adaptationlogic/AlwaysLowestAdaptationLogic.hpp \
demux/dash/adaptationlogic/IAdaptationLogic.h \
demux/dash/adaptationlogic/IDownloadRateObserver.h \
demux/dash/adaptationlogic/RateBasedAdaptationLogic.h \
demux/dash/adaptationlogic/RateBasedAdaptationLogic.cpp \
......@@ -326,6 +325,8 @@ libdash_plugin_la_SOURCES = \
demux/dash/Helper.cpp \
demux/dash/Helper.h \
demux/dash/Properties.hpp \
demux/dash/SegmentTracker.cpp \
demux/dash/SegmentTracker.hpp \
demux/dash/StreamsType.hpp \
demux/dash/Streams.cpp \
demux/dash/Streams.hpp
......
......@@ -29,15 +29,15 @@
#include "DASHManager.h"
#include "adaptationlogic/AdaptationLogicFactory.h"
#include "SegmentTracker.hpp"
using namespace dash;
using namespace dash::http;
using namespace dash::logic;
using namespace dash::mpd;
using namespace dash::buffer;
DASHManager::DASHManager ( MPD *mpd,
IAdaptationLogic::LogicType type, stream_t *stream) :
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
conManager ( NULL ),
logicType ( type ),
mpd ( mpd ),
......@@ -66,18 +66,33 @@ bool DASHManager::start(demux_t *demux)
const AdaptationSet *set = period->getAdaptationSet(type);
if(set)
{
streams[type] = new Streams::Stream(set->getMimeType());
streams[type] = new (std::nothrow) Streams::Stream(set->getMimeType());
if(!streams[type])
continue;
AbstractAdaptationLogic *logic = AdaptationLogicFactory::create(logicType, mpd);
if(!logic)
{
delete streams[type];
streams[type] = NULL;
continue;
}
SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, mpd);
try
{
streams[type]->create(demux, AdaptationLogicFactory::create( logicType, mpd ) );
if(!tracker)
throw VLC_ENOMEM;
streams[type]->create(demux, logic, tracker);
} catch (int) {
delete streams[type];
delete logic;
delete tracker;
streams[type] = NULL;
}
}
}
conManager = new HTTPConnectionManager(stream);
conManager = new (std::nothrow) HTTPConnectionManager(stream);
if(!conManager)
return false;
......
......@@ -26,7 +26,7 @@
#define DASHMANAGER_H_
#include "http/HTTPConnectionManager.h"
#include "adaptationlogic/IAdaptationLogic.h"
#include "adaptationlogic/AbstractAdaptationLogic.h"
#include "mpd/MPD.h"
namespace dash
......@@ -35,7 +35,7 @@ namespace dash
{
public:
DASHManager( mpd::MPD *mpd,
logic::IAdaptationLogic::LogicType type, stream_t *stream);
logic::AbstractAdaptationLogic::LogicType type, stream_t *stream);
virtual ~DASHManager ();
bool start (demux_t *);
......@@ -47,7 +47,7 @@ namespace dash
private:
http::HTTPConnectionManager *conManager;
logic::IAdaptationLogic::LogicType logicType;
logic::AbstractAdaptationLogic::LogicType logicType;
mpd::MPD *mpd;
stream_t *stream;
Streams::Stream *streams[Streams::count];
......
/*
* SegmentTracker.cpp
*****************************************************************************
* Copyright (C) 2014 - VideoLAN authors
*
* 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 "SegmentTracker.hpp"
#include "mpd/MPD.h"
using namespace dash;
using namespace dash::logic;
using namespace dash::http;
using namespace dash::mpd;
SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, mpd::MPD *mpd_)
{
count = 0;
initializing = true;
prevRepresentation = NULL;
currentPeriod = mpd_->getFirstPeriod();
setAdaptationLogic(logic_);
mpd = mpd_;
}
SegmentTracker::~SegmentTracker()
{
}
void SegmentTracker::setAdaptationLogic(AbstractAdaptationLogic *logic_)
{
logic = logic_;
}
void SegmentTracker::resetCounter()
{
count = 0;
prevRepresentation = NULL;
}
Chunk * SegmentTracker::getNextChunk(Streams::Type type)
{
Representation *rep;
ISegment *segment;
if(!currentPeriod)
return NULL;
if(prevRepresentation && !prevRepresentation->canBitswitch())
rep = prevRepresentation;
else
rep = logic->getCurrentRepresentation(type, currentPeriod);
if ( rep == NULL )
return NULL;
if(rep != prevRepresentation)
{
prevRepresentation = rep;
initializing = true;
}
if(initializing)
{
initializing = false;
segment = rep->getSegment(Representation::INFOTYPE_INIT);
if(segment)
return segment->toChunk(count, rep);
}
segment = rep->getSegment(Representation::INFOTYPE_MEDIA, count);
if(!segment)
{
currentPeriod = mpd->getNextPeriod(currentPeriod);
resetCounter();
return getNextChunk(type);
}
Chunk *chunk = segment->toChunk(count, rep);
if(chunk)
{
segment->done();
count++;
}
return chunk;
}
/*
* IAdaptationLogic.h
* SegmentTracker.hpp
*****************************************************************************
* Copyright (C) 2010 - 2011 Klagenfurt University
*
* Created on: Aug 10, 2010
* Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
* Christian Timmerer <christian.timmerer@itec.uni-klu.ac.at>
* Copyright (C) 2014 - VideoLAN authors
*
* 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
......@@ -21,37 +17,54 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef SEGMENTTRACKER_HPP
#define SEGMENTTRACKER_HPP
#ifndef IADAPTATIONLOGIC_H_
#define IADAPTATIONLOGIC_H_
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <http/Chunk.h>
#include <adaptationlogic/IDownloadRateObserver.h>
#include "mpd/Representation.h"
#include "buffer/IBufferObserver.h"
#include "StreamsType.hpp"
#include <vlc_common.h>
namespace dash
{
namespace mpd
{
class MPD;
class Period;
class Representation;
class Segment;
}
namespace logic
{
class IAdaptationLogic : public IDownloadRateObserver
{
public:
enum LogicType
{
Default,
AlwaysBest,
AlwaysLowest,
RateBased,
FixedRate
};
virtual dash::http::Chunk* getNextChunk (Streams::Type) = 0;
virtual dash::mpd::Representation* getCurrentRepresentation(Streams::Type) const = 0;
};
class AbstractAdaptationLogic;
}
namespace http
{
class Chunk;
}
class SegmentTracker
{
public:
SegmentTracker(logic::AbstractAdaptationLogic *, mpd::MPD *);
~SegmentTracker();
void setAdaptationLogic(logic::AbstractAdaptationLogic *);
void resetCounter();
http::Chunk* getNextChunk(Streams::Type);
private:
bool initializing;
uint64_t count;
logic::AbstractAdaptationLogic *logic;
mpd::MPD *mpd;
mpd::Period *currentPeriod;
mpd::Representation *prevRepresentation;
};
}
#endif /* IADAPTATIONLOGIC_H_ */
#endif // SEGMENTTRACKER_HPP
......@@ -19,8 +19,9 @@
*****************************************************************************/
#define __STDC_CONSTANT_MACROS
#include "Streams.hpp"
#include "adaptationlogic/IAdaptationLogic.h"
#include "adaptationlogic/AbstractAdaptationLogic.h"
#include "adaptationlogic/AdaptationLogicFactory.h"
#include "SegmentTracker.hpp"
#include <vlc_stream.h>
#include <vlc_demux.h>
......@@ -46,6 +47,7 @@ void Stream::init(const Type type_, const Format format_)
adaptationLogic = NULL;
currentChunk = NULL;
eof = false;
segmentTracker = NULL;
}
Stream::~Stream()
......@@ -53,6 +55,7 @@ Stream::~Stream()
delete currentChunk;
delete adaptationLogic;
delete output;
delete segmentTracker;
}
Type Stream::mimeToType(const std::string &mime)
......@@ -84,9 +87,8 @@ Format Stream::mimeToFormat(const std::string &mime)
return format;
}
void Stream::create(demux_t *demux, IAdaptationLogic *logic)
void Stream::create(demux_t *demux, AbstractAdaptationLogic *logic, SegmentTracker *tracker)
{
adaptationLogic = logic;
switch(format)
{
case Streams::MP4:
......@@ -99,6 +101,8 @@ void Stream::create(demux_t *demux, IAdaptationLogic *logic)
throw VLC_EBADVAR;
break;
}
adaptationLogic = logic;
segmentTracker = tracker;
}
bool Stream::isEOF() const
......@@ -130,7 +134,7 @@ Chunk * Stream::getChunk()
{
if (currentChunk == NULL)
{
currentChunk = adaptationLogic->getNextChunk(type);
currentChunk = segmentTracker->getNextChunk(type);
if (currentChunk == NULL)
eof = true;
}
......
......@@ -27,12 +27,14 @@
#include <string>
#include <vlc_common.h>
#include "StreamsType.hpp"
#include "adaptationlogic/IAdaptationLogic.h"
#include "adaptationlogic/AbstractAdaptationLogic.h"
#include "http/HTTPConnectionManager.h"
#include "http/Chunk.h"
namespace dash
{
class SegmentTracker;
namespace Streams
{
class AbstractStreamOutput;
......@@ -46,7 +48,7 @@ namespace dash
bool operator==(const Stream &) const;
static Type mimeToType(const std::string &mime);
static Format mimeToFormat(const std::string &mime);
void create(demux_t *, logic::IAdaptationLogic *);
void create(demux_t *, logic::AbstractAdaptationLogic *, SegmentTracker *);
bool isEOF() const;
mtime_t getPCR() const;
int getGroup() const;
......@@ -59,7 +61,8 @@ namespace dash
Type type;
Format format;
AbstractStreamOutput *output;
logic::IAdaptationLogic *adaptationLogic;
logic::AbstractAdaptationLogic *adaptationLogic;
SegmentTracker *segmentTracker;
http::Chunk *currentChunk;
bool eof;
};
......
......@@ -29,78 +29,16 @@
using namespace dash::logic;
using namespace dash::mpd;
using namespace dash::http;
AbstractAdaptationLogic::AbstractAdaptationLogic (MPD *mpd_) :
mpd (mpd_),
currentPeriod (mpd->getFirstPeriod())
mpd (mpd_)
{
reset();
}
AbstractAdaptationLogic::~AbstractAdaptationLogic ()
{
}
void AbstractAdaptationLogic::reset()
{
count = 0;
prevRepresentation = NULL;
}
Chunk* AbstractAdaptationLogic::getNextChunk(Streams::Type type)
{
if(!currentPeriod)
return NULL;
Representation *rep;
if(prevRepresentation && !prevRepresentation->canBitswitch())
rep = prevRepresentation;
else
rep = getCurrentRepresentation(type);
if ( rep == NULL )
return NULL;
bool reinit = count && (rep != prevRepresentation);
prevRepresentation = rep;
std::vector<ISegment *> segments = rep->getSegments();
ISegment *first = segments.empty() ? NULL : segments.front();
if (reinit && first && first->getClassId() == InitSegment::CLASSID_INITSEGMENT)
return first->toChunk(count, rep);
bool b_templated = (first && !first->isSingleShot());
if (count == segments.size() && !b_templated)
{
currentPeriod = mpd->getNextPeriod(currentPeriod);
reset();
return getNextChunk(type);
}
ISegment *seg = NULL;
if ( segments.size() > count )
{
seg = segments.at( count );
}
else if(b_templated)
{
seg = segments.back();
}
if(seg)
{
Chunk *chunk = seg->toChunk(count, rep);
count++;
seg->done();
return chunk;
}
return NULL;
}
void AbstractAdaptationLogic::updateDownloadRate (size_t, mtime_t)
{
}
......@@ -25,34 +25,42 @@
#ifndef ABSTRACTADAPTATIONLOGIC_H_
#define ABSTRACTADAPTATIONLOGIC_H_
#include "adaptationlogic/IAdaptationLogic.h"
#include "http/Chunk.h"
#include "mpd/MPD.h"
#include "mpd/Period.h"
#include "mpd/Representation.h"
#include <adaptationlogic/IDownloadRateObserver.h>
#include "StreamsType.hpp"
struct stream_t;
//struct stream_t;
namespace dash
{
namespace mpd
{
class MPD;
class Period;
class Representation;
}
namespace logic
{
class AbstractAdaptationLogic : public IAdaptationLogic
class AbstractAdaptationLogic : public IDownloadRateObserver
{
public:
AbstractAdaptationLogic (mpd::MPD *mpd);
virtual ~AbstractAdaptationLogic ();
virtual void reset ();
virtual dash::http::Chunk* getNextChunk (Streams::Type);
virtual mpd::Representation* getCurrentRepresentation(Streams::Type, mpd::Period *) const = 0;
virtual void updateDownloadRate (size_t, mtime_t);
enum LogicType
{
Default,
AlwaysBest,
AlwaysLowest,
RateBased,
FixedRate
};
protected:
dash::mpd::MPD *mpd;
dash::mpd::Period *currentPeriod;
size_t count;
mpd::Representation *prevRepresentation;
};
}
}
......
......@@ -30,19 +30,25 @@
#include "adaptationlogic/RateBasedAdaptationLogic.h"
#include "adaptationlogic/AlwaysLowestAdaptationLogic.hpp"
#include <new>
using namespace dash::logic;
using namespace dash::mpd;
IAdaptationLogic* AdaptationLogicFactory::create ( IAdaptationLogic::LogicType logic,
MPD *mpd)
AbstractAdaptationLogic* AdaptationLogicFactory::create (
AbstractAdaptationLogic::LogicType logic, MPD *mpd)
{
switch(logic)
{
case IAdaptationLogic::AlwaysBest: return new AlwaysBestAdaptationLogic (mpd);
case IAdaptationLogic::AlwaysLowest: return new AlwaysLowestAdaptationLogic (mpd);
case IAdaptationLogic::FixedRate: return new FixedRateAdaptationLogic (mpd);
case IAdaptationLogic::Default:
case IAdaptationLogic::RateBased: return new RateBasedAdaptationLogic (mpd);
case AbstractAdaptationLogic::AlwaysBest:
return new (std::nothrow) AlwaysBestAdaptationLogic(mpd);
case AbstractAdaptationLogic::AlwaysLowest:
return new (std::nothrow) AlwaysLowestAdaptationLogic(mpd);
case AbstractAdaptationLogic::FixedRate:
return new (std::nothrow) FixedRateAdaptationLogic(mpd);
case AbstractAdaptationLogic::Default:
case AbstractAdaptationLogic::RateBased:
return new (std::nothrow) RateBasedAdaptationLogic(mpd);
default:
return NULL;
}
......
......@@ -25,18 +25,24 @@
#ifndef ADAPTATIONLOGICFACTORY_H_
#define ADAPTATIONLOGICFACTORY_H_
#include "adaptationlogic/IAdaptationLogic.h"
#include "adaptationlogic/AbstractAdaptationLogic.h"
struct stream_t;
namespace dash
{
namespace mpd
{
class MPD;
}
namespace logic
{
class AdaptationLogicFactory
{
public:
static IAdaptationLogic* create (IAdaptationLogic::LogicType logic, mpd::MPD *mpd);
static AbstractAdaptationLogic* create (
AbstractAdaptationLogic::LogicType logic, mpd::MPD *mpd);
};
}
}
......
......@@ -36,8 +36,8 @@ AlwaysBestAdaptationLogic::AlwaysBestAdaptationLogic (MPD *mpd) :
{
}
Representation *AlwaysBestAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
Representation *AlwaysBestAdaptationLogic::getCurrentRepresentation(Streams::Type type, mpd::Period *period) const
{
RepresentationSelector selector;
return selector.select(currentPeriod, type);
return selector.select(period, type);
}
......@@ -36,7 +36,7 @@ namespace dash
public:
AlwaysBestAdaptationLogic (mpd::MPD *mpd);
virtual mpd::Representation *getCurrentRepresentation(Streams::Type) const;
virtual mpd::Representation *getCurrentRepresentation(Streams::Type, mpd::Period *) const;
};
}
}
......
......@@ -28,8 +28,8 @@ AlwaysLowestAdaptationLogic::AlwaysLowestAdaptationLogic(mpd::MPD *mpd):
{
}
Representation *AlwaysLowestAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
Representation *AlwaysLowestAdaptationLogic::getCurrentRepresentation(Streams::Type type, mpd::Period *period) const
{
RepresentationSelector selector;
return selector.select(currentPeriod, type, 0);
return selector.select(period, type, 0);
}
......@@ -31,7 +31,7 @@ namespace dash
public:
AlwaysLowestAdaptationLogic(mpd::MPD *mpd);
virtual dash::mpd::Representation* getCurrentRepresentation(Streams::Type) const;
virtual dash::mpd::Representation* getCurrentRepresentation(Streams::Type, mpd::Period *) const;
};
}
}
......
......@@ -25,7 +25,11 @@
#ifndef IDOWNLOADRATEOBSERVER_H_
#define IDOWNLOADRATEOBSERVER_H_
#include <stdint.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
namespace dash
{
......
......@@ -27,6 +27,7 @@
#include "RateBasedAdaptationLogic.h"
#include "Representationselectors.hpp"
#include "mpd/MPD.h"
#include <vlc_common.h>
#include <vlc_variables.h>
......@@ -43,16 +44,16 @@ RateBasedAdaptationLogic::RateBasedAdaptationLogic (MPD *mpd) :
height = var_InheritInteger(mpd->getVLCObject(), "dash-prefheight");
}
Representation *RateBasedAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
Representation *RateBasedAdaptationLogic::getCurrentRepresentation(Streams::Type type, mpd::Period *period) const
{
if(currentPeriod == NULL)
if(period == NULL)
return NULL;
RepresentationSelector selector;
Representation *rep = selector.select(currentPeriod, type, currentBps, width, height);
Representation *rep = selector.select(period, type, currentBps, width, height);
if ( rep == NULL )
{
rep = selector.select(currentPeriod, type);
rep = selector.select(period, type);
if ( rep == NULL )
return NULL;
}
......@@ -83,16 +84,16 @@ FixedRateAdaptationLogic::FixedRateAdaptationLogic(mpd::MPD *mpd) :
currentBps = var_InheritInteger( mpd->getVLCObject(), "dash-prefbw" ) * 8192;
}
Representation *FixedRateAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
Representation *FixedRateAdaptationLogic::getCurrentRepresentation(Streams::Type type, mpd::Period *period) const
{
if(currentPeriod == NULL)
if(period == NULL)
return NULL;
RepresentationSelector selector;
Representation *rep = selector.select(currentPeriod, type, currentBps);
Representation *rep = selector.select(period, type, currentBps);
if ( rep == NULL )
{
rep = selector.select(currentPeriod, type);
rep = selector.select(period, type);
if ( rep == NULL )
return NULL;
}
......
......@@ -38,7 +38,7 @@ namespace dash
public:
RateBasedAdaptationLogic (mpd::MPD *mpd);
dash::mpd::Representation *getCurrentRepresentation(Streams::Type) const;
dash::mpd::Representation *getCurrentRepresentation(Streams::Type, mpd::Period *) const;
virtual void updateDownloadRate(size_t, mtime_t);
private:
......@@ -54,7 +54,7 @@ namespace dash
public:
FixedRateAdaptationLogic(mpd::MPD *mpd);
dash::mpd::Representation *getCurrentRepresentation(Streams::Type) const;
dash::mpd::Representation *getCurrentRepresentation(Streams::Type, mpd::Period *) const;
private:
size_t currentBps;
......
......@@ -61,10 +61,10 @@ static void Close (vlc_object_t *);
#define DASH_LOGIC_TEXT N_("Adaptation Logic")
static const int pi_logics[] = {dash::logic::IAdaptationLogic::RateBased,
dash::logic::IAdaptationLogic::FixedRate,
dash::logic::IAdaptationLogic::AlwaysLowest,
dash::logic::IAdaptationLogic::AlwaysBest};
static const int pi_logics[] = {dash::logic::AbstractAdaptationLogic::RateBased,
dash::logic::AbstractAdaptationLogic::FixedRate,
dash::logic::AbstractAdaptationLogic::AlwaysLowest,
dash::logic::AbstractAdaptationLogic::AlwaysBest};