MediaCodec编码摄像头数据时控制帧率的方法

控制帧率

一般而言,使用MediaCodec配合OpenGLES编码摄像头数据是常规做法。如果要限制帧率,最简单的方法是限制OpenGLES的绘制间隔时间。

假设使用GLSurfaceView进行绘制,设置RenderMode为RENDERMODE_WHEN_DIRTY,在SurfaceTexture监听onFrameAvailable()来通知GLSurfaceView绘制时,一般手机能达到60FPS。

按照上面的说法,例如要限制到30FPS,只需要在onFrameAvailable()或者onDrawFrame()中加入sleep(),每次绘制后睡眠一定时间,这样预览画面和实际编码出来的MP4将会是同样的30FPS。

注:使用Camera设定预览帧率貌似不起作用,起码在我的华为Mate9 Pro上没有效果。

但是,我希望可以做到预览画面帧率不变,编码时限制FPS,就需要额外启动线程来处理。

由于MediaCodec中使用InputSurface编码数据时需要运行在GL线程,一般的做法都是额外启动线程->初始化EGL环境->编码。在这基础上,只要我们限制通知MediaCodec编码的频率,就可以限制编码出来的数据的FPS。

下面是自己demo中的部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override
public void onDrawFrame(GL10 gl) {
if (!mMediaRecorder.isInit()) {
mMediaRecorder.setEglContext(EGL14.eglGetCurrentContext());
mMediaRecorder.setTextureId(mCameraDrawable.getTextureId());
mMediaRecorder.init();
}

if (!mMediaRecorder.isStart()) {
mMediaRecorder.startRecord();

new Thread() {
@Override
public void run() {
int fps = 20;
long fpsTime = 1000 / fps;
long time = System.currentTimeMillis();
long diffTime = 0;

while (true) {
LogUtils.i("start");
final SurfaceTexture surfaceTexture = mCameraDrawable.getSurfaceTexture();
surfaceTexture.getTransformMatrix(mTextureMartix);
mMediaRecorder.record(surfaceTexture.getTimestamp(), mTextureMartix);
diffTime = System.currentTimeMillis() - time;
if (diffTime < fpsTime) {
try {
sleep(fpsTime - diffTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(!mMediaRecorder.isStart()){
break;
}
time = System.currentTimeMillis();
}
}
}.start();
}

mCameraDrawable.draw();

mFpsPrinter.printFPS();
}

上述代码中新起的线程就是控制MediaCodec编码频率的。值得一提的是,MediaCodec使用InputSurface编码时,都是需要通过SurfaceTexture来获取每一帧的时间戳。过去我曾经陷入过迷思,不知道如何控制时间戳来控制帧率。后来想想,其实在编译每一帧时获取其对应的时间戳即可。

编码时加速、减速视频

假设我们想保持帧率不变,但是实际编码出来的MP4是加速或减速过的视频,可以通过修改上面提到的时间戳效果。比如,将输入的SurfaceTexture.getTimestamp()乘以2,再传递给EGLExt.eglPresentationTimeANDROID(),最终的效果就是整个视频是加快一倍的;减速同理,除以指定系数即可。

关于取模运算和取余运算 RxJava的一些线程问题

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×