From 33a97577c9b8dca35fa565412f33e807d515ac32 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 6 Feb 2018 12:30:12 -0800 Subject: [PATCH] Move QR decoding back to UI thread. --- source/core/task/capturecam.c | 72 ++----------------------------- source/core/task/capturecam.h | 6 --- source/core/util.h | 7 ++- source/ui/error.c | 2 - source/ui/section/remoteinstall.c | 61 +++++++++++++++++++++----- 5 files changed, 58 insertions(+), 90 deletions(-) diff --git a/source/core/task/capturecam.c b/source/core/task/capturecam.c index 39cb108..4891045 100644 --- a/source/core/task/capturecam.c +++ b/source/core/task/capturecam.c @@ -6,7 +6,6 @@ #include "capturecam.h" #include "task.h" #include "../util.h" -#include "../../libs/quirc/quirc.h" #define EVENT_CANCEL 0 #define EVENT_RECV 1 @@ -14,17 +13,8 @@ #define EVENT_COUNT 3 -typedef struct { - capture_cam_data* data; - - struct quirc* qrContext; -} capture_cam_internal_data; - static void task_capture_cam_thread(void* arg) { - capture_cam_internal_data* internalData = (capture_cam_internal_data*) arg; - capture_cam_data* data = internalData->data; - - data->qrReady = false; + capture_cam_data* data = (capture_cam_data*) arg; Handle events[EVENT_COUNT] = {0}; events[EVENT_CANCEL] = data->cancelEvent; @@ -73,37 +63,6 @@ static void task_capture_cam_thread(void* arg) { GSPGPU_FlushDataCache(data->buffer, bufferSize); svcReleaseMutex(data->mutex); - if(data->scanQR) { - int w = 0; - int h = 0; - uint8_t* qrBuf = quirc_begin(internalData->qrContext, &w, &h); - - for(int x = 0; x < w; x++) { - for(int y = 0; y < h; y++) { - u16 px = buffer[y * data->width + x]; - qrBuf[y * w + x] = (u8) (((((px >> 11) & 0x1F) << 3) + (((px >> 5) & 0x3F) << 2) + ((px & 0x1F) << 3)) / 3); - } - } - - quirc_end(internalData->qrContext); - - int qrCount = quirc_count(internalData->qrContext); - for(int i = 0; i < qrCount; i++) { - struct quirc_code qrCode; - quirc_extract(internalData->qrContext, i, &qrCode); - - struct quirc_data qrData; - if(quirc_decode(&qrCode, &qrData) == 0) { - svcWaitSynchronization(data->mutex, U64_MAX); - - data->qrReady = true; - memcpy(data->qrData, qrData.payload, sizeof(data->qrData)); - - svcReleaseMutex(data->mutex); - } - } - } - res = CAMU_SetReceiving(&events[EVENT_RECV], buffer, PORT_CAM1, bufferSize, (s16) transferUnit); break; case EVENT_BUFFER_ERROR: @@ -150,9 +109,6 @@ static void task_capture_cam_thread(void* arg) { } } - quirc_destroy(internalData->qrContext); - free(internalData); - svcCloseHandle(data->mutex); data->result = res; @@ -164,43 +120,23 @@ Result task_capture_cam(capture_cam_data* data) { return R_FBI_INVALID_ARGUMENT; } - capture_cam_internal_data* internalData = (capture_cam_internal_data*) calloc(1, sizeof(capture_cam_internal_data)); - if(internalData == NULL) { - return R_FBI_OUT_OF_MEMORY; - } - data->mutex = 0; data->finished = false; data->result = 0; data->cancelEvent = 0; - internalData->data = data; - Result res = 0; - internalData->qrContext = quirc_new(); - if(internalData->qrContext != NULL && quirc_resize(internalData->qrContext, data->width, data->height) == 0) { - if(R_SUCCEEDED(res = svcCreateEvent(&data->cancelEvent, RESET_STICKY)) && R_SUCCEEDED(res = svcCreateMutex(&data->mutex, false))) { - if(threadCreate(task_capture_cam_thread, internalData, 0x10000, 0x1A, 1, true) == NULL) { - res = R_FBI_THREAD_CREATE_FAILED; - } + if(R_SUCCEEDED(res = svcCreateEvent(&data->cancelEvent, RESET_STICKY)) && R_SUCCEEDED(res = svcCreateMutex(&data->mutex, false))) { + if(threadCreate(task_capture_cam_thread, data, 0x10000, 0x1A, 0, true) == NULL) { + res = R_FBI_THREAD_CREATE_FAILED; } - } else { - res = R_FBI_QR_INIT_FAILED; } - if(R_FAILED(res)) { data->finished = true; - if(internalData->qrContext != NULL) { - quirc_destroy(internalData->qrContext); - internalData->qrContext = NULL; - } - - free(internalData); - if(data->cancelEvent != 0) { svcCloseHandle(data->cancelEvent); data->cancelEvent = 0; diff --git a/source/core/task/capturecam.h b/source/core/task/capturecam.h index adbb075..23e2a05 100644 --- a/source/core/task/capturecam.h +++ b/source/core/task/capturecam.h @@ -1,7 +1,5 @@ #pragma once -#define CAMERA_QR_DATA_MAX 8896 - typedef enum capture_cam_camera_e { CAMERA_OUTER, CAMERA_INNER @@ -12,10 +10,6 @@ typedef struct capture_cam_data_s { s16 width; s16 height; capture_cam_camera camera; - bool scanQR; - - bool qrReady; - u8 qrData[CAMERA_QR_DATA_MAX]; Handle mutex; diff --git a/source/core/util.h b/source/core/util.h index 2d8f50a..e1d9639 100644 --- a/source/core/util.h +++ b/source/core/util.h @@ -10,13 +10,12 @@ typedef struct json_t json_t; #define R_FBI_PARSE_FAILED MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 5) #define R_FBI_BAD_DATA MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 6) #define R_FBI_TOO_MANY_REDIRECTS MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 7) -#define R_FBI_QR_INIT_FAILED MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 8) -#define R_FBI_CURL_INIT_FAILED MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 9) -#define R_FBI_HTTP_ERROR_BASE MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 10) +#define R_FBI_HTTP_ERROR_BASE MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 8) #define R_FBI_HTTP_ERROR_END (R_FBI_HTTP_ERROR_BASE + 600) -#define R_FBI_CURL_ERROR_BASE (R_FBI_HTTP_ERROR_END + 1) +#define R_FBI_CURL_INIT_FAILED (R_FBI_HTTP_ERROR_END + 1) +#define R_FBI_CURL_ERROR_BASE (R_FBI_CURL_INIT_FAILED + 1) #define R_FBI_NOT_IMPLEMENTED MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, RD_NOT_IMPLEMENTED) #define R_FBI_OUT_OF_MEMORY MAKERESULT(RL_FATAL, RS_OUTOFRESOURCE, RM_APPLICATION, RD_OUT_OF_MEMORY) diff --git a/source/ui/error.c b/source/ui/error.c index 889c6ca..36e4379 100644 --- a/source/ui/error.c +++ b/source/ui/error.c @@ -503,8 +503,6 @@ static const char* description_to_string(Result res) { return "Bad data"; case R_FBI_TOO_MANY_REDIRECTS: return "Too many redirects"; - case R_FBI_QR_INIT_FAILED: - return "Failed to initialize QR code parser."; case R_FBI_CURL_INIT_FAILED: return "Failed to initialize CURL."; default: diff --git a/source/ui/section/remoteinstall.c b/source/ui/section/remoteinstall.c index ecb162b..4b521ca 100644 --- a/source/ui/section/remoteinstall.c +++ b/source/ui/section/remoteinstall.c @@ -251,6 +251,7 @@ static void remoteinstall_receive_urls_network() { #define QR_IMAGE_HEIGHT 240 typedef struct { + struct quirc* qrContext; u32 tex; bool capturing; @@ -285,6 +286,11 @@ static void remoteinstall_qr_free_data(remoteinstall_qr_data* data) { data->tex = 0; } + if(data->qrContext != NULL) { + quirc_destroy(data->qrContext); + data->qrContext = NULL; + } + free(data); } @@ -348,17 +354,39 @@ static void remoteinstall_qr_update(ui_view* view, void* data, float* progress, return; } + int w = 0; + int h = 0; + uint8_t* qrBuf = quirc_begin(installData->qrContext, &w, &h); + svcWaitSynchronization(installData->captureInfo.mutex, U64_MAX); - if(installData->captureInfo.qrReady) { - remoteinstall_set_last_urls((const char*) installData->captureInfo.qrData); - action_install_url("Install from the scanned QR code?", (const char*) installData->captureInfo.qrData, NULL, NULL, NULL, NULL); - installData->captureInfo.qrReady = false; - svcReleaseMutex(installData->captureInfo.mutex); + for(int x = 0; x < w; x++) { + for(int y = 0; y < h; y++) { + u16 px = installData->captureInfo.buffer[y * QR_IMAGE_WIDTH + x]; + qrBuf[y * w + x] = (u8) (((((px >> 11) & 0x1F) << 3) + (((px >> 5) & 0x3F) << 2) + ((px & 0x1F) << 3)) / 3); + } + } - remoteinstall_qr_stop_capture(installData); - } else { - svcReleaseMutex(installData->captureInfo.mutex); + svcReleaseMutex(installData->captureInfo.mutex); + + quirc_end(installData->qrContext); + + int qrCount = quirc_count(installData->qrContext); + for(int i = 0; i < qrCount; i++) { + struct quirc_code qrCode; + quirc_extract(installData->qrContext, i, &qrCode); + + struct quirc_data qrData; + quirc_decode_error_t err = quirc_decode(&qrCode, &qrData); + + if(err == 0) { + remoteinstall_qr_stop_capture(installData); + + remoteinstall_set_last_urls((const char*) qrData.payload); + + action_install_url("Install from the scanned QR code?", (const char*) qrData.payload, NULL, NULL, NULL, NULL); + return; + } } snprintf(text, PROGRESS_TEXT_MAX, "Waiting for QR code..."); @@ -381,10 +409,23 @@ static void remoteinstall_scan_qr_code() { data->captureInfo.camera = CAMERA_OUTER; - data->captureInfo.scanQR = true; - data->captureInfo.finished = true; + data->qrContext = quirc_new(); + if(data->qrContext == NULL) { + error_display(NULL, NULL, "Failed to create QR context."); + + remoteinstall_qr_free_data(data); + return; + } + + if(quirc_resize(data->qrContext, QR_IMAGE_WIDTH, QR_IMAGE_HEIGHT) != 0) { + error_display(NULL, NULL, "Failed to resize QR context."); + + remoteinstall_qr_free_data(data); + return; + } + data->captureInfo.buffer = (u16*) calloc(1, QR_IMAGE_WIDTH * QR_IMAGE_HEIGHT * sizeof(u16)); if(data->captureInfo.buffer == NULL) { error_display(NULL, NULL, "Failed to create image buffer.");