diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 90f152661..0b7e37f5b 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2305,6 +2305,11 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig sqlite3_bctbx_vfs_register(0); #endif + lc->qrcode_rect.h = 0; + lc->qrcode_rect.w = 0; + lc->qrcode_rect.x = 0; + lc->qrcode_rect.y = 0; + lc->vcard_context = linphone_vcard_context_new(); linphone_core_initialize_supported_content_types(lc); lc->bw_controller = ms_bandwidth_controller_new(); @@ -4812,7 +4817,9 @@ static void video_filter_callback(void *userdata, struct _MSFilter *f, unsigned case MS_QRCODE_READER_QRCODE_FOUND: { LinphoneCore *lc = (LinphoneCore *)userdata; if (linphone_core_cbs_get_qrcode_founded(linphone_core_get_current_callbacks(lc)) != NULL) { - linphone_core_notify_qrcode_founded(lc, (const char*)arg); + char* result = ms_strdup((const char*)arg); + linphone_core_notify_qrcode_founded(lc, result); + ms_free(result); } break; } @@ -4859,20 +4866,30 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ if (!vdef || linphone_video_definition_is_undefined(vdef)) { vdef = linphone_core_get_preferred_video_definition(lc); } - vsize.width = (int)linphone_video_definition_get_width(vdef); - vsize.height = (int)linphone_video_definition_get_height(vdef); - lc->previewstream=video_preview_new(lc->factory); + if (linphone_core_qrcode_video_preview_enabled(lc)) { + vsize.width = 720; + vsize.height = 1280; + } else { + vsize.width = (int)linphone_video_definition_get_width(vdef); + vsize.height = (int)linphone_video_definition_get_height(vdef); + } + lc->previewstream = video_preview_new(lc->factory); video_preview_set_size(lc->previewstream,vsize); if (display_filter) video_preview_set_display_filter_name(lc->previewstream,display_filter); if (lc->preview_window_id != NULL) video_preview_set_native_window_id(lc->previewstream,lc->preview_window_id); video_preview_set_fps(lc->previewstream,linphone_core_get_preferred_framerate(lc)); - if (linphone_core_qrcode_video_preview_enabled(lc)) + if (linphone_core_qrcode_video_preview_enabled(lc)) { video_preview_enable_qrcode(lc->previewstream, TRUE); + if (lc->qrcode_rect.w != 0 && lc->qrcode_rect.h != 0) { + video_preview_set_decode_rect(lc->previewstream, lc->qrcode_rect); + } + } video_preview_start(lc->previewstream,lc->video_conf.device); - if (video_preview_qrcode_enabled(lc->previewstream)) + if (video_preview_qrcode_enabled(lc->previewstream)) { ms_filter_add_notify_callback(lc->previewstream->qrcode, video_filter_callback, lc, TRUE); + } } }else{ if (lc->previewstream!=NULL){ @@ -5057,6 +5074,17 @@ bool_t linphone_core_qrcode_video_preview_enabled(const LinphoneCore *lc) { return lc->video_conf.qrcode_decoder; } +void linphone_core_set_qrcode_decode_rect(LinphoneCore *lc, const unsigned int x, const unsigned int y, const unsigned int w, const unsigned int h) { + if (lc) { + MSRect rect; + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + lc->qrcode_rect = rect; + } +} + void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){ #ifdef VIDEO_ENABLED LinphoneCall *call=linphone_core_get_current_call (lc); diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 3c1016a9e..9002d1c71 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -794,6 +794,7 @@ namespace LinphonePrivate { bool_t send_call_stats_periodical_updates; \ bool_t forced_ice_relay; \ bool_t short_turn_refresh; \ + MSRect qrcode_rect; \ char localip[LINPHONE_IPADDR_SIZE]; \ int device_rotation; \ int max_calls; \ diff --git a/include/linphone/core.h b/include/linphone/core.h index eebfc3b62..a1a54d90e 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -3629,6 +3629,17 @@ LINPHONE_PUBLIC bool_t linphone_core_video_preview_enabled(const LinphoneCore *l **/ LINPHONE_PUBLIC void linphone_core_enable_qrcode_video_preview(LinphoneCore *lc, bool_t val); +/** + * Set the rectangle where the decoder will search a QRCode + * @param[in] lc LinphoneCore* object + * @param[in] x axis + * @param[in] y axis + * @param[in] w width + * @param[in] h height + * @ingroup media_parameters + */ +LINPHONE_PUBLIC void linphone_core_set_qrcode_decode_rect(LinphoneCore *lc, const unsigned int x, const unsigned int y, const unsigned int w, const unsigned int h); + /** * Tells whether QRCode is enabled in the preview. * @param[in] lc LinphoneCore object diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 0a1db7740..2fdf1354c 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -140,6 +140,7 @@ set(RC_FILES set(IMAGE_FILES images/linphone.svg images/linphonesiteqr.jpg + images/linphonesiteqr_captured.jpg images/nowebcamCIF.jpg images/nowebcamVGA.jpg ) diff --git a/tester/images/linphonesiteqr_captured.jpg b/tester/images/linphonesiteqr_captured.jpg new file mode 100644 index 000000000..5abe984e4 Binary files /dev/null and b/tester/images/linphonesiteqr_captured.jpg differ diff --git a/tester/images/qrcodesite_captured.jpg b/tester/images/qrcodesite_captured.jpg new file mode 100644 index 000000000..d588bfc15 Binary files /dev/null and b/tester/images/qrcodesite_captured.jpg differ diff --git a/tester/video_tester.c b/tester/video_tester.c index da1ac6dec..1d1ad4295 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -79,7 +79,14 @@ static void qrcode_found_cb(LinphoneCore *lc, const char *result) { } } -static void decode_qrcode_from_nowebcam(void) { +typedef struct struct_image_rect { + int x; + int y; + int w; + int h; +}image_rect; + +static void _decode_qrcode(const char* image_path, image_rect *rect) { qrcode_callback_data qrcode_data; char *qrcode_image; LinphoneCoreManager* lcm = linphone_core_manager_create("empty_rc"); @@ -88,7 +95,7 @@ static void decode_qrcode_from_nowebcam(void) { qrcode_data.text = NULL; linphone_core_manager_start(lcm, FALSE); - qrcode_image = bc_tester_res("images/linphonesiteqr.jpg"); + qrcode_image = bc_tester_res(image_path); linphone_core_set_video_device(lcm->lc, liblinphone_tester_static_image_id); linphone_core_set_static_picture(lcm->lc, qrcode_image); @@ -97,9 +104,12 @@ static void decode_qrcode_from_nowebcam(void) { cbs = linphone_core_get_current_callbacks(lcm->lc); linphone_core_cbs_set_qrcode_founded(cbs, qrcode_found_cb); linphone_core_cbs_set_user_data(cbs, &qrcode_data); + if (rect) { + linphone_core_set_qrcode_decode_rect(lcm->lc, rect->x, rect->y, rect->w, rect->h); + } linphone_core_enable_video_preview(lcm->lc, TRUE); - BC_ASSERT_TRUE(wait_for_until(lcm->lc, NULL, &qrcode_data.qrcode_found, TRUE, 3000)); + BC_ASSERT_TRUE(wait_for_until(lcm->lc, NULL, &qrcode_data.qrcode_found, TRUE, 2000)); if (qrcode_data.qrcode_found) { if (BC_ASSERT_PTR_NOT_NULL(qrcode_data.text)) { ms_message("QRCode decode: %s", qrcode_data.text); @@ -114,9 +124,23 @@ static void decode_qrcode_from_nowebcam(void) { linphone_core_manager_destroy(lcm); } +static void decode_qrcode_from_image(void) { + _decode_qrcode("images/linphonesiteqr.jpg", NULL); +} + +static void decode_qrcode_from_zone(void) { + image_rect rect; + rect.x = 332; + rect.y = 470; + rect.w = 268; + rect.h = 262; + _decode_qrcode("images/linphonesiteqr_captured.jpg", &rect); +} + test_t video_tests[] = { TEST_NO_TAG("Enable/disable camera after camera switches", enable_disable_camera_after_camera_switches), - TEST_NO_TAG("Decode QRCode", decode_qrcode_from_nowebcam) + TEST_ONE_TAG("Decode QRCode from image", decode_qrcode_from_image, "QRCode"), + TEST_ONE_TAG("Decode QRCode from zone", decode_qrcode_from_zone, "QRCode") }; test_suite_t video_test_suite = {