diff --git a/src/gst-controller.c b/src/gst-controller.c
index 06f80b289a07fddffa094fa77c5b7339518129c7..37d63714b59ccda50c3d0973506abdfb24b621be 100644 (file)
--- a/src/gst-controller.c
+++ b/src/gst-controller.c
/*
- * Copyright (c) 2010-2011, Texas Instruments Incorporated
+ * Copyright (c) 2012-2013, Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
/**
* @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"
-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;
- }
+gchar * fsinkArr [] = {"fsink0", "fsink1"};
+static gint fsinkCounter = 0;
+static void getTime (gint64 arr[], gint64 time);
- /*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");
- sink1 = createImageSinkFromWindow (drawArea2, "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;
}
- g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", sink0, NULL);
+ 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);
}
+ 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:
}
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));
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;
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,
- 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_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
{
gboolean ret = TRUE;
-
+
return ret;
}
@@ -260,22 +268,185 @@ 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;
}
+gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue,
+ gchar **timeLabelText)
+{
+ gboolean ret = TRUE;
+ gint64 position = 0, duration = 0;
+ gint64 pos[3], dur[3];
+ GstFormat format = GST_FORMAT_TIME;
+ if (TRUE == gst_element_query_position (pipePtr->pipe, &format, &position)
+ && (TRUE == gst_element_query_duration (pipePtr->pipe, &format, &duration))) {
+
+ getTime (pos, position);
+ getTime (dur, duration);
+ *timeLabelText = g_strdup_printf ("%" G_GINT64_FORMAT ":\
+ %" G_GINT64_FORMAT ":%" G_GINT64_FORMAT "/\
+ %" G_GINT64_FORMAT ":%" G_GINT64_FORMAT ":%" G_GINT64_FORMAT "",
+ pos[HH], pos[MM], pos[SS], dur[HH], dur[MM], dur[SS]);
+ if (duration)
+ *seekScaleValue = (gdouble)position/ (gdouble)duration * 100;
+
+ }
+ else
+ ret = FALSE;
+
+ return ret;
+}
+void DualDecode_setPipelineSink (Pipeline *pipePtr, GstElement *sink0,
+ GstElement *sink1)
+{
+ g_print ("IN SET PIPE IN SINGLE MODE");
+ attachPipeElements (pipePtr, sink0, sink1);
+}
+
+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;
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position = 0;
+
+
+ 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);
+
+
+ /* Get position of the media */
+ gst_element_query_position (otherWindowSink, &format, &position);
+
+ /* 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, position);
+ 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;
+}