[vlc-commits] demux: adaptive: move decryption to base classes

Francois Cartegnie git at videolan.org
Fri May 10 10:37:25 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Apr 18 19:42:40 2019 +0200| [a726ac41fc98e6abdf4d10d2e7b3358878ecf2de] | committer: Francois Cartegnie

demux: adaptive: move decryption to base classes

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a726ac41fc98e6abdf4d10d2e7b3358878ecf2de
---

 .../demux/adaptive/encryption/CommonEncryption.cpp | 16 ++++++--
 .../demux/adaptive/encryption/CommonEncryption.hpp |  8 +++-
 modules/demux/adaptive/encryption/Keyring.cpp      |  1 +
 modules/demux/adaptive/playlist/Segment.cpp        | 29 ++++++++++++-
 modules/demux/adaptive/playlist/Segment.h          | 11 ++++-
 modules/demux/adaptive/playlist/SegmentChunk.cpp   | 29 +++++++++++++
 modules/demux/adaptive/playlist/SegmentChunk.hpp   |  8 ++++
 modules/demux/hls/playlist/HLSSegment.cpp          | 48 ++++------------------
 modules/demux/hls/playlist/HLSSegment.hpp          |  8 ++--
 modules/demux/hls/playlist/Parser.cpp              | 11 ++---
 10 files changed, 109 insertions(+), 60 deletions(-)

diff --git a/modules/demux/adaptive/encryption/CommonEncryption.cpp b/modules/demux/adaptive/encryption/CommonEncryption.cpp
index 31709dea70..743e04e860 100644
--- a/modules/demux/adaptive/encryption/CommonEncryption.cpp
+++ b/modules/demux/adaptive/encryption/CommonEncryption.cpp
@@ -23,6 +23,8 @@
 #endif
 
 #include "CommonEncryption.hpp"
+#include "Keyring.hpp"
+#include "../SharedResources.hpp"
 
 #include <vlc_common.h>
 
@@ -44,12 +46,13 @@ CommonEncryptionSession::CommonEncryptionSession()
     ctx = NULL;
 }
 
+
 CommonEncryptionSession::~CommonEncryptionSession()
 {
     close();
 }
 
-bool CommonEncryptionSession::start(const CommonEncryption &enc)
+bool CommonEncryptionSession::start(SharedResources *res, const CommonEncryption &enc)
 {
     if(ctx)
         close();
@@ -57,11 +60,18 @@ bool CommonEncryptionSession::start(const CommonEncryption &enc)
 #ifdef HAVE_GCRYPT
     if(encryption.method == CommonEncryption::Method::AES_128)
     {
+        if(key.empty())
+        {
+            if(!encryption.uri.empty())
+                key = res->getKeyring()->getKey(res->getAuthStorage(), encryption.uri);
+            if(key.size() != 16)
+                return false;
+        }
+
         vlc_gcrypt_init();
         gcry_cipher_hd_t handle;
         if( gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0) ||
-                encryption.key.size() != 16 ||
-                gcry_cipher_setkey(handle, &encryption.key[0], 16) ||
+                gcry_cipher_setkey(handle, &key[0], 16) ||
                 gcry_cipher_setiv(handle, &encryption.iv[0], 16) )
         {
             gcry_cipher_close(handle);
diff --git a/modules/demux/adaptive/encryption/CommonEncryption.hpp b/modules/demux/adaptive/encryption/CommonEncryption.hpp
index 25d3984bf3..66631c3d2a 100644
--- a/modules/demux/adaptive/encryption/CommonEncryption.hpp
+++ b/modules/demux/adaptive/encryption/CommonEncryption.hpp
@@ -21,9 +21,12 @@
 #define COMMONENCRYPTION_H
 
 #include <vector>
+#include <string>
 
 namespace adaptive
 {
+    class SharedResources;
+
     namespace encryption
     {
         class CommonEncryption
@@ -36,7 +39,7 @@ namespace adaptive
                     AES_128,
                     AES_SAMPLE,
                 } method;
-                std::vector<unsigned char> key;
+                std::string uri;
                 std::vector<unsigned char> iv;
         };
 
@@ -46,11 +49,12 @@ namespace adaptive
                 CommonEncryptionSession();
                 ~CommonEncryptionSession();
 
-                bool start(const CommonEncryption &);
+                bool start(SharedResources *, const CommonEncryption &);
                 void close();
                 size_t decrypt(void *, size_t, bool);
 
             private:
+                std::vector<unsigned char> key;
                 CommonEncryption encryption;
                 void *ctx;
         };
diff --git a/modules/demux/adaptive/encryption/Keyring.cpp b/modules/demux/adaptive/encryption/Keyring.cpp
index 68e2f25daf..baa630a1bc 100644
--- a/modules/demux/adaptive/encryption/Keyring.cpp
+++ b/modules/demux/adaptive/encryption/Keyring.cpp
@@ -53,6 +53,7 @@ KeyringKey Keyring::getKey(AuthStorage *auth, const std::string &uri)
     if(it == keys.end())
     {
         /* Pretty bad inside the lock */
+        msg_Dbg(obj, "Retrieving AES key %s", uri.c_str());
         block_t *p_block = Retrieve::HTTP(obj, auth, uri);
         if(p_block)
         {
diff --git a/modules/demux/adaptive/playlist/Segment.cpp b/modules/demux/adaptive/playlist/Segment.cpp
index 40cba1acdf..36051a9450 100644
--- a/modules/demux/adaptive/playlist/Segment.cpp
+++ b/modules/demux/adaptive/playlist/Segment.cpp
@@ -67,7 +67,22 @@ void ISegment::onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *)
 
 }
 
-SegmentChunk* ISegment::toChunk(SharedResources *, AbstractConnectionManager *connManager,
+bool ISegment::prepareChunk(SharedResources *res, SegmentChunk *chunk, BaseRepresentation *)
+{
+    if(encryption.method != CommonEncryption::Method::NONE)
+    {
+        CommonEncryptionSession *encryptionSession = new CommonEncryptionSession();
+        if(!encryptionSession->start(res, encryption))
+        {
+            delete encryptionSession;
+            return false;
+        }
+        chunk->setEncryptionSession(encryptionSession);
+    }
+    return true;
+}
+
+SegmentChunk* ISegment::toChunk(SharedResources *res, AbstractConnectionManager *connManager,
                                 size_t index, BaseRepresentation *rep)
 {
     const std::string url = getUrlSegment().toString(index, rep);
@@ -79,8 +94,13 @@ SegmentChunk* ISegment::toChunk(SharedResources *, AbstractConnectionManager *co
             source->setBytesRange(BytesRange(startByte, endByte));
 
         SegmentChunk *chunk = new (std::nothrow) SegmentChunk(this, source, rep);
-        if( chunk )
+        if(chunk)
         {
+            if(!prepareChunk(res, chunk, rep))
+            {
+                delete chunk;
+                return NULL;
+            }
             connManager->start(source);
             return chunk;
         }
@@ -163,6 +183,11 @@ int ISegment::compare(ISegment *other) const
     return 0;
 }
 
+void ISegment::setEncryption(CommonEncryption &e)
+{
+    encryption = e;
+}
+
 int ISegment::getClassId() const
 {
     return classId;
diff --git a/modules/demux/adaptive/playlist/Segment.h b/modules/demux/adaptive/playlist/Segment.h
index 1a2c217d58..28494ca2b6 100644
--- a/modules/demux/adaptive/playlist/Segment.h
+++ b/modules/demux/adaptive/playlist/Segment.h
@@ -30,6 +30,7 @@
 #include <vector>
 #include "ICanonicalUrl.hpp"
 #include "../http/Chunk.h"
+#include "../encryption/CommonEncryption.hpp"
 #include "../tools/Properties.hpp"
 #include "Time.hpp"
 
@@ -49,6 +50,7 @@ namespace adaptive
         class SegmentChunk;
 
         using namespace http;
+        using namespace encryption;
 
         class ISegment : public ICanonicalUrl
         {
@@ -72,6 +74,7 @@ namespace adaptive
                 virtual void                            debug           (vlc_object_t *,int = 0) const;
                 virtual bool                            contains        (size_t byte) const;
                 virtual int                             compare         (ISegment *) const;
+                void                                    setEncryption   (CommonEncryption &);
                 int                                     getClassId      () const;
                 Property<stime_t>       startTime;
                 Property<stime_t>       duration;
@@ -80,9 +83,15 @@ namespace adaptive
 
                 static const int CLASSID_ISEGMENT = 0;
                 /* callbacks */
-                virtual void                            onChunkDownload (block_t **, SegmentChunk *, BaseRepresentation *);
+                virtual void                            onChunkDownload (block_t **,
+                                                                         SegmentChunk *,
+                                                                         BaseRepresentation *);
 
             protected:
+                virtual bool                            prepareChunk    (SharedResources *,
+                                                                         SegmentChunk *,
+                                                                         BaseRepresentation *);
+                CommonEncryption        encryption;
                 size_t                  startByte;
                 size_t                  endByte;
                 std::string             debugName;
diff --git a/modules/demux/adaptive/playlist/SegmentChunk.cpp b/modules/demux/adaptive/playlist/SegmentChunk.cpp
index 4616e869ad..19ce1d5b74 100644
--- a/modules/demux/adaptive/playlist/SegmentChunk.cpp
+++ b/modules/demux/adaptive/playlist/SegmentChunk.cpp
@@ -24,9 +24,14 @@
 #include "SegmentChunk.hpp"
 #include "Segment.h"
 #include "BaseRepresentation.h"
+#include "../encryption/CommonEncryption.hpp"
+
+#include <vlc_block.h>
+
 #include <cassert>
 
 using namespace adaptive::playlist;
+using namespace adaptive::encryption;
 using namespace adaptive;
 
 SegmentChunk::SegmentChunk(ISegment *segment_, AbstractChunkSource *source,
@@ -37,16 +42,35 @@ SegmentChunk::SegmentChunk(ISegment *segment_, AbstractChunkSource *source,
     segment->chunksuse.Set(segment->chunksuse.Get() + 1);
     rep = rep_;
     discontinuity = segment_->discontinuity;
+    encryptionSession = NULL;
 }
 
 SegmentChunk::~SegmentChunk()
 {
     assert(segment->chunksuse.Get() > 0);
     segment->chunksuse.Set(segment->chunksuse.Get() - 1);
+    delete encryptionSession;
+}
+
+bool SegmentChunk::decrypt(block_t **pp_block)
+{
+    block_t *p_block = *pp_block;
+
+    if(encryptionSession)
+    {
+        bool b_last = isEmpty();
+        p_block->i_buffer = encryptionSession->decrypt(p_block->p_buffer,
+                                                       p_block->i_buffer, b_last);
+        if(b_last)
+            encryptionSession->close();
+    }
+
+    return true;
 }
 
 void SegmentChunk::onDownload(block_t **pp_block)
 {
+    decrypt(pp_block);
     segment->onChunkDownload(pp_block, this, rep);
 }
 
@@ -58,3 +82,8 @@ StreamFormat SegmentChunk::getStreamFormat() const
         return StreamFormat();
 }
 
+void SegmentChunk::setEncryptionSession(CommonEncryptionSession *s)
+{
+    delete encryptionSession;
+    encryptionSession = s;
+}
diff --git a/modules/demux/adaptive/playlist/SegmentChunk.hpp b/modules/demux/adaptive/playlist/SegmentChunk.hpp
index 5673301c83..9807763a79 100644
--- a/modules/demux/adaptive/playlist/SegmentChunk.hpp
+++ b/modules/demux/adaptive/playlist/SegmentChunk.hpp
@@ -27,10 +27,15 @@
 
 namespace adaptive
 {
+    namespace encryption
+    {
+        class CommonEncryptionSession;
+    }
 
     namespace playlist
     {
         using namespace http;
+        using namespace encryption;
 
         class BaseRepresentation;
         class ISegment;
@@ -40,13 +45,16 @@ namespace adaptive
         public:
             SegmentChunk(ISegment *segment, AbstractChunkSource *, BaseRepresentation *);
             virtual ~SegmentChunk();
+            void         setEncryptionSession(CommonEncryptionSession *);
             StreamFormat getStreamFormat() const;
             bool discontinuity;
 
         protected:
+            bool         decrypt(block_t **);
             virtual void onDownload(block_t **); // reimpl
             ISegment *segment;
             BaseRepresentation *rep;
+            CommonEncryptionSession *encryptionSession;
         };
 
     }
diff --git a/modules/demux/hls/playlist/HLSSegment.cpp b/modules/demux/hls/playlist/HLSSegment.cpp
index a3f26256e1..9b3f671851 100644
--- a/modules/demux/hls/playlist/HLSSegment.cpp
+++ b/modules/demux/hls/playlist/HLSSegment.cpp
@@ -24,10 +24,7 @@
 #include "HLSSegment.hpp"
 #include "../adaptive/playlist/SegmentChunk.hpp"
 #include "../adaptive/playlist/BaseRepresentation.h"
-#include "../adaptive/encryption/CommonEncryption.hpp"
 
-#include <vlc_common.h>
-#include <vlc_block.h>
 
 using namespace hls::playlist;
 
@@ -42,47 +39,23 @@ HLSSegment::~HLSSegment()
 {
 }
 
-void HLSSegment::onChunkDownload(block_t **pp_block, SegmentChunk *chunk, BaseRepresentation *)
+bool HLSSegment::prepareChunk(SharedResources *res, SegmentChunk *chunk, BaseRepresentation *rep)
 {
-    block_t *p_block = *pp_block;
-
-#ifndef HAVE_GCRYPT
-    (void)chunk;
-#else
     if(encryption.method == CommonEncryption::Method::AES_128)
     {
         if (encryption.iv.size() != 16)
         {
+            uint64_t sequence = getSequenceNumber() - Segment::SEQUENCE_FIRST;
             encryption.iv.clear();
             encryption.iv.resize(16);
-            encryption.iv[15] = (getSequenceNumber() - Segment::SEQUENCE_FIRST) & 0xff;
-            encryption.iv[14] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 8)& 0xff;
-            encryption.iv[13] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 16)& 0xff;
-            encryption.iv[12] = ((getSequenceNumber() - Segment::SEQUENCE_FIRST) >> 24)& 0xff;
-        }
-
-        block_t *p_block = *pp_block;
-        /* first bytes */
-        if(chunk->getBytesRead() == p_block->i_buffer)
-        {
-            if(!encryptSession.start(encryption))
-            {
-                p_block->i_buffer = 0;
-                return;
-            }
+            encryption.iv[15] = (sequence >> 0) & 0xff;
+            encryption.iv[14] = (sequence >> 8) & 0xff;
+            encryption.iv[13] = (sequence >> 16) & 0xff;
+            encryption.iv[12] = (sequence >> 24) & 0xff;
         }
-
-        bool b_last = chunk->isEmpty();
-        p_block->i_buffer = encryptSession.decrypt(p_block->p_buffer, p_block->i_buffer, b_last);
-        if(b_last)
-            encryptSession.close();
-    }
-    else
-#endif
-    if(encryption.method != CommonEncryption::Method::NONE)
-    {
-        p_block->i_buffer = 0;
     }
+
+    return Segment::prepareChunk(res, chunk, rep);
 }
 
 vlc_tick_t HLSSegment::getUTCTime() const
@@ -90,11 +63,6 @@ vlc_tick_t HLSSegment::getUTCTime() const
     return utcTime;
 }
 
-void HLSSegment::setEncryption(CommonEncryption &enc)
-{
-    encryption = enc;
-}
-
 int HLSSegment::compare(ISegment *segment) const
 {
     HLSSegment *hlssegment = dynamic_cast<HLSSegment *>(segment);
diff --git a/modules/demux/hls/playlist/HLSSegment.hpp b/modules/demux/hls/playlist/HLSSegment.hpp
index 22cee023c3..e06f9e465b 100644
--- a/modules/demux/hls/playlist/HLSSegment.hpp
+++ b/modules/demux/hls/playlist/HLSSegment.hpp
@@ -27,6 +27,7 @@ namespace hls
 {
     namespace playlist
     {
+        using namespace adaptive;
         using namespace adaptive::playlist;
         using namespace adaptive::encryption;
 
@@ -37,16 +38,13 @@ namespace hls
             public:
                 HLSSegment( ICanonicalUrl *parent, uint64_t sequence );
                 virtual ~HLSSegment();
-                void setEncryption(CommonEncryption &);
                 vlc_tick_t getUTCTime() const;
                 virtual int compare(ISegment *) const; /* reimpl */
 
             protected:
                 vlc_tick_t utcTime;
-                virtual void onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *); /* reimpl */
-
-                CommonEncryption encryption;
-                CommonEncryptionSession encryptSession;
+                virtual bool prepareChunk(SharedResources *, SegmentChunk *,
+                                          BaseRepresentation *); /* reimpl */
         };
     }
 }
diff --git a/modules/demux/hls/playlist/Parser.cpp b/modules/demux/hls/playlist/Parser.cpp
index e3e698d747..109ca08a91 100644
--- a/modules/demux/hls/playlist/Parser.cpp
+++ b/modules/demux/hls/playlist/Parser.cpp
@@ -316,7 +316,7 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
                     keytag->getAttributeByName("URI") )
                 {
                     encryption.method = CommonEncryption::Method::AES_128;
-                    encryption.key.clear();
+                    encryption.uri.clear();
 
                     Url keyurl(keytag->getAttributeByName("URI")->quotedString());
                     if(!keyurl.hasScheme())
@@ -324,11 +324,8 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
                         keyurl.prepend(Helper::getDirectoryPath(rep->getPlaylistUrl().toString()).append("/"));
                     }
 
-                    M3U8 *m3u8 = dynamic_cast<M3U8 *>(rep->getPlaylist());
-                    if(likely(m3u8))
-                        encryption.key = resources->getKeyring()->getKey(
-                                            resources->getAuthStorage(),
-                                            keyurl.toString());
+                    encryption.uri = keyurl.toString();
+
                     if(keytag->getAttributeByName("IV"))
                     {
                         encryption.iv.clear();
@@ -339,7 +336,7 @@ void M3U8Parser::parseSegments(vlc_object_t *, Representation *rep, const std::l
                 {
                     /* unsupported or invalid */
                     encryption.method = CommonEncryption::Method::NONE;
-                    encryption.key.clear();
+                    encryption.uri.clear();
                     encryption.iv.clear();
                 }
             }



More information about the vlc-commits mailing list