一、快速点击拍照按钮闪退

修改UVCButtonCallback.cpp文件里的uvc_button_callback方法

修改前:

1
2
3
4
5
6
7
8
9
10
11
12
13
void UVCButtonCallback::uvc_button_callback(int button, int state, void *user_ptr) {

UVCButtonCallback *buttonCallback = reinterpret_cast<UVCButtonCallback *>(user_ptr);

JavaVM *vm = getVM();
JNIEnv *env;
// attach to JavaVM
vm->AttachCurrentThread(&env, NULL);

buttonCallback->notifyButtonCallback(env, button, state);

vm->DetachCurrentThread();
}

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void UVCButtonCallback::uvc_button_callback(int button, int state, void *user_ptr) {
UVCButtonCallback *buttonCallback = reinterpret_cast<UVCButtonCallback *>(user_ptr);

JavaVM *vm = getVM();
JNIEnv *env;
bool isAttached = false;

int status = vm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (status < 0) {
// attach to JavaVM
if (vm->AttachCurrentThread(&env, NULL)) {
return;
}
isAttached = true;
}

buttonCallback->notifyButtonCallback(env, button, state);

if (isAttached) {
vm->DetachCurrentThread();
}
}

二、拔出设备闪退

2.1 修改android_usbfs.c和linux_usbfs.c文件里的handle_iso_completion方法

1
2
3
4
5
6
7
8
	usbi_mutex_lock(&itransfer->lock);
for (i = 0; i < num_urbs; i++) {
- if (urb == tpriv->iso_urbs[i]) {
+ if (tpriv->iso_urbs != NULL && urb == tpriv->iso_urbs[i]) {
urb_idx = i + 1;
break;
}
}

或者增加判空逻辑:

1
2
3
if (tpriv->iso_urbs == NULL) {
break;
}

修改后:

1
2
3
4
5
6
7
8
9
10
usbi_mutex_lock(&itransfer->lock);
for (i = 0; i < num_urbs; i++) {
if (tpriv->iso_urbs == NULL) {
break;
}
if (urb == tpriv->iso_urbs[i]) {
urb_idx = i + 1;
break;
}
}

2.2 修改stream.c文件里的_uvc_delete_transfer方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
static void _uvc_delete_transfer(struct libusb_transfer *transfer) {
ENTER();

// MARK("");
uvc_stream_handle_t *strmh = transfer->user_data;
if (UNLIKELY(!strmh)) EXIT(); // XXX
int i;

pthread_mutex_lock(&strmh->cb_mutex); // XXX crash while calling uvc_stop_streaming
{
// Mark transfer as deleted.
for (i = 0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) {
if (strmh->transfers[i] == transfer) {
libusb_cancel_transfer(strmh->transfers[i]); // XXX 20141112追加
UVC_DEBUG("Freeing transfer %d (%p)", i, transfer);
free(transfer->buffer);
- libusb_free_transfer(transfer); // 需要注释此行
strmh->transfers[i] = NULL;
break;
}
}
if (UNLIKELY(i == LIBUVC_NUM_TRANSFER_BUFS)) {
UVC_DEBUG("transfer %p not found; not freeing!", transfer);
}

pthread_cond_broadcast(&strmh->cb_cond);
}
pthread_mutex_unlock(&strmh->cb_mutex);
EXIT();
}

注释掉第17行代码://libusb_free_transfer(transfer);

三、预览偶现闪退

3.1 修改UVCPreview.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class UVCPreview {
private:
uvc_device_handle_t *mDeviceHandle;
ANativeWindow *mPreviewWindow;
volatile bool mIsRunning;
int requestWidth, requestHeight, requestMode;
int requestMinFps, requestMaxFps;
float requestBandwidth;
int frameWidth, frameHeight;
int frameMode;
size_t frameBytes;
pthread_t preview_thread;
pthread_mutex_t preview_mutex;
pthread_cond_t preview_sync;
ObjectArray<uvc_frame_t *> previewFrames;
int previewFormat;
size_t previewBytes;
//
volatile bool mIsCapturing;
+ volatile bool mHasCaptureThread;
ANativeWindow *mCaptureWindow;

新增第20行如下代码:

1
volatile bool mHasCaptureThread;

3.2 修改UVCPreview.cpp文件

do_preview:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void UVCPreview::do_preview(uvc_stream_ctrl_t *ctrl) {
ENTER();

uvc_frame_t *frame = NULL;
uvc_frame_t *frame_mjpeg = NULL;
uvc_error_t result = uvc_start_streaming_bandwidth(
mDeviceHandle, ctrl, uvc_preview_frame_callback, (void *)this, requestBandwidth, 0);

+ mHasCaptureThread = false;
if (LIKELY(!result)) {
clearPreviewFrame();
- pthread_create(&capture_thread, NULL, capture_thread_func, (void *)this);
+ if (pthread_create(&capture_thread, NULL, capture_thread_func, (void *)this) == 0) {
+ mHasCaptureThread = true;
+ }

修改后的代码:

1
2
3
4
5
6
mHasCaptureThread = false;
if (LIKELY(!result)) {
clearPreviewFrame();
if (pthread_create(&capture_thread, NULL, capture_thread_func, (void *)this) == 0) {
mHasCaptureThread = true;
}

do_capture_callback:
修改前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* call IFrameCallback#onFrame if needs
*/
void UVCPreview::do_capture_callback(JNIEnv *env, uvc_frame_t *frame) {
ENTER();

if (LIKELY(frame)) {
uvc_frame_t *callback_frame = frame;
if (mFrameCallbackObj) {
if (mFrameCallbackFunc) {
callback_frame = get_frame(callbackPixelBytes);
if (LIKELY(callback_frame)) {
int b = mFrameCallbackFunc(frame, callback_frame);
recycle_frame(frame);
if (UNLIKELY(b)) {
LOGW("failed to convert for callback frame");
goto SKIP;
}
} else {
LOGW("failed to allocate for callback frame");
callback_frame = frame;
goto SKIP;
}
}
jobject buf = env->NewDirectByteBuffer(callback_frame->data, callbackPixelBytes);
env->CallVoidMethod(mFrameCallbackObj, iframecallback_fields.onFrame, buf);
env->ExceptionClear();
env->DeleteLocalRef(buf);
}
SKIP:
recycle_frame(callback_frame);
}
EXIT();
}

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* call IFrameCallback#onFrame if needs
*/
void UVCPreview::do_capture_callback(JNIEnv *env, uvc_frame_t *frame) {
ENTER();

if (LIKELY(frame)) {
uvc_frame_t *callback_frame = frame;
if (mFrameCallbackObj) {
if (mFrameCallbackFunc) {
callback_frame = get_frame(callbackPixelBytes);
if (LIKELY(callback_frame)) {
int b = mFrameCallbackFunc(frame, callback_frame);
recycle_frame(frame);
if (UNLIKELY(b)) {
LOGW("failed to convert for callback frame");
goto SKIP;
}
} else {
LOGW("failed to allocate for callback frame");
callback_frame = frame;
goto SKIP;
}
}
jobject buf = env->NewDirectByteBuffer(callback_frame->data, callbackPixelBytes);
// 以下3行为改变的代码
if (iframecallback_fields.onFrame) {
env->CallVoidMethod(mFrameCallbackObj, iframecallback_fields.onFrame, buf);
}
// 以上3行为改变的代码
env->ExceptionClear();
env->DeleteLocalRef(buf);
}
SKIP:
recycle_frame(callback_frame);
}
EXIT();
}

stopPreview:
修改前:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int UVCPreview::stopPreview() {
ENTER();
bool b = isRunning();
if (LIKELY(b)) {
mIsRunning = false;
pthread_cond_signal(&preview_sync);
pthread_cond_signal(&capture_sync);
if (pthread_join(capture_thread, NULL) != EXIT_SUCCESS) {
LOGW("UVCPreview::terminate capture thread: pthread_join failed");
}
if (pthread_join(preview_thread, NULL) != EXIT_SUCCESS) {
LOGW("UVCPreview::terminate preview thread: pthread_join failed");
}
clearDisplay();
}
clearPreviewFrame();
clearCaptureFrame();
pthread_mutex_lock(&preview_mutex);
if (mPreviewWindow) {
ANativeWindow_release(mPreviewWindow);
mPreviewWindow = NULL;
}
pthread_mutex_unlock(&preview_mutex);
pthread_mutex_lock(&capture_mutex);
if (mCaptureWindow) {
ANativeWindow_release(mCaptureWindow);
mCaptureWindow = NULL;
}
pthread_mutex_unlock(&capture_mutex);
RETURN(0, int);
}

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int UVCPreview::stopPreview() {
ENTER();
bool b = isRunning();
if (LIKELY(b)) {
mIsRunning = false;
pthread_cond_signal(&preview_sync);
// 以下6行为改变的代码
if (mHasCaptureThread) {
pthread_cond_signal(&capture_sync);
if (pthread_join(capture_thread, NULL) != EXIT_SUCCESS) {
LOGW("UVCPreview::terminate capture thread: pthread_join failed");
}
}
// 以上6行为改变的代码
if (pthread_join(preview_thread, NULL) != EXIT_SUCCESS) {
LOGW("UVCPreview::terminate preview thread: pthread_join failed");
}
clearDisplay();
}
clearPreviewFrame();
clearCaptureFrame();
pthread_mutex_lock(&preview_mutex);
if (mPreviewWindow) {
ANativeWindow_release(mPreviewWindow);
mPreviewWindow = NULL;
}
pthread_mutex_unlock(&preview_mutex);
pthread_mutex_lock(&capture_mutex);
if (mCaptureWindow) {
ANativeWindow_release(mCaptureWindow);
mCaptureWindow = NULL;
}
pthread_mutex_unlock(&capture_mutex);
RETURN(0, int);
}

UVCCamera相关内容

参考链接:https://blog.csdn.net/u011630465/article/details/118968297