Add audio/video valve and activate/deactivate function 38/93538/1
authorSeokHoon Lee <andy.shlee@samsung.com>
Tue, 25 Oct 2016 01:17:34 +0000 (10:17 +0900)
committerSeokHoon Lee <andy.shlee@samsung.com>
Tue, 25 Oct 2016 01:18:00 +0000 (10:18 +0900)
[Version] 0.2.210
[Profile] Common
[Issue Type] Update
[Dependency module] N/A
[Dependency commit] N/A
[Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161019.4]

Change-Id: Icce15bc2568399fe51152142059c4a28ed1f0449
Signed-off-by: SeokHoon Lee <andy.shlee@samsung.com>
packaging/libmm-wfd.spec
src/include/mm_wfd_sink_priv.h
src/mm_wfd_sink_priv.c

index 849480c..f524151 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-wfd
 Summary:    Multimedia Framework Wifi-Display Library
-Version:    0.2.209
+Version:    0.2.210
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index eca07d6..513e664 100644 (file)
@@ -43,6 +43,8 @@ enum WFDSinkMainElementID {
        WFD_SINK_M_SRC,
        WFD_SINK_M_DEPAY,
        WFD_SINK_M_DEMUX,
+       WFD_SINK_M_A_VALVE,
+       WFD_SINK_M_V_VALVE,
        WFD_SINK_M_NUM
 };
 
@@ -264,6 +266,10 @@ int __mm_wfd_sink_prepare_video_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **sinkp
 int __mm_wfd_sink_prepare_audio_pipeline(mm_wfd_sink_t *wfd_sink, GstPad **sinkpad);
 int __mm_wfd_sink_unprepare_audio_pipeline(mm_wfd_sink_t *wfd_sink);
 int __mm_wfd_sink_unprepare_video_pipeline(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_activate_audio_stream(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_activate_video_stream(mm_wfd_sink_t *wfd_sink);
+int __mm_wfd_sink_deactivate_audio_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare);
+int __mm_wfd_sink_deactivate_video_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare);
 
 const gchar *_mm_wfds_sink_get_state_name(MMWFDSinkStateType state);
 int __mm_wfd_sink_check_state(mm_wfd_sink_t *wfd_sink, MMWFDSinkCommandType cmd);
index 51b60a8..31e2426 100644 (file)
@@ -559,6 +559,220 @@ _mm_wfd_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
        return ret;
 }
 
+int __mm_wfd_sink_activate_audio_stream(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *valve = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
+       srcpad = gst_element_get_static_pad(valve, "src");
+       if (!srcpad) {
+               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+               goto error;
+       }
+
+       if (gst_pad_is_linked(srcpad)) {
+               wfd_sink_debug("%s:%s is already linked to %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad));
+               goto done;
+       }
+
+       result = __mm_wfd_sink_prepare_audio_pipeline(wfd_sink, &sinkpad);
+       if (MM_ERROR_NONE != result) {
+               wfd_sink_error("failed to prepare audio pipeline....");
+               goto error;
+       }
+
+       wfd_sink_debug("try to link %s:%s and %s:%s",
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+       if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+               wfd_sink_error("failed to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto error;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+done:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+       /* drop all the audio buffers using valve */
+       g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+error:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+       wfd_sink_debug_fleave();
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_activate_video_stream(mm_wfd_sink_t *wfd_sink)
+{
+       GstElement *valve = NULL;
+       GstPad *sinkpad = NULL;
+       GstPad *srcpad = NULL;
+       int result = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
+       srcpad = gst_element_get_static_pad(valve, "src");
+       if (!srcpad) {
+               wfd_sink_error("failed to get src pad from %s", GST_ELEMENT_NAME(valve));
+               goto error;
+       }
+
+       if (gst_pad_is_linked(srcpad)) {
+               wfd_sink_debug("%s is already linked",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto done;
+       }
+
+       result = __mm_wfd_sink_prepare_video_pipeline(wfd_sink, &sinkpad);
+       if (MM_ERROR_NONE != result) {
+               wfd_sink_error("failed to prepare video pipeline....");
+               goto error;
+       }
+
+       wfd_sink_debug("try to link %s:%s and %s:%s",
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+       if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+               wfd_sink_error("failed to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               goto error;
+       }
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+done:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+       /* drop all the video buffers using valve */
+       g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+error:
+       if (srcpad != NULL) {
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+       }
+
+       if (sinkpad != NULL) {
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+       }
+
+       wfd_sink_debug_fleave();
+       return MM_ERROR_WFD_INTERNAL;
+}
+
+int __mm_wfd_sink_deactivate_audio_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       /* drop all the audio buffers using valve */
+       g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst), "drop", TRUE, NULL);
+
+       if (unprepare) {
+               /* unprepare audio pipeline */
+               ret = __mm_wfd_sink_unprepare_audio_pipeline(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to unprepare audio pipeline...");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+}
+
+int __mm_wfd_sink_deactivate_video_stream(mm_wfd_sink_t *wfd_sink, gboolean unprepare)
+{
+       int ret = MM_ERROR_NONE;
+
+       wfd_sink_debug_fenter();
+
+       wfd_sink_return_val_if_fail(wfd_sink &&
+                                                               wfd_sink->pipeline &&
+                                                               wfd_sink->pipeline->mainbin &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst &&
+                                                               wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst,
+                                                               MM_ERROR_WFD_NOT_INITIALIZED);
+
+       /* drop all the video buffers using valve */
+       g_object_set(G_OBJECT(wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst), "drop", TRUE, NULL);
+
+       if (unprepare) {
+               /* unprepare video pipeline */
+               ret = __mm_wfd_sink_unprepare_video_pipeline(wfd_sink);
+               if (ret != MM_ERROR_NONE) {
+                       wfd_sink_error("failed to unprepare video pipeline...");
+                       return MM_ERROR_WFD_INTERNAL;
+               }
+       }
+
+       wfd_sink_debug_fleave();
+
+       return MM_ERROR_NONE;
+
+}
+
 static gboolean
 _mm_wfd_sink_msg_callback(GstBus *bus, GstMessage *msg, gpointer data)
 {
@@ -2153,6 +2367,8 @@ __mm_wfd_sink_demux_pad_added(GstElement *demux, GstPad *pad, gpointer data)
 {
        mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)data;
        gchar *name = gst_pad_get_name(pad);
+       GstElement *pipeline = NULL;
+       GstElement *valve = NULL;
        GstPad *sinkpad = NULL;
        GstPad *srcpad = NULL;
 
@@ -2163,9 +2379,65 @@ __mm_wfd_sink_demux_pad_added(GstElement *demux, GstPad *pad, gpointer data)
                                                        wfd_sink->pipeline->mainbin &&
                                                        wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst);
 
+       pipeline = wfd_sink->pipeline->mainbin[WFD_SINK_M_PIPE].gst;
+
        /* take srcpad from demuxer added pad */
        srcpad = gst_object_ref(pad);
 
+       if (name[0] == 'v') {
+               if (wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst)
+                       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_V_VALVE].gst;
+       } else if (name[0] == 'a') {
+               if (wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst)
+                       valve = wfd_sink->pipeline->mainbin[WFD_SINK_M_A_VALVE].gst;
+       }
+
+       /* add, link and run the valve */
+       if (valve) {
+               wfd_sink_debug("try to add %s to pipeline", GST_ELEMENT_NAME(valve));
+
+               if (!gst_bin_add(GST_BIN(pipeline), valve)) {
+                       wfd_sink_error("failed to add %s to pipeline",
+                                                       GST_ELEMENT_NAME(valve));
+                       goto ERROR;
+               }
+
+               sinkpad = gst_element_get_static_pad(valve, "sink");
+               if (!sinkpad) {
+                               wfd_sink_error("failed to get sink pad from %s",
+                                                               GST_ELEMENT_NAME(valve));
+                       goto ERROR;
+               }
+
+               wfd_sink_debug("try to link %s:%s and %s:%s",
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                               GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+               if (GST_PAD_LINK_OK != gst_pad_link_full(srcpad, sinkpad, GST_PAD_LINK_CHECK_NOTHING)) {
+                       wfd_sink_error("failed to link %s:%s and %s:%s",
+                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(srcpad)), GST_PAD_NAME(srcpad),
+                                                       GST_ELEMENT_NAME(GST_PAD_PARENT(sinkpad)), GST_PAD_NAME(sinkpad));
+                       goto ERROR;
+               }
+               gst_object_unref(GST_OBJECT(srcpad));
+               srcpad = NULL;
+               gst_object_unref(GST_OBJECT(sinkpad));
+               sinkpad = NULL;
+
+               wfd_sink_debug("try to sync %s's state with parent", GST_ELEMENT_NAME(valve));
+               if (!gst_element_sync_state_with_parent(GST_ELEMENT_CAST(valve))) {
+                       wfd_sink_error("failed to sync %s state with parent",
+                                                       GST_PAD_NAME(valve));
+                       goto ERROR;
+               }
+
+               srcpad = gst_element_get_static_pad(valve, "src");
+               if (!srcpad) {
+                       wfd_sink_error("failed to get src pad from %s",
+                                                       GST_ELEMENT_NAME(valve));
+                       goto ERROR;
+               }
+       }
+
        /* take decodebin/sinkbin */
        if (name[0] == 'v') {
                wfd_sink_debug("=========== >>>>>>>>>> Received VIDEO pad...");
@@ -2697,6 +2969,16 @@ static int __mm_wfd_sink_create_pipeline(mm_wfd_sink_t *wfd_sink)
                }
        }
 
+       /* create valve for audio */
+       MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_A_VALVE, "valve", "audio_valve", FALSE);
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "src");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_A_VALVE].gst, "sink");
+
+       /* create valve for video */
+       MMWFDSINK_CREATE_ELEMENT(mainbin, WFD_SINK_M_V_VALVE, "valve", "video_valve", FALSE);
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "src");
+       MMWFDSINK_PAD_PROBE(wfd_sink, NULL, mainbin[WFD_SINK_M_V_VALVE].gst, "sink");
+
        /* adding created elements to pipeline */
        if (!__mm_wfd_sink_gst_element_add_bucket_to_bin(GST_BIN_CAST(mainbin[WFD_SINK_M_PIPE].gst), element_bucket, FALSE)) {
                wfd_sink_error("failed to add elements");