Reputation: 868
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
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