From aa747e94c16c6d73cde4aab42f406e7b3a3bbdbc Mon Sep 17 00:00:00 2001 From: peak3d Date: Wed, 9 Oct 2019 13:06:49 +0200 Subject: [PATCH] [Backport][Android] Use JNI instead NDK MediaCrypto for secure decoder check --- tools/depends/target/libandroidjni/Makefile | 2 +- .../Video/DVDVideoCodecAndroidMediaCodec.cpp | 84 +++++++++++++------ .../Video/DVDVideoCodecAndroidMediaCodec.h | 1 + 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/tools/depends/target/libandroidjni/Makefile b/tools/depends/target/libandroidjni/Makefile index 49dddbb530543..0c4fb8f3ecff6 100644 --- a/tools/depends/target/libandroidjni/Makefile +++ b/tools/depends/target/libandroidjni/Makefile @@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile # lib name, version LIBNAME=libandroidjni -VERSION=aa12538cc5090d061d34b5fd7385d939ea82ce8b +VERSION=82f1a87f1d2397dd0340a9443d7feea70cc7ea3b SOURCE=archive ARCHIVE=$(VERSION).tar.gz GIT_BASE_URL=https://github.com/xbmc diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp index 70a565b43886d..2a27108fc923c 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp @@ -16,12 +16,15 @@ #include #include +#include #include #include #include +#include #include #include +#include #include #include @@ -58,7 +61,8 @@ #define XMEDIAFORMAT_KEY_CROP_RIGHT "crop-right" #define XMEDIAFORMAT_KEY_CROP_TOP "crop-top" #define XMEDIAFORMAT_KEY_CROP_BOTTOM "crop-bottom" -#define XMEDIAFORMAT_KEY_TUNNELED_PLAYBACK "feature-tunneled-playback" +#define XMEDIAFORMAT_FEATURE_TUNNELED_PLAYBACK "feature-tunneled-playback" +#define XMEDIAFORMAT_FEATURE_SECURE_PLAYBACK "feature-secure-playback" using namespace KODI::MESSAGING; @@ -365,10 +369,16 @@ std::atomic CDVDVideoCodecAndroidMediaCodec::m_InstanceGuard(false); bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { int num_codecs; - bool needSecureDecoder(false); int profile(0); + const AMediaUUID* uuid(nullptr); + const AMediaUUID wvuuid = {0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, + 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED}; + const AMediaUUID pruuid = {0x9A, 0x04, 0xF0, 0x79, 0x98, 0x40, 0x42, 0x86, + 0xAB, 0x92, 0xE6, 0x5B, 0xE0, 0x88, 0x5F, 0x95}; + m_opened = false; + m_needSecureDecoder = false; // allow only 1 instance here if (m_InstanceGuard.exchange(true)) { @@ -569,7 +579,35 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio } if (m_hints.cryptoSession) - needSecureDecoder = AMediaCrypto_requiresSecureDecoderComponent(m_mime.c_str()) && (m_hints.cryptoSession->flags & DemuxCryptoSession::FLAG_SECURE_DECODER) != 0; + { + if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_WIDEVINE) + uuid = &wvuuid; + else if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_PLAYREADY) + uuid = &pruuid; + else + { + CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open Unsupported crypto-keysystem %u", + m_hints.cryptoSession->keySystem); + goto FAIL; + } + + int64_t mostSigBits(0), leastSigBits(0); + for (unsigned int i(0); i < 8; ++i) + mostSigBits = (mostSigBits << 8) | (*uuid)[i]; + for (unsigned int i(8); i < 16; ++i) + leastSigBits = (leastSigBits << 8) | (*uuid)[i]; + CJNIUUID juuid(mostSigBits, leastSigBits); + CJNIMediaCrypto crypto(juuid, std::vector(m_hints.cryptoSession->sessionId, + m_hints.cryptoSession->sessionId + + m_hints.cryptoSession->sessionIdSize)); + m_needSecureDecoder = + crypto.requiresSecureDecoderComponent(m_mime) && + (m_hints.cryptoSession->flags & DemuxCryptoSession::FLAG_SECURE_DECODER) != 0; + + CLog::Log(LOGNOTICE, + "CDVDVideoCodecAndroidMediaCodec::Open: Secure decoder requested: %s (stream flags: %d)", + m_needSecureDecoder ? "true" : "false", m_hints.cryptoSession->flags); + } m_codec = nullptr; m_colorFormat = -1; @@ -587,20 +625,26 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio CLog::Log(LOGNOTICE, "CDVDVideoCodecAndroidMediaCodec::Open Testing codec:%s", m_codecname.c_str()); - bool codecIsSecure(m_codecname.find(".secure") != std::string::npos); - if (needSecureDecoder) + CJNIMediaCodecInfoCodecCapabilities codec_caps = codec_info.getCapabilitiesForType(m_mime); + if (xbmc_jnienv()->ExceptionCheck()) + { + // Unsupported type? + xbmc_jnienv()->ExceptionClear(); + continue; + } + + bool codecIsSecure( + m_codecname.find(".secure") != std::string::npos || + codec_caps.isFeatureSupported(CJNIMediaCodecInfoCodecCapabilities::FEATURE_SecurePlayback)); + if (m_needSecureDecoder) { if (!codecIsSecure) m_codecname += ".secure"; } else if (codecIsSecure) - continue; - - CJNIMediaCodecInfoCodecCapabilities codec_caps = codec_info.getCapabilitiesForType(m_mime); - if (xbmc_jnienv()->ExceptionCheck()) { - // Unsupported type? - xbmc_jnienv()->ExceptionClear(); + CLog::Log(LOGNOTICE, "CDVDVideoCodecAndroidMediaCodec::Open: skipping insecure decoder while " + "secure decoding is required"); continue; } @@ -653,20 +697,6 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio { CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::Open Initializing MediaCrypto"); - const AMediaUUID *uuid(nullptr); - const AMediaUUID wvuuid = {0xED,0xEF,0x8B,0xA9,0x79,0xD6,0x4A,0xCE,0xA3,0xC8,0x27,0xDC,0xD5,0x1D,0x21,0xED}; - const AMediaUUID pruuid = {0x9A,0x04,0xF0,0x79,0x98,0x40,0x42,0x86,0xAB,0x92,0xE6,0x5B,0xE0,0x88,0x5F,0x95}; - - if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_WIDEVINE) - uuid = &wvuuid; - else if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_PLAYREADY) - uuid = &pruuid; - else - { - CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open Unsupported crypto-keysystem %u", m_hints.cryptoSession->keySystem); - goto FAIL; - } - m_crypto = AMediaCrypto_new(*uuid, m_hints.cryptoSession->sessionId, m_hints.cryptoSession->sessionIdSize); if (!m_crypto) @@ -1118,7 +1148,9 @@ bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void) { // Handle rotation AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_KEY_ROTATION, m_hints.orientation); - AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_KEY_TUNNELED_PLAYBACK, 0); + AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_FEATURE_TUNNELED_PLAYBACK, 0); + if (m_needSecureDecoder) + AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_FEATURE_SECURE_PLAYBACK, 1); } diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h index 9d3fd1bbcd063..6e25a1331873f 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h @@ -155,6 +155,7 @@ class CDVDVideoCodecAndroidMediaCodec : public CDVDVideoCodec, public CJNISurfac int m_colorFormat; std::string m_formatname; bool m_opened; + bool m_needSecureDecoder = false; int m_codecControlFlags; int m_state; int m_noPictureLoop;