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

Commit d4d00616 authored by Ray Essick's avatar Ray Essick
Browse files

Initial Metrics for Media.player

First round of logging metrics for media player. This marks
mime types, resolution, frames/time played, duration of media.
Expect more data in the future.

Bug: 33547820
Test: run player, observe captured log
Change-Id: I7bbfaf19e44113f4f285edb72f099b725beace72
parent 32a5f5d5
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "NuPlayer"

#include <inttypes.h>

#include <utils/Log.h>

#include "NuPlayer.h"
@@ -1287,6 +1290,8 @@ void NuPlayer::onResume() {
    } else {
        ALOGW("resume called when renderer is gone or not set");
    }

    mLastStartedPlayingTimeNs = systemTime();
}

status_t NuPlayer::onInstantiateSecureDecoders() {
@@ -1396,6 +1401,8 @@ void NuPlayer::onStart(int64_t startPositionUs, MediaPlayerSeekMode mode) {
        mAudioDecoder->setRenderer(mRenderer);
    }

    mLastStartedPlayingTimeNs = systemTime();

    postScanSources();
}

@@ -1414,6 +1421,16 @@ void NuPlayer::onPause() {
    } else {
        ALOGW("pause called when renderer is gone or not set");
    }

    sp<NuPlayerDriver> driver = mDriver.promote();
    if (driver != NULL) {
        int64_t now = systemTime();
        int64_t played = now - mLastStartedPlayingTimeNs;
        ALOGD("played from %" PRId64 " to %" PRId64 " = %" PRId64 ,
              mLastStartedPlayingTimeNs, now, played);

        driver->notifyMorePlayingTimeUs((played+500)/1000);
    }
}

bool NuPlayer::audioDecoderStillNeeded() {
+2 −0
Original line number Diff line number Diff line
@@ -158,6 +158,8 @@ private:
    int32_t mVideoDecoderGeneration;
    int32_t mRendererGeneration;

    int64_t mLastStartedPlayingTimeNs;

    int64_t mPreviousSeekTimeUs;

    List<sp<Action> > mDeferredActions;
+119 −0
Original line number Diff line number Diff line
@@ -31,8 +31,11 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>

#include <media/IMediaAnalyticsService.h>

namespace android {


NuPlayerDriver::NuPlayerDriver(pid_t pid)
    : mState(STATE_IDLE),
      mIsAsyncPrepare(false),
@@ -41,14 +44,20 @@ NuPlayerDriver::NuPlayerDriver(pid_t pid)
      mDurationUs(-1),
      mPositionUs(-1),
      mSeekInProgress(false),
      mPlayingTimeUs(0),
      mLooper(new ALooper),
      mPlayerFlags(0),
      mAnalyticsItem(NULL),
      mAtEOS(false),
      mLooping(false),
      mAutoLoop(false) {
    ALOGV("NuPlayerDriver(%p)", this);
    mLooper->setName("NuPlayerDriver Looper");

    // set up an analytics record
    mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
    mAnalyticsItem->generateSessionID();

    mLooper->start(
            false, /* runOnCallingThread */
            true,  /* canCallJava */
@@ -63,6 +72,15 @@ NuPlayerDriver::NuPlayerDriver(pid_t pid)
NuPlayerDriver::~NuPlayerDriver() {
    ALOGV("~NuPlayerDriver(%p)", this);
    mLooper->stop();

    // finalize any pending metrics, usually a no-op.
    finalizeMetrics("destructor");
    logMetrics("destructor");

    if (mAnalyticsItem != NULL) {
        delete mAnalyticsItem;
        mAnalyticsItem = NULL;
    }
}

status_t NuPlayerDriver::initCheck() {
@@ -450,8 +468,103 @@ status_t NuPlayerDriver::getDuration(int *msec) {
    return OK;
}

void NuPlayerDriver::finalizeMetrics(const char *where) {
    if (where == NULL) {
        where = "unknown";
    }
    ALOGD("finalizeMetrics(%p) from %s at state %d", this, where, mState);

    // gather the final stats for this record
    Vector<sp<AMessage>> trackStats;
    mPlayer->getStats(&trackStats);

    if (trackStats.size() > 0) {
        for (size_t i = 0; i < trackStats.size(); ++i) {
            const sp<AMessage> &stats = trackStats.itemAt(i);

            AString mime;
            stats->findString("mime", &mime);

            AString name;
            stats->findString("component-name", &name);

            if (mime.startsWith("video/")) {
                int32_t width, height;
                mAnalyticsItem->setCString("video/mime", mime.c_str());
                if (!name.empty()) {
                    mAnalyticsItem->setCString("video/codec", name.c_str());
                }

                if (stats->findInt32("width", &width)
                        && stats->findInt32("height", &height)) {
                    mAnalyticsItem->setInt32("wid", width);
                    mAnalyticsItem->setInt32("ht", height);
                }

                int64_t numFramesTotal = 0;
                int64_t numFramesDropped = 0;
                stats->findInt64("frames-total", &numFramesTotal);
                stats->findInt64("frames-dropped-output", &numFramesDropped);

                mAnalyticsItem->setInt64("frames", numFramesTotal);
                mAnalyticsItem->setInt64("dropped", numFramesDropped);


            } else if (mime.startsWith("audio/")) {
                mAnalyticsItem->setCString("audio/mime", mime.c_str());
                if (!name.empty()) {
                    mAnalyticsItem->setCString("audio/codec", name.c_str());
                }
            }
        }

        // getDuration() uses mLock for mutex -- careful where we use it.
        int duration_ms = -1;
        getDuration(&duration_ms);
        if (duration_ms != -1) {
            mAnalyticsItem->setInt64("duration", duration_ms);
        }

        if (mPlayingTimeUs > 0) {
            mAnalyticsItem->setInt64("playing", (mPlayingTimeUs+500)/1000 );
        }
    }
}


void NuPlayerDriver::logMetrics(const char *where) {
    if (where == NULL) {
        where = "unknown";
    }
    ALOGD("logMetrics(%p) from %s at state %d", this, where, mState);

    if (mAnalyticsItem == NULL || mAnalyticsItem->isEnabled() == false) {
        return;
    }

    // only bother to log non-empty records
    if (mAnalyticsItem->count() > 0) {

        mAnalyticsItem->setFinalized(true);
        mAnalyticsItem->selfrecord();

        // re-init in case we prepare() and start() again.
        delete mAnalyticsItem ;
        mAnalyticsItem = new MediaAnalyticsItem("nuplayer");
        if (mAnalyticsItem) {
            mAnalyticsItem->generateSessionID();
        }
    } else {
        ALOGV("did not have anything to record");
    }
}

status_t NuPlayerDriver::reset() {
    ALOGD("reset(%p) at state %d", this, mState);

    finalizeMetrics("reset");
    logMetrics("reset");

    Mutex::Autolock autoLock(mLock);

    switch (mState) {
@@ -493,6 +606,7 @@ status_t NuPlayerDriver::reset() {
    mDurationUs = -1;
    mPositionUs = -1;
    mLooping = false;
    mPlayingTimeUs = 0;

    return OK;
}
@@ -624,6 +738,11 @@ void NuPlayerDriver::notifyDuration(int64_t durationUs) {
    mDurationUs = durationUs;
}

void NuPlayerDriver::notifyMorePlayingTimeUs(int64_t playingUs) {
    Mutex::Autolock autoLock(mLock);
    mPlayingTimeUs += playingUs;
}

void NuPlayerDriver::notifySeekComplete() {
    ALOGV("notifySeekComplete(%p)", this);
    Mutex::Autolock autoLock(mLock);
+8 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <media/MediaPlayerInterface.h>

#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABase.h>

namespace android {
@@ -75,6 +76,7 @@ struct NuPlayerDriver : public MediaPlayerInterface {
    void notifyResetComplete();
    void notifySetSurfaceComplete();
    void notifyDuration(int64_t durationUs);
    void notifyMorePlayingTimeUs(int64_t timeUs);
    void notifySeekComplete();
    void notifySeekComplete_l();
    void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
@@ -112,6 +114,7 @@ private:
    int64_t mDurationUs;
    int64_t mPositionUs;
    bool mSeekInProgress;
    int64_t mPlayingTimeUs;
    // <<<

    sp<ALooper> mLooper;
@@ -119,10 +122,15 @@ private:
    sp<AudioSink> mAudioSink;
    uint32_t mPlayerFlags;

    MediaAnalyticsItem *mAnalyticsItem;

    bool mAtEOS;
    bool mLooping;
    bool mAutoLoop;

    void finalizeMetrics(const char *where);
    void logMetrics(const char *where);

    status_t prepare_l();
    status_t start_l();
    void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);