屏幕截图 android 演示文稿显示/表面 [英] screenshot android presentation display/surface

查看:51
本文介绍了屏幕截图 android 演示文稿显示/表面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Android 中制作 Presentation 对象的即时"屏幕截图.我的演示文稿通常呈现到虚拟显示器 (PRIVATE),该显示器由设置为录制视频的 MediaRecorder 的表面支持.将演示文稿录制为视频效果很好.

I would like to make "instant" screenshots of an Presentation object in Android. My Presentation normally renders to a virtual display (PRIVATE) which is backed by the surface from a MediaRecorder that is setup to record video. Recording the presentation as a video works great.

mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(getScratchFile().getAbsolutePath());
mMediaRecorder.setVideoEncodingBitRate(bitrateInBitsPerSecond);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

mVirtualDisplay = mDisplayManager.createVirtualDisplay(
        DISPLAY_NAME, // string name required
        mVideoSize.getWidth(),
        mVideoSize.getHeight(),
        160, // screen densityDpi, not sure what it means in this context
        mMediaRecorder.getSurface(), // the media recorder must already be {@code prepare()}'d
        DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); // only we can use it

mPresentation = new MyPresentation(getActivity(), mVirtualDisplay().getDisplay());

如何随时获取 mMediaRecorder.getSurface() 的屏幕截图,包括 mMediaRecorder 已设置但未录制时?

How can I get a screenshot of the mMediaRecorder.getSurface() at any time, including when the mMediaRecorder is setup but not recording?

我在 Presentation 根视图对象上尝试了许多与 view.getDrawingCache() 相关的方法,但我只得到了清晰/黑色的输出.演示文稿本身包含 TextureView 对象,我猜这会破坏这个策略.我还尝试将 ImageReader 与 mMediaRecorder 的 DisplayPreview 一起使用,但它在回调中没有收到任何图像——永远

I've tried a number of methods related to the view.getDrawingCache() on the Presentation root view object and I only get clear/black output. The presentation itself contains TextureView objects, which I'm guessing are messing up this strategy. I also tried using an ImageReader with the DisplayPreview of the mMediaRecorder but it receives no images in the callback -- ever

mMediaRecorder.setDisplayPreview(mImageReader.getSurface());

我真的很想要某种方式将支持演示文稿的 Surface 镜像到 ImageReader 并将其用作消费者,我只是看不出如何将一个表面作为生产者镜像"到另一个消费者"类中.SurfaceFlinger 似乎应该有一个简单的方法.

I'd really like some way to mirror the Surface which backs the presentation into an ImageReader and use that as a consumer, I just can't see how to "mirror" one surface as a producer into another "consumer" class. It seems there should be an easy way with SurfaceFlinger.

推荐答案

表面是生产者-消费者数据结构的生产者端.生产者无法从管道中取回数据,因此无法尝试从 Surface 读取帧.

Surfaces are the producer end of a producer-consumer data structure. A producer can't pull data back out of the pipe, so attempting to read frames back from a Surface isn't possible.

在提供 MediaCodec 或 MediaRecorder 时,消费者端处于管理媒体硬件的不同进程 (mediaserver) 中.对于 SurfaceView,消费者在 SurfaceFlinger 中.对于 TextureView,两端都在您的应用中,这就是为什么您可以轻松地从 TextureView 获取框架(调用 getBitmap()).

When feeding MediaCodec or MediaRecorder, the consumer end is in a different process (mediaserver) that manages the media hardware. For a SurfaceView, the consumer is in SurfaceFlinger. For a TextureView, both ends are in your app, which is why you can easily get a frame from TextureView (call getBitmap()).

要拦截传入的数据,您需要在同一进程中同时拥有生产者和消费者.SurfaceTexture 类(也称为GLConsumer")提供了这一点——它是一个将接收到的帧转换为 GLES 纹理的消费者.

To intercept the incoming data you'd need to have both producer and consumer in the same process. The SurfaceTexture class (also known as "GLConsumer") provides this -- it's a consumer that converts the frames it receives into GLES textures.

所以想法是创建一个 SurfaceTexture,从中创建一个新的 Surface(您会注意到 Surface 的 只有公共构造函数采用 SurfaceTexture),并将该 Surface 作为虚拟显示输出 Surface 传递.然后当帧进入时,您通过使用 OpenGL ES 渲染纹理将它们转发"到 MediaRecorder.

So the idea would be to create a SurfaceTexture, create a new Surface from that (you'll note that Surface's only public constructor takes a SurfaceTexture), and pass that Surface as the virtual display output Surface. Then as frames come in you "forward" them to the MediaRecorder by rendering the textures with OpenGL ES.

这并不完全简单,特别是如果您以前没有使用过 OpenGL ES.可以在 Grafika 中找到各种示例(例如来自相机的纹理"和记录 GL 应用程序").

This is not entirely straightforward, especially if you haven't worked with OpenGL ES before. Various examples can be found in Grafika (e.g. "texture from camera" and "record GL app").

我不知道 setDisplayPreview() 是否适用于相机以外的任何东西.

I don't know if setDisplayPreview() is expected to work for anything other than Camera.

这篇关于屏幕截图 android 演示文稿显示/表面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆