[vlc-commits] demux: hls: probe content

Francois Cartegnie git at videolan.org
Tue Jul 23 20:36:18 CEST 2019


vlc/vlc-3.0 | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | 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;
         };



More information about the vlc-commits mailing list