N0un
N0un

Reputation: 868

How to process efficiently with ImageView in a video render case?

I'm working on a video streaming app. It's a particularly case and I need to process each frame manually (from network access to decode and other treatments). At the end of all my process, for each frame, I have a byte[] containing ARGB_8888 encoded image.

For now, I draw each frame this way (assuming width = 1280 and height = 720, and data is my byte[] containing the frame, and imageView is my ImageView container)

// Step 1: reception and treatments
// After that, data contains the frame bytes;

// Step 2: bitmap creation
Bitmap toDraw = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
toDraw.copyPixelsFromBuffer(ByteBuffer.wrap(data));

// Step 3: draw the bitmap
imageView.post(new Runnable() {

    @Override
    public void run()
    {
        imageView.setImageBitmap(toDraw);
    }
});

All works fine, no problem with that. But I have a lot of GC and I really don't like creating a new Bitmap each time for each same-size frame! So I need to know how can I optimize my frames render? I know that I can call createBitmap only the first time then only use copyPixelsFromBuffer to fill it (even if it makes a copy and I don't like it but it's better). An intuitive solution comes to me but I don't know if it's possible or not:

What if I create and draw a Bitmap only the first time, and then I retrieve reference to pixels from imageView and modify it or directly or give my data as reference? I searched about DrawingCache but found no solution.

Otherwise, any idea to do better than this code (by better I mean memory-friendly and faster)? Question is: what is the best way to quickly update my imageView providing my already decoded byte[] data (for each frame).


EDIT: I just see that. I'll test and continue to investigate.

Upvotes: 1

Views: 177

Answers (1)

lelloman
lelloman

Reputation: 14183

you can create the bitmap only if needed, if it's null or if it's size is not ok

Bitmap mBitmap;

private void someMethod(){

    if(mBitmap == null || !isBitmapSizeOk(mBitmap)){
        if(mBitmap != null) mBitmap.recycle();

        mBitmap = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
        // call it only when the Bitmap instance changes
        imageView.setImageBitmap(mBitmap); 
    }

    mBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(data));

    // Step 3: draw the bitmap
    imageView.post(new Runnable() {

        @Override
        public void run(){    
            imageView.invalidate();       
        }
    });
}

you can call setImageBitmap(mBitmap) only when creating the Bitmap and avoid to call it every time, however, the ImageView needs to know that it has to redraw itself, you can do that by calling invalidate()

Upvotes: 1

Related Questions