diff --git a/console/commands.c b/console/commands.c index 3af324b7c..009d8724b 100644 --- a/console/commands.c +++ b/console/commands.c @@ -97,6 +97,7 @@ static int lpc_cmd_camera(LinphoneCore *lc, char *args); static int lpc_cmd_video_window(LinphoneCore *lc, char *args); static int lpc_cmd_preview_window(LinphoneCore *lc, char *args); static int lpc_cmd_snapshot(LinphoneCore *lc, char *args); +static int lpc_cmd_preview_snapshot(LinphoneCore *lc, char *args); static int lpc_cmd_vfureq(LinphoneCore *lc, char *arg); #endif static int lpc_cmd_states(LinphoneCore *lc, char *args); @@ -312,6 +313,9 @@ static LPC_COMMAND advanced_commands[] = { { "snapshot", lpc_cmd_snapshot, "Take a snapshot of currently received video stream", "'snapshot ': take a snapshot and records it in jpeg format into the supplied path\n" }, + { "preview-snapshot", lpc_cmd_preview_snapshot, "Take a snapshot of currently captured video stream", + "'preview-snapshot ': take a snapshot and records it in jpeg format into the supplied path\n" + }, { "vfureq", lpc_cmd_vfureq, "Request the other side to send VFU for the current call"}, #endif { "states", lpc_cmd_states, "Show internal states of liblinphone, registrations and calls, according to linphonecore.h definitions", @@ -2548,6 +2552,17 @@ static int lpc_cmd_snapshot(LinphoneCore *lc, char *args){ return 1; } +static int lpc_cmd_preview_snapshot(LinphoneCore *lc, char *args){ + LinphoneCall *call; + if (!args) return 0; + call=linphone_core_get_current_call(lc); + if (call!=NULL){ + linphone_call_take_preview_snapshot(call,args); + linphonec_out("Taking video preview snapshot in file %s\n", args); + }else linphonec_out("There is no active call.\n"); + return 1; +} + static int lpc_cmd_vfureq(LinphoneCore *lc, char *arg){ LinphoneCall *call; call=linphone_core_get_current_call(lc); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 171b44fd8..568206756 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1287,6 +1287,10 @@ void linphone_call_send_vfu_request(LinphoneCall *call) /** * Take a photo of currently received video 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. + * @param call a LinphoneCall + * @param file a path where to write the jpeg content. + * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). **/ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ #ifdef VIDEO_ENABLED @@ -1299,6 +1303,24 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ return -1; } +/** + * Take a photo of currently captured video 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. + * @param call a LinphoneCall + * @param file a path where to write the jpeg content. + * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). +**/ +int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file){ +#ifdef VIDEO_ENABLED + if (call->videostream!=NULL && call->videostream->local_jpegwriter!=NULL){ + 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."); + return -1; +#endif + return -1; +} + /** * Returns TRUE if camera pictures are allowed to be sent to the remote party. **/ @@ -2147,6 +2169,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna video_stream_enable_adaptive_bitrate_control(call->videostream, linphone_core_adaptive_rate_control_enabled(lc)); video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc)); + if (lc->video_conf.preview_vsize.width!=0) + video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize); video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); video_stream_enable_self_view(call->videostream,lc->video_conf.selfview); if (lc->video_window_id!=0) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 7380ebb80..ca86c4491 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -997,6 +997,9 @@ static void video_config_read(LinphoneCore *lc){ linphone_core_set_preferred_video_size_by_name(lc, lp_config_get_string(lc->config,"video","size","cif")); + + linphone_core_set_preview_video_size_by_name(lc, + lp_config_get_string(lc->config,"video","preview_size",NULL)); #ifdef VIDEO_ENABLED #if defined(ANDROID) || defined(__ios) @@ -4792,8 +4795,9 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ if (val){ if (lc->previewstream==NULL){ const char *display_filter=linphone_core_get_video_display_filter(lc); + MSVideoSize vsize=lc->video_conf.preview_vsize.width!=0 ? lc->video_conf.preview_vsize : lc->video_conf.vsize; lc->previewstream=video_preview_new(); - video_preview_set_size(lc->previewstream,lc->video_conf.vsize); + 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!=0) @@ -5284,6 +5288,7 @@ const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){ static MSVideoSize video_size_get_by_name(const char *name){ MSVideoSizeDef *pdef=supported_resolutions; MSVideoSize null_vsize={0,0}; + if (!name) return null_vsize; for(;pdef->name!=NULL;pdef++){ if (strcasecmp(name,pdef->name)==0){ return pdef->vsize; @@ -5309,6 +5314,13 @@ static bool_t video_size_supported(MSVideoSize vsize){ return FALSE; } +static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoSize vsize){ + if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ + toggle_video_preview(lc,FALSE); + toggle_video_preview(lc,TRUE); + } +} + /** * Sets the preferred video size. * @@ -5318,17 +5330,57 @@ static bool_t video_size_supported(MSVideoSize vsize){ **/ void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){ if (video_size_supported(vsize)){ - MSVideoSize oldvsize=lc->video_conf.vsize; + MSVideoSize oldvsize=lc->video_conf.preview_vsize; + if (oldvsize.width==0){ + oldvsize=lc->video_conf.vsize; + update_preview_size(lc,oldvsize,vsize); + } lc->video_conf.vsize=vsize; + if (linphone_core_ready(lc)) + lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize)); + } +} + +/** + * Sets the video size for the captured (preview) video. + * This method is for advanced usage where a video capture must be set independently of the size of the stream actually sent through the call. + * This allows for example to have the preview window with HD resolution even if due to bandwidth constraint the sent video size is small. + * Using this feature increases the CPU consumption, since a rescaling will be done internally. + * @ingroup media_parameters + * @param lc the linphone core + * @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing. +**/ +void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){ + if (vsize.width==0 && vsize.height==0){ + /*special case to reset the forced preview size mode*/ + lc->video_conf.preview_vsize=vsize; + if (linphone_core_ready(lc)) + lp_config_set_string(lc->config,"video","preview_size",NULL); + return; + } + if (video_size_supported(vsize)){ + MSVideoSize oldvsize=lc->video_conf.preview_vsize; + lc->video_conf.preview_vsize=vsize; if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ toggle_video_preview(lc,FALSE); toggle_video_preview(lc,TRUE); } - if ( linphone_core_ready(lc)) - lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize)); + if (linphone_core_ready(lc)) + lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize)); } } +/** + * Sets the preview video size by its name. See linphone_core_set_preview_video_size() for more information about this feature. + * + * @ingroup media_parameters + * Video resolution names are: qcif, svga, cif, vga, 4cif, svga ... +**/ +void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name){ + MSVideoSize vsize=video_size_get_by_name(name); + linphone_core_set_preview_video_size(lc,vsize); +} + /** * Sets the preferred video size by its name. * diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 40f6b8422..443057e98 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -689,6 +689,7 @@ LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_remote_params(Linph LINPHONE_PUBLIC void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled); LINPHONE_PUBLIC bool_t linphone_call_camera_enabled(const LinphoneCall *lc); LINPHONE_PUBLIC int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file); +LINPHONE_PUBLIC int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file); LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call); LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call); LINPHONE_PUBLIC const char *linphone_call_get_remote_user_agent(LinphoneCall *call); @@ -2227,6 +2228,8 @@ typedef struct MSVideoSizeDef{ /* returns a zero terminated table of MSVideoSizeDef*/ LINPHONE_PUBLIC const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize); +LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize); +LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name); LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name); diff --git a/coreapi/private.h b/coreapi/private.h index b03365858..ffece9f8a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -591,6 +591,7 @@ typedef struct video_config{ struct _MSWebCam *device; const char **cams; MSVideoSize vsize; + MSVideoSize preview_vsize; /*is 0,0 if no forced preview size is set, in which case vsize field above is used.*/ bool_t capture; bool_t show_local; bool_t display;