[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