如何在 Android 本机上升级和渲染远程 (RGB565) 帧缓冲区?

How to upscale and render remote(RGB565) frame buffer on Android native?

我在 Android 4.2.2 上移植了远程帧缓冲区接收 C 代码,它以 RGB565 格式从主机接收帧缓冲区。能够按照标准 android 示例 frameworks/native/services/surfaceflinger/tests/resize/resize.cpp 渲染接收到的帧缓冲区。以下是使用的代码片段

sp<Surface> surface = client->createSurface(String8("resize"),
        800, 480, PIXEL_FORMAT_RGB_565, 0);


SurfaceComposerClient::openGlobalTransaction();
surface->setLayer(100000);
SurfaceComposerClient::closeGlobalTransaction();

Surface::SurfaceInfo info;
surface->lock(&info);
ssize_t bpr = info.s * bytesPerPixel(info.format);
/* rfb is the remote famebuffer filled by C stack*/
memcpy((uint16_t*)info.bits, rfb, 800*480*2);
surface->unlockAndPost();

但我无法升级接收到的缓冲区以在 android 上呈现全屏。例如:- 主机发送 800*480 但 android 设备屏幕为 1024*786 还有以下疑惑,
1. 在原生中创建表面是否是处理此类问题的正确方法?
2. 如何在 Android 原生上做高档原始图像和渲染?
3. 在写app的时候,app是否可以控制这个在native上创建的surface?

我是 android 的新手,如果有人能指导我正确处理这个问题就太好了

您目前正在使用需要特权访问的私有 SurfaceFlinger API。如果您需要这样做,我 认为 您想要使用 setSize() 调用来更改 window 的大小(这与底层表面)。 arch 文档中的 This section 展示了如何读取部分 adb shell dumpsys SurfaceFlinger 输出以查看实际大小是多少——这将告诉您调用是否有效。 (通常你会为此通过 Window 管理器,但你绕过了大部分 Android 框架。)

如果您可以在非特权应用程序中执行您需要的操作,您的代码将更具可移植性,并且不太可能因操作系统的更改而中断。最好的方法是创建一个 OpenGL ES 纹理和 "upload" 具有 glTexImage2D() 的像素到 GL_UNSIGNED_SHORT_5_6_5 纹理。 (我有理由相信 GLES 565 格式与 Android gralloc 格式相匹配,但我还没有尝试过。)一旦你在 GLES 纹理中有了图像,你就可以随心所欲地渲染它——你不再局限于矩形。

一些例子可以在Grafika. In particular, the "texture upload benchmark中找到”activity演示了上传和渲染纹理。(这是一个基准,所以它使用了屏幕外纹理,但其他活动如"texture from camera" 展示如何在屏幕上做事。)

基于 GLES 的方法的工作量要多得多,但您可以从 Grafika 中提取大部分内容。 Java 语言的 GLES 代码通常只是原生等效代码的薄包装,因此如果您决定将 NDK 用于 GLES 工作,这是一个相当直接的转换。不过,由于所有繁重的工作都是由图形驱动程序完成的,因此为此使用 NDK 没有多大意义。 (如果像素是通过纯本机代码到达的,请使用 "direct" ByteBuffer 包装缓冲区以从 Java 语言代码访问。)