diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index d0a603540..2efde998a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -152,6 +152,14 @@ void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsT cbs->tmmbr_received_cb = cb; } +LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs) { + return cbs->snapshot_taken_cb; +} + +void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb) { + cbs->snapshot_taken_cb = cb; +} + bool_t linphone_call_state_is_early(LinphoneCallState state){ switch (state){ @@ -2360,9 +2368,23 @@ void linphone_call_send_vfu_request(LinphoneCall *call) { #endif } +#ifdef VIDEO_ENABLED +static void snapshot_taken(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { + if (id == MS_JPEG_WRITER_SNAPSHOT_TAKEN) { + LinphoneCall *call = (LinphoneCall *)userdata; + if (call) { + const char *filepath = (const char *) arg; + linphone_call_notify_snapshot_taken(call, filepath); + } + linphone_call_unref(call); + } +} +#endif + LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char *file) { #ifdef VIDEO_ENABLED if (call->videostream!=NULL && call->videostream->jpegwriter!=NULL){ + ms_filter_add_notify_callback(call->videostream->jpegwriter, snapshot_taken, linphone_call_ref(call), TRUE); return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file); } ms_warning("Cannot take snapshot: no currently running video stream on this call."); @@ -2373,6 +2395,7 @@ LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file) { #ifdef VIDEO_ENABLED if (call->videostream!=NULL && call->videostream->local_jpegwriter!=NULL){ + ms_filter_add_notify_callback(call->videostream->local_jpegwriter, snapshot_taken, linphone_call_ref(call), TRUE); return ms_filter_call_method(call->videostream->local_jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file); } ms_warning("Cannot take local snapshot: no currently running video stream on this call."); @@ -6275,3 +6298,7 @@ void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *ms void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr) { NOTIFY_IF_EXIST(tmmbr_received_cb, call, stream_index, tmmbr) } + +void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path) { + NOTIFY_IF_EXIST(snapshot_taken_cb, call, file_path) +} diff --git a/coreapi/private.h b/coreapi/private.h index 1537834d5..3b2894fd6 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -314,6 +314,7 @@ struct _LinphoneCallCbs { LinphoneCallCbsTransferStateChangedCb transfer_state_changed_cb; LinphoneCallCbsAckProcessingCb ack_processing; LinphoneCallCbsTmmbrReceivedCb tmmbr_received_cb; + LinphoneCallCbsSnapshotTakenCb snapshot_taken_cb; }; LinphoneCallCbs * _linphone_call_cbs_new(void); @@ -427,6 +428,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallSt void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg); void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received); void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr); +void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path); LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); diff --git a/include/linphone/call.h b/include/linphone/call.h index 9d83be9b9..3a7188ed8 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -698,6 +698,20 @@ LINPHONE_PUBLIC LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_recei */ LINPHONE_PUBLIC void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb); +/** + * Get the snapshot taken callback. + * @param[in] cbs LinphoneCallCbs object. + * @return The current snapshot taken callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs); + +/** + * Set the snapshot taken callback. + * @param[in] cbs LinphoneCallCbs object. + * @param[in] cb The snapshot taken callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb); + /** * @} */ diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h index 83aefe18b..6a6738dbe 100644 --- a/include/linphone/callbacks.h +++ b/include/linphone/callbacks.h @@ -142,6 +142,13 @@ typedef void (*LinphoneCallCbsAckProcessingCb)(LinphoneCall *call, LinphoneHeade */ typedef void (*LinphoneCallCbsTmmbrReceivedCb)(LinphoneCall *call, int stream_index, int tmmbr); +/** + * Callback for notifying a snapshot taken. + * @param call LinphoneCall for which the snapshot was taken + * @param filepath the name of the saved file + */ +typedef void (*LinphoneCallCbsSnapshotTakenCb)(LinphoneCall *call, const char *filepath); + /** * @} **/ diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index c77474239..aecac5c67 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -718,8 +718,6 @@ void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, } } - - static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy,LinphoneMediaEncryption mode, bool_t callee_video_enabled, bool_t caller_video_enabled) { video_call_base_2(pauline,marie,using_policy,mode,callee_video_enabled,caller_video_enabled); end_call(pauline, marie); @@ -1688,6 +1686,15 @@ static void video_call_recording_vp8_test(void) { record_call("recording", TRUE, "VP8"); } +static void snapshot_taken(LinphoneCall *call, const char *filepath) { + char *filename = bc_tester_file("snapshot.jpeg"); + LinphoneCore *lc = linphone_call_get_core(call); + stats *callstats = get_stats(lc); + BC_ASSERT_STRING_EQUAL(filepath, filename); + callstats->number_of_snapshot_taken++; + ms_free(filename); +} + static void video_call_snapshot(void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -1695,7 +1702,6 @@ static void video_call_snapshot(void) { LinphoneCallParams *paulineParams = linphone_core_create_call_params(pauline->lc, NULL); LinphoneCall *callInst = NULL; char *filename = bc_tester_file("snapshot.jpeg"); - int dummy = 0; bool_t call_succeeded = FALSE; linphone_core_enable_video_capture(marie->lc, TRUE); @@ -1708,11 +1714,15 @@ static void video_call_snapshot(void) { BC_ASSERT_TRUE(call_succeeded = call_with_params(marie, pauline, marieParams, paulineParams)); BC_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)); if((call_succeeded == TRUE) && (callInst != NULL)) { + LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc); + BC_ASSERT_PTR_NOT_NULL(pauline_call); + LinphoneCallCbs *pauline_call_cbs = linphone_call_get_current_callbacks(pauline_call); + linphone_call_cbs_set_snapshot_taken(pauline_call_cbs, snapshot_taken); int jpeg_support = linphone_call_take_video_snapshot(callInst, filename); if (jpeg_support < 0) { ms_warning("No jpegwriter support!"); } else { - wait_for_until(marie->lc, pauline->lc, &dummy, 1, 5000); + BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_snapshot_taken,1)); BC_ASSERT_EQUAL(ortp_file_exist(filename), 0, int, "%d"); remove(filename); } @@ -2173,6 +2183,7 @@ test_t call_video_tests[] = { TEST_NO_TAG("Simple video call implicit AVPF to AVPF", video_call_implicit_AVPF_to_AVPF), TEST_NO_TAG("Video added by reINVITE, with implicit AVPF", video_call_established_by_reinvite_with_implicit_avpf), TEST_NO_TAG("Simple video call", video_call), + TEST_NO_TAG("Simple video call with snapshot", video_call_snapshot), TEST_NO_TAG("Simple video call without rtcp",video_call_without_rtcp), TEST_NO_TAG("Simple ZRTP video call", video_call_zrtp), TEST_NO_TAG("Simple DTLS video call", video_call_dtls), diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index c35db9917..3336de02c 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -268,6 +268,8 @@ typedef struct _stats { int number_of_tmmbr_received; int last_tmmbr_value_received; int tmmbr_received_from_cb; + + int number_of_snapshot_taken; }stats;