0x00 如何获取MediaProjection实例
Android 5.0及以上版本提供录屏接口MediaProjection,通过startActivityForResult启动界面,用户授权后获得MediaProjection实例。
注意
startActivityForResult只能在Activity调用,意味着必须借助界面启动。
代码示例
MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager)getApplication().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
//......
startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == Activity.RESULT_OK) {
MediaProjection MediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data));
}
}
0x01 如何使用MediaProjection录制屏幕
通过MediaProjection创建VirtualDisplay(可以认为是和屏幕一样的镜像),关注输入参数surface,VirtualDisplay按照策略(屏幕有变化)将屏幕内容输出到surface中。
VirtualDisplay virtualDisplay = mMediaProjection.createVirtualDisplay("mirror", width, height,
density, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, surface, null, null);
Surface如何创建
1. ImageReader
ImageReader imageReader = ImageReader.newInstance(width, height, ImageFormat.RGB_565, 2);
surface = imageReader.getSurface();
通过imageReader.setOnImageAvailableListener监听最近屏幕更新
获取最行图像imageReader.acquireLatestImage(),保存成png
2. MediaRecorder
MediaRecorder mediaRecorder = new MediaRecorder();
surface = mediaRecorder.getSurface();
VirtualDisplay输出屏幕内容到MediaRecorder的surface,MediaRecorder编码成视频文件
3. MediaCodec
MediaCodec mediaCodec = MediaCodec.createEncoderByType("video/avc");
surface = mediaCodec.createInputSurface();
VirtualDisplay输出屏幕内容到MediaCodec的surface,MediaCodec可以自定义,通过MediaMuxer输出到视频文件或者获取编码的帧数据发送到网络
0x02 帧率如何能满足要求
发现没有,通过上述3种方法,帧率都无法稳定到24fps,即使强制获取surface数据,都无法达到,至于具体原因还不清楚。
下面介绍一种方法,通过GPU surface拷贝的方式,帧率自己控制,稳定输出。
VirtualDisplay和MediaCodec之间插入一个新的surface作为VirtualDisplay输出,共享context,将屏幕内容画出来(屏幕内容没有更新,可以沿用之前的图像),通过swapBuffers填充到MediaCodec的surface,然后编码为一帧视频数据。
网友评论