Add applying display* attribute logic 05/319305/11 accepted/tizen/unified/20250311.054110 accepted/tizen/unified/x/20250311.211324
authorYoungwoo Cho <young222.cho@samsung.com>
Fri, 7 Feb 2025 09:04:12 +0000 (18:04 +0900)
committerYoungwoo Cho <young222.cho@samsung.com>
Mon, 10 Mar 2025 01:53:02 +0000 (10:53 +0900)
- add __mmwfd_apply_attribute() to apply attribute after committing
- fix type of param passed to _mmwfd_set_attribute
- add logic updating videosink param

[Version] 0.4.7

Change-Id: Ia41c939d1c4ed40a2f280313181ab6f87c42b527
Signed-off-by: Youngwoo Cho <young222.cho@samsung.com>
packaging/libmm-wfd.spec
src/include/mm_wfd_sink_priv.h
src/mm_wfd_sink.c
src/mm_wfd_sink_attrs.c
src/mm_wfd_sink_priv.c

index fa4bc63417c8b0b91004d5f70aedd747d625e848..5561757c5369cc1bc84f0ff0e37f56c767fd0327 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.4.6
+Version:    0.4.7
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 42b33137fe1925babca60f423a9d2638eb060a8e..c4cdbe874aaa8b254f037e909890178e223deb5e 100644 (file)
@@ -301,6 +301,7 @@ int _mm_wfd_sink_pause(mm_wfd_sink_t *wfd_sink);
 int _mm_wfd_sink_resume(mm_wfd_sink_t *wfd_sink);
 int _mm_wfd_set_message_callback(mm_wfd_sink_t *wfd_sink, MMWFDMessageCallback callback, void *user_data);
 int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution resolution);
+int _mm_wfd_sink_update_video_param(mm_wfd_sink_t *wfd_sink, const char *param_name);
 int _mm_wfd_sink_set_src_device_type(mm_wfd_sink_t *wfd_sink, MMWFDSinkDeviceType device_type);
 
 int __mm_wfd_sink_link_audio_decodebin(mm_wfd_sink_t *wfd_sink);
index 679a470aa6fcafdff3c42dcf708b225311c7a867..a22e3645fa056fa529c98c54efef0ce0a2602b78 100644 (file)
@@ -244,7 +244,7 @@ int mm_wfd_sink_set_attribute(MMHandleType wfd_sink_handle,  char **err_attr_nam
 
        MMWFDSINK_CMD_LOCK(wfd_sink);
        va_start(var_args, first_attribute_name);
-       result = _mmwfd_set_attribute(MMWFDSINK_GET_ATTRS(wfd_sink), err_attr_name, first_attribute_name, var_args);
+       result = _mmwfd_set_attribute(wfd_sink, err_attr_name, first_attribute_name, var_args);
        va_end(var_args);
        MMWFDSINK_CMD_UNLOCK(wfd_sink);
 
index f949c34bb577623d628c2db9506df91336d144d3..407d40811d8d633cc40f76093bd6dd3b477d4d18 100644 (file)
@@ -550,6 +550,46 @@ _mmwfd_get_attribute(MMHandleType handle,  char **err_attr_name, const char *att
        return result;
 }
 
+int
+__mmwfd_apply_attribute(MMHandleType handle, const char *attribute_name)
+{
+       MMHandleType attrs = 0;
+       mm_wfd_sink_t *wfd_sink = MMWFDSINK_CAST(handle);
+
+       wfd_sink_debug_fenter();
+
+       return_val_if_fail(wfd_sink, MM_ERROR_COMMON_INVALID_ARGUMENT);
+       return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+       attrs = MMWFDSINK_GET_ATTRS(handle);
+
+       return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+       if (!wfd_sink->pipeline ||
+               !wfd_sink->pipeline->v_sinkbin ||
+               !wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst) {
+               /*
+                * The attribute should be committed even though video sink bin is not created yet.
+                * So, true should be returned here.
+                * Otherwise, video can be displayed abnormal.
+                */
+               return MM_ERROR_NONE;
+       }
+
+       if (g_strrstr(attribute_name, "display")) {
+               g_autofree char *param_name = g_strdup(attribute_name);
+               wfd_sink_debug("param_name: %s", param_name);
+               if (MM_ERROR_NONE != _mm_wfd_sink_update_video_param(wfd_sink, param_name)) {
+                       wfd_sink_error("failed to update video param");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
 int
 _mmwfd_set_attribute(MMHandleType handle,  char **err_attr_name, const char *attribute_name, va_list args_list)
 {
@@ -563,7 +603,7 @@ _mmwfd_set_attribute(MMHandleType handle,  char **err_attr_name, const char *att
        return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
        return_val_if_fail(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
 
-       attrs = handle;
+       attrs = MMWFDSINK_GET_ATTRS(handle);
 
        return_val_if_fail(attrs, MM_ERROR_COMMON_INVALID_ARGUMENT);
 
@@ -575,7 +615,13 @@ _mmwfd_set_attribute(MMHandleType handle,  char **err_attr_name, const char *att
                return result;
        }
 
-       /*__mmwfd_apply_attribute(handle, attribute_name); */
+       /* Note: 'attr_commit' function is called before committing the new value to attr struct.
+                 so if there is a value to apply after committing, it should be added below function. */
+       result = __mmwfd_apply_attribute(handle, attribute_name);
+       if (result != MM_ERROR_NONE) {
+               wfd_sink_error("failed to apply attributes\n");
+               return result;
+       }
 
        wfd_sink_debug_fleave();
 
index cfbfa1563f9d7cfad91d8ba0adecfa020982a311..e395d6e0a2648f5fe4b2c38dfbea57049760b520 100644 (file)
@@ -4527,6 +4527,10 @@ int __mm_wfd_sink_create_video_sinkbin(mm_wfd_sink_t *wfd_sink)
        /* take it */
        wfd_sink->pipeline->v_sinkbin = v_sinkbin;
 
+       /* configuring display */
+       if (_mm_wfd_sink_update_video_param(wfd_sink, "update_all_param") != MM_ERROR_NONE)
+               return MM_ERROR_WFD_INTERNAL;
+
        wfd_sink_debug_fleave();
 
        return MM_ERROR_NONE;
@@ -4782,6 +4786,212 @@ int _mm_wfd_sink_set_resolution(mm_wfd_sink_t *wfd_sink, MMWFDSinkResolution res
        return MM_ERROR_NONE;
 }
 
+static bool
+__mm_wfd_sink_video_param_check_video_sink_bin(mm_wfd_sink_t *wfd_sink)
+{
+       /* check video sinkbin is created */
+       wfd_sink_return_val_if_fail(wfd_sink &&
+               wfd_sink->pipeline &&
+               wfd_sink->pipeline->v_sinkbin &&
+               wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_BIN].gst &&
+               wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst,
+               false);
+
+       return true;
+}
+
+static void
+__mm_wfd_sink_video_param_set_display_rotation(mm_wfd_sink_t *wfd_sink)
+{
+       MMHandleType attrs = 0;
+       int rotation_value = 0;
+       wfd_sink_debug_fenter();
+
+       /* check video sinkbin is created */
+       if (!__mm_wfd_sink_video_param_check_video_sink_bin(wfd_sink))
+               return;
+
+       attrs = MMWFDSINK_GET_ATTRS(wfd_sink);
+       wfd_sink_return_if_fail(attrs);
+
+       mm_attrs_get_int_by_name(attrs, "display_rotate", &rotation_value);
+       rotation_value = (4 - rotation_value) % 4;
+       g_object_set(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst, "rotate", rotation_value, NULL);
+       wfd_sink_debug("set video param : rotate %d", rotation_value);
+}
+
+static void
+__mm_wfd_sink_video_param_set_display_visible(mm_wfd_sink_t *wfd_sink)
+{
+       MMHandleType attrs = 0;
+       int visible = 0;
+       wfd_sink_debug_fenter();
+
+       /* check video sinkbin is created */
+       if (!__mm_wfd_sink_video_param_check_video_sink_bin(wfd_sink))
+               return;
+
+       attrs = MMWFDSINK_GET_ATTRS(wfd_sink);
+       wfd_sink_return_if_fail(attrs);
+
+       mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
+       g_object_set(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst, "visible", visible, NULL);
+       wfd_sink_debug("set video param : visible %d", visible);
+}
+
+static void
+__mm_wfd_sink_video_param_set_display_method(mm_wfd_sink_t *wfd_sink)
+{
+       MMHandleType attrs = 0;
+       int display_method = 0;
+       wfd_sink_debug_fenter();
+
+       /* check video sinkbin is created */
+       if (!__mm_wfd_sink_video_param_check_video_sink_bin(wfd_sink))
+               return;
+
+       attrs = MMWFDSINK_GET_ATTRS(wfd_sink);
+       wfd_sink_return_if_fail(attrs);
+
+       mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
+       g_object_set(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst, "display-geometry-method", display_method, NULL);
+       wfd_sink_debug("set video param : method %d", display_method);
+}
+
+static void
+__mm_wfd_sink_video_param_set_render_rectangle(mm_wfd_sink_t *wfd_sink)
+{
+       MMHandleType attrs = 0;
+       int display_method = 0;
+       void *handle = NULL;
+       /*set wl_display*/
+       int wl_window_x = 0;
+       int wl_window_y = 0;
+       int wl_window_width = 0;
+       int wl_window_height = 0;
+       wfd_sink_debug_fenter();
+
+       /* check video sinkbin is created */
+       if (!__mm_wfd_sink_video_param_check_video_sink_bin(wfd_sink))
+               return;
+
+       attrs = MMWFDSINK_GET_ATTRS(wfd_sink);
+       wfd_sink_return_if_fail(attrs);
+
+       /* check roi mode is set */
+       mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
+       if (display_method != MM_DISPLAY_METHOD_CUSTOM_ROI) {
+               wfd_sink_error("must be set display-geometry-method to MM_DISPLAY_METHOD_CUSTOM_ROI before setting render rectangle");
+               return;
+       }
+       mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
+       wfd_sink_return_if_fail(handle);
+
+       /*It should be set after setting window*/
+       mm_attrs_get_int_by_name(attrs, "display_roi_x", &wl_window_x);
+       mm_attrs_get_int_by_name(attrs, "display_roi_y", &wl_window_y);
+       mm_attrs_get_int_by_name(attrs, "display_roi_width", &wl_window_width);
+       mm_attrs_get_int_by_name(attrs, "display_roi_height", &wl_window_height);
+
+       /* After setting window handle, set render      rectangle */
+       gst_video_overlay_set_display_roi_area(
+               GST_VIDEO_OVERLAY(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst),
+               wl_window_x, wl_window_y, wl_window_width, wl_window_height);
+       wfd_sink_debug("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
+               wl_window_x, wl_window_y, wl_window_width, wl_window_height);
+}
+
+static int
+__mm_wfd_sink_update_videosink_video_param(mm_wfd_sink_t* wfd_sink, const char *param_name)
+{
+       gboolean update_all_param = FALSE;
+       wfd_sink_debug_fenter();
+
+       /* check video sinkbin is created */
+       if (!__mm_wfd_sink_video_param_check_video_sink_bin(wfd_sink))
+               return MM_ERROR_WFD_NOT_INITIALIZED;
+
+       if(strcmp(wfd_sink->ini.name_of_video_sink, "tizenwlsink")) {
+               wfd_sink_error("invalid videosink [%s]", wfd_sink->ini.name_of_video_sink);
+               return MM_ERROR_WFD_INTERNAL;
+       }
+
+       wfd_sink_debug("param_name : %s", param_name);
+       update_all_param = (g_strcmp0(param_name, "update_all_param") == 0);
+
+       if (update_all_param || !g_strcmp0(param_name, "display_method"))
+               __mm_wfd_sink_video_param_set_display_method(wfd_sink);
+       if (update_all_param || !g_strcmp0(param_name, "display_visible"))
+               __mm_wfd_sink_video_param_set_display_visible(wfd_sink);
+       if (update_all_param || !g_strcmp0(param_name, "display_rotate"))
+               __mm_wfd_sink_video_param_set_display_rotation(wfd_sink);
+       if (update_all_param || !g_strcmp0(param_name, "display_roi_x"))
+               __mm_wfd_sink_video_param_set_render_rectangle(wfd_sink);
+
+       return MM_ERROR_NONE;
+}
+
+int
+_mm_wfd_sink_update_video_param(mm_wfd_sink_t* wfd_sink, const char *param_name)
+{
+       int surface_type = 0;
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst, MM_ERROR_WFD_INVALID_ARGUMENT);
+       wfd_sink_return_val_if_fail(wfd_sink && wfd_sink->attrs, MM_ERROR_WFD_NOT_INITIALIZED);
+
+       /* update display surface */
+       mm_attrs_get_int_by_name(wfd_sink->attrs, "display_surface_type", &surface_type);
+       wfd_sink_info("check display surface type attribute: %d", surface_type);
+
+       /* configuring display */
+       switch (surface_type) {
+       case MM_DISPLAY_SURFACE_EVAS:
+               {
+                       void *object = NULL;
+                       gint scaling = 0;
+                       /* common case if using evas surface */
+                       mm_attrs_get_data_by_name(wfd_sink->attrs, "display_overlay", &object);
+                       mm_attrs_get_int_by_name(wfd_sink->attrs, "display_evas_do_scaling", &scaling);
+                       if (!object) {
+                               wfd_sink_error("no evas object");
+                               return MM_ERROR_WFD_INTERNAL;
+                       }
+                       wfd_sink_debug("set video param : evas-object %p", object);
+                       g_object_set(G_OBJECT(wfd_sink->pipeline->v_sinkbin[WFD_SINK_V_S_SINK].gst), "evas-object", object, NULL);
+               }
+               break;
+
+       case MM_DISPLAY_SURFACE_OVERLAY:
+               {
+                       ret = __mm_wfd_sink_update_videosink_video_param(wfd_sink, param_name);
+                       if (ret != MM_ERROR_NONE)
+                               return ret;
+               }
+               break;
+
+       case MM_DISPLAY_SURFACE_NULL:
+               {
+                       /* do nothing */
+                       wfd_sink_error("Not Supported Surface.");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+               break;
+       default:
+               {
+                       wfd_sink_error("Not Supported Surface.(default case)");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+               break;
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
 int _mm_wfd_sink_set_src_device_type(mm_wfd_sink_t *wfd_sink, MMWFDSinkDeviceType device_type)
 {
        MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;