How can I get rendered frames statistics (drawn/dropped) from StageFright Media Framework?
I'm very newbie in Android world and I 开发者_开发百科have to write an streaming video quality checker application on Android. I have to use the native StageFright media framework to play videos. As far as I understand there is an native API of render statistics, but I need advice how I can get it. Thank you.
There is an ADB command to print playback framerate.
Procedure
Open console on windows (or linux) on the host. Make sure that required drivers have been installed for USB connectivity with the device (android phone or board)
Run the following commands
$> adb kill-server
$> adb shell setprop debug.video.showfps 1
Run the video playback. If the video is being run using Android Media player stack, then you will see prints reporting frame rate achieved.
You're welcome to use this as well, call it at the beginning and end of each frame rendered. It's a slightly altered version of some sample code from the NDK:
stats.c:
#include <sys/time.h>
#include <string.h>
#include <android/log.h>
#include <stdio.h>
#include "stats.h"
#define LOG_TAG "[STATS]"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define STATS_DUMP(...) __android_
double now_ms()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000. + tv.tv_usec/1000.;
}
void stats_init(Stats* s)
{
s->lastTime = now_ms();
s->firstTime = 0.;
s->firstFrame = 0;
s->numFrames = 0;
s->dump = malloc(128);
memset(s->dump,0,128);
}
void stats_startFrame(Stats* s)
{
s->frameTime = now_ms();
}
void stats_endFrame(Stats* s)
{
double now = now_ms();
double renderTime = now - s->frameTime;
double frameTime = now - s->lastTime;
int nn;
if (now - s->firstTime >= MAX_PERIOD_MS) {
if (s->numFrames > 0) {
double renderTime = now - s->frameTime;
double frameTime = now - s->lastTime;
int nn;
double minRender, maxRender, avgRender;
double minFrame, maxFrame, avgFrame;
int count;
nn = s->firstFrame;
minRender = maxRender = avgRender = s->frames[nn].renderTime;
minFrame = maxFrame = avgFrame = s->frames[nn].frameTime;
for (count = s->numFrames; count > 0; count-- ) {
nn += 1;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS;
double render = s->frames[nn].renderTime;
if (render < minRender) minRender = render;
if (render > maxRender) maxRender = render;
double frame = s->frames[nn].frameTime;
if (frame < minFrame) minFrame = frame;
if (frame > maxFrame) maxFrame = frame;
avgRender += render;
avgFrame += frame;
}
avgRender /= s->numFrames;
avgFrame /= s->numFrames;
sprintf(s->dump,"Frames per second - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]Rendering time ms - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]", 1000./avgFrame, 1000./maxFrame, 1000./minFrame, avgRender, minRender, maxRender);
//LOGI("Frames per second - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]Rendering time ms - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]", 1000./avgFrame, 1000./maxFrame, 1000./minFrame, avgRender, minRender, maxRender);
}
s->numFrames = 0;
s->firstFrame = 0;
s->firstTime = now;
}
nn = s->firstFrame + s->numFrames;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS;
s->frames[nn].renderTime = renderTime;
s->frames[nn].frameTime = frameTime;
if (s->numFrames < MAX_FRAME_STATS) {
s->numFrames += 1;
} else {
s->firstFrame += 1;
if (s->firstFrame >= MAX_FRAME_STATS)
s->firstFrame -= MAX_FRAME_STATS;
}
s->lastTime = now;
}
stats.h:
#include <jni.h>
#define MAX_FRAME_STATS 120
#define MAX_PERIOD_MS 5000
typedef struct{
double renderTime;
double frameTime;
} FrameStats;
typedef struct{
double firstTime;
double lastTime;
double frameTime;
int firstFrame;
int numFrames;
FrameStats frames[ MAX_FRAME_STATS ];
char* dump;
} Stats;
extern double now_ms();
extern void stats_init(Stats *);
extern int stats_dump(Stats *);
extern void stats_startFrame(Stats *);
extern void stats_endFrame(Stats *);
精彩评论