Added flags for gstreamer interfaces.
[glsdk/dual-decode.git] / src / gst-controller.c
1 /*                                                                              
2  *  Copyright (c) 2010-2011, Texas Instruments Incorporated                     
3  *                                                                              
4  *  Redistribution and use in source and binary forms, with or without          
5  *  modification, are permitted provided that the following conditions          
6  *  are met:                                                                    
7  *                                                                              
8  *  *  Redistributions of source code must retain the above copyright           
9  *   notice, this list of conditions and the following disclaimer.              
10  *                                                                              
11  *  *  Redistributions in binary form must reproduce the above copyright        
12  *   notice, this list of conditions and the following disclaimer in the        
13  *   documentation and/or other materials provided with the distribution.       
14  *                                                                              
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of      
16  *   its contributors may be used to endorse or promote products derived        
17  *   from this software without specific prior written permission.              
18  *                                                                              
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,       
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR            
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,       
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,         
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,    
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR     
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,              
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                          
30  *                                                                              
31  *  Contact information for paper mail:                                         
32  *  Texas Instruments                                                           
33  *  Post Office Box 655303                                                      
34  *  Dallas, Texas 75265                                                         
35  *  Contact information:                                                        
36  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
37  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact                             
38  *  ============================================================================
39  *                                                                              
40  */                                                                             
41                                                                                 
42 /**                                                                             
43  * @file  gst-controller.c                                                                 
44  *                                                                              
45  * @brief                                                                       
46  */ 
47 #include <stdint.h>
48 #include <string.h>
49 #include <gst/gst.h>
50 #include <gtk/gtk.h>
51 #include <gdk/gdkx.h>
52 #include <gst/interfaces/xoverlay.h>
54 #include "gst-controller.h"
56 /*GMainLoop *loop;
57 int processDecode (gchar ** files)
58 {
59     gint i;
60     gint fileCount = 0;
61     gint retVal = 1;
62     g_print("In process decode\n");
63     if (NULL == files) {
64         g_print ("Input files not specified\n");
65         exit(1);
66     }
67     for(i = 0; files[i] != NULL; i++){
68         g_print("In init decode %s\n", files[i]);
69     }*/    
70     
71     /*Count files*/
72     /*for (i = 0; NULL != files[i++]; fileCount++);
74     switch (fileCount) {
75     case 1:
76          g_print ("Single Decode\n");
77          setupGst (files, SINGLE);
78          g_main_loop_run(loop);
79          break;
80     case 2:
81          g_print ("Dual Decode\n");
82          setupGst (files, DUAL);
83          g_main_loop_run(loop);
84          break;
85     }
86     return retVal;
87     
88 }   
91 int initGstController ()
92 {
93     gint retVal = 1;
94     gst_init(NULL,NULL);
95     loop = g_main_loop_new(NULL,FALSE);
96     return retVal;
97 }    
99 GstElement *createPipe()
100 {                                                       
101     GstElement  *pipeline = NULL;  */                                       
102     
103     /*create the pipeline. This will be returned to the caller function*/       
104     /*pipeline = gst_element_factory_make("playbin2","pipeline");                 
105     if(!pipeline){                                                              
106         g_print("Playbin Element Creation Failed.\n");                            
107     }                                                                           
108                                                                                 
109     return pipeline;                                                            
110 }        
112 int setupGst (gchar **files, int decode)
114     gint i = 0;   
115     gint retVal = 1;
116     GstElement *bin = NULL;
117     GstElement *tee = NULL;
118     GstElement *queue0 = NULL;
119     GstElement *queue1 = NULL;
120     GstElement *sink0 = NULL;
121     GstElement *sink1 = NULL;
122     GstPad *pad = NULL;       
123                                                        
124     for ( i = 0; i < decode; i++)                                                
125     {                                                                           
126         pipelines[i] = createPipe(); */                                           
127     /**                                                                          
128     * Create a message handler to the bus of the pipeline.                        
129     * messages will be emitted to the application from the bus when there is an   
130     * error or warning, or when the stream is complete. The application can then  
131     * be clo
135 sed if the message is handled.                                      
136     */                                                                          
137     /*g_object_set(G_OBJECT(pipelines[i]),"uri", *files,NULL);                     
138                                                                                 
139                            
140     if (SINGLE == decode) { */ 
141     /*The two xvimagesinks are put inside a bin. They are connected to a    */  
142     /*tee via two queues. The tee is connected to a ghost sink pad which    */  
143     /*makes the bin a sink element. The bin can then serve as a video-sink  */  
144     /*element for the pipeline                                              */  
145     
146     /*bin = gst_bin_new ("vsinkbin");      
147     sink0 = gst_element_factory_make ("xvimagesink","disp0");                                        
148     sink1 = gst_element_factory_make ("xvimagesink","disp1");   
149     tee = gst_element_factory_make ("tee","splitter");                             
150     queue0 = gst_element_factory_make ("queue","q0");                              
151     queue1 = gst_element_factory_make ("queue","q1");                              
152     gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,NULL);          
153     */                                                                            
154     /*connecting the tee through queues is necessary to sync the two displays*/ 
155     /*gst_element_link(tee,queue0);                                               
156     gst_element_link(tee,queue1);                                               
157     gst_element_link(queue0,sink0);                                             
158     gst_element_link(queue1,sink1);                                             
159                                                                                 
160     pad = gst_element_get_static_pad (tee, "sink");                             
161     gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
162     gst_object_unref (GST_OBJECT (pad));        
163     
164     g_object_set(G_OBJECT(pipelines[i]), "video-sink", bin, NULL); 
165     }                                                  
166     else if (DUAL == decode) {                                                         
167         *files++;                                                              
168     }
169     gst_element_set_state (pipelines[i], GST_STATE_PLAYING);                    
170                                                                                 
171                                                                                 
172     bus = gst_pipeline_get_bus (GST_PIPELINE(pipelines[i]));                    
173     gst_bus_add_watch (bus,busCallback,loop);                                   
174     gst_object_unref (bus);    
175     }
176     return retVal;                
177 }     */
178 GstElement * createImageSinkFromWindow(GtkWidget *window,gchar *name)
180         GstElement *sink                = NULL;
181         XID xid                                 = 0;
182         GdkDrawable *drawable   = NULL;
184         /*make an xvimagesink element from factory*/
185         /*TODO : hard coded strings. will change*/
186         sink = gst_element_factory_make("xvimagesink",name);
187         if(NULL == sink){
188                 goto return_pos;
189         }
191         /*get the XID of the display window's drawable*/
192         drawable = gtk_widget_get_window (GTK_WIDGET (window));
193         if(FALSE == GDK_IS_DRAWABLE(drawable)){
194                 /*TODO: A BUG HERE?*/
195                 g_object_unref(G_OBJECT(sink));
196                 sink=NULL;
197                 goto return_pos;
198         }
199         xid = gdk_x11_drawable_get_xid(drawable);
200         
201         /*link the gst sink element to the XID*/
202         gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sink),xid);
204 return_pos:
205         return sink;
208 gboolean attachPipeElements (Pipeline *pipePtr, GtkWidget *drawArea1, 
209                              GtkWidget *drawArea2)
211     gboolean ret = TRUE;
212  
213     GstElement *bin = NULL;   
214     GstElement *tee = NULL;                                                     
215     GstElement *queue0 = NULL;                                                  
216     GstElement *queue1 = NULL;                                                  
217     GstElement *sink0 = NULL;                                                   
218     GstElement *sink1 = NULL;                                                   
219     GstPad *pad = NULL;   
220     
221     
222     if (NULL != drawArea2) { 
223         bin = gst_bin_new ("vsinkbin");
224         tee = gst_element_factory_make ("tee","splitter"); 
225         sink0 = createImageSinkFromWindow (drawArea1, "sink0");
226         queue0 = gst_element_factory_make ("queue","q0");                           
227         sink1 = createImageSinkFromWindow (drawArea2, "sink1"); 
228                 queue1 = gst_element_factory_make ("queue","q1");  
230         if ( !bin || !tee || !sink0 || !sink1 || !queue0 || !queue1) {
231             ret = FALSE;
232             goto exit;
233         }
234                    
235         gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,NULL); 
236     
237         /*Connecting the tee through queues is necessary to sync the two displays*/ 
238         gst_element_link(tee,queue0);                                               
239         gst_element_link(tee,queue1);                                               
240         gst_element_link(queue0,sink0);                                             
241         gst_element_link(queue1,sink1);                                             
242                                                                                 
243         pad = gst_element_get_static_pad (tee, "sink");                             
244         gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
245         gst_object_unref (GST_OBJECT (pad)); 
246         g_object_set (G_OBJECT (pipePtr), "video-sink", bin, NULL);              
247     }
248     else {
249     
250      sink0 = createImageSinkFromWindow (drawArea1, "sink0"); 
251      if (!sink0){
252          ret = FALSE;
253          goto exit;
254     }
255     g_object_set (G_OBJECT (pipePtr), "video-sink", sink0, NULL);
256     }
258 exit:    return ret;
260 gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
261 {    
262         gchar *name             = (gchar *)data;
263     gchar *debugMsg     = NULL;                                                 
264     GError *err         = NULL;                                                 
265     static int count = 0;
267     switch(GST_MESSAGE_TYPE(msg)){                                              
268                                                                                 
269         case GST_MESSAGE_EOS:                                                   
270             g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
271                         count++;
272             break;                                                              
273                                                                                
274          case GST_MESSAGE_ERROR: {                                             
275             gst_message_parse_error(msg,&err,&debugMsg);                      
276             g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);                                                      
277             g_free(debugMsg);                                                   
278             g_error_free(err);                                                  
279                         count++;
280             break;                                                              
281         }                                                                       
282         case GST_MESSAGE_WARNING: {                                             
283             gst_message_parse_warning(msg,&err,&debugMsg);                      
284             g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
285                                            name,err->message,debugMsg);                                                      
286             g_free(debugMsg);                                                   
287             g_error_free(err);                                                  
288             break;                                                              
289         }                                                                       
290                                                                                 
291         default:                                                                
292             break;                                                              
293     }                                                                           
294                                                                                 
295     return TRUE;                                                                
296
297        
298 Pipeline * DualDecode_createPipeline()
300     Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
301     pipelinePtr->pipe = NULL;
302                                                   
303     GstBus *bus = NULL;
304                                                                                 
305            
306     pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);                 
307     bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr));                    
308     pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);                                   
309     gst_object_unref (bus);     
310     pipelinePtr->func = NULL;
311                                                                           
312                                                                                 
313     return pipelinePtr;                
316 gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint position,  
317                                GtkWidget *drawArea1, GtkWidget *drawArea2)
319     gboolean ret = TRUE;
320     
321     g_object_set(G_OBJECT(pipePtr),"uri", filename,NULL);
322         if (!(attachPipeElements (pipePtr, drawArea1, drawArea2))) {
323         ret = FALSE;
324         goto exit;
325     }
326     gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                                 
327     
328      
329 exit:    return ret;
332 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
334     gboolean ret = TRUE;
335     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED))
336         ret = FALSE;  
337     
338     return ret;
341 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)                              
342 {                                                                               
343     gboolean ret = TRUE;                                                        
344     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
345         ret = FALSE;                                                            
346                                                                                 
347     return ret;                                                                 
348
350 gboolean DualDecode_stopMedia (Pipeline *pipePtr)                             
351 {                                                                               
352     gboolean ret = TRUE;                                                        
353     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
354         ret = FALSE;                                                            
355                                                                                 
356     return ret;                                                                 
357 }  
359 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
361     gboolean ret = TRUE;
362     
364     return ret;