]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/dual-decode.git/blobdiff - src/gst-controller.c
Modified in accordance to coding guidelines for header and C files.
[glsdk/dual-decode.git] / src / gst-controller.c
index a5c08d404f78345f5948950f780c07678c214bed..90e4dcec81056551749d6f86424e331127b3f158 100644 (file)
 /**                                                                             
  * @file  gst-controller.c                                                                 
  *                                                                              
- * @brief                                                                       
+ * @brief Imeplements GStreamer related functions                                                                      
  */ 
 #include <stdint.h>
 #include <string.h>
 #include <gst/gst.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <gst/interfaces/xoverlay.h>
 
 #include "gst-controller.h"
 
+gchar * fsinkArr [] = {"fsink0", "fsink1"};
+static gint fsinkCounter = 0;
 static void getTime (gint64 arr[], gint64 time);
 
-GstElement * createImageSinkFromWindow(GtkWidget *window,gchar *name)
-{
-       GstElement *sink                = NULL;
-       XID xid                                 = 0;
-       GdkDrawable *drawable   = NULL;
-
-       /*make an xvimagesink element from factory*/
-       /*TODO : hard coded strings. will change*/
-       sink = gst_element_factory_make("xvimagesink",name);
-       if(NULL == sink){
-               goto return_pos;
-       }
-
-       /*get the XID of the display window's drawable*/
-       drawable = gtk_widget_get_window (GTK_WIDGET (window));
-       if(FALSE == GDK_IS_DRAWABLE(drawable)){
-               /*TODO: A BUG HERE?*/
-               g_object_unref(G_OBJECT(sink));
-               sink=NULL;
-               goto return_pos;
-       }
-       xid = gdk_x11_drawable_get_xid(drawable);
-       
-       /*link the gst sink element to the XID*/
-       gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sink),xid);
+/******************************************************************************
+                     
+                           Static Functions
 
-return_pos:
-       return sink;
-}
-
-gboolean attachPipeElements (Pipeline *pipePtr, GtkWidget *drawArea1, 
-                             GtkWidget *drawArea2)
+******************************************************************************/
+static gboolean attachPipeElements (Pipeline *pipePtr, GstElement *sink0, 
+                             GstElement *sink1)
 {
     gboolean ret = TRUE;
+    GstElement *fsink0 = NULL; 
+    GstElement *fsink1 = NULL;
     GstElement *bin = NULL;   
     GstElement *tee = NULL;                                                     
     GstElement *queue0 = NULL;                                                  
     GstElement *queue1 = NULL;                                                  
-    GstElement *sink0 = NULL;                                                   
-    GstElement *sink1 = NULL;
     GstPad *pad = NULL;   
     
-    
-    //if (NULL != drawArea2) {
-       bin = gst_bin_new ("vsinkbin");
-       tee = gst_element_factory_make ("tee","splitter"); 
-       sink0 = createImageSinkFromWindow (drawArea1, "sink0");
-       queue0 = gst_element_factory_make ("queue","q0");  
-        if(NULL != drawArea2)                         
-           sink1 = createImageSinkFromWindow (drawArea2, "sink1"); 
-        else
-            sink1 = gst_element_factory_make ("fakesink", "sink1"); 
-               queue1 = gst_element_factory_make ("queue","q1");  
-
-       if ( !bin || !tee || !sink0 || !sink1 || !queue0 || !queue1) {
-           ret = FALSE;
-           goto exit;
-       }
-                   
-       gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,NULL); 
-    
-       /*Connecting the tee through queues is necessary to sync the two displays*/ 
-       gst_element_link(tee,queue0);                                               
-       gst_element_link(tee,queue1);                                               
-       gst_element_link(queue0,sink0);                                             
-       gst_element_link(queue1,sink1);                                             
-                                                                                
-       pad = gst_element_get_static_pad (tee, "sink");                             
-       gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
-       gst_object_unref (GST_OBJECT (pad)); 
-       g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);              
-    
-   /* else {
-    
-     sink0 = createImageSinkFromWindow (drawArea1, "sink0"); 
-     if (!sink0)
-    {
-         ret = FALSE;
-         goto exit;
+    bin = gst_bin_new ("vsinkbin");
+    tee = gst_element_factory_make ("tee","splitter"); 
+    queue0 = gst_element_factory_make ("queue","q0");  
+    queue1 = gst_element_factory_make ("queue","q1");
+
+    if (NULL == sink0)
+       fsink0 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]);
+    if (NULL == sink1)                         
+        fsink1 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]); 
+               
+    if (!bin || !tee || !queue0 || !queue1) {
+        ret = FALSE;
+       goto exit;
+    }
+    if (NULL == sink0 && NULL == sink1) {           
+       gst_bin_add_many (GST_BIN (bin), tee, fsink0, fsink1, queue0, queue1,
+                          NULL); 
+        gst_element_link (queue0, fsink0);
+        gst_element_link (queue1,fsink1);
     }
-    g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", sink0, NULL);
-    }*/
 
+    else if (NULL != sink0 && NULL == sink1) {
+        gst_bin_add_many (GST_BIN (bin), tee, sink0, fsink1, queue0, queue1,
+                          NULL);
+        gst_element_link (queue0, sink0);
+        gst_element_link (queue1,fsink1);
+   }
+   else if (NULL!= sink0 && NULL!=sink1) {
+       gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,
+                         NULL);              
+       gst_element_link (queue0, sink0);                                    
+       gst_element_link (queue1,sink1);                                    
+    }      
+    
+    else {
+        ret = FALSE;
+        goto exit;
+    }
+    /*Connecting the tee through queues is necessary to sync the two displays*/ 
+    gst_element_link (tee,queue0);                                               
+    gst_element_link (tee,queue1);                                               
+    
+    pad = gst_element_get_static_pad (tee, "sink");                             
+    gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
+    gst_object_unref (GST_OBJECT (pad)); 
+    g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);     
 exit:    return ret;
 }
-gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
+
+static gboolean busCallback (GstBus *bus, GstMessage *msg, gpointer data)
 {    
        gchar *name             = (gchar *)data;
     gchar *debugMsg     = NULL;                                                 
     GError *err         = NULL;                                                 
-    static int count = 0;
+    static int count    = 0;
 
-    switch(GST_MESSAGE_TYPE(msg)){                                              
+    switch (GST_MESSAGE_TYPE(msg)) {                                              
                                                                                 
-        case GST_MESSAGE_EOS:                                                   
-            g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
-                       count++;
-            break;                                                              
+    case GST_MESSAGE_EOS:                                                   
+        g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
+           count++;
+        break;                                                              
                                                                                
-         case GST_MESSAGE_ERROR: {                                             
-            gst_message_parse_error(msg,&err,&debugMsg);                      
-            g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);                                                      
-            g_free(debugMsg);                                                   
-            g_error_free(err);                                                  
-                       count++;
-            break;                                                              
-        }                                                                       
-        case GST_MESSAGE_WARNING: {                                             
-            gst_message_parse_warning(msg,&err,&debugMsg);                      
-            g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
+    case GST_MESSAGE_ERROR: {                                             
+        gst_message_parse_error(msg,&err,&debugMsg);                      
+        g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", 
+                            name,err->message,debugMsg);                                                      
+        g_free(debugMsg);                                                   
+        g_error_free(err);                                                  
+           count++;
+        break;                                                              
+    }                                                                       
+    case GST_MESSAGE_WARNING: {                                             
+        gst_message_parse_warning(msg,&err,&debugMsg);                      
+        g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
                                            name,err->message,debugMsg);                                                      
-            g_free(debugMsg);                                                   
-            g_error_free(err);                                                  
-            break;                                                              
+        g_free(debugMsg);                                                   
+        g_error_free(err);                                                  
+        break;                                                              
         }                                                                       
                                                                                 
         default:                                                                
@@ -177,8 +158,29 @@ gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
     }                                                                           
                                                                                 
     return TRUE;                                                                
+}
+
+static void getTime (gint64 arr[], gint64 time)
+{
+    gint8 i = 0;
+    time = time / (gint64) NANOSEC;
+
+    for (i = 0; i < 3; i++){
+        arr[i] = time % 60;
+        time = time / 60;
+    } 
+    
 } 
-       
+/*****************************************************************************
+
+                          Public Functions
+
+******************************************************************************/       
+
+
+/*****************************************************************************
+*                         see gst-controller.h
+******************************************************************************/
 Pipeline * DualDecode_createPipeline()
 {
     Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
@@ -187,8 +189,8 @@ Pipeline * DualDecode_createPipeline()
     GstBus *bus = NULL;
                                                                                 
            
-    pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);                 
-    bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr->pipe));                    
+    pipelinePtr->pipe = gst_element_factory_make ("playbin2",NULL);                 
+    bus = gst_pipeline_get_bus (GST_PIPELINE (pipelinePtr->pipe));                    
     pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);                                   
     gst_object_unref (bus);     
     pipelinePtr->logFunc = NULL;
@@ -197,93 +199,68 @@ Pipeline * DualDecode_createPipeline()
     return pipelinePtr;                
 }
 
-gboolean DualDecode_seekMedia(Pipeline *pipePtr, gint64 position)
+gboolean DualDecode_setSinksForPipes (Pipeline **pipes, GstElement *sink0, 
+                                      GstElement *sink1)
+{
+    gboolean ret = TRUE;
+    attachPipeElements (pipes[0], sink0, NULL);
+    attachPipeElements (pipes[1], sink1, NULL);
+       
+
+    return ret;
+}
+gboolean DualDecode_seekMedia (Pipeline *pipePtr, gint64 position)
 {
-       if(position < 0){
+       if (position < 0) {
                return FALSE;
        }
-       return gst_element_seek_simple(pipePtr->pipe,
-                       GST_FORMAT_TIME,
-                       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
-                       position);
+       return gst_element_seek_simple (pipePtr->pipe, GST_FORMAT_TIME,
+                                          GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
+                                              position);
 }
 
-gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position,  
-                               GtkWidget *drawArea1, GtkWidget *drawArea2)
-{
-    gboolean ret = TRUE;
-    
-    g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);
-       if (!(attachPipeElements (pipePtr, drawArea1, drawArea2))) {
-        ret = FALSE;
-        goto exit;
-    }
-       gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                                 
-    gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                                 
-
-       DualDecode_getMediaState(pipePtr);
-       DualDecode_seekMedia(pipePtr, position);
-    
-     
-exit:    return ret;
-}
 
 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
 {
     gboolean ret = TRUE;
-    if (!gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED))
-        ret = FALSE;  
+    GstStateChangeReturn stateReturn;
+    if (GST_STATE_CHANGE_ASYNC == 
+        gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED)) {
+        g_print ("STATE CHANGE RETURNED ASYNC \n");
+        stateReturn = gst_element_get_state (pipePtr->pipe,
+                                NULL,
+                                NULL,
+                                TIMEOUT);
+        g_print ("GET STATE RETURNED %s\n", 
+                  gst_element_state_change_return_get_name (stateReturn));
     
+    }    
     return ret;
 }
 
 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)                              
 {                                                                               
     gboolean ret = TRUE;                                                        
-    if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
+    if (!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
         ret = FALSE;                                                            
-                                                                                
+    g_print ("IN RESUME MEDIA\n");                                                                            
     return ret;                                                                 
 } 
 
 gboolean DualDecode_stopMedia (Pipeline *pipePtr)                             
 {                                                                               
     gboolean ret = TRUE;                                                        
-    if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
+    if (!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
         ret = FALSE;                                                            
                                                                                 
     return ret;                                                                 
 }  
 
-gboolean DualDecode_dualToSingle (Pipeline *pipes[], GtkWidget *thisDrawArea, 
-                               GtkWidget *otherDrawArea,
-                               gint thisWindowIndex,  gint otherWindowIndex)
-{ 
-   GstElement * sinkOld = NULL;
-   //GstElement * sinkNew = NULL;
-   //GstElement * bin = NULL;
-    gboolean ret = TRUE;
-     /*if(!gst_element_set_state (pipes[otherWindowIndex]->pipe, GST_STATE_NULL)){                  
-        ret = FALSE; 
-        goto exit;
-    }*/
-     gst_element_set_state (pipes[thisWindowIndex]->pipe, GST_STATE_PAUSED);
-    /* g_object_get (G_OBJECT (pipes[0]->pipe), "video-sink", bin, NULL);
-     
-     sinkOld = gst_bin_get_by_name (GST_BIN (bin), "sink1");
-     sinkNew = createImageSinkFromWindow (otherDrawArea, "sink1"); 
-     sinkOld = sinkNew;
-
-     gst_element_set_state (pipes[0]->pipe, GST_STATE_PLAYING);     
-*/
-   return ret;
-}
 
 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
 {
     gboolean ret = TRUE;
-    
+     
 
     return ret;   
 }
@@ -291,14 +268,13 @@ gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer da
 GstState DualDecode_getMediaState(Pipeline *pipePtr)
 {
        GstState state, pending;
-       if(GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
-                               pipePtr->pipe,
-                               &state,
-                               &pending,
-                               GST_CLOCK_TIME_NONE)){
+    g_print ("IN GET MEDIA STATE ENTRY\n");
+       if (GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
+               pipePtr->pipe, &state, &pending, GST_CLOCK_TIME_NONE)) {
                /*TODO : a bug here*/
-               g_printerr("No state in GstElement\n");
-       }
+               g_printerr ("No state in GstElement\n");
+       } 
+    g_print ("EXITING FROM GET MEDIA STATE\n");
        return state;
 }
 
@@ -329,17 +305,137 @@ gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue
     return ret;
 }
 
-static void getTime (gint64 arr[], gint64 time)
+
+
+void DualDecode_setPipelineSink (Pipeline *pipePtr, GstElement *sink0, 
+                                 GstElement *sink1)
 {
-    gint8 i = 0;
-    time = time / (gint64) NANOSEC;
+    g_print ("IN SET PIPE IN SINGLE MODE");
+    attachPipeElements (pipePtr, sink0, sink1);
+}
 
-    for (i = 0; i < 3; i++){
-        arr[i] = time % 60;
-        time = time / 60;
-    } 
+gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position)            
+{                                                                               
+    gboolean ret = TRUE;                                                        
+
+    g_print ("IN PLAYMEDIA2");                                                                                
+    g_object_set (G_OBJECT (pipePtr->pipe),"uri", filename,NULL);                 
+    gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                      
+    gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                   
+                                                                                
+    DualDecode_getMediaState (pipePtr);                                          
+    DualDecode_seekMedia (pipePtr, position);                                    
     
+    return ret;                                                                            
+                                                                                
 }
 
+gboolean DualDecode_singleToDual (Pipeline **pipes,GstElement * otherWindowSink,
+                                  gint thisWindow, gint otherWindow,
+                                  gchar *filename)
+{
+    gboolean ret = TRUE;
+
+    GstElement *thisbin   = NULL;
+    GstElement *otherbin  = NULL;
+    GstElement *fsink     = NULL;
+    GstElement *queue0    = NULL;                                                  
+    GstElement *queue1    = NULL;                                                  
+    GstState state0       = GST_STATE_NULL; 
+   
+    gst_element_get_state (pipes[thisWindow]->pipe, &state0, NULL,                                                        
+                           GST_CLOCK_TIME_NONE);  
+
+    /*Remove  otherWindowsink from this pipeline*/
+    g_object_get (G_OBJECT (pipes[thisWindow]->pipe),"video-sink", &thisbin,NULL);
+    queue1 = gst_bin_get_by_name (GST_BIN (thisbin), "q1");                   
+    gst_element_unlink (queue1, otherWindowSink);          
+    gst_object_ref (otherWindowSink);                      
+    gst_bin_remove (GST_BIN (thisbin), otherWindowSink);       
+    
+    /*Remove a fake sink from the other pipeline*/                                                                            
+    g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &otherbin, NULL);
+    queue0 = gst_bin_get_by_name (GST_BIN (otherbin), "q0");                  
+    fsink = gst_bin_get_by_name (GST_BIN (otherbin), "fsink0");               
+    gst_element_unlink (queue0, fsink);                                   
+    gst_object_ref (fsink);                                               
+    gst_bin_remove (GST_BIN (otherbin), fsink);                               
+      
+    /*Add fakesink to this pipeline*/                                                                          
+    gst_bin_add (GST_BIN (thisbin), fsink);                                  
+    gst_element_sync_state_with_parent (fsink);                          
+    gst_element_link (queue1, fsink);                                    
+    
+    /* Add otherWindowSink to other pipeline */                                                                            
+    gst_element_set_state (otherWindowSink, GST_STATE_READY);
+    gst_bin_add (GST_BIN (otherbin), otherWindowSink);        
+    gst_element_link (queue0, otherWindowSink);           
+                                                                                
+    DualDecode_playMedia (pipes[otherWindow], filename, 0);
+    gst_element_set_state (pipes[thisWindow]->pipe, state0); 
+
+    return ret;
+}
+gboolean DualDecode_dualToSingle (Pipeline **pipes,GstElement * otherWindowSink,
+                                  gint thisWindow, gint otherWindow)  
+{
+    gboolean ret = TRUE;
+    GstElement *bin    = NULL;
+    GstElement *bin2   = NULL;
+    GstElement *fsink  = NULL;
+    GstElement *fsink0 = NULL;
+    GstElement *queue0 = NULL;
+    GstElement *queue1 = NULL; 
+    gchar *name        = NULL;
+    
+    /*Remove otherWindow sink from other pipeline*/
+    gst_element_set_state (pipes[otherWindow]->pipe, GST_STATE_PAUSED);
+    g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &bin2, NULL);
+    queue0 = gst_bin_get_by_name (GST_BIN (bin2), "q0");                  
+    gst_element_unlink (queue0, otherWindowSink);          
+    gst_object_ref (otherWindowSink);                      
+    gst_bin_remove (GST_BIN (bin2), otherWindowSink);       
+    
+    /*Remove fake sink from this pipeline*/                                                                            
+    g_object_get (G_OBJECT (pipes[thisWindow]->pipe), "video-sink", &bin, NULL);
+    queue1 = gst_bin_get_by_name (GST_BIN (bin), "q1");                   
+    fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink0");                
+    if (NULL == fsink)                                                    
+        fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink1");            
+    name = gst_element_get_name (fsink);                                   
+    gst_element_unlink (queue1, fsink);                                   
+    gst_object_ref (fsink);                                               
+    gst_bin_remove (GST_BIN (bin),fsink);                                 
+                                                                                
+    gst_element_set_state (otherWindowSink, GST_STATE_READY);
+    
+    /*Add fake sink to other pipeline */                                                                            
+    gst_bin_add (GST_BIN (bin2), fsink);                                  
+    gst_element_sync_state_with_parent (fsink);                           
+                                                                                
+    if (!g_strcmp0 (name, "fsink0")){                                   
+                                                                                
+        g_print ("NAME IS fsink0\n");                                   
+        gst_element_link (queue0, fsink);                               
+    }                                                                     
+    else if (!g_strcmp0 (name, "fsink1")){                                
+        g_print ("NAME IS fsink1\n");                                     
+        fsink0 = gst_bin_get_by_name (GST_BIN (bin2), "fsink0");          
+        queue1 = gst_bin_get_by_name (GST_BIN (bin2), "q1");              
+        gst_element_unlink (queue1, fsink0);                              
+        gst_element_link (queue1, fsink);                                 
+        gst_element_link (queue0, fsink0);                                
+    }                                                                     
+    g_free (name);
+
+    /*Add otherWindowSink to this pipeline*/                                                      
+    gst_bin_add (GST_BIN (bin), otherWindowSink);         
+    gst_element_sync_state_with_parent (otherWindowSink); 
+    gst_element_link (queue1, otherWindowSink); 
+
+
+    return ret;
+}