Add OpenMAX backend (only supports forced pipelines at the moment)
authorMikko Rasa <mikko.rasa@movial.fi>
Wed, 5 Nov 2008 15:12:47 +0000 (17:12 +0200)
committerMikko Rasa <mikko.rasa@movial.fi>
Wed, 5 Nov 2008 15:12:47 +0000 (17:12 +0200)
Backend selection in configure and from command line

configure.ac
data/openmax.ocd [new file with mode: 0644]
src/Makefile.am
src/main.c
src/octopus-backend-omx.c [new file with mode: 0644]
src/octopus-backend-omx.h [new file with mode: 0644]
src/octopus-server.c
src/octopus-server.h

index 1c97336..f08e221 100644 (file)
@@ -31,11 +31,24 @@ PKG_CHECK_MODULES(gnome_vfs, [gnome-vfs-2.0], , AC_MSG_ERROR(gnome-vfs >= 2.0 is
 AC_SUBST(gnome_vfs_CFLAGS)
 AC_SUBST(gnome_vfs_LIBS)
 
-PKG_CHECK_MODULES(gstreamer, [gstreamer-0.10 >= 0.10.10], , AC_MSG_ERROR(gstreamer-0.10 >= 0.10.10 is required))
-AC_SUBST(gstreamer_CFLAGS)
-AC_SUBST(gstreamer_LIBS)
+dnl --- BACKENDS ----------
 
-PKG_CHECK_MODULES(gstreamer_plugins_base, [gstreamer-plugins-base-0.10], , AC_MSG_ERROR(gstreamer-plugins-base-0.10 is required))
+AC_ARG_ENABLE(gstreamer, AS_HELP_STRING([--enable-gstreamer], [Include GStreamer backend]), gst_backend=$enableval, gst_backend=yes)
+AM_CONDITIONAL(GST_BACKEND, test "$gst_backend" = yes)
+if test "$gst_backend" = yes; then
+       PKG_CHECK_MODULES(gstreamer, [gstreamer-0.10 >= 0.10.10], , AC_MSG_ERROR(gstreamer-0.10 >= 0.10.10 is required))
+       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))
+fi
+
+AC_ARG_ENABLE(openmax, AS_HELP_STRING([--enable-openmax], [Include OpenMAX backend]), omx_backend=$enableval, omx_backend=no)
+AM_CONDITIONAL(OMX_BACKEND, test "$omx_backend" = yes)
+
+if test "$gst_backend" != yes -a "$omx_backend" != yes; then
+       AC_MSG_WARN(No backends have been selected.  The resulting Octopus server will be unusable.)
+fi
 
 dnl --- MODULES -----------
 
@@ -46,11 +59,14 @@ 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
+
+if test "$qosm" = yes -o "$omx_backend" = yes; then
        PKG_CHECK_MODULES(openmax, [libomxil-bellagio], , AC_MSG_ERROR(libomxil-bellagio is required))
        AC_SUBST(openmax_CFLAGS)
        AC_SUBST(openmax_LIBS)
+fi
 
+if test "$qosm" = yes; then
        PKG_CHECK_MODULES(libqosm, [libqosm], , AC_MSG_ERROR(libqosm is required))
        AC_SUBST(libqosm_CFLAGS)
        AC_SUBST(libqosm_LIBS)
@@ -59,7 +75,7 @@ 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 "$player" = xyes)
+AM_CONDITIONAL(PLAYER, test "$player" = yes)
 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)
diff --git a/data/openmax.ocd b/data/openmax.ocd
new file mode 100644 (file)
index 0000000..fe05d70
--- /dev/null
@@ -0,0 +1,16 @@
+# Octopus Component Definitions for OpenMAX backend
+
+component src_filereader
+       element OMX.st.audio_filereader
+               source local-file-audioreader
+       dynamic
+
+component dec_mad
+       element OMX.st.audio_decoder.mp3.mad
+
+component dec_ogg
+       element OMX.st.audio_decoder.ogg.single
+
+component sink_alsa
+       element OMX.st.alsa.alsasink
+               sink local-audio-alsa
index eb33a3e..292b67d 100644 (file)
@@ -1,17 +1,31 @@
+if GST_BACKEND
+BACKEND_GST_C = octopus-backend-gst.c
+BACKEND_GST_CFLAGS = $(gstreamer_CFLAGS) -DBACKEND_GST_ENABLED
+BACKEND_GST_LIBS = $(gstreamer_LIBS) -lgstinterfaces-0.10
+endif
+
+if OMX_BACKEND
+BACKEND_OMX_C = octopus-backend-omx.c
+BACKEND_OMX_CFLAGS = $(openmax_CFLAGS) -DBACKEND_OMX_ENABLED
+BACKEND_OMX_LIBS = $(openmax_LIBS)
+endif
+
 bin_PROGRAMS = octopus
 
 octopus_SOURCES =      main.c                          \
                        octopus-server.c                \
                        octopus-route.c         \
                        octopus-backend.c               \
-                       octopus-backend-gst.c   \
+                       $(BACKEND_GST_C)        \
+                       $(BACKEND_OMX_C)        \
                        octopus-module.c                \
                        octopus-module-manager.c \
                        octopus-marshals.c
 
 noinst_HEADERS =       octopus-server.h                \
                        octopus-route.h         \
-                       octopus-backend-gst.h
+                       octopus-backend-gst.h \
+                       octopus-backend-omx.h
 
 
 octopusincludedir =    $(includedir)/octopus
@@ -21,9 +35,9 @@ octopusinclude_HEADERS = \
                        octopus-module.h        \
                        octopus-module-manager.h
 
-AM_CFLAGS = $(glib_CFLAGS) $(dbus_CFLAGS) $(dbus_glib_CFLAGS) $(gmodule_CFLAGS) $(gnome_vfs_CFLAGS) $(gstreamer_CFLAGS) $(x11_CFLAGS) -DPLUGINDIR=\"${MODULEDIR}\" -DCOMPONENTDIR=\"${COMPONENTDIR}\"
+AM_CFLAGS = $(glib_CFLAGS) $(dbus_CFLAGS) $(dbus_glib_CFLAGS) $(gmodule_CFLAGS) $(gnome_vfs_CFLAGS) $(BACKEND_GST_CFLAGS) $(BACKEND_OMX_CFLAGS) $(x11_CFLAGS) -DPLUGINDIR=\"${MODULEDIR}\" -DCOMPONENTDIR=\"${COMPONENTDIR}\"
 
-octopus_LDADD = $(glib_LIBS) $(dbus_LIBS) $(dbus_glib_LIBS) $(gmodule_LIBS) $(gnome_vfs_LIBS) $(gstreamer_LIBS) $(x11_LIBS) -lgstinterfaces-0.10
+octopus_LDADD = $(glib_LIBS) $(dbus_LIBS) $(dbus_glib_LIBS) $(gmodule_LIBS) $(gnome_vfs_LIBS) $(BACKEND_GST_LIBS) $(BACKEND_OMX_LIBS) $(x11_LIBS)
 
 BUILT_SOURCES = octopus-glue.h \
                                                                octopus-marshals.h \
index 610f314..c4de5d8 100644 (file)
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  */
 #include <stdlib.h>
+#include <unistd.h>
 #include <glib.h>
 #include <gmodule.h>
 #include <glib-object.h>
+#ifdef BACKEND_GST_ENABLED
 #include <gst/gst.h>
+#endif
 
 #include "octopus-server.h"
 
 int
-main (int argc, char *argv[])
+main(int argc, char *argv[])
 {
-    GMainLoop       *loop;
-    OctopusServer   *server = NULL;
+  GMainLoop     *loop;
+  OctopusServer *server = NULL;
+  const gchar   *backend = NULL;
+  int           o;
 
-    g_type_init ();
-    gst_init (&argc, &argv);
+  g_type_init();
+#if defined BACKEND_GST_ENABLED
+  gst_init(&argc, &argv);
+  backend = "gst";
+#elif BACKEND_OMX_ENABLED
+  backend = "omx";
+#endif
 
-    loop = g_main_loop_new (NULL, FALSE);
+  while((o = getopt(argc, argv, "b:")) != -1) switch(o) {
+  case 'b':
+    backend = optarg;
+    break;
+  }
 
-    /* Initialize Octopus Server */
-    server = OCTOPUS_SERVER (
-        g_object_new (OCTOPUS_TYPE_SERVER, NULL)
-    );
+  if(!backend) {
+    g_error("No backend specified and no default could be determined at compile time");
+  }
 
-    if (!octopus_server_register_service (server)) {
-        g_object_unref (server);
+  loop = g_main_loop_new(NULL, FALSE);
 
-        g_error ("Registering Octopus Service failed.\n");
-    }
+  /* Initialize Octopus Server */
+  server = OCTOPUS_SERVER(g_object_new(OCTOPUS_TYPE_SERVER, NULL));
 
-    g_main_loop_run (loop);
+  if(!octopus_server_select_backend(server, backend)) {
+    g_object_unref(server);
 
-       return 0;
+    g_error("Couldn't select the backend '%s'", backend);
+  }
+
+  if(!octopus_server_register_service (server)) {
+    g_object_unref(server);
+
+    g_error("Registering Octopus Service failed.\n");
+  }
+
+  g_main_loop_run(loop);
+
+  return 0;
 }
 
 /* Emacs indentatation information
    Local Variables:
    indent-tabs-mode:nil
-   tab-width:4
-   c-set-offset:4
-   c-basic-offset:4
+   tab-width:2
+   c-set-offset:2
+   c-basic-offset:2
    End:
 */
-// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
+// vim: filetype=c:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
 
diff --git a/src/octopus-backend-omx.c b/src/octopus-backend-omx.c
new file mode 100644 (file)
index 0000000..7715b5f
--- /dev/null
@@ -0,0 +1,517 @@
+/*   Octopus Media Engine
+ *   Copyright 2008 Movial Creative Technologies Inc
+ *
+ *   Authors: Mikko Rasa, <mikko.rasa@movial.fi>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include <string.h>
+#include <OMX_Component.h>
+#include <OMX_Core.h>
+#include "octopus-backend-omx.h"
+
+typedef struct _RouteDataOmx  RouteDataOmx;
+typedef struct _OmxBuffer     OmxBuffer;
+typedef struct _OmxConnection OmxConnection;
+
+struct _RouteDataOmx
+{
+  GSList *omx_elems;
+  GSList *omx_conns;
+};
+
+struct _OmxBuffer
+{
+  OMX_BUFFERHEADERTYPE *out_hdr;
+  OMX_BUFFERHEADERTYPE *in_hdr;
+};
+
+struct _OmxConnection
+{
+  OMX_HANDLETYPE source;
+  unsigned       source_port;
+  OMX_HANDLETYPE sink;
+  unsigned       sink_port;
+  GSList         *buffers;
+};
+
+static gboolean
+validate_component(OctopusBackend   *backend,
+                   OctopusComponent *comp);
+static gboolean
+can_link_components(OctopusBackend   *backend,
+                    OctopusComponent *comp1,
+                    OctopusComponent *comp2);
+static gboolean
+init_route(OctopusBackend *backend,
+           OctopusRoute   *route);
+static void
+destroy_route(OctopusBackend *backend,
+              OctopusRoute   *route);
+static gboolean
+play_route(OctopusBackend *backend,
+           OctopusRoute   *route);
+static gboolean
+stop_route(OctopusBackend *backend,
+           OctopusRoute   *route);
+
+static void
+route_mapping_changed(OctopusRoute *route,
+                      gpointer     user_data);
+static OMX_ERRORTYPE
+event_handler(OMX_HANDLETYPE comp,
+              OMX_PTR        app_data,
+              OMX_EVENTTYPE  event,
+              OMX_U32        data1,
+              OMX_U32        data2,
+              OMX_PTR        event_data);
+static OMX_ERRORTYPE
+empty_buffer_done(OMX_HANDLETYPE       comp,
+                  OMX_PTR              app_data,
+                  OMX_BUFFERHEADERTYPE *buffer);
+static OMX_ERRORTYPE
+fill_buffer_done(OMX_HANDLETYPE       comp,
+                 OMX_PTR              app_data,
+                 OMX_BUFFERHEADERTYPE *buffer);
+
+/*
+ * GObject stuff
+ */
+
+G_DEFINE_TYPE(OctopusBackendOmx, octopus_backend_omx, OCTOPUS_TYPE_BACKEND)
+
+static void
+octopus_backend_omx_class_init(OctopusBackendOmxClass *klass)
+{
+  OctopusBackendClass *backend;
+
+  backend = OCTOPUS_BACKEND_CLASS(klass);
+
+  backend->validate_component = validate_component;
+  backend->can_link_components = can_link_components;
+  backend->init_route = init_route;
+  backend->destroy_route = destroy_route;
+  backend->play_route = play_route;
+  /*backend->pause_route = pause_route;*/
+  backend->stop_route = stop_route;
+}
+
+static void
+octopus_backend_omx_init(OctopusBackendOmx *backend)
+{
+  OctopusBackend *base;
+
+  base = OCTOPUS_BACKEND(backend);
+
+  base->name = "openmax";
+
+  OMX_Init();
+
+  g_debug("OpenMAX backend initialized");
+}
+
+/*
+ * OctopusBackend implementation
+ */
+
+static gboolean
+validate_component(OctopusBackend   *backend,
+                   OctopusComponent *comp)
+{
+  GSList *iter;
+
+  for(iter = comp->elements; iter; iter = iter->next) {
+    OctopusElement *elem = (OctopusElement *)iter->data;
+    unsigned       i;
+    char           name[128];
+    OMX_ERRORTYPE  err = OMX_ErrorNone;
+
+    for(i = 0; err == OMX_ErrorNone; ++i) {
+      err = OMX_ComponentNameEnum(name, sizeof(name), i);
+      if(!strcmp(name, elem->name)) 
+        break;
+    }
+
+    if(err != OMX_ErrorNone)
+      return FALSE;
+  }
+
+       return TRUE;
+}
+
+static gboolean
+can_link_components(OctopusBackend   *backend,
+                    OctopusComponent *comp1,
+                    OctopusComponent *comp2)
+{
+       return FALSE;
+}
+
+static gboolean
+init_route(OctopusBackend *backend,
+           OctopusRoute   *route)
+{
+  RouteDataOmx *data;
+
+  data = g_new0(RouteDataOmx, 1);
+  g_object_set_data(G_OBJECT(route), "data", data);
+
+  g_signal_connect(route, "mapping-changed", G_CALLBACK(route_mapping_changed), 0);
+  //g_signal_connect(route, "endpoint-changed", G_CALLBACK(route_endpoint_changed), 0);
+
+  return TRUE;
+}
+
+static void
+destroy_route(OctopusBackend *backend,
+              OctopusRoute   *route)
+{
+  RouteDataOmx *data;
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+  g_free(data);
+}
+
+static gboolean
+play_route(OctopusBackend *backend,
+           OctopusRoute   *route)
+{
+  RouteDataOmx *data;
+  GSList       *iter;
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+
+  for(iter = data->omx_elems; iter; iter = iter->next) {
+    OMX_ERRORTYPE err;
+
+    err = OMX_SendCommand((OMX_HANDLETYPE)iter->data, OMX_CommandStateSet, OMX_StateExecuting, NULL);
+    if(err != OMX_ErrorNone)
+      g_debug("Could not set component to executing state");
+  }
+
+  for(iter = data->omx_conns; iter; iter = iter->next) {
+    OmxConnection *conn = (OmxConnection *)iter->data;
+    GSList        *iter2;
+
+    for(iter2 = conn->buffers; iter2; iter2 = iter2->next) {
+      OmxBuffer *buf = (OmxBuffer *)iter2->data;
+
+      OMX_FillThisBuffer(conn->source, buf->out_hdr);
+    }
+  }
+
+  return TRUE;
+}
+
+static gboolean
+stop_route(OctopusBackend *backend,
+           OctopusRoute   *route)
+{
+  RouteDataOmx *data;
+  GSList       *iter;
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+
+  for(iter = data->omx_elems; iter; iter = iter->next) {
+    OMX_ERRORTYPE err;
+
+    err = OMX_SendCommand((OMX_HANDLETYPE)iter->data, OMX_CommandStateSet, OMX_StateIdle, NULL);
+    if(err != OMX_ErrorNone)
+      g_debug("Could not set component to idle state");
+  }
+
+  return TRUE;
+}
+
+/*
+ * Private functions
+ */
+
+static OMX_HANDLETYPE
+realize_element(OctopusRoute   *route,
+                OctopusElement *elem)
+{
+  g_debug("Realizing element '%s'", elem->name);
+  g_debug("Not implemented yet");
+
+  return NULL;
+}
+
+static void
+realize_component(OctopusBackend   *backend,
+                  OctopusRoute     *route,
+                  OctopusComponent *component)
+{
+  RouteDataOmx *data;
+  GSList       *iter;
+
+  g_debug("Realizing component '%s'", component->name);
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+
+  for(iter = component->elements; iter; iter = iter->next) {
+    OctopusElement *elem = (OctopusElement *)iter->data;
+    OMX_HANDLETYPE handle;
+
+    handle = realize_element(route, elem);
+    data->omx_elems = g_slist_prepend(data->omx_elems, handle);
+  }
+}
+
+static void
+realize_component_chain(OctopusBackend *backend,
+                        OctopusRoute   *route,
+                        GSList         *chain)
+{
+  GSList *iter;
+
+  for(iter = chain; iter; iter = iter->next)
+    realize_component(backend, route, (OctopusComponent *)iter->data);
+}
+
+static void
+realize_fixed_pipeline(OctopusRoute *route,
+                       gchar        **parts)
+{
+  RouteDataOmx     *data;
+  OMX_CALLBACKTYPE *callbacks;
+  gchar            **ptr;
+  OmxConnection    *conn = 0;
+
+  g_debug("route %p", route);
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+
+  callbacks = g_new0(OMX_CALLBACKTYPE, 1);
+  callbacks->EventHandler = event_handler;
+  callbacks->EmptyBufferDone = empty_buffer_done;
+  callbacks->FillBufferDone = fill_buffer_done;
+
+  for(ptr = parts; *ptr; ++ptr) {
+    gchar               *colon;
+    gchar               *cname;
+    OMX_HANDLETYPE      handle;
+    OMX_ERRORTYPE       err;
+    OMX_PORT_PARAM_TYPE pparam;
+    unsigned            i;
+    int                 in_port = -1;
+    int                 out_port = -1;
+    unsigned            nbufs = 0;
+    unsigned            bufsize = 32768;
+
+    colon = strchr(*ptr, ':');
+    if(colon)
+      cname=g_strndup(*ptr, colon-*ptr);
+    else
+      cname=*ptr;
+
+    g_debug(cname);
+
+    err = OMX_GetHandle(&handle, cname, route, callbacks);
+    if(err != OMX_ErrorNone) {
+      g_debug("Could not get handle for %s", *ptr);
+      return;
+    }
+
+    g_debug("%p", handle);
+
+    if(cname != *ptr)
+      g_free(cname);
+
+    data->omx_elems = g_slist_prepend(data->omx_elems, handle);
+
+    if(colon) {
+      OMX_INDEXTYPE input_fn_index;
+
+      OMX_GetExtensionIndex(handle, "OMX.ST.index.param.filereader.inputfilename", &input_fn_index);
+      OMX_SetParameter(handle, input_fn_index, colon+1);
+    }
+
+    pparam.nSize = sizeof(OMX_PORT_PARAM_TYPE);
+    pparam.nVersion.nVersion = 0x00000101;
+    OMX_GetParameter(handle, OMX_IndexParamAudioInit, &pparam);
+    for(i = 0; i < pparam.nPorts; ++i) {
+      OMX_PARAM_PORTDEFINITIONTYPE pdef;
+
+      pdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+      pdef.nVersion.nVersion = 0x00000101;
+      pdef.nPortIndex = pparam.nStartPortNumber+i;
+      OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &pdef);
+
+      if(pdef.eDir == OMX_DirInput) {
+        in_port = pparam.nStartPortNumber+i;
+      } else if(pdef.eDir == OMX_DirOutput) {
+        nbufs = pdef.nBufferCountMin;
+        out_port = pparam.nStartPortNumber+i;
+      }
+    }
+
+    err = OMX_SendCommand(handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+    if(err != OMX_ErrorNone) {
+      g_debug("Could not set component to idle state");
+      return;
+    }
+
+    if(conn) {
+      GSList *iter;
+
+      conn->sink = handle;
+      conn->sink_port = in_port;
+
+      for(iter = conn->buffers; iter; iter = iter->next) {
+        OmxBuffer *buf = (OmxBuffer *)iter->data;
+        OMX_UseBuffer(handle, &buf->in_hdr, in_port, conn, buf->out_hdr->nAllocLen, buf->out_hdr->pBuffer);
+      }
+      conn = 0;
+    }
+
+    if(out_port >= 0) {
+      unsigned j;
+
+      conn = g_new0(OmxConnection, 1);
+      conn->source = handle;
+      conn->source_port = out_port;
+
+      data->omx_conns = g_slist_prepend(data->omx_conns, conn);
+
+      g_debug("Creating %d buffers", nbufs);
+      for(j = 0; j < nbufs; ++j) {
+        OmxBuffer *buf;
+
+        buf = g_new0(OmxBuffer, 1);
+
+        OMX_AllocateBuffer(handle, &buf->out_hdr, out_port, conn, bufsize);
+        conn->buffers = g_slist_prepend(conn->buffers, buf);
+      }
+    }
+  }
+}
+
+static void
+route_mapping_changed(OctopusRoute *route,
+                      gpointer     user_data)
+{
+  RouteDataOmx     *data;
+  OctopusBackend   *backend;
+  OctopusComponent *component;
+  gchar            **sources;
+  gchar            **sinks;
+  gchar            *pipeline_desc;
+  unsigned         i;
+
+  g_debug("Route mapping changed");
+
+  data = (RouteDataOmx *)g_object_get_data(G_OBJECT(route), "data");
+  g_object_get(G_OBJECT(route), "backend", &backend,
+                                "sources", &sources,
+                                "sinks", &sinks,
+                                "pipeline-description", &pipeline_desc, NULL);
+  g_assert(OCTOPUS_IS_BACKEND_OMX(backend));
+
+  if(pipeline_desc) {
+    gchar **parts;
+
+    g_debug("Using forced pipeline description: %s", pipeline_desc);
+
+    parts = g_strsplit(pipeline_desc, " ", 0);
+    realize_fixed_pipeline(route, parts);
+    g_strfreev(parts);
+
+  } else {
+    for(i = 0; sources[i]; ++i) {
+      GSList   *chain = NULL;
+      unsigned j;
+
+      component = octopus_backend_get_component_by_endpoint(backend, sources[i], OCTOPUS_ENDPOINT_SOURCE);
+      if(!component)
+        continue;
+
+      for(j = 0; sinks[j]; ++j) {
+        if((chain = octopus_backend_build_component_chain(backend, component, sinks[j]))) {
+          realize_component_chain(backend, route, chain);
+          g_slist_free(chain);
+          break;
+        }
+      }
+    }
+  }
+}
+
+static OMX_ERRORTYPE
+event_handler(OMX_HANDLETYPE comp,
+              OMX_PTR        app_data,
+              OMX_EVENTTYPE  event,
+              OMX_U32        data1,
+              OMX_U32        data2,
+              OMX_PTR        event_data)
+{
+  OctopusRoute *route = (OctopusRoute *)app_data;
+
+  switch(event) {
+  case OMX_EventBufferFlag:
+    g_debug("End of stream");
+    stop_route(NULL, route);
+    break;
+
+  default:
+    g_debug("event_handler %p %d %lu %lu", comp, event, data1, data2);
+  }
+
+  return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE
+empty_buffer_done(OMX_HANDLETYPE       comp,
+                  OMX_PTR              app_data,
+                  OMX_BUFFERHEADERTYPE *buffer)
+{
+  OmxConnection *conn = (OmxConnection *)buffer->pAppPrivate;
+  OmxBuffer     *buf;
+  GSList        *iter;
+
+  for(iter = conn->buffers; iter; iter = iter->next) {
+    buf = (OmxBuffer *)iter->data;
+    if(buf->in_hdr == buffer) {
+      buf->out_hdr->nFilledLen = 0;
+      OMX_FillThisBuffer(conn->source, buf->out_hdr);
+      break;
+    }
+  }
+
+  return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE
+fill_buffer_done(OMX_HANDLETYPE       comp,
+                 OMX_PTR              app_data,
+                 OMX_BUFFERHEADERTYPE *buffer)
+{
+  OmxConnection *conn = (OmxConnection *)buffer->pAppPrivate;
+  OmxBuffer     *buf;
+  GSList        *iter;
+
+  for(iter = conn->buffers; iter; iter = iter->next) {
+    buf = (OmxBuffer *)iter->data;
+    if(buf->out_hdr == buffer) {
+      buf->in_hdr->nFilledLen = buf->out_hdr->nFilledLen;
+      OMX_EmptyThisBuffer(conn->sink, buf->in_hdr);
+      break;
+    }
+  }
+
+  return OMX_ErrorNone;
+}
+
+// vim: filetype=c:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
diff --git a/src/octopus-backend-omx.h b/src/octopus-backend-omx.h
new file mode 100644 (file)
index 0000000..dbf06d0
--- /dev/null
@@ -0,0 +1,58 @@
+/*   Octopus Media Engine
+ *   Copyright 2008 Movial Creative Technologies Inc
+ *
+ *   Authors: Mikko Rasa, <mikko.rasa@movial.fi>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#ifndef _OCTOPUS_BACKEND_OMX_H_
+#define _OCTOPUS_BACKEND_OMX_H_
+
+#include "octopus-backend.h"
+
+#define OCTOPUS_TYPE_BACKEND_OMX             \
+        (octopus_backend_omx_get_type())
+#define OCTOPUS_BACKEND_OMX(obj)             \
+        (G_TYPE_CHECK_INSTANCE_CAST((obj), OCTOPUS_TYPE_BACKEND_OMX, OctopusBackendOmx))
+#define OCTOPUS_IS_BACKEND_OMX(obj)          \
+        (G_TYPE_CHECK_INSTANCE_TYPE((obj), OCTOPUS_TYPE_BACKEND_OMX))
+#define OCTOPUS_BACKEND_OMX_CLASS(klass)     \
+        (G_TYPE_CHECK_CLASS_CAST((klass), OCTOPUS_TYPE_BACKEND_OMX, OctopusBackendOmxClass))
+#define OCTOPUS_IS_BACKEND_OMX_CLASS(klass)  \
+        (G_TYPE_CHECK_CLASS_TYPE((klass), OCTOPUS_TYPE_BACKEND_OMX))
+#define OCTOPUS_BACKEND_OMX_GET_CLASS(obj)   \
+        (G_TYPE_INSTANCE_GET_CLASS((obj), OCTOPUS_TYPE_BACKEND_OMX, OctopusBackendOmxClass))
+
+typedef struct _OctopusBackendOmx        OctopusBackendOmx;
+typedef struct _OctopusBackendOmxClass   OctopusBackendOmxClass;
+typedef struct _OctopusBackendOmxPrivate OctopusBackendOmxPrivate;
+
+struct _OctopusBackendOmx
+{
+  OctopusBackend           parent;
+  OctopusBackendOmxPrivate *priv;
+};
+
+struct _OctopusBackendOmxClass
+{
+  OctopusBackendClass parent;
+};
+
+GType
+octopus_backend_omx_get_type(void);
+
+#endif
+
+// vim: filetype=c:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
index 3b2d760..13550e7 100644 (file)
  *   License along with this program; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  */
+#include <string.h>
 #include <glib.h>
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-bindings.h>
 
 #include "octopus-server.h"
+#ifdef BACKEND_GST_ENABLED
 #include "octopus-backend-gst.h"
+#endif
+#ifdef BACKEND_OMX_ENABLED
+#include "octopus-backend-omx.h"
+#endif
 #include "octopus-route.h"
 #include "octopus-module-manager.h"
 #include "octopus-glue.h"
@@ -119,9 +125,6 @@ octopus_server_init(OctopusServer *server)
   priv = server->priv = g_new0(OctopusServerPrivate, 1);
 
   priv->module_manager = OCTOPUS_MODULE_MANAGER(g_object_new(OCTOPUS_TYPE_MODULE_MANAGER, NULL));
-  /* XXX Put backends to modules?  Or not? */
-  priv->backend = OCTOPUS_BACKEND(g_object_new(OCTOPUS_TYPE_BACKEND_GST, "module-manager", priv->module_manager, NULL));
-  octopus_backend_load_components_from_directory(priv->backend, COMPONENTDIR);
   priv->routes = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_object_unref);
 }
 
@@ -135,7 +138,8 @@ octopus_server_finalize(GObject *object)
   priv = server->priv;
 
   g_hash_table_destroy(priv->routes);
-  g_object_unref(priv->backend);
+  if(priv->backend)
+    g_object_unref(priv->backend);
   g_object_unref(priv->module_manager);
 
   g_free(priv);
@@ -198,6 +202,32 @@ octopus_server_register_service(OctopusServer *server)
   return TRUE;
 }
 
+gboolean
+octopus_server_select_backend(OctopusServer *server,
+                              const gchar   *name)
+{
+  OctopusServerPrivate *priv = server->priv;
+
+  /* XXX Put backends to modules?  Or not? */
+
+#ifdef BACKEND_GST_ENABLED
+  if(!strcmp(name, "gst") || !strcmp(name, "gstreamer"))
+    priv->backend = OCTOPUS_BACKEND(g_object_new(OCTOPUS_TYPE_BACKEND_GST, "module-manager", priv->module_manager, NULL));
+#endif
+
+#ifdef BACKEND_OMX_ENABLED
+  if(!strcmp(name, "omx") || !strcmp(name, "openmax"))
+    priv->backend = OCTOPUS_BACKEND(g_object_new(OCTOPUS_TYPE_BACKEND_OMX, "module-manager", priv->module_manager, NULL));
+#endif
+
+  if(priv->backend) {
+    octopus_backend_load_components_from_directory(priv->backend, COMPONENTDIR);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 /*
  * Helper functions
  */
index 5d04eca..03aee7e 100644 (file)
@@ -64,6 +64,9 @@ octopus_server_get_type        (void);
 
 gboolean
 octopus_server_register_service(OctopusServer *server);
+gboolean
+octopus_server_select_backend  (OctopusServer *server,
+                                const gchar   *name);
 
 /* D-Bus API */