Commit 9565350a authored by Francois Cartegnie's avatar Francois Cartegnie

demux: hls: add adaptative based hls demuxer

parent 621b86f9
......@@ -57,6 +57,7 @@ Demuxers:
* Support for Creative ADPCM/alaw/ulaw/S16L in VOC files
* Support for Creative ADPCM in AVI
* Directory Demux can now sort items, ignore extensions and hidden files
* Replaced httplive stream filter with new hls demuxer
Stream filter:
* Added ARIB STD-B25 TS streams decoder
......
......@@ -175,6 +175,7 @@ $Id$
* hevc: HEVC demuxer
* hotkeys: hotkeys control module
* hqdn3d: High Quality denoising filter
* hls: HTTP Live Streaming demuxer
* http: HTTP Network access module
* httplive: HTTP Live streaming for playback
* i420_rgb: planar YUV to packed RGB conversion functions
......
......@@ -244,45 +244,7 @@ if HAVE_DVBPSI
demux_LTLIBRARIES += libts_plugin.la
endif
libdash_plugin_la_SOURCES = \
demux/dash/mpd/AdaptationSet.cpp \
demux/dash/mpd/AdaptationSet.h \
demux/dash/mpd/DASHCommonAttributesElements.cpp \
demux/dash/mpd/DASHCommonAttributesElements.h \
demux/dash/mpd/DASHSegment.cpp \
demux/dash/mpd/DASHSegment.h \
demux/dash/mpd/ContentDescription.cpp \
demux/dash/mpd/ContentDescription.h \
demux/dash/mpd/IsoffMainParser.cpp \
demux/dash/mpd/IsoffMainParser.h \
demux/dash/mpd/MPD.cpp \
demux/dash/mpd/MPD.h \
demux/dash/mpd/MPDFactory.cpp \
demux/dash/mpd/MPDFactory.h \
demux/dash/mpd/Period.cpp \
demux/dash/mpd/Period.h \
demux/dash/mpd/Profile.cpp \
demux/dash/mpd/Profile.hpp \
demux/dash/mpd/ProgramInformation.cpp \
demux/dash/mpd/ProgramInformation.h \
demux/dash/mpd/Representation.cpp \
demux/dash/mpd/Representation.h \
demux/dash/mpd/TrickModeType.cpp \
demux/dash/mpd/TrickModeType.h \
demux/dash/mp4/AtomsReader.cpp \
demux/dash/mp4/AtomsReader.hpp \
demux/dash/xml/DOMHelper.cpp \
demux/dash/xml/DOMHelper.h \
demux/dash/xml/DOMParser.cpp \
demux/dash/xml/DOMParser.h \
demux/dash/xml/Node.cpp \
demux/dash/xml/Node.h \
demux/dash/dash.cpp \
demux/dash/dash.hpp \
demux/dash/DASHManager.cpp \
demux/dash/DASHManager.h
libdash_plugin_la_SOURCES += \
adaptative_SOURCES = \
demux/adaptative/playlist/AbstractPlaylist.cpp \
demux/adaptative/playlist/AbstractPlaylist.hpp \
demux/adaptative/playlist/BaseAdaptationSet.cpp \
......@@ -345,8 +307,46 @@ libdash_plugin_la_SOURCES += \
demux/adaptative/tools/Retrieve.cpp \
demux/adaptative/tools/Retrieve.hpp
libdash_plugin_la_SOURCES += demux/mp4/libmp4.c demux/mp4/libmp4.h
libdash_plugin_la_SOURCES = \
demux/dash/mpd/AdaptationSet.cpp \
demux/dash/mpd/AdaptationSet.h \
demux/dash/mpd/DASHCommonAttributesElements.cpp \
demux/dash/mpd/DASHCommonAttributesElements.h \
demux/dash/mpd/DASHSegment.cpp \
demux/dash/mpd/DASHSegment.h \
demux/dash/mpd/ContentDescription.cpp \
demux/dash/mpd/ContentDescription.h \
demux/dash/mpd/IsoffMainParser.cpp \
demux/dash/mpd/IsoffMainParser.h \
demux/dash/mpd/MPD.cpp \
demux/dash/mpd/MPD.h \
demux/dash/mpd/MPDFactory.cpp \
demux/dash/mpd/MPDFactory.h \
demux/dash/mpd/Period.cpp \
demux/dash/mpd/Period.h \
demux/dash/mpd/Profile.cpp \
demux/dash/mpd/Profile.hpp \
demux/dash/mpd/ProgramInformation.cpp \
demux/dash/mpd/ProgramInformation.h \
demux/dash/mpd/Representation.cpp \
demux/dash/mpd/Representation.h \
demux/dash/mpd/TrickModeType.cpp \
demux/dash/mpd/TrickModeType.h \
demux/dash/mp4/AtomsReader.cpp \
demux/dash/mp4/AtomsReader.hpp \
demux/dash/xml/DOMHelper.cpp \
demux/dash/xml/DOMHelper.h \
demux/dash/xml/DOMParser.cpp \
demux/dash/xml/DOMParser.h \
demux/dash/xml/Node.cpp \
demux/dash/xml/Node.h \
demux/dash/dash.cpp \
demux/dash/dash.hpp \
demux/dash/DASHManager.cpp \
demux/dash/DASHManager.h
libdash_plugin_la_SOURCES += $(adaptative_SOURCES)
libdash_plugin_la_SOURCES += demux/mp4/libmp4.c demux/mp4/libmp4.h
libdash_plugin_la_CXXFLAGS = $(AM_CFLAGS) -I$(srcdir)/demux/dash
libdash_plugin_la_LIBADD = $(SOCKET_LIBS) $(LIBM)
if HAVE_ZLIB
......@@ -354,6 +354,36 @@ libdash_plugin_la_LIBADD += -lz
endif
demux_LTLIBRARIES += libdash_plugin.la
libhls_plugin_la_SOURCES = \
demux/hls/playlist/M3U8.hpp \
demux/hls/playlist/M3U8.cpp \
demux/hls/playlist/Parser.hpp \
demux/hls/playlist/Parser.cpp \
demux/hls/playlist/Representation.hpp \
demux/hls/playlist/Representation.cpp \
demux/hls/playlist/HLSSegment.hpp \
demux/hls/playlist/HLSSegment.cpp \
demux/hls/playlist/Tags.hpp \
demux/hls/playlist/Tags.cpp \
demux/hls/HLSManager.hpp \
demux/hls/HLSManager.cpp \
demux/hls/hls.cpp \
demux/hls/hls.hpp
libhls_plugin_la_SOURCES += $(adaptative_SOURCES)
libhls_plugin_la_CXXFLAGS = $(AM_CFLAGS) -I$(srcdir)/demux/hls
libhls_plugin_la_LIBADD = $(SOCKET_LIBS) $(LIBM)
if HAVE_ZLIB
libhls_plugin_la_LIBADD += -lz
endif
if HAVE_GCRYPT
libhls_plugin_la_CXXFLAGS += $(GCRYPT_CFLAGS)
libhls_plugin_la_LIBADD += $(GCRYPT_LIBS)
endif
demux_LTLIBRARIES += libhls_plugin.la
libttml_plugin_la_SOURCES = demux/ttml.c
demux_LTLIBRARIES += libttml_plugin.la
/*****************************************************************************
* HLSManager.cpp
*****************************************************************************
* Copyright © 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 "HLSManager.hpp"
#include "../adaptative/logic/RateBasedAdaptationLogic.h"
#include "../adaptative/tools/Retrieve.hpp"
#include "playlist/Parser.hpp"
#include <vlc_stream.h>
using namespace adaptative;
using namespace adaptative::logic;
using namespace hls;
using namespace hls::playlist;
HLSManager::HLSManager(M3U8 *playlist,
AbstractAdaptationLogic::LogicType type, stream_t *stream) :
PlaylistManager(playlist, type, stream)
{
}
HLSManager::~HLSManager()
{
}
AbstractAdaptationLogic *HLSManager::createLogic(AbstractAdaptationLogic::LogicType type)
{
size_t bps = var_InheritInteger(stream, "hls-prefbw") * 8192;
switch(type)
{
case AbstractAdaptationLogic::FixedRate:
{
size_t bps = var_InheritInteger(stream, "hls-prefbw") * 8192;
return new (std::nothrow) FixedRateAdaptationLogic(bps);
}
case AbstractAdaptationLogic::Default:
case AbstractAdaptationLogic::RateBased:
{
int width = var_InheritInteger(stream, "hls-prefwidth");
int height = var_InheritInteger(stream, "hls-prefheight");
return new (std::nothrow) RateBasedAdaptationLogic(width, height);
}
default:
return PlaylistManager::createLogic(type);
}
}
bool HLSManager::updatePlaylist()
{
if(!playlist->isLive() || !playlist->minUpdatePeriod.Get())
return true;
mtime_t now = time(NULL);
if(nextPlaylistupdate && now < nextPlaylistupdate)
return true;
M3U8 *updatedplaylist = NULL;
/* do update */
if(nextPlaylistupdate)
{
std::string url(stream->psz_access);
url.append("://");
url.append(stream->psz_path);
uint8_t *p_data = NULL;
size_t i_data = Retrieve::HTTP(VLC_OBJECT(stream), url, (void**) &p_data);
if(!p_data)
return false;
stream_t *updatestream = stream_MemoryNew(stream, p_data, i_data, false);
if(!updatestream)
{
free(p_data);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get();
return false;
}
Parser parser(updatestream);
updatedplaylist = parser.parse(url);
if(!updatedplaylist)
{
stream_Delete(updatestream);
nextPlaylistupdate = now + playlist->minUpdatePeriod.Get();
return false;
}
stream_Delete(updatestream);
}
/* Compute new MPD update time */
mtime_t mininterval = 0;
mtime_t maxinterval = 0;
if(updatedplaylist)
{
updatedplaylist->getPlaylistDurationsRange(&mininterval, &maxinterval);
playlist->mergeWith(updatedplaylist);
playlist->debug();
delete updatedplaylist;
/* pruning */
for(int type=0; type<StreamTypeCount; type++)
{
if(!streams[type])
continue;
streams[type]->prune();
}
}
else
{
playlist->getPlaylistDurationsRange(&mininterval, &maxinterval);
}
if(playlist->minUpdatePeriod.Get() * CLOCK_FREQ > mininterval)
mininterval = playlist->minUpdatePeriod.Get() * CLOCK_FREQ;
if(maxinterval < mininterval)
maxinterval = mininterval;
nextPlaylistupdate = now + (mininterval + maxinterval) / (2 * CLOCK_FREQ);
msg_Dbg(stream, "Updated playlist, next update in %" PRId64 "s %ld %ld", nextPlaylistupdate - now, mininterval, maxinterval );
return true;
}
/*
* HLSManager.hpp
*****************************************************************************
* Copyright © 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 HLSMANAGER_HPP
#define HLSMANAGER_HPP
#include "../adaptative/PlaylistManager.h"
#include "../adaptative/logic/AbstractAdaptationLogic.h"
#include "playlist/M3U8.hpp"
namespace hls
{
using namespace adaptative;
class HLSManager : public PlaylistManager
{
public:
HLSManager( playlist::M3U8 *,
logic::AbstractAdaptationLogic::LogicType type,
stream_t *stream );
virtual ~HLSManager();
virtual AbstractAdaptationLogic *createLogic(AbstractAdaptationLogic::LogicType);
virtual bool updatePlaylist();
};
}
#endif // HLSMANAGER_HPP
This diff is collapsed.
/*****************************************************************************
* hls.hpp: HTTP Live Streaming module
*****************************************************************************
* Copyright © 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 HLS_HPP
#define HLS_HPP
struct demux_sys_t
{
adaptative::PlaylistManager *p_manager;
hls::playlist::M3U8 *p_playlist;
mtime_t i_nzpcr;
};
#endif // HLS_HPP
/*
* HLSSegment.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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "HLSSegment.hpp"
#include <vlc_common.h>
#include <vlc_block.h>
#ifdef HAVE_GCRYPT
#include <vlc_gcrypt.h>
#endif
using namespace hls::playlist;
SegmentEncryption::SegmentEncryption()
{
method = SegmentEncryption::NONE;
}
HLSSegment::HLSSegment( ICanonicalUrl *parent, uint64_t seq ) :
Segment( parent )
{
sequence = seq;
#ifdef HAVE_GCRYPT
ctx = NULL;
#endif
}
HLSSegment::~HLSSegment()
{
#ifdef HAVE_GCRYPT
if(ctx)
gcry_cipher_close(ctx);
#endif
}
void HLSSegment::onChunkDownload(block_t **pp_block, Chunk *chunk, BaseRepresentation *)
{
block_t *p_block = *pp_block;
#ifdef HAVE_GCRYPT
if(encryption.method == SegmentEncryption::AES_128)
{
block_t *p_block = *pp_block;
/* first bytes */
if(!ctx && chunk->getBytesRead() == p_block->i_buffer)
{
vlc_gcrypt_init();
if (encryption.iv.size() != 16)
{
encryption.iv.clear();
encryption.iv.resize(16);
encryption.iv[15] = sequence & 0xff;
encryption.iv[14] = (sequence >> 8)& 0xff;
encryption.iv[13] = (sequence >> 16)& 0xff;
encryption.iv[12] = (sequence >> 24)& 0xff;
}
if( gcry_cipher_open(&ctx, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0) ||
gcry_cipher_setkey(ctx, &encryption.key[0], 16) ||
gcry_cipher_setiv(ctx, &encryption.iv[0], 16) )
{
gcry_cipher_close(ctx);
ctx = NULL;
}
}
if(ctx)
{
if ((p_block->i_buffer % 16) != 0 || p_block->i_buffer < 16 ||
gcry_cipher_decrypt(ctx, p_block->p_buffer, p_block->i_buffer, NULL, 0))
{
p_block->i_buffer = 0;
gcry_cipher_close(ctx);
ctx = NULL;
}
else
{
/* last bytes */
if(chunk->getBytesToRead() == 0)
{
/* remove the PKCS#7 padding from the buffer */
const uint8_t pad = p_block->p_buffer[p_block->i_buffer - 1];
for(uint8_t i=0; i<pad && i<=16; i++)
{
if(p_block->p_buffer[p_block->i_buffer - i - 1] != pad)
break;
if(i==pad)
p_block->i_buffer -= pad;
}
gcry_cipher_close(ctx);
ctx = NULL;
}
}
}
}
else
#endif
if(encryption.method != SegmentEncryption::NONE)
{
p_block->i_buffer = 0;
}
}
void HLSSegment::setEncryption(SegmentEncryption &enc)
{
encryption = enc;
}
void HLSSegment::debug(vlc_object_t *obj, int indent) const
{
std::stringstream ss;
ss << std::string(indent, ' ') << debugName <<
" #" << sequence <<
" url=" << getUrlSegment().toString();
if(startByte!=endByte)
ss << " @" << startByte << ".." << endByte;
msg_Dbg(obj, "%s", ss.str().c_str());
}
int HLSSegment::compare(ISegment *segment) const
{
HLSSegment *hlssegment = dynamic_cast<HLSSegment *>(segment);
if(hlssegment)
{
if (sequence > hlssegment->sequence)
return 1;
else if(sequence < hlssegment->sequence)
return -1;
else
return 0;
}
else return ISegment::compare(segment);
}
/*
* HLSSegment.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 HLSSEGMENT_HPP
#define HLSSEGMENT_HPP
#include "../adaptative/playlist/Segment.h"
#include <vector>
#include <gcrypt.h>
namespace hls
{
namespace playlist
{
using namespace adaptative::playlist;
class SegmentEncryption
{
public:
SegmentEncryption();
enum
{
NONE,
AES_128,
AES_SAMPLE,
} method;
std::vector<uint8_t> key;
std::vector<uint8_t> iv;
};
class HLSSegment : public Segment
{
public:
HLSSegment( ICanonicalUrl *parent, uint64_t sequence );
virtual ~HLSSegment();
void setEncryption(SegmentEncryption &);
void debug(vlc_object_t *, int) const; /* reimpl */
virtual int compare(ISegment *) const; /* reimpl */
protected:
virtual void onChunkDownload(block_t **, Chunk *, BaseRepresentation *); /* reimpl */
uint64_t sequence;
SegmentEncryption encryption;
#ifdef HAVE_GCRYPT
gcry_cipher_hd_t ctx;
#endif
};
}
}
#endif // HLSSEGMENT_HPP
/*
* M3U8.cpp
*****************************************************************************
* Copyright © 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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "M3U8.hpp"
#include "Representation.hpp"
#include "../adaptative/playlist/BasePeriod.h"
#include "../adaptative/playlist/BaseAdaptationSet.h"
#include <vlc_common.h>
#include <vlc_stream.h>
using namespace hls::playlist;
M3U8::M3U8 (stream_t *stream_) :
AbstractPlaylist(stream_)
{
minUpdatePeriod.Set( 5 );
}
M3U8::~M3U8()
{
}
bool M3U8::isLive() const
{
std::vector<BasePeriod *>::const_iterator itp;
for(itp = periods.begin(); itp != periods.end(); ++itp)
{
const BasePeriod *period = *itp;
std::vector<BaseAdaptationSet *>::const_iterator ita;
for(ita = period->getAdaptationSets().begin(); ita != period->getAdaptationSets().end(); ++ita)
{
BaseAdaptationSet *adaptSet = *ita;
std::vector<BaseRepresentation *>::iterator itr;
for(itr = adaptSet->getRepresentations().begin(); itr != adaptSet->getRepresentations().end(); ++itr)
{
const Representation *rep = dynamic_cast<const Representation *>(*itr);
if(rep->isLive())
return true;
}
}
}
return false;
}
void M3U8::debug()
{
std::vector<BasePeriod *>::const_iterator i;
for(i = periods.begin(); i != periods.end(); ++i)
(*i)->debug(VLC_OBJECT(stream));
}
/*
* M3U8.hpp
*****************************************************************************
* Copyright © 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 M3U8_H_
#define M3U8_H_
#include "../adaptative/playlist/AbstractPlaylist.hpp"
namespace hls
{
namespace playlist
{
using namespace adaptative::playlist;
class M3U8 : public AbstractPlaylist
{
public:
M3U8(stream_t *);
virtual ~M3U8();
virtual bool isLive() const;
virtual void debug();
private:
std::string data;
};
}
}
#endif /* M3U8_H_ */
This diff is collapsed.
/*
* Parser.hpp
*****************************************************************************
* Copyright © 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 PARSER_HPP
#define PARSER_HPP
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "../adaptative/playlist/SegmentInfoCommon.h"
#include <cstdlib>
#include <sstream>
#include <vlc_common.h>
namespace adaptative
{
namespace playlist
{
class SegmentInformation;
class MediaSegmentTemplate;
class BasePeriod;
class BaseAdaptationSet;
}
}
namespace hls
{
namespace playlist
{
using namespace adaptative::playlist;
class M3U8;
class AttributesTag;
class Tag;
class Representation;
class Parser
{
public:
Parser (stream_t *p_stream);
virtual ~Parser ();
M3U8 * parse (const std::string &);
private:
void parseAdaptationSet(BasePeriod *, const AttributesTag *);
void parseRepresentation(BaseAdaptationSet *, const AttributesTag *);
void parseRepresentation(BaseAdaptationSet *, const AttributesTag *,
const std::list<Tag *>&);
void parseSegments(Representation *, const std::list<Tag *>&);
std::list<Tag *> parseEntries(stream_t *);
stream_t *p_stream;
};
}
}
#endif // PARSER_HPP
/*
* Representation.cpp
*****************************************************************************
* Copyright © 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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cstdlib>
#include "Representation.hpp"
#include "M3U8.hpp"
#include "../adaptative/playlist/BasePeriod.h"
#include "../adaptative/playlist/BaseAdaptationSet.h"
#include "../adaptative/playlist/SegmentList.h"
using namespace hls::playlist;
Representation::Representation ( BaseAdaptationSet *set ) :
BaseRepresentation( set )
{
b_live = true;
}
Representation::~Representation ()
{
}
bool Representation::isLive() const
{
return b_live;
}
void Representation::localMergeWithPlaylist(M3U8 *updated, mtime_t prunebarrier)
{
BasePeriod *period = updated->getFirstPeriod();
if(!period)
return;
BaseAdaptationSet *adapt = period->getAdaptationSets().front();
if(!adapt)
return;
BaseRepresentation *rep = adapt->getRepresentations().front();
if(!rep)
return;
this->mergeWith( rep, prunebarrier );
}
void Representation::mergeWith(SegmentInformation *seginfo, mtime_t prunebarrier)
{
BaseRepresentation::mergeWith(seginfo, prunebarrier);
}
/*
* Representation.hpp
*****************************************************************************
* Copyright © 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 HLSREPRESENTATION_H_
#define HLSREPRESENTATION_H_
#include "../adaptative/playlist/BaseRepresentation.h"
#include "../adaptative/tools/Properties.hpp"
namespace hls
{
namespace playlist
{
class M3U8;
using namespace adaptative::playlist;
class Representation : public BaseRepresentation
{
friend class Parser;
public:
Representation( BaseAdaptationSet * );
virtual ~Representation ();
void localMergeWithPlaylist(M3U8 *, mtime_t);
bool isLive() const;
virtual void mergeWith(SegmentInformation *, mtime_t); /* reimpl */
private:
bool b_live;
Property<std::string> playlistUrl;
Property<std::string> audio;
Property<std::string> video;
Property<std::string> subtitles;
Property<std::string> closedcaptions;
};
}
}
#endif /* HLSREPRESENTATION_H_ */
/*
* Tags.cpp
*****************************************************************************
* Copyright © 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 "Tags.hpp"
#include <sstream>
#include <stack>
#define __STDC_CONSTANT_MACROS
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
using namespace hls::playlist;
Attribute::Attribute(const std::string &name_, const std::string &value_)
{
name = name_;
value = value_;
}
uint64_t Attribute::decimal() const
{
std::istringstream is(value);
uint64_t ret;
is >> ret;
return ret;
}
double Attribute::floatingPoint() const
{
std::istringstream is(value);
is.imbue(std::locale(""));
double ret;
is >> ret;
return ret;
}
std::vector<uint8_t> Attribute::hexSequence() const
{
std::vector<uint8_t> ret;
if(value.length() > 2 && (value.substr(0, 2) == "0X" || value.substr(0, 2) == "0x") )
{
for(size_t i=2; i<=(value.length() - 2); i+=2)
{
unsigned val;
std::stringstream ss(value.substr(i, 2));
ss >> std::hex >> val;
ret.push_back(val);
}
}
return ret;
}
std::pair<std::size_t,std::size_t> Attribute::getByteRange() const
{
std::pair<std::size_t,std::size_t> ret;
std::size_t length = 0;
std::size_t offset = 0;
std::istringstream is(value);
if(!is.eof())
{
is >> length;
if(!is.eof())
{
char c = is.get();
if(c == '@' && !is.eof())
is >> offset;
}
}
ret = std::make_pair(offset, length);
return ret;
}
std::string Attribute::quotedString() const
{
if(value.length() < 2)
return "";
std::istringstream is(value.substr(1, value.length() - 2));
std::ostringstream os;
char c;
while(is.get(c))
{
if(c == '\\')
{
if(!is.get(c))
break;
}
os << c;
}
return os.str();
}
Tag::Tag(int type_)
{
type = type_;
}
Tag::~Tag()
{
}
int Tag::getType() const
{
return type;
}
SingleValueTag::SingleValueTag(int type, const std::string &v)
: Tag(type), attr("", v)
{
}
SingleValueTag::~SingleValueTag()
{
}
const Attribute &SingleValueTag::getValue() const
{
return attr;
}
AttributesTag::AttributesTag(int type, const std::string &v) : Tag(type)
{
parseAttributes(v);
}
AttributesTag::~AttributesTag()
{
std::list<Attribute *>::const_iterator it;
for(it = attributes.begin(); it != attributes.end(); ++it)
delete *it;
}
const Attribute * AttributesTag::getAttributeByName(const char *name) const
{
std::list<Attribute *>::const_iterator it;
for(it = attributes.begin(); it != attributes.end(); ++it)
if((*it)->name == name)
return *it;
return NULL;
}
void AttributesTag::addAttribute(Attribute *attr)
{
attributes.push_back(attr);
}
void AttributesTag::parseAttributes(const std::string &field)
{
std::istringstream iss(field);
std::ostringstream oss;
while(!iss.eof())
{
/* parse attribute name */
while(!iss.eof())
{
char c = iss.peek();
if((c >= 'A' && c <= 'Z') || c == '-')
{
oss.put((char)iss.get());
}
else if(c == '=')
{
iss.get();
break;
}
else /* out of range */
return;
}
std::string attrname = oss.str();
oss.str("");
/* parse attributes value */
bool b_quoted = false;
while(!iss.eof())
{
char c = iss.peek();
if(c == '\\' && b_quoted)
{
iss.get();
}
else if(c == ',' && !b_quoted)
{
iss.get();
break;
}
else if(c == '"')
{
b_quoted = !b_quoted;
}
if(!iss.eof())
oss.put((char)iss.get());
}
std::string attrvalue = oss.str();
oss.str("");
Attribute *attribute = new (std::nothrow) Attribute(attrname, attrvalue);
if(attribute)
attributes.push_back(attribute);
}
}
URITag::URITag(const std::string &v) : AttributesTag(URITag::EXTINF, v)
{
parseAttributes(v);
}
URITag::~URITag()
{
}
void URITag::parseAttributes(const std::string &field)
{
std::size_t pos = field.find(',');
if(pos != std::string::npos)
{
Attribute *attr = new (std::nothrow) Attribute("DURATION", field.substr(0, pos));
if(attr)
addAttribute(attr);
attr = new (std::nothrow) Attribute("TITLE", field.substr(pos));
if(attr)
addAttribute(attr);
}
}
Tag * TagFactory::createTagByName(const std::string &name, const std::string &value)
{
struct
{
const char *psz;
const int i;
} const exttagmapping[] = {
{"EXT-X-BYTERANGE", SingleValueTag::EXTXBYTERANGE},
{"EXT-X-DISCONTINUITY", Tag::EXTXDISCONTINUITY},
{"EXT-X-KEY", AttributesTag::EXTXKEY},
{"EXT-X-MAP", AttributesTag::EXTXMAP},
{"EXT-X-PROGRAM-DATE-TIME", SingleValueTag::EXTXPROGRAMDATETIME},
{"EXT-X-TARGETDURATION", SingleValueTag::EXTXTARGETDURATION},
{"EXT-X-MEDIA-SEQUENCE", SingleValueTag::EXTXMEDIASEQUENCE},
{"EXT-X-DISCONTINUITY-SEQUENCE", SingleValueTag::EXTXDISCONTINUITYSEQUENCE},
{"EXT-X-ENDLIST", Tag::EXTXENDLIST},
{"EXT-X-PLAYLIST-TYPE", SingleValueTag::EXTXPLAYLISTTYPE},
{"EXT-X-I-FRAMES-ONLY", Tag::EXTXIFRAMESONLY},
{"EXT-X-MEDIA", AttributesTag::EXTXMEDIA},
{"EXT-X-STREAM-INF", AttributesTag::EXTXSTREAMINF},
{"EXTINF", URITag::EXTINF},
{NULL, 0},
};
for(int i=0; exttagmapping[i].psz; i++)
{
if(name != exttagmapping[i].psz)
continue;
switch(exttagmapping[i].i)
{
case Tag::EXTXDISCONTINUITY:
case Tag::EXTXENDLIST:
case Tag::EXTXIFRAMESONLY:
return new (std::nothrow) Tag(exttagmapping[i].i);
case SingleValueTag::EXTXVERSION:
case SingleValueTag::EXTXBYTERANGE:
case SingleValueTag::EXTXPROGRAMDATETIME:
case SingleValueTag::EXTXTARGETDURATION:
case SingleValueTag::EXTXMEDIASEQUENCE:
case SingleValueTag::EXTXDISCONTINUITYSEQUENCE:
case SingleValueTag::EXTXPLAYLISTTYPE:
return new (std::nothrow) SingleValueTag(exttagmapping[i].i, value);
case AttributesTag::EXTXKEY:
case AttributesTag::EXTXMAP:
case AttributesTag::EXTXMEDIA:
case AttributesTag::EXTXSTREAMINF:
return new (std::nothrow) AttributesTag(exttagmapping[i].i, value);
case URITag::EXTINF:
return new URITag(value);
}
}
return NULL;
}
/*
* Tags.hpp
*****************************************************************************
* Copyright © 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 TAGS_HPP
#define TAGS_HPP
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdint.h>
#include <string>
#include <vector>
#include <list>
#include <utility>
namespace hls
{
namespace playlist
{
class Attribute
{
public:
Attribute(const std::string &, const std::string &);
uint64_t decimal() const;
std::string quotedString() const;
double floatingPoint() const;
std::vector<uint8_t> hexSequence() const;
std::pair<std::size_t,std::size_t> getByteRange() const;
std::string name;
std::string value;
};
class Tag
{
public:
enum
{
EXTXDISCONTINUITY = 0,
EXTXENDLIST,
EXTXIFRAMESONLY,
};
Tag(int);
virtual ~Tag();
int getType() const;
private:
int type;
};
class SingleValueTag : public Tag
{
public:
enum
{
EXTXVERSION = 10,
EXTXBYTERANGE,
EXTXPROGRAMDATETIME,
EXTXTARGETDURATION,
EXTXMEDIASEQUENCE,
EXTXDISCONTINUITYSEQUENCE,
EXTXPLAYLISTTYPE,
};
SingleValueTag(int, const std::string &);
virtual ~SingleValueTag();
const Attribute & getValue() const;
private:
Attribute attr;
};
class AttributesTag : public Tag
{
public:
enum
{
EXTXKEY = 20,
EXTXMAP,
EXTXMEDIA,
EXTXSTREAMINF,
};
AttributesTag(int, const std::string &);
virtual ~AttributesTag();
const Attribute * getAttributeByName(const char *) const;
void addAttribute(Attribute *);
protected:
virtual void parseAttributes(const std::string &);
std::list<Attribute *> attributes;
};
class URITag : public AttributesTag
{
public:
enum
{
EXTINF = 30
};
URITag(const std::string &);
virtual ~URITag();
protected:
virtual void parseAttributes(const std::string &);
};
class TagFactory
{
public:
static Tag * createTagByName(const std::string &, const std::string &);
static Attribute * createAttributeByName(const std::string &);
};
}
}
#endif // TAGS_HPP
......@@ -465,6 +465,7 @@ modules/demux/demuxdump.c
modules/demux/dirac.c
modules/demux/flac.c
modules/demux/gme.c
modules/demux/hls/hls.cpp
modules/demux/image.c
modules/demux/mjpeg.c
modules/demux/mkv/chapter_command.cpp
......
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