Problem with a laggy application using threads
It is my understanding (please correct me if i'm way off the mark) that my using threads correctly will allow an application to seem to multitask despite high processor load.
In my application I have a thread in which I process images taken from the camera preview and attempt to do real-time face detection with a great deal of success. The problem lies when at the same time as this I want to be able to have a button on the screen which can be pressed and some action taken without any relation to what is going on to the camera detection methods.
The problem is the face detection is pretty quick, but when I go to press the button it takes a good second or so to respond to this. Without the face detection thread being activated (i.e. the start() method never being called) the button is very quick. Below is a stripped version of my code as it's too long just to post straight as it is:
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
faceThread = new Thread(new Runnable(){
public void run(){
//Get camera preview image and detect faces
}
});
faceThread.start();
}
public void onClickShoot(View v) throws InterruptedException,
media = new MediaPlayer();
media.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
media.stop();
media.reset();
}
});
media.setDataSource(this, dataPath);
media.prepare();
media.start();
//And some other stuff here too.
开发者_StackOverflow社区
}
Is it just a limitation that I have this delay on the fact it's a mobile platform and i'm expecting too much? Or is there a way of making this work? I'f you need more info about what i'm doing please just ask :).
Edit (more code to address problem):
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(final byte[] _data, Camera _camera) {
Camera.Parameters parameters = mCamera.getParameters();
int format = parameters.getPreviewFormat();
// YUV formats require more conversion
if (format == ImageFormat.NV21) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(_data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w/3, h); // Rect of the image in which to search for the face
final ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 10, output_stream);
// Convert from Jpeg to Bitmap
detectFaces(BitmapFactory.decodeByteArray(
output_stream.toByteArray(), 0,
output_stream.size()));
Log.v("TEST", "TEST");
}
}
});
public void detectFaces(Bitmap bmp) {
FaceView faceView = new FaceView(this, bmp);
}
You need to determine where the contention is. Is it for CPU time, or is it for some other resource? It might help to do some profiling... Tim Bray recently wrote a good introduction to how and why to do this here: http://android-developers.blogspot.com/2010/10/traceview-war-story.html
For what it's worth MediaPlayer
is notoriously slow and heavyweight. What media are you giving it? Are you giving it a stream or buffer that's mostly in memory, or will it be doing tons of I/O to read media over the network or from storage?
Out of interest, why do you need face detection once the button has been pressed? Maybe you could stop the thread before starting up the media player?
精彩评论