2016-07-29 308 views
1

我想通過JNI使用FFMpeg的sws_scale函數將Java中的TYPE_3BYTE_BGR BufferedImage轉換爲yuv。我首先提取從我的BufferedImage圖像的數據作爲使用FFMpeg將BGR BufferedImage快速轉換爲YUV

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)

回答

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是多餘的,並導致違反綁定。當下一行時,應有的縮放比例會跳過很多空間。接下來,實際色度寬度爲亮度寬度的一半,所以如果你想緊包裝的亮度和色度的飛機沒有在空白行結束下次使用:

int outLinesize[3] = { width , width/2 , width/2 }; // YUV stride 

分配大小保持不變。

+0

感謝您的回覆,但我仍然有一些問題。如果我將步幅調整爲yuv [1] = new uint8_t [lumaPlaneSize/2];和yuv [1] = new uint8_t [lumaPlaneSize/2]; ,你的建議outputLinesize似乎一切正常。除了將輸出寫入文件: fwrite(yuv [0],1,lumaPlaneSize,fp); fwrite(yuv [1],1,lumaPlaneSize/4,fp); fwrite(yuv [2],1,lumaPlaneSize/4,fp); 看來,圖像縮放和不完整。我更改爲fwrite(yuv [1和2],1,lumaPlaneSize/2,fp);那麼圖像就完全不好了我該怎麼辦? – Hossein

+1

什麼不完整的圖像看起來像? – Sergio

+0

之前: https://postimg.org/image/gr93ykns1/ 後: https://postimg.org/image/f0mg9dyvb/ – Hossein

1

望着source,特別是圍繞線321,你會得到警告消息,如果你的系統支持AVX2指令並且各種指針和大小不是16的倍數。可能發生崩潰的原因是您傳入的數組inData,inLineSizeoutLinesize的大小不正確。指針數組至少需要3個元素,步長數組需要4個。在sws_scale的某個地方,它正在訪問inData[1],這個超出了數組範圍,導致了一個錯誤的指針。

+1

「指針數組需要至少3個元素,步長數組需要4 ...」 - 否,這些大小嚴格按照使用的像素格式定義,在YUV420的情況下,緩衝區數組和步長數組都必須包含正好3個元素 - 每個Y,Cr,Cb飛機。 – Sergio