Move QR decoding back to UI thread.

This commit is contained in:
Steven Smith 2018-02-06 12:30:12 -08:00
parent 2c982d85ec
commit 33a97577c9
5 changed files with 58 additions and 90 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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:

View File

@ -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.");