我想使用FFMpeg的sws_scale函数通过JNI将Java中的TYPE_3BYTE_BGR BufferedImage转换为yuv。我首先从BufferedImage中提取我的图像数据
byte[] imgData = ((DataBufferByte) myImage.getRaster().getDataBuffer()).getData();
byte[] output = processImage(toSend,0);
然后我将它传递给processImage函数,这是一个本机函数。 C ++方面如下所示:
JNIEXPORT jbyteArray JNICALL Java_jni_JniExample_processData
(JNIEnv *env, jobject obj, jbyteArray data, jint index)
{
jboolean isCopy;
uint8_t *test = (uint8_t *)env->GetPrimitiveArrayCritical(data, &isCopy);
uint8_t *inData[1]; // RGB24 have one plane
inData[0] = test;
SwsContext * ctx = sws_getContext(width,height,AV_PIX_FMT_BGR24, (int)width, (int)width,
AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
int lumaPlaneSize = width *height;
uint8_t *yuv[3];
yuv[0] = new uint8_t[lumaPlaneSize];
yuv[1] = new uint8_t[lumaPlaneSize/4];
yuv[2] = new uint8_t[lumaPlaneSize/4];
int inLinesize[1] = { 3*nvEncoder->width }; // RGB stride
int outLinesize[3] = { 3*width ,3*width ,3*width }; // YUV stride
sws_scale(ctx, inData, inLinesize, 0, height , yuv, outLinesize);
但是,运行代码后,我收到警告:[swscaler @ 0x7fb598659480] Warning: data is not aligned! This can lead to a speedloss, everything crashes.
,一切都在最后一行崩溃。我是否正确地将正确的参数传递给sws_scale? (特别是步伐)。
更新
此处有一个单独的错误:SwsContext * ctx = sws_getContext(width,height,AV_PIX_FMT_BGR24, (int)width, (int)width,0,NULL,NULL,NULL)
应更改为:SwsContext * ctx = sws_getContext(width,height,AV_PIX_FMT_BGR24, (int)height, (int)width,0,NULL,NULL,NULL)
答案 0 :(得分:1)
查看source,特别是在第321行附近,如果您的系统支持AVX2指令并且各种指针和大小不是16的倍数,则会收到该警告消息。崩溃可能是因为阵列是您的传入,inData
,inLineSize
和outLinesize
的尺寸不合适。指针数组需要至少有3个元素,并且步长数组需要4. sws_scale
中的某个地方正在访问inData[1]
,它超出了数组的边界,导致指针错误。
答案 1 :(得分:1)
我看到的第一个问题 - 输出图像的步幅错误:
yuv[0] = new uint8_t[lumaPlaneSize];
yuv[1] = new uint8_t[lumaPlaneSize/4];
yuv[2] = new uint8_t[lumaPlaneSize/4];
int inLinesize[1] = { 3*nvEncoder->width }; // RGB stride
int outLinesize[3] = { 3*width ,3*width ,3*width }; // YUV stride
// ^^^^^^^ ^^^^^^^ ^^^^^^^
分配的飞机不足以通过步幅。 YUV420为每个通道使用一个字节,因此3
是多余的,并导致绑定违规。到达下一行时,到期的rescaler会跳过很多空间。接下来,实际的色度宽度是亮度宽度的一半,所以如果你想要紧凑的亮度和色度平面,在线端没有间隙,请使用下一个:
int outLinesize[3] = { width , width / 2 , width / 2 }; // YUV stride
分配大小保持不变。