From c1635a66251d4c0ff89b59fcc48ffe372a36aefa Mon Sep 17 00:00:00 2001 From: Erwan Croze Date: Wed, 28 Mar 2018 14:43:56 +0200 Subject: [PATCH] Implementing Qrcode callback on the preview stream --- coreapi/linphonecore.c | 50 ++++++++++++++++++++++----- coreapi/private_functions.h | 2 +- coreapi/private_structs.h | 1 + coreapi/vtables.c | 5 +++ include/linphone/callbacks.h | 7 ++++ include/linphone/core.h | 31 +++++++++++++++++ tester/CMakeLists.txt | 1 + tester/images/linphonesiteqr.jpg | Bin 0 -> 15975 bytes tester/liblinphone_tester.h | 1 + tester/tester.c | 1 + tester/video_tester.c | 56 ++++++++++++++++++++++++++++++- 11 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 tester/images/linphonesiteqr.jpg diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c6af072cf..90f152661 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msjpegwriter.h" #include "mediastreamer2/msogl.h" #include "mediastreamer2/msvolume.h" +#include "mediastreamer2/msqrcodereader.h" #include "bctoolbox/charconv.h" #include "chat/chat-room/client-group-chat-room-p.h" @@ -447,6 +448,14 @@ void linphone_core_cbs_set_chat_room_state_changed (LinphoneCoreCbs *cbs, Linpho cbs->vtable->chat_room_state_changed = cb; } +LinphoneCoreCbsQrcodeFoundedCb linphone_core_cbs_get_qrcode_founded(LinphoneCoreCbs *cbs) { + return cbs->vtable->qrcode_founded; +} + +void linphone_core_cbs_set_qrcode_founded(LinphoneCoreCbs *cbs, LinphoneCoreCbsQrcodeFoundedCb cb) { + cbs->vtable->qrcode_founded = cb; +} + void linphone_core_cbs_set_ec_calibration_result(LinphoneCoreCbs *cbs, LinphoneCoreCbsEcCalibrationResultCb cb) { cbs->vtable->ec_calibration_result = cb; } @@ -3129,15 +3138,15 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ bool_t new_status=lc->network_last_status; char newip[LINPHONE_IPADDR_SIZE]; - /* only do the network up checking every five seconds */ + // only do the network up checking every five seconds if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){ linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,newip); if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; - }else new_status=FALSE; /*no network*/ + }else new_status=FALSE; //no network if (new_status==lc->network_last_status && new_status==TRUE && strcmp(newip,lc->localip)!=0){ - /*IP address change detected*/ + //IP address change detected ms_message("IP address change detected."); set_network_reachable(lc,FALSE,curtime); lc->network_last_status=FALSE; @@ -4791,11 +4800,22 @@ void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { * Video related functions * ******************************************************************************/ + #ifdef VIDEO_ENABLED -static void snapshot_taken(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { - if (id == MS_JPEG_WRITER_SNAPSHOT_TAKEN) { - LinphoneCore *lc = (LinphoneCore *)userdata; - linphone_core_enable_video_preview(lc, FALSE); +static void video_filter_callback(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { + switch(id) { + case MS_JPEG_WRITER_SNAPSHOT_TAKEN: { + LinphoneCore *lc = (LinphoneCore *)userdata; + linphone_core_enable_video_preview(lc, FALSE); + break; + } + 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); + } + break; + } } } #endif @@ -4818,7 +4838,7 @@ LinphoneStatus linphone_core_take_preview_snapshot(LinphoneCore *lc, const char lc->previewstream->ms.factory = lc->factory; linphone_core_enable_video_preview(lc, TRUE); - ms_filter_add_notify_callback(lc->previewstream->local_jpegwriter, snapshot_taken, lc, TRUE); + ms_filter_add_notify_callback(lc->previewstream->local_jpegwriter, video_filter_callback, lc, TRUE); ms_filter_call_method(lc->previewstream->local_jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void*)file); } else { ms_filter_call_method(lc->previewstream->local_jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void*)file); @@ -4848,7 +4868,11 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ 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)) + video_preview_enable_qrcode(lc->previewstream, TRUE); video_preview_start(lc->previewstream,lc->video_conf.device); + 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){ @@ -5023,6 +5047,16 @@ bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc){ return lc->video_conf.show_local; } +void linphone_core_enable_qrcode_video_preview(LinphoneCore *lc, bool_t val) { + lc->video_conf.qrcode_decoder=val; + if (linphone_core_ready(lc)) + lp_config_set_int(lc->config,"video","qrcode_decoder",val); +} + +bool_t linphone_core_qrcode_video_preview_enabled(const LinphoneCore *lc) { + return lc->video_conf.qrcode_decoder; +} + 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_functions.h b/coreapi/private_functions.h index e6a27fbe0..2e8c43984 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -510,7 +510,7 @@ void linphone_core_notify_friend_list_removed(LinphoneCore *lc, LinphoneFriendLi void linphone_core_notify_call_created(LinphoneCore *lc, LinphoneCall *call); void linphone_core_notify_version_update_check_result_received(LinphoneCore *lc, LinphoneVersionUpdateCheckResult result, const char *version, const char *url); void linphone_core_notify_chat_room_state_changed (LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatRoomState state); - +void linphone_core_notify_qrcode_founded(LinphoneCore *lc, const char *result); void linphone_core_notify_ec_calibration_result(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms); void linphone_core_notify_ec_calibration_audio_init(LinphoneCore *lc); void linphone_core_notify_ec_calibration_audio_uninit(LinphoneCore *lc); diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 3bcfc4d78..3c1016a9e 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -326,6 +326,7 @@ struct video_config{ float fps; bool_t capture; bool_t show_local; + bool_t qrcode_decoder; bool_t display; bool_t selfview; /*during calls*/ bool_t reuse_preview_source; diff --git a/coreapi/vtables.c b/coreapi/vtables.c index 13472609c..7df79ee01 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -298,6 +298,11 @@ void linphone_core_notify_chat_room_state_changed (LinphoneCore *lc, LinphoneCha cleanup_dead_vtable_refs(lc); } +void linphone_core_notify_qrcode_founded(LinphoneCore *lc, const char *result) { + NOTIFY_IF_EXIST(qrcode_founded, lc, result); + cleanup_dead_vtable_refs(lc); +} + void linphone_core_notify_ec_calibration_result(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms) { NOTIFY_IF_EXIST(ec_calibration_result, lc, status, delay_ms); cleanup_dead_vtable_refs(lc); diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h index 7511a1d97..4e465c2d2 100644 --- a/include/linphone/callbacks.h +++ b/include/linphone/callbacks.h @@ -405,6 +405,13 @@ typedef void (*LinphoneCoreCbsVersionUpdateCheckResultReceivedCb) (LinphoneCore */ typedef void (*LinphoneCoreCbsChatRoomStateChangedCb) (LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatRoomState state); +/** + * Callback prototype telling the result of decoded qrcode + * @param[in] lc LinphoneCore object + * @param[in] result The result of the decoded qrcode + */ +typedef void (*LinphoneCoreCbsQrcodeFoundedCb)(LinphoneCore *lc, const char *result); + /** * @} **/ diff --git a/include/linphone/core.h b/include/linphone/core.h index 7ee26c5d0..eebfc3b62 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -194,6 +194,7 @@ typedef struct _LinphoneCoreVTable{ LinphoneCoreCbsCallCreatedCb call_created; LinphoneCoreCbsVersionUpdateCheckResultReceivedCb version_update_check_result_received; LinphoneCoreCbsChatRoomStateChangedCb chat_room_state_changed; + LinphoneCoreCbsQrcodeFoundedCb qrcode_founded; LinphoneCoreCbsEcCalibrationResultCb ec_calibration_result; LinphoneCoreCbsEcCalibrationAudioInitCb ec_calibration_audio_init; LinphoneCoreCbsEcCalibrationAudioUninitCb ec_calibration_audio_uninit; @@ -687,6 +688,20 @@ LINPHONE_PUBLIC LinphoneCoreCbsChatRoomStateChangedCb linphone_core_cbs_get_chat */ LINPHONE_PUBLIC void linphone_core_cbs_set_chat_room_state_changed (LinphoneCoreCbs *cbs, LinphoneCoreCbsChatRoomStateChangedCb cb); +/** + * Get the qrcode founded callback. + * @param[in] cbs LinphoneCoreCbs object + * @return The current callback + */ +LINPHONE_PUBLIC LinphoneCoreCbsQrcodeFoundedCb linphone_core_cbs_get_qrcode_founded(LinphoneCoreCbs *cbs); + +/** + * Set the qrcode found callback. + * @param[in] cbs LinphoneCoreCbs object + * @param[in] cb The callback to use + **/ +LINPHONE_PUBLIC void linphone_core_cbs_set_qrcode_founded(LinphoneCoreCbs *cbs, LinphoneCoreCbsQrcodeFoundedCb cb); + /** * @brief Sets a callback to call each time the echo-canceler calibration is completed. */ @@ -3606,6 +3621,22 @@ LINPHONE_PUBLIC void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t **/ LINPHONE_PUBLIC bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc); +/** + * Controls QRCode enablement. + * @param[in] lc LinphoneCore object + * @param[in] val A boolean value telling whether the QRCode is enabled in the preview. + * @ingroup media_parameters + **/ +LINPHONE_PUBLIC void linphone_core_enable_qrcode_video_preview(LinphoneCore *lc, bool_t val); + +/** + * Tells whether QRCode is enabled in the preview. + * @param[in] lc LinphoneCore object + * @return A boolean value telling whether QRCode is enabled in the preview. + * @ingroup media_parameters + **/ +LINPHONE_PUBLIC bool_t linphone_core_qrcode_video_preview_enabled(const LinphoneCore *lc); + /** * Take a photo of currently from capture device and write it into a jpeg file. * Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns. diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index b14e28572..0a1db7740 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -139,6 +139,7 @@ set(RC_FILES set(IMAGE_FILES images/linphone.svg + images/linphonesiteqr.jpg images/nowebcamCIF.jpg images/nowebcamVGA.jpg ) diff --git a/tester/images/linphonesiteqr.jpg b/tester/images/linphonesiteqr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..21768642c0e2b3657e21e6e57a29c07d5be3b3e6 GIT binary patch literal 15975 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 ehRRtX + static void enable_disable_camera_after_camera_switches(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -61,8 +63,60 @@ static void enable_disable_camera_after_camera_switches(void) { linphone_core_manager_destroy(pauline); } +typedef struct struct_qrcode_callback_data { + int qrcode_found; + char *text; +}qrcode_callback_data; + + +static void qrcode_found_cb(LinphoneCore *lc, const char *result) { + LinphoneCoreCbs *cbs = linphone_core_get_current_callbacks(lc); + qrcode_callback_data *found = (qrcode_callback_data *)linphone_core_cbs_get_user_data(cbs); + found->qrcode_found = TRUE; + if (result) { + if (found->text) ms_free(found->text); + found->text = ms_strdup(result); + } +} + +static void decode_qrcode_from_nowebcam(void) { + qrcode_callback_data qrcode_data; + char *qrcode_image; + LinphoneCoreManager* lcm = linphone_core_manager_create("empty_rc"); + LinphoneCoreCbs* cbs = NULL; + qrcode_data.qrcode_found = FALSE; + qrcode_data.text = NULL; + linphone_core_manager_start(lcm, FALSE); + + qrcode_image = bc_tester_res("images/linphonesiteqr.jpg"); + + linphone_core_set_video_device(lcm->lc, liblinphone_tester_static_image_id); + linphone_core_set_static_picture(lcm->lc, qrcode_image); + + linphone_core_enable_qrcode_video_preview(lcm->lc, TRUE); + 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); + linphone_core_enable_video_preview(lcm->lc, TRUE); + + BC_ASSERT_TRUE(wait_for_until(lcm->lc, NULL, &qrcode_data.qrcode_found, TRUE, 3000)); + if (qrcode_data.qrcode_found) { + if (BC_ASSERT_PTR_NOT_NULL(qrcode_data.text)) { + ms_message("QRCode decode: %s", qrcode_data.text); + BC_ASSERT_STRING_EQUAL(qrcode_data.text, "https://www.linphone.org/"); + } + } + + if (qrcode_data.text) ms_free(qrcode_data.text); + if (qrcode_image) ms_free(qrcode_image); + + linphone_core_enable_video_preview(lcm->lc, FALSE); + linphone_core_manager_destroy(lcm); +} + test_t video_tests[] = { - TEST_NO_TAG("Enable/disable camera after camera switches", enable_disable_camera_after_camera_switches) + 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_suite_t video_test_suite = {