Integrate QoS manager library
authorMikko Rasa <mikko.rasa@movial.fi>
Mon, 3 Nov 2008 10:28:58 +0000 (12:28 +0200)
committerMikko Rasa <mikko.rasa@movial.fi>
Mon, 3 Nov 2008 10:28:58 +0000 (12:28 +0200)
configure.ac
modules/Makefile.am
modules/gstomx-qos-bridge.c
src/octopus-backend-gst.c

index f89bf37..9dfa3e2 100644 (file)
@@ -35,7 +35,7 @@ PKG_CHECK_MODULES(gstreamer, [gstreamer-0.10 >= 0.10.10], , AC_MSG_ERROR(gstream
 AC_SUBST(gstreamer_CFLAGS)
 AC_SUBST(gstreamer_LIBS)
 
-PKG_CHECK_MODULES(gstreamer-plugins-base, [gstreamer-plugins-base-0.10], , AC_MSG_ERROR(gstreamer-plugins-base-0.10 is required))
+PKG_CHECK_MODULES(gstreamer_plugins_base, [gstreamer-plugins-base-0.10], , AC_MSG_ERROR(gstreamer-plugins-base-0.10 is required))
 
 dnl --- MODULES -----------
 
@@ -44,10 +44,18 @@ AC_SUBST(MODULEDIR)
 COMPONENTDIR='${datadir}/octopus'
 AC_SUBST(COMPONENTDIR)
 
+AC_ARG_ENABLE(qosm, AS_HELP_STRING([--enable-qosm], [Include support for QoS manager]), qosm=$enableval, qosm=no)
+AM_CONDITIONAL(QOSM, test "$qosm" = yes)
+if test "$qosm" = yes; then
+       PKG_CHECK_MODULES(libqosm, [libqosm], , AC_MSG_ERROR(libqosm is required))
+       AC_SUBST(libqosm_CFLAGS)
+       AC_SUBST(libqosm_LIBS)
+fi
+
 dnl --- Player ------------
 
 AC_ARG_ENABLE(player, AS_HELP_STRING([--enable-player], [Build a simple GTK frontend]), player=$enableval, player=no)
-AM_CONDITIONAL(PLAYER, test x$player = xyes)
+AM_CONDITIONAL(PLAYER, test "$player" = xyes)
 if test "$player" = yes; then
        PKG_CHECK_MODULES(gtk, [gtk+-2.0 >= 2.4], , AC_MSG_ERROR(gtk+ >= 2.4 is required))
        AC_SUBST(gtk_CFLAGS)
index 3c3e0f6..a05125c 100644 (file)
@@ -1,7 +1,12 @@
-pkglib_LTLIBRARIES = gstomx_qos_bridge.la
+if QOSM
+QOS_BRIDGE_LA = gstomx_qos_bridge.la
+endif
+
+pkglib_LTLIBRARIES = $(QOS_BRIDGE_LA)
 
 gst_CFLAGS = $(glib_CFLAGS) $(gstreamer_CFLAGS)
 
 gstomx_qos_bridge_la_SOURCES = gstomx-qos-bridge.c
-gstomx_qos_bridge_la_CFLAGS = $(gst_CFLAGS)
+gstomx_qos_bridge_la_CFLAGS = $(gst_CFLAGS) $(libqosm_CFLAGS)
 gstomx_qos_bridge_la_LDFLAGS = -module
+gstomx_qos_bridge_la_LIBADD = $(libqosm_LIBS)
index 4d6661e..f2d6af8 100644 (file)
@@ -1,3 +1,4 @@
+#include <IQoSManager.h>
 #include "src/octopus-module.h"
 #include "src/octopus-module-manager.h"
 #include "src/octopus-backend-gst.h"
@@ -9,6 +10,7 @@
 
 typedef struct _GstOmxQosBridge      GstOmxQosBridge;
 typedef struct _GstOmxQosBridgeClass GstOmxQosBridgeClass;
+typedef struct _RouteDataQos         RouteDataQos;
 
 struct _GstOmxQosBridge
 {
@@ -20,6 +22,12 @@ struct _GstOmxQosBridgeClass
   OctopusModuleClass parent;
 };
 
+struct _RouteDataQos
+{
+  int qos_graph_id;
+  int resources_ok;
+};
+
 GType
 gstomx_qos_bridge_get_type(void);
 static void
@@ -28,10 +36,18 @@ static void
 init_hook(OctopusBackendGst *backend,
           OctopusRoute      *route,
           gpointer          user_data);
+static void
+destroy_hook(OctopusBackendGst *backend,
+             OctopusRoute      *route,
+             gpointer          user_data);
 static gint
 play_hook(OctopusBackendGst *backend,
           OctopusRoute      *route,
           gpointer          user_data);
+static gint
+stop_hook(OctopusBackendGst *backend,
+          OctopusRoute      *route,
+          gpointer          user_data);;
 static void
 bus_watch(GstBus     *bus,
           GstMessage *msg,
@@ -57,7 +73,7 @@ gstomx_qos_bridge_init(GstOmxQosBridge *bridge)
 }
 
 /*
- * OctopusModule implementation
+ * GStreamer backend hooks
  */
 
 static void
@@ -65,7 +81,9 @@ backend_set(OctopusModule *module)
 {
   g_assert(OCTOPUS_IS_BACKEND_GST(module->backend));
   g_signal_connect(G_OBJECT(module->backend), "hook-init", G_CALLBACK(init_hook), NULL);
+  g_signal_connect(G_OBJECT(module->backend), "hook-destroy", G_CALLBACK(destroy_hook), NULL);
   g_signal_connect(G_OBJECT(module->backend), "hook-play", G_CALLBACK(play_hook), NULL);
+  g_signal_connect(G_OBJECT(module->backend), "hook-stop", G_CALLBACK(stop_hook), NULL);
 }
 
 static void
@@ -74,13 +92,32 @@ init_hook(OctopusBackendGst *backend,
           gpointer          user_data)
 {
   OctopusRouteDataGst *data;
+  RouteDataQos        *qosdata;
   GstBus              *bus;
 
+  qosdata = g_new0(RouteDataQos, 1);
+  g_object_set_data(G_OBJECT(route), "qosdata", qosdata);
+  qosdata->resources_ok = TRUE;
+
   data = (OctopusRouteDataGst *)g_object_get_data(G_OBJECT(route), "data");
   bus = gst_pipeline_get_bus(GST_PIPELINE(data->pipeline));
   g_signal_connect(G_OBJECT(bus), "message", G_CALLBACK(bus_watch), route);
 }
 
+static void
+destroy_hook(OctopusBackendGst *backend,
+             OctopusRoute      *route,
+             gpointer          user_data)
+{
+  RouteDataQos        *qosdata;
+
+  qosdata = (RouteDataQos *)g_object_get_data(G_OBJECT(route), "qosdata");
+
+  if(qosdata->qos_graph_id)
+    deleteQoSGraph(qosdata->qos_graph_id);
+  g_free(qosdata);
+}
+
 static gint
 play_hook(OctopusBackendGst *backend,
           OctopusRoute      *route,
@@ -97,34 +134,27 @@ play_hook(OctopusBackendGst *backend,
   return 0;
 }
 
-/*
- * Private functions
- */
-
-static gboolean
-check_resources(OctopusRoute *route)
+static gint
+stop_hook(OctopusBackendGst *backend,
+          OctopusRoute      *route,
+          gpointer          user_data)
 {
-  OctopusRouteDataGst *data;
-  GstIterator         *iter;
-  gpointer            elem;
+  RouteDataQos        *qosdata;
 
-  data = (OctopusRouteDataGst *)g_object_get_data(G_OBJECT(route), "data");
-  iter = gst_bin_iterate_recurse(GST_BIN(data->pipeline));
-  while(gst_iterator_next(iter, &elem) == GST_ITERATOR_OK) {
-    if(g_object_class_find_property(G_OBJECT_GET_CLASS(elem), "omx-handle")) {
-      gpointer omx_handle;
-      gchar    *omx_comp_name;
-
-      g_object_get(G_OBJECT(elem), "omx-handle", &omx_handle, "component-name", &omx_comp_name, NULL);
-      g_debug("OpenMAX component: %s (%p)", omx_comp_name, omx_handle);
-      g_free(omx_comp_name);
-    }
+  qosdata = (RouteDataQos *)g_object_get_data(G_OBJECT(route), "qosdata");
+
+  if(qosdata->qos_graph_id) {
+    deleteQoSGraph(qosdata->qos_graph_id);
+    qosdata->qos_graph_id = 0;
   }
-  gst_iterator_free(iter);
 
-  return rand()%2;
+  return 0;
 }
 
+/*
+ * Private functions
+ */
+
 static void
 bus_watch(GstBus     *bus,
           GstMessage *msg,
@@ -132,9 +162,11 @@ bus_watch(GstBus     *bus,
 {
   OctopusRoute        *route;
   OctopusRouteDataGst *data;
+  RouteDataQos        *qosdata;
   
   route = OCTOPUS_ROUTE(user_data);
   data = (OctopusRouteDataGst *)g_object_get_data(G_OBJECT(route), "data");
+  qosdata = (RouteDataQos *)g_object_get_data(G_OBJECT(route), "qosdata");
   
   if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_STATE_CHANGED)
   {
@@ -143,15 +175,33 @@ bus_watch(GstBus     *bus,
 
     elem = GST_ELEMENT(GST_MESSAGE_SRC(msg));
     gst_message_parse_state_changed(msg, &previous, &state, &pending);
-    if(elem == data->pipeline && previous == GST_STATE_READY && state == GST_STATE_PAUSED && pending == GST_STATE_VOID_PENDING)
-    {
-      if(check_resources(route)) {
-        g_debug("Resources acquired, playback is GO");
-        octopus_route_play(route);
-      } else {
-        g_debug("No resources available, stopping the route");
+    if(previous == GST_STATE_NULL && state == GST_STATE_READY) {
+      int status = 1;
+      if(g_object_class_find_property(G_OBJECT_GET_CLASS(elem), "omx-handle")) {
+        struct qos_component comp;
+
+        g_object_get(G_OBJECT(elem), "omx-handle", &comp.handle, "component-name", &comp.name, NULL);
+        g_debug("Reserving resources for OpenMAX component %s (%p)", comp.name, comp.handle);
+        if(qosdata->qos_graph_id)
+          status = addComponentGraph(&comp, 1, qosdata->qos_graph_id);
+        else {
+          status = checkGraph(&comp, 1, &qosdata->qos_graph_id);
+          if(status)
+            status = createQoSGraph(qosdata->qos_graph_id);
+        }
+        g_free(comp.name);
+      }
+      if(!status) {
+        g_debug("QoS manager says no resources available, stopping the route");
+        qosdata->resources_ok = FALSE;
         octopus_route_stop(route);
       }
+    } else if(elem == data->pipeline
+              && previous == GST_STATE_READY && state == GST_STATE_PAUSED && pending == GST_STATE_VOID_PENDING
+              && qosdata->resources_ok)
+    {
+      g_debug("All resources acquired, playback is GO");
+      octopus_route_play(route);
     }
   }
 }
index a322079..1e71c9b 100644 (file)
@@ -28,7 +28,9 @@
 enum
 {
   HOOK_INIT,
+  HOOK_DESTROY,
   HOOK_PLAY,
+  HOOK_STOP,
   N_HOOKS
 };
 
@@ -132,6 +134,16 @@ octopus_backend_gst_class_init(OctopusBackendGstClass *klass)
                   G_TYPE_NONE,
                   1, G_TYPE_POINTER);
 
+  hooks[HOOK_DESTROY] = 
+    g_signal_new ("hook-destroy",
+                  G_TYPE_FROM_CLASS(klass),
+                  G_SIGNAL_NO_RECURSE,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__POINTER,
+                  G_TYPE_NONE,
+                  1, G_TYPE_POINTER);
+
   hooks[HOOK_PLAY] = 
     g_signal_new ("hook-play",
                   G_TYPE_FROM_CLASS(klass),
@@ -141,6 +153,16 @@ octopus_backend_gst_class_init(OctopusBackendGstClass *klass)
                   g_cclosure_user_marshal_INT__POINTER,
                   G_TYPE_INT,
                   1, G_TYPE_POINTER);
+
+  hooks[HOOK_STOP] = 
+    g_signal_new ("hook-stop",
+                  G_TYPE_FROM_CLASS(klass),
+                  G_SIGNAL_NO_RECURSE,
+                  0,
+                  hook_accumulator, NULL,
+                  g_cclosure_user_marshal_INT__POINTER,
+                  G_TYPE_INT,
+                  1, G_TYPE_POINTER);
 }
 
 static void
@@ -339,6 +361,9 @@ destroy_route(OctopusBackend *backend,
   RouteDataGst *data;
 
   stop_route(backend, route);
+
+  g_signal_emit(backend, hooks[HOOK_DESTROY], 0, route);
+
   data = (RouteDataGst *)g_object_get_data(G_OBJECT(route), "data");
   gst_object_unref(GST_OBJECT(data->pipeline));
   g_free(data);
@@ -409,6 +434,7 @@ stop_route(OctopusBackend *backend,
 {
   RouteDataGst         *data;
   GstStateChangeReturn ret;
+  int                  hook_ret;
 
   data = (RouteDataGst *)g_object_get_data(G_OBJECT(route), "data");
 
@@ -417,6 +443,10 @@ stop_route(OctopusBackend *backend,
     data->timeout_tag = 0;
   }
 
+  g_signal_emit(backend, hooks[HOOK_STOP], 0, route, &hook_ret);
+  if(hook_ret)
+    return hook_ret > 0;
+
   ret = gst_element_set_state(GST_ELEMENT(data->pipeline), GST_STATE_NULL);
   if(ret == GST_STATE_CHANGE_FAILURE) {
     g_debug("Pipeline failed to stop playback");