Search code examples
androidperformancepreviewframe-rate

What is the best way to store android preview frames at 30 FPS?


We are working on a project that utilizes Android preview feature. We are capturing preview at maximum available resolution (1600 x 1200 at present).

Requirement is to save each and every frame of preview on secondary storage. OnPreviewFrame is capable of giving preview at 30 FPS (approx. 30 milliseconds/frame) but when code is added to save the data, it limits the FPS.

Tested so far:

  1. Both OnPreviewFrame and Saving JPEG in the Main thread. In this case, saving roughly takes 250-260 milliseconds. So, FPS becomes 5-6.

  2. OnPreviewFrame in main thread and Saving JPEG in another thread. So, a new thread is created for each frame for saving. It creates a lot if threads in memory (each taking approx. 450-500 ms for quality factor 60) and when memory is freed, a gap is observed in the preview.

So, it there any possible workaround by which we can save all the frames at 30 FPS?

YuvImage yuvImage = new YuvImage(data, activity.previewFormat, activity.previewWidth, activity.previewHeight, null);
FileOutputStream fos = new FileOutputStream(this.file);
yuvImage.compressToJpeg(new Rect(0, 0, activity.previewWidth, activity.previewHeight), 60, fos);
fos.flush();
fos.close();

Solution

  • You are doing a lot of resource consuming operations. some can't be avoided like the disk I/O, the others can be significantly reduced.

    1. Memory allocation and de-allocation (GC) is very expensive task. consider pre-allocating 15-30 frames and using a frame pool.
    2. Thread creation is very expensive. consider using one background thread which will poll some queue for frames and return the frame to the frame pool after it is saved. (If a single thread is not up to the task of saving the file on time, consider a thread pool which are allocated in advance).
    3. I/O must be done on a background thread like you suggested.