我想使用YUV420为动态创建的YUVFormat创建一个jmf / fmj CaptureDevice实例。对于strideY,strideUV,offsetY,offsetU和offsetV的值,我感到困惑。 YUVFormat类中仅以下构造函数可用:

1. YUVFormat()
2. YUVFormat(int yuvType)
3. YUVFormat(java.awt.Dimension大小,int maxDataLength,java.lang.Class dataType,float frameRate,int yuvType,int strideY,int strideUV,int offsetY,int offsetU,int offsetV)


使用#1或#2不允许我在事后设置大小,帧速率或数据类型。所以我不能使用它们。使用#3需要我知道另外五个参数。我已经从Google搜索中阅读了以下所有帖子,但对于值应该是什么仍然感到困惑。我认为我可以安全地假设strideY和strideUV将是框架的宽度,但是我不确定100%。

Javadoc:http://fmj-sf.net/doc/fmj/javax/media/format/YUVFormat.html

MediaWiki:http://wiki.multimedia.cx/index.php?title=PIX_FMT_YUV420P

FourCC:http://www.fourcc.org/yuv.php#IYUV

到目前为止,这是我的代码:

int strideY =宽度,strideUV =宽度/ 2;
int offsetY = 0,offsetU = 0,offsetV = 0;
YUVFormat yuv = new YUVFormat(new Dimension(width,height),Format.NOT_SPECIFIED,Format.byteArray,frameRate,YUVFormat.YUV_420,strideY,strideUV,offsetY,offsetU,offsetV);

最佳答案

上次使用这些类时,内部发生了内存问题。

该格式实际上不需要数据速率或帧速率。它仅指定像素在内存中的排列方式。

我建议尽可能处理数组中的字节。

想想RGBA数据。存储器中的每个字均为4像素。 [RGBA] [RGBA] ...通常,它首先写出左下角,然后在右上角结束。数据大小易于了解,特定像素易于操作。

YUV是平面或半平面格式,平均每个像素12位,而不是32位。这是通过使U和V大小加倍而具有8位Y和8位U和V来实现的。 U和V的8位覆盖Y平面的4个像素。

因此,如果图片大小为320 x 240,则前320 * 240字节将是Y平面数据。

存储器中的下一个字节是隔行扫描的U / V线(半平面)或全平面,首先是全部U,然后是全部V数据。

Y的步幅是宽度。
U / V的步幅是宽度的一半。
Y的偏移量是像素行/跨距之间的字节数。
U的偏移量是像素行/步之间的字节数。
V的偏移是像素行/步之间的字节数。

它们还具有Java中未公开的“基址”。前Y个像素数据的存储地址。

在至少只能分配32位字的系统上,使用12位色深或奇数像素大小的图像会使主机系统在像素数据在寻址的内存中的位置方面以不同的方式表现。

例如,
写入所有打包的Y数据,它将具有零偏移。
接下来写一条水平线的U数据。
接下来写入一条V数据水平线。
接下来写一条水平线的U数据。
接下来写入一条V数据水平线。

U和V的步幅是Y的步幅的一半。

在Java中,应该能够通过写入像素数据而在U和V数据之间没有间隙的情况下使用零偏移量。

yuv的另一种格式将全部U数据然后全部V数据写入完整块中。

偏移量对应于单个Y / U / V行之间的字节数。

基址将对应于U / V平面的起始地址。

数据以“这里(基数)”开头,即为“宽(跨度)”,下一行从此开始(偏移量)

使用java,可能会指定基址。

可能没有回答问题

{
    unsigned int planeSize;
    unsigned int halfWidth;

    unsigned char * yplane;
    unsigned char * uplane;
    unsigned char * vplane;
    const unsigned char * rgbIndex;

    int x, y;
    unsigned char * yline;
    unsigned char * uline;
    unsigned char * vline;

    planeSize = srcFrameWidth * srcFrameHeight;
    halfWidth = srcFrameWidth >> 1;

    // get pointers to the data
    yplane = yuv;
    uplane = yuv + planeSize;
    vplane = yuv + planeSize + (planeSize >> 2);
    rgbIndex = rgb;

        for (y = 0; y < srcFrameHeight; y++)
        {
        yline = yplane + (y * srcFrameWidth);
        uline = uplane + ((y >> 1) * halfWidth);
        vline = vplane + ((y >> 1) * halfWidth);

        if (flip)
        rgbIndex = rgb + (srcFrameWidth*(srcFrameHeight-1-y)*rgbIncrement);

            for (x = 0; x < (int) srcFrameWidth; x+=2)
            {
                rgbtoyuv(rgbIndex[0], rgbIndex[1], rgbIndex[2], *yline, *uline, *vline);
                rgbIndex += rgbIncrement;
                yline++;
                rgbtoyuv(rgbIndex[0], rgbIndex[1], rgbIndex[2], *yline, *uline, *vline);
                rgbIndex += rgbIncrement;
                yline++;
                uline++;
                vline++;
}
}
}


在Java中

public static byte[] YV12toYUV420Planar(byte[] input, byte[] output, int width, int height) {
    final int frameSize = width * height;
    final int qFrameSize = frameSize/4;

    System.arraycopy(input, 0, output, 0, frameSize); // Y
    System.arraycopy(input, frameSize, output, frameSize + qFrameSize, qFrameSize); // Cr (V)
    System.arraycopy(input, frameSize + qFrameSize, output, frameSize, qFrameSize); // Cb (U)

    return output;
}

关于java - 创建一个YUVFormat实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24684040/

10-08 21:16