简体   繁体   English

Android虚拟显示的帧侦听器(NDK内部版本)

[英]Frame Listener for Android Virtual Display (NDK internal build)

I'm building an internal shared library for Android platform. 我正在为Android平台构建内部共享库。 I have the signing keystore from the device manufacturer. 我有设备制造商提供的签名密钥库。

My library is making use of ScreenRecord.cpp internal file from Android source. 我的图书馆正在使用Android来源的ScreenRecord.cpp内部文件。 Recording works fine with the MediaCodec encoder; 使用MediaCodec编码器可以很好地进行记录; however I want to access each frame so that I can apply some image overlay logo on to each frame before it gets passed to the encoder. 但是我想访问每个帧,以便在将每个帧传递到编码器之前可以在它们上应用一些图像叠加徽标。 There's an overlay example in Android source too, but that only works for newer versions of Android (5.0 / API 21+). Android源代码中也有一个覆盖示例,但仅适用于更新版本的Android(5.0 / API 21+)。 I want to have an overlay solution for Android Kitkat (4.4 / API 19) 我想为Android Kitkat(4.4 / API 19)提供覆盖解决方案

Here's a code example that I obtained from minicap . 这是我从minicap获得的代码示例。

mVirtualDisplay = android::SurfaceComposerClient::createDisplay(
android::String8("minicap"),
true);

LOGI("Creating buffer queue");
mScreenshotClient.getCpuConsumer();
mBufferQueue = mScreenshotClient.mBufferQueue;

LOGI("Creating CPU consumer");
mConsumer = new android::CpuConsumer(mBufferQueue, 3, false);
mConsumer->setName(android::String8("minicap"));
mConsumer->setDefaultBufferSize(targetWidth, targetHeight);
mConsumer->setDefaultBufferFormat(android::PIXEL_FORMAT_RGBA_8888);

mConsumer->setFrameAvailableListener(mFrameProxy); 
//mFrameProxy is from:
//class FrameProxy: public android::ConsumerBase::FrameAvailableListener

LOGI("Publishing virtual display");
android::SurfaceComposerClient::openGlobalTransaction();
android::SurfaceComposerClient::setDisplaySurface(mVirtualDisplay, mBufferQueue);
android::SurfaceComposerClient::setDisplayProjection(mVirtualDisplay,
android::DISPLAY_ORIENTATION_0, layerStackRect, visibleRect);
android::SurfaceComposerClient::setDisplayLayerStack(mVirtualDisplay, 0);// default stack

android::SurfaceComposerClient::closeGlobalTransaction();

I set up the above code, but onFrameAvailable() method of FrameAvailableListener gets called only once. 我设置了上面的代码,但是FrameAvailableListener的onFrameAvailable()方法仅被调用一次。 It never gets called again even when I do stuff on the screen. 即使我在屏幕上放东西,也再也不会调用它。 What am I missing here? 我在这里想念什么? Isn't there any lesser tricky way to access the frames before passing to the encoder? 在传递给编码器之前,是否没有其他更轻松的方法来访问帧?

An example of adding an overlay is built into the screenrecord sources for Lollipop. Lollipop的屏幕记录源中内置了一个添加覆盖的示例。 As far as I can recall it doesn't rely on any features added in Lollipop, so you should be able to build and run it on 4.4. 据我所知,它不依赖于Lollipop中添加的任何功能,因此您应该能够在4.4上构建和运行它。 As noted on bigflake , the --bugreport mode was added to AOSP in the 4.4 time frame, but didn't actually ship with the system until 5.x. bigflake所述,-- --bugreport模式是在4.4的时间范围内添加到AOSP的,但实际上直到5.x才随系统一起提供。 (With a minor tweak, it should even run on 4.3, but I haven't tried it.) (稍作调整,它甚至应在4.3上运行,但我没有尝试过。)

The key source files are Overlay.{cpp,h} . 关键源文件是Overlay.{cpp,h} It does the same thing that you would do from code written in Java: create a GLConsumer (SurfaceTexture), use that to convert the incoming frames to GLES textures, then render texture + overlay to the video encoder. 它执行与用Java编写的代码相同的操作:创建GLConsumer(SurfaceTexture),使用它将传入的帧转换为GLES纹理,然后将纹理+叠加层渲染到视频编码器。

Sample video is here . 示例视频在这里 Note it adds a block of text to the very start, and a running timestamp / frame-counter to the top left corner. 请注意,它从一开始就添加了一块文本,并在左上角添加了运行时间戳/帧计数器。

Note for anyone else reading this: this code is using internal private APIs that have been changing in recent releases, so any binaries must be built for specific versions of Android, and may not be portable to devices built by different manufacturers even if they run the same version of Android (sometimes the OEMs like to mess with things). 请其他人注意:此代码使用的是内部私有API,这些API在最新版本中已发生更改,因此任何二进制文件都必须针对特定版本的Android构建,并且即使运行不同制造商的设备也可能无法移植到由不同制造商制造的设备上相同版本的Android(有时OEM会喜欢弄乱东西)。

Update: My earlier statements about working on KitKat weren't accurate -- there was a major API shift before the Lollipop version went out. 更新:我先前关于使用KitKat的说法并不准确-在Lollipop版本发布之前,API发生了重大变化。 The trick is to grab the sources before this change went in, as that was when the BufferQueue API rewrite reached screenrecord. 诀窍是在进行此更改之前先获取源代码,因为那是在BufferQueue API重写到达屏幕记录时。 You can see from the change list that the --bugreport option went in about five months before that. 您可以从更改列表中看到--bugreport选项在此之前大约五个月出现了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM