NDK图形函数在某些机型下显示花屏的问题

简介: NDK使用ANativeWindow渲染surface,大致代码如下:ANativeWindow *nativeWindow = ANativeWindow_fromSurface(e...

NDK使用ANativeWindow渲染surface,

大致代码如下:

ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
if (nativeWindow == 0) {
	LOGE("ANativeWindow_window_from_surface error;env[0x%x] surface[0x%x]", env, surface);
	return NULL;
}

int err = ANativeWindow_setBuffersGeometry(nativeWindow, width, height, WINDOW_FORMAT_RGB_565);
if ( err < 0 ) {
	LOGE("ANativeWindow_setBuffersGeometry error");
	return NULL;
}


LOGI("AnativeSurface_Draw param invalid. %d | %d | %d | %d | %d | %d", env, NativeSurface, ImgData, dataLen, width, height);
if (env == NULL || NativeSurface == NULL || ImgData == NULL
			|| dataLen == 0 || width == 0 || height == 0) {
	LOGE("AnativeSurface_Draw param invalid. %d | %d | %d | %d | %d | %d", env, NativeSurface, ImgData, dataLen, width, height);
	return ;
}

ANativeWindow_Buffer windowBuffer;
int nlocked = ANativeWindow_lock((ANativeWindow*)NativeSurface, &windowBuffer, 0);
if (nlocked < 0) {
	LOGW("AnativeSurface lock error:%d", nlocked);
	return;
}

if (windowBuffer.bits != NULL) {
	memcpy(windowBuffer.bits, ImgData, dataLen);
}

ANativeWindow_unlockAndPost((ANativeWindow*)NativeSurface);

ANativeWindow_release((ANativeWindow*)NativeSurface);

在测试的过程中,发现有些机型上出现花屏的现象,经内存拷贝测试,发现这些机型上,windowbuffer.bits的大小不等于 width * height * RGBSIZE,因此会导致数据错位而无法正常显示。


翻了下native_window.h(development/ndk/platforms/android-x/include/android目录下),对于windowBuffer的定义如下:

typedef struct ANativeWindow_Buffer {
    // The number of pixels that are show horizontally.
    int32_t width;

    // The number of pixels that are shown vertically.
    int32_t height;

    // The number of *pixels* that a line in the buffer takes in
    // memory.  This may be >= width.
    int32_t stride;

    // The format of the buffer.  One of WINDOW_FORMAT_*
    int32_t format;

    // The actual bits.
    void* bits;
    
    // Do not touch.
    uint32_t reserved[6];
} ANativeWindow_Buffer;

其中一个叫stride的项,表示在内存中每一行包含的像素数量,这个值可能会大于width。


再次测试,发现所有有问题的机型,果然stride大于width。因此在拷贝的时候需要注意内存对齐。。


最后解决方案如下:

    if (windowBuffer.bits != NULL) {
    	//memcpy(windowBuffer.bits, ImgData, dataLen);
    	if (windowBuffer.width == windowBuffer.stride) {
    		memcpy(windowBuffer.bits, ImgData, dataLen);
    	} else {
    		for (int ii=0; ii < windowBuffer.height; ii++) {
    			char *srcPointer = ImgData + windowBuffer.width * ii * 2;
    			char *dstPointer = ((char *)windowBuffer.bits) + windowBuffer.stride * ii * 2;

    			memcpy(dstPointer, srcPointer, windowBuffer.width * 2);
    		}
    	}
    }



目录
相关文章
|
编解码 Python
Python 技术篇-使用PyQt5库获取电脑屏幕桌面的宽、高和分辨率
Python 技术篇-使用PyQt5库获取电脑屏幕桌面的宽、高和分辨率
1208 0
Python 技术篇-使用PyQt5库获取电脑屏幕桌面的宽、高和分辨率
|
3天前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。
|
9月前
|
图形学
|
12月前
|
编解码 Dart
Flutter如何获取屏幕的分辨率和实际画布的分辨率
Flutter如何获取屏幕的分辨率和实际画布的分辨率
|
iOS开发 MacOS
MacOS:使用内置的屏幕截图和屏幕录像功能
MacOS:使用内置的屏幕截图和屏幕录像功能
104 0
MacOS:使用内置的屏幕截图和屏幕录像功能
|
Ubuntu 虚拟化 数据安全/隐私保护
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(二)
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(二)
199 0
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(二)
|
Ubuntu Linux
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(一)
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(一)
195 0
Ubuntu使用优化(中文输入法,下载速度,窗口适配)(一)
|
编解码
QT应用编程: 获取系统屏幕数量及分辨率
QT应用编程: 获取系统屏幕数量及分辨率
686 0
|
数据采集 编解码 API
Android平台、屏幕、OpenGL不同版本用户数统计
Android平台的碎片化问题被开发者诟病已久。最近Google公布了一些Android设备的统计信息,开发者可以根据市场占有率决定不同设备开发和优化需要投入的经历。特别是人力较少的小公司和个人开发者,更需要集中精力,有所取舍。
704 0
Android平台、屏幕、OpenGL不同版本用户数统计
|
缓存 编解码 并行计算
iOS 开发:绘制像素到屏幕
像素是如何绘制到屏幕上面的?把数据输出到屏幕的方法有很多,通过调用很多不同的framework和不同的函数。这里我们讲一下这个过程背后的东西。希望能够帮助大家了解什么时候该使用什么API,特别是当遇到性能问题需要调试的时候。当然,我们这里主要讲iOS,但是事实上,很多东西也是可以应用到OSX上面的。
283 0
iOS 开发:绘制像素到屏幕

热门文章

最新文章