Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09223fc4 authored by Ray Essick's avatar Ray Essick Committed by Android Build Coastguard Worker
Browse files

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
Change-Id: I739248436a4801a4b9a96395f481640f2956cedf
(cherry picked from commit 49e842e7)
Merged-In: I739248436a4801a4b9a96395f481640f2956cedf
parent 660fa800
Loading
Loading
Loading
Loading
+97 −22
Original line number Diff line number Diff line
@@ -685,6 +685,8 @@ MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
    mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
            ::ndk::SharedRefBase::make<ResourceManagerClient>(this));

    // we want an empty metrics record for any early getMetrics() call
    // this should be the *only* initMediametrics() call that's not on the Looper thread
    initMediametrics();
}

@@ -693,8 +695,17 @@ MediaCodec::~MediaCodec() {
    mResourceManagerProxy->removeClient();

    flushMediametrics();

    // clean any saved metrics info we stored as part of configure()
    if (mConfigureMsg != nullptr) {
        mediametrics_handle_t metricsHandle;
        if (mConfigureMsg->findInt64("metrics", &metricsHandle)) {
            mediametrics_delete(metricsHandle);
        }
    }
}

// except for in constructor, called from the looper thread (and therefore mutexed)
void MediaCodec::initMediametrics() {
    if (mMetricsHandle == 0) {
        mMetricsHandle = mediametrics_create(kCodecKeyName);
@@ -724,11 +735,12 @@ void MediaCodec::initMediametrics() {
}

void MediaCodec::updateMediametrics() {
    ALOGV("MediaCodec::updateMediametrics");
    if (mMetricsHandle == 0) {
        return;
    }

    Mutex::Autolock _lock(mMetricsLock);

    if (mLatencyHist.getCount() != 0 ) {
        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -763,6 +775,8 @@ void MediaCodec::updateMediametrics() {
#endif
}

// called to update info being passed back via getMetrics(), which is a
// unique copy for that call, no concurrent access worries.
void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
    ALOGD("MediaCodec::updateEphemeralMediametrics()");

@@ -802,7 +816,13 @@ void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
}

void MediaCodec::flushMediametrics() {
    ALOGD("flushMediametrics");

    // update does its own mutex locking
    updateMediametrics();

    // ensure mutex while we do our own work
    Mutex::Autolock _lock(mMetricsLock);
    if (mMetricsHandle != 0) {
        if (mediametrics_count(mMetricsHandle) > 0) {
            mediametrics_selfRecord(mMetricsHandle);
@@ -1189,6 +1209,8 @@ status_t MediaCodec::init(const AString &name) {
    }
    msg->setString("name", name);

    // initial naming setup covers the period before the first call to ::configure().
    // after that, we manage this through ::configure() and the setup message.
    if (mMetricsHandle != 0) {
        mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
        mediametrics_setCString(mMetricsHandle, kCodecMode,
@@ -1248,18 +1270,24 @@ status_t MediaCodec::configure(
        const sp<IDescrambler> &descrambler,
        uint32_t flags) {
    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
    mediametrics_handle_t nextMetricsHandle = mediametrics_create(kCodecKeyName);

    if (mMetricsHandle != 0) {
    if (nextMetricsHandle != 0) {
        int32_t profile = 0;
        if (format->findInt32("profile", &profile)) {
            mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
            mediametrics_setInt32(nextMetricsHandle, kCodecProfile, profile);
        }
        int32_t level = 0;
        if (format->findInt32("level", &level)) {
            mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
            mediametrics_setInt32(nextMetricsHandle, kCodecLevel, level);
        }
        mediametrics_setInt32(mMetricsHandle, kCodecEncoder,
        mediametrics_setInt32(nextMetricsHandle, kCodecEncoder,
                              (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);

        // moved here from ::init()
        mediametrics_setCString(nextMetricsHandle, kCodecCodec, mInitName.c_str());
        mediametrics_setCString(nextMetricsHandle, kCodecMode,
                                mIsVideo ? kCodecModeVideo : kCodecModeAudio);
    }

    if (mIsVideo) {
@@ -1269,17 +1297,17 @@ status_t MediaCodec::configure(
            mRotationDegrees = 0;
        }

        if (mMetricsHandle != 0) {
            mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth);
            mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight);
            mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
        if (nextMetricsHandle != 0) {
            mediametrics_setInt32(nextMetricsHandle, kCodecWidth, mVideoWidth);
            mediametrics_setInt32(nextMetricsHandle, kCodecHeight, mVideoHeight);
            mediametrics_setInt32(nextMetricsHandle, kCodecRotation, mRotationDegrees);
            int32_t maxWidth = 0;
            if (format->findInt32("max-width", &maxWidth)) {
                mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth);
                mediametrics_setInt32(nextMetricsHandle, kCodecMaxWidth, maxWidth);
            }
            int32_t maxHeight = 0;
            if (format->findInt32("max-height", &maxHeight)) {
                mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
                mediametrics_setInt32(nextMetricsHandle, kCodecMaxHeight, maxHeight);
            }
        }

@@ -1303,13 +1331,23 @@ status_t MediaCodec::configure(
        } else {
            msg->setPointer("descrambler", descrambler.get());
        }
        if (mMetricsHandle != 0) {
            mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1);
        if (nextMetricsHandle != 0) {
            mediametrics_setInt32(nextMetricsHandle, kCodecCrypto, 1);
        }
    } else if (mFlags & kFlagIsSecure) {
        ALOGW("Crypto or descrambler should be given for secure codec");
    }

    if (mConfigureMsg != nullptr) {
        // if re-configuring, we have one of these from before.
        // Recover the space before we discard the old mConfigureMsg
        mediametrics_handle_t metricsHandle;
        if (mConfigureMsg->findInt64("metrics", &metricsHandle)) {
            mediametrics_delete(metricsHandle);
        }
    }
    msg->setInt64("metrics", nextMetricsHandle);

    // save msg for reset
    mConfigureMsg = msg;

@@ -1821,24 +1859,42 @@ status_t MediaCodec::getCodecInfo(sp<MediaCodecInfo> *codecInfo) const {
    return OK;
}

// this is the user-callable entry point
status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) {

    reply = 0;

    // shouldn't happen, but be safe
    if (mMetricsHandle == 0) {
        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
    updateMediametrics();
    CHECK(response->findInt64("metrics", &reply));

    // send it back to the caller.
    reply = mediametrics_dup(mMetricsHandle);
    return OK;
}

    updateEphemeralMediametrics(reply);
// runs on the looper thread (for mutex purposes)
void MediaCodec::onGetMetrics(const sp<AMessage>& msg) {

    return OK;
    mediametrics_handle_t results = 0;

    sp<AReplyToken> replyID;
    CHECK(msg->senderAwaitsResponse(&replyID));

    if (mMetricsHandle != 0) {
        updateMediametrics();
        results = mediametrics_dup(mMetricsHandle);
        updateEphemeralMediametrics(results);
    } else {
        results = mediametrics_dup(mMetricsHandle);
    }

    sp<AMessage> response = new AMessage;
    response->setInt64("metrics", results);
    response->postReply(replyID);
}

status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
@@ -2834,6 +2890,13 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatGetMetrics:
        {
            onGetMetrics(msg);
            break;
        }


        case kWhatConfigure:
        {
            sp<AReplyToken> replyID;
@@ -2850,6 +2913,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
            mediametrics_handle_t handle;
            CHECK(msg->findInt64("metrics", &handle));
            if (handle != 0) {
                if (mMetricsHandle != 0) {
                    flushMediametrics();
                }
                mMetricsHandle = mediametrics_dup(handle);
                // and set some additional metrics values
                initMediametrics();
            }

            int32_t push;
            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
                mFlags |= kFlagPushBlankBuffersOnShutdown;
+4 −0
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ private:
        kWhatSetNotification                = 'setN',
        kWhatDrmReleaseCrypto               = 'rDrm',
        kWhatCheckBatteryStats              = 'chkB',
        kWhatGetMetrics                     = 'getM',
    };

    enum {
@@ -371,6 +372,7 @@ private:
    sp<Surface> mSurface;
    SoftwareRenderer *mSoftRenderer;

    Mutex mMetricsLock;
    mediametrics_handle_t mMetricsHandle = 0;
    nsecs_t mLifetimeStartNs = 0;
    void initMediametrics();
@@ -378,6 +380,8 @@ private:
    void flushMediametrics();
    void updateEphemeralMediametrics(mediametrics_handle_t item);
    void updateLowLatency(const sp<AMessage> &msg);
    void onGetMetrics(const sp<AMessage>& msg);


    sp<AMessage> mOutputFormat;
    sp<AMessage> mInputFormat;