Affichage de L'image YUV sur Android

dans mon application, nous avons besoin d'afficher le cadre vidéo reçoit du serveur à notre application android,

Le serveur envoie des données vidéo à 50 images par seconde, après avoir encodé dans WebM c'est-à-dire en utilisant libvpx pour encoder et décoder les images,

maintenant après avoir décodé depuis libvpx ses données YUV, que nous pouvons afficher sur la mise en page de l'image,

l'implémentation actuelle est quelque chose comme cela,

EN code JNI / natif C++, Nous sommes conversion des données YUV en Données RVB Dans le cadre D'Android, Appel

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;
}  

pour créer l'image bitmap,

pour afficher l'image sur imageView en utilisant le code suivant,

               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");
                }

Ma requête est, dans l'ensemble, cette fonction est prise environ 40 ms, est-il possible de l'optimiser,

1 -- y a-t-il un moyen d'Afficher des données YUV dans imageView ?

2 -- Existe-t-il un autre moyen de créer une Image( image Bitmap) à partir de données RVB? ,

3 -- je crois que je crée toujours l'image, mais je suppose que je devrais créer bitmap une seule fois et faire / fournir un nouveau tampon toujours, comme et quand nous avons reçu.

merci de partager votre point de vue.

22
demandé sur Amitg2k12 2012-02-08 16:05:52

2 réponses

Code suivant résoudre votre problème et il peut prendre moins de temps sur les données de format Yuv parce que la classe YuvImage est fourni avec Android-SDK.

Vous pouvez l'essayer,

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);

ou

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);
    }
}
}
34
répondu Hitesh Patel 2015-01-21 20:22:11

créer un bitmap après avoir obtenu la largeur et la hauteur dans onCreate.

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

Et onPreviewFrame.

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

Et

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;
}

Et Bonus.

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

finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);
-2
répondu Xar E Ahmer 2015-04-30 08:56:29