vlc/vlc-3.0 | branch: master | Francois Cartegnie <[email protected]> | Tue Apr 23 14:34:37 2019 +0200| [72ab7359fdf4fa533ea6a2bea3c2232538b01aa1] | committer: Francois Cartegnie
demux: hls: probe content Solves issues when the server does not sends proper MIME and the file does not match known extension. (cherry picked from commit dfe4aca1f22265115e07c501a77c870cfea4cd52) > http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=72ab7359fdf4fa533ea6a2bea3c2232538b01aa1 --- modules/demux/adaptive/SegmentTracker.cpp | 6 +++--- modules/demux/adaptive/StreamFormat.cpp | 24 +++++++++++++++++++++- modules/demux/adaptive/StreamFormat.hpp | 2 ++ modules/demux/adaptive/Streams.cpp | 2 +- modules/demux/adaptive/plumbing/Demuxer.cpp | 15 ++++++++++++-- modules/demux/hls/HLSStreams.cpp | 4 ++-- modules/demux/hls/playlist/Parser.cpp | 32 ----------------------------- modules/demux/hls/playlist/Parser.hpp | 1 - 8 files changed, 44 insertions(+), 42 deletions(-) diff --git a/modules/demux/adaptive/SegmentTracker.cpp b/modules/demux/adaptive/SegmentTracker.cpp index ce5db8874f..23835117cb 100644 --- a/modules/demux/adaptive/SegmentTracker.cpp +++ b/modules/demux/adaptive/SegmentTracker.cpp @@ -86,7 +86,7 @@ SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSe curRepresentation = NULL; setAdaptationLogic(logic_); adaptationSet = adaptSet; - format = StreamFormat::UNSUPPORTED; + format = StreamFormat::UNKNOWN; } SegmentTracker::~SegmentTracker() @@ -132,7 +132,7 @@ void SegmentTracker::reset() init_sent = false; index_sent = false; initializing = true; - format = StreamFormat::UNSUPPORTED; + format = StreamFormat::UNKNOWN; } SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, @@ -199,7 +199,7 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, if(rep->getStreamFormat() != format) { /* Initial format ? */ - if(format == StreamFormat(StreamFormat::UNSUPPORTED)) + if(format == StreamFormat(StreamFormat::UNKNOWN)) { format = rep->getStreamFormat(); } diff --git a/modules/demux/adaptive/StreamFormat.cpp b/modules/demux/adaptive/StreamFormat.cpp index 11cee69dac..d31cc1800c 100644 --- a/modules/demux/adaptive/StreamFormat.cpp +++ b/modules/demux/adaptive/StreamFormat.cpp @@ -23,6 +23,8 @@ #endif #include "StreamFormat.hpp" + +#include <vlc_common.h> #include <algorithm> using namespace adaptive; @@ -64,7 +66,7 @@ StreamFormat::StreamFormat( const std::string &mimetype ) std::string mime = mimetype; std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); std::string::size_type pos = mime.find("/"); - formatid = UNSUPPORTED; + formatid = UNKNOWN; if(pos != std::string::npos) { std::string tail = mime.substr(pos + 1); @@ -79,6 +81,26 @@ StreamFormat::StreamFormat( const std::string &mimetype ) } } +StreamFormat::StreamFormat(const void *data_, size_t sz) +{ + const uint8_t *data = reinterpret_cast<const uint8_t *>(data_); + formatid = UNKNOWN; + const char moov[] = "ftypmoovmoof"; + + if(sz > 188 && data[0] == 0x47 && data[188] == 0x47) + formatid = StreamFormat::MPEG2TS; + else if(sz > 8 && (!memcmp(&moov, &data[4], 4) || + !memcmp(&moov[4], &data[4], 4) || + !memcmp(&moov[8], &data[4], 4))) + formatid = StreamFormat::MP4; + else if(sz > 7 && !memcmp("WEBVTT", data, 6) && + std::isspace(static_cast<unsigned char>(data[7]))) + formatid = StreamFormat::WEBVTT; + else if(sz > 3 && (!memcmp("\xFF\xF1", data, 2)|| + !memcmp("\xFF\xF9", data, 2))) + formatid = StreamFormat::PACKEDAAC; +} + StreamFormat::~StreamFormat() { diff --git a/modules/demux/adaptive/StreamFormat.hpp b/modules/demux/adaptive/StreamFormat.hpp index 7b3d49e1b4..738e04574b 100644 --- a/modules/demux/adaptive/StreamFormat.hpp +++ b/modules/demux/adaptive/StreamFormat.hpp @@ -35,9 +35,11 @@ namespace adaptive static const unsigned TTML = 4; static const unsigned PACKEDAAC = 5; static const unsigned UNKNOWN = 0xFF; /* will probe */ + static const unsigned PEEK_SIZE = 189; StreamFormat( unsigned = UNSUPPORTED ); explicit StreamFormat( const std::string &mime ); + StreamFormat( const void *, size_t ); ~StreamFormat(); operator unsigned() const; std::string str() const; diff --git a/modules/demux/adaptive/Streams.cpp b/modules/demux/adaptive/Streams.cpp index 4bded1ba70..fe36b8df6f 100644 --- a/modules/demux/adaptive/Streams.cpp +++ b/modules/demux/adaptive/Streams.cpp @@ -41,7 +41,7 @@ using namespace adaptive::http; AbstractStream::AbstractStream(demux_t * demux_) { p_realdemux = demux_; - format = StreamFormat::UNSUPPORTED; + format = StreamFormat::UNKNOWN; currentChunk = NULL; eof = false; dead = false; diff --git a/modules/demux/adaptive/plumbing/Demuxer.cpp b/modules/demux/adaptive/plumbing/Demuxer.cpp index caf78c5667..6c6ca8cd2f 100644 --- a/modules/demux/adaptive/plumbing/Demuxer.cpp +++ b/modules/demux/adaptive/plumbing/Demuxer.cpp @@ -100,13 +100,24 @@ bool MimeDemuxer::create() if(!p_newstream) return false; + StreamFormat format(StreamFormat::UNKNOWN); char *type = stream_ContentType(p_newstream); if(type) { - demuxer = factory->newDemux( p_realdemux, StreamFormat(std::string(type)), - p_es_out, sourcestream ); + format = StreamFormat(std::string(type)); free(type); } + /* Try to probe */ + if(format == StreamFormat(StreamFormat::UNKNOWN)) + { + const uint8_t *p_peek; + size_t i_peek = sourcestream->Peek(&p_peek, StreamFormat::PEEK_SIZE); + format = StreamFormat(reinterpret_cast<const void *>(p_peek), i_peek); + } + + if(format != StreamFormat(StreamFormat::UNKNOWN)) + demuxer = factory->newDemux(p_realdemux, format, p_es_out, sourcestream); + vlc_stream_Delete(p_newstream); if(!demuxer || !demuxer->create()) diff --git a/modules/demux/hls/HLSStreams.cpp b/modules/demux/hls/HLSStreams.cpp index 30cb2640bf..b4434d7a4c 100644 --- a/modules/demux/hls/HLSStreams.cpp +++ b/modules/demux/hls/HLSStreams.cpp @@ -161,11 +161,11 @@ AbstractDemuxer *HLSStream::newDemux(demux_t *p_realdemux, const StreamFormat &f return ret; } -AbstractStream * HLSStreamFactory::create(demux_t *realdemux, const StreamFormat &, +AbstractStream * HLSStreamFactory::create(demux_t *realdemux, const StreamFormat &format, SegmentTracker *tracker, AbstractConnectionManager *manager) const { HLSStream *stream = new (std::nothrow) HLSStream(realdemux); - if(stream && !stream->init(StreamFormat(StreamFormat::UNKNOWN), tracker, manager)) + if(stream && !stream->init(format, tracker, manager)) { delete stream; return NULL; diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp index d5b65cd15e..54e18d8819 100644 --- a/modules/demux/hls/playlist/Parser.cpp +++ b/modules/demux/hls/playlist/Parser.cpp @@ -74,36 +74,6 @@ static void releaseTagsList(std::list<Tag *> &list) list.clear(); } -void M3U8Parser::setFormatFromExtension(Representation *rep, const std::string &filename) -{ - std::size_t pos = filename.find_last_of('.'); - if(pos != std::string::npos) - { - std::string extension = Helper::getFileExtension(filename); - transform(extension.begin(), extension.end(), extension.begin(), (int (*)(int))std::tolower); - if(extension == "aac") - { - rep->streamFormat = StreamFormat(StreamFormat::PACKEDAAC); - } - else if(extension == "ts" || extension == "mp2t" || extension == "mpeg" || extension == "m2ts") - { - rep->streamFormat = StreamFormat(StreamFormat::MPEG2TS); - } - else if(extension == "mp4" || extension == "m4s" || extension == "mov" || extension == "m4v") - { - rep->streamFormat = StreamFormat(StreamFormat::MP4); - } - else if(extension == "vtt" || extension == "wvtt" || extension == "webvtt") - { - rep->streamFormat = StreamFormat(StreamFormat::WEBVTT); - } - else - { - rep->streamFormat = StreamFormat(StreamFormat::UNSUPPORTED); - } - } -} - Representation * M3U8Parser::createRepresentation(BaseAdaptationSet *adaptSet, const AttributesTag * tag) { const Attribute *uriAttr = tag->getAttributeByName("URI"); @@ -241,8 +211,6 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l break; segment->setSourceUrl(uritag->getValue().value); - if((unsigned)rep->getStreamFormat() == StreamFormat::UNKNOWN) - setFormatFromExtension(rep, uritag->getValue().value); /* Need to use EXTXTARGETDURATION as default as some can't properly set segment one */ double duration = rep->targetDuration; diff --git a/modules/demux/hls/playlist/Parser.hpp b/modules/demux/hls/playlist/Parser.hpp index e46ae15b30..dc2c148e78 100644 --- a/modules/demux/hls/playlist/Parser.hpp +++ b/modules/demux/hls/playlist/Parser.hpp @@ -68,7 +68,6 @@ namespace hls void createAndFillRepresentation(vlc_object_t *, BaseAdaptationSet *, const AttributesTag *, const std::list<Tag *>&); void parseSegments(vlc_object_t *, Representation *, const std::list<Tag *>&); - void setFormatFromExtension(Representation *rep, const std::string &); std::list<Tag *> parseEntries(stream_t *); AuthStorage *auth; }; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
