我正在为Android平台构建一个内部共享库。我有设备制造商提供的签名密钥存储库。
我的库是利用ScreenRecord.cpp内部文件从Android源。记录工作良好的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();
我设置了上面的代码,但是frameavailableelistener的onFrameAvailable()方法只被调用一次。即使我在屏幕上执行操作,它也不会再被调用。我遗漏了什么?在将帧传递给编码器之前,没有更简单的方法来访问帧吗?
添加叠加的示例是内置到Lollipop的屏幕记录源中。据我所知,它不依赖于Lollipop中添加的任何功能,因此您应该能够在4.4上构建和运行它。正如在bigflake上所指出的,--bugreport
模式在4.4时间框架中被添加到AOSP中,但直到5.x才真正随系统一起发布。(稍微调整一下,它甚至应该在4.3上运行,但我还没有试过。)
密钥源文件为Overlay.{cpp,h}
。它做的事情和你用Java写的代码做的事情是一样的:创建一个GLConsumer (SurfaceTexture),使用它将传入的帧转换为GLES纹理,然后将纹理+覆盖渲染到视频编码器。
示例视频在这里。请注意,它在最开始添加了一个文本块,并在左上角添加了一个运行的时间戳/帧计数器。
请注意:这段代码使用的是内部私有api,这些api在最近的版本中一直在变化,所以任何二进制文件都必须针对特定的Android版本构建,并且可能无法移植到不同制造商构建的设备上,即使它们运行的是相同的Android版本(有时oem喜欢弄乱东西)。
Update:我之前关于制作KitKat的陈述是不准确的——在Lollipop版本发布之前有一个主要的API转变。诀窍是在进行更改之前获取源,因为这是在BufferQueue API重写到screenrecord时。您可以从变更列表中看到,--bugreport
选项在此之前大约五个月出现。