我在我的应用程序中使用UVCCamera。该库使用了大量的线程工作,这使我感到困惑,而且我无法跟踪调用回调的位置。例如,我需要在onFrame
方法中获取预览帧并对其应用效果,但是问题是,不清楚何时调用onFrame方法。 Android线程文档和专家说,在同一线程中调用了在runnable中设置的回调。因此,我在启动摄像头的线程中定义了IFrameCallback
,但Logcat仍然显示从未调用过onFrame
方法。
private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
@Override
public void onAttach(final UsbDevice device) {
Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
releaseCamera();
queueEvent(new Runnable() {
@Override
public void run() {
final UVCCamera camera = new UVCCamera();
camera.open(ctrlBlock);
camera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_YUV);
Log.d(TAG, "run: mIFrameCallback set");
camera.setStatusCallback(new IStatusCallback() {
@Override
public void onStatus(final int statusClass, final int event, final int selector,
final int statusAttribute, final ByteBuffer data) {
Log.d(TAG, "onStatus: ");
runOnUiThread(new Runnable() {
@Override
public void run() {
final Toast toast = Toast.makeText(MainActivity.this, "onStatus(statusClass=" + statusClass
+ "; " +
"event=" + event + "; " +
"selector=" + selector + "; " +
"statusAttribute=" + statusAttribute + "; " +
"data=...)", Toast.LENGTH_SHORT);
synchronized (mSync) {
if (mToast != null) {
mToast.cancel();
}
toast.show();
mToast = toast;
}
}
});
}
});
camera.setButtonCallback(new IButtonCallback() {
@Override
public void onButton(final int button, final int state) {
Log.d(TAG, "onButton: button callback");
runOnUiThread(new Runnable() {
@Override
public void run() {
final Toast toast = Toast.makeText(MainActivity.this, "onButton(button=" + button + "; " +
"state=" + state + ")", Toast.LENGTH_SHORT);
synchronized (mSync) {
if (mToast != null) {
mToast.cancel();
}
mToast = toast;
toast.show();
}
}
});
}
});
// camera.setPreviewTexture(camera.getSurfaceTexture());
if (mPreviewSurface != null) {
mPreviewSurface.release();
mPreviewSurface = null;
}
try {
camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.FRAME_FORMAT_MJPEG);
} catch (final IllegalArgumentException e) {
// fallback to YUV mode
try {
camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.DEFAULT_PREVIEW_MODE);
} catch (final IllegalArgumentException e1) {
camera.destroy();
return;
}
}
final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
if (st != null) {
mPreviewSurface = new Surface(st);
camera.setPreviewDisplay(mPreviewSurface);
// camera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_RGB565/*UVCCamera.PIXEL_FORMAT_NV21*/);
camera.startPreview();
}
synchronized (mSync) {
mUVCCamera = camera;
mUVCCamera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_NV21);
}
}
private final IFrameCallback mIFrameCallback = new IFrameCallback() {
@Override
public void onFrame(final ByteBuffer frame) {
frame.clear();
synchronized (bitmap) {
bitmap.copyPixelsFromBuffer(frame);
Log.d(TAG, "onFrame: frame length: " + frame.array().length);
}
mImageView.post(mUpdateImageTask);
}
};
}, 0);
}
@Override
public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
// XXX you should check whether the coming device equal to camera device that currently using
releaseCamera();
}
@Override
public void onDettach(final UsbDevice device) {
Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel(final UsbDevice device) {
}
};
答案 0 :(得分:0)
正如您在问题中所看到的,IFrameCallback是在可运行内部定义的。错了应该在onConnect方法之外定义它,然后将其作为变量传递给setFrameCallback。至少,我可以看到这对我有用:
private final IFrameCallback mIFrameCallback = new IFrameCallback() {
@Override
public void onFrame(final ByteBuffer frame) {
Log.d("Inside onFrame");
}
};
private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
@Override
public void onAttach(final UsbDevice device) {
Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
releaseCamera();
queueEvent(new Runnable() {
@Override
public void run() {
final UVCCamera camera = new UVCCamera();
camera.open(ctrlBlock);
camera.setStatusCallback(new IStatusCallback() {
@Override
public void onStatus(final int statusClass, final int event, final int selector,
final int statusAttribute, final ByteBuffer data) {
Log.d(TAG, "onStatus: ");
runOnUiThread(new Runnable() {
@Override
public void run() {
final Toast toast = Toast.makeText(MainActivity.this, "onStatus(statusClass=" + statusClass
+ "; " +
"event=" + event + "; " +
"selector=" + selector + "; " +
"statusAttribute=" + statusAttribute + "; " +
"data=...)", Toast.LENGTH_SHORT);
synchronized (mSync) {
if (mToast != null) {
mToast.cancel();
}
// toast.show();
mToast = toast;
}
}
});
}
});
camera.setButtonCallback(new IButtonCallback() {
@Override
public void onButton(final int button, final int state) {
Log.d(TAG, "onButton: button callback");
runOnUiThread(new Runnable() {
@Override
public void run() {
final Toast toast = Toast.makeText(MainActivity.this, "onButton(button=" + button + "; " +
"state=" + state + ")", Toast.LENGTH_SHORT);
synchronized (mSync) {
if (mToast != null) {
mToast.cancel();
}
mToast = toast;
toast.show();
}
}
});
}
});
// camera.setPreviewTexture(camera.getSurfaceTexture());
if (mPreviewSurface != null) {
mPreviewSurface.release();
mPreviewSurface = null;
}
try {
camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.FRAME_FORMAT_MJPEG);
} catch (final IllegalArgumentException e) {
try {
camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.DEFAULT_PREVIEW_MODE);
} catch (final IllegalArgumentException e1) {
camera.destroy();
return;
}
}
final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
if (st != null) {
mPreviewSurface = new Surface(st);
camera.setPreviewDisplay(mPreviewSurface);
camera.setFrameCallback(mIFrameCallback, UVCCamera.PIXEL_FORMAT_YUV420SP);
camera.startPreview();
}
synchronized (mSync) {
mUVCCamera = camera;
}
}
}, 0);
}