一、快速点击拍照按钮闪退 {#一、快速点击拍照按钮闪退}
修改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相关内容}
- Android UVCCamera 简介
- Android UVCCamera基本库介绍
- Android UVCCamera调用过程介绍
- 解决Android UVCCamera项目编译和运行报错的问题
- Android UVCCamera扫描USB Device的过程和原理分析
- Android UVCCamera闪退问题解决方法
- 解决UVCCamera拔出USB摄像头APP崩溃(闪退)的问题
- Android中多USB摄像头解决方案 ------ UVCCamera
- UVCCamera源码分析(一)
- UVCCamera源码分析(二)
- UVCCamera源码分析(三)
- UVCCamera源码分析(四)
- UVCCamera源码分析(五)
参考链接:https://blog.csdn.net/u011630465/article/details/118968297