开发者

Need help with Synchronized

I am creating a live streaming app, but I'm stuck at a certain point. So, this is my code:

public synchronized byte[] getPicture(int Width, int Height) {
    FrameWidth = Width;
    FrameHeight = Height;

    try {                           
        while (!isPrevie开发者_如何学JAVAwOn) {
            wait();
        }

        isDecoding = true;
        mAvailableFrame = false;

        c.setOneShotPreviewCallback(mPreviewCallback);                

        while (isDecoding) {
            wait();
        }

    }
    catch (Exception e) {   
        return null;
    }

    mAvailableFrame = false;

    return mCurrentFrame;
}

PreviewCallback mPreviewCallback = new PreviewCallback() {

    @Override
    public synchronized void onPreviewFrame(byte[] data, Camera camera) {
        int width = FrameWidth;
        int height = FrameHeight;

        // API 7
        int[] temp = new int[width*height];
        OutputStream out = new ByteArrayOutputStream();
        Bitmap bm = null;

        raw2jpg(temp, data, width, height);
        bm = Bitmap.createBitmap(temp, width, height, Bitmap.Config.RGB_565);
        bm.compress(CompressFormat.JPEG, 100, out);
        /*ref*/mCurrentFrame = ((ByteArrayOutputStream)out).toByteArray();
        mAvailableFrame = true;
        isDecoding = false;
        notify();                   
    }
};

When synchronised getPicture() is called, while it is executing no other thread can call a synchronised method on that instance. While getPicture() is waiting for isDecoding it is holding a lock on the instance. I suspect setOneShotPreviewCallback() is executing and that the camera is trying to call onPreviewFrame() on its own thread but as that is also a synchronised method it blocks waiting for getPicture() to terminate which it can't as it needs the callback to clear isDecoding. It looks like a deadlock situation.

It can't call onPreviewFrame because the object instance is locked so the camera thread is blocked waiting for getPicture() to complete.

Am I correct? And how should I fix this? So I have to notify OnPreviewFrame again that IsDecoding = false

Any help is very much appreciated.

Also vote this up and I will give a bounty ;)


The notify() in mPreviewCallback.onPreviewFrame() notifies the mPreviewCallback object monitor, while wait() in getPicture() waits on another object monitor - notify will never release wait(). You should define a (final) variable accessible from both objects and call wait() and notify() explicitly on that variable. Something like this:

public final Object myMonitor = new Object();

public synchronized byte[] getPicture(int Width, int Height) {
    FrameWidth = Width;
    FrameHeight = Height;

    try {                     
        synchronized(myMonitor) {    
            while (!isPreviewOn) {
                myMonitor.wait();
            }
        }
        isDecoding = true;
        mAvailableFrame = false;

        c.setOneShotPreviewCallback(mPreviewCallback);                

        synchronized(myMonitor) {    
            while (isDecoding) {
                myMonitor.wait();
            }
        }
    }
    catch (Exception e) {   
        return null;
    }

    mAvailableFrame = false;

    return mCurrentFrame;
}

PreviewCallback mPreviewCallback = new PreviewCallback() {

    @Override
    public synchronized void onPreviewFrame(byte[] data, Camera camera) {
        int width = FrameWidth;
        int height = FrameHeight;

        // API 7
        int[] temp = new int[width*height];
        OutputStream out = new ByteArrayOutputStream();
        Bitmap bm = null;

        raw2jpg(temp, data, width, height);
        bm = Bitmap.createBitmap(temp, width, height, Bitmap.Config.RGB_565);
        bm.compress(CompressFormat.JPEG, 100, out);
        /*ref*/mCurrentFrame = ((ByteArrayOutputStream)out).toByteArray();
        mAvailableFrame = true;
        isDecoding = false;
        synchronized(myMonitor) {    
            myMonitor.notify();                   
        }
    }
};

I don't know the API you are extending, but probably the processes won't need to be synchronized after this change. Also, it is not clear who is setting isPreviewOn.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜