From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ray Essick <essick@google.com>
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 <media/IResourceManagerService.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/MediaAnalyticsItem.h>
+// RBE do i need to add this? #include <media/MediaMetrics.h>         // RBE
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -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<AMessage> 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<AMessage> msg = new AMessage(kWhatGetMetrics, this);
+    sp<AMessage> 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<AMessage>& msg) {
 
-    return OK;
+    MediaAnalyticsItem *results = nullptr;
+
+    sp<AReplyToken> replyID;
+    CHECK(msg->senderAwaitsResponse(&replyID));
+
+    // RBE is it always non-null at this point?
+    if (mAnalyticsItem != nullptr) {
+        updateAnalyticsItem();
+        results = mAnalyticsItem->dup();
+        updateEphemeralAnalytics(results);
+    }
+
+    sp<AMessage> response = new AMessage;
+    response->setPointer("metrics", results);
+    response->postReply(replyID);
 }
 
 status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
@@ -2381,6 +2426,13 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
             break;
         }
 
+        case kWhatGetMetrics:
+        {
+            onGetMetrics(msg);
+            break;
+        }
+
+
         case kWhatConfigure:
         {
             sp<AReplyToken> replyID;
@@ -2397,6 +2449,18 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
             sp<AMessage> 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<Surface> mSurface;
     SoftwareRenderer *mSoftRenderer;
 
+    Mutex mMetricsLock;
     MediaAnalyticsItem *mAnalyticsItem;
     void initAnalyticsItem();
     void updateAnalyticsItem();
     void flushAnalyticsItem();
     void updateEphemeralAnalytics(MediaAnalyticsItem *item);
+    void onGetMetrics(const sp<AMessage>& msg);
 
     sp<AMessage> mOutputFormat;
     sp<AMessage> mInputFormat;
