本文共 2434 字,大约阅读时间需要 8 分钟。
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); } } }
转载地址:http://wslzl.baihongyu.com/