scrcpy学习--(2)屏幕获取

scrcpy的开发文档DEVELOP.md中,对屏幕获取的方法是轻描淡写的说了下,使用MediaCodeC的相关接口,关联屏幕surface对象,就可以获取屏幕数据了。

https://github.com/Genymobile/scrcpy

打不开的可以看这个

https://gitee.com/mirrors/scrcpy/blob/master/DEVELOP.md

Screen video encoding

The encoding is managed by ScreenEncoder.

The video is encoded using the MediaCodec API. The codec takes its input from a surface associated to the display, and writes the resulting H.264 stream to the provided output stream (the socket connected to the client).

 

code
    private void internalStreamScreen(Device device, FileDescriptor fd) throws IOException {
        MediaFormat format = createFormat(bitRate, maxFps, codecOptions);
        device.setRotationListener(this);
        boolean alive;
        try {
            do {
                MediaCodec codec = createCodec();
                IBinder display = createDisplay();
                ScreenInfo screenInfo = device.getScreenInfo();
                Rect contentRect = screenInfo.getContentRect();
                // include the locked video orientation
                Rect videoRect = screenInfo.getVideoSize().toRect();
                // does not include the locked video orientation
                Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect();
                int videoRotation = screenInfo.getVideoRotation();
                int layerStack = device.getLayerStack();

                setSize(format, videoRect.width(), videoRect.height());
                configure(codec, format);
                Surface surface = codec.createInputSurface();
                setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
                codec.start();
                try {
                    alive = encode(codec, fd);
                    // do not call stop() on exception, it would trigger an IllegalStateException
                    codec.stop();
                } finally {
                    destroyDisplay(display);
                    codec.release();
                    surface.release();
                }
            } while (alive);
        } finally {
            device.setRotationListener(null);
        }
    }
 

 

    private static IBinder createDisplay() {
        return SurfaceControl.createDisplay("scrcpy", true);
    }

 

现在录屏使用virsualDisplay较多,以下是另外的获取屏幕实现

 

https://blog.csdn.net/u012894808/article/details/112395881

 public void startEncode() {
        //声明MediaFormat,创建视频格式。
        MediaFormat mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_HEVC, width, height);
        //描述视频格式的内容的颜色格式
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        //比特率(比特/秒)
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height);
        //帧率
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 20);
        //I帧的频率
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
        try {
            //创建编码MediaCodec 类型是video/hevc
            mediaCodec = MediaCodec.createEncoderByType(enCodeType);
            //配置编码器
            mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            //创建一个目的surface来存放输入数据
            Surface surface = mediaCodec.createInputSurface();
            //获取屏幕流
            mediaProjection.createVirtualDisplay("screen", width, height, 1, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
                    , surface, null, null);
        } catch (IOException e) {
            Log.d(TAG,"initEncode IOException");
            e.printStackTrace();
        }
        //启动子线程
        this.start();
    }

    @Override
    public void run() {
        //编解码器立即进入刷新子状态
        mediaCodec.start();
        //缓存区的元数据
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        //子线程需要一直运行,进行编码推流,所以要一直循环
        while (play) {
            //查询编码输出
            int outPutBufferId = mediaCodec.dequeueOutputBuffer(bufferInfo, timeOut);
            if (outPutBufferId >= 0) {
                //获取编码之后的数据输出流队列
                ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(outPutBufferId);
                //添加上vps,sps,pps
                reEncode(byteBuffer, bufferInfo);
                //处理完成,释放ByteBuffer数据
                mediaCodec.releaseOutputBuffer(outPutBufferId, false);
            }
        }
    }
————————————————
版权声明:本文为CSDN博主「coder_soldier」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012894808/article/details/112395881

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值