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

Commit f631809c authored by Brian Lindahl's avatar Brian Lindahl Committed by Automerger Merge Worker
Browse files

Merge changes I5e3a8b02,Ie3995fb9,Ie8b4d2c8 into udc-dev am: 7d1066db am: c308a822

parents 6ef9eb56 c308a822
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -86,6 +86,11 @@ void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
    if (item != NULL) item->setRate(attr, count, duration);
}

void mediametrics_setString(mediametrics_handle_t handle, attr_t attr,
                                 const std::string &string) {
    mediametrics_setCString(handle, attr, string.c_str());
}

void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
                                 const char *value) {
    Item *item = (Item *) handle;
@@ -152,6 +157,14 @@ bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
    return item->getRate(attr, count, duration, rate);
}

bool mediametrics_getString(mediametrics_handle_t handle, attr_t attr,
                                 std::string *string) {
    Item *item = (Item *) handle;
    if (item == NULL) return false;

    return item->getString(attr, string);
}

// NB: caller owns the string that comes back, is responsible for freeing it
bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
                                 char **value) {
+8 −1
Original line number Diff line number Diff line
@@ -95,4 +95,11 @@ bool mediametrics_getAttributes(mediametrics_handle_t handle, char **buffer, siz

__END_DECLS

#ifdef __cplusplus
#include <string>
void mediametrics_setString(mediametrics_handle_t handle, attr_t attr,
                            const std::string &value);
bool mediametrics_getString(mediametrics_handle_t handle, attr_t attr, std::string *value);
#endif // __cplusplus

#endif
+3 −3
Original line number Diff line number Diff line
@@ -1048,6 +1048,9 @@ public:
        }
        return true;
    }
    bool getString(const char *key, std::string *value) const {
        return get(key, value);
    }
    // Caller owns the returned string
    bool getCString(const char *key, char **value) const {
        std::string s;
@@ -1057,9 +1060,6 @@ public:
        }
        return false;
    }
    bool getString(const char *key, std::string *value) const {
        return get(key, value);
    }

    const Prop::Elem* get(const char *key) const {
        const Prop *prop = findProp(key);
+2 −0
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ cc_library {
        "MediaCodecSource.cpp",
        "MediaExtractor.cpp",
        "MediaExtractorFactory.cpp",
        "MediaHistogram.cpp",
        "MediaSource.cpp",
        "MediaSync.cpp",
        "MediaTrack.cpp",
@@ -270,6 +271,7 @@ cc_library {
        "SurfaceUtils.cpp",
        "ThrottledSource.cpp",
        "Utils.cpp",
        "VideoRenderQualityTracker.cpp",
        "VideoFrameSchedulerBase.cpp",
        "VideoFrameScheduler.cpp",
    ],
+85 −111
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#include <C2Buffer.h>

#include "include/SoftwareRenderer.h"
#include "PlaybackDurationAccumulator.h"

#include <android/binder_manager.h>
#include <android/content/pm/IPackageManagerNative.h>
@@ -199,6 +198,23 @@ static const char *kCodecRecentLatencyHist = "android.media.mediacodec.recent.hi
static const char *kCodecPlaybackDurationSec =
        "android.media.mediacodec.playback-duration-sec"; /* in sec */

static const char *kCodecFramesReleased = "android.media.mediacodec.frames.released";
static const char *kCodecFramesRendered = "android.media.mediacodec.frames.rendered";
static const char *kCodecFramesSkipped = "android.media.mediacodec.frames.skipped";
static const char *kCodecFramesDropped = "android.media.mediacodec.frames.dropped";
static const char *kCodecFramerateContent = "android.media.mediacodec.framerate.content";
static const char *kCodecFramerateDesired = "android.media.mediacodec.framerate.desired";
static const char *kCodecFramerateActual = "android.media.mediacodec.framerate.actual";

static const char *kCodecFreezeCount = "android.media.mediacodec.freeze.count";
static const char *kCodecFreezeDurationAverage = "android.media.mediacodec.freeze.duration.average";
static const char *kCodecFreezeDurationMax = "android.media.mediacodec.freeze.duration.max";
static const char *kCodecFreezeDurationHistogram =
        "android.media.mediacodec.freeze.duration.histogram";
static const char *kCodecFreezeDistanceAverage = "android.media.mediacodec.freeze.distance.average";
static const char *kCodecFreezeDistanceHistogram =
        "android.media.mediacodec.freeze.distance.histogram";

/* -1: shaper disabled
   >=0: number of fields changed */
static const char *kCodecShapingEnhanced = "android.media.mediacodec.shaped";
@@ -960,8 +976,7 @@ MediaCodec::MediaCodec(
      mHaveInputSurface(false),
      mHavePendingInputBuffers(false),
      mCpuBoostRequested(false),
      mPlaybackDurationAccumulator(new PlaybackDurationAccumulator()),
      mIsSurfaceToScreen(false),
      mIsSurfaceToDisplay(false),
      mLatencyUnknown(0),
      mBytesEncoded(0),
      mEarliestEncodedPtsUs(INT64_MAX),
@@ -1096,6 +1111,32 @@ void MediaCodec::updateMediametrics() {
    mediametrics_setInt32(mMetricsHandle, kCodecResolutionChangeCount,
            mReliabilityContextMetrics.resolutionChangeCount);

    // Video rendering quality metrics
    {
        const VideoRenderQualityMetrics& m = mVideoRenderQualityTracker.getMetrics();
        if (m.frameRenderedCount > 0) {
            mediametrics_setInt64(mMetricsHandle, kCodecFramesReleased, m.frameReleasedCount);
            mediametrics_setInt64(mMetricsHandle, kCodecFramesRendered, m.frameRenderedCount);
            mediametrics_setInt64(mMetricsHandle, kCodecFramesSkipped, m.frameSkippedCount);
            mediametrics_setInt64(mMetricsHandle, kCodecFramesDropped, m.frameDroppedCount);
            mediametrics_setDouble(mMetricsHandle, kCodecFramerateContent, m.contentFrameRate);
            mediametrics_setDouble(mMetricsHandle, kCodecFramerateDesired, m.desiredFrameRate);
            mediametrics_setDouble(mMetricsHandle, kCodecFramerateActual, m.actualFrameRate);
        }
        if (m.freezeDurationMsHistogram.getCount() >= 1) {
            const MediaHistogram &histogram = m.freezeDurationMsHistogram;
            mediametrics_setInt64(mMetricsHandle, kCodecFreezeCount, histogram.getCount());
            mediametrics_setInt64(mMetricsHandle, kCodecFreezeDurationAverage, histogram.getAvg());
            mediametrics_setInt64(mMetricsHandle, kCodecFreezeDurationMax, histogram.getMax());
            mediametrics_setString(mMetricsHandle, kCodecFreezeDurationHistogram, histogram.emit());
        }
        if (m.freezeDistanceMsHistogram.getCount() >= 1) {
            const MediaHistogram &histogram = m.freezeDistanceMsHistogram;
            mediametrics_setInt64(mMetricsHandle, kCodecFreezeDistanceAverage, histogram.getAvg());
            mediametrics_setString(mMetricsHandle, kCodecFreezeDistanceHistogram, histogram.emit());
        }
    }

    if (mLatencyHist.getCount() != 0 ) {
        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
        mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -1111,7 +1152,7 @@ void MediaCodec::updateMediametrics() {
    if (mLatencyUnknown > 0) {
        mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
    }
    int64_t playbackDurationSec = mPlaybackDurationAccumulator->getDurationInSeconds();
    int64_t playbackDurationSec = mPlaybackDurationAccumulator.getDurationInSeconds();
    if (playbackDurationSec > 0) {
        mediametrics_setInt64(mMetricsHandle, kCodecPlaybackDurationSec, playbackDurationSec);
    }
@@ -1302,7 +1343,7 @@ void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
        return;
    }

    Histogram recentHist;
    MediaHistogram recentHist;

    // build an empty histogram
    recentHist.setup(kLatencyHistBuckets, kLatencyHistWidth, kLatencyHistFloor);
@@ -1436,116 +1477,34 @@ void MediaCodec::updateTunnelPeek(const sp<AMessage> &msg) {
    ALOGV("TunnelPeekState: %s -> %s", asString(previousState), asString(mTunnelPeekState));
}

void MediaCodec::updatePlaybackDuration(const sp<AMessage> &msg) {
void MediaCodec::processRenderedFrames(const sp<AMessage> &msg) {
    int what = 0;
    msg->findInt32("what", &what);
    if (msg->what() != kWhatCodecNotify && what != kWhatOutputFramesRendered) {
        static bool logged = false;
        if (!logged) {
            logged = true;
            ALOGE("updatePlaybackDuration: expected kWhatOuputFramesRendered (%d)", msg->what());
        }
        return;
            ALOGE("processRenderedFrames: expected kWhatOutputFramesRendered (%d)", msg->what());
        }
    // Playback duration only counts if the buffers are going to the screen.
    if (!mIsSurfaceToScreen) {
        return;
    }
    // Rendered frames only matter if they're being sent to the display
    if (mIsSurfaceToDisplay) {
        int64_t renderTimeNs;
    size_t index = 0;
    while (msg->findInt64(AStringPrintf("%zu-system-nano", index++).c_str(), &renderTimeNs)) {
        mPlaybackDurationAccumulator->processRenderTime(renderTimeNs);
    }
}

bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor)
{
    if (nbuckets <= 0 || width <= 0) {
        return false;
    }

    // get histogram buckets
    if (nbuckets == mBucketCount && mBuckets != NULL) {
        // reuse our existing buffer
        memset(mBuckets, 0, sizeof(*mBuckets) * mBucketCount);
    } else {
        // get a new pre-zeroed buffer
        int64_t *newbuckets = (int64_t *)calloc(nbuckets, sizeof (*mBuckets));
        if (newbuckets == NULL) {
            goto bad;
        }
        if (mBuckets != NULL)
            free(mBuckets);
        mBuckets = newbuckets;
    }

    mWidth = width;
    mFloor = floor;
    mCeiling = floor + nbuckets * width;
    mBucketCount = nbuckets;

    mMin = INT64_MAX;
    mMax = INT64_MIN;
    mSum = 0;
    mCount = 0;
    mBelow = mAbove = 0;

    return true;

  bad:
    if (mBuckets != NULL) {
        free(mBuckets);
        mBuckets = NULL;
    }

    return false;
}

void MediaCodec::Histogram::insert(int64_t sample)
{
    // histogram is not set up
    if (mBuckets == NULL) {
        return;
    }

    mCount++;
    mSum += sample;
    if (mMin > sample) mMin = sample;
    if (mMax < sample) mMax = sample;

    if (sample < mFloor) {
        mBelow++;
    } else if (sample >= mCeiling) {
        mAbove++;
    } else {
        int64_t slot = (sample - mFloor) / mWidth;
        CHECK(slot < mBucketCount);
        mBuckets[slot]++;
    }
    return;
        for (size_t index = 0;
            msg->findInt64(AStringPrintf("%zu-system-nano", index).c_str(), &renderTimeNs);
            index++) {
            // Capture metrics for playback duration
            mPlaybackDurationAccumulator.onFrameRendered(renderTimeNs);
            // Capture metrics for quality
            int64_t mediaTimeUs = 0;
            if (!msg->findInt64(AStringPrintf("%zu-media-time-us", index).c_str(), &mediaTimeUs)) {
                ALOGE("processRenderedFrames: no media time found");
                continue;
            }

std::string MediaCodec::Histogram::emit()
{
    std::string value;
    char buffer[64];

    // emits:  width,Below{bucket0,bucket1,...., bucketN}above
    // unconfigured will emit: 0,0{}0
    // XXX: is this best representation?
    snprintf(buffer, sizeof(buffer), "%" PRId64 ",%" PRId64 ",%" PRId64 "{",
             mFloor, mWidth, mBelow);
    value = buffer;
    for (int i = 0; i < mBucketCount; i++) {
        if (i != 0) {
            value = value + ",";
            mVideoRenderQualityTracker.onFrameRendered(mediaTimeUs, renderTimeNs);
        }
        snprintf(buffer, sizeof(buffer), "%" PRId64, mBuckets[i]);
        value = value + buffer;
    }
    snprintf(buffer, sizeof(buffer), "}%" PRId64 , mAbove);
    value = value + buffer;
    return value;
}

// when we send a buffer to the codec;
@@ -3964,7 +3923,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                asString(previousState),
                                asString(TunnelPeekState::kBufferRendered));
                    }
                    updatePlaybackDuration(msg);
                    processRenderedFrames(msg);
                    // check that we have a notification set
                    if (mOnFrameRenderedNotification != NULL) {
                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
@@ -4158,6 +4117,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                              mState, stateString(mState).c_str());
                        break;
                    }

                    if (mIsSurfaceToDisplay) {
                        mVideoRenderQualityTracker.resetForDiscontinuity();
                    }
                    // Notify the RM that the codec has been stopped.
                    ClientConfigParcel clientConfig;
                    initClientConfigParcel(clientConfig);
@@ -4213,6 +4176,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        break;
                    }

                    if (mIsSurfaceToDisplay) {
                        mVideoRenderQualityTracker.resetForDiscontinuity();
                    }

                    if (mFlags & kFlagIsAsync) {
                        setState(FLUSHED);
                    } else {
@@ -5927,7 +5894,9 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {

        // If rendering to the screen, then schedule a time in the future to poll to see if this
        // frame was ever rendered to seed onFrameRendered callbacks.
        if (mIsSurfaceToScreen) {
        if (mIsSurfaceToDisplay) {
            noRenderTime ? mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs)
                         : mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs, renderTimeNs);
            // can't initialize this in the constructor because the Looper parent class needs to be
            // initialized first
            if (mMsgPollForRenderedBuffers == nullptr) {
@@ -5957,6 +5926,11 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
            ALOGI("rendring output error %d", err);
        }
    } else {
        if (mIsSurfaceToDisplay) {
            int64_t mediaTimeUs = -1;
            buffer->meta()->findInt64("timeUs", &mediaTimeUs);
            mVideoRenderQualityTracker.onFrameSkipped(mediaTimeUs);
        }
        mBufferChannel->discardBuffer(buffer);
    }

@@ -6023,7 +5997,7 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {

        // in case we don't connect, ensure that we don't signal the surface is
        // connected to the screen
        mIsSurfaceToScreen = false;
        mIsSurfaceToDisplay = false;

        err = nativeWindowConnect(surface.get(), "connectToSurface");
        if (err == OK) {
@@ -6053,7 +6027,7 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
            // keep track whether or not the buffers of the connected surface go to the screen
            int result = 0;
            surface->query(NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &result);
            mIsSurfaceToScreen = result != 0;
            mIsSurfaceToDisplay = result != 0;
        }
    }
    // do not return ALREADY_EXISTS unless surfaces are the same
@@ -6071,7 +6045,7 @@ status_t MediaCodec::disconnectFromSurface() {
        }
        // assume disconnected even on error
        mSurface.clear();
        mIsSurfaceToScreen = false;
        mIsSurfaceToDisplay = false;
    }
    return err;
}
Loading