发现835手机外接1080p@60摄像头时,帧率不稳定(burst)。现象是如果统计一千帧,帧率是60fps,但是如果打印两帧之间的间隔,发现有时候间隔是3毫秒,有时是9ms。这样导致UI处理不过来,而Android GraphicBuffer在queueBuffer时,最多只能缓存一帧,而丢弃前面的帧
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
................................................
sp<IConsumerListener> frameAvailableListener;
sp<IConsumerListener> frameReplacedListener;
int callbackTicket = 0;
uint64_t currentFrameNumber = 0;
BufferItem item;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
.........................................
output->bufferReplaced = false;
if (mCore->mQueue.empty()) {
// When the queue is empty, we can ignore mDequeueBufferCannotBlock
// and simply queue this buffer
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
// When the queue is not empty, we need to look at the last buffer
// in the queue to see if we need to replace it
const BufferItem& last = mCore->mQueue.itemAt(
mCore->mQueue.size() - 1);
if (last.mIsDroppable) {
if (!last.mIsStale) {
mSlots[last.mSlot].mBufferState.freeQueued();
// After leaving shared buffer mode, the shared buffer will
// still be around. Mark it as no longer shared if this
// operation causes it to be free.
if (!mCore->mSharedBufferMode &&
mSlots[last.mSlot].mBufferState.isFree()) {
mSlots[last.mSlot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list.
if (!mSlots[last.mSlot].mBufferState.isShared()) {
mCore->mActiveBuffers.erase(last.mSlot);
mCore->mFreeBuffers.push_back(last.mSlot);
output->bufferReplaced = true;
}
}
// Overwrite the droppable buffer with the incoming one
mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
}
}
。。。。。。。。。。。。。。。。。。。。。
VALIDATE_CONSISTENCY();
} // Autolock scope
。。。。。。。。。。。。。。。。
return NO_ERROR;
}
为了避免这个问题,只好增加延时,在一个队列中先缓存3帧,然后每隔16.66毫秒,送出一帧。这样保证了帧率,但是增加了50毫秒的延时。
Linux提供了一个高精度的定时器timer_create,代码如下。一秒钟打印60次
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
static int times = 1;
unsigned int lastTime;
unsigned int RealTimeInMilliseconds() {
struct timespec spec;
clock_gettime(CLOCK_REALTIME, &spec);
return spec.tv_sec * 1000 + spec.tv_nsec / 1000000;
}
//Thread function to be invoked when the periodic timer expires
void sighler (union sigval val)
{
unsigned int now = RealTimeInMilliseconds();
printf("Time Diff: %u Count: %d\n", now - lastTime, times++);
lastTime = now;
}
int main()
{
int Ret;
pthread_attr_t attr;
pthread_attr_init( &attr );
struct sched_param parm;
parm.sched_priority = 0;
pthread_attr_setschedparam(&attr, &parm);
struct sigevent sig;
sig.sigev_notify = SIGEV_THREAD;
sig.sigev_notify_function = sighler;
sig.sigev_value.sival_int =20;
sig.sigev_notify_attributes = &attr;
//create a new timer.
timer_t timerid;
Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
if (Ret == 0)
{
struct itimerspec in, out;
in.it_value.tv_sec = 0;
in.it_value.tv_nsec = 16666666;
in.it_interval.tv_sec = 0;
in.it_interval.tv_nsec = 16666666;
//issue the periodic timer request here.
lastTime = RealTimeInMilliseconds();
Ret = timer_settime(timerid, 0, &in, &out);
if(Ret == 0)
sleep(1);
else
printf("timer_settime() failed with %d\n", errno);
//delete the timer.
timer_delete(timerid);
}
else
printf("timer_create() failed with %d\n", errno);
return Ret;
}
打印输出如下:
Time Diff: 17 Count: 1
Time Diff: 16 Count: 2
Time Diff: 17 Count: 3
Time Diff: 17 Count: 4
Time Diff: 16 Count: 5
Time Diff: 17 Count: 6
Time Diff: 17 Count: 7
Time Diff: 16 Count: 8
Time Diff: 17 Count: 9
Time Diff: 17 Count: 10
Time Diff: 16 Count: 11
Time Diff: 17 Count: 12
Time Diff: 17 Count: 13
Time Diff: 16 Count: 14
Time Diff: 17 Count: 15
Time Diff: 17 Count: 16
Time Diff: 16 Count: 17
Time Diff: 17 Count: 18
Time Diff: 17 Count: 19
Time Diff: 16 Count: 20
Time Diff: 17 Count: 21
Time Diff: 17 Count: 22
Time Diff: 16 Count: 23
Time Diff: 17 Count: 24
Time Diff: 17 Count: 25
Time Diff: 16 Count: 26
Time Diff: 17 Count: 27
Time Diff: 17 Count: 28
Time Diff: 16 Count: 29
Time Diff: 17 Count: 30
Time Diff: 17 Count: 31
Time Diff: 16 Count: 32
Time Diff: 17 Count: 33
Time Diff: 17 Count: 34
Time Diff: 16 Count: 35
Time Diff: 17 Count: 36
Time Diff: 17 Count: 37
Time Diff: 16 Count: 38
Time Diff: 17 Count: 39
Time Diff: 17 Count: 40
Time Diff: 16 Count: 41
Time Diff: 17 Count: 42
Time Diff: 17 Count: 43
Time Diff: 16 Count: 44
Time Diff: 17 Count: 45
Time Diff: 17 Count: 46
Time Diff: 16 Count: 47
Time Diff: 17 Count: 48
Time Diff: 17 Count: 49
Time Diff: 16 Count: 50
Time Diff: 17 Count: 51
Time Diff: 17 Count: 52
Time Diff: 16 Count: 53
Time Diff: 17 Count: 54
Time Diff: 17 Count: 55
Time Diff: 16 Count: 56
Time Diff: 17 Count: 57
Time Diff: 17 Count: 58
Time Diff: 16 Count: 59
Time Diff: 17 Count: 60
版权声明:本文为wanghuasn911原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。