Reputation: 66
I'm trying to store and manipulate frames of data streaming off of the camera preview. The code to do this is pretty simple (even with converting YUV->RGB), but the framerate is terrible.
If I do nothing but open the preview and write out all the YUV data (640x480 * 1.5 for YUV format), my framerate is less than 8FPS. If I don't do any storage, framerate goes up to 100FPS (which means the callback must be uncoupled from the hardware, but that's no big deal).
Before I keep fighting this, am I just dealing with a limitation in my hardware? Is it unreasonable to ask the phone to store 461k thirty times per second? I realize that it's 13megs/second, but I'm reusing the allocated space. So it's not a memory question, it's a processing speed question, and I honestly don't know if that's an unreasonable request.
Has anyone else tried to manipulate data streamed off of an Android camera?
Thanks for taking the time to read this.
Upvotes: 0
Views: 5332
Reputation: 5980
From the description of the question, I am clear that the issue is purely due to the very high datarate of your file-write into the system. As you have rightly pointed out, storing 30 VGA (640x480)
images amounts to 13.2 MBytes/sec, which is roughly 106 Mbits/sec. This is extremely high data-rate and storing the same would require a very high speed storage media along with relevant software changes.
If you are storing the uncompressed YUV
frames into SD-Card, from the specifications of the SD-Card, you can find that you would require a UHS
class of card. Please refer to this link for more details on the same: http://en.wikipedia.org/wiki/Secure_Digital#Speed_Class_Rating
If you are storing into internal flash memory, you would have to find out the max. data transfer rate of your memory device to know your theoretical limits.
To summarize, if you wish to store 30 VGA frames/sec, then
The file write would have to be asynchronous in a separate thread as already pointed out by Alex Chap.
The priority of this thread should be carefully chosen in order to ensure that it doesn't contend with other active threads in your system. File system writes at times can take some time and if your thread is blocked due to the file-system update, then you can potentially land up choking your system, if the priority is not carefully chosen.
The number of buffers in the queue will have to be carefully chosen. The sink i.e. file-write of your YUV
frames will be the slower part of the chain. In order to reuse a fixed set of buffers, you will have to determine the number of buffers which can handle the jitter in the system i.e. even though the file-write is slow, you can still keep continuing the capture of video frames. This will have a huge impact on the memory requirement of your use-case.
Upvotes: 1
Reputation: 59
My first question is, do you use Previewcallbacks in order to process bytes coming from the Preview ?
If yes, a method to improve the framerate is to use a preview Callback with buffers. See http://developer.android.com/reference/android/hardware/Camera.html#setPreviewCallbackWithBuffer%28android.hardware.Camera.PreviewCallback%29 for a reference.
Another nice possibility is to put your processing in a separated thread. Here's an example :
private ExecutorService processingExecutor;
// ...
this.processingExecutor = Executors.newSingleThreadExecutor();
public void onPreviewFrame(final byte[] data, final Camera camera) {
processingExecutor.execute(new Runnable() {
public void run() {
processImage(data);
}
});
// update your view here
camera.addCallbackBuffer(data);
}
protected void processImage(byte[] data) {
// do you processing here
}
Don't forget that the Views can only be updated from the UI thread.
Upvotes: 4