1

我正在为 Android 平台构建一个内部共享库。我有来自设备制造商的签名密钥库。

我的库正在使用来自 Android 源的ScreenRecord.cpp内部文件。使用 MediaCodec 编码器可以正常录制;但是我想访问每一帧,这样我就可以在每一帧被传递给编码器之前应用一些图像覆盖标志。Android 源代码中也有一个覆盖示例,但这仅适用于较新版本的 Android(5.0 / API 21+)。我想为 Android Kitkat (4.4 / API 19) 提供一个覆盖解决方案

这是我从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();

我设置了上面的代码,但是 FrameAvailableListener 的 onFrameAvailable() 方法只被调用一次。即使我在屏幕上做事,它也不会再被调用。我在这里想念什么?在传递给编码器之前是否有任何不那么棘手的方法来访问帧?

4

1 回答 1

2

Lollipop的屏幕记录源中内置了一个添加叠加层的示例。据我所知,它不依赖于 Lollipop 中添加的任何功能,因此您应该能够在 4.4 上构建和运行它。如bigflake 所述,该--bugreport模式在 4.4 时间范围内添加到 AOSP,但实际上直到 5.x 才随系统一起提供。(稍作调整,它甚至应该在 4.3 上运行,但我还没有尝试过。)

关键源文件是Overlay.{cpp,h}. 它与用 Java 编写的代码执行相同的操作:创建一个 GLConsumer (SurfaceTexture),使用它将传入的帧转换为 GLES 纹理,然后将纹理 + 叠加层渲染到视频编码器。

示例视频在这里。请注意,它在一开始就添加了一个文本块,并在左上角添加了一个正在运行的时间戳/帧计数器。

阅读本文的其他人请注意:此代码使用的内部私有 API 在最近的版本中发生了变化,因此必须为特定版本的 Android 构建任何二进制文件,并且可能无法移植到不同制造商构建的设备上,即使它们运行相同版本的 Android(有时 OEM 喜欢搞砸东西)。

更新:我之前关于开发 KitKat 的声明并不准确——在 Lollipop 版本发布之前,API 发生了重大变化。诀窍是在此更改生效之前获取源,因为那是 BufferQueue API 重写到达屏幕记录的时候。您可以从更改列表中看到该--bugreport选项在此之前的大约五个月内出现。

于 2015-09-17T15:08:57.743 回答