Android 图像 U 和 V 缓冲区太大
Android Image U and V buffers too large
我正在使用 camera2 api 从 android 图像中读取 YUV 值。因此我有3架飞机。
for (int x = 0; x < imageSheaf[0].Width; x++)
{
for (int y = 0; y < imageSheaf[0].Height; y++)
{
imageYuv[x, y] = new yuv();
}
}
for (int j = 0; bufferY.HasRemaining; j++)
{
for (int i = 0; i < rowStrideY/2; i += 2)
{
if (i > width / 2 - 1 || j > height / 2 - 1)
Log.Info("Processing", "Out of Bounds");
imageYuv[i, j].y = bufferY.Get();
bufferY.Get();//skip a pixel due to 4:2:0 sub sampling
}
for (int i = 0; i < rowStrideY/2; i++)//skip a line due to 4:2:0 sub sampling
{
bufferY.Get();
bufferY.Get();
}
if (!bufferY.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferU.HasRemaining; j++)
{
for (int i = 0; i < rowStrideU; i++)
{
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].u = bufferU.Get();
}
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferV.HasRemaining; j++)
{
for (int i = 0; i < rowStrideV; i++)
{
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].v = bufferV.Get();
}
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
}
这是我用来从字节缓冲区获取 Y、U 和 V 值的代码。
ImageFormat 是 YUV_420_888,据我了解,4:2:0 子采样意味着对于每个 U 或 V 像素有 4 个 Y 像素。
我的问题是 U 和 V 平面的字节缓冲区大小大于它们应该导致数组越界异常的大小:
[Processing] RowstrideY = 720
[Processing] RowstrideU = 368
[Processing] RowstrideV = 368
[Processing] y.remaining = 345600, u.remaining = 88312, v.remaining = 88312
(图片尺寸为720x480)
YUV420 的 Y 每像素 8 位,U 和 V 每四像素组 8 位。因此在 720x480 下,您希望 U-V 平面为 360x240。
但是,实际硬件可能有额外的对齐或步幅限制。在这种情况下,硬件似乎要求步幅是 16 的倍数,所以它从 360 增加到 368。
你希望它变成 368*240=88320 的长度,但请记住,每行的最后八个字节只是填充。所以buffer实际上可以是(368*239)+360 = 88312字节,不遗漏任何数据。如果您收到数组边界异常,那是因为您试图从最后一行读取行尾填充字节,但这是不允许的。 API 仅保证您将能够读取数据。
这样做的动机是,如果最后一行的填充恰好跨越页面边界,系统将需要为每个缓冲区分配一个额外的不必要的页面。
您可以修改代码以从每一行复制数据字节,然后进行第二个循环,仅消耗行末尾的填充字节(如果有)。
我正在使用 camera2 api 从 android 图像中读取 YUV 值。因此我有3架飞机。
for (int x = 0; x < imageSheaf[0].Width; x++)
{
for (int y = 0; y < imageSheaf[0].Height; y++)
{
imageYuv[x, y] = new yuv();
}
}
for (int j = 0; bufferY.HasRemaining; j++)
{
for (int i = 0; i < rowStrideY/2; i += 2)
{
if (i > width / 2 - 1 || j > height / 2 - 1)
Log.Info("Processing", "Out of Bounds");
imageYuv[i, j].y = bufferY.Get();
bufferY.Get();//skip a pixel due to 4:2:0 sub sampling
}
for (int i = 0; i < rowStrideY/2; i++)//skip a line due to 4:2:0 sub sampling
{
bufferY.Get();
bufferY.Get();
}
if (!bufferY.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferU.HasRemaining; j++)
{
for (int i = 0; i < rowStrideU; i++)
{
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].u = bufferU.Get();
}
if (!bufferU.HasRemaining)
Log.Debug("Processing", "finished");
}
for (int j = 0; bufferV.HasRemaining; j++)
{
for (int i = 0; i < rowStrideV; i++)
{
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
imageYuv[i, j].v = bufferV.Get();
}
if (!bufferV.HasRemaining)
Log.Debug("Processing", "finished");
}
这是我用来从字节缓冲区获取 Y、U 和 V 值的代码。
ImageFormat 是 YUV_420_888,据我了解,4:2:0 子采样意味着对于每个 U 或 V 像素有 4 个 Y 像素。
我的问题是 U 和 V 平面的字节缓冲区大小大于它们应该导致数组越界异常的大小:
[Processing] RowstrideY = 720
[Processing] RowstrideU = 368
[Processing] RowstrideV = 368
[Processing] y.remaining = 345600, u.remaining = 88312, v.remaining = 88312
(图片尺寸为720x480)
YUV420 的 Y 每像素 8 位,U 和 V 每四像素组 8 位。因此在 720x480 下,您希望 U-V 平面为 360x240。
但是,实际硬件可能有额外的对齐或步幅限制。在这种情况下,硬件似乎要求步幅是 16 的倍数,所以它从 360 增加到 368。
你希望它变成 368*240=88320 的长度,但请记住,每行的最后八个字节只是填充。所以buffer实际上可以是(368*239)+360 = 88312字节,不遗漏任何数据。如果您收到数组边界异常,那是因为您试图从最后一行读取行尾填充字节,但这是不允许的。 API 仅保证您将能够读取数据。
这样做的动机是,如果最后一行的填充恰好跨越页面边界,系统将需要为每个缓冲区分配一个额外的不必要的页面。
您可以修改代码以从每一行复制数据字节,然后进行第二个循环,仅消耗行末尾的填充字节(如果有)。