我正在创建一个实时流媒体应用,但我陷入了某种困境。 所以,这是我的代码:
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();
}
};
当调用synchronized getPicture()时,在执行时,没有其他线程可以在该实例上调用synchronized方法。当getPicture()等待isDecoding时,它正在对实例进行锁定。我怀疑setOneShotPreviewCallback()正在执行,并且相机正在尝试在其自己的线程上调用onPreviewFrame(),但因为这也是一个同步方法,它阻止等待getPicture()终止,因为它需要回调到清楚是解码。这看起来像是一个僵局。
它无法调用onPreviewFrame,因为对象实例已被锁定,因此相机线程被阻塞,等待getPicture()完成。
我说错了吗? 我该如何解决这个问题呢?所以我必须再次通知OnPreviewFrame,IsDecoding = false
非常感谢任何帮助。
同时投票,我将给予赏金;)
答案 0 :(得分:1)
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。