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 */
42 /**
43 * @file gst-controller.c
44 *
45 * @brief
46 */
47 #include <stdint.h>
48 #include <string.h>
49 #include <gst/gst.h>
51 #include "gst-controller.h"
53 gchar * fsinkArr [] = {"fsink0", "fsink1"};
54 static gint fsinkCounter = 0;
55 static void getTime (gint64 arr[], gint64 time);
57 static gboolean attachPipeElements (Pipeline *pipePtr, GstElement *sink0,
58 GstElement *sink1)
59 {
60 gboolean ret = TRUE;
61 GstElement *fsink0 = NULL;
62 GstElement *fsink1 = NULL;
63 GstElement *bin = NULL;
64 GstElement *tee = NULL;
65 GstElement *queue0 = NULL;
66 GstElement *queue1 = NULL;
67 GstPad *pad = NULL;
71 bin = gst_bin_new ("vsinkbin");
72 tee = gst_element_factory_make ("tee","splitter");
73 //sink0 = createImageSinkFromWindow (drawArea1, "sink0");
74 queue0 = gst_element_factory_make ("queue","q0");
75 queue1 = gst_element_factory_make ("queue","q1");
77 if (NULL == sink0)
78 fsink0 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]);
79 if (NULL == sink1)
80 fsink1 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]);
83 if ( !bin || !tee || !queue0 || !queue1) {
84 ret = FALSE;
85 goto exit;
86 }
87 if (NULL == sink0 && NULL == sink1) {
88 gst_bin_add_many (GST_BIN (bin), tee,
89 fsink0, fsink1, queue0, queue1,NULL);
90 gst_element_link (queue0, fsink0);
91 gst_element_link(queue1,fsink1);
92 }
94 else if (NULL != sink0 && NULL == sink1){
95 gst_bin_add_many (GST_BIN (bin), tee,
96 sink0, fsink1, queue0, queue1,NULL);
97 gst_element_link (queue0, sink0);
98 gst_element_link(queue1,fsink1);
99 }
100 else if (NULL!= sink0 && NULL!=sink1) {
101 gst_bin_add_many (GST_BIN (bin), tee,
102 sink0, sink1, queue0, queue1,NULL);
103 gst_element_link (queue0, sink0);
104 gst_element_link(queue1,sink1);
105 }
107 else {
108 ret = FALSE;
109 goto exit;
110 }
111 /*Connecting the tee through queues is necessary to sync the two displays*/
112 gst_element_link(tee,queue0);
113 gst_element_link(tee,queue1);
114 //gst_element_link(queue0,sink0);
115 //gst_element_link(queue1,sink1);
117 pad = gst_element_get_static_pad (tee, "sink");
118 gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
119 gst_object_unref (GST_OBJECT (pad));
120 g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);
124 exit: return ret;
125 }
126 gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
127 {
128 gchar *name = (gchar *)data;
129 gchar *debugMsg = NULL;
130 GError *err = NULL;
131 static int count = 0;
133 switch(GST_MESSAGE_TYPE(msg)){
135 case GST_MESSAGE_EOS:
136 g_printerr("%s -> Message (EOS) : End of stream.\n",name);
137 count++;
138 break;
140 case GST_MESSAGE_ERROR: {
141 gst_message_parse_error(msg,&err,&debugMsg);
142 g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);
143 g_free(debugMsg);
144 g_error_free(err);
145 count++;
146 break;
147 }
148 case GST_MESSAGE_WARNING: {
149 gst_message_parse_warning(msg,&err,&debugMsg);
150 g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
151 name,err->message,debugMsg);
152 g_free(debugMsg);
153 g_error_free(err);
154 break;
155 }
157 default:
158 break;
159 }
161 return TRUE;
162 }
164 Pipeline * DualDecode_createPipeline()
165 {
166 Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
167 pipelinePtr->pipe = NULL;
169 GstBus *bus = NULL;
172 pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);
173 bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr->pipe));
174 pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);
175 gst_object_unref (bus);
176 pipelinePtr->logFunc = NULL;
179 return pipelinePtr;
180 }
182 gboolean DualDecode_setSinksForPipes (Pipeline **pipes,GstElement *sink0, GstElement *sink1)
183 {
184 gboolean ret = TRUE;
185 attachPipeElements (pipes[0], sink0, NULL);
186 attachPipeElements (pipes[1], sink1, NULL);
189 return ret;
190 }
191 gboolean DualDecode_seekMedia(Pipeline *pipePtr, gint64 position)
192 {
193 if(position < 0){
194 return FALSE;
195 }
196 return gst_element_seek_simple(pipePtr->pipe,
197 GST_FORMAT_TIME,
198 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
199 position);
200 }
203 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
204 {
205 gboolean ret = TRUE;
206 if (GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED)){
207 g_print ("SET CHANGE RETURNED ASYNC \n");
208 gst_element_get_state (pipePtr->pipe,
209 NULL,
210 NULL,
211 GST_CLOCK_TIME_NONE);
212 }
213 return ret;
214 }
216 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)
217 {
218 gboolean ret = TRUE;
219 if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))
220 ret = FALSE;
221 g_print ("IN RESUME MEDIA\n");
222 return ret;
223 }
225 gboolean DualDecode_stopMedia (Pipeline *pipePtr)
226 {
227 gboolean ret = TRUE;
228 if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))
229 ret = FALSE;
231 return ret;
232 }
235 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
236 {
237 gboolean ret = TRUE;
240 return ret;
241 }
243 GstState DualDecode_getMediaState(Pipeline *pipePtr)
244 {
245 GstState state, pending;
246 g_print ("IN GET MEDIA STATE ENTRY\n");
247 if(GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
248 pipePtr->pipe,
249 &state,
250 &pending,
251 GST_CLOCK_TIME_NONE)){
252 /*TODO : a bug here*/
253 g_printerr("No state in GstElement\n");
254 }
255 g_print("EXITING FROM GET MEDIA STATE\n");
256 return state;
257 }
260 gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue,
261 gchar **timeLabelText)
262 {
263 gboolean ret = TRUE;
264 gint64 position = 0, duration = 0;
265 gint64 pos[3], dur[3];
266 GstFormat format = GST_FORMAT_TIME;
268 if (TRUE == gst_element_query_position (pipePtr->pipe, &format, &position)
269 && (TRUE == gst_element_query_duration (pipePtr->pipe, &format, &duration))) {
271 getTime (pos, position);
272 getTime (dur, duration);
273 *timeLabelText = g_strdup_printf ("%ld:%ld:%ld/%ld:%ld:%ld",
274 pos[HH], pos[MM], pos[SS], dur[HH], dur[MM], dur[SS]);
275 if (duration)
276 *seekScaleValue = (gdouble)position/ (gdouble)duration * 100;
278 }
279 else
280 ret = FALSE;
283 return ret;
284 }
286 static void getTime (gint64 arr[], gint64 time)
287 {
288 gint8 i = 0;
289 time = time / (gint64) NANOSEC;
291 for (i = 0; i < 3; i++){
292 arr[i] = time % 60;
293 time = time / 60;
294 }
296 }
298 void DualDecode_setPipelineSink (Pipeline *pipePtr, GstElement *sink0, GstElement *sink1)
299 {
300 g_print ("IN SET PIPE IN SINGLE MODE");
301 attachPipeElements (pipePtr, sink0, sink1);
302 //gst_element_set_state (pipePtr->pipe, GST_STATE_READY);
303 }
305 gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position)
306 {
307 gboolean ret = TRUE;
309 g_print ("IN PLAYMEDIA2");
310 g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);
311 gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);
312 gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);
314 DualDecode_getMediaState(pipePtr);
315 DualDecode_seekMedia(pipePtr, position);
317 return ret;
319 }
321 gboolean DualDecode_singleToDual (Pipeline **pipes,GstElement * otherWindowSink,
322 gint thisWindow, gint otherWindow,
323 gchar *filename)
324 {
325 gboolean ret = TRUE;
327 GstElement *thisbin = NULL;
328 GstElement *otherbin = NULL;
329 GstElement *fsink = NULL;
330 GstElement *queue0 = NULL;
331 GstElement *queue1 = NULL;
332 GstState state0 ;
334 //gst_element_set_state (pipes[thisWindow]->pipe, GST_STATE_PAUSED);
335 gst_element_get_state(
336 pipes[thisWindow]->pipe,
337 &state0,
338 NULL,
339 GST_CLOCK_TIME_NONE);
341 g_object_get (G_OBJECT (pipes[thisWindow]->pipe),"video-sink", &thisbin,NULL);
342 queue1 = gst_bin_get_by_name (GST_BIN (thisbin), "q1");
343 gst_element_unlink (queue1, otherWindowSink);
344 gst_object_ref (otherWindowSink);
345 gst_bin_remove (GST_BIN (thisbin), otherWindowSink);
347 g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &otherbin, NULL);
348 queue0 = gst_bin_get_by_name (GST_BIN (otherbin), "q0");
349 fsink = gst_bin_get_by_name (GST_BIN (otherbin), "fsink0");
350 gst_element_unlink (queue0, fsink);
351 gst_object_ref (fsink);
352 gst_bin_remove (GST_BIN (otherbin), fsink);
354 gst_bin_add (GST_BIN (thisbin), fsink);
355 gst_element_sync_state_with_parent (fsink);
356 gst_element_link (queue1, fsink);
358 gst_element_set_state (otherWindowSink, GST_STATE_READY);
359 gst_bin_add (GST_BIN (otherbin), otherWindowSink);
360 //gst_element_sync_state_with_parent (window[otherWindow]->sink);
361 gst_element_link (queue0, otherWindowSink);
363 DualDecode_playMedia (pipes[otherWindow], filename, 0);
364 //DualDecode_playMedia (pipes[thiswindow], filename[DECODER_INDEX_SINGLE], SEEK_START);
365 gst_element_set_state (pipes[thisWindow]->pipe, state0);
367 return ret;
368 }
370 gboolean DualDecode_dualToSingle (Pipeline **pipes,GstElement * otherWindowSink,
371 gint thisWindow, gint otherWindow)
372 {
373 gboolean ret = TRUE;
375 GstElement *bin = NULL;
376 GstElement *bin2 = NULL;
377 GstElement *fsink = NULL;
378 GstElement *fsink0 = NULL;
379 GstElement *queue0 = NULL;
380 GstElement *queue1 = NULL;
381 gchar *name = NULL;
382 gst_element_set_state (pipes[otherWindow]->pipe, GST_STATE_PAUSED);
384 g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &bin2, NULL);
385 queue0 = gst_bin_get_by_name (GST_BIN (bin2), "q0");
386 gst_element_unlink (queue0, otherWindowSink);
387 gst_object_ref (otherWindowSink);
388 gst_bin_remove (GST_BIN (bin2), otherWindowSink);
390 g_object_get (G_OBJECT (pipes[thisWindow]->pipe), "video-sink", &bin, NULL);
391 queue1 = gst_bin_get_by_name (GST_BIN (bin), "q1");
392 fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink0");
393 if (NULL == fsink)
394 fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink1");
395 name = gst_element_get_name(fsink);
397 gst_element_unlink (queue1, fsink);
398 gst_object_ref (fsink);
399 gst_bin_remove (GST_BIN (bin),fsink);
401 gst_element_set_state (otherWindowSink, GST_STATE_READY);
403 gst_bin_add (GST_BIN (bin2), fsink);
404 gst_element_sync_state_with_parent (fsink);
406 if (!g_strcmp0 (name, "fsink0")){
408 g_print ("NAME IS fsink0\n");
409 gst_element_link (queue0, fsink);
410 }
411 else if (!g_strcmp0 (name, "fsink1")){
412 g_print ("NAME IS fsink1\n");
413 fsink0 = gst_bin_get_by_name (GST_BIN (bin2), "fsink0");
414 queue1 = gst_bin_get_by_name (GST_BIN (bin2), "q1");
415 gst_element_unlink (queue1, fsink0);
416 gst_element_link (queue1, fsink);
417 gst_element_link (queue0, fsink0);
418 }
419 g_free (name);
420 gst_bin_add (GST_BIN (bin), otherWindowSink);
421 gst_element_sync_state_with_parent (otherWindowSink);
422 gst_element_link (queue1, otherWindowSink);
425 return ret;
426 }