[vlc-commits] [Git][videolan/vlc][master] 4 commits: demux: adaptive: add std::optional compatibility

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Jun 21 12:34:00 UTC 2025



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
3870be59 by François Cartegnie at 2025-06-21T12:20:45+00:00
demux: adaptive: add std::optional compatibility

- - - - -
af4c229f by François Cartegnie at 2025-06-21T12:20:45+00:00
demux: adaptive: replace Unset with optional

- - - - -
e367a322 by François Cartegnie at 2025-06-21T12:20:45+00:00
demux: hls: fix byterange attribute comment

- - - - -
c52d819d by François Cartegnie at 2025-06-21T12:20:45+00:00
demux: hls: fix byterange offset propagation

refs #29179

- - - - -


12 changed files:

- modules/demux/Makefile.am
- modules/demux/adaptive/logic/BufferingLogic.cpp
- modules/demux/adaptive/logic/BufferingLogic.hpp
- modules/demux/adaptive/playlist/BaseAdaptationSet.cpp
- modules/demux/adaptive/playlist/BaseAdaptationSet.h
- modules/demux/adaptive/playlist/CommonAttributesElements.h
- modules/demux/adaptive/test/playlist/M3U8.cpp
- + modules/demux/adaptive/tools/Compatibility.hpp
- modules/demux/adaptive/tools/Properties.hpp
- modules/demux/hls/playlist/Parser.cpp
- modules/demux/hls/playlist/Tags.cpp
- modules/demux/hls/playlist/Tags.hpp


Changes:

=====================================
modules/demux/Makefile.am
=====================================
@@ -406,6 +406,7 @@ libvlc_adaptive_la_SOURCES = \
     demux/adaptive/Streams.cpp \
     demux/adaptive/Streams.hpp \
     demux/adaptive/Time.hpp \
+    demux/adaptive/tools/Compatibility.hpp \
     demux/adaptive/tools/Conversions.hpp \
     demux/adaptive/tools/Conversions.cpp \
     demux/adaptive/tools/Debug.hpp \


=====================================
modules/demux/adaptive/logic/BufferingLogic.cpp
=====================================
@@ -387,7 +387,5 @@ vlc_tick_t DefaultBufferingLogic::getBufferingOffset(const BasePlaylist *p) cons
 
 bool DefaultBufferingLogic::isLowLatency(const BasePlaylist *p) const
 {
-    if(userLowLatency.isSet())
-        return userLowLatency.value();
-    return p->isLowLatency();
+    return userLowLatency.value_or(p->isLowLatency());
 }


=====================================
modules/demux/adaptive/logic/BufferingLogic.hpp
=====================================
@@ -23,7 +23,7 @@
 #include <vlc_common.h>
 #include <vlc_tick.h>
 
-#include "../tools/Properties.hpp"
+#include "../tools/Compatibility.hpp"
 
 namespace adaptive
 {
@@ -61,7 +61,7 @@ namespace adaptive
                 vlc_tick_t userMinBuffering;
                 vlc_tick_t userMaxBuffering;
                 vlc_tick_t userLiveDelay;
-                Undef<bool> userLowLatency;
+                optional<bool> userLowLatency;
         };
 
         class DefaultBufferingLogic : public AbstractBufferingLogic


=====================================
modules/demux/adaptive/playlist/BaseAdaptationSet.cpp
=====================================
@@ -112,12 +112,12 @@ void BaseAdaptationSet::setBitswitchAble(bool b)
 
 bool BaseAdaptationSet::isSegmentAligned() const
 {
-    return !segmentAligned.isSet() || segmentAligned.value();
+    return segmentAligned.value_or(true);
 }
 
 bool BaseAdaptationSet::isBitSwitchable() const
 {
-    return bitswitchAble.isSet() && segmentAligned.value();
+    return bitswitchAble.has_value() && isSegmentAligned();
 }
 
 void BaseAdaptationSet::setRole(const Role &r)


=====================================
modules/demux/adaptive/playlist/BaseAdaptationSet.h
=====================================
@@ -68,8 +68,8 @@ namespace adaptive
                 Role                            role;
                 std::vector<BaseRepresentation *>   representations;
                 std::string                     lang;
-                Undef<bool>                     segmentAligned;
-                Undef<bool>                     bitswitchAble;
+                optional<bool>                  segmentAligned;
+                optional<bool>                  bitswitchAble;
         };
     }
 }


=====================================
modules/demux/adaptive/playlist/CommonAttributesElements.h
=====================================
@@ -24,6 +24,7 @@
 #ifndef COMMONATTRIBUTESELEMENTS_H
 #define COMMONATTRIBUTESELEMENTS_H
 
+#include "../tools/Compatibility.hpp"
 #include "../tools/Properties.hpp"
 #include <string>
 


=====================================
modules/demux/adaptive/test/playlist/M3U8.cpp
=====================================
@@ -554,6 +554,8 @@ int M3U8Playlist_test()
         "#EXT-X-BYTERANGE:4000 at 2000\n"
         "foobar.ts\n"
         "#EXT-X-BYTERANGE:500\n"
+        "foobar.ts\n"
+        "#EXT-X-BYTERANGE:1000 at 0\n"
         "foobar.ts\n";
 
     m3u = ParseM3U8(obj, manifest6, sizeof(manifest6));
@@ -571,6 +573,9 @@ int M3U8Playlist_test()
         seg = rep->getMediaSegment(12);
         Expect(seg);
         Expect(seg->getOffset() == 6000);
+        seg = rep->getMediaSegment(13);
+        Expect(seg);
+        Expect(seg->getOffset() == 0);
         delete m3u;
     }
     catch (...)


=====================================
modules/demux/adaptive/tools/Compatibility.hpp
=====================================
@@ -0,0 +1,214 @@
+/*
+ * Compatibility.hpp
+ *****************************************************************************
+ * Copyright (C) 2025 - VideoLabs, VideoLAN and VLC 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 COMPATIBILITY_HPP
+#define COMPATIBILITY_HPP
+
+/* Provide std::optional compatibility for builds with c++17 or
+   incomplete/bogus c++17 with MacOS <= 10.13 and iOS < 12 */
+
+#ifdef __APPLE__
+# include <TargetConditionals.h>
+# if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < 120000) || \
+     (TARGET_OS_MAC && __MAC_OS_X_VERSION_MIN_REQUIRED < 101400)
+#  define IOS_INCOMPLETE_CPP17
+# endif
+#endif
+
+#if __cplusplus >= 201703L && !defined(IOS_INCOMPLETE_CPP17)
+# include <optional>
+#else
+# include <utility>
+# include <type_traits>
+# include <stdexcept>
+#endif
+
+namespace adaptive
+{
+
+#if __cplusplus >= 201703L && !defined(IOS_INCOMPLETE_CPP17)
+
+template <typename T>
+using optional = std::optional<T>;
+using nullopt_t = std::nullopt_t;
+constexpr auto nullopt = std::nullopt;
+using in_place_t = std::in_place_t;
+constexpr auto in_place = std::in_place;
+using bad_optional_access = std::bad_optional_access;
+#else
+
+struct nullopt_t {
+    explicit nullopt_t() = default;
+};
+constexpr nullopt_t nullopt{};
+
+struct in_place_t {
+    explicit in_place_t() = default;
+};
+constexpr in_place_t in_place{};
+
+class bad_optional_access : public std::exception {
+public:
+    const char* what() const noexcept override {
+        return "Bad optional access";
+    }
+};
+
+template <typename T>
+class optional
+{
+private:
+    alignas(T) unsigned char storage[sizeof(T)];
+    bool has_value_ = false;
+
+    T* ptr() noexcept
+    {
+        return reinterpret_cast<T*>(storage);
+    }
+    const T* ptr() const noexcept
+    {
+        return reinterpret_cast<const T*>(storage);
+    }
+
+    void destroy() noexcept(std::is_nothrow_destructible<T>::value)
+    {
+        if (has_value_)
+        {
+            ptr()->~T();
+            has_value_ = false;
+        }
+    }
+
+public:
+    optional() noexcept = default;
+
+    optional(nullopt_t) noexcept : optional() {}
+
+    optional(const T& value) : has_value_(true)
+    {
+        new (storage) T(value);
+    }
+    optional(T&& value) : has_value_(true)
+    {
+        new (storage) T(std::move(value));
+    }
+    optional(optional&& other) noexcept(std::is_nothrow_move_constructible<T>::value)
+        : has_value_(other.has_value_) {
+        if (has_value_) { new (storage) T(std::move(*other.ptr())); other.destroy(); }
+    }
+
+    ~optional() {destroy();}
+
+    optional& operator=(const optional& other)
+    {
+        if (this != &other)
+        {
+            destroy();
+            has_value_ = other.has_value_;
+            if (has_value_)
+                new (storage) T(*other.ptr());
+        }
+        return *this;
+    }
+
+    optional& operator=(optional&& other) noexcept(
+        std::is_nothrow_move_constructible<T>::value &&
+        std::is_nothrow_move_assignable<T>::value)
+    {
+        if (this != &other)
+        {
+            destroy();
+            has_value_ = other.has_value_;
+            if (has_value_)
+            {
+                new (storage) T(std::move(*other.ptr()));
+                other.destroy();
+            }
+        }
+        return *this;
+    }
+
+    optional& operator=(nullopt_t) noexcept
+    {
+        destroy();
+        return *this;
+    }
+
+    optional& operator=(const T& value)
+    {
+        destroy();
+        has_value_ = true;
+        new (storage) T(value);
+        return *this;
+    }
+    optional& operator=(T&& value)
+    {
+        destroy();
+        has_value_ = true;
+        new (storage) T(std::move(value));
+        return *this;
+    }
+
+    template <typename... Args>
+    void emplace(Args&&... args)
+    {
+        destroy();
+        has_value_ = true;
+        new (storage) T(std::forward<Args>(args)...);
+    }
+
+    explicit operator bool() const noexcept { return has_value_; }
+    bool has_value() const noexcept { return has_value_; }
+
+    T& value()
+    {
+        if (!has_value_) throw bad_optional_access{};
+        return *ptr();
+    }
+    const T& value() const
+    {
+        if (!has_value_) throw bad_optional_access{};
+        return *ptr();
+    }
+
+    T* operator->() { return ptr(); }
+    const T* operator->() const { return ptr(); }
+    T& operator*() { return *ptr(); }
+    const T& operator*() const { return *ptr(); }
+
+    template <typename U>
+    T value_or(U&& default_value) const& {
+        return has_value_ ? *ptr() : static_cast<T>(std::forward<U>(default_value));
+    }
+    template <typename U>
+    T value_or(U&& default_value) && {
+        return has_value_ ? std::move(*ptr()) : static_cast<T>(std::forward<U>(default_value));
+    }
+
+    void reset() noexcept
+    {
+        destroy();
+    }
+};
+
+#endif // #if __cplusplus < 201703L
+
+}
+
+#endif // COMPATIBILITY_HPP


=====================================
modules/demux/adaptive/tools/Properties.hpp
=====================================
@@ -39,24 +39,6 @@ template <typename T> class Property
         T value;
 };
 
-template <typename T> class Undef
-{
-    public:
-        Undef() { undef = true; }
-
-        bool isSet() const
-        {
-            return !undef;
-        }
-
-        void operator =(const T &v) { val = v; undef = false; }
-        const T& value() const { return val; }
-
-    private:
-        bool undef;
-        T val;
-};
-
 template <typename T> class Ratio
 {
     public:


=====================================
modules/demux/hls/playlist/Parser.cpp
=====================================
@@ -362,11 +362,11 @@ void M3U8Parser::parseSegments(vlc_object_t *, HLSRepresentation *rep, const std
 
                 if(ctx_byterange)
                 {
-                    std::pair<std::size_t,std::size_t> range = ctx_byterange->getValue().getByteRange();
-                    if(range.first == 0) /* first == size, second = offset */
+                    ByteRange range = ctx_byterange->getValue().getByteRange();
+                    if(!range.first.has_value()) /* first == offset, second = length */
                         range.first = prevbyterangeoffset;
-                    prevbyterangeoffset = range.first + range.second;
-                    segment->setByteRange(range.first, prevbyterangeoffset - 1);
+                    prevbyterangeoffset = range.first.value() + range.second;
+                    segment->setByteRange(range.first.value(), prevbyterangeoffset - 1);
                     ctx_byterange = nullptr;
                 }
                 segment->setDiscontinuitySequenceNumber(discontinuitySequence);
@@ -428,8 +428,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, HLSRepresentation *rep, const std
                         const Attribute *byterangeAttr = keytag->getAttributeByName("BYTERANGE");
                         if(byterangeAttr)
                         {
-                            const std::pair<std::size_t,std::size_t> range = byterangeAttr->unescapeQuotes().getByteRange();
-                            initSegment->setByteRange(range.first, range.first + range.second - 1);
+                            const ByteRange range = byterangeAttr->unescapeQuotes().getByteRange();
+                            initSegment->setByteRange(range.first.value_or(0), range.first.value_or(0) + range.second - 1);
                         }
                         segmentList->initialisationSegment.Set(initSegment);
                     }


=====================================
modules/demux/hls/playlist/Tags.cpp
=====================================
@@ -72,10 +72,18 @@ std::vector<uint8_t> Attribute::hexSequence() const
     return ret;
 }
 
-std::pair<std::size_t,std::size_t> Attribute::getByteRange() const
+static inline std::istream& operator>>(std::istream& is, adaptive::optional<std::size_t>& data)
 {
-    std::size_t length = 0;
-    std::size_t offset = 0;
+    size_t val;
+    is >> val;
+    data = val;
+    return is;
+}
+
+ByteRange Attribute::getByteRange() const
+{
+    std::size_t length;
+    adaptive::optional<std::size_t> offset;
     std::istringstream is(value);
     is.imbue(std::locale("C"));
 
@@ -90,7 +98,7 @@ std::pair<std::size_t,std::size_t> Attribute::getByteRange() const
         }
     }
 
-    return std::make_pair(offset, length);
+    return ByteRange(std::move(offset), length);
 }
 
 std::pair<int, int> Attribute::getResolution() const


=====================================
modules/demux/hls/playlist/Tags.hpp
=====================================
@@ -20,6 +20,8 @@
 #ifndef TAGS_HPP
 #define TAGS_HPP
 
+#include "../../adaptive/tools/Compatibility.hpp"
+
 #include <stdint.h>
 
 #include <string>
@@ -32,6 +34,7 @@ namespace hls
 
     namespace playlist
     {
+        using ByteRange = std::pair<adaptive::optional<std::size_t>,std::size_t>;
 
         class Attribute
         {
@@ -43,7 +46,7 @@ namespace hls
                 std::string quotedString() const;
                 double floatingPoint() const;
                 std::vector<uint8_t> hexSequence() const;
-                std::pair<std::size_t,std::size_t> getByteRange() const;
+                ByteRange getByteRange() const;
                 std::pair<int, int> getResolution() const;
 
                 std::string name;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/eccffab95e19558e771be09c4a3f26455b266579...c52d819d60090ac41d78604e6455e3deaeffb736

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/eccffab95e19558e771be09c4a3f26455b266579...c52d819d60090ac41d78604e6455e3deaeffb736
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list