Commit e017b611 authored by François Cartegnie's avatar François Cartegnie 🤞
Browse files

demux: adaptative: refactor into playlistmanager

parent 7b2c07c6
......@@ -33,6 +33,7 @@
#include "logic/RateBasedAdaptationLogic.h"
#include "logic/AlwaysLowestAdaptationLogic.hpp"
#include <vlc_stream.h>
#include <vlc_demux.h>
#include <ctime>
......@@ -40,16 +41,17 @@ using namespace adaptative::http;
using namespace adaptative::logic;
using namespace adaptative;
PlaylistManager::PlaylistManager( AbstractPlaylist *pl,
PlaylistManager::PlaylistManager( demux_t *p_demux_,
AbstractPlaylist *pl,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type,
stream_t *stream) :
AbstractAdaptationLogic::LogicType type ) :
conManager ( NULL ),
logicType ( type ),
playlist ( pl ),
streamOutputFactory( factory ),
stream ( stream ),
nextPlaylistupdate ( 0 )
p_demux ( p_demux_ ),
nextPlaylistupdate ( 0 ),
i_nzpcr ( 0 )
{
currentPeriod = playlist->getFirstPeriod();
}
......@@ -110,14 +112,12 @@ bool PlaylistManager::setupPeriod()
return true;
}
bool PlaylistManager::start(demux_t *demux_)
bool PlaylistManager::start()
{
p_demux = demux_;
if(!setupPeriod())
return false;
conManager = new (std::nothrow) HTTPConnectionManager(VLC_OBJECT(stream));
conManager = new (std::nothrow) HTTPConnectionManager(VLC_OBJECT(p_demux->s));
if(!conManager)
return false;
......@@ -261,6 +261,124 @@ bool PlaylistManager::updatePlaylist()
return true;
}
#define DEMUX_INCREMENT (CLOCK_FREQ / 20)
int PlaylistManager::demux_callback(demux_t *p_demux)
{
PlaylistManager *manager = reinterpret_cast<PlaylistManager *>(p_demux->p_sys);
return manager->doDemux(DEMUX_INCREMENT);
}
int PlaylistManager::doDemux(int64_t increment)
{
if(i_nzpcr == VLC_TS_INVALID)
{
if( Stream::status_eof == demux(i_nzpcr + increment, false) )
{
return VLC_DEMUXER_EOF;
}
i_nzpcr = getFirstDTS();
if(i_nzpcr == VLC_TS_INVALID)
i_nzpcr = getPCR();
}
Stream::status status = demux(i_nzpcr + increment, true);
switch(status)
{
case Stream::status_eof:
return VLC_DEMUXER_EOF;
case Stream::status_buffering:
break;
case Stream::status_eop:
i_nzpcr = VLC_TS_INVALID;
es_out_Control(p_demux->out, ES_OUT_RESET_PCR);
break;
case Stream::status_demuxed:
if( i_nzpcr != VLC_TS_INVALID )
{
i_nzpcr += increment;
int group = getGroup();
es_out_Control(p_demux->out, ES_OUT_SET_GROUP_PCR, group, VLC_TS_0 + i_nzpcr);
}
break;
}
if( !updatePlaylist() )
msg_Warn(p_demux, "Can't update MPD");
return VLC_DEMUXER_SUCCESS;
}
int PlaylistManager::control_callback(demux_t *p_demux, int i_query, va_list args)
{
PlaylistManager *manager = reinterpret_cast<PlaylistManager *>(p_demux->p_sys);
return manager->doControl(i_query, args);
}
int PlaylistManager::doControl(int i_query, va_list args)
{
switch (i_query)
{
case DEMUX_CAN_SEEK:
*(va_arg (args, bool *)) = seekAble();
break;
case DEMUX_CAN_CONTROL_PACE:
*(va_arg (args, bool *)) = true;
break;
case DEMUX_CAN_PAUSE:
*(va_arg (args, bool *)) = playlist->isLive();
break;
case DEMUX_GET_TIME:
*(va_arg (args, int64_t *)) = i_nzpcr;
break;
case DEMUX_GET_LENGTH:
*(va_arg (args, int64_t *)) = getDuration();
break;
case DEMUX_GET_POSITION:
if(!getDuration())
return VLC_EGENERIC;
*(va_arg (args, double *)) = (double) i_nzpcr
/ getDuration();
break;
case DEMUX_SET_POSITION:
{
int64_t time = getDuration() * va_arg(args, double);
if(playlist->isLive() ||
!getDuration() ||
!setPosition(time))
return VLC_EGENERIC;
i_nzpcr = VLC_TS_INVALID;
break;
}
case DEMUX_SET_TIME:
{
int64_t time = va_arg(args, int64_t);
if(playlist->isLive() ||
!setPosition(time))
return VLC_EGENERIC;
i_nzpcr = VLC_TS_INVALID;
break;
}
case DEMUX_GET_PTS_DELAY:
*va_arg (args, int64_t *) = INT64_C(1000) *
var_InheritInteger(p_demux, "network-caching");
break;
default:
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
AbstractAdaptationLogic *PlaylistManager::createLogic(AbstractAdaptationLogic::LogicType type)
{
switch(type)
......
......@@ -49,13 +49,12 @@ namespace adaptative
class PlaylistManager
{
public:
PlaylistManager( AbstractPlaylist *,
PlaylistManager( demux_t *, AbstractPlaylist *,
AbstractStreamOutputFactory *,
AbstractAdaptationLogic::LogicType type,
stream_t *stream);
AbstractAdaptationLogic::LogicType type );
virtual ~PlaylistManager ();
bool start(demux_t *);
bool start();
Stream::status demux(mtime_t, bool);
mtime_t getDuration() const;
......@@ -67,7 +66,15 @@ namespace adaptative
bool seekAble() const;
virtual bool updatePlaylist();
/* static callbacks */
static int control_callback(demux_t *, int, va_list);
static int demux_callback(demux_t *);
protected:
/* Demux calls */
virtual int doControl(int, va_list);
virtual int doDemux(int64_t);
bool setupPeriod();
void unsetPeriod();
/* local factories */
......@@ -77,10 +84,10 @@ namespace adaptative
AbstractAdaptationLogic::LogicType logicType;
AbstractPlaylist *playlist;
AbstractStreamOutputFactory *streamOutputFactory;
stream_t *stream;
demux_t *p_demux;
std::vector<Stream *> streams;
mtime_t nextPlaylistupdate;
mtime_t i_nzpcr;
BasePeriod *currentPeriod;
};
......
......@@ -31,9 +31,12 @@
#include "DASHManager.h"
#include "DASHStreamFormat.hpp"
#include "mpd/MPDFactory.h"
#include "mpd/ProgramInformation.h"
#include "xml/DOMParser.h"
#include "../adaptative/logic/RateBasedAdaptationLogic.h"
#include <vlc_stream.h>
#include <vlc_demux.h>
#include <vlc_meta.h>
#include "../adaptative/tools/Retrieve.hpp"
#include <algorithm>
......@@ -58,10 +61,10 @@ AbstractStreamOutput *DASHStreamOutputFactory::create(demux_t *demux, const Stre
return NULL;
}
DASHManager::DASHManager(MPD *mpd,
DASHManager::DASHManager(demux_t *demux_, MPD *mpd,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
PlaylistManager(mpd, factory, type, stream)
AbstractAdaptationLogic::LogicType type) :
PlaylistManager(demux_, mpd, factory, type)
{
}
......@@ -81,16 +84,16 @@ bool DASHManager::updatePlaylist()
/* do update */
if(nextPlaylistupdate)
{
std::string url(stream->psz_access);
std::string url(p_demux->s->psz_access);
url.append("://");
url.append(stream->psz_path);
url.append(p_demux->s->psz_path);
uint8_t *p_data = NULL;
size_t i_data = Retrieve::HTTP(VLC_OBJECT(stream), url, (void**) &p_data);
size_t i_data = Retrieve::HTTP(VLC_OBJECT(p_demux->s), url, (void**) &p_data);
if(!p_data)
return false;
stream_t *mpdstream = stream_MemoryNew(stream, p_data, i_data, false);
stream_t *mpdstream = stream_MemoryNew(p_demux->s, p_data, i_data, false);
if(!mpdstream)
{
free(p_data);
......@@ -139,26 +142,64 @@ bool DASHManager::updatePlaylist()
nextPlaylistupdate = now + (maxinterval - mininterval) / (2 * CLOCK_FREQ);
msg_Dbg(stream, "Updated MPD, next update in %" PRId64 "s (%" PRId64 "..%" PRId64 ")",
msg_Dbg(p_demux, "Updated MPD, next update in %" PRId64 "s (%" PRId64 "..%" PRId64 ")",
nextPlaylistupdate - now, mininterval, maxinterval );
return true;
}
int DASHManager::doControl(int i_query, va_list args)
{
switch (i_query)
{
case DEMUX_GET_META:
{
MPD *mpd = dynamic_cast<MPD *>(playlist);
if(!mpd)
return VLC_EGENERIC;
if(!mpd->programInfo.Get())
break;
vlc_meta_t *p_meta = (vlc_meta_t *) va_arg (args, vlc_meta_t*);
vlc_meta_t *meta = vlc_meta_New();
if (meta == NULL)
return VLC_EGENERIC;
if(!mpd->programInfo.Get()->getTitle().empty())
vlc_meta_SetTitle(meta, mpd->programInfo.Get()->getTitle().c_str());
if(!mpd->programInfo.Get()->getSource().empty())
vlc_meta_SetPublisher(meta, mpd->programInfo.Get()->getSource().c_str());
if(!mpd->programInfo.Get()->getCopyright().empty())
vlc_meta_SetCopyright(meta, mpd->programInfo.Get()->getCopyright().c_str());
if(!mpd->programInfo.Get()->getMoreInformationUrl().empty())
vlc_meta_SetURL(meta, mpd->programInfo.Get()->getMoreInformationUrl().c_str());
vlc_meta_Merge(p_meta, meta);
vlc_meta_Delete(meta);
break;
}
}
return PlaylistManager::doControl(i_query, args);
}
AbstractAdaptationLogic *DASHManager::createLogic(AbstractAdaptationLogic::LogicType type)
{
switch(type)
{
case AbstractAdaptationLogic::FixedRate:
{
size_t bps = var_InheritInteger(stream, "dash-prefbw") * 8192;
size_t bps = var_InheritInteger(p_demux, "dash-prefbw") * 8192;
return new (std::nothrow) FixedRateAdaptationLogic(bps);
}
case AbstractAdaptationLogic::Default:
case AbstractAdaptationLogic::RateBased:
{
int width = var_InheritInteger(stream, "dash-prefwidth");
int height = var_InheritInteger(stream, "dash-prefheight");
int width = var_InheritInteger(p_demux, "dash-prefwidth");
int height = var_InheritInteger(p_demux, "dash-prefheight");
return new (std::nothrow) RateBasedAdaptationLogic(width, height);
}
default:
......
......@@ -42,14 +42,16 @@ namespace dash
class DASHManager : public PlaylistManager
{
public:
DASHManager( mpd::MPD *mpd,
DASHManager( demux_t *, mpd::MPD *mpd,
AbstractStreamOutputFactory *,
logic::AbstractAdaptationLogic::LogicType type,
stream_t *stream);
logic::AbstractAdaptationLogic::LogicType type);
virtual ~DASHManager ();
virtual bool updatePlaylist(); //reimpl
virtual AbstractAdaptationLogic *createLogic(AbstractAdaptationLogic::LogicType); //reimpl
protected:
virtual int doControl(int, va_list); /* reimpl */
};
}
......
......@@ -35,14 +35,10 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_demux.h>
#include <vlc_meta.h>
#include <errno.h>
#include "xml/DOMParser.h"
#include "mpd/MPDFactory.h"
#include "mpd/Period.h"
#include "mpd/ProgramInformation.h"
#include "DASHManager.h"
using namespace adaptative::logic;
......@@ -96,15 +92,6 @@ vlc_module_end ()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
struct demux_sys_t
{
dash::DASHManager *p_dashManager;
dash::mpd::MPD *p_mpd;
mtime_t i_nzpcr;
};
static int Demux( demux_t * );
static int Control (demux_t *p_demux, int i_query, va_list args);
/*****************************************************************************
* Open:
......@@ -140,30 +127,21 @@ static int Open(vlc_object_t *p_obj)
return VLC_EGENERIC;
}
demux_sys_t *p_sys = (demux_sys_t *) malloc(sizeof(demux_sys_t));
if (unlikely(p_sys == NULL))
return VLC_ENOMEM;
p_sys->p_mpd = mpd;
int logic = var_InheritInteger( p_obj, "dash-logic" );
DASHManager*p_dashManager = new DASHManager(p_sys->p_mpd,
DASHManager *p_dashManager = new (std::nothrow) DASHManager(p_demux, mpd,
new (std::nothrow) DASHStreamOutputFactory,
static_cast<AbstractAdaptationLogic::LogicType>(logic),
p_demux->s);
static_cast<AbstractAdaptationLogic::LogicType>(logic));
BasePeriod *period = mpd->getFirstPeriod();
if(period && !p_dashManager->start(p_demux))
if(period && !p_dashManager->start())
{
delete p_dashManager;
free( p_sys );
return VLC_EGENERIC;
}
p_sys->p_dashManager = p_dashManager;
p_demux->p_sys = p_sys;
p_demux->pf_demux = Demux;
p_demux->pf_control = Control;
p_sys->i_nzpcr = 0;
p_demux->p_sys = reinterpret_cast<demux_sys_t *>(p_dashManager);
p_demux->pf_demux = p_dashManager->demux_callback;
p_demux->pf_control = p_dashManager->control_callback;
msg_Dbg(p_obj,"opening mpd file (%s)", p_demux->s->psz_path);
......@@ -174,151 +152,9 @@ static int Open(vlc_object_t *p_obj)
*****************************************************************************/
static void Close(vlc_object_t *p_obj)
{
demux_t *p_demux = (demux_t*) p_obj;
demux_sys_t *p_sys = (demux_sys_t *) p_demux->p_sys;
DASHManager *p_dashManager = p_sys->p_dashManager;
delete p_dashManager;
free(p_sys);
}
/*****************************************************************************
* Callbacks:
*****************************************************************************/
#define DEMUX_INCREMENT (CLOCK_FREQ / 20)
static int Demux(demux_t *p_demux)
{
demux_sys_t *p_sys = p_demux->p_sys;
if(p_sys->i_nzpcr == VLC_TS_INVALID)
{
if( Stream::status_eof ==
p_sys->p_dashManager->demux(p_sys->i_nzpcr + DEMUX_INCREMENT, false) )
{
return VLC_DEMUXER_EOF;
}
p_sys->i_nzpcr = p_sys->p_dashManager->getFirstDTS();
if(p_sys->i_nzpcr == VLC_TS_INVALID)
p_sys->i_nzpcr = p_sys->p_dashManager->getPCR();
}
Stream::status status =
p_sys->p_dashManager->demux(p_sys->i_nzpcr + DEMUX_INCREMENT, true);
switch(status)
{
case Stream::status_eof:
return VLC_DEMUXER_EOF;
case Stream::status_buffering:
break;
case Stream::status_eop:
p_sys->i_nzpcr = VLC_TS_INVALID;
es_out_Control(p_demux->out, ES_OUT_RESET_PCR);
break;
case Stream::status_demuxed:
if( p_sys->i_nzpcr != VLC_TS_INVALID )
{
p_sys->i_nzpcr += DEMUX_INCREMENT;
int group = p_sys->p_dashManager->getGroup();
es_out_Control(p_demux->out, ES_OUT_SET_GROUP_PCR, group, VLC_TS_0 + p_sys->i_nzpcr);
}
break;
}
if( !p_sys->p_dashManager->updatePlaylist() )
msg_Warn(p_demux, "Can't update MPD");
demux_t *p_demux = (demux_t*) p_obj;
PlaylistManager *p_manager = reinterpret_cast<PlaylistManager *>(p_demux->p_sys);
return VLC_DEMUXER_SUCCESS;
delete p_manager;
}
static int Control (demux_t *p_demux, int i_query, va_list args)
{
demux_sys_t *p_sys = p_demux->p_sys;
switch (i_query)
{
case DEMUX_CAN_SEEK:
*(va_arg (args, bool *)) = p_sys->p_dashManager->seekAble();
break;
case DEMUX_CAN_CONTROL_PACE:
*(va_arg (args, bool *)) = true;
break;
case DEMUX_CAN_PAUSE:
*(va_arg (args, bool *)) = p_sys->p_mpd->isLive();
break;
case DEMUX_GET_TIME:
*(va_arg (args, int64_t *)) = p_sys->i_nzpcr;
break;
case DEMUX_GET_LENGTH:
*(va_arg (args, int64_t *)) = p_sys->p_dashManager->getDuration();
break;
case DEMUX_GET_POSITION:
if(!p_sys->p_dashManager->getDuration())
return VLC_EGENERIC;
*(va_arg (args, double *)) = (double) p_sys->i_nzpcr
/ p_sys->p_dashManager->getDuration();
break;
case DEMUX_SET_POSITION:
{
int64_t time = p_sys->p_dashManager->getDuration() * va_arg(args, double);
if(p_sys->p_mpd->isLive() ||
!p_sys->p_dashManager->getDuration() ||
!p_sys->p_dashManager->setPosition(time))
return VLC_EGENERIC;
p_sys->i_nzpcr = VLC_TS_INVALID;
break;
}
case DEMUX_SET_TIME:
{
int64_t time = va_arg(args, int64_t);
if(p_sys->p_mpd->isLive() ||
!p_sys->p_dashManager->setPosition(time))
return VLC_EGENERIC;
p_sys->i_nzpcr = VLC_TS_INVALID;
break;
}
case DEMUX_GET_PTS_DELAY:
*va_arg (args, int64_t *) = INT64_C(1000) *
var_InheritInteger(p_demux, "network-caching");
break;
case DEMUX_GET_META:
{
if(!p_sys->p_mpd->programInfo.Get())
break;
vlc_meta_t *p_meta = (vlc_meta_t *) va_arg (args, vlc_meta_t*);
vlc_meta_t *meta = vlc_meta_New();
if (meta == NULL)
return VLC_EGENERIC;
if(!p_sys->p_mpd->programInfo.Get()->getTitle().empty())
vlc_meta_SetTitle(meta, p_sys->p_mpd->programInfo.Get()->getTitle().c_str());
if(!p_sys->p_mpd->programInfo.Get()->getSource().empty())
vlc_meta_SetPublisher(meta, p_sys->p_mpd->programInfo.Get()->getSource().c_str());
if(!p_sys->p_mpd->programInfo.Get()->getCopyright().empty())
vlc_meta_SetCopyright(meta, p_sys->p_mpd->programInfo.Get()->getCopyright().c_str());
if(!p_sys->p_mpd->programInfo.Get()->getMoreInformationUrl().empty())
vlc_meta_SetURL(meta, p_sys->p_mpd->programInfo.Get()->getMoreInformationUrl().c_str());
vlc_meta_Merge(p_meta, meta);
vlc_meta_Delete(meta);
break;
}
default:
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
......@@ -27,6 +27,7 @@
#include "../adaptative/tools/Retrieve.hpp"
#include "playlist/Parser.hpp"
#include <vlc_stream.h>
#include <vlc_demux.h>
#include <time.h>
using namespace adaptative;
......@@ -34,10 +35,10 @@ using namespace adaptative::logic;
using namespace hls;
using namespace hls::playlist;
HLSManager::HLSManager(M3U8 *playlist,
HLSManager::HLSManager(demux_t *demux_, M3U8 *playlist,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
PlaylistManager(playlist, factory, type, stream)
AbstractAdaptationLogic::LogicType type) :
PlaylistManager(demux_, playlist, factory, type)
{
}
......@@ -51,14 +52,14 @@ AbstractAdaptationLogic *HLSManager::createLogic(AbstractAdaptationLogic::LogicT
{
case AbstractAdaptationLogic::FixedRate: