Commit bfdc2b60 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: rework stream format setup

parent 98332157
......@@ -298,6 +298,8 @@ adaptative_SOURCES = \
demux/adaptative/PlaylistManager.h \
demux/adaptative/SegmentTracker.cpp \
demux/adaptative/SegmentTracker.hpp \
demux/adaptative/StreamFormat.cpp \
demux/adaptative/StreamFormat.hpp \
demux/adaptative/Streams.cpp \
demux/adaptative/Streams.hpp \
demux/adaptative/StreamsType.hpp \
......@@ -343,7 +345,8 @@ libdash_plugin_la_SOURCES = \
demux/dash/dash.cpp \
demux/dash/dash.hpp \
demux/dash/DASHManager.cpp \
demux/dash/DASHManager.h
demux/dash/DASHManager.h \
demux/dash/DASHStreamFormat.hpp
libdash_plugin_la_SOURCES += $(adaptative_SOURCES)
libdash_plugin_la_SOURCES += demux/mp4/libmp4.c demux/mp4/libmp4.h
......@@ -368,6 +371,7 @@ libhls_plugin_la_SOURCES = \
demux/hls/playlist/Tags.cpp \
demux/hls/HLSManager.hpp \
demux/hls/HLSManager.cpp \
demux/hls/HLSStreamFormat.hpp \
demux/hls/hls.cpp \
demux/hls/hls.hpp
......
......@@ -41,12 +41,13 @@ using namespace adaptative::logic;
using namespace adaptative;
PlaylistManager::PlaylistManager( AbstractPlaylist *pl,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type,
stream_t *stream) :
conManager ( NULL ),
logicType ( type ),
playlist ( pl ),
streamOutputFactory( NULL ),
streamOutputFactory( factory ),
stream ( stream ),
nextPlaylistupdate ( 0 )
{
......@@ -57,6 +58,7 @@ PlaylistManager::PlaylistManager( AbstractPlaylist *pl,
PlaylistManager::~PlaylistManager ()
{
delete conManager;
delete streamOutputFactory;
for(int i=0; i<StreamTypeCount; i++)
delete streams[i];
}
......@@ -73,7 +75,7 @@ bool PlaylistManager::start(demux_t *demux)
const BaseAdaptationSet *set = period->getAdaptationSet(type);
if(set)
{
streams[type] = new (std::nothrow) Stream(set->getMimeType());
streams[type] = new (std::nothrow) Stream(type, set->getStreamFormat());
if(!streams[type])
continue;
AbstractAdaptationLogic *logic = createLogic(logicType);
......@@ -85,13 +87,11 @@ bool PlaylistManager::start(demux_t *demux)
}
SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, playlist);
DefaultStreamOutputFactory defaultfactory;
try
{
if(!tracker)
if(!tracker || !streamOutputFactory)
throw VLC_ENOMEM;
streams[type]->create(demux, logic, tracker,
(streamOutputFactory) ? *streamOutputFactory : defaultfactory );
streams[type]->create(demux, logic, tracker, streamOutputFactory);
} catch (int) {
delete streams[type];
delete logic;
......
......@@ -42,12 +42,15 @@ namespace adaptative
using namespace http;
class AbstractStreamFactory;
class AbstractStreamOutputFactory;
class PlaylistManager
{
public:
PlaylistManager( AbstractPlaylist *,
AbstractAdaptationLogic::LogicType type, stream_t *stream);
AbstractStreamOutputFactory *,
AbstractAdaptationLogic::LogicType type,
stream_t *stream);
virtual ~PlaylistManager ();
bool start(demux_t *);
......
/*
* StreamFormat.cpp
*****************************************************************************
* Copyright (C) 2015 - 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 "StreamFormat.hpp"
using namespace adaptative;
StreamFormat::operator unsigned() const
{
return formatid;
}
StreamFormat::StreamFormat( int formatid_ )
{
formatid = formatid_;
}
StreamFormat::~StreamFormat()
{
}
bool StreamFormat::operator ==(const StreamFormat &other) const
{
return formatid == other.formatid;
}
/*
* StreamFormat.hpp
*****************************************************************************
* Copyright (C) 2015 - 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.
*****************************************************************************/
#ifndef STREAMFORMAT_HPP
#define STREAMFORMAT_HPP
namespace adaptative
{
class StreamFormat
{
public:
static const unsigned UNSUPPORTED = 0;
StreamFormat( int = UNSUPPORTED );
~StreamFormat();
operator unsigned() const;
bool operator==(const StreamFormat &) const;
private:
unsigned formatid;
};
}
#endif // STREAMFORMAT_HPP
......@@ -31,17 +31,12 @@ using namespace adaptative;
using namespace adaptative::http;
using namespace adaptative::logic;
Stream::Stream(const std::string &mime)
{
init(mimeToType(mime), mimeToFormat(mime));
}
Stream::Stream(const StreamType type, const StreamFormat format)
Stream::Stream(const StreamType type, const StreamFormat &format)
{
init(type, format);
}
void Stream::init(const StreamType type_, const StreamFormat format_)
void Stream::init(const StreamType type_, const StreamFormat &format_)
{
type = type_;
format = format_;
......@@ -74,29 +69,26 @@ StreamType Stream::mimeToType(const std::string &mime)
return mimetype;
}
StreamFormat Stream::mimeToFormat(const std::string &mime)
{
StreamFormat format = StreamFormat::UNSUPPORTED;
std::string::size_type pos = mime.find("/");
if(pos != std::string::npos)
{
std::string tail = mime.substr(pos + 1);
if(tail == "mp4")
format = StreamFormat::MP4;
else if (tail == "mp2t")
format = StreamFormat::MPEG2TS;
}
return format;
}
void Stream::create(demux_t *demux, AbstractAdaptationLogic *logic,
SegmentTracker *tracker, AbstractStreamOutputFactory &factory)
SegmentTracker *tracker, const AbstractStreamOutputFactory *factory)
{
output = factory.create(demux, format);
updateFormat(demux, format, factory);
adaptationLogic = logic;
segmentTracker = tracker;
}
void Stream::updateFormat(demux_t *demux, StreamFormat &newformat, const AbstractStreamOutputFactory *factory)
{
if( format == newformat && output )
return;
delete output;
format = newformat;
output = factory->create(demux, format);
if(!output)
throw VLC_EGENERIC;
}
bool Stream::isEOF() const
{
return false;
......@@ -104,21 +96,29 @@ bool Stream::isEOF() const
mtime_t Stream::getPCR() const
{
if(!output)
return 0;
return output->getPCR();
}
mtime_t Stream::getFirstDTS() const
{
if(!output)
return 0;
return output->getFirstDTS();
}
int Stream::getGroup() const
{
if(!output)
return 0;
return output->getGroup();
}
int Stream::esCount() const
{
if(!output)
return 0;
return output->esCount();
}
......@@ -129,7 +129,7 @@ bool Stream::operator ==(const Stream &stream) const
Chunk * Stream::getChunk()
{
if (currentChunk == NULL)
if (currentChunk == NULL && output)
{
currentChunk = segmentTracker->getNextChunk(type, output->switchAllowed());
if (currentChunk == NULL)
......@@ -145,6 +145,9 @@ bool Stream::seekAble() const
Stream::status Stream::demux(HTTPConnectionManager *connManager, mtime_t nz_deadline, bool send)
{
if(!output)
return Stream::status_eof;
if(nz_deadline + VLC_TS_0 > output->getPCR()) /* not already demuxed */
{
/* need to read, demuxer still buffering, ... */
......@@ -225,13 +228,19 @@ size_t Stream::read(HTTPConnectionManager *connManager)
readsize = block->i_buffer;
output->pushBlock(block);
if(output)
output->pushBlock(block);
else
block_Release(block);
return readsize;
}
bool Stream::setPosition(mtime_t time, bool tryonly)
{
if(!output)
return false;
bool ret = segmentTracker->setPosition(time, output->reinitsOnSeek(), tryonly);
if(!tryonly && ret)
{
......@@ -623,21 +632,3 @@ void BaseStreamOutput::esOutDestroy(es_out_t *fakees)
me->realdemux->out->pf_destroy(me->realdemux->out);
}
/* !Static callbacks */
AbstractStreamOutput *DefaultStreamOutputFactory::create(demux_t *demux, int format) const
{
switch(format)
{
case StreamFormat::MP4:
return new BaseStreamOutput(demux, "mp4");
case StreamFormat::MPEG2TS:
return new BaseStreamOutput(demux, "ts");
default:
throw VLC_EBADVAR;
break;
}
return NULL;
}
......@@ -29,6 +29,7 @@
#include <vlc_common.h>
#include <vlc_es.h>
#include "StreamsType.hpp"
#include "StreamFormat.hpp"
namespace adaptative
{
......@@ -55,14 +56,13 @@ namespace adaptative
class Stream
{
public:
Stream(const std::string &mime);
Stream(const StreamType, const StreamFormat);
Stream(const StreamType, const StreamFormat &);
~Stream();
bool operator==(const Stream &) const;
static StreamType mimeToType(const std::string &mime);
static StreamFormat mimeToFormat(const std::string &mime);
void create(demux_t *, AbstractAdaptationLogic *,
SegmentTracker *, AbstractStreamOutputFactory &);
SegmentTracker *, const AbstractStreamOutputFactory *);
void updateFormat(demux_t *, StreamFormat &, const AbstractStreamOutputFactory *);
bool isEOF() const;
mtime_t getPCR() const;
mtime_t getFirstDTS() const;
......@@ -77,7 +77,7 @@ namespace adaptative
private:
Chunk *getChunk();
void init(const StreamType, const StreamFormat);
void init(const StreamType, const StreamFormat &);
size_t read(HTTPConnectionManager *);
StreamType type;
StreamFormat format;
......@@ -114,13 +114,8 @@ namespace adaptative
class AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const = 0;
};
class DefaultStreamOutputFactory : public AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, int streamType) const;
virtual ~AbstractStreamOutputFactory() {}
virtual AbstractStreamOutput *create(demux_t*, const StreamFormat &) const = 0;
};
class BaseStreamOutput : public AbstractStreamOutput
......
......@@ -31,13 +31,6 @@ namespace adaptative
APPLICATION
};
enum StreamFormat
{
UNSUPPORTED = 0,
MP4,
MPEG2TS
};
static const int StreamTypeCount = APPLICATION + 1;
}
......
......@@ -35,6 +35,7 @@
#include "SegmentTemplate.h"
#include "BasePeriod.h"
using namespace adaptative;
using namespace adaptative::playlist;
BaseAdaptationSet::BaseAdaptationSet(BasePeriod *period) :
......@@ -50,12 +51,9 @@ BaseAdaptationSet::~BaseAdaptationSet ()
childs.clear();
}
const std::string& BaseAdaptationSet::getMimeType() const
StreamFormat BaseAdaptationSet::getStreamFormat() const
{
if (mimeType.empty() && !representations.empty())
return representations.front()->getMimeType();
else
return mimeType;
return StreamFormat();
}
std::vector<BaseRepresentation*>& BaseAdaptationSet::getRepresentations()
......
......@@ -30,6 +30,7 @@
#include "CommonAttributesElements.h"
#include "SegmentInformation.hpp"
#include "../StreamFormat.hpp"
namespace adaptative
{
......@@ -45,7 +46,7 @@ namespace adaptative
BaseAdaptationSet(BasePeriod *);
virtual ~BaseAdaptationSet();
virtual const std::string& getMimeType() const; /*reimpl*/
virtual StreamFormat getStreamFormat() const; /*reimpl*/
std::vector<BaseRepresentation *>& getRepresentations ();
void setSwitchPolicy(bool value);
bool getBitstreamSwitching() const;
......
......@@ -31,6 +31,7 @@
#include "BaseAdaptationSet.h"
#include "SegmentTemplate.h"
using namespace adaptative;
using namespace adaptative::playlist;
BaseRepresentation::BaseRepresentation( BaseAdaptationSet *set ) :
......@@ -44,6 +45,11 @@ BaseRepresentation::~BaseRepresentation ()
{
}
StreamFormat BaseRepresentation::getStreamFormat() const
{
return StreamFormat();
}
uint64_t BaseRepresentation::getBandwidth () const
{
return bandwidth;
......
......@@ -30,6 +30,7 @@
#include "CommonAttributesElements.h"
#include "SegmentInformation.hpp"
#include "../StreamFormat.hpp"
namespace adaptative
{
......@@ -46,6 +47,7 @@ namespace adaptative
BaseRepresentation( BaseAdaptationSet * );
virtual ~BaseRepresentation ();
virtual StreamFormat getStreamFormat() const;
/*
* @return The bitrate required for this representation
* in bits per seconds.
......
......@@ -29,6 +29,7 @@
#include <inttypes.h>
#include "DASHManager.h"
#include "DASHStreamFormat.hpp"
#include "mpd/MPDFactory.h"
#include "xml/DOMParser.h"
#include "../adaptative/logic/RateBasedAdaptationLogic.h"
......@@ -42,9 +43,25 @@ using namespace dash;
using namespace dash::mpd;
using namespace adaptative::logic;
AbstractStreamOutput *DASHStreamOutputFactory::create(demux_t *demux, const StreamFormat &format) const
{
unsigned fmt = format;
switch(fmt)
{
case DASHStreamFormat::MP4:
return new BaseStreamOutput(demux, "mp4");
case DASHStreamFormat::MPEG2TS:
return new BaseStreamOutput(demux, "ts");
}
return NULL;
}
DASHManager::DASHManager(MPD *mpd,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
PlaylistManager(mpd, type, stream)
PlaylistManager(mpd, factory, type, stream)
{
}
......
......@@ -33,10 +33,17 @@ namespace dash
{
using namespace adaptative;
class DASHStreamOutputFactory : public AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, const StreamFormat &) const;
};
class DASHManager : public PlaylistManager
{
public:
DASHManager( mpd::MPD *mpd,
AbstractStreamOutputFactory *,
logic::AbstractAdaptationLogic::LogicType type,
stream_t *stream);
virtual ~DASHManager ();
......
/*
* DASHStreamFormat.hpp
*****************************************************************************
* Copyright (C) 2015 - 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.
*****************************************************************************/
#ifndef DASHSTREAMFORMAT_HPP
#define DASHSTREAMFORMAT_HPP
#include "../adaptative/StreamFormat.hpp"
#include <string>
namespace dash
{
using namespace adaptative;
class DASHStreamFormat : public StreamFormat
{
public:
static const unsigned MPEG2TS = StreamFormat::UNSUPPORTED + 1;
static const unsigned MP4 = StreamFormat::UNSUPPORTED + 2;
static StreamFormat mimeToFormat(const std::string &mime)
{
std::string::size_type pos = mime.find("/");
if(pos != std::string::npos)
{
std::string tail = mime.substr(pos + 1);
if(tail == "mp4")
return StreamFormat(DASHStreamFormat::MP4);
else if (tail == "mp2t")
return StreamFormat(DASHStreamFormat::MPEG2TS);
}
return StreamFormat();
}
};
}
#endif // DASHSTREAMFORMAT_HPP
......@@ -141,6 +141,7 @@ static int Open(vlc_object_t *p_obj)
p_sys->p_mpd = mpd;
int logic = var_InheritInteger( p_obj, "dash-logic" );
DASHManager*p_dashManager = new DASHManager(p_sys->p_mpd,
new (std::nothrow) DASHStreamOutputFactory,
static_cast<AbstractAdaptationLogic::LogicType>(logic),
p_demux->s);
......
......@@ -25,6 +25,7 @@
#include "AdaptationSet.h"
#include "Representation.h"
#include "Period.h"
#include "../DASHStreamFormat.hpp"
using namespace dash::mpd;
......@@ -39,6 +40,22 @@ AdaptationSet::~AdaptationSet()
{
}
StreamFormat AdaptationSet::getStreamFormat() const
{
if(!getMimeType().empty())
{
return DASHStreamFormat::mimeToFormat(getMimeType());
}
else if (!representations.empty())
{
return representations.front()->getStreamFormat();
}
else
{
return StreamFormat();
}
}
bool AdaptationSet::getSubsegmentAlignmentFlag() const
{
return subsegmentAlignmentFlag;
......
......@@ -39,6 +39,8 @@ namespace dash
class Period;
class Representation;
using namespace adaptative;
class AdaptationSet : public adaptative::playlist::BaseAdaptationSet,
public DASHCommonAttributesElements
{
......@@ -46,6 +48,7 @@ namespace dash
AdaptationSet(Period *);
virtual ~AdaptationSet();
virtual StreamFormat getStreamFormat() const; /* reimpl */
bool getSubsegmentAlignmentFlag() const;
void setSubsegmentAlignmentFlag( bool alignment );
const Representation* getRepresentationById ( const std::string &id ) const;
......
......@@ -33,6 +33,7 @@
#include "TrickModeType.h"
#include "../adaptative/playlist/SegmentTemplate.h"
#include "../adaptative/playlist/SegmentTimeline.h"
#include "../DASHStreamFormat.hpp"
using namespace dash::mpd;
......@@ -48,6 +49,14 @@ Representation::~Representation ()
delete(this->trickModeType);
}
StreamFormat Representation::getStreamFormat() const
{
if(getMimeType().empty())
return DASHStreamFormat::mimeToFormat(adaptationSet->getMimeType());
else
return DASHStreamFormat::mimeToFormat(getMimeType());
}
TrickModeType* Representation::getTrickModeType () const
{
return this->trickModeType;
......
......@@ -37,6 +37,7 @@ namespace dash
class TrickModeType;
class MPD;
using namespace adaptative;
using namespace adaptative::playlist;
class Representation : public BaseRepresentation,
......@@ -47,6 +48,7 @@ namespace dash
Representation( AdaptationSet * );
virtual ~Representation ();
virtual StreamFormat getStreamFormat() const; /* reimpl */
int getQualityRanking () const;
void setQualityRanking ( int qualityRanking );
const std::list<const Representation*>& getDependencies() const;
......
......@@ -23,6 +23,7 @@
#endif
#include "HLSManager.hpp"
#include "HLSStreamFormat.hpp"
#include "../adaptative/logic/RateBasedAdaptationLogic.h"
#include "../adaptative/tools/Retrieve.hpp"
#include "playlist/Parser.hpp"
......@@ -34,9 +35,22 @@ using namespace adaptative::logic;
using namespace hls;
using namespace hls::playlist;
AbstractStreamOutput *HLSStreamOutputFactory::create(demux_t *demux, const StreamFormat &format) const
{
unsigned fmt = format;
switch(fmt)
{
default:
case HLSStreamFormat::MPEG2TS:
return new BaseStreamOutput(demux, "ts");
}
return NULL;
}
HLSManager::HLSManager(M3U8 *playlist,
AbstractStreamOutputFactory *factory,
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
PlaylistManager(playlist, type, stream)
PlaylistManager(playlist, factory, type, stream)
{
}
......
......@@ -28,10 +28,17 @@ namespace hls
{
using namespace adaptative;
class HLSStreamOutputFactory : public AbstractStreamOutputFactory
{
public:
virtual AbstractStreamOutput *create(demux_t*, const StreamFormat &) const;
};
class HLSManager : public PlaylistManager
{
public:
HLSManager( playlist::M3U8 *,
AbstractStreamOutputFactory *,
logic::AbstractAdaptationLogic::LogicType type,
stream_t *stream );
virtual ~HLSManager();
......
/*
* HLSStreamFormat.hpp
*****************************************************************************
* Copyright (C) 2015 - 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.
*****************************************************************************/
#ifndef HLSSTREAMFORMAT_HPP
#define HLSSTREAMFORMAT_HPP
#include "../adaptative/StreamFormat.hpp"
#include <string>
namespace hls
{
using namespace adaptative;
class HLSStreamFormat : public StreamFormat
{
public:
static const unsigned MPEG2TS = StreamFormat::UNSUPPORTED + 1;
};
}
#endif // HLSSTREAMFORMAT_HPP
......@@ -178,6 +178,7 @@ static int Open(vlc_object_t *p_obj)
HLSManager *p_manager =
new (std::nothrow) HLSManager(p_sys->p_playlist,
new (std::nothrow) HLSStreamOutputFactory,
static_cast<AbstractAdaptationLogic::LogicType>(logic),
p_demux->s);
......
......@@ -113,8 +113,6 @@ void Parser::parseRepresentation(BaseAdaptationSet *adaptSet, const AttributesTa
Representation *rep = new (std::nothrow) Representation(adaptSet);
if(rep)
{
rep->setMimeType("video/mp2t");
if(uriAttr)
{
size_t pos = uriAttr->value.find_last_of('/');
......
......@@ -28,7 +28,9 @@
#include "../adaptative/playlist/BasePeriod.h"
#include "../adaptative/playlist/BaseAdaptationSet.h"
#include "../adaptative/playlist/SegmentList.h"
#include "../HLSStreamFormat.hpp"
using namespace hls;
using namespace hls::playlist;
Representation::Representation ( BaseAdaptationSet *set ) :
......@@ -41,6 +43,11 @@ Representation::~Representation ()
{
}
StreamFormat Representation::getStreamFormat() const
{
return StreamFormat(HLSStreamFormat::MPEG2TS);
}
bool Representation::isLive() const
{
return b_live;
......
......@@ -30,6 +30,7 @@ namespace hls
{
class M3U8;
using namespace adaptative;
using namespace adaptative::playlist;
class Representation : public BaseRepresentation
......@@ -39,6 +40,8 @@ namespace hls
public:
Representation( BaseAdaptationSet * );
virtual ~Representation ();
virtual StreamFormat getStreamFormat() const; /* reimpl */
void localMergeWithPlaylist(M3U8 *, mtime_t);
bool isLive() const;
virtual void mergeWith(SegmentInformation *, mtime_t); /* reimpl */
......
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