From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ray Essick Date: Thu, 1 Dec 2022 21:02:09 -0600 Subject: [PATCH] move MediaCodec metrics processing to looper thread consolidate to avoid concurrency/mutex problems. Bug: 256087846 Bug: 245860753 Test: atest CtsMediaV2TestCases Test: atest CtsMediaCodecTestCases Merged-In: Ie77f0028cab8091edd97d3a60ad4c80da3092cfe Merged-In: I56eceb6b12ce14348d3f9f2944968e70c6086aa8 Merged-In: I94b0a2ac029dc0b90a93e9ed844768e9da5259b9 Merged-In: I739248436a4801a4b9a96395f481640f2956cedf Change-Id: If5269d3efcd7c262020e580fe84fe89261a1af60 (cherry picked from commit 0ccdce19f669cd628ab6d116c131efc8d15707ee) Merged-In: If5269d3efcd7c262020e580fe84fe89261a1af60 --- media/libstagefright/MediaCodec.cpp | 102 ++++++++++++++---- .../include/media/stagefright/MediaCodec.h | 3 + 2 files changed, 86 insertions(+), 19 deletions(-) diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 353e40702f..cd1d24b06b 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -40,6 +40,7 @@ #include #include #include +// RBE do i need to add this? #include // RBE #include #include #include @@ -546,6 +547,14 @@ MediaCodec::~MediaCodec() { mResourceManagerService->removeResource(getId(mResourceManagerClient)); flushAnalyticsItem(); + + // clean up any saved AnalyticsItem stored in the configuration message + if (mConfigureMsg != nullptr) { + MediaAnalyticsItem *oldItem = nullptr; + if (mConfigureMsg->findPointer("metrics", (void**) &oldItem)) { + delete oldItem; + } + } } void MediaCodec::initAnalyticsItem() { @@ -570,6 +579,8 @@ void MediaCodec::updateAnalyticsItem() { return; } + Mutex::Autolock _lock(mMetricsLock); + if (mLatencyHist.getCount() != 0 ) { mAnalyticsItem->setInt64(kCodecLatencyMax, mLatencyHist.getMax()); mAnalyticsItem->setInt64(kCodecLatencyMin, mLatencyHist.getMin()); @@ -632,7 +643,10 @@ void MediaCodec::updateEphemeralAnalytics(MediaAnalyticsItem *item) { } void MediaCodec::flushAnalyticsItem() { + // update does its own mutex locking updateAnalyticsItem(); + + Mutex::Autolock _lock(mMetricsLock); if (mAnalyticsItem != NULL) { // don't log empty records if (mAnalyticsItem->count() > 0) { @@ -1018,16 +1032,22 @@ status_t MediaCodec::configure( uint32_t flags) { sp msg = new AMessage(kWhatConfigure, this); - if (mAnalyticsItem != NULL) { + MediaAnalyticsItem *newItem = new MediaAnalyticsItem(kCodecKeyName); + + if (newItem != NULL) { int32_t profile = 0; if (format->findInt32("profile", &profile)) { - mAnalyticsItem->setInt32(kCodecProfile, profile); + newItem->setInt32(kCodecProfile, profile); } int32_t level = 0; if (format->findInt32("level", &level)) { - mAnalyticsItem->setInt32(kCodecLevel, level); + newItem->setInt32(kCodecLevel, level); } - mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0); + newItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0); + + newItem->setCString(kCodecCodec, mInitName.c_str()); + newItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio); + } if (mIsVideo) { @@ -1037,17 +1057,17 @@ status_t MediaCodec::configure( mRotationDegrees = 0; } - if (mAnalyticsItem != NULL) { - mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth); - mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight); - mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees); + if (newItem != NULL) { + newItem->setInt32(kCodecWidth, mVideoWidth); + newItem->setInt32(kCodecHeight, mVideoHeight); + newItem->setInt32(kCodecRotation, mRotationDegrees); int32_t maxWidth = 0; if (format->findInt32("max-width", &maxWidth)) { - mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth); + newItem->setInt32(kCodecMaxWidth, maxWidth); } int32_t maxHeight = 0; if (format->findInt32("max-height", &maxHeight)) { - mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight); + newItem->setInt32(kCodecMaxHeight, maxHeight); } } @@ -1075,6 +1095,15 @@ status_t MediaCodec::configure( ALOGW("Crypto or descrambler should be given for secure codec"); } + // recover space of any previous saved baseline analytics info + if (mConfigureMsg != nullptr) { + MediaAnalyticsItem *oldItem = nullptr; + if (mConfigureMsg->findPointer("metrics", (void **) &oldItem)) { + delete oldItem; + } + } + msg->setPointer("metrics", newItem); + // save msg for reset mConfigureMsg = msg; @@ -1530,20 +1559,36 @@ status_t MediaCodec::getMetrics(MediaAnalyticsItem * &reply) { reply = NULL; - // shouldn't happen, but be safe - if (mAnalyticsItem == NULL) { - return UNKNOWN_ERROR; + sp msg = new AMessage(kWhatGetMetrics, this); + sp response; + status_t err; + if ((err = PostAndAwaitResponse(msg, &response)) != OK) { + return err; } - // update any in-flight data that's not carried within the record - updateAnalyticsItem(); + CHECK(response->findPointer("metrics", (void **) &reply)); - // send it back to the caller. - reply = mAnalyticsItem->dup(); + return OK; +} - updateEphemeralAnalytics(reply); +// runs on the looper thread (for mutex purposes) +void MediaCodec::onGetMetrics(const sp& msg) { - return OK; + MediaAnalyticsItem *results = nullptr; + + sp replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + // RBE is it always non-null at this point? + if (mAnalyticsItem != nullptr) { + updateAnalyticsItem(); + results = mAnalyticsItem->dup(); + updateEphemeralAnalytics(results); + } + + sp response = new AMessage; + response->setPointer("metrics", results); + response->postReply(replyID); } status_t MediaCodec::getInputBuffers(Vector > *buffers) const { @@ -2381,6 +2426,13 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } + case kWhatGetMetrics: + { + onGetMetrics(msg); + break; + } + + case kWhatConfigure: { sp replyID; @@ -2397,6 +2449,18 @@ void MediaCodec::onMessageReceived(const sp &msg) { sp format; CHECK(msg->findMessage("format", &format)); + // start with a copy of the passed metrics info for use in this run + MediaAnalyticsItem *handle; + CHECK(msg->findPointer("metrics", (void **) &handle)); + if (handle != nullptr) { + if (mAnalyticsItem != nullptr) { + flushAnalyticsItem(); + } + mAnalyticsItem = handle->dup(); + // and set some additional metrics values + initAnalyticsItem(); + } + int32_t push; if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) { mFlags |= kFlagPushBlankBuffersOnShutdown; diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 7f6aae6281..b9f5c0b239 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -257,6 +257,7 @@ private: kWhatSetCallback = 'setC', kWhatSetNotification = 'setN', kWhatDrmReleaseCrypto = 'rDrm', + kWhatGetMetrics = 'getM', }; enum { @@ -320,11 +321,13 @@ private: sp mSurface; SoftwareRenderer *mSoftRenderer; + Mutex mMetricsLock; MediaAnalyticsItem *mAnalyticsItem; void initAnalyticsItem(); void updateAnalyticsItem(); void flushAnalyticsItem(); void updateEphemeralAnalytics(MediaAnalyticsItem *item); + void onGetMetrics(const sp& msg); sp mOutputFormat; sp mInputFormat;