我正在创建一个实时流媒体应用程序,但在某个时候遇到了困难。
所以,这是我的代码:
public synchronized byte[] getPicture(int Width, int Height) {
FrameWidth = Width;
FrameHeight = Height;
try {
while (!isPreviewOn) {
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();
}
};
当调用了同步getPicture()时,在执行过程中,没有其他线程可以在该实例上调用同步方法。当getPicture()等待isDecoding时,它将在实例上持有一个锁。我怀疑setOneShotPreviewCallback()正在执行,并且摄像头正在尝试在其自己的线程上调用onPreviewFrame(),但是由于这也是一个同步方法,因此它阻塞了等待getPicture()终止的过程,因为它需要回调才能终止清除isDecoding。看起来像是僵局。
它无法调用onPreviewFrame,因为对象实例已锁定,因此相机线程被阻塞,等待getPicture()完成。
我对么?
我该如何解决呢?所以我必须再次通知OnPreviewFrame IsDecoding = false
很感谢任何形式的帮助。
还要对此投票,我将提供赏金;)
最佳答案
mPreviewCallback.onPreviewFrame()中的notify()通知mPreviewCallback对象监视器,而getPicture()中的wait()等待另一个对象监视器-notify永远不会释放wait()。您应该定义两个对象都可以访问的(最终)变量,并在该变量上显式调用wait()和notify()。像这样:
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();
}
}
};
我不知道您要扩展的API,但是更改之后,可能不需要同步进程。另外,不清楚谁在设置isPreviewOn。