一、快速点击拍照按钮闪退 修改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; 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 ) { 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 (); uvc_stream_handle_t *strmh = transfer->user_data; if (UNLIKELY (!strmh)) EXIT (); int i; pthread_mutex_lock (&strmh->cb_mutex); { for (i = 0 ; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { if (strmh->transfers[i] == transfer) { libusb_cancel_transfer (strmh->transfers[i]); 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 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 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); if (iframecallback_fields.onFrame) { env->CallVoidMethod (mFrameCallbackObj, iframecallback_fields.onFrame, buf); } 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); if (mHasCaptureThread) { 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 ); }
UVCCamera相关内容
参考链接:https://blog.csdn.net/u011630465/article/details/118968297