我正在使用SDL2.0.7(Nexus 5,armeabi-v7a,ndk 16.1)在本机应用上显示Android Camera预览。
我正在使用N21 YUV图像格式,我期待着,创建一个这种格式的SDL_Texture
,SDL_LockTexture()
返回的音高值将大于我现在所获得的音高值。
示例代码:
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV21, SDL_TEXTUREACCESS_STREAMING, 720, 480);
int res = SDL_LockTexture(texture, nullptr, &pixels, &pitch);
我期望获得720 * 12 / 8
的音高值,即1080
,其中720
是一行的宽度,12
是单个YUV N21像素的位数,8
是一个字节中的位数,因为the SDL2 documentation声明:
音高:这是用锁定像素的音高填充的; pitch是一行的长度,以字节为单位
现在,函数调用实际返回的音高值是720
。事实是,如果我使用720
值,相机预览将以不自然的绿色优势显示,而如果我忽略720
音高并使用我预期的1080
音高,相机预览是好的(应用程序运行顺畅,太)。
我的假设是否有问题(例如,N21像素的位数是12,正如Android的ImageFormat.getBitsPerPixel()
所暗示的那样)?我是否以错误的方式使用SDL库?
流纹理的创建纹理实用程序在内部执行此操作:
// ...
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
size = texture->h * data->pitch;
if (data->yuv) {
/* Need to add size for the U and V planes */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
if (data->nv12) {
/* Need to add size for the U/V plane */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
}
}
// ...
在你的情况下,因为你正在使用SDL_PIXELFORMAT_NV21
,yuv
是假的,nv12
是真的(如果听起来很奇怪,请尝试使用调试器)。
这意味着分配的大小不是pitch * height
。相反,它是:
(pitch * height) + 2 * ((height + 1) / 2) * ((pitch + 1) / 2);
在这种情况下,pitch
等于width
。
在一天结束时,它是图像大小的1.5倍,即每像素12位。
它被授予pitch
的价值在某种程度上是错误的,因为它等于width
。
实际上,由于分配的空间,它应该是您想象的图像宽度的1.5倍。
但是我对此并不确定,因为我不是SDL2的专家。