Modular DRM for MediaPlayer/Fixing legacy frame drop at NuPlayerDecoder
Bug: 34559906
Bug: 38039230
Bug: 38430289
Test: GTS/CTS Tests
Change-Id: I68dca5f8bae4f9f7866cfaaa6aba97c80dcd8ffb
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index a4a5861..8fe255b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -79,6 +79,8 @@
mIsAudio(true),
mIsVideoAVC(false),
mIsSecure(false),
+ mIsEncrypted(false),
+ mIsEncryptedObservedEarlier(false),
mFormatChangePending(false),
mTimeChangePending(false),
mFrameRateTotal(kDefaultVideoFrameRateTotal),
@@ -330,6 +332,10 @@
pCrypto = NULL;
}
sp<ICrypto> crypto = (ICrypto*)pCrypto;
+ // non-encrypted source won't have a crypto
+ mIsEncrypted = (crypto != NULL);
+ // configure is called once; still using OR in case the behavior changes.
+ mIsEncryptedObservedEarlier = mIsEncryptedObservedEarlier || mIsEncrypted;
ALOGV("onConfigure mCrypto: %p (%d) mIsSecure: %d",
crypto.get(), (crypto != NULL ? crypto->getStrongCount() : 0), mIsSecure);
@@ -611,6 +617,9 @@
sp<AMessage> response = new AMessage;
response->setInt32("status", status);
+ // Clearing the state as it's tied to crypto. mIsEncryptedObservedEarlier is sticky though
+ // and lasts for the lifetime of this codec. See its use in fetchInputData.
+ mIsEncrypted = false;
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
@@ -878,7 +887,20 @@
}
dropAccessUnit = false;
- if (!mIsAudio && !mIsSecure) {
+ if (!mIsAudio && !mIsEncrypted) {
+ // Extra safeguard if higher-level behavior changes. Otherwise, not required now.
+ // Preventing the buffer from being processed (and sent to codec) if this is a later
+ // round of playback but this time without prepareDrm. Or if there is a race between
+ // stop (which is not blocking) and releaseDrm allowing buffers being processed after
+ // Crypto has been released (GenericSource currently prevents this race though).
+ // Particularly doing this check before IsAVCReferenceFrame call to prevent parsing
+ // of encrypted data.
+ if (mIsEncryptedObservedEarlier) {
+ ALOGE("fetchInputData: mismatched mIsEncrypted/mIsEncryptedObservedEarlier (0/1)");
+
+ return INVALID_OPERATION;
+ }
+
int32_t layerId = 0;
bool haveLayerId = accessUnit->meta()->findInt32("temporal-layer-id", &layerId);
if (mRenderer->getVideoLateByUs() > 100000ll