blob: 50fe0087620b22e3ee6f8e548303a0a88dcba34f [file] [edit]
From 49dfcb724a8ca7ab69ba27ef7e43430d9f766335 Mon Sep 17 00:00:00 2001
From: Douglas Adler <douglas_adler2@comcast.com>
Date: Mon, 8 Mar 2021 16:14:38 +0000
Subject: [PATCH] RDK-31882 : Add GstCaps parsing in OCDM to
wpeframework-clientlibraries
Source: COMCAST
Upstream-Status: N/A
Reason for change: Amlogic needs to handle Audio data outside the SVP path
Test Procedure: Verify that CDM module is detecting the stream type
Risks: None
Signed-off-by: Douglas Adler <douglas_adler2@comcast.com>
---
Source/ocdm/DataExchange.h | 21 +++++++++++++++
Source/ocdm/IOCDM.h | 3 +++
.../broadcom-svp-secbuf/open_cdm_adapter.cpp | 22 ++++++++++++---
.../adapter/gstreamer/open_cdm_adapter.cpp | 22 ++++++++++++---
Source/ocdm/adapter/open_cdm_adapter.h | 9 +++++--
Source/ocdm/open_cdm.cpp | 27 +++++++++++++++++--
Source/ocdm/open_cdm.h | 20 ++++++++++++--
Source/ocdm/open_cdm_impl.h | 15 ++++++++---
8 files changed, 124 insertions(+), 15 deletions(-)
diff --git a/Source/ocdm/DataExchange.h b/Source/ocdm/DataExchange.h
index 5744709..c63cf5c 100644
--- a/Source/ocdm/DataExchange.h
+++ b/Source/ocdm/DataExchange.h
@@ -43,6 +43,8 @@ private:
uint8_t IV[24];
uint16_t SubLength;
uint8_t Sub[2048];
+ uint16_t StreamInfoLength;
+ uint8_t StreamInfo[2048];
bool InitWithLast15;
};
@@ -88,6 +90,15 @@ public:
return (reinterpret_cast<const Administration*>(AdministrationBuffer())
->InitWithLast15);
}
+ void SetStreamInfo(const uint16_t length, const uint8_t* data)
+ {
+ Administration* admin = reinterpret_cast<Administration*>(AdministrationBuffer());
+ admin->StreamInfoLength = (length > sizeof(Administration::StreamInfo) ? sizeof(Administration::StreamInfo)
+ : length);
+ if (data != nullptr) {
+ ::memcpy(admin->StreamInfo, data, admin->StreamInfoLength);
+ }
+ }
void SetIV(const uint8_t ivDataLength, const uint8_t ivData[])
{
Administration* admin = reinterpret_cast<Administration*>(AdministrationBuffer());
@@ -146,6 +157,16 @@ public:
ASSERT(length <= 16);
return (length > 0 ? &admin->KeyId[1] : nullptr);
}
+ const uint8_t* StreamInfo() const
+ {
+ const Administration* admin = reinterpret_cast<const Administration*>(AdministrationBuffer());
+ return (admin->StreamInfo);
+ }
+ const uint16_t StreamInfoLength() const
+ {
+ const Administration* admin = reinterpret_cast<const Administration*>(AdministrationBuffer());
+ return (admin->StreamInfoLength);
+ }
};
} // namespace OCDM
diff --git a/Source/ocdm/IOCDM.h b/Source/ocdm/IOCDM.h
index 61f3fcc..b6dce72 100644
--- a/Source/ocdm/IOCDM.h
+++ b/Source/ocdm/IOCDM.h
@@ -117,6 +117,9 @@ struct ISession : virtual public WPEFramework::Core::IUnknown {
// Let the CDM know playback has stopped in order to disable output protection
virtual void ResetOutputProtection() = 0;
+ // Set a name/value pair into the CDM
+ virtual void SetParameter(const std::string& name, const std::string& value) = 0;
+
// During instantiation a callback is set, here we can decouple.
virtual void Revoke(OCDM::ISession::ICallback* callback) = 0;
};
diff --git a/Source/ocdm/adapter/broadcom-svp-secbuf/open_cdm_adapter.cpp b/Source/ocdm/adapter/broadcom-svp-secbuf/open_cdm_adapter.cpp
index b8c9932..1b67514 100644
--- a/Source/ocdm/adapter/broadcom-svp-secbuf/open_cdm_adapter.cpp
+++ b/Source/ocdm/adapter/broadcom-svp-secbuf/open_cdm_adapter.cpp
@@ -31,8 +31,15 @@ struct Rpc_Secbuf_Info {
size_t size;
void *token;
};
-OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSampleBuffer, const uint32_t subSampleCount,
- GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15)
+
+OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSample, const uint32_t subSampleCount,
+ GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15)
+{
+ return opencdm_gstreamer_session_decrypt_ex(session, buffer, subSample, subSampleCount, IV, keyID, initWithLast15, NULL);
+}
+
+OpenCDMError opencdm_gstreamer_session_decrypt_ex(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSampleBuffer, const uint32_t subSampleCount,
+ GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15, GstCaps* caps)
{
OpenCDMError result (ERROR_INVALID_SESSION);
@@ -60,6 +67,16 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
return (ERROR_INVALID_DECRYPT_BUFFER);
}
+ // Generate a GstCaps string for stream info in CDM module
+ uint8_t* caps_str = NULL;
+ uint16_t caps_len = 0;
+ if(caps != NULL) {
+ caps_str = (uint8_t*)gst_caps_to_string(caps);
+ if(caps_str != nullptr) {
+ caps_len = strlen((const char*)caps_str);
+ }
+ }
+
uint8_t *mappedData = reinterpret_cast<uint8_t* >(dataMap.data);
uint32_t mappedDataSize = static_cast<uint32_t >(dataMap.size);
uint8_t *mappedIV = reinterpret_cast<uint8_t* >(ivMap.data);
@@ -111,7 +128,8 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
}
gst_byte_reader_set_pos(reader, 0);
- result = opencdm_session_decrypt(session, encryptedData, totalEncrypted, mappedIV, mappedIVSize, mappedKeyID, mappedKeyIDSize, initWithLast15);
+ result = opencdm_session_decrypt(session, encryptedData, totalEncrypted, mappedIV, mappedIVSize,
+ mappedKeyID, mappedKeyIDSize, initWithLast15, caps_str, caps_len);
if(result == ERROR_NONE) {
memcpy(&sb_info, encryptedData, sizeof(Rpc_Secbuf_Info));
@@ -138,7 +156,8 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
fEncryptedData = encryptedData;
memcpy(encryptedData, mappedData, mappedDataSize);
- result = opencdm_session_decrypt(session, encryptedData, totalEncryptedSize, mappedIV, mappedIVSize, mappedKeyID, mappedKeyIDSize, initWithLast15);
+ result = opencdm_session_decrypt(session, encryptedData, totalEncryptedSize, mappedIV, mappedIVSize,
+ mappedKeyID, mappedKeyIDSize, initWithLast15, caps_str, caps_len);
if(result == ERROR_NONE){
memcpy(&sb_info, fEncryptedData, sizeof(Rpc_Secbuf_Info));
@@ -150,6 +169,11 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
}
g_free(fEncryptedData);
}
+
+ if(caps_str != nullptr) {
+ g_free(caps_str);
+ }
+
gst_buffer_unmap(keyID, &keyIDMap);
gst_buffer_unmap(IV, &ivMap);
gst_buffer_unmap(buffer, &dataMap);
diff --git a/Source/ocdm/adapter/gstreamer/open_cdm_adapter.cpp b/Source/ocdm/adapter/gstreamer/open_cdm_adapter.cpp
index 6459e69..7dfe765 100644
--- a/Source/ocdm/adapter/gstreamer/open_cdm_adapter.cpp
+++ b/Source/ocdm/adapter/gstreamer/open_cdm_adapter.cpp
@@ -23,8 +23,14 @@
#include <gst/gst.h>
#include <gst/base/gstbytereader.h>
-OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSampleBuffer, const uint32_t subSampleCount,
- GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15)
+OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSample, const uint32_t subSampleCount,
+ GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15)
+{
+ return opencdm_gstreamer_session_decrypt_ex(session, buffer, subSample, subSampleCount, IV, keyID, initWithLast15, NULL);
+}
+
+OpenCDMError opencdm_gstreamer_session_decrypt_ex(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSampleBuffer, const uint32_t subSampleCount,
+ GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15, GstCaps* caps)
{
OpenCDMError result (ERROR_INVALID_SESSION);
@@ -58,6 +64,16 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
mappedKeyIDSize = static_cast<uint32_t >(keyIDMap.size);
}
+ // Generate a GstCaps string for stream info in CDM module
+ uint8_t* caps_str = NULL;
+ uint16_t caps_len = 0;
+ if(caps != NULL) {
+ caps_str = (uint8_t*)gst_caps_to_string(caps);
+ if(caps_str != nullptr) {
+ caps_len = strlen((const char*)caps_str);
+ }
+ }
+
uint8_t *mappedData = reinterpret_cast<uint8_t* >(dataMap.data);
uint32_t mappedDataSize = static_cast<uint32_t >(dataMap.size);
uint8_t *mappedIV = reinterpret_cast<uint8_t* >(ivMap.data);
@@ -102,8 +118,9 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
}
gst_byte_reader_set_pos(reader, 0);
+ result = opencdm_session_decrypt(session, encryptedData, totalEncrypted, mappedIV, mappedIVSize,
+ mappedKeyID, mappedKeyIDSize, initWithLast15, caps_str, caps_len);
- result = opencdm_session_decrypt(session, encryptedData, totalEncrypted, mappedIV, mappedIVSize, mappedKeyID, mappedKeyIDSize, initWithLast15);
// Re-build sub-sample data.
index = 0;
unsigned total = 0;
@@ -120,7 +137,12 @@ OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, G
free(encryptedData);
gst_buffer_unmap(subSampleBuffer, &sampleMap);
} else {
- result = opencdm_session_decrypt(session, mappedData, mappedDataSize, mappedIV, mappedIVSize, mappedKeyID, mappedKeyIDSize, initWithLast15);
+ result = opencdm_session_decrypt(session, mappedData, mappedDataSize, mappedIV, mappedIVSize,
+ mappedKeyID, mappedKeyIDSize, initWithLast15, caps_str, caps_len);
+ }
+
+ if(caps_str != nullptr) {
+ g_free(caps_str);
}
if (keyID != nullptr) {
diff --git a/Source/ocdm/adapter/open_cdm_adapter.h b/Source/ocdm/adapter/open_cdm_adapter.h
index 02c06af..d9ff7cb 100644
index 02c06af..bd8a36b 100644
--- a/Source/ocdm/adapter/open_cdm_adapter.h
+++ b/Source/ocdm/adapter/open_cdm_adapter.h
@@ -24,6 +24,8 @@
struct _GstBuffer;
typedef struct _GstBuffer GstBuffer;
+struct _GstCaps;
+typedef struct _GstCaps GstCaps;
#ifdef __cplusplus
extern "C" {
@@ -41,9 +43,31 @@ extern "C" {
* \param subSampleCount count of subsamples
* \param IV Gstreamer buffer containing initial vector (IV) used during decryption.
* \param keyID Gstreamer buffer containing keyID to use for decryption
+ * \param initWithLast15 Init flag
+ * \param caps GstCaps structure
* \return Zero on success, non-zero on error.
*/
- EXTERNAL OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSample, const uint32_t subSampleCount,
+ EXTERNAL OpenCDMError opencdm_gstreamer_session_decrypt_ex(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSample, const uint32_t subSampleCount,
+ GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15, GstCaps* caps = NULL);
+
+
+/**
+ * \brief Performs decryption based on adapter implementation.
+ *
+ * This method accepts encrypted data and will typically decrypt it out-of-process (for security reasons). The actual data copying is performed
+ * using a memory-mapped file (for performance reasons). If the DRM system allows access to decrypted data (i.e. decrypting is not
+ * performed in a TEE), the decryption is performed in-place.
+ * \param session \ref OpenCDMSession instance.
+ * \param buffer Gstreamer buffer containing encrypted data and related meta data. If applicable, decrypted data will be stored here after this call returns.
+ * \param subSample Gstreamer buffer containing subsamples size which has been parsed from protection meta data.
+ * \param subSampleCount count of subsamples
+ * \param IV Gstreamer buffer containing initial vector (IV) used during decryption.
+ * \param keyID Gstreamer buffer containing keyID to use for decryption
+ * \param initWithLast15 Init flag
+ * \return Zero on success, non-zero on error.
+ */
+/** This provides implementation to support the older API. */
+ EXTERNAL OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession* session, GstBuffer* buffer, GstBuffer* subSample, const uint32_t subSampleCount,
GstBuffer* IV, GstBuffer* keyID, uint32_t initWithLast15);
#ifdef __cplusplus
diff --git a/Source/ocdm/open_cdm.cpp b/Source/ocdm/open_cdm.cpp
index 76db016..f7e76ec 100644
--- a/Source/ocdm/open_cdm.cpp
+++ b/Source/ocdm/open_cdm.cpp
@@ -435,6 +435,25 @@ OpenCDMError opencdm_session_resetoutputprotection(struct OpenCDMSession* sessio
return (result);
}
+/**
+ * Set a name/value pair into the CDM
+ * \param session \ref OpenCDMSession instance.
+ * \return Zero on success, non-zero on error.
+ */
+OpenCDMError opencdm_session_set_parameter(struct OpenCDMSession* session,
+ const std::string& name,
+ const std::string& value)
+{
+ OpenCDMError result(ERROR_INVALID_SESSION);
+
+ if (session != nullptr) {
+ session->SetParameter(name, value);
+ result = OpenCDMError::ERROR_NONE;
+ }
+
+ return (result);
+}
+
/**
* Closes a session.
* \param session \ref OpenCDMSession instance.
@@ -467,6 +486,8 @@ OpenCDMError opencdm_session_close(struct OpenCDMSession* session)
* \param encryptedLength Length of encrypted data buffer (in bytes).
* \param IV Initial vector (IV) used during decryption.
* \param IVLength Length of IV buffer (in bytes).
+ * \param streamInfo data blob with information about the current stream.
+ * \param streamInfoLength Length of info buffer (in bytes).
* \return Zero on success, non-zero on error.
* REPLACING: uint32_t decrypt(void* session, uint8_t*, const uint32_t, const
* uint8_t*, const uint16_t);
@@ -476,13 +497,15 @@ OpenCDMError opencdm_session_decrypt(struct OpenCDMSession* session,
const uint32_t encryptedLength,
const uint8_t* IV, const uint16_t IVLength,
const uint8_t* keyId, const uint16_t keyIdLength,
- uint32_t initWithLast15 /* = 0 */)
+ uint32_t initWithLast15 /* = 0 */,
+ uint8_t* streamInfo /* = NULL */,
+ uint16_t streamInfoLength /* = 0 */)
{
OpenCDMError result(ERROR_INVALID_SESSION);
if (session != nullptr) {
result = encryptedLength > 0 ? static_cast<OpenCDMError>(session->Decrypt(
- encrypted, encryptedLength, IV, IVLength, keyId, keyIdLength, initWithLast15)) : ERROR_NONE;
+ encrypted, encryptedLength, IV, IVLength, keyId, keyIdLength, initWithLast15, streamInfo, streamInfoLength)) : ERROR_NONE;
}
return (result);
diff --git a/Source/ocdm/open_cdm.h b/Source/ocdm/open_cdm.h
index 4acfd6a..de273dd 100644
--- a/Source/ocdm/open_cdm.h
+++ b/Source/ocdm/open_cdm.h
@@ -56,6 +56,7 @@
#include <stdint.h>
#include <string.h>
+#include <string>
#include <stdio.h>
#include <list>
@@ -401,6 +402,17 @@ EXTERNAL OpenCDMError opencdm_session_metadata(const struct OpenCDMSession* sess
*/
EXTERNAL OpenCDMError opencdm_session_resetoutputprotection(struct OpenCDMSession* session);
+/**
+ * Set a name/value pair into the CDM
+ * \param session \ref OpenCDMSession instance.
+ * \param name \ref Name of parameter
+ * \param value \ref Value of parameter
+ * \return Zero on success, non-zero on error.
+ */
+OpenCDMError opencdm_session_set_parameter(struct OpenCDMSession* session,
+ const std::string& name,
+ const std::string& value);
+
/**
* Gets Session ID for a session.
* \param session \ref OpenCDMSession instance.
@@ -486,14 +498,18 @@ EXTERNAL OpenCDMError opencdm_session_decrypt(struct OpenCDMSession* session,
const uint32_t encryptedLength,
const uint8_t* IV, uint16_t IVLength,
const uint8_t* keyId, const uint16_t keyIdLength,
- uint32_t initWithLast15 = 0);
+ uint32_t initWithLast15 = 0,
+ uint8_t* streamInfo = NULL,
+ uint16_t streamInfoLength = 0);
#else
EXTERNAL OpenCDMError opencdm_session_decrypt(struct OpenCDMSession* session,
uint8_t encrypted[],
const uint32_t encryptedLength,
const uint8_t* IV, uint16_t IVLength,
const uint8_t* keyId, const uint16_t keyIdLength,
- uint32_t initWithLast15);
+ uint32_t initWithLast15,
+ uint8_t* streamInfo,
+ uint16_t streamInfoLength);
#endif // __cplusplus
#ifdef __cplusplus
diff --git a/Source/ocdm/open_cdm_impl.h b/Source/ocdm/open_cdm_impl.h
index 0b321ba..c46daf1 100644
--- a/Source/ocdm/open_cdm_impl.h
+++ b/Source/ocdm/open_cdm_impl.h
@@ -409,7 +409,9 @@ private:
uint32_t Decrypt(uint8_t* encryptedData, uint32_t encryptedDataLength,
const uint8_t* ivData, uint16_t ivDataLength,
const uint8_t* keyId, uint16_t keyIdLength,
- uint32_t initWithLast15 /* = 0 */)
+ uint32_t initWithLast15 /* = 0 */,
+ const uint8_t* streamInfo /* = NULL */,
+ const uint16_t streamInfoLength /* = 0 */)
{
int ret = 0;
@@ -431,6 +433,7 @@ private:
SetSubSampleData(0, nullptr);
KeyId(static_cast<uint8_t>(keyIdLength), keyId);
InitWithLast15(initWithLast15);
+ SetStreamInfo(streamInfoLength, streamInfo);
Write(encryptedDataLength, encryptedData);
// This will trigger the OpenCDMIServer to decrypt this memory...
@@ -588,6 +591,12 @@ public:
_session->ResetOutputProtection();
}
+ inline void SetParameter(const std::string& name, const std::string& value)
+ {
+ ASSERT (_session != nullptr);
+
+ _session->SetParameter(name, value);
+ }
inline int Remove()
{
@@ -612,7 +621,7 @@ public:
uint32_t Decrypt(uint8_t* encryptedData, const uint32_t encryptedDataLength,
const uint8_t* ivData, uint16_t ivDataLength,
const uint8_t* keyId, const uint16_t keyIdLength,
- uint32_t initWithLast15)
+ uint32_t initWithLast15, const uint8_t* streamInfo, const uint16_t streamInfoLength)
{
uint32_t result = OpenCDMError::ERROR_INVALID_DECRYPT_BUFFER;
@@ -627,7 +636,7 @@ public:
if (decryptSession != nullptr) {
result = decryptSession->Decrypt(encryptedData, encryptedDataLength, ivData,
ivDataLength, keyId, keyIdLength,
- initWithLast15);
+ initWithLast15, streamInfo, streamInfoLength);
if(result)
{
TRACE_L1("Decrypt() failed with return code: %x", result);
--
2.24.0