Fixed copyright, including header files and permissions issues.
[glsdk/dual-decode.git] / src / gst-controller.c
1 /*                                                                              
2  *  Copyright (c) 2012-2013, 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 static void getTime (gint64 arr[], gint64 time);
58 GstElement * createImageSinkFromWindow(GtkWidget *window,gchar *name)
59 {
60         GstElement *sink                = NULL;
61         XID xid                                 = 0;
62         GdkDrawable *drawable   = NULL;
64         /*make an xvimagesink element from factory*/
65         /*TODO : hard coded strings. will change*/
66         sink = gst_element_factory_make("xvimagesink",name);
67         if(NULL == sink){
68                 goto return_pos;
69         }
71         /*get the XID of the display window's drawable*/
72         drawable = gtk_widget_get_window (GTK_WIDGET (window));
73         if(FALSE == GDK_IS_DRAWABLE(drawable)){
74                 /*TODO: A BUG HERE?*/
75                 g_object_unref(G_OBJECT(sink));
76                 sink=NULL;
77                 goto return_pos;
78         }
79         xid = gdk_x11_drawable_get_xid(drawable);
80         
81         /*link the gst sink element to the XID*/
82         gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sink),xid);
84 return_pos:
85         return sink;
86 }
88 gboolean attachPipeElements (Pipeline *pipePtr, GtkWidget *drawArea1, 
89                              GtkWidget *drawArea2)
90 {
91     gboolean ret = TRUE;
92  
93     GstElement *bin = NULL;   
94     GstElement *tee = NULL;                                                     
95     GstElement *queue0 = NULL;                                                  
96     GstElement *queue1 = NULL;                                                  
97     GstElement *sink0 = NULL;                                                   
98     GstElement *sink1 = NULL;
99     GstPad *pad = NULL;   
100     
101     
102     //if (NULL != drawArea2) {
103         bin = gst_bin_new ("vsinkbin");
104         tee = gst_element_factory_make ("tee","splitter"); 
105         sink0 = createImageSinkFromWindow (drawArea1, "sink0");
106         queue0 = gst_element_factory_make ("queue","q0");  
107         if(NULL != drawArea2)                         
108             sink1 = createImageSinkFromWindow (drawArea2, "sink1"); 
109         else
110             sink1 = gst_element_factory_make ("fakesink", "sink1"); 
111                 queue1 = gst_element_factory_make ("queue","q1");  
113         if ( !bin || !tee || !sink0 || !sink1 || !queue0 || !queue1) {
114             ret = FALSE;
115             goto exit;
116         }
117                    
118         gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,NULL); 
119     
120         /*Connecting the tee through queues is necessary to sync the two displays*/ 
121         gst_element_link(tee,queue0);                                               
122         gst_element_link(tee,queue1);                                               
123         gst_element_link(queue0,sink0);                                             
124         gst_element_link(queue1,sink1);                                             
125                                                                                 
126         pad = gst_element_get_static_pad (tee, "sink");                             
127         gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
128         gst_object_unref (GST_OBJECT (pad)); 
129         g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);              
130     
131    /* else {
132     
133      sink0 = createImageSinkFromWindow (drawArea1, "sink0"); 
134      if (!sink0)
135     {
136          ret = FALSE;
137          goto exit;
138     }
139     g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", sink0, NULL);
140     }*/
142 exit:    return ret;
144 gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
145 {    
146         gchar *name             = (gchar *)data;
147     gchar *debugMsg     = NULL;                                                 
148     GError *err         = NULL;                                                 
149     static int count = 0;
151     switch(GST_MESSAGE_TYPE(msg)){                                              
152                                                                                 
153         case GST_MESSAGE_EOS:                                                   
154             g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
155                         count++;
156             break;                                                              
157                                                                                
158          case GST_MESSAGE_ERROR: {                                             
159             gst_message_parse_error(msg,&err,&debugMsg);                      
160             g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);                                                      
161             g_free(debugMsg);                                                   
162             g_error_free(err);                                                  
163                         count++;
164             break;                                                              
165         }                                                                       
166         case GST_MESSAGE_WARNING: {                                             
167             gst_message_parse_warning(msg,&err,&debugMsg);                      
168             g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
169                                            name,err->message,debugMsg);                                                      
170             g_free(debugMsg);                                                   
171             g_error_free(err);                                                  
172             break;                                                              
173         }                                                                       
174                                                                                 
175         default:                                                                
176             break;                                                              
177     }                                                                           
178                                                                                 
179     return TRUE;                                                                
180
181        
182 Pipeline * DualDecode_createPipeline()
184     Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
185     pipelinePtr->pipe = NULL;
186                                                   
187     GstBus *bus = NULL;
188                                                                                 
189            
190     pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);                 
191     bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr->pipe));                    
192     pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);                                   
193     gst_object_unref (bus);     
194     pipelinePtr->logFunc = NULL;
195                                                                           
196                                                                                 
197     return pipelinePtr;                
200 gboolean DualDecode_seekMedia(Pipeline *pipePtr, gint64 position)
202         if(position < 0){
203                 return FALSE;
204         }
205         return gst_element_seek_simple(pipePtr->pipe,
206                         GST_FORMAT_TIME,
207                         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
208                         position);
211 gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position,  
212                                GtkWidget *drawArea1, GtkWidget *drawArea2)
214     gboolean ret = TRUE;
215     
216     g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);
217         if (!(attachPipeElements (pipePtr, drawArea1, drawArea2))) {
218         ret = FALSE;
219         goto exit;
220     }
221         gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                                 
222     gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                                 
224         DualDecode_getMediaState(pipePtr);
225         DualDecode_seekMedia(pipePtr, position);
226     
227      
228 exit:    return ret;
231 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
233     gboolean ret = TRUE;
234     if (!gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED))
235         ret = FALSE;  
236     
237     return ret;
240 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)                              
241 {                                                                               
242     gboolean ret = TRUE;                                                        
243     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
244         ret = FALSE;                                                            
245                                                                                 
246     return ret;                                                                 
247
249 gboolean DualDecode_stopMedia (Pipeline *pipePtr)                             
250 {                                                                               
251     gboolean ret = TRUE;                                                        
252     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
253         ret = FALSE;                                                            
254                                                                                 
255     return ret;                                                                 
256 }  
258 gboolean DualDecode_dualToSingle (Pipeline *pipes[], GtkWidget *thisDrawArea, 
259                                GtkWidget *otherDrawArea,
260                                gint thisWindowIndex,  gint otherWindowIndex)
261
262    GstElement * sinkOld = NULL;
263    GstElement * sinkNew = NULL;
264    GstElement * bin = NULL;
265  
266     gboolean ret = TRUE;
267      /*if(!gst_element_set_state (pipes[otherWindowIndex]->pipe, GST_STATE_NULL)){                  
268         ret = FALSE; 
269         goto exit;
270     }*/
271      gst_element_set_state (pipes[thisWindowIndex]->pipe, GST_STATE_PAUSED);
272     /* g_object_get (G_OBJECT (pipes[0]->pipe), "video-sink", bin, NULL);
273      
274      sinkOld = gst_bin_get_by_name (GST_BIN (bin), "sink1");
275      sinkNew = createImageSinkFromWindow (otherDrawArea, "sink1"); 
276      sinkOld = sinkNew;
278      gst_element_set_state (pipes[0]->pipe, GST_STATE_PLAYING);     
279 */
280 exit:    return ret;
283 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
285     gboolean ret = TRUE;
286     
288     return ret;   
291 GstState DualDecode_getMediaState(Pipeline *pipePtr)
293         GstState state, pending;
294         if(GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
295                                 pipePtr->pipe,
296                                 &state,
297                                 &pending,
298                                 GST_CLOCK_TIME_NONE)){
299                 /*TODO : a bug here*/
300                 g_printerr("No state in GstElement\n");
301         }
302         return state;
306 gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue,
307                                       gchar **timeLabelText)
309         gboolean ret = TRUE;
310     gint64 position = 0, duration = 0;
311     gint64 pos[3], dur[3];
312     GstFormat format = GST_FORMAT_TIME; 
314     if (TRUE == gst_element_query_position (pipePtr->pipe, &format, &position) 
315     && (TRUE == gst_element_query_duration (pipePtr->pipe, &format, &duration))) {
316        
317         getTime (pos, position);
318         getTime (dur, duration); 
319         *timeLabelText = g_strdup_printf ("%ld:%ld:%ld/%ld:%ld:%ld", 
320         pos[HH], pos[MM], pos[SS], dur[HH], dur[MM], dur[SS]);
321         if (duration)
322             *seekScaleValue = (gdouble)position/ (gdouble)duration * 100;
323         
324     }    
325     else 
326         ret = FALSE;
327     
329     return ret;
332 static void getTime (gint64 arr[], gint64 time)
334     gint8 i = 0;
335     time = time / (gint64) NANOSEC;
337     for (i = 0; i < 3; i++){
338         arr[i] = time % 60;
339         time = time / 60;
340     } 
341