51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Android UVC Camera闪退问题解决方法

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

修改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方法 {#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方法 {#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文件 {#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文件 {#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相关内容 {#UVCCamera相关内容}

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


赞(3)
未经允许不得转载:工具盒子 » Android UVC Camera闪退问题解决方法