Loading include/media/stagefright/ExtendedStats.h +19 −98 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ #define STATS_PROFILE_SET_CAMERA_SOURCE "Set camera source" #define STATS_PROFILE_SET_ENCODER(isVideo) (isVideo != 0 ? "Set video encoder" : "Set audio encoder") #define STATS_PROFILE_STOP "Stop" #define STATS_BITRATE "Video Bitrate" namespace android { Loading Loading @@ -79,6 +80,7 @@ public: virtual ~LogEntry() { mData = 0;} virtual void insert(statsDataType) { } virtual void dump(const char* label) const; virtual void reset() {mData = 0;} inline statsDataType data() const { return mData; } protected: statsDataType mData; Loading @@ -92,14 +94,9 @@ public: // Supported evaluations (and hence possible variants of 'LogEntry's) enum LogType { TOTAL = 1 << 0, AVERAGE = 1 << 1, AVERAGE = 1 << 0, MOVING_AVERAGE = 1 << 1, PROFILE = 1 << 2, ARCHIVE = 1 << 3, MAX = 1 << 4, MIN = 1 << 5, }; enum { Loading @@ -109,89 +106,7 @@ public: }; static const size_t kMaxStringLength = 1024; struct StatsFrameInfo { StatsFrameInfo(); int64_t size; int64_t timestamp; }; /* struct used to wrap a StatsFrameInfo* for use with * a SortedVector */ struct StatsFrameInfoWrapper { StatsFrameInfoWrapper(StatsFrameInfo* oInfoPtr); StatsFrameInfoWrapper(const StatsFrameInfoWrapper& copy); StatsFrameInfo* infoPtr; inline bool operator < (const StatsFrameInfoWrapper& rhs) const { if (!infoPtr || !rhs.infoPtr) return false; return infoPtr->timestamp < (rhs.infoPtr)->timestamp; } explicit StatsFrameInfoWrapper() : infoPtr(NULL) {} }; /* used to keep a "pool" of allocated StatsFrameInfo* * to reduce number of allocations */ struct StatsFrameInfoPool { //retrieve from pool; will dynamically create new obj if empty StatsFrameInfo* get(); //add back into pool void add(StatsFrameInfo* info); //frees everything in the pool void clear(); ~StatsFrameInfoPool(); private: Vector<StatsFrameInfo*> pool; uint32_t numAllocated; }; /* Stores StatsFrameInfoWrapper objects such that * all frames are bounded by timestamps between MAX_TIME_US and * MIN_TIME_US. As more frames are added, frames with * older timestamps are put back into the pool. * Also keeps track of the max bitrate encountered * and the average bitrate throughout. */ struct TimeBoundVector { explicit TimeBoundVector(StatsFrameInfoPool& infoPool); static const int64_t MAX_TIME_US = 120000; static const int64_t MIN_TIME_US = 100000; void clear(); void add(StatsFrameInfoWrapper item); //keeps track of the current bounded sum in the vector int64_t mCurrBoundedSum; //max time-bounded avg int64_t mMaxBoundedAvg; //running total num of buffers seen, used for avg bitrate int64_t mTotalNumBuffers; //running total of buffer sizes, used for avg bitrate int64_t mTotalSizeSum; ~TimeBoundVector(); private: SortedVector<StatsFrameInfoWrapper> mList; StatsFrameInfoPool& mFrameInfoPool; Mutex mLock; }; static const int32_t kMaxWindowSize = 120; struct AutoProfile { AutoProfile(const char* eventName, sp<MediaExtendedStats> mediaExtendedStats = NULL, Loading @@ -209,6 +124,7 @@ public: void log(LogType type, const char* key, statsDataType value, bool condition = true); sp<LogEntry> getLogEntry(const char *key, LogType type); virtual void dump(const char* key = NULL) const; virtual void reset(const char* key) const; static int64_t getSystemTime() { struct timeval tv; Loading @@ -216,7 +132,7 @@ public: return (int64_t)tv.tv_sec * 1E6 + tv.tv_usec; } static sp<LogEntry> createLogEntry(LogType type); static sp<LogEntry> createLogEntry(LogType type, int32_t windowSize); //only profile once, as opposed to up to kMaxOccurrences inline void profileStartOnce(const char* name, bool condition = true) { Loading @@ -235,6 +151,10 @@ public: static MediaExtendedStats* Create(enum StatsType statsType, const char* name, pid_t tid); //wrapper function to set window size. inline void setWindowSize(int32_t windowSize) { mWindowSize = windowSize; } protected: KeyedVector<AString, sp<LogEntry> > mLogEntry; Loading @@ -244,6 +164,7 @@ protected: pid_t mTid; Mutex mLock; int32_t mWindowSize; }; inline ExtendedStats::LogType operator| (ExtendedStats::LogType a, ExtendedStats::LogType b) { Loading @@ -256,12 +177,9 @@ class MediaExtendedStats : public RefBase { public: explicit MediaExtendedStats(const char* name, pid_t tid); //log up to this many video width/height changes static const int32_t MAX_NUM_DIMENSION_CHANGES = 8; void logFrameDropped(); void logDimensions(int32_t width, int32_t height); void logBitRate(int64_t size, int64_t timestamp); void logBitRate(int64_t frameSize, int64_t timestamp); //only profile once, as opposed to up to kMaxOccurrences inline void profileStartOnce(const char* name, bool condition = true) { Loading @@ -286,6 +204,11 @@ public: virtual void notifyPause(int64_t pauseTimeUs) = 0; virtual void dump() = 0; int32_t setFrameRate(int32_t frameRate) { mFrameRate = frameRate; mProfileTimes->setWindowSize(mFrameRate); } protected: AString mName; pid_t mTid; Loading @@ -300,10 +223,8 @@ protected: Vector<int32_t> mWidthDimensions; Vector<int32_t> mHeightDimensions; ExtendedStats::StatsFrameInfoPool mFrameInfoPool; ExtendedStats::TimeBoundVector mBitRateVector; sp<ExtendedStats> mProfileTimes; int32_t mFrameRate; /* helper functions */ void resetConsecutiveFramesDropped(); Loading media/libmediaplayerservice/nuplayer/NuPlayer.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) { mRenderer->setVideoFrameRate(rate); PLAYER_STATS(setFrameRate, rate); } postScanSources(); Loading media/libstagefright/ExtendedStats.cpp +70 −147 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ ExtendedStats::ExtendedStats(const char *id, pid_t tid) { mLogEntry.clear(); mName.setTo(id); mTid = tid; mWindowSize = kMaxWindowSize; } ExtendedStats::~ExtendedStats() { Loading @@ -55,71 +56,75 @@ ExtendedStats::LogEntry::LogEntry() : mData(0) { } ExtendedStats::StatsFrameInfoWrapper::StatsFrameInfoWrapper(const StatsFrameInfoWrapper& copy) { infoPtr = copy.infoPtr; } ExtendedStats::StatsFrameInfoWrapper::StatsFrameInfoWrapper(StatsFrameInfo* oInfoPtr) : infoPtr(oInfoPtr) { } ExtendedStats::StatsFrameInfo::StatsFrameInfo() { size = 0; timestamp = 0; } ExtendedStats::TimeBoundVector::TimeBoundVector(StatsFrameInfoPool& infoPool) : mFrameInfoPool(infoPool) { mCurrBoundedSum = 0; mMaxBoundedAvg = 0; mTotalNumBuffers = 0; mTotalSizeSum = 0; } void ExtendedStats::LogEntry::dump(const char* label) const { ALOGI("%s : %" PRId64 "", label, mData); } struct Min : public ExtendedStats::LogEntry { Min() { mData = INT64_MAX; } void insert(statsDataType value) { if (value < mData) mData = value; } }; struct Max : public ExtendedStats::LogEntry { void insert(statsDataType value) { if (value > mData) mData = value; } }; // Accumulates inserted values struct Total : public ExtendedStats::LogEntry { Total() {} ~Total() {} void insert(statsDataType value) { mData += value; } }; // Accumulates running-average of inserted values // Running-average of inserted values struct Average : public ExtendedStats::LogEntry { void insert(statsDataType value) { mN++; mSum += value; mData = mSum / mN; mRem = mSum % mN; } Average() { mN = 0; mSum = 0; mRem = 0; } int32_t mN; int32_t mSum; int32_t mRem; int64_t mSum; }; // Moving-average of inserted values struct MovingAverage : public ExtendedStats::LogEntry { static const int32_t kMaxWindowSize = ExtendedStats::kMaxWindowSize; void insert(statsDataType value) { Mutex::Autolock lock(mLock); // pipeline is full, drop the tail and pick the head. if (mHead == mTail) { mSum -= mDataPoints[mTail]; mTail = advance(mTail); } mSum += value; mDataPoints[mHead] = value; mCount++; mHead = advance(mHead); mData = mSum / ((mCount > mNWindow) ? mNWindow : mCount); mPeak = (mData > mPeak) ? mData : mPeak; } MovingAverage(int32_t window) { mNWindow = (window < 1) ? 1 : (window > kMaxWindowSize) ? kMaxWindowSize : window; ALOGI("Creating MovingAverage of window size : %d\n", mNWindow); reset(); } void reset() { Mutex::Autolock lock(mLock); mData = 0; mHead = 0; mTail = mNWindow - 1; mSum = 0; mCount = 0; mPeak = 0; memset(mDataPoints, 0x0, sizeof(mDataPoints)); } void dump(const char* label) const { ALOGI("Avg %s : %" PRId64 "", label, mData); ALOGI("Peak %s : %" PRId64 "", label, mPeak); } private: int32_t mNWindow; int32_t mHead; int32_t mTail; int64_t mSum; int64_t mDataPoints[kMaxWindowSize]; int32_t mCount; int32_t mPeak; int32_t advance(int32_t index) { return ++index % mNWindow; } Mutex mLock; }; // Saves inserted values in a bound array Loading Loading @@ -196,18 +201,14 @@ private: //static // LogEntry factory sp<ExtendedStats::LogEntry> ExtendedStats::createLogEntry(LogType type) { sp<ExtendedStats::LogEntry> ExtendedStats::createLogEntry(LogType type, int32_t windowSize) { switch(type) { case TOTAL: return new Total(); case AVERAGE: return new Average(); case PROFILE: return new TimeProfile(); case MAX: return new Max(); case MIN: return new Min(); case MOVING_AVERAGE: return new MovingAverage(windowSize); default: return new LogEntry(); } Loading @@ -224,7 +225,7 @@ sp<ExtendedStats::LogEntry> ExtendedStats::getLogEntry(const char *key, if (idx < 0) { /* keep write access to the KeyedVector thread-safe */ Mutex::Autolock autoLock(mLock); sp<LogEntry> logEntry = createLogEntry(type); sp<LogEntry> logEntry = createLogEntry(type, mWindowSize); mLogEntry.add(key, logEntry); return logEntry; } else { Loading Loading @@ -257,78 +258,13 @@ void ExtendedStats::dump(const char* key) const { } } /* FrameInfoPool methods */ ExtendedStats::StatsFrameInfo* ExtendedStats::StatsFrameInfoPool::get() { if (pool.empty()) { return new StatsFrameInfo(); } else { StatsFrameInfo* info = pool.editTop(); pool.pop(); return info; } } void ExtendedStats::StatsFrameInfoPool::add(StatsFrameInfo* info) { pool.add(info); } void ExtendedStats::StatsFrameInfoPool::clear() { for (uint32_t i = 0; i < pool.size(); i++) { delete pool.editItemAt(i); pool.editItemAt(i) = 0; } pool.clear(); } ExtendedStats::StatsFrameInfoPool::~StatsFrameInfoPool() { clear(); } /* TimeBoundVector methods */ void ExtendedStats::TimeBoundVector::add(StatsFrameInfoWrapper item) { Mutex::Autolock lock(mLock); mList.add(item); mCurrBoundedSum += (item.infoPtr)->size; mTotalSizeSum += (item.infoPtr)->size; mTotalNumBuffers++; StatsFrameInfo* first = mList.itemAt(0).infoPtr; StatsFrameInfo* last = mList.top().infoPtr; // remove as many as needed to get within range while (last->timestamp - first->timestamp > MAX_TIME_US) { mCurrBoundedSum -= first->size; // reclaim it in the pool mFrameInfoPool.add(mList.editItemAt(0).infoPtr); mList.removeAt(0); first = mList.itemAt(0).infoPtr; } // calculate average if we are within the window range if (last->timestamp - first->timestamp > MIN_TIME_US) { int64_t avg = mCurrBoundedSum / mList.size(); if (mMaxBoundedAvg < avg) { mMaxBoundedAvg = avg; } } } void ExtendedStats::TimeBoundVector::clear() { Mutex::Autolock lock(mLock); for (uint32_t i = 0; i < mList.size(); i++) { delete mList.editItemAt(i).infoPtr; mList.editItemAt(i).infoPtr = 0; void ExtendedStats::reset(const char* key) const { if (key) { ssize_t idx = mLogEntry.indexOfKey(key); if (idx >= 0) { mLogEntry.valueAt(idx)->reset(); } mList.clear(); mCurrBoundedSum = 0; } ExtendedStats::TimeBoundVector::~TimeBoundVector() { clear(); } ExtendedStats::AutoProfile::AutoProfile( Loading Loading @@ -375,8 +311,7 @@ MediaExtendedStats* ExtendedStats::Create( /***************************** MediaExtendedStats ************************/ MediaExtendedStats::MediaExtendedStats(const char* name, pid_t tid) : mBitRateVector(mFrameInfoPool) { MediaExtendedStats::MediaExtendedStats(const char* name, pid_t tid) { mName = name; mTid = tid; Loading Loading @@ -404,9 +339,7 @@ void MediaExtendedStats::reset() { mWidthDimensions.clear(); mHeightDimensions.clear(); mFrameInfoPool.clear(); mBitRateVector.clear(); mFrameRate = 30; mProfileTimes = new ExtendedStats(mName.c_str(), mTid); } Loading @@ -424,16 +357,11 @@ void MediaExtendedStats::logDimensions(int32_t width, int32_t height) { } } void MediaExtendedStats::logBitRate(int64_t size, int64_t timestamp) { ExtendedStats::StatsFrameInfo* sfInfo = mFrameInfoPool.get(); sfInfo->size = size; sfInfo->timestamp = timestamp; mBitRateVector.add(ExtendedStats::StatsFrameInfoWrapper(sfInfo)); void MediaExtendedStats::logBitRate(int64_t frameSize, int64_t timestamp) { mProfileTimes->log(ExtendedStats::MOVING_AVERAGE, STATS_BITRATE, frameSize, true); } MediaExtendedStats::~MediaExtendedStats() { mBitRateVector.clear(); mFrameInfoPool.clear(); } /***************************** PlayerExtendedStats ************************/ Loading Loading @@ -513,7 +441,6 @@ void PlayerExtendedStats::notifyPause(int64_t pauseTimeUs) { } void PlayerExtendedStats::notifySeek(int64_t seekTimeUs) { mBitRateVector.clear(); notifyPlaying(false); mLastSeekTime = seekTimeUs; } Loading Loading @@ -564,9 +491,8 @@ void PlayerExtendedStats::dump() { ALOGI("Last pause time: %"PRId64" ms", mLastPauseTime/1000); ALOGI("Average FPS: %0.2f", mTotalPlayingTime == 0 ? 0 : mFramesRendered /(mTotalPlayingTime / 1E6)); ALOGI("Peak bitrate: %"PRId64"", mBitRateVector.mMaxBoundedAvg); ALOGI("Average bitrate: %"PRId64"", mBitRateVector.mTotalNumBuffers == 0 ? 0 : mBitRateVector.mTotalSizeSum / mBitRateVector.mTotalNumBuffers); mProfileTimes->dump(STATS_BITRATE); ALOGI("EOS(%d)", mEOS ? 1 : 0); ALOGI("PLAYING(%d)", mPlaying ? 1 : 0); Loading Loading @@ -656,9 +582,6 @@ void RecorderExtendedStats::dump() { ALOGI("Total recording duration: %"PRId64" ms", mTotalRecordingTime/1000); ALOGI("Last pause time: %"PRId64" ms", mLastPauseTime/1000); ALOGI("Input frame rate: %0.2f", mTotalRecordingTime == 0 ? 0 : mFramesEncoded/(mTotalRecordingTime/1E6)); ALOGI("Peak bitrate: %"PRId64"", mBitRateVector.mMaxBoundedAvg); ALOGI("Average bitrate: %"PRId64"", mBitRateVector.mTotalNumBuffers == 0 ? 0 : mBitRateVector.mTotalSizeSum/mBitRateVector.mTotalNumBuffers); ALOGI("------- Profile Latencies --------"); Loading media/libstagefright/OMXCodec.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -1564,6 +1564,11 @@ status_t OMXCodec::setVideoOutputFormat( return err; } //////////////////////////////////////////////////////////////////////////// int32_t frameRate; if (meta->findInt32(kKeyFrameRate, &frameRate)) { PLAYER_STATS(setFrameRate, frameRate); } //////////////////////////////////////////////////////////////////////////// InitOMXParams(&def); Loading Loading
include/media/stagefright/ExtendedStats.h +19 −98 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ #define STATS_PROFILE_SET_CAMERA_SOURCE "Set camera source" #define STATS_PROFILE_SET_ENCODER(isVideo) (isVideo != 0 ? "Set video encoder" : "Set audio encoder") #define STATS_PROFILE_STOP "Stop" #define STATS_BITRATE "Video Bitrate" namespace android { Loading Loading @@ -79,6 +80,7 @@ public: virtual ~LogEntry() { mData = 0;} virtual void insert(statsDataType) { } virtual void dump(const char* label) const; virtual void reset() {mData = 0;} inline statsDataType data() const { return mData; } protected: statsDataType mData; Loading @@ -92,14 +94,9 @@ public: // Supported evaluations (and hence possible variants of 'LogEntry's) enum LogType { TOTAL = 1 << 0, AVERAGE = 1 << 1, AVERAGE = 1 << 0, MOVING_AVERAGE = 1 << 1, PROFILE = 1 << 2, ARCHIVE = 1 << 3, MAX = 1 << 4, MIN = 1 << 5, }; enum { Loading @@ -109,89 +106,7 @@ public: }; static const size_t kMaxStringLength = 1024; struct StatsFrameInfo { StatsFrameInfo(); int64_t size; int64_t timestamp; }; /* struct used to wrap a StatsFrameInfo* for use with * a SortedVector */ struct StatsFrameInfoWrapper { StatsFrameInfoWrapper(StatsFrameInfo* oInfoPtr); StatsFrameInfoWrapper(const StatsFrameInfoWrapper& copy); StatsFrameInfo* infoPtr; inline bool operator < (const StatsFrameInfoWrapper& rhs) const { if (!infoPtr || !rhs.infoPtr) return false; return infoPtr->timestamp < (rhs.infoPtr)->timestamp; } explicit StatsFrameInfoWrapper() : infoPtr(NULL) {} }; /* used to keep a "pool" of allocated StatsFrameInfo* * to reduce number of allocations */ struct StatsFrameInfoPool { //retrieve from pool; will dynamically create new obj if empty StatsFrameInfo* get(); //add back into pool void add(StatsFrameInfo* info); //frees everything in the pool void clear(); ~StatsFrameInfoPool(); private: Vector<StatsFrameInfo*> pool; uint32_t numAllocated; }; /* Stores StatsFrameInfoWrapper objects such that * all frames are bounded by timestamps between MAX_TIME_US and * MIN_TIME_US. As more frames are added, frames with * older timestamps are put back into the pool. * Also keeps track of the max bitrate encountered * and the average bitrate throughout. */ struct TimeBoundVector { explicit TimeBoundVector(StatsFrameInfoPool& infoPool); static const int64_t MAX_TIME_US = 120000; static const int64_t MIN_TIME_US = 100000; void clear(); void add(StatsFrameInfoWrapper item); //keeps track of the current bounded sum in the vector int64_t mCurrBoundedSum; //max time-bounded avg int64_t mMaxBoundedAvg; //running total num of buffers seen, used for avg bitrate int64_t mTotalNumBuffers; //running total of buffer sizes, used for avg bitrate int64_t mTotalSizeSum; ~TimeBoundVector(); private: SortedVector<StatsFrameInfoWrapper> mList; StatsFrameInfoPool& mFrameInfoPool; Mutex mLock; }; static const int32_t kMaxWindowSize = 120; struct AutoProfile { AutoProfile(const char* eventName, sp<MediaExtendedStats> mediaExtendedStats = NULL, Loading @@ -209,6 +124,7 @@ public: void log(LogType type, const char* key, statsDataType value, bool condition = true); sp<LogEntry> getLogEntry(const char *key, LogType type); virtual void dump(const char* key = NULL) const; virtual void reset(const char* key) const; static int64_t getSystemTime() { struct timeval tv; Loading @@ -216,7 +132,7 @@ public: return (int64_t)tv.tv_sec * 1E6 + tv.tv_usec; } static sp<LogEntry> createLogEntry(LogType type); static sp<LogEntry> createLogEntry(LogType type, int32_t windowSize); //only profile once, as opposed to up to kMaxOccurrences inline void profileStartOnce(const char* name, bool condition = true) { Loading @@ -235,6 +151,10 @@ public: static MediaExtendedStats* Create(enum StatsType statsType, const char* name, pid_t tid); //wrapper function to set window size. inline void setWindowSize(int32_t windowSize) { mWindowSize = windowSize; } protected: KeyedVector<AString, sp<LogEntry> > mLogEntry; Loading @@ -244,6 +164,7 @@ protected: pid_t mTid; Mutex mLock; int32_t mWindowSize; }; inline ExtendedStats::LogType operator| (ExtendedStats::LogType a, ExtendedStats::LogType b) { Loading @@ -256,12 +177,9 @@ class MediaExtendedStats : public RefBase { public: explicit MediaExtendedStats(const char* name, pid_t tid); //log up to this many video width/height changes static const int32_t MAX_NUM_DIMENSION_CHANGES = 8; void logFrameDropped(); void logDimensions(int32_t width, int32_t height); void logBitRate(int64_t size, int64_t timestamp); void logBitRate(int64_t frameSize, int64_t timestamp); //only profile once, as opposed to up to kMaxOccurrences inline void profileStartOnce(const char* name, bool condition = true) { Loading @@ -286,6 +204,11 @@ public: virtual void notifyPause(int64_t pauseTimeUs) = 0; virtual void dump() = 0; int32_t setFrameRate(int32_t frameRate) { mFrameRate = frameRate; mProfileTimes->setWindowSize(mFrameRate); } protected: AString mName; pid_t mTid; Loading @@ -300,10 +223,8 @@ protected: Vector<int32_t> mWidthDimensions; Vector<int32_t> mHeightDimensions; ExtendedStats::StatsFrameInfoPool mFrameInfoPool; ExtendedStats::TimeBoundVector mBitRateVector; sp<ExtendedStats> mProfileTimes; int32_t mFrameRate; /* helper functions */ void resetConsecutiveFramesDropped(); Loading
media/libmediaplayerservice/nuplayer/NuPlayer.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -660,6 +660,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { if (meta != NULL && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) { mRenderer->setVideoFrameRate(rate); PLAYER_STATS(setFrameRate, rate); } postScanSources(); Loading
media/libstagefright/ExtendedStats.cpp +70 −147 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ ExtendedStats::ExtendedStats(const char *id, pid_t tid) { mLogEntry.clear(); mName.setTo(id); mTid = tid; mWindowSize = kMaxWindowSize; } ExtendedStats::~ExtendedStats() { Loading @@ -55,71 +56,75 @@ ExtendedStats::LogEntry::LogEntry() : mData(0) { } ExtendedStats::StatsFrameInfoWrapper::StatsFrameInfoWrapper(const StatsFrameInfoWrapper& copy) { infoPtr = copy.infoPtr; } ExtendedStats::StatsFrameInfoWrapper::StatsFrameInfoWrapper(StatsFrameInfo* oInfoPtr) : infoPtr(oInfoPtr) { } ExtendedStats::StatsFrameInfo::StatsFrameInfo() { size = 0; timestamp = 0; } ExtendedStats::TimeBoundVector::TimeBoundVector(StatsFrameInfoPool& infoPool) : mFrameInfoPool(infoPool) { mCurrBoundedSum = 0; mMaxBoundedAvg = 0; mTotalNumBuffers = 0; mTotalSizeSum = 0; } void ExtendedStats::LogEntry::dump(const char* label) const { ALOGI("%s : %" PRId64 "", label, mData); } struct Min : public ExtendedStats::LogEntry { Min() { mData = INT64_MAX; } void insert(statsDataType value) { if (value < mData) mData = value; } }; struct Max : public ExtendedStats::LogEntry { void insert(statsDataType value) { if (value > mData) mData = value; } }; // Accumulates inserted values struct Total : public ExtendedStats::LogEntry { Total() {} ~Total() {} void insert(statsDataType value) { mData += value; } }; // Accumulates running-average of inserted values // Running-average of inserted values struct Average : public ExtendedStats::LogEntry { void insert(statsDataType value) { mN++; mSum += value; mData = mSum / mN; mRem = mSum % mN; } Average() { mN = 0; mSum = 0; mRem = 0; } int32_t mN; int32_t mSum; int32_t mRem; int64_t mSum; }; // Moving-average of inserted values struct MovingAverage : public ExtendedStats::LogEntry { static const int32_t kMaxWindowSize = ExtendedStats::kMaxWindowSize; void insert(statsDataType value) { Mutex::Autolock lock(mLock); // pipeline is full, drop the tail and pick the head. if (mHead == mTail) { mSum -= mDataPoints[mTail]; mTail = advance(mTail); } mSum += value; mDataPoints[mHead] = value; mCount++; mHead = advance(mHead); mData = mSum / ((mCount > mNWindow) ? mNWindow : mCount); mPeak = (mData > mPeak) ? mData : mPeak; } MovingAverage(int32_t window) { mNWindow = (window < 1) ? 1 : (window > kMaxWindowSize) ? kMaxWindowSize : window; ALOGI("Creating MovingAverage of window size : %d\n", mNWindow); reset(); } void reset() { Mutex::Autolock lock(mLock); mData = 0; mHead = 0; mTail = mNWindow - 1; mSum = 0; mCount = 0; mPeak = 0; memset(mDataPoints, 0x0, sizeof(mDataPoints)); } void dump(const char* label) const { ALOGI("Avg %s : %" PRId64 "", label, mData); ALOGI("Peak %s : %" PRId64 "", label, mPeak); } private: int32_t mNWindow; int32_t mHead; int32_t mTail; int64_t mSum; int64_t mDataPoints[kMaxWindowSize]; int32_t mCount; int32_t mPeak; int32_t advance(int32_t index) { return ++index % mNWindow; } Mutex mLock; }; // Saves inserted values in a bound array Loading Loading @@ -196,18 +201,14 @@ private: //static // LogEntry factory sp<ExtendedStats::LogEntry> ExtendedStats::createLogEntry(LogType type) { sp<ExtendedStats::LogEntry> ExtendedStats::createLogEntry(LogType type, int32_t windowSize) { switch(type) { case TOTAL: return new Total(); case AVERAGE: return new Average(); case PROFILE: return new TimeProfile(); case MAX: return new Max(); case MIN: return new Min(); case MOVING_AVERAGE: return new MovingAverage(windowSize); default: return new LogEntry(); } Loading @@ -224,7 +225,7 @@ sp<ExtendedStats::LogEntry> ExtendedStats::getLogEntry(const char *key, if (idx < 0) { /* keep write access to the KeyedVector thread-safe */ Mutex::Autolock autoLock(mLock); sp<LogEntry> logEntry = createLogEntry(type); sp<LogEntry> logEntry = createLogEntry(type, mWindowSize); mLogEntry.add(key, logEntry); return logEntry; } else { Loading Loading @@ -257,78 +258,13 @@ void ExtendedStats::dump(const char* key) const { } } /* FrameInfoPool methods */ ExtendedStats::StatsFrameInfo* ExtendedStats::StatsFrameInfoPool::get() { if (pool.empty()) { return new StatsFrameInfo(); } else { StatsFrameInfo* info = pool.editTop(); pool.pop(); return info; } } void ExtendedStats::StatsFrameInfoPool::add(StatsFrameInfo* info) { pool.add(info); } void ExtendedStats::StatsFrameInfoPool::clear() { for (uint32_t i = 0; i < pool.size(); i++) { delete pool.editItemAt(i); pool.editItemAt(i) = 0; } pool.clear(); } ExtendedStats::StatsFrameInfoPool::~StatsFrameInfoPool() { clear(); } /* TimeBoundVector methods */ void ExtendedStats::TimeBoundVector::add(StatsFrameInfoWrapper item) { Mutex::Autolock lock(mLock); mList.add(item); mCurrBoundedSum += (item.infoPtr)->size; mTotalSizeSum += (item.infoPtr)->size; mTotalNumBuffers++; StatsFrameInfo* first = mList.itemAt(0).infoPtr; StatsFrameInfo* last = mList.top().infoPtr; // remove as many as needed to get within range while (last->timestamp - first->timestamp > MAX_TIME_US) { mCurrBoundedSum -= first->size; // reclaim it in the pool mFrameInfoPool.add(mList.editItemAt(0).infoPtr); mList.removeAt(0); first = mList.itemAt(0).infoPtr; } // calculate average if we are within the window range if (last->timestamp - first->timestamp > MIN_TIME_US) { int64_t avg = mCurrBoundedSum / mList.size(); if (mMaxBoundedAvg < avg) { mMaxBoundedAvg = avg; } } } void ExtendedStats::TimeBoundVector::clear() { Mutex::Autolock lock(mLock); for (uint32_t i = 0; i < mList.size(); i++) { delete mList.editItemAt(i).infoPtr; mList.editItemAt(i).infoPtr = 0; void ExtendedStats::reset(const char* key) const { if (key) { ssize_t idx = mLogEntry.indexOfKey(key); if (idx >= 0) { mLogEntry.valueAt(idx)->reset(); } mList.clear(); mCurrBoundedSum = 0; } ExtendedStats::TimeBoundVector::~TimeBoundVector() { clear(); } ExtendedStats::AutoProfile::AutoProfile( Loading Loading @@ -375,8 +311,7 @@ MediaExtendedStats* ExtendedStats::Create( /***************************** MediaExtendedStats ************************/ MediaExtendedStats::MediaExtendedStats(const char* name, pid_t tid) : mBitRateVector(mFrameInfoPool) { MediaExtendedStats::MediaExtendedStats(const char* name, pid_t tid) { mName = name; mTid = tid; Loading Loading @@ -404,9 +339,7 @@ void MediaExtendedStats::reset() { mWidthDimensions.clear(); mHeightDimensions.clear(); mFrameInfoPool.clear(); mBitRateVector.clear(); mFrameRate = 30; mProfileTimes = new ExtendedStats(mName.c_str(), mTid); } Loading @@ -424,16 +357,11 @@ void MediaExtendedStats::logDimensions(int32_t width, int32_t height) { } } void MediaExtendedStats::logBitRate(int64_t size, int64_t timestamp) { ExtendedStats::StatsFrameInfo* sfInfo = mFrameInfoPool.get(); sfInfo->size = size; sfInfo->timestamp = timestamp; mBitRateVector.add(ExtendedStats::StatsFrameInfoWrapper(sfInfo)); void MediaExtendedStats::logBitRate(int64_t frameSize, int64_t timestamp) { mProfileTimes->log(ExtendedStats::MOVING_AVERAGE, STATS_BITRATE, frameSize, true); } MediaExtendedStats::~MediaExtendedStats() { mBitRateVector.clear(); mFrameInfoPool.clear(); } /***************************** PlayerExtendedStats ************************/ Loading Loading @@ -513,7 +441,6 @@ void PlayerExtendedStats::notifyPause(int64_t pauseTimeUs) { } void PlayerExtendedStats::notifySeek(int64_t seekTimeUs) { mBitRateVector.clear(); notifyPlaying(false); mLastSeekTime = seekTimeUs; } Loading Loading @@ -564,9 +491,8 @@ void PlayerExtendedStats::dump() { ALOGI("Last pause time: %"PRId64" ms", mLastPauseTime/1000); ALOGI("Average FPS: %0.2f", mTotalPlayingTime == 0 ? 0 : mFramesRendered /(mTotalPlayingTime / 1E6)); ALOGI("Peak bitrate: %"PRId64"", mBitRateVector.mMaxBoundedAvg); ALOGI("Average bitrate: %"PRId64"", mBitRateVector.mTotalNumBuffers == 0 ? 0 : mBitRateVector.mTotalSizeSum / mBitRateVector.mTotalNumBuffers); mProfileTimes->dump(STATS_BITRATE); ALOGI("EOS(%d)", mEOS ? 1 : 0); ALOGI("PLAYING(%d)", mPlaying ? 1 : 0); Loading Loading @@ -656,9 +582,6 @@ void RecorderExtendedStats::dump() { ALOGI("Total recording duration: %"PRId64" ms", mTotalRecordingTime/1000); ALOGI("Last pause time: %"PRId64" ms", mLastPauseTime/1000); ALOGI("Input frame rate: %0.2f", mTotalRecordingTime == 0 ? 0 : mFramesEncoded/(mTotalRecordingTime/1E6)); ALOGI("Peak bitrate: %"PRId64"", mBitRateVector.mMaxBoundedAvg); ALOGI("Average bitrate: %"PRId64"", mBitRateVector.mTotalNumBuffers == 0 ? 0 : mBitRateVector.mTotalSizeSum/mBitRateVector.mTotalNumBuffers); ALOGI("------- Profile Latencies --------"); Loading
media/libstagefright/OMXCodec.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -1564,6 +1564,11 @@ status_t OMXCodec::setVideoOutputFormat( return err; } //////////////////////////////////////////////////////////////////////////// int32_t frameRate; if (meta->findInt32(kKeyFrameRate, &frameRate)) { PLAYER_STATS(setFrameRate, frameRate); } //////////////////////////////////////////////////////////////////////////// InitOMXParams(&def); Loading