2014-07-10 36 views
1

我想爲使用YUV420動態創建的CaptureDevice創建一個jmf/fmj YUVFormat實例。對於strideY,strideUV,offsetY,offsetU和offsetV應該是什麼值,我感到困惑。只有下面的構造在YUVFormat類可供選擇:創建YUV格式實例

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

使用1號或2不允許我這樣的事實後設置大小,幀速率或數據類型;所以我不能使用它們。使用#3需要我知道五個附加參數。我已經從我的谷歌搜索中閱讀了以下所有帖子,但我仍然對值的內容感到困惑。我認爲我可以放心地認爲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 = width, strideUV = width/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); 
+0

什麼是平臺? Android? – renick

+0

該平臺是服務器端java –

回答

2

我最後一次使用這些類我有記憶問題,從他們身上內部。

格式不應該真的需要數據速率或幀速率。它僅指定像素在內存中的排列方式。

如果可能的話,我會建議處理數組中的字節。

想想RGBA數據。內存中的每個字都是4個像素。 [RGBA] [RGBA] ...通常它會先寫出左下角,然後結束於右上角。數據的大小很容易知道,特定像素易於操作。

YUV是一種平面或半平面格式,平均每像素12位而不是32位。這通過具有8位Y和8位U和V以及U和V的雙倍大小來實現。 U和V的8位覆蓋Y平面的4個像素。

因此,如果圖片大小爲320×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的基址很可能給出。

大概didnt回答這個問題洛爾

{ 
    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; 
} 
+0

在C++中,從rgb轉換爲yuv。可能會給你一些視覺問題。 –

+0

在這種情況下,我使用YUV420P格式已經解碼的h.264字節 –

1

健和偏移量是依賴於幀存儲器的佈局和所述視頻幀的尺寸和可能的填充。

  • 一般步幅(explained here)是字節 的你需要添加一個指針去從一個平面線到下一個量。
  • 偏移量是您需要添加以從幀開始移動到特定平面(Y,U或V)的字節數量
  • 請參閱this Microsoft article解釋各種YUV幀內存佈局。
  • 另請參閱此Android源代碼,其中的strides and offsets are calculated取決於FOURCC(僅適用於Android支持的格式)。