Android录屏简介

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,然后编码为一帧视频数据。

你可能感兴趣的:(Android录屏简介)