2012-02-08 67 views
20

在我的應用程序中,我們需要顯示視頻幀從服務器接收到我們的android應用程序,
服務器正在發送每秒50幀的視頻數據,在WebM中編碼,即使用libvpx編碼和解碼圖像,在Android中顯示YUV圖像

現在從libvpx其獲得的YUV數據

當前實現是這樣的,

在JNI /原生C++代碼進行解碼,我們就可以顯示在圖像上的佈局,之後,我們正在將YUV數據轉換爲RGB數據 在Android框架,呼籲

public Bitmap createImgae(byte[] bits, int width, int height, int scan) { 
    Bitmap bitmap=null; 
    System.out.println("video: creating bitmap"); 
    //try{ 

      bitmap = Bitmap.createBitmap(width, height, 
        Bitmap.Config.ARGB_8888); 
      bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(bits));  

    //}catch(OutOfMemoryError ex){ 

    //} 
      System.out.println("video: bitmap created"); 
    return bitmap; 
} 

要創建位圖圖像,

使用下面的代碼顯示在imageview的形象,

   img = createImgae(imgRaw, imgInfo[0], imgInfo[1], 1); 
       if(img!=null && !img.isRecycled()){ 

        iv.setImageBitmap(img); 
        //img.recycle(); 
        img=null; 
        System.out.println("video: image displayed"); 
       } 

我的查詢,總體來說,這一功能被約走40毫秒,有沒有什麼辦法來優化它,
1 - 有沒有什麼方法可以將YUV數據顯示到imageView?

2 - 是否有任何其他的方法來創建映像(位圖圖像​​)的RGB數據,

3 - 我相信,我總是創造的形象,但我想我應該只有一次創建位圖,並做/總是提供新的緩衝區,當我們收到時。
請分享您的觀點。

+0

'bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(位));'並從YUV變換爲RGB?或者你說這就是你在本地做的事情? – weston 2012-02-08 12:11:10

+0

這是一種方法。檢查出http://stackoverflow.com/questions/9192982/displaying-yuv-image-in-android – bob 2012-06-30 20:34:43

回答

30

下面的代碼解決了您的問題,因爲YuvImage類是隨Android-SDK提供的,所以它可能需要更少的時間在Yuv格式數據上。

你可以試試這個,

ByteArrayOutputStream out = new ByteArrayOutputStream(); 
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null); 
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 50, out); 
byte[] imageBytes = out.toByteArray(); 
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); 
iv.setImageBitmap(image); 

void yourFunction(byte[] data, int mWidth, int mHeight) 
{ 

int[] mIntArray = new int[mWidth*mHeight]; 

// Decode Yuv data to integer array 
decodeYUV420SP(mIntArray, data, mWidth, mHeight); 

//Initialize the bitmap, with the replaced color 
Bitmap bmp = Bitmap.createBitmap(mIntArray, mWidth, mHeight, Bitmap.Config.ARGB_8888); 

// Draw the bitmap with the replaced color 
iv.setImageBitmap(bmp); 

} 

static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, 
    int height) { 
final int frameSize = width * height; 

for (int j = 0, yp = 0; j < height; j++) { 
    int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 
    for (int i = 0; i < width; i++, yp++) { 
     int y = (0xff & ((int) yuv420sp[yp])) - 16; 
     if (y < 0) 
      y = 0; 
     if ((i & 1) == 0) { 
      v = (0xff & yuv420sp[uvp++]) - 128; 
      u = (0xff & yuv420sp[uvp++]) - 128; 
     } 

     int y1192 = 1192 * y; 
     int r = (y1192 + 1634 * v); 
     int g = (y1192 - 833 * v - 400 * u); 
     int b = (y1192 + 2066 * u); 

     if (r < 0) 
      r = 0; 
     else if (r > 262143) 
      r = 262143; 
     if (g < 0) 
      g = 0; 
     else if (g > 262143) 
      g = 262143; 
     if (b < 0) 
      b = 0; 
     else if (b > 262143) 
      b = 262143; 

     // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 
     // 0xff00) | ((b >> 10) & 0xff); 
     // rgba, divide 2^10 (>> 10) 
     rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) 
       | ((b >> 2) | 0xff00); 
    } 
} 
} 
+2

我試過你的方法decodeYUV420SP()但它創建的圖像不好。它充滿了黃色和綠色的波浪。我做了這一個,它的工作原理:http:// stackoverflow。com/questions/5272388/need-help-with-androids-nv21-format/12702836#12702836 – Derzu 2012-10-05 14:24:35

+1

我不明白爲什麼rgba [yp] = ...被移位了8位。註釋掉的線更加正確。我得到一個旋轉的圖像。 – 2013-04-02 14:15:55

+5

是否有無損壓縮(即不是JPEG)的方式? – 2013-08-01 17:48:32

-2

創建越來越寬度和高度的onCreate後的位圖。

editedBitmap = Bitmap.createBitmap(widthPreview, heightPreview, 
       android.graphics.Bitmap.Config.ARGB_8888); 

而且在onPreviewFrame.

int[] rgbData = decodeGreyscale(aNv21Byte,widthPreview,heightPreview); 
editedBitmap.setPixels(rgbData, 0, widthPreview, 0, 0, widthPreview, heightPreview); 

private int[] decodeGreyscale(byte[] nv21, int width, int height) { 
    int pixelCount = width * height; 
    int[] out = new int[pixelCount]; 
    for (int i = 0; i < pixelCount; ++i) { 
     int luminance = nv21[i] & 0xFF; 
     // out[i] = Color.argb(0xFF, luminance, luminance, luminance); 
     out[i] = 0xff000000 | luminance <<16 | luminance <<8 | luminance;//No need to create Color object for each. 
    } 
    return out; 
} 

和獎金。

if(cameraId==CameraInfo.CAMERA_FACING_FRONT) 
{ 
    matrix.setRotate(270F); 
} 

finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);