Adding SN12/ST12 format support
authorBarun Kumar Singh <barun.singh@samsung.com>
Wed, 30 Sep 2015 06:21:14 +0000 (11:51 +0530)
committerBarun Kumar Singh <barun.singh@samsung.com>
Sat, 31 Oct 2015 17:36:41 +0000 (10:36 -0700)
Adding gst-omx version 1.2.0 base code.
Signed-off-by: Barun Kr. Singh <barun.singh@samsung.com>
Change-Id: I61a89aff3b294b993fc4c5540a492a51b886bf76

101 files changed:
Android.mk [deleted file]
ChangeLog
INSTALL [deleted file]
Makefile.am
NEWS
RELEASE
common [deleted submodule]
common/Makefile.am [new file with mode: 0644]
common/extract-release-date-from-doap-file [new file with mode: 0644]
common/gst-autogen.sh [new file with mode: 0644]
common/m4/Makefile.am [new file with mode: 0644]
common/m4/README [new file with mode: 0644]
common/m4/as-ac-expand.m4 [new file with mode: 0644]
common/m4/as-auto-alt.m4 [new file with mode: 0644]
common/m4/as-compiler-flag.m4 [new file with mode: 0644]
common/m4/as-compiler.m4 [new file with mode: 0644]
common/m4/as-docbook.m4 [new file with mode: 0644]
common/m4/as-gcc-inline-assembly.m4 [new file with mode: 0644]
common/m4/as-libtool-tags.m4 [new file with mode: 0644]
common/m4/as-libtool.m4 [new file with mode: 0644]
common/m4/as-python.m4 [new file with mode: 0644]
common/m4/as-version.m4 [new file with mode: 0644]
common/m4/ax_create_stdint_h.m4 [new file with mode: 0644]
common/m4/check.m4 [new file with mode: 0644]
common/m4/glib-gettext.m4 [new file with mode: 0644]
common/m4/gst-arch.m4 [new file with mode: 0644]
common/m4/gst-args.m4 [new file with mode: 0644]
common/m4/gst-check.m4 [new file with mode: 0644]
common/m4/gst-debuginfo.m4 [new file with mode: 0644]
common/m4/gst-default.m4 [new file with mode: 0644]
common/m4/gst-doc.m4 [new file with mode: 0644]
common/m4/gst-dowhile.m4 [new file with mode: 0644]
common/m4/gst-error.m4 [new file with mode: 0644]
common/m4/gst-feature.m4 [new file with mode: 0644]
common/m4/gst-function.m4 [new file with mode: 0644]
common/m4/gst-gettext.m4 [new file with mode: 0644]
common/m4/gst-glib2.m4 [new file with mode: 0644]
common/m4/gst-libxml2.m4 [new file with mode: 0644]
common/m4/gst-package-release-datetime.m4 [new file with mode: 0644]
common/m4/gst-parser.m4 [new file with mode: 0644]
common/m4/gst-platform.m4 [new file with mode: 0644]
common/m4/gst-plugin-docs.m4 [new file with mode: 0644]
common/m4/gst-plugindir.m4 [new file with mode: 0644]
common/m4/gst-valgrind.m4 [new file with mode: 0644]
common/m4/gst-x11.m4 [new file with mode: 0644]
common/m4/gst.m4 [new file with mode: 0644]
common/m4/gtk-doc.m4 [new file with mode: 0644]
common/m4/introspection.m4 [new file with mode: 0644]
common/m4/orc.m4 [new file with mode: 0644]
common/m4/pkg.m4 [new file with mode: 0644]
config/Makefile.am [changed mode: 0755->0644]
config/bellagio/gstomx.conf
config/exynos/Makefile.am [changed mode: 0755->0644]
config/exynos/gstomx.conf [changed mode: 0755->0644]
config/exynos64/Makefile.am [moved from config/odroid/Makefile.am with 76% similarity]
config/exynos64/gstomx.conf [moved from config/odroid/gstomx.conf with 72% similarity]
config/rpi/gstomx.conf
configure.ac [changed mode: 0755->0644]
examples/Makefile.am [new file with mode: 0644]
examples/egl/Makefile.am [new file with mode: 0644]
examples/egl/cube_texture_and_coords.h [new file with mode: 0644]
examples/egl/testegl.c [new file with mode: 0644]
gst-omx.doap
gst-omx.manifest [new file with mode: 0644]
m4/Makefile.am [new file with mode: 0644]
omx/Makefile.am
omx/gstomx.c [changed mode: 0755->0644]
omx/gstomx.h
omx/gstomxaacdec.c [new file with mode: 0644]
omx/gstomxaacdec.h [new file with mode: 0644]
omx/gstomxamrdec.c [new file with mode: 0644]
omx/gstomxamrdec.h [new file with mode: 0644]
omx/gstomxanalogaudiosink.c [new file with mode: 0644]
omx/gstomxanalogaudiosink.h [new file with mode: 0644]
omx/gstomxaudiodec.c [new file with mode: 0644]
omx/gstomxaudiodec.h [new file with mode: 0644]
omx/gstomxaudioenc.c
omx/gstomxaudioenc.h
omx/gstomxaudiosink.c [new file with mode: 0644]
omx/gstomxaudiosink.h [new file with mode: 0644]
omx/gstomxbufferpool.c [new file with mode: 0644]
omx/gstomxbufferpool.h [new file with mode: 0644]
omx/gstomxh263enc.c
omx/gstomxh264dec.c
omx/gstomxh264enc.c
omx/gstomxh264enc.h
omx/gstomxhdmiaudiosink.c [new file with mode: 0644]
omx/gstomxhdmiaudiosink.h [new file with mode: 0644]
omx/gstomxmp3dec.c [new file with mode: 0644]
omx/gstomxmp3dec.h [new file with mode: 0644]
omx/gstomxmpeg4videoenc.c
omx/gstomxvideo.c [new file with mode: 0644]
omx/gstomxvideo.h [new file with mode: 0644]
omx/gstomxvideodec.c [changed mode: 0755->0644]
omx/gstomxvideodec.h
omx/gstomxvideoenc.c [changed mode: 0755->0644]
omx/gstomxvideoenc.h [changed mode: 0755->0644]
omx/gstomxvp8dec.h
packaging/common.tar.bz2 [deleted file]
packaging/gitmodules.sh [deleted file]
packaging/gst-omx.spec [changed mode: 0755->0644]

diff --git a/Android.mk b/Android.mk
deleted file mode 100644 (file)
index bc99d9f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-GST_OMX_TOP := $(LOCAL_PATH)
-
-GST_OMX_BUILT_SOURCES := omx/Android.mk
-
-GST_OMX_BUILT_SOURCES := $(patsubst %, $(abspath $(GST_OMX_TOP))/%, $(GST_OMX_BUILT_SOURCES))
-
-.PHONY: gst-omx-configure
-gst-omx-configure:
-       cd $(GST_OMX_TOP) ; \
-       CC="$(CONFIGURE_CC)" \
-       CFLAGS="$(CONFIGURE_CFLAGS)" \
-       LD=$(TARGET_LD) \
-       LDFLAGS="$(CONFIGURE_LDFLAGS)" \
-       CPP=$(CONFIGURE_CPP) \
-       CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \
-       PKG_CONFIG_LIBDIR="$(CONFIGURE_PKG_CONFIG_LIBDIR)" \
-       PKG_CONFIG_TOP_BUILD_DIR=/ \
-       $(abspath $(GST_OMX_TOP))/$(CONFIGURE) --host=arm-linux-androideabi \
-       --prefix=/system --disable-orc --disable-valgrind --disable-gtk-doc && \
-       for file in $(GST_OMX_BUILT_SOURCES); do \
-               rm -f $$file && \
-               make -C $$(dirname $$file) $$(basename $$file) ; \
-       done
-
-CONFIGURE_TARGETS += gst-omx-configure
-
--include $(GST_OMX_TOP)/omx/Android.mk
index 1f254ce..3ba19b7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+=== release 1.2.0 ===
+
+2014-07-23  Sebastian Dröge <slomo@coaxion.net>
+
+       * configure.ac:
+         releasing 1.2.0
+
+2014-07-22 09:23:00 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * config/bellagio/gstomx.conf:
+       * config/rpi/gstomx.conf:
+         config: Update ranks to PRIMARY+1 to have higher preference than avdec_*
+         See https://bugzilla.gnome.org/show_bug.cgi?id=732161
+
+2014-07-20 17:46:30 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudiosink.c:
+         omxaudiosink: Set port to not flushing in prepare() and keep it at flushing in unprepare()
+         https://bugzilla.gnome.org/show_bug.cgi?id=733168
+
+2014-07-13 22:15:18 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaacdec.c:
+       * omx/gstomxaudiodec.c:
+       * omx/gstomxaudiodec.h:
+       * omx/gstomxmp3dec.c:
+         omxaudiodec: Implement setting of fallback channel positions
+
+2014-07-13 18:22:39 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/Makefile.am:
+       * omx/gstomx.c:
+       * omx/gstomxaacdec.c:
+       * omx/gstomxaacdec.h:
+       * omx/gstomxmp3dec.c:
+         omx: Add AAC audio decoder
+
+2014-07-02 09:22:28 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudiodec.c:
+         omxaudiodec: Get PCM parameters from the out port, not the in port
+
+2014-05-15 13:24:39 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudiodec.c:
+         omxaudiodec: Implement hack for not disabling the output port after set_format until the output format is known
+         Needed on some OMX implementations, e.g. the one from Atmel. It does
+         not send the settings-changed event on the output port if it is
+         disabled.
+
+2014-05-10 23:12:54 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/Makefile.am:
+       * omx/gstomx.c:
+       * omx/gstomxaudiodec.c:
+       * omx/gstomxaudiodec.h:
+       * omx/gstomxmp3dec.c:
+       * omx/gstomxmp3dec.h:
+         omx: Add audio decoder base class and a subclass for MP3
+
+2014-07-01 09:38:01 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * configure.ac:
+       * omx/Makefile.am:
+         omx: Link to gmodule-2.0-no-export for being able to use the g_module_*() API
+         https://bugzilla.gnome.org/show_bug.cgi?id=732518
+
+2014-06-30 15:00:54 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * examples/egl/testegl.c:
+         examples: #define GST_USE_UNSTABLE_API for libgstgl
+
+2014-06-29 19:10:19 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxh264enc.c:
+       * omx/gstomxh264enc.h:
+         omxh264enc: Properly accumulate headers and push before the next frame
+         Fixes output of encoding on RPi, where each header buffer (SPS and PPS)
+         is in a separate OMX buffer.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726669
+
+2014-06-29 19:04:54 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: Implement flush() instead of the deprecated reset()
+
+2014-06-25 17:14:18 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * config/rpi/gstomx.conf:
+         rpi: It's 44100Hz, not 41400Hz
+
+2014-06-25 11:12:51 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * configure.ac:
+         configure.ac: require gstgl >= 1.3.3
+
+2014-04-25 13:25:05 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * Makefile.am:
+       * configure.ac:
+         example: enable testegl
+         See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-25 10:19:54 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * examples/egl/testegl.c:
+         testegl: do matrix mutlplication in the shader
+         See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-25 09:36:38 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * examples/egl/testegl.c:
+         testegl: add a comment for the parse command
+         See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-04-25 17:32:16 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * examples/egl/Makefile.am:
+       * examples/egl/cube_texture_and_coords.h:
+       * examples/egl/testegl.c:
+         testegl: convert code from GLESv1 to GLESv2
+         See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-04-25 13:21:59 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * examples/egl/Makefile.am:
+       * examples/egl/testegl.c:
+         testegl: port to gstgl API
+         - append a glfilter just before fakesink
+         So that we get gltexture or eglimages
+         - propagate our EGLDisplay to the pipeline
+         see GST_QUERY_CONTEXT
+         - share our EGLContext with the iternal gl context
+         of the pipeline, see GST_QUERY_ALLOCATION
+         - use GstVideoGLTextureUploadMeta to upload
+         the incoming gltexture or eglimage to our gl texture
+         TODO: convert from GLESv1 to GLESv2
+         See https://bugzilla.gnome.org/show_bug.cgi?id=728940
+
+2014-06-24 14:52:58 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxbufferpool.c:
+       * omx/gstomxbufferpool.h:
+       * omx/gstomxvideodec.c:
+         omxbufferpool: Copy buffers if the stride does not match and we can't use video meta
+         https://bugzilla.gnome.org/show_bug.cgi?id=731672
+
+2014-06-24 14:52:43 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * configure.ac:
+       * omx/gstomx.h:
+       * omx/gstomxvp8dec.h:
+         omx: Only include OMX_VideoExt.h conditionally
+         It does not exist on the RPi for example.
+
+2014-06-24 13:59:44 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * configure.ac:
+         configure.ac: Require GStreamer core/base >= 1.2.2
+         Needed at least for gst_video_decoder_release_frame().
+
+2014-06-24 13:02:13 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: Fix format string compiler warning
+
+2014-06-22 21:11:45 +0000  Michal Lazo <xlazom00@gmail.com>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: Initialize debug category
+
+2014-06-24 12:42:22 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: Properly convert OMX alignment to GStreamer alignment
+         GStreamer uses a bitmask for the alignment while OMX uses the
+         alignment itself. Let's convert.
+         https://bugzilla.gnome.org/show_bug.cgi?id=710564
+
+2014-06-24 11:11:28 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxh264enc.c:
+         omxh264enc: Don't let baseclass finish frames for SPS/PPS buffers
+         Otherwise we a) send them twice, and b) finish a frame for something
+         that does not even include a frame.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726669
+
+2014-06-24 10:22:37 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideo.h:
+         omxvideo: Include the separate headers too for compatibility with 1.0.x
+
+2014-03-24 16:09:40 +0800  Zhao, Halley <halley.zhao@intel.com>
+
+       * configure.ac:
+       * omx/gstomxvp8dec.h:
+         omxvp8dec: use VP8 definition from OMX_VideoExt.h
+         https://bugzilla.gnome.org/show_bug.cgi?id=726957
+
+2014-03-24 15:33:26 +0800  Zhao, Halley <halley.zhao@intel.com>
+
+       * configure.ac:
+         configure: add --with-omx-header-path option for external omx headers
+         https://bugzilla.gnome.org/show_bug.cgi?id=726957
+
+2014-06-18 23:04:33 +0200  Aurélien Zanelli <aurelien.zanelli@darkosphere.fr>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fix a query leak
+         Also add a debug message if query fails.
+         https://bugzilla.gnome.org/show_bug.cgi?id=731898
+
+2014-05-30 15:29:15 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: release frames with old PTS to avoid memory issue
+         Interlaced stream could make the decoder use two input frames to produce
+         one output frame causing the gstvideodecoder frame list to grow.
+         Assuming the video decoder output frame in display order rather than in
+         decoding order, this commit add a way to release frames with PTS less
+         than current output frame.
+         https://bugzilla.gnome.org/show_bug.cgi?id=730995
+
+2013-06-27 21:59:29 +0900  Kazunori Kobayashi <kkobayas@igel.co.jp>
+
+       * omx/gstomx.c:
+         omx: Fix a missing g_free() in error path
+         This fixes a memory leak with g_strdup() when an error occurs.
+         https://bugzilla.gnome.org/show_bug.cgi?id=731141
+
+2014-06-02 15:34:09 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: add missing stream unlock in error path
+
+2014-05-31 15:12:05 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+         omx: Don't handle disabling/enabling ports exactly like flushing
+         Otherwise we might abort a flush operation in another thread when
+         enabling/disabling ports, leading to deadlocks sometimes.
+         https://bugzilla.gnome.org/show_bug.cgi?id=730989
+
+2014-05-26 11:02:10 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Don't leak buffer pool config in error cases
+         CID 1216158
+
+2014-05-21 10:53:43 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * common:
+         Automatic update of common submodule
+         From 211fa5f to 1f5d3c3
+
+2014-05-19 09:10:07 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: Don't forget to unref codec state
+         CID 1214603
+
+2014-05-19 09:08:33 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Make output buffer pointer always initialized
+         CID 1214605
+
+2014-05-19 09:06:42 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Check return value of gst_buffer_map()
+         CID 1214599
+
+2014-05-19 09:04:09 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Check return value of gst_omx_port_set_enabled() for errors
+         CID 1214589
+
+2014-05-19 09:01:46 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Check return values of buffer pool config parsing functions
+         CID 1214588
+
+2014-05-19 08:48:50 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+         omx: Remove dead code, buf can never be NULL here as we just check for that the line above
+         CID 1214596
+
+2014-05-19 08:47:36 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+         omx: Fix comparisons in gst_omx_state_to_string() case to actually make sense
+         CID 1214593
+
+2014-05-19 08:45:10 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+         omx: Make sure to compare the error codes as unsigned integers so that comparisons >2**31 actually work
+         CID 1214592
+
+2014-05-19 08:40:23 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+         omx: Fix comparisons in gst_omx_command_to_string() default cause to actually work
+         CID 1214591
+
+2014-05-15 13:22:56 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudioenc.c:
+         omxaudioenc: Implement hack for not disabling the output port after set_format until the output format is known
+         Needed on some OMX implementations, e.g. the one from Atmel. It does
+         not send the settings-changed event on the output port if it is
+         disabled.
+
+2014-05-15 13:21:07 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: Implement hack for not disabling the output port after set_format until the output format is known
+         Needed on some OMX implementations, e.g. the one from Atmel. It does
+         not send the settings-changed event on the output port if it is
+         disabled.
+
+2014-05-15 10:58:34 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomx.c:
+       * omx/gstomx.h:
+       * omx/gstomxvideodec.c:
+         omx: Add a hack for not disabling the output port after set_format until the output format is known
+         Needed on some OMX implementations, e.g. the one from Atmel. It does
+         not send the settings-changed event on the output port if it is
+         disabled.
+
+2014-05-12 12:33:32 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxaudiosink.c:
+         omxaudiosink: implement _delay only in the RaspberryPI
+         Make code implementation conditionally built for RaspberryPI because
+         OMX_IndexConfigAudioRenderingLatency seems to be a Broadcom extension.
+         On other targets the query position might not be accurate without
+         implementing _delay appropriatelly.
+
+2014-05-12 08:56:15 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudioenc.c:
+         omxaudioenc: Correctly scale nTickCount by OMX_TICKS_PER_SECOND
+
+2014-05-10 22:48:23 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudioenc.c:
+         omxaudioenc: Drain encoder on NULL buffer and don't drain on flushing
+
+2014-05-10 22:47:56 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Set nTickCount based on the buffer's duration instead of something wrong
+
+2014-05-10 22:47:21 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: Set nTickCount to the whole duration of the buffer instead of a wrong calculation
+
+2014-05-10 22:46:51 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudiosink.c:
+         omxaudiosink: Fix format string compiler warnings
+
+2014-04-04 14:11:58 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * config/rpi/gstomx.conf:
+       * omx/Makefile.am:
+       * omx/gstomx.c:
+       * omx/gstomxanalogaudiosink.c:
+       * omx/gstomxanalogaudiosink.h:
+       * omx/gstomxaudiosink.c:
+       * omx/gstomxaudiosink.h:
+       * omx/gstomxhdmiaudiosink.c:
+       * omx/gstomxhdmiaudiosink.h:
+         omxaudiosink: Implements OpenMAX based audio sinks
+         Provides omxanalogaudiosink and omxhdmiaudiosink elements on
+         the Raspberry PI.
+         - omxanalogaudiosink is capable to render raw mono or stereo audio
+         through the jack output.
+         - omxhdmiaudiosink is capable to render raw audio up to 8 channels
+         and transmit ac3/dts(IEC 61937) through the HDMI output.
+         - sinks provide a clock derived from rendered samples
+         - sinks support the GstStreamVolume interface by implementing
+         the volume and mute properties.
+         https://bugzilla.gnome.org/show_bug.cgi?id=728962
+
+2014-05-03 10:17:35 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+       * common:
+         Automatic update of common submodule
+         From bcb1518 to 211fa5f
+
+2014-04-29 15:16:16 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: can negotiate caps with memory:EGLImage feature when using EGLImage allocator
+         Previously when using gst EGLImage allocator the caps was
+         video/x-raw, format=RGBA instead of
+         video/x-raw(memory:EGLImage), format=RGBA
+         Kepp previous behavior in case negotiation fails with caps feature.
+         It means it will still have a chance to use EGLImage even if the
+         feature is not in the caps.
+         https://bugzilla.gnome.org/show_bug.cgi?id=729196
+
+2014-04-23 09:57:48 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvp8dec.h:
+         omxvp8dec: fix typo in GST_TYPE_OMX_VP8_DEC define
+         https://bugzilla.gnome.org/show_bug.cgi?id=728774
+
+2014-04-16 11:00:55 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: don't unref caps before logging field from it
+         https://bugzilla.gnome.org/show_bug.cgi?id=728322
+
+2014-04-15 17:30:13 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * Makefile.am:
+       * configure.ac:
+         example: disable testegl since libgstegl has been removed
+         As decided in bug #703343
+         Not compatible with the new libgstgl API.
+         A portage has been started, attachment 272800.
+         https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-15 17:11:08 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: use new libgstgl API since libgstegl has been removed
+         There is no point to retrieve a ref/unref type
+         instead of an EGLDisplay directly. It's like for EGLImage.
+         https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-15 17:06:38 +0100  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * configure.ac:
+       * examples/Makefile.am:
+       * omx/Makefile.am:
+       * omx/gstomxvideodec.c:
+         configure.ac: check for libgstgl since libgstegl has been removed
+         https://bugzilla.gnome.org/show_bug.cgi?id=703343
+
+2014-04-09 18:52:16 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxbufferpool.c:
+       * omx/gstomxvideodec.c:
+         omxvideodec: add support of more color format
+         Add support for ABGR, ARGB, RGB16, BGR16, YUY2, UYVY, YVYU, GRAY8 and
+         NV16 color format.
+
+2014-04-09 18:51:57 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: simplify color format conversion in fill_buffer function
+
+2014-04-09 18:51:41 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: make video stride and offset calculation easier
+         It will be easier to support more color format.
+
+2014-04-09 18:51:12 +0200  Aurélien Zanelli <aurelien.zanelli@parrot.com>
+
+       * omx/gstomxvideo.c:
+       * omx/gstomxvideo.h:
+       * omx/gstomxvideodec.c:
+         omx: add an helper to convert OMX color format to GStreamer color format
+
+2014-03-10 17:43:50 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+       * omx/gstomxvideodec.c:
+         omxvideodec: Implement pipeline draining to support adaptive scenarios
+         When draining due a format change also drain
+         the pipeline to reclaim back all buffers.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-27 13:57:32 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: fix several memory leaks in the testegl example
+         Ensure to call to image_data_free in order to release GPU resources.
+         Also ensure to destroy EGLImage and GLTexture from proper
+         thread/context.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-25 17:16:31 +0000  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * examples/egl/testegl.c:
+         examples: keep a ref on the buffer instead of the memory
+         Like in eglglessink
+         https://bugzilla.gnome.org/show_bug.cgi?id=726107
+
+2014-03-07 20:08:05 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fixes race condition during seeks
+         Acording 6.1.3 Seek Event Sequence in the OpenMAX IL 1.1.2 spec
+         document in order to flush the component it needs to be in
+         paused state.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-01-29 18:31:26 +0000  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: use flush because reset is deprecated
+         https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-01-27 17:03:50 +0000  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: populate the most downstream output port on reset
+         Make seeking work when using egl_render component
+         https://bugzilla.gnome.org/show_bug.cgi?id=726038
+
+2014-03-24 17:49:59 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: return buffers to the pool instead of freeing them
+         We have to return the buffers back to the pool in when stopping to
+         not mess with the GstBufferPool accounting.
+         The OMX buffers will be freed when those won't be in charge of the
+         pool in the chained up call to 'stop'.
+         Fixes segfaults on finalize and pool not being properly deactivated.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726337
+
+2014-03-19 12:12:49 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: add missing unlock in the error path
+         Signed-off-by: Christian König <christian.koenig@amd.com>
+         https://bugzilla.gnome.org/show_bug.cgi?id=726958
+
+2014-03-18 23:36:59 +0100  Michal Lazo <xlazom00@gmail.com>
+
+       * omx/gstomxh264enc.c:
+       * omx/gstomxh264enc.h:
+         fix filemode
+
+2014-03-17 09:57:11 +0000  Julien Isorce <julien.isorce@collabora.co.uk>
+
+       * omx/gstomxbufferpool.c:
+         omxbufferpool: fix memory leak if used on output port
+         When using GstOMXBufferPool on an output port, it internally uses
+         a GPtrArray to manage the GstBuffers instead of the default queue
+         from the GstBufferPool base class.
+         In this case GstBufferPool::default_free_buffer is not called when
+         the pool is stopped. Because the queue is empty. So explicitely
+         call gst_omx_buffer_pool_free_buffer on each buffer contained in
+         the GPtrArray.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726337
+
+2014-03-16 17:32:05 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxh264enc.c:
+         omxh264enc: Fix compiler warnings
+
+2014-03-16 17:19:08 +0100  Michal Lazo <xlazom00@gmail.com>
+
+       * omx/gstomxh264enc.c:
+       * omx/gstomxh264enc.h:
+         omxh264enc: IDR interval, SPS and PPS headers for rpi
+         https://bugzilla.gnome.org/show_bug.cgi?id=720031
+
+2014-03-13 14:26:58 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomx.c:
+       * omx/gstomx.h:
+       * omx/gstomxvideo.c:
+         omxvideo: fix debug category initialisation
+         https://bugzilla.gnome.org/show_bug.cgi?id=726024
+
+2014-03-13 19:04:47 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxbufferpool.h:
+         omxbufferpool: add proper type definitions
+         https://bugzilla.gnome.org/show_bug.cgi?id=726325
+
+2014-03-02 10:30:04 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomx.c:
+         omx: consolidate message waiting code
+         Add a wait_message helper function and remove all those duplicated code.
+         https://bugzilla.gnome.org/show_bug.cgi?id=725493
+
+2014-03-12 12:48:12 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideo.c:
+         omx: Copy old copyright notice into the new file
+
+2014-03-12 12:47:34 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxvideo.c:
+       * omx/gstomxvideo.h:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: Rename function from _4_ to _for_ for clarity
+
+2014-03-03 16:15:24 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/Makefile.am:
+       * omx/gstomxvideo.c:
+       * omx/gstomxvideo.h:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omxvideo: start sharing more code between video decoder and encoder
+         Identical functionality spread of two different components.
+         We can't use a common base class because of different inheritance,
+         but let's try to share the code anyway.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726024
+
+2014-03-12 12:43:49 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * examples/egl/Makefile.am:
+         examples: Only build RPi EGL example if RPi was chosen as target
+
+2014-03-12 12:42:23 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxbufferpool.h:
+         omxbufferpool: Fix header include guard
+
+2014-03-05 11:41:02 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/Makefile.am:
+       * omx/gstomxbufferpool.c:
+       * omx/gstomxbufferpool.h:
+       * omx/gstomxvideodec.c:
+         omxvideodec: separate the buffer pool from the decoder
+         https://bugzilla.gnome.org/show_bug.cgi?id=726025
+
+2014-03-04 17:41:20 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomx.c:
+       * omx/gstomx.h:
+       * omx/gstomxvideodec.c:
+         omx: simplify tunnel functions
+         Specifying the component is error prone and unnecessary.
+         https://bugzilla.gnome.org/show_bug.cgi?id=726021
+
+2014-03-07 17:12:24 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fix memory leak in gst_omx_video_dec_allocate_output_buffers
+         https://bugzilla.gnome.org/show_bug.cgi?id=725907
+
+2014-03-07 13:18:49 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fix memory leak gst_omx_video_dec_negotiate
+         https://bugzilla.gnome.org/show_bug.cgi?id=725907
+
+2014-03-05 18:54:05 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: fix a memory leak in gst_omx_video_enc_getcaps
+         https://bugzilla.gnome.org/show_bug.cgi?id=725826
+
+2014-03-05 17:43:33 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * Makefile.am:
+         Makefile.am: build examples
+         There's no reason to not build the examples now that are ported to 1.x.
+
+2014-03-05 17:25:09 +0100  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: avoid a clashing name with the recently added GstEGLImagePool
+         Fixes build with current master.
+
+2013-09-05 03:41:10 -0600  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: simplify _find_nearest_frame
+         Just the same as we did with the decoder. Also give the
+         function a gst_omx_video_enc prefix to distinct it from
+         the decoder function.
+         https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2013-09-05 02:23:39 -0600  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: simplify _find_nearest_frame
+         No need to make it more complicated and error prone than
+         necessary. Also give the function a gst_omx_video_dec prefix
+         to distinct it from the encoder function.
+         https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2013-09-05 02:05:52 -0600  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: remove dead code
+         This code doesn't seems to be used for quite a while,
+         remove it before it starts to rot.
+         https://bugzilla.gnome.org/show_bug.cgi?id=724236
+
+2014-03-01 22:28:24 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomx.c:
+         omx: fix two serious message handling bugs
+         Waiting for the next message if we already got one
+         is nonsense and can lead to lockups.
+         https://bugzilla.gnome.org/show_bug.cgi?id=725468
+
+2014-03-01 18:49:41 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideoenc.c:
+         omxvideoenc: fix startup race condition
+         The reset function shouldn't start the src pad
+         loop if it wasn't started before.
+         Signed-off-by: Christian König <christian.koenig@amd.com>
+
+2014-03-01 18:48:17 +0100  Christian König <christian.koenig@amd.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fix startup race condition
+         The reset function shouldn't start the src pad
+         loop if it wasn't started before.
+         Signed-off-by: Christian König <christian.koenig@amd.com>
+
+2014-02-28 09:36:13 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * common:
+         Automatic update of common submodule
+         From fe1672e to bcb1518
+
+2014-02-26 22:15:00 +0100  Stefan Sauer <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From 1a07da9 to fe1672e
+
+2014-01-30 10:45:18 +0100  Edward Hervey <bilboed@bilboed.com>
+
+       * common:
+         Automatic update of common submodule
+         From d48bed3 to 1a07da9
+
+2014-01-25 17:44:14 +0100  Sebastian Dröge <sebastian@centricular.com>
+
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: Don't handle FLUSHING and NOT_LINKED as errors
+         Also don't stop the task on NOT_LINKED. We're not a demuxer.
+
+2013-12-22 22:35:31 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * common:
+         Automatic update of common submodule
+         From dbedaa0 to d48bed3
+
+2013-11-05 11:22:02 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+       * common:
+         Automatic update of common submodule
+         From 865aa20 to dbedaa0
+
+2013-09-28 13:32:37 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: simplify the thread synchronization code
+         Make everithing more simple and fix the races conditions remaining in
+         the previous approaches.
+
+2013-09-25 19:17:17 +0200  Sebastian Dröge <slomo@circular-chaos.org>
+
+       * config/rpi/gstomx.conf:
+         rpi: The WMV/VC1 decoder can only do WMV9 and VC1, no older versions
+
+2013-09-24 18:34:42 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * common:
+         Automatic update of common submodule
+         From 6b03ba7 to 865aa20
+
+2013-09-24 18:48:24 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: fix another race condition
+         Fix a race condition that caused randome deadlocks on EOS.
+
+2013-09-20 17:19:53 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * config/rpi/gstomx.conf:
+         rpi: fix a copy paste error in the config file
+
+2013-09-20 17:09:52 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: fix a race condition when seeking
+         Fixes a race condition that caused pipeline deadlock during seeks.
+
+2013-09-20 10:38:12 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: display QoS statistics
+
+2013-09-20 09:34:37 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: use dedicated thread for rendering the scene
+         Produces smother animation and prevents dropping frames due busy
+         mainloop.
+
+2013-09-20 08:25:21 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/testegl.c:
+         examples: don't force an specific audio sink
+         Let playbin2 choose the audiosink available in the system.
+
+2013-09-20 08:19:48 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * examples/egl/Makefile.am:
+         examples: drop remnants of initial appsink attempt
+
+2013-09-20 16:18:18 +0200  Edward Hervey <edward@collabora.com>
+
+       * common:
+         Automatic update of common submodule
+         From b613661 to 6b03ba7
+
+2013-09-19 18:45:36 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * common:
+         Automatic update of common submodule
+         From 74a6857 to b613661
+
+2013-09-19 17:38:30 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * common:
+         Automatic update of common submodule
+         From 01a7a46 to 74a6857
+
+2013-08-20 16:00:07 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * omx/gstomx.c:
+       * omx/gstomxvideodec.c:
+         omx: don't use the 'z' modifier to print size_t
+         gcc will warn in some cases even if the size of the type
+         is exactly that of size_t on the platform.
+         https://bugzilla.gnome.org/show_bug.cgi?id=699008
+
+2013-07-01 15:48:47 +0200  Roman Arutyunyan <arutyunyan.roman@gmail.com>
+
+       * omx/gstomxvideoenc.c:
+         gstomxvideoenc: Set bitrate in setcaps
+         Otherwise it gets lost whenever we configure new caps
+         https://bugzilla.gnome.org/show_bug.cgi?id=698049
+
+2013-06-30 18:17:05 +0700  Ilya Smelykh <ilya@videoexpertsgroup.com>
+
+       * examples/egl/testegl.c:
+         examples: enable audio in testegl example
+
+2013-06-12 09:38:22 +0200  Sebastian Dröge <slomo@circular-chaos.org>
+
+       * configure.ac:
+         configure: Allow build without gstreamer-egl
+
+2013-06-07 12:39:18 +0700  Ilya Smelykh <ilya@videoexpertsgroup.com>
+
+       * examples/egl/Makefile.am:
+       * examples/egl/testegl.c:
+         examples: testegl example port to 1.x
+         https://bugzilla.gnome.org/show_bug.cgi?id=701706
+
+2013-06-05 15:17:16 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * common:
+         Automatic update of common submodule
+         From 098c0d7 to 01a7a46
+
+2013-05-20 12:06:34 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: Take lock on EOS to update the flow return value
+         Fixes "GThread-ERROR **: file gthread-posix.c: line 171
+         (g_mutex_free_posix_impl): error 'Device or resource busy' during
+         'pthread_mutex_destroy ((pthread_mutex_t *) mutex)'" in _finalize.
+
+2013-05-15 10:54:12 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * common:
+         Automatic update of common submodule
+         From 5edcd85 to 098c0d7
+
+2013-04-11 17:35:19 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * Makefile.am:
+       * configure.ac:
+       * examples/Makefile.am:
+       * examples/egl/Makefile.am:
+       * examples/egl/cube_texture_and_coords.h:
+       * examples/egl/testegl.c:
+         examples: add an example aplication based OpenGL ES + EGL
+         Application that shows how to integrate playbin with an OpenGL ES
+         scene through EGL. Renders a video on the surfaces of an animated cube.
+         The code is not ported to 1.x so it's not built by default.
+
+2013-05-10 12:25:07 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Redesign video size change reconfiguration code
+         Ensure stop the decoder before clossing the tunnel.
+
+2013-05-06 16:25:27 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * Makefile.am:
+         Makefile.am: Add -I common/m4
+         This allows autoreconf to work correctly and automatic regeneration
+         of autotools files if something changed.
+
+2013-05-06 19:03:59 +0530  jitendra <jvarshney20@gmail.com>
+
+       * omx/gstomx.c:
+       * omx/gstomx.h:
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: Add pads based on element type
+         This allows to later add sources and sink that only have a srcpad
+         or sinkpad.
+         https://bugzilla.gnome.org/show_bug.cgi?id=699754
+
+2013-04-27 02:50:25 +0200  Carlos Rafael Giani <dv@pseudoterminal.org>
+
+       * omx/gstomx.c:
+         omx: fixed type error in printf call
+         %zu expects size_t
+         https://bugzilla.gnome.org/show_bug.cgi?id=699008
+
+2013-04-08 17:26:16 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+       * omx/Makefile.am:
+       * omx/gstomxvideodec.c:
+         Check for gstreamer-egl
+         And don't use if not available.
+         https://bugzilla.gnome.org/show_bug.cgi?id=697574
+
+2013-04-23 09:53:18 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * configure.ac:
+         configure: error out if no OMX target has been set explicitly with --with-omx-target=x
+         Avoids people building for e.g. the Raspberry Pi and then wondering
+         why things don't work as expected (since structs are packed differently
+         there).
+
+2013-04-22 23:55:03 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * common:
+         Automatic update of common submodule
+         From 3cb3d3c to 5edcd85
+
+2013-04-18 22:07:28 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * omx/gstomx.c:
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxh263enc.c:
+       * omx/gstomxh264enc.c:
+       * omx/gstomxmpeg4videoenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: more printf format fixes
+         Fix printf formats again, so that gst-omx compiles warning-
+         free on the Raspberry Pi as well. Unfortunately OMX_UINT32
+         maybe be typedefed to uint32_t or unsigned long, which
+         doesn't work well with our debugging printf format strings,
+         so just use %u for those and cast to guint.
+
+2013-04-18 16:40:06 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomx.c:
+         omx: fixes unused variable 'comp' when GStreamer is built without debug
+
+2013-04-18 16:03:56 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: don't use 'self->dec_out_port' anymore and use just 'port'
+         Fixes some criticals.
+
+2013-04-18 15:21:32 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: fixes 'port' may be used uninitialized in this function
+
+2013-04-18 12:03:31 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: silence warnings building for RPI related to 'vcos_*'
+
+2013-04-18 11:19:52 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Use new type from libgstvideo
+
+2013-04-16 14:50:49 +0530  jitendra <jvarshney20@gmail.com>
+
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: Disable output port before transition to idle state
+         https://bugzilla.gnome.org/show_bug.cgi?id=698109
+
+2012-10-24 12:19:41 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * configure.ac:
+         gst: Add better support for static plugins
+
+2013-04-14 17:57:34 +0100  Tim-Philipp Müller <tim@centricular.net>
+
+       * common:
+         Automatic update of common submodule
+         From aed87ae to 3cb3d3c
+
+2013-04-12 17:58:30 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+         configure: add --disable-fatal-warnings for disabling -Werror
+
+2013-04-09 21:02:09 +0200  Stefan Sauer <ensonic@users.sf.net>
+
+       * common:
+         Automatic update of common submodule
+         From 04c7a1e to aed87ae
+
+2013-04-08 17:02:32 +0100  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * omx/gstomx.c:
+       * omx/gstomxaudioenc.c:
+       * omx/gstomxh263enc.c:
+       * omx/gstomxh264enc.c:
+       * omx/gstomxmpeg4videoenc.c:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideoenc.c:
+         omx: fix printf formats in debug messages
+         OMX_U32 is typedefed to an unsigned long,
+         OMX_TICKS to a 64-bit integer.
+
+2013-04-08 16:52:19 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: use the correct printf format in a debug message
+
+2013-04-08 16:31:33 +0200  Josep Torra <n770galaxy@gmail.com>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: use the correct OMX_IndexParam value
+         Fixes playback is not smooth in the EGL path.
+
+2013-04-05 13:45:24 +0200  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * omx/gstomxvideodec.c:
+         omxvideodec: Don't use API that is not in master yet
+         It's not really needed here yet, will be needed in future versions
+
+2013-02-25 11:55:04 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
+       * configure.ac:
+       * omx/Makefile.am:
+       * omx/gstomx.c:
+       * omx/gstomx.h:
+       * omx/gstomxvideodec.c:
+       * omx/gstomxvideodec.h:
+         omxvideodec: Add support for egl_render on RPi
+
+2013-03-22 19:26:54 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * configure.ac:
+         Back to development
+
+2013-03-22 19:23:14 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
+
+       * omx/gstomxh263enc.c:
+       * omx/gstomxh264enc.c:
+       * omx/gstomxmpeg4videoenc.c:
+         omx: fix compiler warnings when compiling with -DG_DISABLE_ASSERT
+         As we do for releases. Fixes 'variable may be used uninitialized'
+         warnings.
+
 === release 1.0.0 ===
 
-2013-03-22  Sebastian Dröge <sebastian.droege@collabora.co.uk>
+2013-03-22 17:16:33 +0100  Sebastian Dröge <sebastian.droege@collabora.co.uk>
 
+       * AUTHORS:
+       * ChangeLog:
+       * Makefile.am:
+       * NEWS:
+       * RELEASE:
        * configure.ac:
-         releasing 1.0.0
+       * gst-omx.doap:
+         Release 1.0.0
 
 2013-03-19 16:40:09 +0000  Tim-Philipp Müller <tim.muller@collabora.co.uk>
 
diff --git a/INSTALL b/INSTALL
deleted file mode 100644 (file)
index 7d1c323..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,365 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-
-   Copying and distribution of this file, with or without modification,
-are permitted in any medium without royalty provided the copyright
-notice and this notice are preserved.  This file is offered as-is,
-without warranty of any kind.
-
-Basic Installation
-==================
-
-   Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package.  The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.  Some packages provide this
-`INSTALL' file but do not implement all of the features documented
-below.  The lack of an optional feature in a given package is not
-necessarily a bug.  More recommendations for GNU packages can be found
-in *note Makefile Conventions: (standards)Makefile Conventions.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-   The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.
-
-     Running `configure' might take a while.  While running, it prints
-     some messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package, generally using the just-built uninstalled binaries.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.  When installing into a prefix owned by root, it is
-     recommended that the package be configured and built as a regular
-     user, and only the `make install' phase executed with root
-     privileges.
-
-  5. Optionally, type `make installcheck' to repeat any self-tests, but
-     this time using the binaries in their final installed location.
-     This target does not install anything.  Running this target as a
-     regular user, particularly if the prior `make install' required
-     root privileges, verifies that the installation completed
-     correctly.
-
-  6. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-  7. Often, you can also type `make uninstall' to remove the installed
-     files again.  In practice, not all packages have tested that
-     uninstallation works correctly, even though it is required by the
-     GNU Coding Standards.
-
-  8. Some packages, particularly those that use Automake, provide `make
-     distcheck', which can by used by developers to test that all other
-     targets like `make install' and `make uninstall' work correctly.
-     This target is generally not run by end users.
-
-Compilers and Options
-=====================
-
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-   You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you can use GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.  This
-is known as a "VPATH" build.
-
-   With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory.  After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-   On MacOS X 10.5 and later systems, you can create libraries and
-executables that work on multiple system types--known as "fat" or
-"universal" binaries--by specifying multiple `-arch' options to the
-compiler but only a single `-arch' option to the preprocessor.  Like
-this:
-
-     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
-                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
-                 CPP="gcc -E" CXXCPP="g++ -E"
-
-   This is not guaranteed to produce working output in all cases, you
-may have to build one architecture at a time and combine the results
-using the `lipo' tool if you have problems.
-
-Installation Names
-==================
-
-   By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc.  You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX', where PREFIX must be an
-absolute file name.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.  In general, the
-default for these options is expressed in terms of `${prefix}', so that
-specifying just `--prefix' will affect all of the other directory
-specifications that were not explicitly provided.
-
-   The most portable way to affect installation locations is to pass the
-correct locations to `configure'; however, many packages provide one or
-both of the following shortcuts of passing variable assignments to the
-`make install' command line to change installation locations without
-having to reconfigure or recompile.
-
-   The first method involves providing an override variable for each
-affected directory.  For example, `make install
-prefix=/alternate/directory' will choose an alternate location for all
-directory configuration variables that were expressed in terms of
-`${prefix}'.  Any directories that were specified during `configure',
-but not in terms of `${prefix}', must each be overridden at install
-time for the entire installation to be relocated.  The approach of
-makefile variable overrides for each directory variable is required by
-the GNU Coding Standards, and ideally causes no recompilation.
-However, some platforms have known limitations with the semantics of
-shared libraries that end up requiring recompilation when using this
-method, particularly noticeable in packages that use GNU Libtool.
-
-   The second method involves providing the `DESTDIR' variable.  For
-example, `make install DESTDIR=/alternate/directory' will prepend
-`/alternate/directory' before all installation names.  The approach of
-`DESTDIR' overrides is not required by the GNU Coding Standards, and
-does not work on platforms that have drive letters.  On the other hand,
-it does better at avoiding recompilation issues, and works well even
-when some directory options were not specified in terms of `${prefix}'
-at `configure' time.
-
-Optional Features
-=================
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-   Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-   Some packages offer the ability to configure how verbose the
-execution of `make' will be.  For these packages, running `./configure
---enable-silent-rules' sets the default to minimal output, which can be
-overridden with `make V=1'; while running `./configure
---disable-silent-rules' sets the default to verbose, which can be
-overridden with `make V=0'.
-
-Particular systems
-==================
-
-   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
-CC is not installed, it is recommended to use the following options in
-order to use an ANSI C compiler:
-
-     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
-
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
-
-   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
-parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
-a workaround.  If GNU CC is not installed, it is therefore recommended
-to try
-
-     ./configure CC="cc"
-
-and if that doesn't work, try
-
-     ./configure CC="cc -nodtk"
-
-   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
-directory contains several dysfunctional programs; working variants of
-these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
-in your `PATH', put it _after_ `/usr/bin'.
-
-   On Haiku, software installed for all users goes in `/boot/common',
-not `/usr/local'.  It is recommended to use the following options:
-
-     ./configure --prefix=/boot/common
-
-Specifying the System Type
-==========================
-
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS
-     KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-   Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug.  Until the bug is fixed you can use this workaround:
-
-     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-   `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
-     Print a summary of all of the options to `configure', and exit.
-
-`--help=short'
-`--help=recursive'
-     Print a summary of the options unique to this package's
-     `configure', and exit.  The `short' variant lists options used
-     only in the top level, while the `recursive' variant lists options
-     also present in any nested packages.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`--prefix=DIR'
-     Use DIR as the installation prefix.  *note Installation Names::
-     for more details, including other options available for fine-tuning
-     the installation locations.
-
-`--no-create'
-`-n'
-     Run the configure checks, but stop before creating any output
-     files.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
index 424630a..fd79a40 100644 (file)
@@ -1,6 +1,10 @@
-SUBDIRS = common omx tools config
+SUBDIRS = common omx tools config 
 
-ACLOCAL_AMFLAGS = -I m4
+if BUILD_EXAMPLES
+SUBDIRS += examples
+endif
+
+ACLOCAL_AMFLAGS = -I m4 -I common/m4
 
 DISTCLEANFILES = _stdint.h
 
diff --git a/NEWS b/NEWS
index cffbaae..41a6e0a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1 +1 @@
-This is gst-omx 1.0.0
+This is gst-omx 1.2.0
diff --git a/RELEASE b/RELEASE
index b304649..50d7090 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,15 +1,9 @@
 
-Release notes for GStreamer OpenMAX IL wrapper plugin 1.0.0
-
-The GStreamer team is proud to announce a new feature release
-in the 1.x stable series of the GStreamer OpenMAX IL
-wrapper plugin.
-
-
-The 1.x series is a stable series targeted at end users.
-It is not API or ABI compatible with the stable 0.10.x series.
-It is, however, parallel installable with the 0.10.x series and
-will not affect an existing 0.10.x installation.
+Release notes for GStreamer OpenMAX IL wrapper plugin 1.2.0
+    
+The GStreamer project is proud to announce a new release of the
+GStreamer OpenMAX IL wrapper plugin for the API and ABI-stable
+1.x series of the GStreamer multimedia framework.
 
 
 
@@ -40,13 +34,53 @@ contains a set of less supported plugins that haven't passed the
 
 Features of this release
     
-      * Parallel installability with 0.10.x series
       * Generic support for OpenMAX IL implementations
-      * Special support for features of: Raspberry Pi
+      * Support for audio decoders
+      * Support for raw and encoded audio sink
+      * Improved support for the Raspberry Pi
+      * Many bugfixes to work properly with AMD's, NVIDIA's, Qualcomm's and other OpenMAX IL implementations
 
 Bugs fixed in this release
      
-      * 692446 : Add mpeg2 support
+      * 697574 : Only use EGL code paths conditionally if gstreamer-egl is available
+      * 698049 : omxh264enc: openmax API ignores output bitrate
+      * 698109 : Disable output port before transition to idle state
+      * 699008 : Fix printf format compiler warning
+      * 699754 : Don't force elements of type source/sink  to add two pads
+      * 701706 : gst-omx testegl.c example not compatible with gstreamer 1.x
+      * 710564 : Need to convert OMX alignments to GStreamer alignments
+      * 710948 : omxvideodec: Doesn't recover after aspect ratio changes
+      * 720031 : omxh264enc:  key frame interval missing
+      * 723176 : omx: Examples need to be ported to 1.0
+      * 723386 : Bad port index playing VC-1 WMV in Raspberry Pi
+      * 723851 : omxvideoenc/dec: Fix for a startup race condition
+      * 724236 : omx: Enhancements/cleanup for decoder/encoder frame handling
+      * 725468 : Fix two serious message handling bugs
+      * 725493 : Consolidate message waiting code
+      * 725826 : omxvideoenc: Fix a minor memory leak in gst_omx_video_enc_getcaps
+      * 725907 : omxvideodec: Two more minor fixes for memory leaks
+      * 726021 : Simplify tunnel functions
+      * 726024 : Share more code between video decoder and  encoder
+      * 726025 : omxvideodec: separate the buffer pool from the decoder
+      * 726038 : omxvideodec: Multiple issues during seeks
+      * 726107 : omxvideodec: Drain pipeline to support adaptive streaming scenarios and partially fix gpu resource leaks
+      * 726337 : omxbufferpool: leak buffers when stopped
+      * 726669 : omxh264enc: Properly accumulate headers and provide them to the base class
+      * 726957 : Add configure option for external omxil headers
+      * 726958 : omxvideodec: add missing unlock in the error path
+      * 727825 : omxvideodec: Enhance colorformat support
+      * 728322 : omvideodec: don't unref caps before logging field from it
+      * 728774 : omxvp8dec: fix typo in GST_TYPE_OMX_VP8_DEC define
+      * 728940 : gst-omx: port testegl example to new libgstgl
+      * 728962 : Add audiosink elements to support raw and ac3/dts passthrough on the RPI
+      * 729196 : omxvideodec: no memory:EGLImage feature in the caps when using eglimage allocator
+      * 730989 : omxdec: Get stuck while doing ctrl+c during preroll
+      * 730995 : omxvideodec: Memory leak with interlaced h264 streams
+      * 731141 : Fix a missing g_free() in error path
+      * 731672 : omxvideodec: uses non-standard stride without videometa
+      * 731898 : omxvideodec: fix a query leak
+      * 732518 : Link with gmodule-2.0-no-export for g_module_*() API
+      * 733168 : omxaudiosink: Does not set ports to non-flushing after prepare
 
 ==== Download ====
 
@@ -83,20 +117,19 @@ subscribe to the gstreamer-devel list.
         
 Contributors to this release
     
-      * Alessandro Decina
-      * Arun Raghavan
-      * Dake Gu
+      * Aurélien Zanelli
+      * Carlos Rafael Giani
+      * Christian König
       * Edward Hervey
-      * George Kiagiadakis
-      * Jonas Larsson
+      * Ilya Smelykh
       * Josep Torra
-      * Julian Scheel
-      * Matej Knopp
-      * Nicolas Dufresne
-      * Olivier Crête
-      * Reynaldo H. Verdejo Pinochet
+      * Julien Isorce
+      * Kazunori Kobayashi
+      * Michal Lazo
+      * Roman Arutyunyan
       * Sebastian Dröge
       * Stefan Sauer
       * Tim-Philipp Müller
-      * Vincent Penquerc'h
+      * Zhao, Halley
+      * jitendra
 Â 
\ No newline at end of file
diff --git a/common b/common
deleted file mode 160000 (submodule)
index 04c7a1e..0000000
--- a/common
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 04c7a1ec1b9ced0b4359b3bbb2d8dc87bc7642c8
diff --git a/common/Makefile.am b/common/Makefile.am
new file mode 100644 (file)
index 0000000..25966fc
--- /dev/null
@@ -0,0 +1,22 @@
+SUBDIRS = m4
+
+EXTRA_DIST = \
+       ChangeLog \
+       gettext.patch \
+       glib-gen.mak gtk-doc.mak upload-doc.mak \
+       cruft.mak release.mak win32.mak po.mak \
+       parallel-subdirs.mak \
+       gst-autogen.sh \
+       check-exports \
+       c-to-xml.py mangle-tmpl.py scangobj-merge.py \
+       gtk-doc-plugins.mak \
+       plugins.xsl gstdoc-scangobj \
+       gst.supp check.mak \
+       coverage/lcov.mak \
+       coverage/coverage-report.pl \
+       coverage/coverage-report.xsl \
+       coverage/coverage-report-entry.pl \
+       download-translations \
+       extract-release-date-from-doap-file \
+       gst-indent \
+       orc.mak
diff --git a/common/extract-release-date-from-doap-file b/common/extract-release-date-from-doap-file
new file mode 100644 (file)
index 0000000..f57e307
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Shell script to extract the date given a release version and a .doap file
+
+if test "x$1" = "x" -o "x$2" = "x" -o ! -s "$2"; then
+  echo "Usage: $0 RELEASE-VERSION-NUMBER DOAP-FILE" >&2;
+  exit 1
+fi
+
+if ! grep '<Project' "$2" >/dev/null ; then
+  echo "$2 does not look lika a .doap file" >&2;
+  exit 1
+fi
+
+if ! grep "$1" "$2" >/dev/null ; then
+  echo "$2 contains no reference to a version $1" >&2;
+  exit 1
+fi
+
+awk 'BEGIN {x=0}
+{
+if ( $0 ~ /<release>/ ) {x=1; chunk=""}
+if (x==1) {
+  if ($0 ~ /<revision>/) { chunk = chunk $0 }
+  if ($0 ~ /<created>/) { chunk = chunk $0 }
+}
+if ($0 ~ /<\/release>/) {x=0; print chunk}
+}' < "$2" | \
+\
+grep '<revision>'"$1"'</revision>' | \
+\
+sed -e 's/^.*<created>//' -e 's/<\/created>.*$//'
+
diff --git a/common/gst-autogen.sh b/common/gst-autogen.sh
new file mode 100644 (file)
index 0000000..78cab66
--- /dev/null
@@ -0,0 +1,345 @@
+# a silly hack that generates autoregen.sh but it's handy
+# Remove the old autoregen.sh first to create a new file,
+# as the current one may be being read by the shell executing
+# this script.
+if [ -f "autoregen.sh" ]; then
+  rm autoregen.sh
+fi
+echo "#!/bin/sh" > autoregen.sh
+echo "./autogen.sh $@ \$@" >> autoregen.sh
+chmod +x autoregen.sh
+
+# helper functions for autogen.sh
+
+debug ()
+# print out a debug message if DEBUG is a defined variable
+{
+  if test ! -z "$DEBUG"
+  then
+    echo "DEBUG: $1"
+  fi
+}
+
+version_get ()
+# based on the command's version output, set variables
+# _MAJOR, _MINOR, _MICRO, _VERSION, using the given prefix as variable prefix
+#
+# arg 1: command binary name
+# arg 2: (uppercased) variable name prefix
+{
+  COMMAND=$1
+  VARPREFIX=`echo $2 | tr .,- _`
+  local ${VARPREFIX}_VERSION
+
+  # strip everything that's not a digit, then use cut to get the first field
+  pkg_version=`$COMMAND --version|head -n 1|sed 's/^.*)[^0-9]*//'|cut -d' ' -f1`
+  debug "pkg_version $pkg_version"
+  # remove any non-digit characters from the version numbers to permit numeric
+  # comparison
+  pkg_major=`echo $pkg_version | cut -d. -f1 | sed s/[a-zA-Z\-].*//g`
+  pkg_minor=`echo $pkg_version | cut -d. -f2 | sed s/[a-zA-Z\-].*//g`
+  pkg_micro=`echo $pkg_version | cut -d. -f3 | sed s/[a-zA-Z\-].*//g`
+  test -z "$pkg_major" && pkg_major=0
+  test -z "$pkg_minor" && pkg_minor=0
+  test -z "$pkg_micro" && pkg_micro=0
+  debug "found major $pkg_major minor $pkg_minor micro $pkg_micro"
+  eval ${VARPREFIX}_MAJOR=$pkg_major
+  eval ${VARPREFIX}_MINOR=$pkg_minor
+  eval ${VARPREFIX}_MICRO=$pkg_micro
+  eval ${VARPREFIX}_VERSION=$pkg_version
+}
+
+version_compare ()
+# Checks whether the version of VARPREFIX is equal to or
+# newer than the requested version
+# arg1: VARPREFIX
+# arg2: MAJOR
+# arg3: MINOR
+# arg4: MICRO
+{
+  VARPREFIX=`echo $1 | tr .,- _`
+  MAJOR=$2
+  MINOR=$3
+  MICRO=$4
+
+  eval pkg_major=\$${VARPREFIX}_MAJOR;
+  eval pkg_minor=\$${VARPREFIX}_MINOR;
+  eval pkg_micro=\$${VARPREFIX}_MICRO;
+
+  #start checking the version
+  debug "version_compare: $VARPREFIX against $MAJOR.$MINOR.$MICRO"
+
+    # reset check
+    WRONG=
+
+    if [ ! "$pkg_major" -gt "$MAJOR" ]; then
+      debug "major: $pkg_major <= $MAJOR"
+      if [ "$pkg_major" -lt "$MAJOR" ]; then
+        debug "major: $pkg_major < $MAJOR"
+        WRONG=1
+      elif [ ! "$pkg_minor" -gt "$MINOR" ]; then
+        debug "minor: $pkg_minor <= $MINOR"
+        if [ "$pkg_minor" -lt "$MINOR" ]; then
+          debug "minor: $pkg_minor < $MINOR"
+          WRONG=1
+        elif [ "$pkg_micro" -lt "$MICRO" ]; then
+          debug "micro: $pkg_micro < $MICRO"
+         WRONG=1
+        fi
+      fi
+    fi
+    if test ! -z "$WRONG"; then
+      debug "version_compare: $VARPREFIX older than $MAJOR.$MINOR.$MICRO"
+      return 1
+    fi
+    debug "version_compare: $VARPREFIX equal to/newer than $MAJOR.$MINOR.$MICRO"
+    return 0
+}
+
+
+version_check ()
+# check the version of a package
+# first argument : package name (executable)
+# second argument : optional path where to look for it instead
+# third argument : source download url
+# rest of arguments : major, minor, micro version
+# all consecutive ones : suggestions for binaries to use
+# (if not specified in second argument)
+{
+  PACKAGE=$1
+  PKG_PATH=$2
+  URL=$3
+  MAJOR=$4
+  MINOR=$5
+  MICRO=$6
+
+  # for backwards compatibility, we let PKG_PATH=PACKAGE when PKG_PATH null
+  if test -z "$PKG_PATH"; then PKG_PATH=$PACKAGE; fi
+  debug "major $MAJOR minor $MINOR micro $MICRO"
+  VERSION=$MAJOR
+  if test ! -z "$MINOR"; then VERSION=$VERSION.$MINOR; else MINOR=0; fi
+  if test ! -z "$MICRO"; then VERSION=$VERSION.$MICRO; else MICRO=0; fi
+
+  debug "major $MAJOR minor $MINOR micro $MICRO"
+
+  for SUGGESTION in $PKG_PATH; do
+    COMMAND="$SUGGESTION"
+
+    # don't check if asked not to
+    test -z "$NOCHECK" && {
+      printf "  checking for $COMMAND >= $VERSION ... "
+    } || {
+      # we set a var with the same name as the package, but stripped of
+      # unwanted chars
+      VAR=`echo $PACKAGE | sed 's/-//g'`
+      debug "setting $VAR"
+      eval $VAR="$COMMAND"
+      return 0
+    }
+
+    which $COMMAND > /dev/null 2>&1
+    if test $? -eq 1;
+    then 
+      debug "$COMMAND not found"
+      continue
+    fi
+
+    VARPREFIX=`echo $COMMAND | sed 's/-//g' | tr [:lower:] [:upper:]`
+    version_get $COMMAND $VARPREFIX
+
+    version_compare $VARPREFIX $MAJOR $MINOR $MICRO
+    if test $? -ne 0; then
+      echo "found $pkg_version, not ok !"
+      continue
+    else
+      echo "found $pkg_version, ok."
+      # we set a var with the same name as the package, but stripped of
+      # unwanted chars
+      VAR=`echo $PACKAGE | sed 's/-//g'`
+      debug "setting $VAR"
+      eval $VAR="$COMMAND"
+      return 0
+    fi
+  done
+
+  echo "$PACKAGE not found !"
+  echo "You must have $PACKAGE installed to compile $package."
+  echo "Download the appropriate package for your distribution,"
+  echo "or get the source tarball at $URL"
+  return 1;
+}
+
+aclocal_check ()
+{
+  # normally aclocal is part of automake
+  # so we expect it to be in the same place as automake
+  # so if a different automake is supplied, we need to adapt as well
+  # so how's about replacing automake with aclocal in the set var,
+  # and saving that in $aclocal ?
+  # note, this will fail if the actual automake isn't called automake*
+  # or if part of the path before it contains it
+  if [ -z "$automake" ]; then
+    echo "Error: no automake variable set !"
+    return 1
+  else
+    aclocal=`echo $automake | sed s/automake/aclocal/`
+    debug "aclocal: $aclocal"
+    if [ "$aclocal" != "aclocal" ];
+    then
+      CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal"
+    fi
+    if [ ! -x `which $aclocal` ]; then
+      echo "Error: cannot execute $aclocal !"
+      return 1
+    fi
+  fi
+}
+
+autoheader_check ()
+{
+  # same here - autoheader is part of autoconf
+  # use the same voodoo
+  if [ -z "$autoconf" ]; then
+    echo "Error: no autoconf variable set !"
+    return 1
+  else
+    autoheader=`echo $autoconf | sed s/autoconf/autoheader/`
+    debug "autoheader: $autoheader"
+    if [ "$autoheader" != "autoheader" ];
+    then
+      CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader"
+    fi
+    if [ ! -x `which $autoheader` ]; then
+      echo "Error: cannot execute $autoheader !"
+      return 1
+    fi
+  fi
+
+}
+
+die_check ()
+{
+  # call with $DIE
+  # if set to 1, we need to print something helpful then die
+  DIE=$1
+  if test "x$DIE" = "x1";
+  then
+    echo
+    echo "- Please get the right tools before proceeding."
+    echo "- Alternatively, if you're sure we're wrong, run with --nocheck."
+    exit 1
+  fi
+}
+
+autogen_options ()
+{
+  if test "x$1" = "x"; then
+    return 0
+  fi
+
+  while test "x$1" != "x" ; do
+    optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    case "$1" in
+      --noconfigure)
+          NOCONFIGURE=defined
+         AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --noconfigure"
+          echo "+ configure run disabled"
+          shift
+          ;;
+      --nocheck)
+         AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --nocheck"
+          NOCHECK=defined
+          echo "+ autotools version check disabled"
+          shift
+          ;;
+      -d|--debug)
+          DEBUG=defined
+         AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --debug"
+          echo "+ debug output enabled"
+          shift
+          ;;
+      -h|--help)
+          echo "autogen.sh (autogen options) -- (configure options)"
+          echo "autogen.sh help options: "
+          echo " --noconfigure            don't run the configure script"
+          echo " --nocheck                don't do version checks"
+          echo " --debug                  debug the autogen process"
+          echo
+          echo " --with-autoconf PATH     use autoconf in PATH"
+          echo " --with-automake PATH     use automake in PATH"
+          echo
+          echo "Any argument either not in the above list or after a '--' will be "
+          echo "passed to ./configure."
+         exit 1
+          ;;
+      --with-automake=*)
+          AUTOMAKE=$optarg
+          echo "+ using alternate automake in $optarg"
+         CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-automake=$AUTOMAKE"
+          shift
+          ;;
+      --with-autoconf=*)
+          AUTOCONF=$optarg
+          echo "+ using alternate autoconf in $optarg"
+         CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoconf=$AUTOCONF"
+          shift
+          ;;
+      --) shift ; break ;;
+      *)
+          echo "+ passing argument $1 to configure"
+         CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $1"
+          shift
+          ;;
+    esac
+  done
+
+  for arg do CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $arg"; done
+  if test ! -z "$CONFIGURE_EXT_OPT"
+  then
+    echo "+ options passed to configure: $CONFIGURE_EXT_OPT"
+  fi
+}
+
+toplevel_check ()
+{
+  srcfile=$1
+  test -f $srcfile || {
+        echo "You must run this script in the top-level $package directory"
+        exit 1
+  }
+}
+
+tool_run ()
+{
+  tool=$1
+  options=$2
+  run_if_fail=$3
+  echo "+ running $tool $options..."
+  $tool $options || {
+    echo
+    echo $tool failed
+    eval $run_if_fail
+    exit 1
+  }
+}
+
+install_git_hooks ()
+{
+  if test -d .git; then
+    # install pre-commit hook for doing clean commits
+    for hook in pre-commit; do
+      if test ! \( -x .git/hooks/$hook -a -L .git/hooks/$hook \); then
+        echo "+ Installing git $hook hook"
+        rm -f .git/hooks/$hook
+        ln -s ../../common/hooks/$hook.hook .git/hooks/$hook || {
+          # if we couldn't create a symbolic link, try doing a plain cp
+          if cp common/hooks/pre-commit.hook .git/hooks/pre-commit; then
+            chmod +x .git/hooks/pre-commit;
+          else
+            echo "********** Couldn't install git $hook hook **********";
+          fi
+        }
+      fi
+    done
+  fi
+}
diff --git a/common/m4/Makefile.am b/common/m4/Makefile.am
new file mode 100644 (file)
index 0000000..3d387ee
--- /dev/null
@@ -0,0 +1,40 @@
+EXTRA_DIST = \
+       README \
+       as-ac-expand.m4 \
+       as-auto-alt.m4 \
+       as-compiler-flag.m4 \
+       as-compiler.m4 \
+       as-docbook.m4 \
+       as-gcc-inline-assembly.m4 \
+       as-libtool.m4 \
+       as-libtool-tags.m4 \
+       as-python.m4 \
+       as-version.m4 \
+       ax_create_stdint_h.m4 \
+       glib-gettext.m4 \
+       gst-arch.m4 \
+       gst-args.m4 \
+       gst-check.m4 \
+       gst-debuginfo.m4 \
+       gst-default.m4 \
+       gst-doc.m4 \
+       gst-dowhile.m4 \
+       gst-error.m4 \
+       gst-feature.m4 \
+       gst-function.m4 \
+       gst-gettext.m4 \
+       gst-glib2.m4 \
+       gst-libxml2.m4 \
+       gst-parser.m4 \
+       gst-package-release-datetime.m4 \
+       gst-platform.m4 \
+       gst-plugindir.m4 \
+       gst-plugin-docs.m4 \
+       gst-valgrind.m4 \
+       gst-x11.m4 \
+       gst.m4 \
+       gtk-doc.m4 \
+       introspection.m4 \
+       pkg.m4 \
+       check.m4 \
+       orc.m4
diff --git a/common/m4/README b/common/m4/README
new file mode 100644 (file)
index 0000000..867a344
--- /dev/null
@@ -0,0 +1,3 @@
+All aclocal .m4 files we need are put here and cat'd to acinclude.m4 in
+the source root.  Official ones (taken from the relevant devel packages)
+are named as-is, unofficial ones (or changed ones) get a gst-prefix.
diff --git a/common/m4/as-ac-expand.m4 b/common/m4/as-ac-expand.m4
new file mode 100644 (file)
index 0000000..d6c9e33
--- /dev/null
@@ -0,0 +1,43 @@
+dnl as-ac-expand.m4 0.2.0
+dnl autostars m4 macro for expanding directories using configure's prefix
+dnl thomas@apestaart.org
+
+dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
+dnl example
+dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
+dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
+
+AC_DEFUN([AS_AC_EXPAND],
+[
+  EXP_VAR=[$1]
+  FROM_VAR=[$2]
+
+  dnl first expand prefix and exec_prefix if necessary
+  prefix_save=$prefix
+  exec_prefix_save=$exec_prefix
+
+  dnl if no prefix given, then use /usr/local, the default prefix
+  if test "x$prefix" = "xNONE"; then
+    prefix="$ac_default_prefix"
+  fi
+  dnl if no exec_prefix given, then use prefix
+  if test "x$exec_prefix" = "xNONE"; then
+    exec_prefix=$prefix
+  fi
+
+  full_var="$FROM_VAR"
+  dnl loop until it doesn't change anymore
+  while true; do
+    new_full_var="`eval echo $full_var`"
+    if test "x$new_full_var" = "x$full_var"; then break; fi
+    full_var=$new_full_var
+  done
+
+  dnl clean up
+  full_var=$new_full_var
+  AC_SUBST([$1], "$full_var")
+
+  dnl restore prefix and exec_prefix
+  prefix=$prefix_save
+  exec_prefix=$exec_prefix_save
+])
diff --git a/common/m4/as-auto-alt.m4 b/common/m4/as-auto-alt.m4
new file mode 100644 (file)
index 0000000..3f7920d
--- /dev/null
@@ -0,0 +1,50 @@
+dnl as-auto-alt.m4 0.0.2
+dnl autostars m4 macro for supplying alternate autotools versions to configure
+dnl thomas@apestaart.org
+dnl
+dnl AS_AUTOTOOLS_ALTERNATE()
+dnl
+dnl supplies --with arguments for autoconf, autoheader, automake, aclocal
+
+AC_DEFUN([AS_AUTOTOOLS_ALTERNATE],
+[
+  dnl allow for different autoconf version
+  AC_ARG_WITH(autoconf,
+    AC_HELP_STRING([--with-autoconf],
+                   [use a different autoconf for regeneration of Makefiles]),
+    [
+      unset AUTOCONF
+      AM_MISSING_PROG(AUTOCONF, ${withval})
+      AC_MSG_NOTICE([Using $AUTOCONF as autoconf])
+    ])
+
+  dnl allow for different autoheader version
+  AC_ARG_WITH(autoheader,
+    AC_HELP_STRING([--with-autoheader],
+                   [use a different autoheader for regeneration of Makefiles]),
+    [
+      unset AUTOHEADER
+      AM_MISSING_PROG(AUTOHEADER, ${withval})
+      AC_MSG_NOTICE([Using $AUTOHEADER as autoheader])
+    ])
+
+  dnl allow for different automake version
+  AC_ARG_WITH(automake,
+    AC_HELP_STRING([--with-automake],
+                   [use a different automake for regeneration of Makefiles]),
+    [
+      unset AUTOMAKE
+      AM_MISSING_PROG(AUTOMAKE, ${withval})
+      AC_MSG_NOTICE([Using $AUTOMAKE as automake])
+    ])
+
+  dnl allow for different aclocal version
+  AC_ARG_WITH(aclocal,
+    AC_HELP_STRING([--with-aclocal],
+                   [use a different aclocal for regeneration of Makefiles]),
+    [
+      unset ACLOCAL
+      AM_MISSING_PROG(ACLOCAL, ${withval})
+      AC_MSG_NOTICE([Using $ACLOCAL as aclocal])
+    ])
+])
diff --git a/common/m4/as-compiler-flag.m4 b/common/m4/as-compiler-flag.m4
new file mode 100644 (file)
index 0000000..8bb853a
--- /dev/null
@@ -0,0 +1,96 @@
+dnl as-compiler-flag.m4 0.1.0
+
+dnl autostars m4 macro for detection of compiler flags
+
+dnl David Schleef <ds@schleef.org>
+dnl Tim-Philipp Müller <tim centricular net>
+
+dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_COMPILER_FLAG],
+[
+  AC_MSG_CHECKING([to see if compiler understands $1])
+
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $1"
+
+  AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+  CFLAGS="$save_CFLAGS"
+
+  if test "X$flag_ok" = Xyes ; then
+    $2
+    true
+  else
+    $3
+    true
+  fi
+  AC_MSG_RESULT([$flag_ok])
+])
+
+dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CPPFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_CXX_COMPILER_FLAG],
+[
+  AC_REQUIRE([AC_PROG_CXX])
+
+  AC_MSG_CHECKING([to see if c++ compiler understands $1])
+
+  save_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $1"
+
+  AC_LANG_PUSH(C++)
+
+  AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+  CPPFLAGS="$save_CPPFLAGS"
+
+  if test "X$flag_ok" = Xyes ; then
+    $2
+    true
+  else
+    $3
+    true
+  fi
+
+  AC_LANG_POP(C++)
+
+  AC_MSG_RESULT([$flag_ok])
+])
+
+dnl AS_OBJC_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CPPFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_OBJC_COMPILER_FLAG],
+[
+  AC_REQUIRE([AC_PROG_OBJC])
+
+  AC_MSG_CHECKING([to see if Objective C compiler understands $1])
+
+  save_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $1"
+
+  AC_LANG_PUSH([Objective C])
+
+  AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+  CPPFLAGS="$save_CPPFLAGS"
+
+  if test "X$flag_ok" = Xyes ; then
+    $2
+    true
+  else
+    $3
+    true
+  fi
+
+  AC_LANG_POP([Objective C])
+
+  AC_MSG_RESULT([$flag_ok])
+])
+
diff --git a/common/m4/as-compiler.m4 b/common/m4/as-compiler.m4
new file mode 100644 (file)
index 0000000..309a060
--- /dev/null
@@ -0,0 +1,44 @@
+dnl as-compiler.m4 0.1.0
+
+dnl autostars m4 macro for detection of compiler flavor
+
+dnl Thomas Vander Stichele <thomas at apestaart dot org>
+
+dnl $Id: as-compiler.m4,v 1.4 2004/06/01 09:44:19 thomasvs Exp $
+
+dnl AS_COMPILER(COMPILER)
+dnl will set variable COMPILER to
+dnl - gcc
+dnl - forte
+dnl - (empty) if no guess could be made
+
+AC_DEFUN([AS_COMPILER],
+[
+  as_compiler=
+  AC_MSG_CHECKING(for compiler flavour)
+
+  dnl is it gcc ?
+  if test "x$GCC" = "xyes"; then
+    as_compiler="gcc"
+  fi
+
+  dnl is it forte ?
+  AC_TRY_RUN([
+int main
+(int argc, char *argv[])
+{
+#ifdef __sun
+  return 0;
+#else
+  return 1;
+#endif
+}
+  ], as_compiler="forte", ,)
+
+  if test "x$as_compiler" = "x"; then
+    AC_MSG_RESULT([unknown !])
+  else
+    AC_MSG_RESULT($as_compiler)
+  fi
+  [$1]=$as_compiler
+])
diff --git a/common/m4/as-docbook.m4 b/common/m4/as-docbook.m4
new file mode 100644 (file)
index 0000000..2e27050
--- /dev/null
@@ -0,0 +1,78 @@
+dnl AS_DOCBOOK([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl checks if xsltproc can build docbook documentation
+dnl (which is possible if the catalog is set up properly
+dnl I also tried checking for a specific version and type of docbook
+dnl but xsltproc seemed to happily run anyway, so we can't check for that
+dnl and version
+dnl this macro takes inspiration from
+dnl http://www.movement.uklinux.net/docs/docbook-autotools/configure.html
+AC_DEFUN([AS_DOCBOOK],
+[
+  XSLTPROC_FLAGS=--nonet
+  DOCBOOK_ROOT=
+  TYPE_LC=xml
+  TYPE_UC=XML
+  DOCBOOK_VERSION=4.1.2
+
+  if test -n "$XML_CATALOG_FILES"; then
+    oldIFS=$IFS
+    IFS=' '
+    for xml_catalog_file in $XML_CATALOG_FILES; do
+      if test -f $xml_catalog_file; then
+        XML_CATALOG=$xml_catalog_file
+        CAT_ENTRY_START='<!--'
+        CAT_ENTRY_END='-->'
+        break
+      fi
+    done
+    IFS=$oldIFS
+  elif test ! -f /etc/xml/catalog; then
+    for i in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh /usr/share/sgml/docbook/xsl-stylesheets/ /usr/local/share/xsl/docbook ;
+    do
+      if test -d "$i"; then
+        DOCBOOK_ROOT=$i
+      fi
+    done
+  else
+    XML_CATALOG=/etc/xml/catalog
+    CAT_ENTRY_START='<!--'
+    CAT_ENTRY_END='-->'
+  fi
+
+  dnl We need xsltproc to process the test
+  AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,)
+  XSLTPROC_WORKS=no
+  if test -n "$XSLTPROC"; then
+    AC_MSG_CHECKING([whether xsltproc docbook processing works])
+
+    if test -n "$XML_CATALOG"; then
+      DB_FILE="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
+    else
+      DB_FILE="$DOCBOOK_ROOT/xhtml/docbook.xsl"
+    fi
+    $XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook $TYPE_UC V$DOCBOOK_VERSION//EN" "http://www.oasis-open.org/docbook/$TYPE_LC/$DOCBOOK_VERSION/docbookx.dtd">
+<book id="test">
+</book>
+END
+    if test "$?" = 0; then
+      XSLTPROC_WORKS=yes
+    fi
+    AC_MSG_RESULT($XSLTPROC_WORKS)
+  fi
+
+  if test "x$XSLTPROC_WORKS" = "xyes"; then
+    dnl execute ACTION-IF-FOUND
+    ifelse([$1], , :, [$1])
+  else
+    dnl execute ACTION-IF-NOT-FOUND
+    ifelse([$2], , :, [$2])
+  fi
+
+  AC_SUBST(XML_CATALOG)
+  AC_SUBST(XSLTPROC_FLAGS)
+  AC_SUBST(DOCBOOK_ROOT)
+  AC_SUBST(CAT_ENTRY_START)
+  AC_SUBST(CAT_ENTRY_END)
+])
diff --git a/common/m4/as-gcc-inline-assembly.m4 b/common/m4/as-gcc-inline-assembly.m4
new file mode 100644 (file)
index 0000000..af32104
--- /dev/null
@@ -0,0 +1,52 @@
+dnl as-gcc-inline-assembly.m4 0.1.0
+
+dnl autostars m4 macro for detection of gcc inline assembly
+
+dnl David Schleef <ds@schleef.org>
+
+dnl $Id$
+
+dnl AS_COMPILER_FLAG(ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_GCC_INLINE_ASSEMBLY],
+[
+  AC_MSG_CHECKING([if compiler supports gcc-style inline assembly])
+
+  AC_TRY_COMPILE([], [
+#ifdef __GNUC_MINOR__
+#if (__GNUC__ * 1000 + __GNUC_MINOR__) < 3004
+#error GCC before 3.4 has critical bugs compiling inline assembly
+#endif
+#endif
+__asm__ (""::) ], [flag_ok=yes], [flag_ok=no])
+
+  if test "X$flag_ok" = Xyes ; then
+    $1
+    true
+  else
+    $2
+    true
+  fi
+  AC_MSG_RESULT([$flag_ok])
+])
+
+
+AC_DEFUN([AS_GCC_ASM_POWERPC_FPU],
+[
+  AC_MSG_CHECKING([if compiler supports FPU instructions on PowerPC])
+
+  AC_TRY_COMPILE([], [__asm__ ("fadd 0,0,0"::) ], [flag_ok=yes], [flag_ok=no])
+
+  if test "X$flag_ok" = Xyes ; then
+    $1
+    true
+  else
+    $2
+    true
+  fi
+  AC_MSG_RESULT([$flag_ok])
+])
+
diff --git a/common/m4/as-libtool-tags.m4 b/common/m4/as-libtool-tags.m4
new file mode 100644 (file)
index 0000000..06f0ae4
--- /dev/null
@@ -0,0 +1,83 @@
+dnl as-libtool-tags.m4 0.1.4
+
+dnl autostars m4 macro for selecting libtool "tags" (languages)
+
+dnl Andy Wingo does not claim credit for this macro
+dnl backported from libtool 1.6 by Paolo Bonzini
+dnl see http://lists.gnu.org/archive/html/libtool/2003-12/msg00007.html
+
+dnl $Id$
+
+dnl AS_LIBTOOL_TAGS([tags...])
+
+dnl example
+dnl AS_LIBTOOL_TAGS([]) for only C (no fortran, etc)
+
+dnl When AC_LIBTOOL_TAGS is used, I redefine _LT_AC_TAGCONFIG
+dnl to be more similar to the libtool 1.6 implementation, which
+dnl uses an m4 loop and m4 case instead of a shell loop.  This
+dnl way the CXX/GCJ/F77/RC tests are not always expanded.
+
+dnl AS_LIBTOOL_TAGS
+dnl ---------------
+dnl tags to enable
+AC_DEFUN([AS_LIBTOOL_TAGS],
+[m4_define([_LT_TAGS],[$1])
+m4_define([_LT_AC_TAGCONFIG], [
+  # redefined LT AC TAGCONFIG
+  if test -f "$ltmain"; then
+    if test ! -f "${ofile}"; then
+      AC_MSG_WARN([output file `$ofile' does not exist])
+    fi
+
+    if test -z "$LTCC"; then
+      eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+      if test -z "$LTCC"; then
+        AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+      else
+        AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+      fi
+    fi
+
+    AC_FOREACH([_LT_TAG], _LT_TAGS,
+      echo THOMAS: tag _LT_TAG
+      [m4_case(_LT_TAG,
+      [CXX], [
+    if test -n "$CXX" && test "X$CXX" != "Xno"; then
+      echo "THOMAS: YAY CXX"
+      AC_LIBTOOL_LANG_CXX_CONFIG
+      available_tags="$available_tags _LT_TAG"
+    fi],
+      [F77], [
+    if test -n "$F77" && test "X$F77" != "Xno"; then
+      AC_LIBTOOL_LANG_F77_CONFIG
+      available_tags="$available_tags _LT_TAG"
+    fi],
+      [GCJ], [
+    if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+      AC_LIBTOOL_LANG_GCJ_CONFIG
+      available_tags="$available_tags _LT_TAG"
+    fi],
+      [RC], [
+    if test -n "$RC" && test "X$RC" != "Xno"; then
+      AC_LIBTOOL_LANG_RC_CONFIG
+      available_tags="$available_tags _LT_TAG"
+    fi],
+      [m4_errprintn(m4_location[: error: invalid tag name: ]"_LT_TAG")
+      m4_exit(1)])
+    ])
+    echo THOMAS: available tags: $available_tags
+  fi
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+    AC_MSG_NOTICE([updated available libtool tags with $available_tags.])
+  else
+    rm -f "${ofile}T"
+    AC_MSG_ERROR([unable to update list of available tagged configurations.])
+
+  fi
+
+])dnl _LT_AC_TAG_CONFIG
+])
diff --git a/common/m4/as-libtool.m4 b/common/m4/as-libtool.m4
new file mode 100644 (file)
index 0000000..3b16095
--- /dev/null
@@ -0,0 +1,46 @@
+dnl as-libtool.m4 0.1.4
+
+dnl autostars m4 macro for libtool versioning
+
+dnl Thomas Vander Stichele <thomas at apestaart dot org>
+
+dnl $Id: as-libtool.m4,v 1.10 2005/10/15 13:44:23 thomasvs Exp $
+
+dnl AS_LIBTOOL(PREFIX, CURRENT, REVISION, AGE, [RELEASE])
+
+dnl example
+dnl AS_LIBTOOL(GST, 2, 0, 0)
+
+dnl this macro
+dnl - defines [$PREFIX]_CURRENT, REVISION and AGE
+dnl - defines [$PREFIX]_LIBVERSION
+dnl - defines [$PREFIX]_LT_LDFLAGS to set versioning
+dnl - AC_SUBST's them all
+
+dnl if RELEASE is given, then add a -release option to the LDFLAGS
+dnl with the given release version
+dnl then use [$PREFIX]_LT_LDFLAGS in the relevant Makefile.am's
+
+dnl call AM_PROG_LIBTOOL after this call
+
+AC_DEFUN([AS_LIBTOOL],
+[
+  [$1]_CURRENT=[$2]
+  [$1]_REVISION=[$3]
+  [$1]_AGE=[$4]
+  [$1]_LIBVERSION=[$2]:[$3]:[$4]
+  AC_SUBST([$1]_CURRENT)
+  AC_SUBST([$1]_REVISION)
+  AC_SUBST([$1]_AGE)
+  AC_SUBST([$1]_LIBVERSION)
+
+  [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -version-info $[$1]_LIBVERSION"
+  if test ! -z "[$5]"
+  then
+    [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -release [$5]"
+  fi
+  AC_SUBST([$1]_LT_LDFLAGS)
+
+  LT_PREREQ([2.2.6])
+  LT_INIT([dlopen win32-dll disable-static])
+])
diff --git a/common/m4/as-python.m4 b/common/m4/as-python.m4
new file mode 100644 (file)
index 0000000..eb9b175
--- /dev/null
@@ -0,0 +1,152 @@
+## ------------------------
+## Python file handling
+## From Andrew Dalke
+## Updated by James Henstridge
+## Updated by Andy Wingo to loop through possible pythons
+## ------------------------
+
+# AS_PATH_PYTHON([MINIMUM-VERSION])
+
+# Adds support for distributing Python modules and packages.  To
+# install modules, copy them to $(pythondir), using the python_PYTHON
+# automake variable.  To install a package with the same name as the
+# automake package, install to $(pkgpythondir), or use the
+# pkgpython_PYTHON automake variable.
+
+# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
+# locations to install python extension modules (shared libraries).
+# Another macro is required to find the appropriate flags to compile
+# extension modules.
+
+# If your package is configured with a different prefix to python,
+# users will have to add the install directory to the PYTHONPATH
+# environment variable, or create a .pth file (see the python
+# documentation for details).
+
+# If the MINIMUM-VERSION argument is passed, AS_PATH_PYTHON will
+# cause an error if the version of python installed on the system
+# doesn't meet the requirement.  MINIMUM-VERSION should consist of
+# numbers and dots only.
+
+# Updated to loop over all possible python binaries by Andy Wingo
+# <wingo@pobox.com>
+# Updated to only warn and unset PYTHON if no good one is found
+
+AC_DEFUN([AS_PATH_PYTHON],
+ [
+  dnl Find a version of Python.  I could check for python versions 1.4
+  dnl or earlier, but the default installation locations changed from
+  dnl $prefix/lib/site-python in 1.4 to $prefix/lib/python1.5/site-packages
+  dnl in 1.5, and I don't want to maintain that logic.
+
+  dnl should we do the version check?
+  PYTHON_CANDIDATES="python python2.2 python2.1 python2.0 python2 \
+                     python1.6 python1.5"
+  ifelse([$1],[],
+         [AC_PATH_PROG(PYTHON, $PYTHON_CANDIDATES)],
+         [
+     AC_MSG_NOTICE(Looking for Python version >= $1)
+    changequote(<<, >>)dnl
+    prog="
+import sys, string
+minver = '$1'
+# split string by '.' and convert to numeric
+minver_info = map(string.atoi, string.split(minver, '.'))
+# we can now do comparisons on the two lists:
+if sys.version_info >= tuple(minver_info):
+       sys.exit(0)
+else:
+       sys.exit(1)"
+    changequote([, ])dnl
+
+    python_good=false
+    for python_candidate in $PYTHON_CANDIDATES; do
+      unset PYTHON
+      AC_PATH_PROG(PYTHON, $python_candidate) 1> /dev/null 2> /dev/null
+
+      if test "x$PYTHON" = "x"; then continue; fi
+
+      if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC; then
+        AC_MSG_CHECKING(["$PYTHON":])
+       AC_MSG_RESULT([okay])
+        python_good=true
+        break;
+      else
+        dnl clear the cache val
+        unset ac_cv_path_PYTHON
+      fi
+    done
+  ])
+
+  if test "$python_good" != "true"; then
+    AC_MSG_WARN([No suitable version of python found])
+    PYTHON=
+  else
+
+  AC_MSG_CHECKING([local Python configuration])
+
+  dnl Query Python for its version number.  Getting [:3] seems to be
+  dnl the best way to do this; it's what "site.py" does in the standard
+  dnl library.  Need to change quote character because of [:3]
+
+  AC_SUBST(PYTHON_VERSION)
+  changequote(<<, >>)dnl
+  PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[:3]"`
+  changequote([, ])dnl
+
+
+  dnl Use the values of $prefix and $exec_prefix for the corresponding
+  dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX.  These are made
+  dnl distinct variables so they can be overridden if need be.  However,
+  dnl general consensus is that you shouldn't need this ability.
+
+  AC_SUBST(PYTHON_PREFIX)
+  PYTHON_PREFIX='${prefix}'
+
+  AC_SUBST(PYTHON_EXEC_PREFIX)
+  PYTHON_EXEC_PREFIX='${exec_prefix}'
+
+  dnl At times (like when building shared libraries) you may want
+  dnl to know which OS platform Python thinks this is.
+
+  AC_SUBST(PYTHON_PLATFORM)
+  PYTHON_PLATFORM=`$PYTHON -c "import sys; print sys.platform"`
+
+
+  dnl Set up 4 directories:
+
+  dnl pythondir -- where to install python scripts.  This is the
+  dnl   site-packages directory, not the python standard library
+  dnl   directory like in previous automake betas.  This behaviour
+  dnl   is more consistent with lispdir.m4 for example.
+  dnl
+  dnl Also, if the package prefix isn't the same as python's prefix,
+  dnl then the old $(pythondir) was pretty useless.
+
+  AC_SUBST(pythondir)
+  pythondir=$PYTHON_PREFIX"/lib/python"$PYTHON_VERSION/site-packages
+
+  dnl pkgpythondir -- $PACKAGE directory under pythondir.  Was
+  dnl   PYTHON_SITE_PACKAGE in previous betas, but this naming is
+  dnl   more consistent with the rest of automake.
+  dnl   Maybe this should be put in python.am?
+
+  AC_SUBST(pkgpythondir)
+  pkgpythondir=\${pythondir}/$PACKAGE
+
+  dnl pyexecdir -- directory for installing python extension modules
+  dnl   (shared libraries)  Was PYTHON_SITE_EXEC in previous betas.
+
+  AC_SUBST(pyexecdir)
+  pyexecdir=$PYTHON_EXEC_PREFIX"/lib/python"$PYTHON_VERSION/site-packages
+
+  dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
+  dnl   Maybe this should be put in python.am?
+
+  AC_SUBST(pkgpyexecdir)
+  pkgpyexecdir=\${pyexecdir}/$PACKAGE
+
+  AC_MSG_RESULT([looks good])
+
+  fi
+])
diff --git a/common/m4/as-version.m4 b/common/m4/as-version.m4
new file mode 100644 (file)
index 0000000..22ff774
--- /dev/null
@@ -0,0 +1,75 @@
+dnl as-version.m4 0.2.0
+
+dnl autostars m4 macro for versioning
+
+dnl Thomas Vander Stichele <thomas at apestaart dot org>
+
+dnl $Id: as-version.m4,v 1.15 2006/04/01 09:40:24 thomasvs Exp $
+
+dnl AS_VERSION
+
+dnl example
+dnl AS_VERSION
+
+dnl this macro
+dnl - AC_SUBST's PACKAGE_VERSION_MAJOR, _MINOR, _MICRO
+dnl - AC_SUBST's PACKAGE_VERSION_RELEASE,
+dnl    which can be used for rpm release fields
+dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents
+dnl   maintainer mode from running correctly
+dnl
+dnl don't forget to put #undef PACKAGE_VERSION_RELEASE in acconfig.h
+dnl if you use acconfig.h
+
+AC_DEFUN([AS_VERSION],
+[
+  PACKAGE_VERSION_MAJOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f1)
+  PACKAGE_VERSION_MINOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f2)
+  PACKAGE_VERSION_MICRO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f3)
+
+  AC_SUBST(PACKAGE_VERSION_MAJOR)
+  AC_SUBST(PACKAGE_VERSION_MINOR)
+  AC_SUBST(PACKAGE_VERSION_MICRO)
+])
+
+dnl AS_NANO(ACTION-IF-NANO-NON-NULL, [ACTION-IF-NANO-NULL])
+
+dnl requires AC_INIT to be called before
+dnl For projects using a fourth or nano number in your versioning to indicate
+dnl development or prerelease snapshots, this macro allows the build to be
+dnl set up differently accordingly.
+
+dnl this macro:
+dnl - parses AC_PACKAGE_VERSION, set by AC_INIT, and extracts the nano number
+dnl - sets the variable PACKAGE_VERSION_NANO
+dnl - sets the variable PACKAGE_VERSION_RELEASE, which can be used
+dnl   for rpm release fields
+dnl - executes ACTION-IF-NANO-NON-NULL or ACTION-IF-NANO-NULL
+
+dnl example:
+dnl AS_NANO(RELEASE="yes", RELEASE="no")
+
+AC_DEFUN([AS_NANO],
+[
+  AC_MSG_CHECKING(nano version)
+
+  NANO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f4)
+
+  if test x"$NANO" = x || test "x$NANO" = "x0" ; then
+    AC_MSG_RESULT([0 (release)])
+    NANO=0
+    PACKAGE_VERSION_RELEASE=1
+    ifelse([$1], , :, [$1])
+  else
+    AC_MSG_RESULT($NANO)
+    PACKAGE_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S`
+    if test "x$NANO" != "x1" ; then
+       ifelse([$1], , :, [$1])
+    else
+       ifelse([$2], , :, [$2])
+    fi
+  fi
+  PACKAGE_VERSION_NANO=$NANO
+  AC_SUBST(PACKAGE_VERSION_NANO)
+  AC_SUBST(PACKAGE_VERSION_RELEASE)
+])
diff --git a/common/m4/ax_create_stdint_h.m4 b/common/m4/ax_create_stdint_h.m4
new file mode 100644 (file)
index 0000000..13bf699
--- /dev/null
@@ -0,0 +1,734 @@
+##### http://autoconf-archive.cryp.to/ax_create_stdint_h.html
+#
+# SYNOPSIS
+#
+#   AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
+#
+# DESCRIPTION
+#
+#   the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
+#   existence of an include file <stdint.h> that defines a set of
+#   typedefs, especially uint8_t,int32_t,uintptr_t. Many older
+#   installations will not provide this file, but some will have the
+#   very same definitions in <inttypes.h>. In other enviroments we can
+#   use the inet-types in <sys/types.h> which would define the typedefs
+#   int8_t and u_int8_t respectivly.
+#
+#   This macros will create a local "_stdint.h" or the headerfile given
+#   as an argument. In many cases that file will just "#include
+#   <stdint.h>" or "#include <inttypes.h>", while in other environments
+#   it will provide the set of basic 'stdint's definitions/typedefs:
+#
+#     int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
+#     int_least32_t.. int_fast32_t.. intmax_t
+#
+#   which may or may not rely on the definitions of other files, or
+#   using the AC_CHECK_SIZEOF macro to determine the actual sizeof each
+#   type.
+#
+#   if your header files require the stdint-types you will want to
+#   create an installable file mylib-int.h that all your other
+#   installable header may include. So if you have a library package
+#   named "mylib", just use
+#
+#        AX_CREATE_STDINT_H(mylib-int.h)
+#
+#   in configure.ac and go to install that very header file in
+#   Makefile.am along with the other headers (mylib.h) - and the
+#   mylib-specific headers can simply use "#include <mylib-int.h>" to
+#   obtain the stdint-types.
+#
+#   Remember, if the system already had a valid <stdint.h>, the
+#   generated file will include it directly. No need for fuzzy
+#   HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled
+#   its stdint.h for non-c99 compilation and the c99-mode is not the
+#   default. Therefore this macro will not use the compiler's stdint.h
+#   - please complain to the GCC developers).
+#
+# LAST MODIFICATION
+#
+#   2007-06-27
+#
+# COPYLEFT
+#
+#   Copyright (c) 2007 Guido U. Draheim <guidod@gmx.de>
+#
+#   This program is free software; you can redistribute it and/or
+#   modify it under the terms of the GNU General Public License as
+#   published by the Free Software Foundation; either version 2 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
+#   General Public License for more details.
+#
+#   You should have received a copy of the GNU 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.
+#
+#   As a special exception, the respective Autoconf Macro's copyright
+#   owner gives unlimited permission to copy, distribute and modify the
+#   configure scripts that are the output of Autoconf when processing
+#   the Macro. You need not follow the terms of the GNU General Public
+#   License when using or distributing such scripts, even though
+#   portions of the text of the Macro appear in them. The GNU General
+#   Public License (GPL) does govern all other use of the material that
+#   constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the
+#   Autoconf Macro released by the Autoconf Macro Archive. When you
+#   make and distribute a modified version of the Autoconf Macro, you
+#   may extend this special exception to the GPL to apply to your
+#   modified version as well.
+
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+   AC_CHECK_SIZEOF(char)
+   AC_CHECK_SIZEOF(short)
+   AC_CHECK_SIZEOF(int)
+   AC_CHECK_SIZEOF(long)
+   AC_CHECK_SIZEOF(void*)
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   AC_MSG_CHECKING([data model])
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
+   esac
+   AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
+  do
+   unset ac_cv_type_uintptr_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+  done
+  AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
+  do
+   unset ac_cv_type_uint32_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_u_int32_t
+   unset ac_cv_type_u_int64_t
+   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
+AC_DEFUN([AX_CREATE_STDINT_H],
+[# ------ AX CREATE STDINT H -------------------------------------
+AC_MSG_CHECKING([for stdint types])
+ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
+# try to shortcircuit - if the default include path of the compiler
+# can find a "stdint.h" header then we assume that all compilers can.
+AC_CACHE_VAL([ac_cv_header_stdint_t],[
+old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
+old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
+old_CFLAGS="$CFLAGS"     ; CFLAGS=""
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[ac_cv_stdint_result="(assuming C99 compatible system)"
+ ac_cv_header_stdint_t="stdint.h"; ],
+[ac_cv_header_stdint_t=""])
+if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
+CFLAGS="-std=c99"
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
+fi
+CXXFLAGS="$old_CXXFLAGS"
+CPPFLAGS="$old_CPPFLAGS"
+CFLAGS="$old_CFLAGS" ])
+
+v="... $ac_cv_header_stdint_h"
+if test "$ac_stdint_h" = "stdint.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
+elif test "$ac_stdint_h" = "inttypes.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
+elif test "_$ac_cv_header_stdint_t" = "_" ; then
+ AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
+else
+ ac_cv_header_stdint="$ac_cv_header_stdint_t"
+ AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
+fi
+
+if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
+
+dnl .....intro message done, now do a few system checks.....
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
+dnl instead that is triggered with 3 or more arguments (see types.m4)
+
+inttype_headers=`echo $2 | sed -e 's/,/ /g'`
+
+ac_cv_stdint_result="(no helpful system typedefs seen)"
+AX_CHECK_HEADER_STDINT_X(dnl
+   stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+AX_CHECK_HEADER_STDINT_O(dnl,
+   inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+   ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
+fi
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+if test "_$ac_cv_header_stdint_o" = "_" ; then
+AX_CHECK_HEADER_STDINT_U(dnl,
+   sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
+fi fi
+
+dnl if there was no good C99 header file, do some typedef checks...
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+   AC_MSG_CHECKING([for stdint datatype model])
+   AC_MSG_RESULT([(..)])
+   AX_CHECK_DATA_MODEL
+fi
+
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_x"
+elif  test "_$ac_cv_header_stdint_o" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_o"
+elif  test "_$ac_cv_header_stdint_u" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_u"
+else
+   ac_cv_header_stdint="stddef.h"
+fi
+
+AC_MSG_CHECKING([for extra inttypes in chosen header])
+AC_MSG_RESULT([($ac_cv_header_stdint)])
+dnl see if int_least and int_fast types are present in _this_ header.
+unset ac_cv_type_int_least32_t
+unset ac_cv_type_int_fast32_t
+AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
+AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
+AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
+
+fi # shortcircut to system "stdint.h"
+# ------------------ PREPARE VARIABLES ------------------------------
+if test "$GCC" = "yes" ; then
+ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
+else
+ac_cv_stdint_message="using $CC"
+fi
+
+AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
+$ac_cv_stdint_result])
+
+dnl -----------------------------------------------------------------
+# ----------------- DONE inttypes.h checks START header -------------
+AC_CONFIG_COMMANDS([$ac_stdint_h],[
+AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
+ac_stdint=$tmp/_stdint.h
+
+echo "#ifndef" $_ac_stdint_h >$ac_stdint
+echo "#define" $_ac_stdint_h "1" >>$ac_stdint
+echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
+echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
+echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_t" != "_" ; then
+echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
+
+cat >>$ac_stdint <<STDINT_EOF
+
+/* ................... shortcircuit part ........................... */
+
+#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <stddef.h>
+
+/* .................... configured part ............................ */
+
+STDINT_EOF
+
+echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+  ac_header="$ac_cv_header_stdint_x"
+  echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
+fi
+
+echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_o" != "_" ; then
+  ac_header="$ac_cv_header_stdint_o"
+  echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
+fi
+
+echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_u" != "_" ; then
+  ac_header="$ac_cv_header_stdint_u"
+  echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
+fi
+
+echo "" >>$ac_stdint
+
+if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
+  echo "#include <$ac_header>" >>$ac_stdint
+  echo "" >>$ac_stdint
+fi fi
+
+echo "/* which 64bit typedef has been found */" >>$ac_stdint
+if test "$ac_cv_type_uint64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_UINT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
+fi
+if test "$ac_cv_type_u_int64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_U_INT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* which type model has been detected */" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
+else
+echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
+echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* whether int_least types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_least32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_LEAST32_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
+fi
+echo "/* whether int_fast types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_fast32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
+fi
+echo "/* whether intmax_t type was detected */" >>$ac_stdint
+if test "$ac_cv_type_intmax_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+  cat >>$ac_stdint <<STDINT_EOF
+/* .................... detections part ............................ */
+
+/* whether we need to define bitspecific types from compiler base types */
+#ifndef _STDINT_HEADER_INTPTR
+#ifndef _STDINT_HEADER_UINT32
+#ifndef _STDINT_HEADER_U_INT32
+#define _STDINT_NEED_INT_MODEL_T
+#else
+#define _STDINT_HAVE_U_INT_TYPES
+#endif
+#endif
+#endif
+
+#ifdef _STDINT_HAVE_U_INT_TYPES
+#undef _STDINT_NEED_INT_MODEL_T
+#endif
+
+#ifdef  _STDINT_CHAR_MODEL
+#if     _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
+#ifndef _STDINT_BYTE_MODEL
+#define _STDINT_BYTE_MODEL 12
+#endif
+#endif
+#endif
+
+#ifndef _STDINT_HAVE_INT_LEAST32_T
+#define _STDINT_NEED_INT_LEAST_T
+#endif
+
+#ifndef _STDINT_HAVE_INT_FAST32_T
+#define _STDINT_NEED_INT_FAST_T
+#endif
+
+#ifndef _STDINT_HEADER_INTPTR
+#define _STDINT_NEED_INTPTR_T
+#ifndef _STDINT_HAVE_INTMAX_T
+#define _STDINT_NEED_INTMAX_T
+#endif
+#endif
+
+
+/* .................... definition part ............................ */
+
+/* some system headers have good uint64_t */
+#ifndef _HAVE_UINT64_T
+#if     defined _STDINT_HAVE_UINT64_T  || defined HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#elif   defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
+#define _HAVE_UINT64_T
+typedef u_int64_t uint64_t;
+#endif
+#endif
+
+#ifndef _HAVE_UINT64_T
+/* .. here are some common heuristics using compiler runtime specifics */
+#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+#elif !defined __STRICT_ANSI__
+#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
+#define _HAVE_UINT64_T
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
+/* note: all ELF-systems seem to have loff-support which needs 64-bit */
+#if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
+#elif defined __alpha || (defined __mips && defined _ABIN32)
+#if !defined _NO_LONGLONG
+typedef long int64_t;
+typedef unsigned long uint64_t;
+#endif
+  /* compiler/cpu type to define int64_t */
+#endif
+#endif
+#endif
+
+#if defined _STDINT_HAVE_U_INT_TYPES
+/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
+typedef u_int8_t uint8_t;
+typedef u_int16_t uint16_t;
+typedef u_int32_t uint32_t;
+
+/* glibc compatibility */
+#ifndef __int8_t_defined
+#define __int8_t_defined
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INT_MODEL_T
+/* we must guess all the basic types. Apart from byte-adressable system, */
+/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
+/* (btw, those nibble-addressable systems are way off, or so we assume) */
+
+dnl   /* have a look at "64bit and data size neutrality" at */
+dnl   /* http://unix.org/version2/whatsnew/login_64bit.html */
+dnl   /* (the shorthand "ILP" types always have a "P" part) */
+
+#if defined _STDINT_BYTE_MODEL
+#if _STDINT_LONG_MODEL+0 == 242
+/* 2:4:2 =  IP16 = a normal 16-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned long   uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          long    int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
+/* 2:4:4 =  LP32 = a 32-bit system derived from a 16-bit */
+/* 4:4:4 = ILP32 = a normal 32-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
+/* 4:8:4 =  IP32 = a 32-bit system prepared for 64-bit    */
+/* 4:8:8 =  LP64 = a normal 64-bit system                 */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* this system has a "long" of 64bit */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+typedef unsigned long   uint64_t;
+typedef          long    int64_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 448
+/*      LLP64   a 64-bit system derived from a 32-bit system */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* assuming the system has a "long long" */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef unsigned long long uint64_t;
+typedef          long long  int64_t;
+#endif
+#else
+#define _STDINT_NO_INT32_T
+#endif
+#else
+#define _STDINT_NO_INT8_T
+#define _STDINT_NO_INT32_T
+#endif
+#endif
+
+/*
+ * quote from SunOS-5.8 sys/inttypes.h:
+ * Use at your own risk.  As of February 1996, the committee is squarely
+ * behind the fixed sized types; the "least" and "fast" types are still being
+ * discussed.  The probability that the "fast" types may be removed before
+ * the standard is finalized is high enough that they are not currently
+ * implemented.
+ */
+
+#if defined _STDINT_NEED_INT_LEAST_T
+typedef  int8_t    int_least8_t;
+typedef  int16_t   int_least16_t;
+typedef  int32_t   int_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_least64_t;
+#endif
+
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_least64_t;
+#endif
+  /* least types */
+#endif
+
+#if defined _STDINT_NEED_INT_FAST_T
+typedef  int8_t    int_fast8_t;
+typedef  int       int_fast16_t;
+typedef  int32_t   int_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_fast64_t;
+#endif
+
+typedef uint8_t   uint_fast8_t;
+typedef unsigned  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_fast64_t;
+#endif
+  /* fast types */
+#endif
+
+#ifdef _STDINT_NEED_INTMAX_T
+#ifdef _HAVE_UINT64_T
+typedef  int64_t       intmax_t;
+typedef uint64_t      uintmax_t;
+#else
+typedef          long  intmax_t;
+typedef unsigned long uintmax_t;
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INTPTR_T
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+/* we encourage using "long" to store pointer values, never use "int" ! */
+#if   _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
+typedef  unsigned int   uintptr_t;
+typedef           int    intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
+typedef        uint64_t uintptr_t;
+typedef         int64_t  intptr_t;
+#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#endif
+#endif
+#endif
+
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+
+/* Maximum of unsigned integral types.  */
+# define UINT8_MAX              (255)
+# define UINT16_MAX             (65535)
+# define UINT32_MAX             (4294967295U)
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
+  /* shortcircuit*/
+#endif
+  /* once */
+#endif
+#endif
+STDINT_EOF
+fi
+    if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
+      AC_MSG_NOTICE([$ac_stdint_h is unchanged])
+    else
+      ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
+      AS_MKDIR_P(["$ac_dir"])
+      rm -f $ac_stdint_h
+      mv $ac_stdint $ac_stdint_h
+    fi
+],[# variables for create stdint.h replacement
+PACKAGE="$PACKAGE"
+VERSION="$VERSION"
+ac_stdint_h="$ac_stdint_h"
+_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
+ac_cv_stdint_message="$ac_cv_stdint_message"
+ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
+ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
+ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
+ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
+ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
+ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
+ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
+ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
+ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
+])
+])
diff --git a/common/m4/check.m4 b/common/m4/check.m4
new file mode 100644 (file)
index 0000000..afd26eb
--- /dev/null
@@ -0,0 +1,181 @@
+dnl _AM_TRY_CHECK(MINIMUM-VERSION, EXTRA-CFLAGS, EXTRA-LIBS, CHECK-LIB-NAME
+dnl               [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS
+dnl Done this way because of the brokenness that is
+dnl https://launchpad.net/distros/ubuntu/+source/check/+bug/5840
+dnl
+
+AC_DEFUN([_AM_TRY_CHECK],
+[
+  min_check_version=$1
+  extra_cflags=$2
+  extra_libs=$3
+  check_lib_name=$4
+
+  CHECK_CFLAGS="$extra_cflags"
+  CHECK_LIBS="$extra_libs -l$check_lib_name"
+
+  ac_save_CFLAGS="$CFLAGS"
+  ac_save_LIBS="$LIBS"
+
+  CFLAGS="$CFLAGS $CHECK_CFLAGS"
+  LIBS="$CHECK_LIBS $LIBS"
+
+  AC_MSG_CHECKING(for check named $check_lib_name  - version >= $min_check_version)
+
+  rm -f conf.check-test
+  dnl unset no_check, since in our second run it would have been set to yes
+  dnl before
+  no_check=
+  AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <check.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.check-test");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = strdup("$min_check_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_check_version");
+     return 1;
+   }
+
+  if ((CHECK_MAJOR_VERSION != check_major_version) ||
+      (CHECK_MINOR_VERSION != check_minor_version) ||
+      (CHECK_MICRO_VERSION != check_micro_version))
+    {
+      printf("\n*** The check header file (version %d.%d.%d) does not match\n",
+            CHECK_MAJOR_VERSION, CHECK_MINOR_VERSION, CHECK_MICRO_VERSION);
+      printf("*** the check library (version %d.%d.%d).\n",
+            check_major_version, check_minor_version, check_micro_version);
+      return 1;
+    }
+
+  if ((check_major_version > major) ||
+      ((check_major_version == major) && (check_minor_version > minor)) ||
+      ((check_major_version == major) && (check_minor_version == minor) && (check_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** An old version of check (%d.%d.%d) was found.\n",
+             check_major_version, check_minor_version, check_micro_version);
+      printf("*** You need a version of check being at least %d.%d.%d.\n", major, minor, micro);
+      printf("***\n");
+      printf("*** If you have already installed a sufficiently new version, this error\n");
+      printf("*** probably means that the wrong copy of the check library and header\n");
+      printf("*** file is being found. Rerun configure with the --with-check=PATH option\n");
+      printf("*** to specify the prefix where the correct version was installed.\n");
+    }
+
+  return 1;
+}
+],, no_check=yes, [echo $ac_n "cross compiling; assumed OK... $ac_c"])
+
+  CFLAGS="$ac_save_CFLAGS"
+  LIBS="$ac_save_LIBS"
+
+  if test "x$no_check" = x ; then
+    AC_MSG_RESULT(yes)
+    ifelse([$5], , :, [$5])
+  else
+    AC_MSG_RESULT(no)
+    if test -f conf.check-test ; then
+      :
+    else
+      echo "*** Could not run check test program, checking why..."
+      CFLAGS="$CFLAGS $CHECK_CFLAGS"
+      LIBS="$CHECK_LIBS $LIBS"
+      AC_TRY_LINK([
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <check.h>
+], ,  [ echo "*** The test program compiled, but did not run. This usually means"
+        echo "*** that the run-time linker is not finding check. You'll need to set your"
+        echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+        echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+        echo "*** is required on your system"
+       echo "***"
+        echo "*** If you have an old version installed, it is best to remove it, although"
+        echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+      [ echo "*** The test program failed to compile or link. See the file config.log for"
+        echo "*** the exact error that occured." ])
+
+      CFLAGS="$ac_save_CFLAGS"
+      LIBS="$ac_save_LIBS"
+    fi
+
+    CHECK_CFLAGS=""
+    CHECK_LIBS=""
+
+    rm -f conf.check-test
+    ifelse([$6], , AC_MSG_ERROR([check not found]), [$6])
+  fi
+])
+
+
+dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS
+dnl
+
+AC_DEFUN([AM_PATH_CHECK],
+[
+  AC_ARG_WITH(check,
+  [  --with-check=PATH       prefix where check is installed [default=auto]])
+
+  AC_ARG_WITH(checklibname,
+    AC_HELP_STRING([--with-check-lib-name=NAME],
+      [name of the PIC check library (default=check)]))
+
+  min_check_version=ifelse([$1], ,0.8.2,$1)
+
+  if test x$with_check = xno; then
+    AC_MSG_RESULT(disabled)
+    ifelse([$3], , AC_MSG_ERROR([disabling check is not supported]), [$3])
+  else
+    if test "x$with_check" != x; then
+      CHECK_EXTRA_CFLAGS="-I$with_check/include"
+      CHECK_EXTRA_LIBS="-L$with_check/lib"
+    else
+      CHECK_EXTRA_CFLAGS=""
+      CHECK_EXTRA_LIBS=""
+    fi
+
+    if test x$with_checklibname = x; then
+      _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS,
+        check_pic, [have_check=true], [have_check=false])
+      if test x$have_check = xtrue; then
+        ifelse([$2], , :, [$2])
+      else
+        _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS,
+          check, [have_check=true], [have_check=false])
+        if test x$have_check = xtrue; then
+          ifelse([$2], , :, [$2])
+        else
+          ifelse([$3], , AC_MSG_ERROR([check not found]), [$3])
+        fi
+      fi
+    else
+      _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS,
+        $with_checklibname, [have_check=true], [have_check=false])
+      if test x$have_check = xtrue; then
+        ifelse([$2], , :, [$2])
+      else
+        ifelse([$3], , AC_MSG_ERROR([check not found]), [$3])
+      fi
+    fi
+
+    AC_SUBST(CHECK_CFLAGS)
+    AC_SUBST(CHECK_LIBS)
+    rm -f conf.check-test
+  fi
+])
diff --git a/common/m4/glib-gettext.m4 b/common/m4/glib-gettext.m4
new file mode 100644 (file)
index 0000000..f8d442f
--- /dev/null
@@ -0,0 +1,432 @@
+# Copyright (C) 1995-2002 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003,2004 Red Hat, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License.  As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# This file can be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+#
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995, 1996
+#
+# Modified to never use included libintl.
+# Owen Taylor <otaylor@redhat.com>, 12/15/1998
+#
+# Major rework to remove unused code
+# Owen Taylor <otaylor@redhat.com>, 12/11/2002
+#
+# Added better handling of ALL_LINGUAS from GNU gettext version
+# written by Bruno Haible, Owen Taylor <otaylor.redhat.com> 5/30/3002
+#
+# Modified to require ngettext
+# Matthias Clasen <mclasen@redhat.com> 08/06/2004
+#
+# We need this here as well, since someone might use autoconf-2.5x
+# to configure GLib then an older version to configure a package
+# using AM_GLIB_GNU_GETTEXT
+AC_PREREQ(2.53)
+
+dnl
+dnl We go to great lengths to make sure that aclocal won't
+dnl try to pull in the installed version of these macros
+dnl when running aclocal in the glib directory.
+dnl
+m4_copy([AC_DEFUN],[glib_DEFUN])
+m4_copy([AC_REQUIRE],[glib_REQUIRE])
+dnl
+dnl At the end, if we're not within glib, we'll define the public
+dnl definitions in terms of our private definitions.
+dnl
+
+# GLIB_LC_MESSAGES
+#--------------------
+glib_DEFUN([GLIB_LC_MESSAGES],
+  [AC_CHECK_HEADERS([locale.h])
+    if test $ac_cv_header_locale_h = yes; then
+    AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+      [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+       am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      AC_DEFINE(HAVE_LC_MESSAGES, 1,
+        [Define if your <locale.h> file defines LC_MESSAGES.])
+    fi
+  fi])
+
+# GLIB_PATH_PROG_WITH_TEST
+#----------------------------
+dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+glib_DEFUN([GLIB_PATH_PROG_WITH_TEST],
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+  /*)
+  ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in ifelse([$5], , $PATH, [$5]); do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if [$3]; then
+       ac_cv_path_$1="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+  ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+  AC_MSG_RESULT([$]$1)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# GLIB_WITH_NLS
+#-----------------
+glib_DEFUN([GLIB_WITH_NLS],
+  dnl NLS is obligatory
+  [USE_NLS=yes
+    AC_SUBST(USE_NLS)
+
+    gt_cv_have_gettext=no
+
+    CATOBJEXT=NONE
+    XGETTEXT=:
+    INTLLIBS=
+
+    AC_CHECK_HEADER(libintl.h,
+     [gt_cv_func_dgettext_libintl="no"
+      libintl_extra_libs=""
+
+      #
+      # First check in libc
+      #
+      AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc,
+        [AC_TRY_LINK([
+#include <libintl.h>
+],
+         [return !ngettext ("","", 1)],
+         gt_cv_func_ngettext_libc=yes,
+          gt_cv_func_ngettext_libc=no)
+        ])
+
+      if test "$gt_cv_func_ngettext_libc" = "yes" ; then
+             AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc,
+               [AC_TRY_LINK([
+#include <libintl.h>
+],
+                 [return !dgettext ("","")],
+                 gt_cv_func_dgettext_libc=yes,
+                 gt_cv_func_dgettext_libc=no)
+               ])
+      fi
+
+      if test "$gt_cv_func_ngettext_libc" = "yes" ; then
+        AC_CHECK_FUNCS(bind_textdomain_codeset)
+      fi
+
+      #
+      # If we don't have everything we want, check in libintl
+      #
+      if test "$gt_cv_func_dgettext_libc" != "yes" \
+        || test "$gt_cv_func_ngettext_libc" != "yes" \
+         || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then
+
+        AC_CHECK_LIB(intl, bindtextdomain,
+           [AC_CHECK_LIB(intl, ngettext,
+                   [AC_CHECK_LIB(intl, dgettext,
+                                 gt_cv_func_dgettext_libintl=yes)])])
+
+       if test "$gt_cv_func_dgettext_libintl" != "yes" ; then
+         AC_MSG_CHECKING([if -liconv is needed to use gettext])
+         AC_MSG_RESULT([])
+         AC_CHECK_LIB(intl, ngettext,
+               [AC_CHECK_LIB(intl, dcgettext,
+                      [gt_cv_func_dgettext_libintl=yes
+                       libintl_extra_libs=-liconv],
+                       :,-liconv)],
+               :,-liconv)
+        fi
+
+        #
+        # If we found libintl, then check in it for bind_textdomain_codeset();
+        # we'll prefer libc if neither have bind_textdomain_codeset(),
+        # and both have dgettext and ngettext
+        #
+        if test "$gt_cv_func_dgettext_libintl" = "yes" ; then
+          glib_save_LIBS="$LIBS"
+          LIBS="$LIBS -lintl $libintl_extra_libs"
+          unset ac_cv_func_bind_textdomain_codeset
+          AC_CHECK_FUNCS(bind_textdomain_codeset)
+          LIBS="$glib_save_LIBS"
+
+          if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then
+            gt_cv_func_dgettext_libc=no
+          else
+            if test "$gt_cv_func_dgettext_libc" = "yes" \
+               && test "$gt_cv_func_ngettext_libc" = "yes"; then
+              gt_cv_func_dgettext_libintl=no
+            fi
+          fi
+        fi
+      fi
+
+      if test "$gt_cv_func_dgettext_libc" = "yes" \
+       || test "$gt_cv_func_dgettext_libintl" = "yes"; then
+        gt_cv_have_gettext=yes
+      fi
+
+      if test "$gt_cv_func_dgettext_libintl" = "yes"; then
+        INTLLIBS="-lintl $libintl_extra_libs"
+      fi
+
+      if test "$gt_cv_have_gettext" = "yes"; then
+       AC_DEFINE(HAVE_GETTEXT,1,
+         [Define if the GNU gettext() function is already present or preinstalled.])
+       GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+       if test "$MSGFMT" != "no"; then
+          glib_save_LIBS="$LIBS"
+          LIBS="$LIBS $INTLLIBS"
+         AC_CHECK_FUNCS(dcgettext)
+         MSGFMT_OPTS=
+         AC_MSG_CHECKING([if msgfmt accepts -c])
+         GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: test 1.0\n"
+"PO-Revision-Date: 2007-02-15 12:01+0100\n"
+"Last-Translator: test <foo@bar.xx>\n"
+"Language-Team: C <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
+         AC_SUBST(MSGFMT_OPTS)
+         AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+         GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+           [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+         AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+                        return _nl_msg_cat_cntr],
+           [CATOBJEXT=.gmo
+             DATADIRNAME=share],
+           [case $host in
+           *-*-solaris*)
+           dnl On Solaris, if bind_textdomain_codeset is in libc,
+           dnl GNU format message catalog is always supported,
+            dnl since both are added to the libc all together.
+           dnl Hence, we'd like to go with DATADIRNAME=share and
+           dnl and CATOBJEXT=.gmo in this case.
+            AC_CHECK_FUNC(bind_textdomain_codeset,
+             [CATOBJEXT=.gmo
+               DATADIRNAME=share],
+             [CATOBJEXT=.mo
+               DATADIRNAME=lib])
+           ;;
+           *)
+           CATOBJEXT=.mo
+            DATADIRNAME=lib
+           ;;
+           esac])
+          LIBS="$glib_save_LIBS"
+         INSTOBJEXT=.mo
+       else
+         gt_cv_have_gettext=no
+       fi
+      fi
+    ])
+
+    if test "$gt_cv_have_gettext" = "yes" ; then
+      AC_DEFINE(ENABLE_NLS, 1,
+        [always defined to indicate that i18n is enabled])
+    fi
+
+    dnl Test whether we really found GNU xgettext.
+    if test "$XGETTEXT" != ":"; then
+      dnl If it is not GNU xgettext we define it as : so that the
+      dnl Makefiles still can work.
+      if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+        : ;
+      else
+        AC_MSG_RESULT(
+         [found xgettext program is not GNU xgettext; ignore it])
+        XGETTEXT=":"
+      fi
+    fi
+
+    # We need to process the po/ directory.
+    POSUB=po
+
+    AC_OUTPUT_COMMANDS(
+      [case "$CONFIG_FILES" in *po/Makefile.in*)
+        sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+      esac])
+
+    dnl These rules are solely for the distribution goal.  While doing this
+    dnl we only have to keep exactly one list of the available catalogs
+    dnl in configure.in.
+    for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST(CATALOGS)
+    AC_SUBST(CATOBJEXT)
+    AC_SUBST(DATADIRNAME)
+    AC_SUBST(GMOFILES)
+    AC_SUBST(INSTOBJEXT)
+    AC_SUBST(INTLLIBS)
+    AC_SUBST(PO_IN_DATADIR_TRUE)
+    AC_SUBST(PO_IN_DATADIR_FALSE)
+    AC_SUBST(POFILES)
+    AC_SUBST(POSUB)
+  ])
+
+# AM_GLIB_GNU_GETTEXT
+# -------------------
+# Do checks necessary for use of gettext. If a suitable implementation
+# of gettext is found in either in libintl or in the C library,
+# it will set INTLLIBS to the libraries needed for use of gettext
+# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable
+# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST()
+# on various variables needed by the Makefile.in.in installed by
+# glib-gettextize.
+dnl
+glib_DEFUN([GLIB_GNU_GETTEXT],
+  [AC_REQUIRE([AC_PROG_CC])dnl
+   AC_REQUIRE([AC_HEADER_STDC])dnl
+
+   GLIB_LC_MESSAGES
+   GLIB_WITH_NLS
+
+   if test "$gt_cv_have_gettext" = "yes"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       AC_MSG_CHECKING(for catalogs to be installed)
+       NEW_LINGUAS=
+       for presentlang in $ALL_LINGUAS; do
+         useit=no
+         if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then
+           desiredlanguages="$LINGUAS"
+         else
+           desiredlanguages="$ALL_LINGUAS"
+         fi
+         for desiredlang in $desiredlanguages; do
+          # Use the presentlang catalog if desiredlang is
+           #   a. equal to presentlang, or
+           #   b. a variant of presentlang (because in this case,
+           #      presentlang can be used as a fallback for messages
+           #      which are not translated in the desiredlang catalog).
+           case "$desiredlang" in
+             "$presentlang"*) useit=yes;;
+           esac
+         done
+         if test $useit = yes; then
+           NEW_LINGUAS="$NEW_LINGUAS $presentlang"
+         fi
+       done
+       LINGUAS=$NEW_LINGUAS
+       AC_MSG_RESULT($LINGUAS)
+     fi
+
+     dnl Construct list of names of catalog files to be constructed.
+     if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+   dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+   dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
+   dnl Try to locate is.
+   MKINSTALLDIRS=
+   if test -n "$ac_aux_dir"; then
+     MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+   fi
+   if test -z "$MKINSTALLDIRS"; then
+     MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+   fi
+   AC_SUBST(MKINSTALLDIRS)
+
+   dnl Generate list of files to be processed by xgettext which will
+   dnl be included in po/Makefile.
+   test -d po || mkdir po
+   if test "x$srcdir" != "x."; then
+     if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+       posrcprefix="$srcdir/"
+     else
+       posrcprefix="../$srcdir/"
+     fi
+   else
+     posrcprefix="../"
+   fi
+   rm -f po/POTFILES
+   sed -e "/^#/d" -e "/^\$/d" -e "s,.*,        $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+       < $srcdir/po/POTFILES.in > po/POTFILES
+  ])
+
+# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE)
+# -------------------------------
+# Define VARIABLE to the location where catalog files will
+# be installed by po/Makefile.
+glib_DEFUN([GLIB_DEFINE_LOCALEDIR],
+[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl
+glib_save_prefix="$prefix"
+glib_save_exec_prefix="$exec_prefix"
+glib_save_datarootdir="$datarootdir"
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix=$prefix
+datarootdir=`eval echo "${datarootdir}"`
+if test "x$CATOBJEXT" = "x.mo" ; then
+  localedir=`eval echo "${libdir}/locale"`
+else
+  localedir=`eval echo "${datadir}/locale"`
+fi
+prefix="$glib_save_prefix"
+exec_prefix="$glib_save_exec_prefix"
+datarootdir="$glib_save_datarootdir"
+AC_DEFINE_UNQUOTED($1, "$localedir",
+  [Define the location where the catalogs will be installed])
+])
+
+dnl
+dnl Now the definitions that aclocal will find
+dnl
+ifdef(glib_configure_in,[],[
+AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)])
+AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)])
+])dnl
+
+# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL])
+#
+# Create a temporary file with TEST-FILE as its contents and pass the
+# file name to PROGRAM.  Perform ACTION-IF-PASS if PROGRAM exits with
+# 0 and perform ACTION-IF-FAIL for any other exit status.
+AC_DEFUN([GLIB_RUN_PROG],
+[cat >conftest.foo <<_ACEOF
+$2
+_ACEOF
+if AC_RUN_LOG([$1 conftest.foo]); then
+  m4_ifval([$3], [$3], [:])
+m4_ifvaln([$4], [else $4])dnl
+echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD
+sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD
+fi])
+
diff --git a/common/m4/gst-arch.m4 b/common/m4/gst-arch.m4
new file mode 100644 (file)
index 0000000..077a20b
--- /dev/null
@@ -0,0 +1,140 @@
+dnl AG_GST_ARCH
+dnl sets up defines and automake conditionals for host architecture
+dnl checks endianness
+dnl defines HOST_CPU
+
+AC_DEFUN([AG_GST_ARCH],
+[
+  dnl Determine CPU
+  case "x${target_cpu}" in
+    xi?86 | xk? | xi?86_64)
+      case $target_os in
+         solaris*)
+            AC_CHECK_DECL([__i386],    [I386_ABI="yes"], [I386_ABI="no"])
+            AC_CHECK_DECL([__amd64], [AMD64_ABI="yes"], [AMD64_ABI="no"])
+
+            if test "x$I386_ABI" = "xyes" ; then
+               HAVE_CPU_I386=yes
+               AC_DEFINE(HAVE_CPU_I386, 1, [Define if the target CPU is an x86])
+            fi
+            if test "x$AMD64_ABI" = "xyes" ; then
+                HAVE_CPU_X86_64=yes
+                AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the target CPU is a x86_64])
+            fi
+            ;;
+         *)
+            HAVE_CPU_I386=yes
+            AC_DEFINE(HAVE_CPU_I386, 1, [Define if the target CPU is an x86])
+
+            dnl FIXME could use some better detection
+            dnl (ie CPUID)
+            case "x${target_cpu}" in
+              xi386 | xi486) ;;
+            *)
+              AC_DEFINE(HAVE_RDTSC, 1, [Define if RDTSC is available]) ;;
+            esac
+            ;;
+      esac
+      ;;
+    xpowerpc)
+      HAVE_CPU_PPC=yes
+      AC_DEFINE(HAVE_CPU_PPC, 1, [Define if the target CPU is a PowerPC]) ;;
+    xpowerpc64)
+      HAVE_CPU_PPC64=yes
+      AC_DEFINE(HAVE_CPU_PPC64, 1, [Define if the target CPU is a 64 bit PowerPC]) ;;
+    xalpha*)
+      HAVE_CPU_ALPHA=yes
+      AC_DEFINE(HAVE_CPU_ALPHA, 1, [Define if the target CPU is an Alpha]) ;;
+    xarm*)
+      HAVE_CPU_ARM=yes
+      AC_DEFINE(HAVE_CPU_ARM, 1, [Define if the target CPU is an ARM]) ;;
+    xsparc*)
+      HAVE_CPU_SPARC=yes
+      AC_DEFINE(HAVE_CPU_SPARC, 1, [Define if the target CPU is a SPARC]) ;;
+    xmips*)
+      HAVE_CPU_MIPS=yes
+      AC_DEFINE(HAVE_CPU_MIPS, 1, [Define if the target CPU is a MIPS]) ;;
+    xhppa*)
+      HAVE_CPU_HPPA=yes
+      AC_DEFINE(HAVE_CPU_HPPA, 1, [Define if the target CPU is a HPPA]) ;;
+    xs390*)
+      HAVE_CPU_S390=yes
+      AC_DEFINE(HAVE_CPU_S390, 1, [Define if the target CPU is a S390]) ;;
+    xia64*)
+      HAVE_CPU_IA64=yes
+      AC_DEFINE(HAVE_CPU_IA64, 1, [Define if the target CPU is a IA64]) ;;
+    xm68k*)
+      HAVE_CPU_M68K=yes
+      AC_DEFINE(HAVE_CPU_M68K, 1, [Define if the target CPU is a M68K]) ;;
+    xx86_64)
+      HAVE_CPU_X86_64=yes
+      AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the target CPU is a x86_64]) ;;
+    xcris)
+      HAVE_CPU_CRIS=yes
+      AC_DEFINE(HAVE_CPU_CRIS, 1, [Define if the target CPU is a CRIS]) ;;
+    xcrisv32)
+      HAVE_CPU_CRISV32=yes
+      AC_DEFINE(HAVE_CPU_CRISV32, 1, [Define if the target CPU is a CRISv32]) ;;
+  esac
+
+  dnl Determine endianness
+  AC_C_BIGENDIAN
+
+  AM_CONDITIONAL(HAVE_CPU_I386,       test "x$HAVE_CPU_I386" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_PPC,        test "x$HAVE_CPU_PPC" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_PPC64,      test "x$HAVE_CPU_PPC64" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_ALPHA,      test "x$HAVE_CPU_ALPHA" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_ARM,        test "x$HAVE_CPU_ARM" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_SPARC,      test "x$HAVE_CPU_SPARC" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_HPPA,       test "x$HAVE_CPU_HPPA" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_MIPS,       test "x$HAVE_CPU_MIPS" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_S390,       test "x$HAVE_CPU_S390" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_IA64,       test "x$HAVE_CPU_IA64" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_M68K,       test "x$HAVE_CPU_M68K" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_X86_64,     test "x$HAVE_CPU_X86_64" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_CRIS,       test "x$HAVE_CPU_CRIS" = "xyes")
+  AM_CONDITIONAL(HAVE_CPU_CRISV32,    test "x$HAVE_CPU_CRISV32" = "xyes")
+
+  AC_DEFINE_UNQUOTED(HOST_CPU, "$host_cpu", [the host CPU])
+  AC_DEFINE_UNQUOTED(TARGET_CPU, "$target_cpu", [the target CPU])
+])
+
+dnl check if unaligned memory access works correctly
+AC_DEFUN([AG_GST_UNALIGNED_ACCESS], [
+  AC_MSG_CHECKING([if unaligned memory access works correctly])
+  if test x"$as_cv_unaligned_access" = x ; then
+    case $host in
+      alpha*|arm*|hp*|mips*|sh*|sparc*|ia64*)
+        _AS_ECHO_N([(blacklisted) ])
+        as_cv_unaligned_access=no
+       ;;
+      i?86*|x86_64*|amd64*|powerpc*|m68k*|cris*)
+        _AS_ECHO_N([(whitelisted) ])
+        as_cv_unaligned_access=yes
+       ;;
+    esac
+  else
+    _AS_ECHO_N([(cached) ])
+  fi
+  if test x"$as_cv_unaligned_access" = x ; then
+    AC_TRY_RUN([
+int main(int argc, char **argv)
+{
+  char array[] = "ABCDEFGH";
+  unsigned int iarray[2];
+  memcpy(iarray,array,8);
+#define GET(x) (*(unsigned int *)((char *)iarray + (x)))
+  if(GET(0) != 0x41424344 && GET(0) != 0x44434241) return 1;
+  if(GET(1) != 0x42434445 && GET(1) != 0x45444342) return 1;
+  if(GET(2) != 0x43444546 && GET(2) != 0x46454443) return 1;
+  if(GET(3) != 0x44454647 && GET(3) != 0x47464544) return 1;
+  return 0;
+}
+    ], as_cv_unaligned_access="yes", as_cv_unaligned_access="no")
+  fi
+  AC_MSG_RESULT($as_cv_unaligned_access)
+  if test "$as_cv_unaligned_access" = "yes"; then
+    AC_DEFINE_UNQUOTED(HAVE_UNALIGNED_ACCESS, 1,
+      [defined if unaligned memory access works correctly])
+  fi
+])
diff --git a/common/m4/gst-args.m4 b/common/m4/gst-args.m4
new file mode 100644 (file)
index 0000000..b478c82
--- /dev/null
@@ -0,0 +1,360 @@
+dnl configure-time options shared among gstreamer modules
+
+dnl AG_GST_ARG_DEBUG
+dnl AG_GST_ARG_PROFILING
+dnl AG_GST_ARG_VALGRIND
+dnl AG_GST_ARG_GCOV
+
+dnl AG_GST_ARG_EXAMPLES
+
+dnl AG_GST_ARG_WITH_PKG_CONFIG_PATH
+dnl AG_GST_ARG_WITH_PACKAGE_NAME
+dnl AG_GST_ARG_WITH_PACKAGE_ORIGIN
+
+dnl AG_GST_ARG_WITH_PLUGINS
+dnl AG_GST_CHECK_PLUGIN
+dnl AG_GST_DISABLE_PLUGIN
+
+dnl AG_GST_ARG_ENABLE_EXTERNAL
+dnl AG_GST_ARG_ENABLE_EXPERIMENTAL
+dnl AG_GST_ARG_ENABLE_BROKEN
+
+dnl AG_GST_ARG_DISABLE_FATAL_WARNINGS
+AC_DEFUN([AG_GST_ARG_DEBUG],
+[
+  dnl debugging stuff
+  AC_ARG_ENABLE(debug,
+    AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]),
+    [
+      case "${enableval}" in
+        yes) USE_DEBUG=yes ;;
+        no)  USE_DEBUG=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+      esac
+    ],
+    [USE_DEBUG=yes]) dnl Default value
+])
+
+AC_DEFUN([AG_GST_ARG_PROFILING],
+[
+  AC_ARG_ENABLE(profiling,
+    AC_HELP_STRING([--enable-profiling],
+      [adds -pg to compiler commandline, for profiling]),
+    [
+      case "${enableval}" in
+        yes) USE_PROFILING=yes ;;
+        no)  USE_PROFILING=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-profiling) ;;
+      esac
+    ],
+    [USE_PROFILING=no]) dnl Default value
+])
+
+AC_DEFUN([AG_GST_ARG_VALGRIND],
+[
+  dnl valgrind inclusion
+  AC_ARG_ENABLE(valgrind,
+    AC_HELP_STRING([--disable-valgrind],[disable run-time valgrind detection]),
+    [
+      case "${enableval}" in
+        yes) USE_VALGRIND="$USE_DEBUG" ;;
+        no)  USE_VALGRIND=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;;
+      esac
+    ],
+    [USE_VALGRIND="$USE_DEBUG"]) dnl Default value
+  VALGRIND_REQ="3.0"
+  if test "x$USE_VALGRIND" = xyes; then
+    PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ,
+      USE_VALGRIND="yes",
+      USE_VALGRIND="no")
+  fi
+  if test "x$USE_VALGRIND" = xyes; then
+    AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used])
+    AC_MSG_NOTICE(Using extra code paths for valgrind)
+  fi
+])
+
+AC_DEFUN([AG_GST_ARG_GCOV],
+[
+  AC_ARG_ENABLE(gcov,
+    AC_HELP_STRING([--enable-gcov],
+      [compile with coverage profiling instrumentation (gcc only)]),
+    enable_gcov=$enableval,
+    enable_gcov=no)
+  if test x$enable_gcov = xyes ; then
+    if test "x$GCC" != "xyes"
+    then
+      AC_MSG_ERROR([gcov only works if gcc is used])
+    fi
+
+    AS_COMPILER_FLAG(["-fprofile-arcs"],
+      [GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs"],
+      true)
+    AS_COMPILER_FLAG(["-ftest-coverage"],
+      [GCOV_CFLAGS="$GCOV_CFLAGS -ftest-coverage"],
+      true)
+    dnl remove any -O flags - FIXME: is this needed ?
+    GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[[0-9]]*//g'`
+    dnl libtool 1.5.22 and lower strip -fprofile-arcs from the flags
+    dnl passed to the linker, which is a bug; -fprofile-arcs implicitly
+    dnl links in -lgcov, so we do it explicitly here for the same effect
+    GCOV_LIBS=-lgcov
+    AC_SUBST(GCOV_CFLAGS)
+    AC_SUBST(GCOV_LIBS)
+    GCOV=`echo $CC | sed s/gcc/gcov/g`
+    AC_SUBST(GCOV)
+
+    GST_GCOV_ENABLED=yes
+    AC_DEFINE_UNQUOTED(GST_GCOV_ENABLED, 1,
+      [Defined if gcov is enabled to force a rebuild due to config.h changing])
+    dnl if gcov is used, we do not want default -O2 CFLAGS
+    if test "x$GST_GCOV_ENABLED" = "xyes"
+    then
+      CFLAGS="$CFLAGS -O0"
+      AC_SUBST(CFLAGS)
+      CXXFLAGS="$CXXFLAGS -O0"
+      AC_SUBST(CXXFLAGS)
+      FFLAGS="$FFLAGS -O0"
+      AC_SUBST(FFLAGS)
+      CCASFLAGS="$CCASFLAGS -O0"
+      AC_SUBST(CCASFLAGS)
+      AC_MSG_NOTICE([gcov enabled, setting CFLAGS and friends to $CFLAGS])
+    fi
+  fi
+  AM_CONDITIONAL(GST_GCOV_ENABLED, test x$enable_gcov = xyes)
+])
+
+AC_DEFUN([AG_GST_ARG_EXAMPLES],
+[
+  AC_ARG_ENABLE(examples,
+    AC_HELP_STRING([--disable-examples], [disable building examples]),
+      [
+        case "${enableval}" in
+          yes) BUILD_EXAMPLES=yes ;;
+          no)  BUILD_EXAMPLES=no ;;
+          *)   AC_MSG_ERROR(bad value ${enableval} for --disable-examples) ;;
+        esac
+      ],
+      [BUILD_EXAMPLES=yes]) dnl Default value
+  AM_CONDITIONAL(BUILD_EXAMPLES,      test "x$BUILD_EXAMPLES" = "xyes")
+])
+
+AC_DEFUN([AG_GST_ARG_WITH_PKG_CONFIG_PATH],
+[
+  dnl possibly modify pkg-config path
+  AC_ARG_WITH(pkg-config-path,
+     AC_HELP_STRING([--with-pkg-config-path],
+                    [colon-separated list of pkg-config(1) dirs]),
+     [
+       export PKG_CONFIG_PATH=${withval}
+       AC_MSG_NOTICE(Set PKG_CONFIG_PATH to $PKG_CONFIG_PATH)
+     ])
+])
+
+
+dnl This macro requires that GST_GIT or GST_CVS is set to yes or no (release)
+AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_NAME],
+[
+  dnl package name in plugins
+  AC_ARG_WITH(package-name,
+    AC_HELP_STRING([--with-package-name],
+      [specify package name to use in plugins]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;;
+        *)   GST_PACKAGE_NAME="${withval}" ;;
+      esac
+    ],
+    [
+      P=$1
+      if test "x$P" = "x"
+      then
+        P=$PACKAGE_NAME
+      fi
+
+      if test "x$PACKAGE_VERSION_NANO" = "x0"
+      then
+        GST_PACKAGE_NAME="$P source release"
+      else
+        if test "x$PACKAGE_VERSION_NANO" = "x1"
+        then
+          GST_PACKAGE_NAME="$P git"
+        else
+          GST_PACKAGE_NAME="$P prerelease"
+        fi
+      fi
+    ]
+  )
+  AC_MSG_NOTICE(Using $GST_PACKAGE_NAME as package name)
+  AC_DEFINE_UNQUOTED(GST_PACKAGE_NAME, "$GST_PACKAGE_NAME",
+      [package name in plugins])
+  AC_SUBST(GST_PACKAGE_NAME)
+])
+
+AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_ORIGIN],
+[
+  dnl package origin URL
+  AC_ARG_WITH(package-origin,
+    AC_HELP_STRING([--with-package-origin],
+      [specify package origin URL to use in plugins]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;;
+        *)   GST_PACKAGE_ORIGIN="${withval}" ;;
+      esac
+    ],
+    [GST_PACKAGE_ORIGIN="[Unknown package origin]"] dnl Default value
+  )
+  AC_MSG_NOTICE(Using $GST_PACKAGE_ORIGIN as package origin)
+  AC_DEFINE_UNQUOTED(GST_PACKAGE_ORIGIN, "$GST_PACKAGE_ORIGIN",
+      [package origin])
+  AC_SUBST(GST_PACKAGE_ORIGIN)
+])
+
+dnl sets WITH_PLUGINS to the list of plug-ins given as an argument
+dnl also clears GST_PLUGINS_ALL and GST_PLUGINS_SELECTED
+AC_DEFUN([AG_GST_ARG_WITH_PLUGINS],
+[
+  AC_ARG_WITH(plugins,
+    AC_HELP_STRING([--with-plugins],
+      [comma-separated list of dependencyless plug-ins to compile]),
+    [WITH_PLUGINS=$withval],
+    [WITH_PLUGINS=])
+
+  GST_PLUGINS_ALL=""
+  GST_PLUGINS_SELECTED=""
+  GST_PLUGINS_NONPORTED=""
+
+  AC_SUBST(GST_PLUGINS_ALL)
+  AC_SUBST(GST_PLUGINS_SELECTED)
+  AC_SUBST(GST_PLUGINS_NONPORTED)
+])
+
+dnl AG_GST_CHECK_PLUGIN(PLUGIN-NAME)
+dnl
+dnl This macro adds the plug-in <PLUGIN-NAME> to GST_PLUGINS_ALL. Then it
+dnl checks if WITH_PLUGINS is empty or the plugin is present in WITH_PLUGINS,
+dnl and if so adds it to GST_PLUGINS_SELECTED. Then it checks if the plugin
+dnl is present in WITHOUT_PLUGINS (ie. was disabled specifically) and if so
+dnl removes it from GST_PLUGINS_SELECTED.
+dnl
+dnl The macro will call AM_CONDITIONAL(USE_PLUGIN_<PLUGIN-NAME>, ...) to allow
+dnl control of what is built in Makefile.ams.
+AC_DEFUN([AG_GST_CHECK_PLUGIN],
+[
+  GST_PLUGINS_ALL="$GST_PLUGINS_ALL [$1]"
+
+  define([pname_def],translit([$1], -a-z, _a-z))
+
+  AC_ARG_ENABLE([$1],
+    AC_HELP_STRING([--disable-[$1]], [disable dependency-less $1 plugin]),
+    [
+      case "${enableval}" in
+        yes) [gst_use_]pname_def=yes ;;
+        no) [gst_use_]pname_def=no ;;
+        *) AC_MSG_ERROR([bad value ${enableval} for --enable-$1]) ;;
+       esac
+    ],
+    [[gst_use_]pname_def=yes]) dnl Default value
+
+  if test x$[gst_use_]pname_def = xno; then
+    AC_MSG_NOTICE(disabling dependency-less plugin $1)
+    WITHOUT_PLUGINS="$WITHOUT_PLUGINS [$1]"
+  fi
+  undefine([pname_def])
+
+  dnl First check inclusion
+  if [[ -z "$WITH_PLUGINS" ]] || echo " [$WITH_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then
+    GST_PLUGINS_SELECTED="$GST_PLUGINS_SELECTED [$1]"
+  fi
+  dnl Then check exclusion
+  if echo " [$WITHOUT_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then
+    GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'`
+  fi
+  dnl Finally check if the plugin is ported or not
+  if echo " [$GST_PLUGINS_NONPORTED] " | tr , ' ' | grep -i " [$1] " > /dev/null; then
+    GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'`
+  fi
+  AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), echo " $GST_PLUGINS_SELECTED " | grep -i " [$1] " > /dev/null)
+])
+
+dnl AG_GST_DISABLE_PLUGIN(PLUGIN-NAME)
+dnl
+dnl This macro disables the plug-in <PLUGIN-NAME> by removing it from
+dnl GST_PLUGINS_SELECTED.
+AC_DEFUN([AG_GST_DISABLE_PLUGIN],
+[
+  GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'`
+  AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), false)
+])
+
+AC_DEFUN([AG_GST_ARG_ENABLE_EXTERNAL],
+[
+  AG_GST_CHECK_FEATURE(EXTERNAL, [building of plug-ins with external deps],,
+    HAVE_EXTERNAL=yes, enabled,
+    [
+      AC_MSG_NOTICE(building external plug-ins)
+      BUILD_EXTERNAL="yes"
+    ],[
+      AC_MSG_WARN(all plug-ins with external dependencies will not be built)
+      BUILD_EXTERNAL="no"
+    ])
+  # make BUILD_EXTERNAL available to Makefile.am
+  AM_CONDITIONAL(BUILD_EXTERNAL, test "x$BUILD_EXTERNAL" = "xyes")
+])
+
+dnl experimental plug-ins; stuff that hasn't had the dust settle yet
+dnl read 'builds, but might not work'
+AC_DEFUN([AG_GST_ARG_ENABLE_EXPERIMENTAL],
+[
+  AG_GST_CHECK_FEATURE(EXPERIMENTAL, [building of experimental plug-ins],,
+    HAVE_EXPERIMENTAL=yes, disabled,
+    [
+      AC_MSG_WARN(building experimental plug-ins)
+      BUILD_EXPERIMENTAL="yes"
+    ],[
+      AC_MSG_NOTICE(not building experimental plug-ins)
+      BUILD_EXPERIMENTAL="no"
+    ])
+  # make BUILD_EXPERIMENTAL available to Makefile.am
+  AM_CONDITIONAL(BUILD_EXPERIMENTAL, test "x$BUILD_EXPERIMENTAL" = "xyes")
+])
+
+dnl broken plug-ins; stuff that doesn't seem to build at the moment
+AC_DEFUN([AG_GST_ARG_ENABLE_BROKEN],
+[
+  AG_GST_CHECK_FEATURE(BROKEN, [building of broken plug-ins],,
+    HAVE_BROKEN=yes, disabled,
+    [
+      AC_MSG_WARN([building broken plug-ins -- no bug reports on these, only patches ...])
+    ],[
+      AC_MSG_NOTICE([not building broken plug-ins])
+    ])
+])
+
+dnl allow people (or build tools) to override default behaviour
+dnl for fatal compiler warnings
+dnl Enable fatal warnings by default only for development versions
+AC_DEFUN([AG_GST_ARG_DISABLE_FATAL_WARNINGS],
+[
+  AC_ARG_ENABLE(fatal-warnings,
+    AC_HELP_STRING([--disable-fatal-warnings],
+                   [Don't turn compiler warnings into fatal errors]),
+    [
+      case "${enableval}" in
+        yes) FATAL_WARNINGS=yes ;;
+        no)  FATAL_WARNINGS=no ;;
+        *)   AC_MSG_ERROR(bad value ${enableval} for --disable-fatal-warnings) ;;
+      esac
+    ],
+    [
+      if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then
+        FATAL_WARNINGS=yes
+      else
+        FATAL_WARNINGS=no
+      fi
+    ])
+])
diff --git a/common/m4/gst-check.m4 b/common/m4/gst-check.m4
new file mode 100644 (file)
index 0000000..4277053
--- /dev/null
@@ -0,0 +1,294 @@
+dnl pkg-config-based checks for GStreamer modules and dependency modules
+
+dnl generic:
+dnl AG_GST_PKG_CHECK_MODULES([PREFIX], [WHICH], [REQUIRED])
+dnl sets HAVE_[$PREFIX], [$PREFIX]_*
+dnl AG_GST_CHECK_MODULES([PREFIX], [MODULE], [MINVER], [NAME], [REQUIRED])
+dnl sets HAVE_[$PREFIX], [$PREFIX]_*
+
+dnl specific:
+dnl AG_GST_CHECK_GST([MAJMIN], [MINVER], [REQUIRED])
+dnl   also sets/ACSUBSTs GST_TOOLS_DIR and GST_PLUGINS_DIR
+dnl AG_GST_CHECK_GST_BASE([MAJMIN], [MINVER], [REQUIRED])
+dnl AG_GST_CHECK_GST_CONTROLLER([MAJMIN], [MINVER], [REQUIRED])
+dnl AG_GST_CHECK_GST_NET([MAJMIN], [MINVER], [REQUIRED])
+dnl AG_GST_CHECK_GST_CHECK([MAJMIN], [MINVER], [REQUIRED])
+dnl AG_GST_CHECK_GST_PLUGINS_BASE([MAJMIN], [MINVER], [REQUIRED])
+dnl   also sets/ACSUBSTs GSTPB_PLUGINS_DIR
+
+AC_DEFUN([AG_GST_PKG_CHECK_MODULES],
+[
+  which="[$2]"
+  dnl not required by default, since we use this mostly for plugin deps
+  required=ifelse([$3], , "no", [$3])
+
+  PKG_CHECK_MODULES([$1], $which,
+    [
+      HAVE_[$1]="yes"
+    ],
+    [
+      HAVE_[$1]="no"
+      if test "x$required" = "xyes"; then
+        AC_MSG_ERROR($[$1]_PKG_ERRORS)
+      else
+        AC_MSG_NOTICE($[$1]_PKG_ERRORS)
+      fi
+    ])
+
+  dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7
+  dnl It gets done automatically in automake >= 1.7, which we now require
+]))
+
+AC_DEFUN([AG_GST_CHECK_MODULES],
+[
+  module=[$2]
+  minver=[$3]
+  name="[$4]"
+  required=ifelse([$5], , "yes", [$5]) dnl required by default
+
+  PKG_CHECK_MODULES([$1], $module >= $minver,
+    [
+      HAVE_[$1]="yes"
+    ],
+    [
+      HAVE_[$1]="no"
+      AC_MSG_NOTICE($[$1]_PKG_ERRORS)
+      if test "x$required" = "xyes"; then
+        AC_MSG_ERROR([no $module >= $minver ($name) found])
+      else
+        AC_MSG_NOTICE([no $module >= $minver ($name) found])
+      fi
+    ])
+
+  dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7
+  dnl It gets done automatically in automake >= 1.7, which we now require
+]))
+
+AC_DEFUN([AG_GST_CHECK_GST],
+[
+  AG_GST_CHECK_MODULES(GST, gstreamer-[$1], [$2], [GStreamer], [$3])
+  dnl allow setting before calling this macro to override
+  if test -z $GST_TOOLS_DIR; then
+    GST_TOOLS_DIR=`$PKG_CONFIG --variable=toolsdir gstreamer-[$1]`
+    if test -z $GST_TOOLS_DIR; then
+      AC_MSG_ERROR(
+        [no tools dir set in GStreamer pkg-config file, core upgrade needed.])
+    fi
+  fi
+  AC_MSG_NOTICE([using GStreamer tools in $GST_TOOLS_DIR])
+  AC_SUBST(GST_TOOLS_DIR)
+
+  dnl check for where core plug-ins got installed
+  dnl this is used for unit tests
+  dnl allow setting before calling this macro to override
+  if test -z $GST_PLUGINS_DIR; then
+    GST_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-[$1]`
+    if test -z $GST_PLUGINS_DIR; then
+      AC_MSG_ERROR(
+        [no pluginsdir set in GStreamer pkg-config file, core upgrade needed.])
+    fi
+  fi
+  AC_MSG_NOTICE([using GStreamer plug-ins in $GST_PLUGINS_DIR])
+  AC_SUBST(GST_PLUGINS_DIR)
+])
+
+AC_DEFUN([AG_GST_CHECK_GST_BASE],
+[
+  AG_GST_CHECK_MODULES(GST_BASE, gstreamer-base-[$1], [$2],
+    [GStreamer Base Libraries], [$3])
+])
+
+AC_DEFUN([AG_GST_CHECK_GST_CONTROLLER],
+[
+  AG_GST_CHECK_MODULES(GST_CONTROLLER, gstreamer-controller-[$1], [$2],
+    [GStreamer Controller Library], [$3])
+])
+
+AC_DEFUN([AG_GST_CHECK_GST_NET],
+[
+  AG_GST_CHECK_MODULES(GST_NET, gstreamer-net-[$1], [$2],
+    [GStreamer Network Library], [$3])
+])
+
+AC_DEFUN([AG_GST_CHECK_GST_CHECK],
+[
+  AG_GST_CHECK_MODULES(GST_CHECK, gstreamer-check-[$1], [$2],
+    [GStreamer Check unittest Library], [$3])
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_UNINSTALLED_SETUP([ACTION-IF-UNINSTALLED], [ACTION-IF-NOT])
+dnl
+dnl ACTION-IF-UNINSTALLED  (optional) extra actions to perform if the setup
+dnl                        is an uninstalled setup
+dnl ACTION-IF-NOT          (optional) extra actions to perform if the setup
+dnl                        is not an uninstalled setup
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_UNINSTALLED_SETUP],
+[
+  AC_MSG_CHECKING([whether this is an uninstalled GStreamer setup])
+  AC_CACHE_VAL(gst_cv_is_uninstalled_setup,[
+    gst_cv_is_uninstalled_setup=no
+    if (set -u; : $GST_PLUGIN_SYSTEM_PATH) 2>/dev/null ; then
+      if test -z "$GST_PLUGIN_SYSTEM_PATH" \
+           -a -n "$GST_PLUGIN_SCANNER"     \
+           -a -n "$GST_PLUGIN_PATH"        \
+           -a -n "$GST_REGISTRY"           \
+           -a -n "$DYLD_LIBRARY_PATH"      \
+           -a -n "$LD_LIBRARY_PATH"; then
+        gst_cv_is_uninstalled_setup=yes;
+      fi
+    fi
+  ])
+  AC_MSG_RESULT($gst_cv_is_uninstalled_setup)
+  if test "x$gst_cv_is_uninstalled_setup" = "xyes"; then
+    ifelse([$1], , :, [$1])
+  else
+    ifelse([$2], , :, [$2])
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_GST_PLUGINS_BASE([GST-API_VERSION], [MIN-VERSION], [REQUIRED])
+dnl
+dnl Sets GST_PLUGINS_BASE_CFLAGS and GST_PLUGINS_BASE_LIBS.
+dnl
+dnl Also sets GSTPB_PLUGINS_DIR (and for consistency also GST_PLUGINS_BASE_DIR)
+dnl for use in Makefile.am. This is only really needed/useful in uninstalled
+dnl setups, since in an installed setup all plugins will be found in
+dnl GST_PLUGINS_DIR anyway.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BASE],
+[
+  AG_GST_CHECK_MODULES(GST_PLUGINS_BASE, gstreamer-plugins-base-[$1], [$2],
+    [GStreamer Base Plugins], [$3])
+
+  if test "x$HAVE_GST_PLUGINS_BASE" = "xyes"; then
+    dnl check for where base plugins got installed
+    dnl this is used for unit tests
+    dnl allow setting before calling this macro to override
+    if test -z $GSTPB_PLUGINS_DIR; then
+      GSTPB_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-base-[$1]`
+      if test -z $GSTPB_PLUGINS_DIR; then
+        AC_MSG_ERROR(
+          [no pluginsdir set in GStreamer Base Plugins pkg-config file])
+      fi
+    fi
+    AC_MSG_NOTICE([using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR])
+    GST_PLUGINS_BASE_DIR="$GSTPB_PLUGINS_DIR/gst:$GSTPB_PLUGINS_DIR/sys:$GSTPB_PLUGINS_DIR/ext"
+    AC_SUBST(GST_PLUGINS_BASE_DIR)
+    AC_SUBST(GSTPB_PLUGINS_DIR)
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_GST_PLUGINS_GOOD([GST-API_VERSION], [MIN-VERSION])
+dnl
+dnl Will set GST_PLUGINS_GOOD_DIR for use in Makefile.am. Note that this will
+dnl only be set in an uninstalled setup, since -good ships no .pc file and in
+dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_GOOD],
+[
+  AG_GST_CHECK_MODULES(GST_PLUGINS_GOOD, gstreamer-plugins-good-[$1], [$2],
+    [GStreamer Good Plugins], [no])
+
+  if test "x$HAVE_GST_PLUGINS_GOOD" = "xyes"; then
+    dnl check for where good plugins got installed
+    dnl this is used for unit tests
+    dnl allow setting before calling this macro to override
+    if test -z $GST_PLUGINS_GOOD_DIR; then
+      GST_PLUGINS_GOOD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-good-[$1]`
+      if test -z $GST_PLUGINS_GOOD_DIR; then
+        AC_MSG_ERROR([no pluginsdir set in GStreamer Good Plugins pkg-config file])
+      fi
+    fi
+    AC_MSG_NOTICE([using GStreamer Good Plugins in $GST_PLUGINS_GOOD_DIR])
+    GST_PLUGINS_GOOD_DIR="$GST_PLUGINS_GOOD_DIR/gst:$GST_PLUGINS_GOOD_DIR/sys:$GST_PLUGINS_GOOD_DIR/ext"
+    AC_SUBST(GST_PLUGINS_GOOD_DIR)
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_GST_PLUGINS_UGLY([GST-API_VERSION], [MIN-VERSION])
+dnl
+dnl Will set GST_PLUGINS_UGLY_DIR for use in Makefile.am. Note that this will
+dnl only be set in an uninstalled setup, since -bad ships no .pc file and in
+dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_UGLY],
+[
+  AG_GST_CHECK_MODULES(GST_PLUGINS_UGLY, gstreamer-plugins-ugly-[$1], [$2],
+    [GStreamer Ugly Plugins], [no])
+
+  if test "x$HAVE_GST_PLUGINS_UGLY" = "xyes"; then
+    dnl check for where ugly plugins got installed
+    dnl this is used for unit tests
+    dnl allow setting before calling this macro to override
+    if test -z $GST_PLUGINS_UGLY_DIR; then
+      GST_PLUGINS_UGLY_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-ugly-[$1]`
+      if test -z $GST_PLUGINS_UGLY_DIR; then
+        AC_MSG_ERROR([no pluginsdir set in GStreamer Ugly Plugins pkg-config file])
+      fi
+    fi
+    AC_MSG_NOTICE([using GStreamer Ugly Plugins in $GST_PLUGINS_UGLY_DIR])
+    GST_PLUGINS_UGLY_DIR="$GST_PLUGINS_UGLY_DIR/gst:$GST_PLUGINS_UGLY_DIR/sys:$GST_PLUGINS_UGLY_DIR/ext"
+    AC_SUBST(GST_PLUGINS_UGLY_DIR)
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_GST_PLUGINS_BAD([GST-API_VERSION], [MIN-VERSION])
+dnl
+dnl Will set GST_PLUGINS_BAD_DIR for use in Makefile.am. Note that this will
+dnl only be set in an uninstalled setup, since -ugly ships no .pc file and in
+dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BAD],
+[
+  AG_GST_CHECK_MODULES(GST_PLUGINS_BAD, gstreamer-plugins-bad-[$1], [$2],
+    [GStreamer Bad Plugins], [no])
+
+  if test "x$HAVE_GST_PLUGINS_BAD" = "xyes"; then
+    dnl check for where bad plugins got installed
+    dnl this is used for unit tests
+    dnl allow setting before calling this macro to override
+    if test -z $GST_PLUGINS_BAD_DIR; then
+      GST_PLUGINS_BAD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-bad-[$1]`
+      if test -z $GST_PLUGINS_BAD_DIR; then
+        AC_MSG_ERROR([no pluginsdir set in GStreamer Bad Plugins pkg-config file])
+      fi
+    fi
+    AC_MSG_NOTICE([using GStreamer Bad Plugins in $GST_PLUGINS_BAD_DIR])
+    GST_PLUGINS_BAD_DIR="$GST_PLUGINS_BAD_DIR/gst:$GST_PLUGINS_BAD_DIR/sys:$GST_PLUGINS_BAD_DIR/ext"
+    AC_SUBST(GST_PLUGINS_BAD_DIR)
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_CHECK_GST_PLUGINS_LIBAV([GST-API_VERSION], [MIN-VERSION])
+dnl
+dnl Will set GST_PLUGINS_LIBAV_DIR for use in Makefile.am. Note that this will
+dnl only be set in an uninstalled setup, since -libav ships no .pc file and in
+dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_LIBAV],
+[
+  AG_GST_CHECK_MODULES(GST_PLUGINS_LIBAV, gstreamer-plugins-libav-[$1], [$2],
+    [GStreamer Libav Plugins], [no])
+
+  if test "x$HAVE_GST_PLUGINS_LIBAV" = "xyes"; then
+    dnl check for where libav plugins got installed
+    dnl this is used for unit tests
+    dnl allow setting before calling this macro to override
+    if test -z $GST_PLUGINS_LIBAV_DIR; then
+      GST_PLUGINS_LIBAV_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-libav-[$1]`
+      if test -z $GST_PLUGINS_LIBAV_DIR; then
+        AC_MSG_ERROR([no pluginsdir set in GStreamer Libav Plugins pkg-config file])
+      fi
+    fi
+    GST_PLUGINS_LIBAV_DIR="$GST_PLUGINS_LIBAV_DIR/ext/libav"
+    AC_MSG_NOTICE([using GStreamer Libav Plugins in $GST_PLUGINS_LIBAV_DIR])
+    AC_SUBST(GST_PLUGINS_LIBAV_DIR)
+  fi
+])
diff --git a/common/m4/gst-debuginfo.m4 b/common/m4/gst-debuginfo.m4
new file mode 100644 (file)
index 0000000..b48854d
--- /dev/null
@@ -0,0 +1,46 @@
+AC_DEFUN([AG_GST_DEBUGINFO], [
+AC_ARG_ENABLE(debug,
+AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]),
+[case "${enableval}" in
+  yes) USE_DEBUG=yes ;;
+  no)  USE_DEBUG=no ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+esac],
+[USE_DEBUG=yes]) dnl Default value
+
+AC_ARG_ENABLE(DEBUG,
+AC_HELP_STRING([--disable-DEBUG],[disables compilation of debugging messages]),
+[case "${enableval}" in
+  yes) ENABLE_DEBUG=yes ;;
+  no)  ENABLE_DEBUG=no ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-DEBUG) ;;
+esac],
+[ENABLE_DEBUG=yes]) dnl Default value
+if test x$ENABLE_DEBUG = xyes; then
+  AC_DEFINE(GST_DEBUG_ENABLED, 1, [Define if DEBUG statements should be compiled in])
+fi
+
+AC_ARG_ENABLE(INFO,
+AC_HELP_STRING([--disable-INFO],[disables compilation of informational messages]),
+[case "${enableval}" in
+  yes) ENABLE_INFO=yes ;;
+  no)  ENABLE_INFO=no ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-INFO) ;;
+esac],
+[ENABLE_INFO=yes]) dnl Default value
+if test x$ENABLE_INFO = xyes; then
+  AC_DEFINE(GST_INFO_ENABLED, 1, [Define if INFO statements should be compiled in])
+fi
+
+AC_ARG_ENABLE(debug-color,
+AC_HELP_STRING([--disable-debug-color],[disables color output of DEBUG and INFO output]),
+[case "${enableval}" in
+  yes) ENABLE_DEBUG_COLOR=yes ;;
+  no)  ENABLE_DEBUG_COLOR=no ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug-color) ;;
+esac],
+[ENABLE_DEBUG_COLOR=yes]) dnl Default value
+if test "x$ENABLE_DEBUG_COLOR" = xyes; then
+  AC_DEFINE(GST_DEBUG_COLOR, 1, [Define if debugging messages should be colorized])
+fi
+])
diff --git a/common/m4/gst-default.m4 b/common/m4/gst-default.m4
new file mode 100644 (file)
index 0000000..8de9756
--- /dev/null
@@ -0,0 +1,120 @@
+dnl default elements used for tests and such
+
+dnl AG_GST_DEFAULT_ELEMENTS
+
+AC_DEFUN([AG_GST_DEFAULT_ELEMENTS],
+[
+  dnl decide on default elements
+  dnl FIXME: describe where exactly this gets used
+  dnl FIXME: decide if it's a problem that this could point to sinks from
+  dnl        depending plugin modules
+  dnl FIXME: when can we just use autoaudiosrc and autovideosrc?
+  DEFAULT_AUDIOSINK="autoaudiosink"
+  DEFAULT_VIDEOSINK="autovideosink"
+  DEFAULT_AUDIOSRC="alsasrc"
+  DEFAULT_VIDEOSRC="v4l2src"
+  DEFAULT_VISUALIZER="goom"
+  case "$host" in
+    *-sun-* | *pc-solaris* )
+      DEFAULT_AUDIOSRC="sunaudiosrc"
+      ;;
+    *-darwin* )
+      DEFAULT_AUDIOSRC="osxaudiosrc"
+      ;;
+  esac
+
+  dnl Default audio sink
+  AC_ARG_WITH(default-audiosink,
+    AC_HELP_STRING([--with-default-audiosink], [specify default audio sink]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;;
+        *)   DEFAULT_AUDIOSINK="${withval}" ;;
+      esac
+    ],
+    [
+      DEFAULT_AUDIOSINK="$DEFAULT_AUDIOSINK"
+    ] dnl Default value as determined above
+  )
+  AC_MSG_NOTICE(Using $DEFAULT_AUDIOSINK as default audio sink)
+  AC_SUBST(DEFAULT_AUDIOSINK)
+  AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSINK, "$DEFAULT_AUDIOSINK",
+    [Default audio sink])
+
+  dnl Default audio source
+  AC_ARG_WITH(default-audiosrc,
+    AC_HELP_STRING([--with-default-audiosrc], [specify default audio source]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;;
+        *)   DEFAULT_AUDIOSRC="${withval}" ;;
+      esac
+    ],
+    [
+      DEFAULT_AUDIOSRC="$DEFAULT_AUDIOSRC"
+    ] dnl Default value as determined above
+  )
+  AC_MSG_NOTICE(Using $DEFAULT_AUDIOSRC as default audio source)
+  AC_SUBST(DEFAULT_AUDIOSRC)
+  AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSRC, "$DEFAULT_AUDIOSRC",
+    [Default audio source])
+
+  dnl Default video sink
+  AC_ARG_WITH(default-videosink,
+    AC_HELP_STRING([--with-default-videosink], [specify default video sink]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;;
+        *)   DEFAULT_VIDEOSINK="${withval}" ;;
+      esac
+    ],
+    [
+      DEFAULT_VIDEOSINK="$DEFAULT_VIDEOSINK"
+    ] dnl Default value as determined above
+  )
+  AC_MSG_NOTICE(Using $DEFAULT_VIDEOSINK as default video sink)
+  AC_SUBST(DEFAULT_VIDEOSINK)
+  AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSINK, "$DEFAULT_VIDEOSINK",
+    [Default video sink])
+
+  dnl Default video source
+  AC_ARG_WITH(default-videosrc,
+    AC_HELP_STRING([--with-default-videosrc], [specify default video source]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;;
+        *)   DEFAULT_VIDEOSRC="${withval}" ;;
+      esac
+    ],
+    [
+      DEFAULT_VIDEOSRC="$DEFAULT_VIDEOSRC"
+    ] dnl Default value as determined above
+  )
+  AC_MSG_NOTICE(Using $DEFAULT_VIDEOSRC as default video source)
+  AC_SUBST(DEFAULT_VIDEOSRC)
+  AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSRC, "$DEFAULT_VIDEOSRC",
+    [Default video source])
+
+    dnl Default visualizer
+  AC_ARG_WITH(default-visualizer,
+    AC_HELP_STRING([--with-default-visualizer], [specify default visualizer]),
+    [
+      case "${withval}" in
+        yes) AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;;
+        no)  AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;;
+        *)   DEFAULT_VISUALIZER="${withval}" ;;
+      esac
+    ],
+    [
+      DEFAULT_VISUALIZER="$DEFAULT_VISUALIZER"
+    ] dnl Default value as determined above
+  )
+  AC_MSG_NOTICE(Using $DEFAULT_VISUALIZER as default visualizer)
+  AC_SUBST(DEFAULT_VISUALIZER)
+  AC_DEFINE_UNQUOTED(DEFAULT_VISUALIZER, "$DEFAULT_VISUALIZER",
+    [Default visualizer])
+])
diff --git a/common/m4/gst-doc.m4 b/common/m4/gst-doc.m4
new file mode 100644 (file)
index 0000000..5d3f0fd
--- /dev/null
@@ -0,0 +1,92 @@
+AC_DEFUN([AG_GST_DOCBOOK_CHECK],
+[
+  dnl choose a location to install docbook docs in
+  if test "x$PACKAGE_TARNAME" = "x"
+  then
+    AC_MSG_ERROR([Internal error - PACKAGE_TARNAME not set])
+  fi
+  docdir="\$(datadir)/doc/$PACKAGE_TARNAME-$GST_API_VERSION"
+
+  dnl enable/disable docbook documentation building
+  AC_ARG_ENABLE(docbook,
+  AC_HELP_STRING([--enable-docbook],
+                 [use docbook to build documentation [default=no]]),,
+                 enable_docbook=no)
+
+  have_docbook=no
+
+  if test x$enable_docbook = xyes; then
+    dnl check if we actually have everything we need
+
+    dnl check for docbook tools
+    AC_CHECK_PROG(HAVE_DOCBOOK2PS, docbook2ps, yes, no)
+    AC_CHECK_PROG(HAVE_XSLTPROC, xsltproc, yes, no)
+    AC_CHECK_PROG(HAVE_JADETEX, jadetex, yes, no)
+    AC_CHECK_PROG(HAVE_PS2PDF, ps2pdf, yes, no)
+
+    dnl check if we can process docbook stuff
+    AS_DOCBOOK(have_docbook=yes, have_docbook=no)
+
+    dnl check for extra tools
+    AC_CHECK_PROG(HAVE_DVIPS, dvips, yes, no)
+    AC_CHECK_PROG(HAVE_XMLLINT, xmllint, yes, no)
+
+    AC_CHECK_PROG(HAVE_PNGTOPNM, pngtopnm, yes, no)
+    AC_CHECK_PROG(HAVE_PNMTOPS,  pnmtops,  yes, no)
+    AC_CHECK_PROG(HAVE_EPSTOPDF, epstopdf, yes, no)
+
+    dnl check if we can generate HTML
+    if test "x$HAVE_XSLTPROC" = "xyes" && \
+       test "x$enable_docbook" = "xyes" && \
+       test "x$HAVE_XMLLINT" = "xyes"; then
+      DOC_HTML=yes
+      AC_MSG_NOTICE(Will output HTML documentation)
+     else
+      DOC_HTML=no
+      AC_MSG_NOTICE(Will not output HTML documentation)
+    fi
+
+    dnl check if we can generate PS
+    if test "x$HAVE_DOCBOOK2PS" = "xyes" && \
+       test "x$enable_docbook" = "xyes" && \
+       test "x$HAVE_XMLLINT" = "xyes" && \
+       test "x$HAVE_JADETEX" = "xyes" && \
+       test "x$HAVE_DVIPS" = "xyes" && \
+       test "x$HAVE_PNGTOPNM" = "xyes" && \
+       test "x$HAVE_PNMTOPS" = "xyes"; then
+      DOC_PS=yes
+      AC_MSG_NOTICE(Will output PS documentation)
+    else
+      DOC_PS=no
+      AC_MSG_NOTICE(Will not output PS documentation)
+    fi
+
+    dnl check if we can generate PDF - using only ps2pdf
+    if test "x$DOC_PS" = "xyes" && \
+       test "x$enable_docbook" = "xyes" && \
+       test "x$HAVE_XMLLINT" = "xyes" && \
+       test "x$HAVE_PS2PDF" = "xyes"; then
+      DOC_PDF=yes
+      AC_MSG_NOTICE(Will output PDF documentation)
+    else
+      DOC_PDF=no
+      AC_MSG_NOTICE(Will not output PDF documentation)
+    fi
+
+    dnl if we don't have everything, we should disable
+    if test "x$have_docbook" != "xyes"; then
+      enable_docbook=no
+    fi
+  fi
+
+  dnl if we're going to install documentation, tell us where
+  if test "x$have_docbook" = "xyes"; then
+    AC_MSG_NOTICE(Installing documentation in $docdir)
+    AC_SUBST(docdir)
+  fi
+
+  AM_CONDITIONAL(ENABLE_DOCBOOK,      test x$enable_docbook = xyes)
+  AM_CONDITIONAL(DOC_HTML,            test x$DOC_HTML = xyes)
+  AM_CONDITIONAL(DOC_PDF,             test x$DOC_PDF = xyes)
+  AM_CONDITIONAL(DOC_PS,              test x$DOC_PS = xyes)
+])
diff --git a/common/m4/gst-dowhile.m4 b/common/m4/gst-dowhile.m4
new file mode 100644 (file)
index 0000000..069808d
--- /dev/null
@@ -0,0 +1,24 @@
+dnl
+dnl Check for working do while(0) macros. This is used by G_STMT_START
+dnl and G_STMT_END in glib/gmacros.h. Without having this defined we
+dnl get "ambigious if-else" compiler warnings when compling C++ code.
+dnl
+dnl Copied from GLib's configure.in
+dnl
+AC_DEFUN([AG_GST_CHECK_DOWHILE_MACROS],[
+
+dnl *** check for working do while(0) macros ***
+AC_CACHE_CHECK([for working do while(0) macros], _cv_g_support_dowhile_macros, [
+       AC_TRY_COMPILE([],[
+       #define STMT_START do
+       #define STMT_END while(0)
+       #define STMT_TEST STMT_START { i = 0; } STMT_END
+       int main(void) { int i = 1; STMT_TEST; return i; }],
+       [_cv_g_support_dowhile_macros=yes],
+       [_cv_g_support_dowhile_macros=no],
+       [_cv_g_support_dowhile_macros=yes])
+])
+if test x$_cv_g_support_dowhile_macros = xyes; then
+  AC_DEFINE(HAVE_DOWHILE_MACROS, 1, [define for working do while(0) macros])
+fi
+])
diff --git a/common/m4/gst-error.m4 b/common/m4/gst-error.m4
new file mode 100644 (file)
index 0000000..bce80d2
--- /dev/null
@@ -0,0 +1,298 @@
+dnl handle various error-related things
+
+dnl Thomas Vander Stichele <thomas@apestaart.org>
+dnl Tim-Philipp Müller <tim centricular net>
+
+dnl Last modification: 2008-02-18
+
+dnl AG_GST_SET_ERROR_CFLAGS([ADD-WERROR], [MORE_FLAGS])
+dnl AG_GST_SET_ERROR_CXXFLAGS([ADD-WERROR], [MORE_FLAGS])
+dnl AG_GST_SET_LEVEL_DEFAULT([IS-GIT-VERSION])
+
+
+dnl Sets WARNING_CFLAGS and ERROR_CFLAGS to something the compiler 
+dnl will accept and AC_SUBST them so they are available in Makefile
+dnl
+dnl WARNING_CFLAGS will contain flags to make the compiler emit more
+dnl   warnings.
+dnl ERROR_CFLAGS will contain flags to make those warnings fatal,
+dnl   unless ADD-WERROR is set to "no"
+dnl 
+dnl If MORE_FLAGS is set, tries to add each of the given flags
+dnl to WARNING_CFLAGS if the compiler supports them. Each flag is 
+dnl tested separately.
+dnl
+dnl These flags can be overridden at make time:
+dnl make ERROR_CFLAGS=
+AC_DEFUN([AG_GST_SET_ERROR_CFLAGS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AS_COMPILER_FLAG])
+
+  WARNING_CFLAGS=""
+  ERROR_CFLAGS=""
+
+  dnl if we support -Wall, set it unconditionally
+  AS_COMPILER_FLAG(-Wall,
+                   WARNING_CFLAGS="$WARNING_CFLAGS -Wall")
+
+  dnl Warn if declarations after statements are used (C99 extension)
+  AS_COMPILER_FLAG(-Wdeclaration-after-statement,
+        WARNING_CFLAGS="$WARNING_CFLAGS -Wdeclaration-after-statement")
+
+  dnl Warn if variable length arrays are used (C99 extension)
+  AS_COMPILER_FLAG(-Wvla,
+        WARNING_CFLAGS="$WARNING_CFLAGS -Wvla")
+
+  dnl Warn for invalid pointer arithmetic
+  AS_COMPILER_FLAG(-Wpointer-arith,
+        WARNING_CFLAGS="$WARNING_CFLAGS -Wpointer-arith")
+
+  dnl if asked for, add -Werror if supported
+  if test "x$1" != "xno"
+  then
+    AS_COMPILER_FLAG(-Werror, ERROR_CFLAGS="$ERROR_CFLAGS -Werror")
+
+    dnl if -Werror isn't suported, try -errwarn=%all (Sun Forte case)
+    if test "x$ERROR_CFLAGS" = "x"
+    then
+      AS_COMPILER_FLAG([-errwarn=%all], [
+          ERROR_CFLAGS="-errwarn=%all"
+          dnl try -errwarn=%all,no%E_EMPTY_DECLARATION,
+          dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH,
+          dnl no%E_MACRO_REDEFINED (Sun Forte case)
+          dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon
+          dnl "statement not reached" disabled because there is g_assert_not_reached () in some places
+          dnl "macro redefined" because of gst/gettext.h
+          dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'?
+          for f in 'no%E_EMPTY_DECLARATION' \
+                   'no%E_STATEMENT_NOT_REACHED' \
+                   'no%E_ARGUEMENT_MISMATCH' \
+                   'no%E_MACRO_REDEFINED' \
+                   'no%E_LOOP_NOT_ENTERED_AT_TOP'
+          do
+            AS_COMPILER_FLAG([-errwarn=%all,$f], [
+              ERROR_CFLAGS="$ERROR_CFLAGS,$f"
+            ])
+          done
+      ])
+    else
+      dnl Add -fno-strict-aliasing for GLib versions before 2.19.8
+      dnl as before G_LOCK and friends caused strict aliasing compiler
+      dnl warnings.
+      PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [
+        AS_COMPILER_FLAG(-fno-strict-aliasing,
+            ERROR_CFLAGS="$ERROR_CFLAGS -fno-strict-aliasing")
+       ])
+    fi
+  fi
+
+  if test "x$2" != "x"
+  then
+    UNSUPPORTED=""
+    list="$2"
+    for each in $list
+    do
+      AS_COMPILER_FLAG($each,
+          WARNING_CFLAGS="$WARNING_CFLAGS $each",
+          UNSUPPORTED="$UNSUPPORTED $each")
+    done
+    if test "X$UNSUPPORTED" != X ; then
+      AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED])
+    fi
+  fi
+
+  AC_SUBST(WARNING_CFLAGS)
+  AC_SUBST(ERROR_CFLAGS)
+  AC_MSG_NOTICE([set WARNING_CFLAGS to $WARNING_CFLAGS])
+  AC_MSG_NOTICE([set ERROR_CFLAGS to $ERROR_CFLAGS])
+])
+
+dnl Sets WARNING_CXXFLAGS and ERROR_CXXFLAGS to something the compiler 
+dnl will accept and AC_SUBST them so they are available in Makefile
+dnl
+dnl WARNING_CXXFLAGS will contain flags to make the compiler emit more
+dnl   warnings.
+dnl ERROR_CXXFLAGS will contain flags to make those warnings fatal,
+dnl   unless ADD-WERROR is set to "no"
+dnl 
+dnl If MORE_FLAGS is set, tries to add each of the given flags
+dnl to WARNING_CFLAGS if the compiler supports them. Each flag is 
+dnl tested separately.
+dnl
+dnl These flags can be overridden at make time:
+dnl make ERROR_CXXFLAGS=
+AC_DEFUN([AG_GST_SET_ERROR_CXXFLAGS],
+[
+  AC_REQUIRE([AC_PROG_CXX])
+  AC_REQUIRE([AS_CXX_COMPILER_FLAG])
+
+  ERROR_CXXFLAGS=""
+  WARNING_CXXFLAGS=""
+
+  dnl if we support -Wall, set it unconditionally
+  AS_CXX_COMPILER_FLAG(-Wall, WARNING_CXXFLAGS="$WARNING_CXXFLAGS -Wall")
+
+  dnl if asked for, add -Werror if supported
+  if test "x$1" != "xno"
+  then
+    AS_CXX_COMPILER_FLAG(-Werror, ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror")
+
+    if test "x$ERROR_CXXFLAGS" != "x"
+    then
+        dnl add exceptions
+        AS_CXX_COMPILER_FLAG([-Wno-non-virtual-dtor], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Wno-non-virtual-dtor")
+
+       dnl Add -fno-strict-aliasing for GLib versions before 2.19.8
+       dnl as before G_LOCK and friends caused strict aliasing compiler
+       dnl warnings.
+       PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [
+         AS_CXX_COMPILER_FLAG([-fno-strict-aliasing],
+           ERROR_CXXFLAGS="$ERROR_CXXFLAGS -fno-strict-aliasing")
+         ])
+    else
+      dnl if -Werror isn't suported, try -errwarn=%all
+      AS_CXX_COMPILER_FLAG([-errwarn=%all], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -errwarn=%all")
+      if test "x$ERROR_CXXFLAGS" != "x"; then
+        dnl try -errwarn=%all,no%E_EMPTY_DECLARATION,
+        dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH,
+        dnl no%E_MACRO_REDEFINED (Sun Forte case)
+        dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon
+        dnl "statement not reached" disabled because there is g_assert_not_reached () in some places
+        dnl "macro redefined" because of gst/gettext.h
+        dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'?
+        dnl FIXME: do any of these work with the c++ compiler? if not, why
+        dnl do we check at all?
+        for f in 'no%E_EMPTY_DECLARATION' \
+                 'no%E_STATEMENT_NOT_REACHED' \
+                 'no%E_ARGUEMENT_MISMATCH' \
+                 'no%E_MACRO_REDEFINED' \
+                 'no%E_LOOP_NOT_ENTERED_AT_TOP'
+        do
+          AS_CXX_COMPILER_FLAG([-errwarn=%all,$f], [ERROR_CXXFLAGS="$ERROR_CXXFLAGS,$f"])
+        done
+      fi
+    fi
+  fi
+
+  if test "x$2" != "x"
+  then
+    UNSUPPORTED=""
+    list="$2"
+    for each in $list
+    do
+      AS_CXX_COMPILER_FLAG($each,
+          WARNING_CXXFLAGS="$WARNING_CXXFLAGS $each",
+          UNSUPPORTED="$UNSUPPORTED $each")
+    done
+    if test "X$UNSUPPORTED" != X ; then
+      AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED])
+    fi
+  fi
+
+  AC_SUBST(WARNING_CXXFLAGS)
+  AC_SUBST(ERROR_CXXFLAGS)
+  AC_MSG_NOTICE([set WARNING_CXXFLAGS to $WARNING_CXXFLAGS])
+  AC_MSG_NOTICE([set ERROR_CXXFLAGS to $ERROR_CXXFLAGS])
+])
+
+dnl Sets WARNING_OBJCFLAGS and ERROR_OBJCFLAGS to something the compiler 
+dnl will accept and AC_SUBST them so they are available in Makefile
+dnl
+dnl WARNING_OBJCFLAGS will contain flags to make the compiler emit more
+dnl   warnings.
+dnl ERROR_OBJCFLAGS will contain flags to make those warnings fatal,
+dnl   unless ADD-WERROR is set to "no"
+dnl 
+dnl If MORE_FLAGS is set, tries to add each of the given flags
+dnl to WARNING_CFLAGS if the compiler supports them. Each flag is 
+dnl tested separately.
+dnl
+dnl These flags can be overridden at make time:
+dnl make ERROR_OBJCFLAGS=
+AC_DEFUN([AG_GST_SET_ERROR_OBJCFLAGS],
+[
+  AC_REQUIRE([AC_PROG_OBJC])
+  AC_REQUIRE([AS_OBJC_COMPILER_FLAG])
+
+  ERROR_OBJCFLAGS=""
+  WARNING_OBJCFLAGS=""
+
+  dnl if we support -Wall, set it unconditionally
+  AS_OBJC_COMPILER_FLAG(-Wall, WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS -Wall")
+
+  dnl if asked for, add -Werror if supported
+  if test "x$1" != "xno"
+  then
+    AS_OBJC_COMPILER_FLAG(-Werror, ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -Werror")
+
+    if test "x$ERROR_OBJCFLAGS" != "x"
+    then
+       dnl Add -fno-strict-aliasing for GLib versions before 2.19.8
+       dnl as before G_LOCK and friends caused strict aliasing compiler
+       dnl warnings.
+       PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [
+         AS_OBJC_COMPILER_FLAG([-fno-strict-aliasing],
+           ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -fno-strict-aliasing")
+         ])
+    else
+      dnl if -Werror isn't suported, try -errwarn=%all
+      AS_OBJC_COMPILER_FLAG([-errwarn=%all], ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS -errwarn=%all")
+      if test "x$ERROR_OBJCFLAGS" != "x"; then
+        dnl try -errwarn=%all,no%E_EMPTY_DECLARATION,
+        dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH,
+        dnl no%E_MACRO_REDEFINED (Sun Forte case)
+        dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon
+        dnl "statement not reached" disabled because there is g_assert_not_reached () in some places
+        dnl "macro redefined" because of gst/gettext.h
+        dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'?
+        dnl FIXME: do any of these work with the c++ compiler? if not, why
+        dnl do we check at all?
+        for f in 'no%E_EMPTY_DECLARATION' \
+                 'no%E_STATEMENT_NOT_REACHED' \
+                 'no%E_ARGUEMENT_MISMATCH' \
+                 'no%E_MACRO_REDEFINED' \
+                 'no%E_LOOP_NOT_ENTERED_AT_TOP'
+        do
+          AS_OBJC_COMPILER_FLAG([-errwarn=%all,$f], [ERROR_OBJCFLAGS="$ERROR_OBJCFLAGS,$f"])
+        done
+      fi
+    fi
+  fi
+
+  if test "x$2" != "x"
+  then
+    UNSUPPORTED=""
+    list="$2"
+    for each in $list
+    do
+      AS_OBJC_COMPILER_FLAG($each,
+          WARNING_OBJCFLAGS="$WARNING_OBJCFLAGS $each",
+          UNSUPPORTED="$UNSUPPORTED $each")
+    done
+    if test "X$UNSUPPORTED" != X ; then
+      AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED])
+    fi
+  fi
+
+  AC_SUBST(WARNING_OBJCFLAGS)
+  AC_SUBST(ERROR_OBJCFLAGS)
+  AC_MSG_NOTICE([set WARNING_OBJCFLAGS to $WARNING_OBJCFLAGS])
+  AC_MSG_NOTICE([set ERROR_OBJCFLAGS to $ERROR_OBJCFLAGS])
+])
+
+dnl Sets the default error level for debugging messages
+AC_DEFUN([AG_GST_SET_LEVEL_DEFAULT],
+[
+  dnl define correct errorlevel for debugging messages. We want to have
+  dnl GST_ERROR messages printed when running cvs builds
+  if test "x[$1]" = "xyes"; then
+    GST_LEVEL_DEFAULT=GST_LEVEL_ERROR
+  else
+    GST_LEVEL_DEFAULT=GST_LEVEL_NONE
+  fi
+  AC_DEFINE_UNQUOTED(GST_LEVEL_DEFAULT, $GST_LEVEL_DEFAULT,
+    [Default errorlevel to use])
+  dnl AC_SUBST so we can use it for win32/common/config.h
+  AC_SUBST(GST_LEVEL_DEFAULT)
+])
diff --git a/common/m4/gst-feature.m4 b/common/m4/gst-feature.m4
new file mode 100644 (file)
index 0000000..876215e
--- /dev/null
@@ -0,0 +1,297 @@
+dnl Perform a check for a feature for GStreamer
+dnl Richard Boulton <richard-alsa@tartarus.org>
+dnl Thomas Vander Stichele <thomas@apestaart.org> added useful stuff
+dnl Last modification: 25/06/2001
+dnl
+dnl AG_GST_CHECK_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION,
+dnl                   DEPENDENT-PLUGINS, TEST-FOR-FEATURE,
+dnl                   DISABLE-BY-DEFAULT, ACTION-IF-USE, ACTION-IF-NOTUSE)
+dnl
+dnl This macro adds a command line argument to allow the user to enable
+dnl or disable a feature, and if the feature is enabled, performs a supplied
+dnl test to check if the feature is available.
+dnl
+dnl The test should define HAVE_<FEATURE-NAME> to "yes" or "no" depending
+dnl on whether the feature is available.
+dnl
+dnl The macro will set USE_<FEATURE-NAME> to "yes" or "no" depending on
+dnl whether the feature is to be used.
+dnl Thomas changed this, so that when USE_<FEATURE-NAME> was already set
+dnl to no, then it stays that way.
+dnl
+dnl The macro will call AM_CONDITIONAL(USE_<FEATURE-NAME>, ...) to allow
+dnl the feature to control what is built in Makefile.ams.  If you want
+dnl additional actions resulting from the test, you can add them with the
+dnl ACTION-IF-USE and ACTION-IF-NOTUSE parameters.
+dnl
+dnl FEATURE-NAME        is the name of the feature, and should be in
+dnl                     purely upper case characters.
+dnl FEATURE-DESCRIPTION is used to describe the feature in help text for
+dnl                     the command line argument.
+dnl DEPENDENT-PLUGINS   lists any plug-ins which depend on this feature.
+dnl TEST-FOR-FEATURE    is a test which sets HAVE_<FEATURE-NAME> to "yes"
+dnl                     or "no" depending on whether the feature is
+dnl                     available.
+dnl DISABLE-BY-DEFAULT  if "disabled", the feature is disabled by default,
+dnl                     if any other value, the feature is enabled by default.
+dnl ACTION-IF-USE       any extra actions to perform if the feature is to be
+dnl                     used.
+dnl ACTION-IF-NOTUSE    any extra actions to perform if the feature is not to
+dnl                     be used.
+dnl
+dnl
+dnl thomas :
+dnl we also added a history.
+dnl GST_PLUGINS_YES will contain all plugins to be built
+dnl                 that were checked through AG_GST_CHECK_FEATURE
+dnl GST_PLUGINS_NO will contain those that won't be built
+
+AC_DEFUN([AG_GST_CHECK_FEATURE],
+[echo
+AC_MSG_NOTICE(*** checking feature: [$2] ***)
+if test "x[$3]" != "x"
+then
+  AC_MSG_NOTICE(*** for plug-ins: [$3] ***)
+fi
+dnl
+builtin(define, [gst_endisable], ifelse($5, [disabled], [enable], [disable]))dnl
+dnl if it is set to NO, then don't even consider it for building
+NOUSE=
+if test "x$USE_[$1]" = "xno"; then
+  NOUSE="yes"
+fi
+AC_ARG_ENABLE(translit([$1], A-Z, a-z),
+  [  ]builtin(format, --%-26s gst_endisable %s, gst_endisable-translit([$1], A-Z, a-z), [$2]ifelse([$3],,,: [$3])),
+  [ case "${enableval}" in
+      yes) USE_[$1]=yes;;
+      no) USE_[$1]=no;;
+      *) AC_MSG_ERROR(bad value ${enableval} for --enable-translit([$1], A-Z, a-z)) ;;
+    esac],
+  [ USE_$1=]ifelse($5, [disabled], [no], [yes]))           dnl DEFAULT
+
+dnl *** set it back to no if it was preset to no
+if test "x$NOUSE" = "xyes"; then
+  USE_[$1]="no"
+  AC_MSG_WARN(*** $3 pre-configured not to be built)
+fi
+NOUSE=
+
+dnl *** Check if it is ported or not
+if echo " [$GST_PLUGINS_NONPORTED] " | tr , ' ' | grep -i " [$1] " > /dev/null; then
+  USE_[$1]="no"
+  AC_MSG_WARN(*** $3 not ported)
+fi
+
+dnl *** If it's enabled
+
+if test x$USE_[$1] = xyes; then
+  dnl save compile variables before the test
+
+  gst_check_save_LIBS=$LIBS
+  gst_check_save_LDFLAGS=$LDFLAGS
+  gst_check_save_CFLAGS=$CFLAGS
+  gst_check_save_CPPFLAGS=$CPPFLAGS
+  gst_check_save_CXXFLAGS=$CXXFLAGS
+
+  HAVE_[$1]=no
+  dnl TEST_FOR_FEATURE
+  $4
+
+  LIBS=$gst_check_save_LIBS
+  LDFLAGS=$gst_check_save_LDFLAGS
+  CFLAGS=$gst_check_save_CFLAGS
+  CPPFLAGS=$gst_check_save_CPPFLAGS
+  CXXFLAGS=$gst_check_save_CXXFLAGS
+
+  dnl If it isn't found, unset USE_[$1]
+  if test x$HAVE_[$1] = xno; then
+    USE_[$1]=no
+  else
+    ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will be built: [$3])])
+  fi
+fi
+dnl *** Warn if it's disabled or not found
+if test x$USE_[$1] = xyes; then
+  ifelse([$6], , :, [$6])
+  if test "x$3" != "x"; then
+    GST_PLUGINS_YES="\t[$3]\n$GST_PLUGINS_YES"
+  fi
+  AC_DEFINE(HAVE_[$1], , [Define to enable $2]ifelse($3,,, [ (used by $3)]).)
+else
+  ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will not be built: [$3])])
+  if test "x$3" != "x"; then
+    GST_PLUGINS_NO="\t[$3]\n$GST_PLUGINS_NO"
+  fi
+  ifelse([$7], , :, [$7])
+fi
+dnl *** Define the conditional as appropriate
+AM_CONDITIONAL(USE_[$1], test x$USE_[$1] = xyes)
+])
+
+dnl Use AC_CHECK_LIB and AC_CHECK_HEADER to do both tests at once
+dnl sets HAVE_module if we have it
+dnl Richard Boulton <richard-alsa@tartarus.org>
+dnl Last modification: 26/06/2001
+dnl AG_GST_CHECK_LIBHEADER(FEATURE-NAME, LIB NAME, LIB FUNCTION, EXTRA LD FLAGS,
+dnl                     HEADER NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)
+dnl
+dnl This check was written for GStreamer: it should be renamed and checked
+dnl for portability if you decide to use it elsewhere.
+dnl
+AC_DEFUN([AG_GST_CHECK_LIBHEADER],
+[
+  AC_CHECK_LIB([$2], [$3], HAVE_[$1]=yes, HAVE_[$1]=no,[$4])
+  if test "x$HAVE_[$1]" = "xyes"; then
+    AC_CHECK_HEADER([$5], :, HAVE_[$1]=no)
+    if test "x$HAVE_[$1]" = "xyes"; then
+      dnl execute what needs to be
+      ifelse([$6], , :, [$6])
+    else
+      ifelse([$7], , :, [$7])
+    fi
+  else
+    ifelse([$7], , :, [$7])
+  fi
+  AC_SUBST(HAVE_[$1])
+]
+)
+
+dnl 2004-02-14 Thomas - changed to get set properly and use proper output
+dnl 2003-06-27 Benjamin Otte - changed to make this work with gstconfig.h
+dnl
+dnl Add a subsystem --disable flag and all the necessary symbols and substitions
+dnl
+dnl AG_GST_CHECK_SUBSYSTEM_DISABLE(SYSNAME, [subsystem name])
+dnl
+AC_DEFUN([AG_GST_CHECK_SUBSYSTEM_DISABLE],
+[
+  dnl this define will replace each literal subsys_def occurrence with
+  dnl the lowercase hyphen-separated subsystem
+  dnl e.g. if $1 is GST_DEBUG then subsys_def will be a macro with gst-debug
+  define([subsys_def],translit([$1], _A-Z, -a-z))
+
+  AC_ARG_ENABLE(subsys_def,
+    AC_HELP_STRING(--disable-subsys_def, [disable $2]),
+    [
+      case "${enableval}" in
+        yes) GST_DISABLE_[$1]=no ;;
+        no) GST_DISABLE_[$1]=yes ;;
+        *) AC_MSG_ERROR([bad value ${enableval} for --enable-subsys_def]) ;;
+       esac
+    ],
+    [GST_DISABLE_[$1]=no]) dnl Default value
+
+  if test x$GST_DISABLE_[$1] = xyes; then
+    AC_MSG_NOTICE([disabled subsystem [$2]])
+    GST_DISABLE_[$1]_DEFINE="#define GST_DISABLE_$1 1"
+  else
+    GST_DISABLE_[$1]_DEFINE="/* #undef GST_DISABLE_$1 */"
+  fi
+  AC_SUBST(GST_DISABLE_[$1]_DEFINE)
+  undefine([subsys_def])
+])
+
+
+dnl Parse gstconfig.h for feature and defines add the symbols and substitions
+dnl
+dnl AG_GST_PARSE_SUBSYSTEM_DISABLE(GST_CONFIGPATH, FEATURE)
+dnl
+AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLE],
+[
+  grep >/dev/null "#undef GST_DISABLE_$2" $1
+  if test $? = 0; then
+    GST_DISABLE_[$2]=0
+  else
+    GST_DISABLE_[$2]=1
+  fi
+  AC_SUBST(GST_DISABLE_[$2])
+])
+
+dnl Parse gstconfig.h and defines add the symbols and substitions
+dnl
+dnl GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-1.0`"/gst/gstconfig.h"
+dnl AG_GST_PARSE_SUBSYSTEM_DISABLES(GST_CONFIGPATH)
+dnl
+AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLES],
+[
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,GST_DEBUG)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,LOADSAVE)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PARSE)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,TRACE)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,ALLOC_TRACE)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,REGISTRY)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PLUGIN)
+  AG_GST_PARSE_SUBSYSTEM_DISABLE($1,XML)
+])
+
+dnl AG_GST_CHECK_GST_DEBUG_DISABLED(ACTION-IF-DISABLED, ACTION-IF-NOT-DISABLED)
+dnl
+dnl Checks if the GStreamer debugging system is disabled in the core version
+dnl we are compiling against (by checking gstconfig.h)
+dnl
+AC_DEFUN([AG_GST_CHECK_GST_DEBUG_DISABLED],
+[
+  AC_REQUIRE([AG_GST_CHECK_GST])
+
+  AC_MSG_CHECKING([whether the GStreamer debugging system is enabled])
+  AC_LANG_PUSH([C])
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$GST_CFLAGS $CFLAGS"
+  AC_COMPILE_IFELSE([
+    AC_LANG_SOURCE([[
+      #include <gst/gstconfig.h>
+      #ifdef GST_DISABLE_GST_DEBUG
+      #error "debugging disabled, make compiler fail"
+      #endif]])], [ debug_system_enabled=yes], [debug_system_enabled=no])
+  CFLAGS="$save_CFLAGS"
+  AC_LANG_POP([C])
+
+  AC_MSG_RESULT([$debug_system_enabled])
+
+  if test "x$debug_system_enabled" = "xyes" ; then
+    $2
+    true
+  else
+    $1
+    true
+  fi
+])
+
+dnl relies on GST_PLUGINS_ALL, GST_PLUGINS_SELECTED, GST_PLUGINS_YES,
+dnl GST_PLUGINS_NO, and BUILD_EXTERNAL
+AC_DEFUN([AG_GST_OUTPUT_PLUGINS], [
+
+printf "configure: *** Plug-ins without external dependencies that will be built:\n"
+( for i in $GST_PLUGINS_SELECTED; do printf '\t'$i'\n'; done ) | sort
+printf "\n"
+
+printf "configure: *** Plug-ins without external dependencies that will NOT be built:\n"
+( for i in $GST_PLUGINS_ALL; do
+    case " $GST_PLUGINS_SELECTED " in
+      *\ $i\ *)
+       ;;
+      *)
+       printf '\t'$i'\n'
+       ;;
+    esac
+  done ) | sort
+printf "\n"
+
+printf "configure: *** Plug-ins that have NOT been ported:\n"
+( for i in $GST_PLUGINS_NONPORTED; do
+       printf '\t'$i'\n'
+  done ) | sort
+printf "\n"
+
+if test "x$BUILD_EXTERNAL" = "xno"; then
+  printf "configure: *** No plug-ins with external dependencies will be built\n"
+else
+  printf "configure: *** Plug-ins with dependencies that will be built:"
+  printf "$GST_PLUGINS_YES\n" | sort
+  printf "\n"
+  printf "configure: *** Plug-ins with dependencies that will NOT be built:"
+  printf "$GST_PLUGINS_NO\n" | sort
+  printf "\n"
+fi
+])
+
diff --git a/common/m4/gst-function.m4 b/common/m4/gst-function.m4
new file mode 100644 (file)
index 0000000..61adfd3
--- /dev/null
@@ -0,0 +1,63 @@
+dnl
+dnl Check for compiler mechanism to show functions in debugging
+dnl copied from an Ali patch floating on the internet
+dnl
+AC_DEFUN([AG_GST_CHECK_FUNCTION],[
+  dnl #1: __PRETTY_FUNCTION__
+  AC_MSG_CHECKING(whether $CC implements __PRETTY_FUNCTION__)
+  AC_CACHE_VAL(gst_cv_have_pretty_function,[
+    AC_TRY_LINK([#include <stdio.h>],
+                [printf("%s", __PRETTY_FUNCTION__);],
+                gst_cv_have_pretty_function=yes,
+                gst_cv_have_pretty_function=no)
+  ])
+  AC_MSG_RESULT($gst_cv_have_pretty_function)
+  if test "$gst_cv_have_pretty_function" = yes; then
+    AC_DEFINE(HAVE_PRETTY_FUNCTION, 1,
+              [defined if the compiler implements __PRETTY_FUNCTION__])
+  fi
+
+dnl #2: __FUNCTION__
+  AC_MSG_CHECKING(whether $CC implements __FUNCTION__)
+  AC_CACHE_VAL(gst_cv_have_function,[
+    AC_TRY_LINK([#include <stdio.h>],
+                [printf("%s", __FUNCTION__);],
+                gst_cv_have_function=yes,
+                gst_cv_have_function=no)
+  ])
+  AC_MSG_RESULT($gst_cv_have_function)
+  if test "$gst_cv_have_function" = yes; then
+    AC_DEFINE(HAVE_FUNCTION, 1,
+              [defined if the compiler implements __FUNCTION__])
+  fi
+
+dnl #3: __func__
+  AC_MSG_CHECKING(whether $CC implements __func__)
+  AC_CACHE_VAL(gst_cv_have_func,[
+    AC_TRY_LINK([#include <stdio.h>],
+                [printf("%s", __func__);],
+                gst_cv_have_func=yes,
+                gst_cv_have_func=no)
+  ])
+  AC_MSG_RESULT($gst_cv_have_func)
+  if test "$gst_cv_have_func" = yes; then
+    AC_DEFINE(HAVE_FUNC, 1,
+              [defined if the compiler implements __func__])
+  fi
+
+dnl now define FUNCTION to whatever works, and fallback to ""
+  if test "$gst_cv_have_pretty_function" = yes; then
+    function=__PRETTY_FUNCTION__
+  else
+    if test "$gst_cv_have_function" = yes; then
+      function=__FUNCTION__
+    else
+      if test "$gst_cv_have_func" = yes; then
+        function=__func__
+      else
+        function=\"\"
+      fi
+    fi
+  fi
+  AC_DEFINE_UNQUOTED(GST_FUNCTION, $function, [macro to use to show function name])
+])
diff --git a/common/m4/gst-gettext.m4 b/common/m4/gst-gettext.m4
new file mode 100644 (file)
index 0000000..df817eb
--- /dev/null
@@ -0,0 +1,28 @@
+dnl gettext setup
+
+dnl AG_GST_GETTEXT([gettext-package])
+dnl defines GETTEXT_PACKAGE and LOCALEDIR
+
+AC_DEFUN([AG_GST_GETTEXT],
+[
+  if test "$USE_NLS" = "yes"; then
+    GETTEXT_PACKAGE=[$1]
+  else
+    GETTEXT_PACKAGE=[NULL]
+  fi
+  AC_SUBST(GETTEXT_PACKAGE)
+  AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], "$GETTEXT_PACKAGE",
+                     [gettext package name])
+
+  dnl make sure po/Makevars is kept in sync with GETTEXT_PACKAGE
+  if test -e "${srcdir}/po/Makevars"; then
+    if ! grep -e "$1" "${srcdir}/po/Makevars"; then
+      AC_MSG_ERROR([DOMAIN in po/Makevars does not match GETTEXT_PACKAGE $1])
+    fi
+  fi
+
+  dnl define LOCALEDIR in config.h
+  AS_AC_EXPAND(LOCALEDIR, $datadir/locale)
+  AC_DEFINE_UNQUOTED([LOCALEDIR], "$LOCALEDIR",
+                     [gettext locale dir])
+])
diff --git a/common/m4/gst-glib2.m4 b/common/m4/gst-glib2.m4
new file mode 100644 (file)
index 0000000..63f0f46
--- /dev/null
@@ -0,0 +1,126 @@
+dnl check for a minimum version of GLib
+
+dnl AG_GST_GLIB_CHECK([minimum-version-required])
+
+AC_DEFUN([AG_GST_GLIB_CHECK],
+[
+  AC_REQUIRE([AS_NANO])
+
+  dnl Minimum required version of GLib
+  GLIB_REQ=[$1]
+  if test "x$GLIB_REQ" = "x"
+  then
+    AC_MSG_ERROR([Please specify a required version for GLib 2.0])
+  fi
+  AC_SUBST(GLIB_REQ)
+
+  dnl Check for glib with everything
+  AG_GST_PKG_CHECK_MODULES(GLIB,
+    glib-2.0 >= $GLIB_REQ gobject-2.0 gmodule-no-export-2.0)
+
+  if test "x$HAVE_GLIB" = "xno"; then
+    AC_MSG_ERROR([This package requires GLib >= $GLIB_REQ to compile.])
+  fi
+
+  dnl Add define to tell GLib that threading is always enabled within GStreamer
+  dnl code (optimisation, bypasses checks if the threading system is enabled
+  dnl when using threading primitives)
+  GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_THREADS_MANDATORY"
+
+  dnl Define G_DISABLE_DEPRECATED for development versions
+  if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then
+    GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_DEPRECATED"
+  fi
+
+  AC_ARG_ENABLE(gobject-cast-checks,
+    AS_HELP_STRING([--enable-gobject-cast-checks[=@<:@no/auto/yes@:>@]],
+      [Enable GObject cast checks]),[enable_gobject_cast_checks=$enableval],
+    [enable_gobject_cast_checks=auto])
+
+  if test "x$enable_gobject_cast_checks" = "xauto"; then
+    dnl Turn on cast checks only for development versions
+    if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then
+      enable_gobject_cast_checks=yes
+    else
+      enable_gobject_cast_checks=no
+    fi
+  fi
+
+  if test "x$enable_gobject_cast_checks" = "xno"; then
+    GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_CAST_CHECKS"
+  fi
+
+  AC_ARG_ENABLE(glib-asserts,
+    AS_HELP_STRING([--enable-glib-asserts[=@<:@no/auto/yes@:>@]],
+      [Enable GLib assertion]),[enable_glib_assertions=$enableval],
+    [enable_glib_assertions=auto])
+
+  if test "x$enable_glib_assertions" = "xauto"; then
+    dnl Enable assertions only for development versions
+    if test "x`expr $PACKAGE_VERSION_MINOR % 2`" = "x1" -a "x`expr $PACKAGE_VERSION_MICRO '<' 90`" = "x1"; then
+      enable_glib_assertions=yes
+    else
+      enable_glib_assertions=no
+    fi
+  fi
+
+  if test "x$enable_glib_assertions" = "xno"; then
+    GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_ASSERT"
+  fi
+
+  dnl Find location of glib utils. People may want to or have to override these,
+  dnl e.g. in a cross-compile situation where PATH is a bit messed up. We need
+  dnl for these tools to work on the host, so can't just use the one from the
+  dnl GLib installation that pkg-config picks up, as that might be for a
+  dnl different target architecture.
+  dnl
+  dnl glib-genmarshal:
+  AC_MSG_CHECKING(for glib-genmarshal)
+  if test "x$GLIB_GENMARSHAL" != "x"; then
+    AC_MSG_RESULT([$GLIB_GENMARSHAL (from environment)])
+  else
+    GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
+    if $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then
+      AC_MSG_RESULT([$GLIB_GENMARSHAL (from pkg-config path)])
+    else
+      AC_PATH_PROG(GLIB_GENMARSHAL, [glib-genmarshal], [glib-genmarshal])
+      AC_MSG_RESULT([$GLIB_GENMARSHAL])
+    fi
+  fi
+  if ! $GLIB_GENMARSHAL --version 2>/dev/null >/dev/null; then
+    AC_MSG_WARN([$GLIB_GENMARSHAL does not seem to work!])
+  fi
+  AC_SUBST(GLIB_GENMARSHAL)
+
+  dnl glib-mkenums:
+  AC_MSG_CHECKING(for glib-mkenums)
+  if test "x$GLIB_MKENUMS" != "x"; then
+    AC_MSG_RESULT([$GLIB_MKENUMS (from environment)])
+  else
+    dnl glib-mkenums is written in perl so should always work really
+    GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
+    AC_MSG_RESULT([$GLIB_MKENUMS])
+  fi
+  if ! $GLIB_MKENUMS --version 2>/dev/null >/dev/null; then
+    AC_MSG_WARN([$GLIB_MKENUMS does not seem to work!])
+  fi
+  AC_SUBST(GLIB_MKENUMS)
+
+  AC_SUBST(GLIB_EXTRA_CFLAGS)
+
+  dnl Now check for GIO
+  PKG_CHECK_MODULES(GIO, gio-2.0 >= $GLIB_REQ)
+  if test "x$HAVE_GIO" = "xno"; then
+    AC_MSG_ERROR([This package requires GIO >= $GLIB_REQ to compile.])
+  fi
+  
+  GIO_MODULE_DIR="`$PKG_CONFIG --variable=giomoduledir gio-2.0`"
+  AC_DEFINE_UNQUOTED(GIO_MODULE_DIR, "$GIO_MODULE_DIR",
+      [The GIO modules directory.])
+  GIO_LIBDIR="`$PKG_CONFIG --variable=libdir gio-2.0`"
+  AC_DEFINE_UNQUOTED(GIO_LIBDIR, "$GIO_LIBDIR",
+      [The GIO library directory.])
+  AC_SUBST(GIO_CFLAGS)
+  AC_SUBST(GIO_LIBS)
+  AC_SUBST(GIO_LDFLAGS)
+])
diff --git a/common/m4/gst-libxml2.m4 b/common/m4/gst-libxml2.m4
new file mode 100644 (file)
index 0000000..4a843f0
--- /dev/null
@@ -0,0 +1,52 @@
+dnl call this macro with the minimum required version as an argument
+dnl this macro sets and AC_SUBSTs XML_CFLAGS and XML_LIBS
+dnl it also sets LIBXML_PKG, used for the pkg-config file
+
+AC_DEFUN([AG_GST_LIBXML2_CHECK],
+[
+  dnl Minimum required version of libxml2
+  dnl default to 2.4.9 if not specified
+  LIBXML2_REQ=ifelse([$1],,2.4.9,[$1])
+  AC_SUBST(LIBXML2_REQ)
+
+  dnl check for libxml2
+  PKG_CHECK_MODULES(XML, libxml-2.0 >= $LIBXML2_REQ,
+                    HAVE_LIBXML2=yes, [
+                      AC_MSG_RESULT(no)
+                      HAVE_LIBXML2=no
+                    ])
+  if test "x$HAVE_LIBXML2" = "xyes"; then
+    AC_DEFINE(HAVE_LIBXML2, 1, [Define if libxml2 is available])
+  else
+    AC_MSG_ERROR([
+        Need libxml2 and development headers/files to build GStreamer.
+
+        You can do without libxml2 if you pass --disable-loadsave to
+        configure, but that breaks ABI, so don't do that unless you
+        are building for an embedded setup and know what you are doing.
+    ])
+  fi
+  dnl this is for the .pc file
+  LIBXML_PKG=', libxml-2.0'
+  AC_SUBST(LIBXML_PKG)
+  AC_SUBST(XML_LIBS)
+  AC_SUBST(XML_CFLAGS)
+
+  dnl XML_LIBS might pull in -lz without zlib actually being on the system, so
+  dnl try linking with these LIBS and CFLAGS
+  ac_save_CFLAGS=$CFLAGS
+  ac_save_LIBS=$LIBS
+  CFLAGS="$CFLAGS $XML_CFLAGS"
+  LIBS="$LIBS $XML_LIBS"
+  AC_TRY_LINK([
+#include <libxml/tree.h>
+#include <stdio.h>
+],[
+/* function body */
+],
+    AC_MSG_NOTICE([Test xml2 program linked]),
+    AC_MSG_ERROR([Could not link libxml2 test program.  Check if you have the necessary dependencies.])
+  )
+  CFLAGS="$ac_save_CFLAGS"
+  LIBS="$ac_save_LIBS"
+])
diff --git a/common/m4/gst-package-release-datetime.m4 b/common/m4/gst-package-release-datetime.m4
new file mode 100644 (file)
index 0000000..bc885e3
--- /dev/null
@@ -0,0 +1,89 @@
+dnl macros to set GST_PACKAGE_RELEASE_DATETIME
+
+dnl ===========================================================================
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME
+dnl
+dnl Usage:
+dnl
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME()
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no]...)
+dnl sets the release datetime to the current date
+dnl (no = this is not a release, but git or prerelease)
+dnl
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD])
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [YYYY-MM-DD])
+dnl sets the release datetime to the specified date (and time, if given)
+dnl (yes = this is a release, not git or prerelease)
+dnl
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [DOAP-FILE], [RELEASE-VERSION])
+dnl sets the release date to the release date associated with version
+dnl RELEASE-VERSION in the .doap file DOAP-FILE
+dnl (yes = this is a release, not git or prerelease)
+dnl
+dnl We need to treat pre-releases like git because there won't be an entry
+dnl in the .doap file for pre-releases yet, and we don't want to use the
+dnl date of the last release either.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME],
+[
+  dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME()
+  dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes]...)
+  if test "x$1" = "xno" -o "x$1" = "x"; then
+    GST_PACKAGE_RELEASE_DATETIME=`date -u "+%Y-%m-%dT%H:%MZ"`
+  elif test "x$1" = "xyes"; then
+    dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], ["YYYY-MM-DD"])
+    dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], [DOAP-FILE], [RELEASE-VERSION])
+    if ( echo $1 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then
+      GST_PACKAGE_RELEASE_DATETIME=$1
+    else
+      dnl we assume the .doap file contains the date as YYYY-MM-DD
+      YYYY_MM_DD=`sh "${srcdir}/common/extract-release-date-from-doap-file" $3 $2`;
+      if test "x$YYYY_MM_DD" != "x"; then
+        GST_PACKAGE_RELEASE_DATETIME=$YYYY_MM_DD
+      else
+        AC_MSG_ERROR([SET_PACKAGE_RELEASE_DATETIME: could not extract
+            release date for release version $3 from $2])
+        GST_PACKAGE_RELEASE_DATETIME=""
+      fi
+    fi
+  dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD])
+  elif ( echo $1 | grep '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then
+    GST_PACKAGE_RELEASE_DATETIME=$1
+  else
+    AC_MSG_WARN([SET_PACKAGE_RELEASE_DATETIME: invalid first argument])
+    GST_PACKAGE_RELEASE_DATETIME=""
+  fi
+
+  if test "x$GST_PACKAGE_RELEASE_DATETIME" = "x"; then
+    AC_MSG_WARN([Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME])
+  else
+    AC_MSG_NOTICE([Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME])
+
+    AC_DEFINE_UNQUOTED([GST_PACKAGE_RELEASE_DATETIME],
+        ["$GST_PACKAGE_RELEASE_DATETIME"],
+        [GStreamer package release date/time for plugins as YYYY-MM-DD])
+  fi
+])
+
+dnl ===========================================================================
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO
+dnl
+dnl Usage:
+dnl
+dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([NANO-VERSION], [DOAP-FILE], [RELEASE-VERSION])
+dnl if NANO-VERSION is 0, sets the release date to the release date associated
+dnl with version RELEASE-VERSION in the .doap file DOAP-FILE, otherwise sets
+dnl the release date and time to the current date/time.
+dnl
+dnl We need to treat pre-releases like git because there won't be an entry
+dnl in the .doap file for pre-releases yet, and we don't want to use the
+dnl date of the last release either.
+dnl ===========================================================================
+AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO],
+[
+  if test "x$1" = "x0"; then
+    AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [ $2 ], [ $3 ])
+  else
+    AG_GST_SET_PACKAGE_RELEASE_DATETIME([no])
+  fi
+])
diff --git a/common/m4/gst-parser.m4 b/common/m4/gst-parser.m4
new file mode 100644 (file)
index 0000000..b002047
--- /dev/null
@@ -0,0 +1,55 @@
+AC_DEFUN([AG_GST_BISON_CHECK],
+[
+  dnl FIXME: check if AC_PROG_YACC is suitable here
+  dnl FIXME: make precious
+  AC_PATH_PROG(BISON_PATH, bison, no)
+  if test x$BISON_PATH = xno; then
+    AC_MSG_ERROR(Could not find bison)
+  fi
+
+  dnl check bison version
+  dnl we need version >= 2.4 for the '<>' support
+  dnl in the parser.
+  dnl First lines observed: 'bison (GNU Bison) 2.3' or 'GNU Bison version 1.28'
+  bison_min_version=2.4
+  bison_version=`$BISON_PATH --version | head -n 1 |  sed 's/^[[^0-9]]*//' | sed 's/[[^0-9]]*$//' | cut -d' ' -f1`
+  AC_MSG_CHECKING([bison version $bison_version >= $bison_min_version])
+
+  if perl -we "exit ((v$bison_version ge v$bison_min_version) ? 0 : 1)"; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_ERROR([no])
+  fi
+])
+
+AC_DEFUN([AG_GST_FLEX_CHECK],
+[
+  dnl we require flex for building the parser
+  AC_PATH_PROG(FLEX_PATH, flex, no)
+  if test x$FLEX_PATH = xno; then
+    AC_MSG_ERROR(Could not find flex)
+  fi
+
+  dnl check flex version
+  dnl we need version >= 2.5.31 for the reentrancy support
+  dnl in the parser.
+  flex_min_version=2.5.31
+  flex_version=`$FLEX_PATH --version | head -n 1 | awk '{print $2}'`
+  AC_MSG_CHECKING([flex version $flex_version >= $flex_min_version])
+  if perl -w <<EOF
+    (\$min_version_major, \$min_version_minor, \$min_version_micro ) = "$flex_min_version" =~ /(\d+)\.(\d+)\.(\d+)/;
+    (\$flex_version_major, \$flex_version_minor, \$flex_version_micro ) = "$flex_version" =~ /(\d+)\.(\d+)\.(\d+)/;
+    exit (((\$flex_version_major > \$min_version_major) ||
+     ((\$flex_version_major == \$min_version_major) &&
+      (\$flex_version_minor > \$min_version_minor)) ||
+     ((\$flex_version_major == \$min_version_major) &&
+      (\$flex_version_minor == \$min_version_minor) &&
+      (\$flex_version_micro >= \$min_version_micro)))
+     ? 0 : 1);
+EOF
+  then
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_ERROR([no])
+  fi
+])
diff --git a/common/m4/gst-platform.m4 b/common/m4/gst-platform.m4
new file mode 100644 (file)
index 0000000..40d6faf
--- /dev/null
@@ -0,0 +1,67 @@
+dnl AG_GST_PLATFORM
+dnl Check for platform specific features and define some variables
+dnl
+dnl GST_EXTRA_MODULE_SUFFIX: contains a platform specific
+dnl   extra module suffix additional to G_MODULE_SUFFIX
+dnl
+dnl HAVE_OSX: Defined if compiling for OS X
+dnl
+dnl GST_HAVE_UNSAFE_FORK: Defined if fork is unsafe (Windows)
+dnl
+dnl HAVE_WIN32: Defined if compiling on Win32
+dnl
+
+AC_DEFUN([AG_GST_PLATFORM],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case $host_os in
+    rhapsody*)
+      AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix])
+      ;;
+    darwin*)
+      AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix])
+      AC_DEFINE_UNQUOTED(HAVE_OSX, 1, [Defined if compiling for OSX])
+      ;;
+    cygwin*)
+      AC_DEFINE_UNQUOTED(GST_HAVE_UNSAFE_FORK, 1, [Defined when registry scanning through fork is unsafe])
+      ;;
+    mingw* | msvc* | mks*)
+      dnl HAVE_WIN32 currently means "disable POSIXisms".
+      AC_DEFINE_UNQUOTED(HAVE_WIN32, 1, [Defined if compiling for Windows])
+
+      dnl define __MSVCRT_VERSION__ version if not set already by the
+      dnl compiler (ie. mostly for mingw). This is needed for things like
+      dnl __stat64 to be available. If set by the compiler, ensure it's
+      dnl new enough - we need at least WinXP SP2.
+      AC_TRY_COMPILE([ ], [ return __MSVCRT_VERSION__; ], [
+          AC_TRY_COMPILE([ ], [
+            #if __MSVCRT_VERSION__ < 0x0601
+            #error "MSVCRT too old"
+            #endif
+          ], [
+            AC_MSG_NOTICE([MSVCRT version looks ok])
+          ], [
+            AC_MSG_ERROR([MSVCRT version too old, need at least WinXP SP2])
+          ])
+      ], [
+        AC_MSG_NOTICE([Setting MSVCRT version to 0x0601])
+        AC_DEFINE_UNQUOTED(__MSVCRT_VERSION__, 0x0601, [We need at least WinXP SP2 for __stat64])
+      ])
+      ;;
+     *)
+      ;;
+  esac
+])
+
+AC_DEFUN([AG_GST_LIBTOOL_PREPARE],
+[
+  dnl Persuade libtool to also link (-l) a 'pure' (DirectX) static lib,
+  dnl i.e. as opposed to only import lib with dll counterpart.
+  dnl Needs to be tweaked before libtool's checks.
+  case $host_os in
+  cygwin* | mingw*)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+])
\ No newline at end of file
diff --git a/common/m4/gst-plugin-docs.m4 b/common/m4/gst-plugin-docs.m4
new file mode 100644 (file)
index 0000000..0e2ab6e
--- /dev/null
@@ -0,0 +1,25 @@
+dnl AG_GST_PLUGIN_DOCS([MINIMUM-GTK-DOC-VERSION])
+dnl
+dnl checks for prerequisites for the common/mangle-tmpl.py script
+dnl used when building the plugin documentation
+
+AC_DEFUN([AG_GST_PLUGIN_DOCS],
+[
+  AC_BEFORE([GTK_DOC_CHECK],[$0])dnl check for gtk-doc first
+  AC_REQUIRE([AM_PATH_PYTHON])dnl find python first
+
+  build_plugin_docs=no
+  AC_MSG_CHECKING([whether to build plugin documentation])
+  if test x$enable_gtk_doc = xyes; then
+    if test x$PYTHON != x; then
+      build_plugin_docs=yes
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no (python not found)])
+    fi
+  else
+    AC_MSG_RESULT([no (gtk-doc disabled or not available)])
+  fi
+
+  AM_CONDITIONAL(ENABLE_PLUGIN_DOCS, test x$build_plugin_docs = xyes)
+])
diff --git a/common/m4/gst-plugindir.m4 b/common/m4/gst-plugindir.m4
new file mode 100644 (file)
index 0000000..c9e1301
--- /dev/null
@@ -0,0 +1,17 @@
+dnl AG_GST_SET_PLUGINDIR
+
+dnl AC_DEFINE PLUGINDIR to the full location where plug-ins will be installed
+dnl AC_SUBST plugindir, to be used in Makefile.am's
+
+AC_DEFUN([AG_GST_SET_PLUGINDIR],
+[
+  dnl define location of plugin directory
+  AS_AC_EXPAND(PLUGINDIR, ${libdir}/gstreamer-$GST_API_VERSION)
+  AC_DEFINE_UNQUOTED(PLUGINDIR, "$PLUGINDIR",
+    [directory where plugins are located])
+  AC_MSG_NOTICE([Using $PLUGINDIR as the plugin install location])
+
+  dnl plugin directory configure-time variable for use in Makefile.am
+  plugindir="\$(libdir)/gstreamer-$GST_API_VERSION"
+  AC_SUBST(plugindir)
+])
diff --git a/common/m4/gst-valgrind.m4 b/common/m4/gst-valgrind.m4
new file mode 100644 (file)
index 0000000..5c0d608
--- /dev/null
@@ -0,0 +1,35 @@
+AC_DEFUN([AG_GST_VALGRIND_CHECK],
+[
+  dnl valgrind inclusion
+  AC_ARG_ENABLE(valgrind,
+    AC_HELP_STRING([--disable-valgrind], [disable run-time valgrind detection]),
+    [
+      case "${enableval}" in
+        yes) USE_VALGRIND="$USE_DEBUG" ;;
+        no)  USE_VALGRIND=no ;;
+        *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;;
+      esac],
+    [
+      USE_VALGRIND="$USE_DEBUG"
+    ]) dnl Default value
+
+  VALGRIND_REQ="3.0"
+  if test "x$USE_VALGRIND" = xyes; then
+    PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ,
+      USE_VALGRIND="yes",
+      [
+        USE_VALGRIND="no"
+        AC_MSG_RESULT([no])
+      ])
+  fi
+
+  if test "x$USE_VALGRIND" = xyes; then
+    AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used])
+    AC_MSG_NOTICE(Using extra code paths for valgrind)
+  fi
+  AC_SUBST(VALGRIND_CFLAGS)
+  AC_SUBST(VALGRIND_LIBS)
+
+  AC_PATH_PROG(VALGRIND_PATH, valgrind, no)
+  AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno")
+])
diff --git a/common/m4/gst-x11.m4 b/common/m4/gst-x11.m4
new file mode 100644 (file)
index 0000000..1723ca5
--- /dev/null
@@ -0,0 +1,74 @@
+dnl macros for X-related detections
+dnl AC_SUBST's HAVE_X, X_CFLAGS, X_LIBS
+AC_DEFUN([AG_GST_CHECK_X],
+[
+  AC_PATH_XTRA
+  ac_cflags_save="$CFLAGS"
+  ac_cppflags_save="$CPPFLAGS"
+  CFLAGS="$CFLAGS $X_CFLAGS"
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  dnl now try to find the HEADER
+  HAVE_X="no"
+  AC_CHECK_HEADER([X11/Xlib.h], [
+    dnl and then the library with the most uniquitous function
+    AC_CHECK_LIB(X11, [XSync], [HAVE_X="yes"], [], [$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS])
+  ])
+
+  if test "x$HAVE_X" = "xno"
+  then
+    AC_MSG_NOTICE([cannot find X11 development files])
+  else
+    dnl this is much more than we want
+    X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS"
+    dnl AC_PATH_XTRA only defines the path needed to find the X libs,
+    dnl it does not add the libs; therefore we add them here
+    X_LIBS="$X_LIBS -lX11"
+    AC_SUBST(X_CFLAGS)
+    AC_SUBST(X_LIBS)
+  fi
+  AC_SUBST(HAVE_X)
+
+  CFLAGS="$ac_cflags_save"
+  CPPFLAGS="$ac_cppflags_save"
+])
+
+dnl *** XVideo ***
+dnl Look for the PIC library first, Debian requires it.
+dnl Check debian-devel archives for gory details.
+dnl 20020110:
+dnl At the moment XFree86 doesn't distribute shared libXv due
+dnl to unstable API.  On many platforms you CAN NOT link a shared
+dnl lib to a static non-PIC lib.  This is what the xvideo GStreamer
+dnl plug-in wants to do.  So Debian distributes a PIC compiled
+dnl version of the static lib for plug-ins to link to when it is
+dnl inappropriate to link the main application to libXv directly.
+dnl FIXME: add check if this platform can support linking to a
+dnl        non-PIC libXv, if not then don not use Xv.
+dnl FIXME: perhaps warn user if they have a shared libXv since
+dnl        this is an error until XFree86 starts shipping one
+AC_DEFUN([AG_GST_CHECK_XV],
+[
+  if test x$HAVE_X = xyes; then
+    AC_CHECK_LIB(Xv_pic, XvQueryExtension,
+                 HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
+                 $X_LIBS -lXext)
+
+    if test x$HAVE_XVIDEO = xyes; then
+      XVIDEO_LIBS="-lXv_pic -lXext"
+      AC_SUBST(XVIDEO_LIBS)
+    else
+      dnl try again using something else if we didn't find it first
+      if test x$HAVE_XVIDEO = xno; then
+        AC_CHECK_LIB(Xv, XvQueryExtension,
+                   HAVE_XVIDEO="yes", HAVE_XVIDEO="no",
+                   $X_LIBS -lXext)
+
+        if test x$HAVE_XVIDEO = xyes; then
+          XVIDEO_LIBS="-lXv -lXext"
+          AC_SUBST(XVIDEO_LIBS)
+        fi
+      fi
+    fi
+  fi
+])
diff --git a/common/m4/gst.m4 b/common/m4/gst.m4
new file mode 100644 (file)
index 0000000..d4c53cb
--- /dev/null
@@ -0,0 +1,36 @@
+dnl AG_GST_INIT
+dnl sets up use of GStreamer configure.ac macros
+dnl all GStreamer autoconf macros are prefixed
+dnl with AG_GST_ for public macros
+dnl with _AG_GST_ for private macros
+dnl
+dnl We call AC_CANONICAL_TARGET and AC_CANONICAL_HOST so that
+dnl it is valid before AC_ARG_PROGRAM is called
+
+AC_DEFUN([AG_GST_INIT],
+[
+  m4_pattern_forbid(^_?AG_GST_)
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use host_ variables
+  AC_REQUIRE([AC_CANONICAL_TARGET]) dnl we use target_ variables
+])
+
+dnl AG_GST_PKG_CONFIG_PATH
+dnl
+dnl sets up a GST_PKG_CONFIG_PATH variable for use in Makefile.am
+dnl which contains the path of the in-tree pkgconfig directory first
+dnl and then any paths specified in PKG_CONFIG_PATH.
+dnl
+dnl We do this mostly so we don't have to use unportable shell constructs
+dnl such as ${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH} in Makefile.am to handle
+dnl the case where the environment variable is not set, but also in order
+dnl to avoid a trailing ':' in the PKG_CONFIG_PATH which apparently causes
+dnl problems with pkg-config on windows with msys/mingw.
+AC_DEFUN([AG_GST_PKG_CONFIG_PATH],
+[
+  GST_PKG_CONFIG_PATH="\$(top_builddir)/pkgconfig"
+  if test "x$PKG_CONFIG_PATH" != "x"; then
+    GST_PKG_CONFIG_PATH="$GST_PKG_CONFIG_PATH:$PKG_CONFIG_PATH"
+  fi
+  AC_SUBST([GST_PKG_CONFIG_PATH])
+  AC_MSG_NOTICE([Using GST_PKG_CONFIG_PATH = $GST_PKG_CONFIG_PATH])
+])
diff --git a/common/m4/gtk-doc.m4 b/common/m4/gtk-doc.m4
new file mode 100644 (file)
index 0000000..b243f1c
--- /dev/null
@@ -0,0 +1,70 @@
+dnl -*- mode: autoconf -*-
+
+# serial 1
+
+dnl Usage:
+dnl   GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+  AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+  AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+  AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+
+  dnl check for tools we added during development
+  AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check])
+  AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
+  AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
+
+  dnl for overriding the documentation installation directory
+  AC_ARG_WITH([html-dir],
+    AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+    [with_html_dir='${datadir}/gtk-doc/html'])
+  HTML_DIR="$with_html_dir"
+  AC_SUBST([HTML_DIR])
+
+  dnl enable/disable documentation building
+  AC_ARG_ENABLE([gtk-doc],
+    AS_HELP_STRING([--enable-gtk-doc],
+                   [use gtk-doc to build documentation [[default=no]]]),,
+    [enable_gtk_doc=no])
+
+  if test x$enable_gtk_doc = xyes; then
+    ifelse([$1],[],
+      [PKG_CHECK_EXISTS([gtk-doc],,
+                        AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))],
+      [PKG_CHECK_EXISTS([gtk-doc >= $1],,
+                        AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))])
+    dnl don't check for glib if we build glib
+    if test "x$PACKAGE_NAME" != "xglib"; then
+      dnl don't fail if someone does not have glib
+      PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0  >= 2.10.0,,)
+    fi
+    dnl don't rely on sed being pulled in implicitly. Fixes Solaris build.
+    if test -z "$SED"; then
+      AC_PROG_SED
+    fi
+  fi
+
+  AC_MSG_CHECKING([whether to build gtk-doc documentation])
+  AC_MSG_RESULT($enable_gtk_doc)
+
+  dnl enable/disable output formats
+  AC_ARG_ENABLE([gtk-doc-html],
+    AS_HELP_STRING([--enable-gtk-doc-html],
+                   [build documentation in html format [[default=yes]]]),,
+    [enable_gtk_doc_html=yes])
+    AC_ARG_ENABLE([gtk-doc-pdf],
+      AS_HELP_STRING([--enable-gtk-doc-pdf],
+                     [build documentation in pdf format [[default=no]]]),,
+      [enable_gtk_doc_pdf=no])
+
+  if test -z "$GTKDOC_MKPDF"; then
+    enable_gtk_doc_pdf=no
+  fi
+
+
+  AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
+  AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
+  AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
+  AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
+])
diff --git a/common/m4/introspection.m4 b/common/m4/introspection.m4
new file mode 100644 (file)
index 0000000..589721c
--- /dev/null
@@ -0,0 +1,94 @@
+dnl -*- mode: autoconf -*-
+dnl Copyright 2009 Johan Dahlin
+dnl
+dnl This file is free software; the author(s) gives unlimited
+dnl permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+
+# serial 1
+
+m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
+[
+    AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+    AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+    AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
+
+    dnl enable/disable introspection
+    m4_if([$2], [require],
+    [dnl
+        enable_introspection=yes
+    ],[dnl
+        AC_ARG_ENABLE(introspection,
+                  AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
+                                 [Enable introspection for this build]),, 
+                                 [enable_introspection=auto])
+    ])dnl
+
+    AC_MSG_CHECKING([for gobject-introspection])
+
+    dnl presence/version checking
+    AS_CASE([$enable_introspection],
+    [no], [dnl
+        found_introspection="no (disabled, use --enable-introspection to enable)"
+    ],dnl
+    [yes],[dnl
+        PKG_CHECK_EXISTS([gobject-introspection-1.0],,
+                         AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
+        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
+                         found_introspection=yes,
+                         AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
+    ],dnl
+    [auto],[dnl
+        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
+    ],dnl
+    [dnl       
+        AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
+    ])dnl
+
+    AC_MSG_RESULT([$found_introspection])
+
+    INTROSPECTION_SCANNER=
+    INTROSPECTION_COMPILER=
+    INTROSPECTION_GENERATE=
+    INTROSPECTION_GIRDIR=
+    INTROSPECTION_TYPELIBDIR=
+    if test "x$found_introspection" = "xyes"; then
+       INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+       INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
+       INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
+       INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
+       INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
+       INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
+       INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
+       INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
+    fi
+    AC_SUBST(INTROSPECTION_SCANNER)
+    AC_SUBST(INTROSPECTION_COMPILER)
+    AC_SUBST(INTROSPECTION_GENERATE)
+    AC_SUBST(INTROSPECTION_GIRDIR)
+    AC_SUBST(INTROSPECTION_TYPELIBDIR)
+    AC_SUBST(INTROSPECTION_CFLAGS)
+    AC_SUBST(INTROSPECTION_LIBS)
+    AC_SUBST(INTROSPECTION_MAKEFILE)
+
+    AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
+])
+
+
+dnl Usage:
+dnl   GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
+
+AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
+[
+  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
+])
+
+dnl Usage:
+dnl   GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
+
+
+AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
+[
+  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
+])
diff --git a/common/m4/orc.m4 b/common/m4/orc.m4
new file mode 100644 (file)
index 0000000..26b2459
--- /dev/null
@@ -0,0 +1,70 @@
+dnl pkg-config-based checks for Orc
+
+dnl specific:
+dnl ORC_CHECK([REQUIRED_VERSION])
+
+AC_DEFUN([ORC_CHECK],
+[
+  ORC_REQ=ifelse([$1], , "0.4.6", [$1])
+
+  AC_ARG_ENABLE(orc,
+  AC_HELP_STRING([--enable-orc],[use Orc if installed]),
+  [case "${enableval}" in
+    auto) enable_orc=auto ;;
+    yes) enable_orc=yes ;;
+    no)  enable_orc=no ;;
+    *) AC_MSG_ERROR(bad value ${enableval} for --enable-orc) ;;
+  esac
+  ],
+  [enable_orc=auto]) dnl Default value
+
+  if test "x$enable_orc" != "xno" ; then
+    PKG_CHECK_MODULES(ORC, orc-0.4 >= $ORC_REQ, [
+      AC_DEFINE(HAVE_ORC, 1, [Use Orc])
+      HAVE_ORC=yes
+      if test "x$ORCC" = "x" ; then
+        AC_MSG_CHECKING(for usable orcc)
+        ORCC=`$PKG_CONFIG --variable=orcc orc-0.4`
+        dnl check whether the orcc found by pkg-config can be run from the build environment
+        dnl if this is not the case (e.g. when cross-compiling) fall back to orcc from PATH
+        AS_IF([$ORCC --version 1> /dev/null 2> /dev/null], [], [ORCC=`which orcc`])
+        AC_MSG_RESULT($ORCC)
+      fi
+      AC_SUBST(ORCC)
+      ORCC_FLAGS="--compat $ORC_REQ"
+      AC_SUBST(ORCC_FLAGS)
+      AS_IF([test "x$ORCC" = "x"], [HAVE_ORCC=no], [HAVE_ORCC=yes])
+    ], [
+      if test "x$enable_orc" = "xyes" ; then
+        AC_MSG_ERROR([--enable-orc specified, but Orc >= $ORC_REQ not found])
+      fi
+      AC_DEFINE(DISABLE_ORC, 1, [Disable Orc])
+      HAVE_ORC=no
+      HAVE_ORCC=no
+    ])
+  else
+    AC_DEFINE(DISABLE_ORC, 1, [Disable Orc])
+    HAVE_ORC=no
+    HAVE_ORCC=no
+  fi
+  AM_CONDITIONAL(HAVE_ORC, [test "x$HAVE_ORC" = "xyes"])
+  AM_CONDITIONAL(HAVE_ORCC, [test "x$HAVE_ORCC" = "xyes"])
+
+]))
+
+AC_DEFUN([ORC_OUTPUT],
+[
+  if test "$HAVE_ORC" = yes ; then
+    printf "configure: *** Orc acceleration enabled.\n"
+  else
+    if test "x$enable_orc" = "xno" ; then
+      printf "configure: *** Orc acceleration disabled by --disable-orc.  Slower code paths\n"
+      printf "               will be used.\n"
+    else
+      printf "configure: *** Orc acceleration disabled.  Requires Orc >= $ORC_REQ, which was\n"
+      printf "               not found.  Slower code paths will be used.\n"
+    fi
+  fi
+  printf "\n"
+])
+
diff --git a/common/m4/pkg.m4 b/common/m4/pkg.m4
new file mode 100644 (file)
index 0000000..996e294
--- /dev/null
@@ -0,0 +1,157 @@
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+#
+# Copyright Â© 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+    if test -n "$$1"; then
+        pkg_cv_[]$1="$$1"
+    else
+        PKG_CHECK_EXISTS([$3],
+                         [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+                        [pkg_failed=yes])
+    fi
+else
+       pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+        else
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+               [AC_MSG_RESULT([no])
+                $4])
+elif test $pkg_failed = untried; then
+       ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+               [$4])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
old mode 100755 (executable)
new mode 100644 (file)
index b9bac60..cd13a1b
@@ -1 +1 @@
-SUBDIRS = bellagio rpi exynos
+SUBDIRS = bellagio rpi exynos exynos64
index 78f8e7d..5ca8ba6 100644 (file)
@@ -2,7 +2,7 @@
 type-name=GstOMXMPEG4VideoDec
 core-name=/usr/local/lib/libomxil-bellagio.so.0
 component-name=OMX.st.video_decoder.mpeg4
-rank=256
+rank=257
 in-port-index=0
 out-port-index=1
 hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1
@@ -11,7 +11,7 @@ hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-chang
 type-name=GstOMXH264Dec
 core-name=/usr/local/lib/libomxil-bellagio.so.0
 component-name=OMX.st.video_decoder.avc
-rank=256
+rank=257
 in-port-index=0
 out-port-index=1
 hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 0106ef2..68f559e
@@ -1,4 +1,4 @@
-[omxmpeg2videodec]
+[omxdec_mpeg2]
 type-name=GstOMXMPEG2VideoDec
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG2.Decoder
@@ -7,7 +7,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxmpeg4videodec]
+[omxdec_mpeg4]
 type-name=GstOMXMPEG4VideoDec
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG4.Decoder
@@ -16,7 +16,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh263dec]
+[omxdec_h263]
 type-name=GstOMXH263Dec
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.H263.Decoder
@@ -25,7 +25,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh264dec]
+[omxdec_h264]
 type-name=GstOMXH264Dec
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.AVC.Decoder
@@ -34,7 +34,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxvc1dec]
+[omxdec_vc1]
 type-name=GstOMXWMVDec
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.WMV.Decoder
@@ -44,7 +44,7 @@ out-port-index=1
 hacks=no-component-role
 sink-template-caps=video/x-wmv,wmvversion=(int)3,format=(string){WMV3,WVC1},width=(int)[1,MAX],height=(int)[1,MAX]
 
-[omxh264enc]
+[omxenc_h264]
 type-name=GstOMXH264Enc
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.AVC.Encoder
@@ -53,7 +53,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxmpeg4enc]
+[omxenc_mpeg4]
 type-name=GstOMXMPEG4VideoEnc
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG4.Encoder
@@ -62,7 +62,7 @@ in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh263enc]
+[omxenc_h263]
 type-name=GstOMXH263Enc
 core-name=/usr/lib/libExynosOMX_Core.so
 component-name=OMX.Exynos.H263.Encoder
@@ -70,3 +70,4 @@ rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
+
similarity index 76%
rename from config/odroid/Makefile.am
rename to config/exynos64/Makefile.am
index b2946fc..4c835c8 100755 (executable)
@@ -1,6 +1,6 @@
 EXTRA_DIST = gstomx.conf
 
-if USE_OMX_TARGET_ODROID
+if USE_OMX_TARGET_EXYNOS64
 configdir = $(sysconfdir)/xdg
 config_DATA = gstomx.conf
 endif
similarity index 72%
rename from config/odroid/gstomx.conf
rename to config/exynos64/gstomx.conf
index 0106ef2..f276db0 100755 (executable)
@@ -1,42 +1,42 @@
-[omxmpeg2videodec]
+[omxdec_mpeg2]
 type-name=GstOMXMPEG2VideoDec
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG2.Decoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxmpeg4videodec]
+[omxdec_mpeg4]
 type-name=GstOMXMPEG4VideoDec
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG4.Decoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh263dec]
+[omxdec_h263]
 type-name=GstOMXH263Dec
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.H263.Decoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh264dec]
+[omxdec_h264]
 type-name=GstOMXH264Dec
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.AVC.Decoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxvc1dec]
+[omxdec_vc1]
 type-name=GstOMXWMVDec
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.WMV.Decoder
 rank=256
 in-port-index=0
@@ -44,27 +44,27 @@ out-port-index=1
 hacks=no-component-role
 sink-template-caps=video/x-wmv,wmvversion=(int)3,format=(string){WMV3,WVC1},width=(int)[1,MAX],height=(int)[1,MAX]
 
-[omxh264enc]
+[omxenc_h264]
 type-name=GstOMXH264Enc
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.AVC.Encoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxmpeg4enc]
+[omxenc_mpeg4]
 type-name=GstOMXMPEG4VideoEnc
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.MPEG4.Encoder
 rank=258
 in-port-index=0
 out-port-index=1
 hacks=no-component-role
 
-[omxh263enc]
+[omxenc_h263]
 type-name=GstOMXH263Enc
-core-name=/usr/lib/libExynosOMX_Core.so
+core-name=/usr/lib64/libExynosOMX_Core.so
 component-name=OMX.Exynos.H263.Encoder
 rank=258
 in-port-index=0
index 8b65059..827ebb6 100644 (file)
@@ -2,7 +2,7 @@
 type-name=GstOMXMPEG2VideoDec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -11,7 +11,7 @@ hacks=no-component-role
 type-name=GstOMXMPEG4VideoDec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -20,7 +20,7 @@ hacks=no-component-role
 type-name=GstOMXH263Dec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -29,7 +29,7 @@ hacks=no-component-role
 type-name=GstOMXH264Dec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -38,7 +38,7 @@ hacks=no-component-role
 type-name=GstOMXTheoraDec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -47,7 +47,7 @@ hacks=no-component-role
 type-name=GstOMXVP8Dec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -56,7 +56,7 @@ hacks=no-component-role
 type-name=GstOMXMJPEGDec
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_decode
-rank=256
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -64,8 +64,8 @@ hacks=no-component-role
 [omxvc1dec]
 type-name=GstOMXWMVDec
 core-name=/opt/vc/lib/libopenmaxil.so
-component-name=OMX.broadcom.video_encode
-rank=256
+component-name=OMX.broadcom.video_decode
+rank=257
 in-port-index=130
 out-port-index=131
 hacks=no-component-role
@@ -75,8 +75,28 @@ sink-template-caps=video/x-wmv,wmvversion=(int)3,format=(string){WMV3,WVC1},widt
 type-name=GstOMXH264Enc
 core-name=/opt/vc/lib/libopenmaxil.so
 component-name=OMX.broadcom.video_encode
-rank=256
+rank=257
 in-port-index=200
 out-port-index=201
 hacks=no-component-role
 
+[omxanalogaudiosink]
+type-name=GstOMXAnalogAudioSink
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.audio_render
+rank=257
+in-port-index=100
+out-port-index=101
+hacks=no-component-role
+sink-template-caps=audio/x-raw,format=(string){S16LE,S32LE},layout=(string)interleaved,rate=(int){8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000},channels=(int)[1,2]
+
+[omxhdmiaudiosink]
+type-name=GstOMXHdmiAudioSink
+core-name=/opt/vc/lib/libopenmaxil.so
+component-name=OMX.broadcom.audio_render
+rank=258
+in-port-index=100
+out-port-index=101
+hacks=no-component-role
+sink-template-caps=audio/x-raw,format=(string){S16LE,S32LE},layout=(string)interleaved,rate=(int){8000,11025,16000,22050,24000,32000,44100,48000,88200,96000,176400,192000},channels=(int)[1,8];audio/x-ac3,framed=(boolean)true;audio/x-dts,framed=(boolean)true,block-size=(int){512,1024,2048}
+
old mode 100755 (executable)
new mode 100644 (file)
index 1db36cb..715724a
@@ -5,7 +5,7 @@ dnl please read gstreamer/docs/random/autotools before changing this file
 dnl initialize autoconf
 dnl releases only do -Wall, git and prerelease does -Werror too
 dnl use a three digit version number for releases, and four for git/prerelease
-AC_INIT(GStreamer OpenMAX Plug-ins, 1.0.0,
+AC_INIT(GStreamer OpenMAX Plug-ins, 1.2.0,
     http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer,
     gst-omx)
 
@@ -48,7 +48,7 @@ AG_GST_LIBTOOL_PREPARE
 AS_LIBTOOL(GST, 0, 0, 0)
 
 dnl *** required versions of GStreamer stuff ***
-GST_REQ=1.0.0
+GST_REQ=1.2.2
 
 dnl *** autotools stuff ****
 
@@ -60,6 +60,8 @@ AC_SUBST(ACLOCAL_AMFLAGS, "-I m4 -I common/m4")
 
 dnl *** check for arguments to configure ***
 
+AG_GST_ARG_DISABLE_FATAL_WARNINGS
+
 AG_GST_ARG_DEBUG
 AG_GST_ARG_PROFILING
 AG_GST_ARG_VALGRIND
@@ -137,6 +139,9 @@ dnl *** checks for dependency libraries ***
 dnl GLib is required
 AG_GST_GLIB_CHECK([2.32])
 
+dnl Needed by plugins that use g_module_*() API
+PKG_CHECK_MODULES(GMODULE_NO_EXPORT, gmodule-no-export-2.0)
+
 dnl checks for gstreamer
 dnl uninstalled is selected preferentially -- see pkg-config(1)
 AG_GST_CHECK_GST($GST_API_VERSION, [$GST_REQ], yes)
@@ -145,6 +150,11 @@ AG_GST_CHECK_GST_CONTROLLER($GST_API_VERSION, [$GST_REQ], yes)
 AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
 AG_GST_CHECK_GST_PLUGINS_BASE($GST_API_VERSION, [$GST_REQ], yes)
 AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
+PKG_CHECK_MODULES([GST_GL], [gstreamer-gl-1.0 >= 1.4.0], [
+  AC_DEFINE(HAVE_GST_GL, 1, [Have gstreamer-gl])
+  GST_GL=yes
+], [GST_GL=no])
+AM_CONDITIONAL(HAVE_GST_GL, test "x$GST_GL" = "xyes")
 
 dnl Check for documentation xrefs
 GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
@@ -152,17 +162,38 @@ GST_PREFIX="`$PKG_CONFIG --variable=prefix gstreamer-$GST_API_VERSION`"
 AC_SUBST(GLIB_PREFIX)
 AC_SUBST(GST_PREFIX)
 
+AC_ARG_WITH([omx-header-path],
+            AS_HELP_STRING([--with-omx-header-path],[path of external OpenMAX IL header files]),
+        [omx_header_path="$withval"], [omx_header_path="none"])
+
+if test x"$omx_header_path" != x"none"; then
+    CPPFLAGS="$CPPFLAGS -I$omx_header_path"
+fi
 dnl Check for external OpenMAX IL headers
 AC_CHECK_HEADER([OMX_Core.h], [HAVE_EXTERNAL_OMX=yes], [HAVE_EXTERNAL_OMX=no], [AC_INCLUDES_DEFAULT])
 AM_CONDITIONAL(HAVE_EXTERNAL_OMX, test "x$HAVE_EXTERNAL_OMX" = "xyes")
 
+dnl Our internal OpenMAX IL headers have OMX_VideoExt.h
+HAVE_VIDEO_EXT=yes
+if test "x$HAVE_EXTERNAL_OMX" = "xyes"; then
+    AC_CHECK_HEADER([OMX_VideoExt.h], [HAVE_VIDEO_EXT=yes], [HAVE_VIDEO_EXT=no], [AC_INCLUDES_DEFAULT])
+fi
+
+VIDEO_HEADERS="#include <OMX_Video.h>"
+if test "x$HAVE_VIDEO_EXT" = "xyes"; then
+    AC_DEFINE(HAVE_VIDEO_EXT, 1, [OpenMAX IL has OMX_VideoExt.h header])
+    VIDEO_HEADERS="$VIDEO_HEADERS
+#include <OMX_VideoExt.h>
+"
+fi
+
 AC_CHECK_DECLS([OMX_VIDEO_CodingVP8],
   [
     AC_DEFINE(HAVE_VP8, 1, [OpenMAX IL has VP8 support])
     HAVE_VP8=yes
   ], [
     HAVE_VP8=no
-  ], [[#include <OMX_Video.h>]])
+  ], [[$VIDEO_HEADERS]])
 AM_CONDITIONAL(HAVE_VP8, test "x$HAVE_VP8" = "xyes")
 
 AC_CHECK_DECLS([OMX_VIDEO_CodingTheora],
@@ -171,7 +202,7 @@ AC_CHECK_DECLS([OMX_VIDEO_CodingTheora],
     HAVE_THEORA=yes
   ], [
     HAVE_THEORA=no
-  ], [[#include <OMX_Video.h>]])
+  ], [[$VIDEO_HEADERS]])
 AM_CONDITIONAL(HAVE_THEORA, test "x$HAVE_THEORA" = "xyes")
 
 dnl Check for -Bsymbolic-functions linker flag used to avoid
@@ -190,8 +221,8 @@ AC_ARG_ENABLE(Bsymbolic,
                LDFLAGS="${SAVED_LDFLAGS}"])
 
 AC_ARG_WITH([omx-target],
-        AS_HELP_STRING([--with-omx-target],[Use this OpenMAX IL target (generic, bellagio, rpi, exynos)]),
-        [ac_cv_omx_target="$withval"], [ac_cv_omx_target="generic"])
+        AS_HELP_STRING([--with-omx-target],[Use this OpenMAX IL target (generic, bellagio, rpi)]),
+        [ac_cv_omx_target="$withval"], [ac_cv_omx_target="none"])
 
 ac_cv_omx_target_struct_packing="none"
 AC_MSG_NOTICE([Using $ac_cv_omx_target as OpenMAX IL target])
@@ -206,9 +237,12 @@ case "${ac_cv_omx_target}" in
   bellagio)
     AC_DEFINE(USE_OMX_TARGET_BELLAGIO, 1, [Use Bellagio OpenMAX IL target])
     ;;
- exynos)
 exynos)
     AC_DEFINE(USE_OMX_TARGET_EXYNOS, 1, [Use Exynos OpenMAX IL target])
     ;;
+ exynos64)
+    AC_DEFINE(USE_OMX_TARGET_EXYNOS64, 1, [Use Exynos64 OpenMAX IL target])
+    ;;
   *)
     AC_ERROR([invalid OpenMAX IL target])
     ;;
@@ -217,6 +251,7 @@ AM_CONDITIONAL(USE_OMX_TARGET_GENERIC, test "x$ac_cv_omx_target" = "xgeneric")
 AM_CONDITIONAL(USE_OMX_TARGET_BELLAGIO, test "x$ac_cv_omx_target" = "xbellagio")
 AM_CONDITIONAL(USE_OMX_TARGET_RPI, test "x$ac_cv_omx_target" = "xrpi")
 AM_CONDITIONAL(USE_OMX_TARGET_EXYNOS, test "x$ac_cv_omx_target" = "xexynos")
+AM_CONDITIONAL(USE_OMX_TARGET_EXYNOS64, test "x$ac_cv_omx_target" = "xexynos64")
 
 AC_ARG_WITH([omx-struct-packing],
         AS_HELP_STRING([--with-omx-struct-packing],[Force OpenMAX struct packing, (default is none)]),
@@ -245,8 +280,30 @@ AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO],
   ["${srcdir}/gst-omx.doap"],
   [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO])
 
+dnl build static plugins or not
+AC_MSG_CHECKING([whether to build static plugins or not])
+AC_ARG_ENABLE(
+  static-plugins,
+  AC_HELP_STRING(
+    [--enable-static-plugins],
+    [build static plugins @<:@default=no@:>@]),
+  [AS_CASE(
+    [$enableval], [no], [], [yes], [],
+    [AC_MSG_ERROR([bad value "$enableval" for --enable-static-plugins])])],
+  [enable_static_plugins=no])
+AC_MSG_RESULT([$enable_static_plugins])
+if test "x$enable_static_plugins" = xyes; then
+  AC_DEFINE(GST_PLUGIN_BUILD_STATIC, 1,
+    [Define if static plugins should be built])
+  GST_PLUGIN_LIBTOOLFLAGS=""
+else
+  GST_PLUGIN_LIBTOOLFLAGS="--tag=disable-static"
+fi
+AC_SUBST(GST_PLUGIN_LIBTOOLFLAGS)
+AM_CONDITIONAL(GST_PLUGIN_BUILD_STATIC, test "x$enable_static_plugins" = "xyes")
+
 dnl define an ERROR_CFLAGS Makefile variable
-AG_GST_SET_ERROR_CFLAGS($GST_GIT, [
+AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [
     -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef
     -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wformat-nonliteral
     -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return
@@ -308,7 +365,7 @@ AC_SUBST(GST_OMX_CFLAGS)
 
 dnl FIXME: do we want to rename to GST_ALL_* ?
 dnl add GST_OPTION_CFLAGS, but overridable
-GST_CFLAGS="$GLIB_CFLAGS $GST_CFLAGS $GLIB_EXTRA_CFLAGS \$(GST_OPTION_CFLAGS)"
+GST_CFLAGS="$GST_CFLAGS $GLIB_EXTRA_CFLAGS \$(GST_OPTION_CFLAGS)"
 AC_SUBST(GST_CFLAGS)
 dnl add GCOV libs because libtool strips -fprofile-arcs -ftest-coverage
 GST_LIBS="$GST_LIBS \$(GCOV_LIBS)"
@@ -324,7 +381,7 @@ AC_SUBST(GST_ALL_LDFLAGS)
 
 dnl this really should only contain flags, not libs - they get added before
 dnl whatevertarget_LIBS and -L flags here affect the rest of the linking
-GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_desc.*' $GST_ALL_LDFLAGS"
+GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_.*' $GST_ALL_LDFLAGS"
 AC_SUBST(GST_PLUGIN_LDFLAGS)
 
 dnl *** output files ***
@@ -350,6 +407,9 @@ config/Makefile
 config/bellagio/Makefile
 config/rpi/Makefile
 config/exynos/Makefile
+config/exynos64/Makefile
+examples/Makefile
+examples/egl/Makefile
 )
 
 AC_OUTPUT
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644 (file)
index 0000000..b7c064c
--- /dev/null
@@ -0,0 +1,5 @@
+if HAVE_GST_GL
+SUBDIRS = egl
+endif
+
+DIST_SUBDIRS = egl
diff --git a/examples/egl/Makefile.am b/examples/egl/Makefile.am
new file mode 100644 (file)
index 0000000..2646cba
--- /dev/null
@@ -0,0 +1,24 @@
+noinst_PROGRAMS = 
+
+if USE_OMX_TARGET_RPI
+noinst_PROGRAMS += testegl
+endif
+
+testegl_SOURCES = testegl.c
+
+noinst_HEADERS = cube_texture_and_coords.h
+
+testegl_LDADD = \
+       $(GST_PLUGINS_BASE_LIBS) \
+  -lgstvideo-@GST_API_VERSION@ \
+       $(GST_BASE_LIBS) \
+       $(GST_LIBS) \
+       $(GST_GL_LIBS) \
+       -lm
+
+testegl_CFLAGS = \
+       $(GST_PLUGINS_BASE_CFLAGS) \
+       $(GST_BASE_CFLAGS) \
+       $(GST_CFLAGS) \
+       $(GST_GL_CFLAGS)
+
diff --git a/examples/egl/cube_texture_and_coords.h b/examples/egl/cube_texture_and_coords.h
new file mode 100644 (file)
index 0000000..1832df3
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 2012, Broadcom Europe Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holder nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Spatial coordinates for the cube
+
+static const GLfloat quadx[6*4*3] = {
+   /* FRONT */
+   -1.f, -1.f,  1.f,
+   1.f, -1.f,  1.f,
+   -1.f,  1.f,  1.f,
+   1.f,  1.f,  1.f,
+
+   /* BACK */
+   -1.f, -1.f, -1.f,
+   -1.f,  1.f, -1.f,
+   1.f, -1.f, -1.f,
+   1.f,  1.f, -1.f,
+
+   /* LEFT */
+   -1.f, -1.f,  1.f,
+   -1.f,  1.f,  1.f,
+   -1.f, -1.f, -1.f,
+   -1.f,  1.f, -1.f,
+
+   /* RIGHT */
+   1.f, -1.f, -1.f,
+   1.f,  1.f, -1.f,
+   1.f, -1.f,  1.f,
+   1.f,  1.f,  1.f,
+
+   /* TOP */
+   -1.f,  1.f,  1.f,
+   1.f,  1.f,  1.f,
+   -1.f,  1.f, -1.f,
+   1.f,  1.f, -1.f,
+
+   /* BOTTOM */
+   -1.f, -1.f,  1.f,
+   -1.f, -1.f, -1.f,
+   1.f, -1.f,  1.f,
+   1.f, -1.f, -1.f,
+};
+
+/** Texture coordinates for the quad. */
+static const GLfloat texCoords[6 * 4 * 2] = {
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+
+   0.f,  0.f,
+   1.f,  0.f,
+   0.f,  1.f,
+   1.f,  1.f,
+};
+
diff --git a/examples/egl/testegl.c b/examples/egl/testegl.c
new file mode 100644 (file)
index 0000000..bccf6c1
--- /dev/null
@@ -0,0 +1,1605 @@
+/*
+Copyright (c) 2012, Broadcom Europe Ltd
+Copyright (c) 2012, OtherCrashOverride
+Copyright (C) 2013, Fluendo S.A.
+   @author: Josep Torra <josep@fluendo.com>
+Copyright (C) 2013, Video Experts Group LLC.
+   @author: Ilya Smelykh <ilya@videoexpertsgroup.com>
+Copyright (C) 2014 Julien Isorce <julien.isorce@collabora.co.uk>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the copyright holder nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* A rotating cube rendered with OpenGL|ES and video played using GStreamer on
+ * the cube faces.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <gst/gst.h>
+
+#if defined (USE_OMX_TARGET_RPI) && defined (__GNUC__)
+#ifndef __VCCOREVER__
+#define __VCCOREVER__ 0x04000000
+#endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#pragma GCC optimize ("gnu89-inline")
+#endif
+
+#define GST_USE_UNSTABLE_API
+#include <gst/gl/gl.h>
+#include <gst/gl/egl/gstgldisplay_egl.h>
+
+#if defined (USE_OMX_TARGET_RPI)
+#include <bcm_host.h>
+#endif
+
+#if defined (USE_OMX_TARGET_RPI) && defined (__GNUC__)
+#pragma GCC reset_options
+#pragma GCC diagnostic pop
+#endif
+
+#include "cube_texture_and_coords.h"
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+#define SYNC_BUFFERS TRUE
+
+#define TRACE_VC_MEMORY_ENABLED 0
+
+#if defined (USE_OMX_TARGET_RPI) && TRACE_VC_MEMORY_ENABLED
+#define TRACE_VC_MEMORY(str)                 \
+  fprintf (stderr, "\n\n" str "\n");         \
+  system ("vcdbg reloc >&2")
+
+#define TRACE_VC_MEMORY_DEFINE_ID(id)        \
+  static int id = 0
+
+#define TRACE_VC_MEMORY_RESET_ID(id)         \
+  G_STMT_START {                             \
+    id = 0;                                  \
+  } G_STMT_END
+
+#define TRACE_VC_MEMORY_ONCE_FOR_ID(str,id)  \
+  G_STMT_START {                             \
+    if (id == 0) {                           \
+      fprintf (stderr, "\n\n" str "\n");     \
+      system ("vcdbg reloc >&2");            \
+      id = 1;                                \
+    }                                        \
+  } G_STMT_END
+
+#define TRACE_VC_MEMORY_ONCE(str,id)         \
+  G_STMT_START {                             \
+    static int id = 0;                       \
+    if (id == 0) {                           \
+      fprintf (stderr, "\n\n" str "\n");     \
+      system ("vcdbg reloc >&2");            \
+      id = 1;                                \
+    }                                        \
+  } G_STMT_END
+
+#else
+#define TRACE_VC_MEMORY(str) while(0)
+#define TRACE_VC_MEMORY_DEFINE_ID(id)
+#define TRACE_VC_MEMORY_RESET_ID(id) while(0)
+#define TRACE_VC_MEMORY_ONCE_FOR_ID(str,id) while(0)
+#define TRACE_VC_MEMORY_ONCE(str,id) while(0)
+#endif
+
+/* some helpers that we should provide in libgstgl */
+
+typedef struct
+{
+  GLfloat m[4][4];
+} GstGLMatrix;
+
+static void
+gst_gl_matrix_load_identity (GstGLMatrix * matrix)
+{
+  memset (matrix, 0x0, sizeof (GstGLMatrix));
+  matrix->m[0][0] = 1.0f;
+  matrix->m[1][1] = 1.0f;
+  matrix->m[2][2] = 1.0f;
+  matrix->m[3][3] = 1.0f;
+}
+
+static void
+gst_gl_matrix_multiply (GstGLMatrix * matrix, GstGLMatrix * srcA,
+    GstGLMatrix * srcB)
+{
+  GstGLMatrix tmp;
+  int i;
+
+  for (i = 0; i < 4; i++) {
+    tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
+        (srcA->m[i][1] * srcB->m[1][0]) +
+        (srcA->m[i][2] * srcB->m[2][0]) + (srcA->m[i][3] * srcB->m[3][0]);
+
+    tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
+        (srcA->m[i][1] * srcB->m[1][1]) +
+        (srcA->m[i][2] * srcB->m[2][1]) + (srcA->m[i][3] * srcB->m[3][1]);
+
+    tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
+        (srcA->m[i][1] * srcB->m[1][2]) +
+        (srcA->m[i][2] * srcB->m[2][2]) + (srcA->m[i][3] * srcB->m[3][2]);
+
+    tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
+        (srcA->m[i][1] * srcB->m[1][3]) +
+        (srcA->m[i][2] * srcB->m[2][3]) + (srcA->m[i][3] * srcB->m[3][3]);
+  }
+
+  memcpy (matrix, &tmp, sizeof (GstGLMatrix));
+}
+
+static void
+gst_gl_matrix_translate (GstGLMatrix * matrix, GLfloat tx, GLfloat ty,
+    GLfloat tz)
+{
+  matrix->m[3][0] +=
+      (matrix->m[0][0] * tx + matrix->m[1][0] * ty + matrix->m[2][0] * tz);
+  matrix->m[3][1] +=
+      (matrix->m[0][1] * tx + matrix->m[1][1] * ty + matrix->m[2][1] * tz);
+  matrix->m[3][2] +=
+      (matrix->m[0][2] * tx + matrix->m[1][2] * ty + matrix->m[2][2] * tz);
+  matrix->m[3][3] +=
+      (matrix->m[0][3] * tx + matrix->m[1][3] * ty + matrix->m[2][3] * tz);
+}
+
+static void
+gst_gl_matrix_frustum (GstGLMatrix * matrix, GLfloat left, GLfloat right,
+    GLfloat bottom, GLfloat top, GLfloat nearZ, GLfloat farZ)
+{
+  GLfloat deltaX = right - left;
+  GLfloat deltaY = top - bottom;
+  GLfloat deltaZ = farZ - nearZ;
+  GstGLMatrix frust;
+
+  if ((nearZ <= 0.0f) || (farZ <= 0.0f) ||
+      (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
+    return;
+
+  frust.m[0][0] = 2.0f * nearZ / deltaX;
+  frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+  frust.m[1][1] = 2.0f * nearZ / deltaY;
+  frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+  frust.m[2][0] = (right + left) / deltaX;
+  frust.m[2][1] = (top + bottom) / deltaY;
+  frust.m[2][2] = -(nearZ + farZ) / deltaZ;
+  frust.m[2][3] = -1.0f;
+
+  frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
+  frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+  gst_gl_matrix_multiply (matrix, &frust, matrix);
+}
+
+static void
+gst_gl_matrix_perspective (GstGLMatrix * matrix, GLfloat fovy, GLfloat aspect,
+    GLfloat nearZ, GLfloat farZ)
+{
+  GLfloat frustumW, frustumH;
+
+  frustumH = tanf (fovy / 360.0f * M_PI) * nearZ;
+  frustumW = frustumH * aspect;
+
+  gst_gl_matrix_frustum (matrix, -frustumW, frustumW, -frustumH, frustumH,
+      nearZ, farZ);
+}
+
+/* *INDENT-OFF* */
+
+/* vertex source */
+static const gchar *cube_v_src =
+    "attribute vec4 a_position;                          \n"
+    "attribute vec2 a_texCoord;                          \n"
+    "uniform float u_rotx;                               \n"
+    "uniform float u_roty;                               \n"
+    "uniform float u_rotz;                               \n"
+    "uniform mat4 u_modelview;                           \n"
+    "uniform mat4 u_projection;                          \n"
+    "varying vec2 v_texCoord;                            \n"
+    "void main()                                         \n"
+    "{                                                   \n"
+    "   float PI = 3.14159265;                           \n"
+    "   float xrot = u_rotx*2.0*PI/360.0;                \n"
+    "   float yrot = u_roty*2.0*PI/360.0;                \n"
+    "   float zrot = u_rotz*2.0*PI/360.0;                \n"
+    "   mat4 matX = mat4 (                               \n"
+    "            1.0,        0.0,        0.0, 0.0,       \n"
+    "            0.0,  cos(xrot),  sin(xrot), 0.0,       \n"
+    "            0.0, -sin(xrot),  cos(xrot), 0.0,       \n"
+    "            0.0,        0.0,        0.0, 1.0 );     \n"
+    "   mat4 matY = mat4 (                               \n"
+    "      cos(yrot),        0.0, -sin(yrot), 0.0,       \n"
+    "            0.0,        1.0,        0.0, 0.0,       \n"
+    "      sin(yrot),        0.0,  cos(yrot), 0.0,       \n"
+    "            0.0,        0.0,       0.0,  1.0 );     \n"
+    "   mat4 matZ = mat4 (                               \n"
+    "      cos(zrot),  sin(zrot),        0.0, 0.0,       \n"
+    "     -sin(zrot),  cos(zrot),        0.0, 0.0,       \n"
+    "            0.0,        0.0,        1.0, 0.0,       \n"
+    "            0.0,        0.0,        0.0, 1.0 );     \n"
+    "   gl_Position = u_projection * u_modelview * matZ * matY * matX * a_position;\n"
+    "   v_texCoord = a_texCoord;                         \n"
+    "}                                                   \n";
+
+/* fragment source */
+static const gchar *cube_f_src =
+    "precision mediump float;                            \n"
+    "varying vec2 v_texCoord;                            \n"
+    "uniform sampler2D s_texture;                        \n"
+    "void main()                                         \n"
+    "{                                                   \n"
+    "  gl_FragColor = texture2D (s_texture, v_texCoord); \n"
+    "}                                                   \n";
+/* *INDENT-ON* */
+
+typedef struct
+{
+#if defined (USE_OMX_TARGET_RPI)
+  DISPMANX_DISPLAY_HANDLE_T dispman_display;
+  DISPMANX_ELEMENT_HANDLE_T dispman_element;
+#endif
+
+  uint32_t screen_width;
+  uint32_t screen_height;
+  gboolean animate;
+
+  GstCaps *caps;
+
+  /* OpenGL|ES objects */
+  EGLDisplay display;
+  EGLSurface surface;
+  EGLContext context;
+  GLuint tex;
+
+  GLint vshader;
+  GLint fshader;
+  GLint program;
+
+  GLint u_modelviewmatrix;
+  GLint u_projectionmatrix;
+  GLint s_texture;
+  GLint u_rotx;
+  GLint u_roty;
+  GLint u_rotz;
+
+  GstGLMatrix modelview;
+  GstGLMatrix projection;
+  GLfloat fov;
+  GLfloat aspect;
+
+  /* model rotation vector and direction */
+  GLfloat rot_angle_x_inc;
+  GLfloat rot_angle_y_inc;
+  GLfloat rot_angle_z_inc;
+
+  /* current model rotation angles */
+  GLfloat rot_angle_x;
+  GLfloat rot_angle_y;
+  GLfloat rot_angle_z;
+
+  /* current distance from camera */
+  GLfloat distance;
+  GLfloat distance_inc;
+
+  /* GStreamer related resources */
+  GstElement *pipeline;
+  GstElement *vsink;
+  GstGLDisplayEGL *gst_display;
+  gboolean can_avoid_upload;
+
+  /* Interthread comunication */
+  GAsyncQueue *queue;
+  GMutex queue_lock;
+  GCond cond;
+  gboolean flushing;
+  GstMiniObject *popped_obj;
+  GstBuffer *current_buffer;
+
+  /* GLib mainloop */
+  GMainLoop *main_loop;
+  GstBuffer *last_buffer;
+
+  /* Rendering thread state */
+  gboolean running;
+
+  /* number of rendered and dropped frames */
+  guint64 rendered;
+  guint64 dropped;
+} APP_STATE_T;
+
+static void init_ogl (APP_STATE_T * state);
+static void init_model_proj (APP_STATE_T * state);
+static void reset_model (APP_STATE_T * state);
+static GLfloat inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc);
+static void redraw_scene (APP_STATE_T * state);
+static void update_model (APP_STATE_T * state);
+static void init_textures (APP_STATE_T * state, GstBuffer * buffer);
+static APP_STATE_T _state, *state = &_state;
+static gboolean queue_object (APP_STATE_T * state, GstMiniObject * obj,
+    gboolean synchronous);
+
+TRACE_VC_MEMORY_DEFINE_ID (gid0);
+TRACE_VC_MEMORY_DEFINE_ID (gid1);
+TRACE_VC_MEMORY_DEFINE_ID (gid2);
+
+typedef enum
+{
+  GST_PLAY_FLAG_VIDEO = (1 << 0),
+  GST_PLAY_FLAG_AUDIO = (1 << 1),
+  GST_PLAY_FLAG_TEXT = (1 << 2),
+  GST_PLAY_FLAG_VIS = (1 << 3),
+  GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
+  GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
+  GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
+  GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
+  GST_PLAY_FLAG_BUFFERING = (1 << 8),
+  GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
+  GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
+} GstPlayFlags;
+
+/***********************************************************
+ * Name: init_ogl
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Sets the display, OpenGL|ES context and screen stuff
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_ogl (APP_STATE_T * state)
+{
+  int32_t success = 0;
+  EGLBoolean result;
+  EGLint num_config;
+  EGLNativeWindowType window_handle = (EGLNativeWindowType) 0;
+
+#if defined (USE_OMX_TARGET_RPI)
+  static EGL_DISPMANX_WINDOW_T nativewindow;
+
+  DISPMANX_UPDATE_HANDLE_T dispman_update;
+  VC_RECT_T dst_rect;
+  VC_RECT_T src_rect;
+
+  VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0 };
+#endif
+
+  static const EGLint attribute_list[] = {
+    EGL_DEPTH_SIZE, 16,
+    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+    EGL_NONE
+  };
+
+  static const EGLint context_attributes[] = {
+    EGL_CONTEXT_CLIENT_VERSION, 2,
+    EGL_NONE
+  };
+
+  EGLConfig config;
+
+  /* get an EGL display connection */
+  state->display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+  assert (state->display != EGL_NO_DISPLAY);
+
+  /* initialize the EGL display connection */
+  result = eglInitialize (state->display, NULL, NULL);
+  assert (EGL_FALSE != result);
+
+#if defined (USE_OMX_TARGET_RPI)
+  /* get an appropriate EGL frame buffer configuration
+   * this uses a BRCM extension that gets the closest match, rather
+   * than standard which returns anything that matches. */
+  result =
+      eglSaneChooseConfigBRCM (state->display, attribute_list, &config, 1,
+      &num_config);
+  assert (EGL_FALSE != result);
+#else
+  result =
+      eglChooseConfig (state->display, attribute_list, &config, 1, &num_config);
+#endif
+
+  /* create an EGL rendering context */
+  state->context =
+      eglCreateContext (state->display, config, EGL_NO_CONTEXT,
+      context_attributes);
+  assert (state->context != EGL_NO_CONTEXT);
+
+#if defined (USE_OMX_TARGET_RPI)
+  /* create an EGL window surface */
+  success = graphics_get_display_size (0 /* LCD */ , &state->screen_width,
+      &state->screen_height);
+  assert (success >= 0);
+
+  dst_rect.x = 0;
+  dst_rect.y = 0;
+  dst_rect.width = state->screen_width;
+  dst_rect.height = state->screen_height;
+
+  src_rect.x = 0;
+  src_rect.y = 0;
+  src_rect.width = state->screen_width << 16;
+  src_rect.height = state->screen_height << 16;
+
+  state->dispman_display = vc_dispmanx_display_open (0 /* LCD */ );
+  dispman_update = vc_dispmanx_update_start (0);
+
+  state->dispman_element =
+      vc_dispmanx_element_add (dispman_update, state->dispman_display,
+      0 /*layer */ , &dst_rect, 0 /*src */ ,
+      &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp */ ,
+      0 /*transform */ );
+
+  nativewindow.element = state->dispman_element;
+  nativewindow.width = state->screen_width;
+  nativewindow.height = state->screen_height;
+  vc_dispmanx_update_submit_sync (dispman_update);
+
+  window_handle = &nativewindow;
+#endif
+
+  state->surface =
+      eglCreateWindowSurface (state->display, config, window_handle, NULL);
+  assert (state->surface != EGL_NO_SURFACE);
+
+  /* connect the context to the surface */
+  result =
+      eglMakeCurrent (state->display, state->surface, state->surface,
+      state->context);
+  assert (EGL_FALSE != result);
+}
+
+/***********************************************************
+ * Name: init_model_proj
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Sets the OpenGL|ES model to default values
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_model_proj (APP_STATE_T * state)
+{
+  GLint ret = 0;
+
+  state->vshader = glCreateShader (GL_VERTEX_SHADER);
+
+  glShaderSource (state->vshader, 1, &cube_v_src, NULL);
+  glCompileShader (state->vshader);
+  assert (glGetError () == GL_NO_ERROR);
+
+  state->fshader = glCreateShader (GL_FRAGMENT_SHADER);
+
+  glShaderSource (state->fshader, 1, &cube_f_src, NULL);
+  glCompileShader (state->fshader);
+  assert (glGetError () == GL_NO_ERROR);
+
+  state->program = glCreateProgram ();
+
+  glAttachShader (state->program, state->vshader);
+  glAttachShader (state->program, state->fshader);
+
+  glBindAttribLocation (state->program, 0, "a_position");
+  glBindAttribLocation (state->program, 1, "a_texCoord");
+
+  glLinkProgram (state->program);
+
+  glGetProgramiv (state->program, GL_LINK_STATUS, &ret);
+  assert (ret == GL_TRUE);
+
+  glUseProgram (state->program);
+
+  state->u_rotx = glGetUniformLocation (state->program, "u_rotx");
+  state->u_roty = glGetUniformLocation (state->program, "u_roty");
+  state->u_rotz = glGetUniformLocation (state->program, "u_rotz");
+
+  state->u_modelviewmatrix =
+      glGetUniformLocation (state->program, "u_modelview");
+
+  state->u_projectionmatrix =
+      glGetUniformLocation (state->program, "u_projection");
+
+  state->s_texture = glGetUniformLocation (state->program, "s_texture");
+
+  glViewport (0, 0, (GLsizei) state->screen_width,
+      (GLsizei) state->screen_height);
+
+  state->fov = 45.0f;
+  state->distance = 5.0f;
+  state->aspect =
+      (GLfloat) state->screen_width / (GLfloat) state->screen_height;
+
+  gst_gl_matrix_load_identity (&state->projection);
+  gst_gl_matrix_perspective (&state->projection, state->fov, state->aspect,
+      1.0f, 100.0f);
+
+  gst_gl_matrix_load_identity (&state->modelview);
+  gst_gl_matrix_translate (&state->modelview, 0.0f, 0.0f, -state->distance);
+
+  reset_model (state);
+}
+
+/***********************************************************
+ * Name: reset_model
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Resets the Model projection and rotation direction
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+reset_model (APP_STATE_T * state)
+{
+  /* reset model rotation */
+  state->rot_angle_x = 45.f;
+  state->rot_angle_y = 30.f;
+  state->rot_angle_z = 0.f;
+  state->rot_angle_x_inc = 0.5f;
+  state->rot_angle_y_inc = 0.5f;
+  state->rot_angle_z_inc = 0.f;
+}
+
+/***********************************************************
+ * Name: update_model
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description: Updates model projection to current position/rotation
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+update_model (APP_STATE_T * state)
+{
+  if (state->animate) {
+    /* update position */
+    state->rot_angle_x =
+        inc_and_wrap_angle (state->rot_angle_x, state->rot_angle_x_inc);
+    state->rot_angle_y =
+        inc_and_wrap_angle (state->rot_angle_y, state->rot_angle_y_inc);
+    state->rot_angle_z =
+        inc_and_wrap_angle (state->rot_angle_z, state->rot_angle_z_inc);
+  }
+}
+
+/***********************************************************
+ * Name: inc_and_wrap_angle
+ *
+ * Arguments:
+ *       GLfloat angle     current angle
+ *       GLfloat angle_inc angle increment
+ *
+ * Description:   Increments or decrements angle by angle_inc degrees
+ *                Wraps to 0 at 360 deg.
+ *
+ * Returns: new value of angle
+ *
+ ***********************************************************/
+static GLfloat
+inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc)
+{
+  angle += angle_inc;
+
+  if (angle >= 360.0)
+    angle -= 360.f;
+  else if (angle <= 0)
+    angle += 360.f;
+
+  return angle;
+}
+
+/***********************************************************
+ * Name: redraw_scene
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description:   Draws the model and calls eglSwapBuffers
+ *                to render to screen
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+redraw_scene (APP_STATE_T * state)
+{
+  glBindFramebuffer (GL_FRAMEBUFFER, 0);
+
+  glEnable (GL_CULL_FACE);
+  glEnable (GL_DEPTH_TEST);
+
+  /* Set background color and clear buffers */
+  glClearColor (0.15f, 0.25f, 0.35f, 1.0f);
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glUseProgram (state->program);
+
+  glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, quadx);
+  glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
+
+  glEnableVertexAttribArray (0);
+  glEnableVertexAttribArray (1);
+
+  glActiveTexture (GL_TEXTURE0);
+  glBindTexture (GL_TEXTURE_2D, state->tex);
+  glUniform1i (state->s_texture, 0);
+
+  glUniform1f (state->u_rotx, state->rot_angle_x);
+  glUniform1f (state->u_roty, state->rot_angle_y);
+  glUniform1f (state->u_rotz, state->rot_angle_z);
+
+  glUniformMatrix4fv (state->u_modelviewmatrix, 1, GL_FALSE,
+      &state->modelview.m[0][0]);
+
+  glUniformMatrix4fv (state->u_projectionmatrix, 1, GL_FALSE,
+      &state->projection.m[0][0]);
+
+  /* draw first 4 vertices */
+  glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+  glDrawArrays (GL_TRIANGLE_STRIP, 4, 4);
+  glDrawArrays (GL_TRIANGLE_STRIP, 8, 4);
+  glDrawArrays (GL_TRIANGLE_STRIP, 12, 4);
+  glDrawArrays (GL_TRIANGLE_STRIP, 16, 4);
+  glDrawArrays (GL_TRIANGLE_STRIP, 20, 4);
+
+  eglSwapBuffers (state->display, state->surface);
+
+  glDisable (GL_DEPTH_TEST);
+  glDisable (GL_CULL_FACE);
+}
+
+/***********************************************************
+ * Name: init_textures
+ *
+ * Arguments:
+ *       APP_STATE_T *state - holds OGLES model info
+ *
+ * Description:   Initialise OGL|ES texture surfaces to use image
+ *                buffers
+ *
+ * Returns: void
+ *
+ ***********************************************************/
+static void
+init_textures (APP_STATE_T * state, GstBuffer * buffer)
+{
+  GstCapsFeatures *feature = gst_caps_get_features (state->caps, 0);
+
+  if (gst_caps_features_contains (feature, "memory:EGLImage")) {
+    /* nothing special to do */
+    g_print ("Prepare texture for EGLImage\n");
+    state->can_avoid_upload = FALSE;
+    glGenTextures (1, &state->tex);
+    glBindTexture (GL_TEXTURE_2D, state->tex);
+  } else if (gst_caps_features_contains (feature, "memory:GLMemory")) {
+    g_print ("Prepare texture for GLMemory\n");
+    state->can_avoid_upload = TRUE;
+    state->tex = 0;
+  } else if (gst_caps_features_contains (feature,
+          "meta:GstVideoGLTextureUploadMeta")) {
+    GstVideoMeta *meta = NULL;
+    g_print ("Prepare texture for GstVideoGLTextureUploadMeta\n");
+    meta = gst_buffer_get_video_meta (buffer);
+    state->can_avoid_upload = FALSE;
+    glGenTextures (1, &state->tex);
+    glBindTexture (GL_TEXTURE_2D, state->tex);
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, meta->width, meta->height, 0,
+        GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  } else {
+    g_assert_not_reached ();
+  }
+
+#if 0
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+#else
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  assert (glGetError () == GL_NO_ERROR);
+}
+
+static void
+render_scene (APP_STATE_T * state)
+{
+  update_model (state);
+  redraw_scene (state);
+  TRACE_VC_MEMORY_ONCE_FOR_ID ("after render_scene", gid2);
+}
+
+static void
+update_image (APP_STATE_T * state, GstBuffer * buffer)
+{
+  GstVideoGLTextureUploadMeta *meta = NULL;
+
+  if (state->current_buffer) {
+    gst_buffer_unref (state->current_buffer);
+  } else {
+    /* Setup the model world */
+    init_model_proj (state);
+    TRACE_VC_MEMORY ("after init_model_proj");
+
+    /* initialize the OGLES texture(s) */
+    init_textures (state, buffer);
+    TRACE_VC_MEMORY ("after init_textures");
+  }
+  state->current_buffer = gst_buffer_ref (buffer);
+
+  TRACE_VC_MEMORY_ONCE_FOR_ID ("before GstVideoGLTextureUploadMeta", gid0);
+
+  if (state->can_avoid_upload) {
+    GstMemory *mem = gst_buffer_peek_memory (state->current_buffer, 0);
+    g_assert (gst_is_gl_memory (mem));
+    state->tex = ((GstGLMemory *) mem)->tex_id;
+  } else if ((meta = gst_buffer_get_video_gl_texture_upload_meta (buffer))) {
+    if (meta->n_textures == 1) {
+      guint ids[4] = { state->tex, 0, 0, 0 };
+      if (!gst_video_gl_texture_upload_meta_upload (meta, ids)) {
+        GST_WARNING ("failed to upload to texture");
+      }
+    }
+  }
+
+  TRACE_VC_MEMORY_ONCE_FOR_ID ("after GstVideoGLTextureUploadMeta", gid1);
+}
+
+static void
+init_intercom (APP_STATE_T * state)
+{
+  state->queue =
+      g_async_queue_new_full ((GDestroyNotify) gst_mini_object_unref);
+  g_mutex_init (&state->queue_lock);
+  g_cond_init (&state->cond);
+}
+
+static void
+terminate_intercom (APP_STATE_T * state)
+{
+  /* Release intercom */
+  if (state->queue) {
+    g_async_queue_unref (state->queue);
+  }
+
+  g_mutex_clear (&state->queue_lock);
+  g_cond_clear (&state->cond);
+}
+
+static void
+flush_internal (APP_STATE_T * state)
+{
+  if (state->current_buffer) {
+    gst_buffer_unref (state->current_buffer);
+  }
+  state->current_buffer = NULL;
+}
+
+static void
+flush_start (APP_STATE_T * state)
+{
+  GstMiniObject *object = NULL;
+
+  g_mutex_lock (&state->queue_lock);
+  state->flushing = TRUE;
+  g_cond_broadcast (&state->cond);
+  g_mutex_unlock (&state->queue_lock);
+
+  while ((object = g_async_queue_try_pop (state->queue))) {
+    gst_mini_object_unref (object);
+  }
+  g_mutex_lock (&state->queue_lock);
+  flush_internal (state);
+  state->popped_obj = NULL;
+  g_mutex_unlock (&state->queue_lock);
+}
+
+static void
+flush_stop (APP_STATE_T * state)
+{
+  GstMiniObject *object = NULL;
+
+  g_mutex_lock (&state->queue_lock);
+  while ((object = GST_MINI_OBJECT_CAST (g_async_queue_try_pop (state->queue)))) {
+    gst_mini_object_unref (object);
+  }
+  flush_internal (state);
+  state->popped_obj = NULL;
+  state->flushing = FALSE;
+  g_mutex_unlock (&state->queue_lock);
+}
+
+static void
+pipeline_pause (APP_STATE_T * state)
+{
+  gst_element_set_state (state->pipeline, GST_STATE_PAUSED);
+}
+
+static void
+pipeline_play (APP_STATE_T * state)
+{
+  gst_element_set_state (state->pipeline, GST_STATE_PLAYING);
+}
+
+static gint64
+pipeline_get_position (APP_STATE_T * state)
+{
+  gint64 position = -1;
+
+  if (state->pipeline) {
+    gst_element_query_position (state->vsink, GST_FORMAT_TIME, &position);
+  }
+
+  return position;
+}
+
+static gint64
+pipeline_get_duration (APP_STATE_T * state)
+{
+  gint64 duration = -1;
+
+  if (state->pipeline) {
+    gst_element_query_duration (state->pipeline, GST_FORMAT_TIME, &duration);
+  }
+
+  return duration;
+}
+
+static void
+pipeline_seek (APP_STATE_T * state, gint64 position)
+{
+  if (state->pipeline) {
+    GstEvent *event;
+    event = gst_event_new_seek (1.0,
+        GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
+        GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
+    if (!gst_element_send_event (state->vsink, event)) {
+      g_print ("seek failed\n");
+    }
+  }
+}
+
+static gboolean
+handle_queued_objects (APP_STATE_T * state)
+{
+  GstMiniObject *object = NULL;
+
+  g_mutex_lock (&state->queue_lock);
+  if (state->flushing) {
+    g_cond_broadcast (&state->cond);
+    goto beach;
+  } else if (g_async_queue_length (state->queue) == 0) {
+    goto beach;
+  }
+
+  if ((object = g_async_queue_try_pop (state->queue))) {
+    if (GST_IS_BUFFER (object)) {
+      GstBuffer *buffer = GST_BUFFER_CAST (object);
+      update_image (state, buffer);
+      render_scene (state);
+      gst_buffer_unref (buffer);
+      if (!SYNC_BUFFERS) {
+        object = NULL;
+      }
+    } else if (GST_IS_QUERY (object)) {
+      GstQuery *query = GST_QUERY_CAST (object);
+      GstStructure *s = (GstStructure *) gst_query_get_structure (query);
+
+      if (gst_structure_has_name (s, "not-used")) {
+        g_assert_not_reached ();
+      } else {
+        g_assert_not_reached ();
+      }
+    } else if (GST_IS_EVENT (object)) {
+      GstEvent *event = GST_EVENT_CAST (object);
+      g_print ("\nevent %p %s\n", event,
+          gst_event_type_get_name (GST_EVENT_TYPE (event)));
+
+      switch (GST_EVENT_TYPE (event)) {
+        case GST_EVENT_EOS:
+          flush_internal (state);
+          break;
+        default:
+          break;
+      }
+      gst_event_unref (event);
+      object = NULL;
+    }
+  }
+
+  if (object) {
+    state->popped_obj = object;
+    g_cond_broadcast (&state->cond);
+  }
+
+beach:
+  g_mutex_unlock (&state->queue_lock);
+
+  return FALSE;
+}
+
+static gboolean
+queue_object (APP_STATE_T * state, GstMiniObject * obj, gboolean synchronous)
+{
+  gboolean res = TRUE;
+
+  g_mutex_lock (&state->queue_lock);
+  if (state->flushing) {
+    gst_mini_object_unref (obj);
+    res = FALSE;
+    goto beach;
+  }
+
+  g_async_queue_push (state->queue, obj);
+
+  if (synchronous) {
+    /* Waiting for object to be handled */
+    do {
+      g_cond_wait (&state->cond, &state->queue_lock);
+    } while (!state->flushing && state->popped_obj != obj);
+  }
+
+beach:
+  g_mutex_unlock (&state->queue_lock);
+  return res;
+}
+
+static void
+preroll_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+    gpointer user_data)
+{
+  APP_STATE_T *state = (APP_STATE_T *) user_data;
+  queue_object (state, GST_MINI_OBJECT_CAST (gst_buffer_ref (buffer)), FALSE);
+}
+
+static void
+buffers_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+    gpointer user_data)
+{
+  APP_STATE_T *state = (APP_STATE_T *) user_data;
+  queue_object (state, GST_MINI_OBJECT_CAST (gst_buffer_ref (buffer)),
+      SYNC_BUFFERS);
+}
+
+static GstPadProbeReturn
+events_cb (GstPad * pad, GstPadProbeInfo * probe_info, gpointer user_data)
+{
+  APP_STATE_T *state = (APP_STATE_T *) user_data;
+  GstEvent *event = GST_PAD_PROBE_INFO_EVENT (probe_info);
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      if (state->caps) {
+        gst_caps_unref (state->caps);
+        state->caps = NULL;
+      }
+      gst_event_parse_caps (event, &state->caps);
+      if (state->caps)
+        gst_caps_ref (state->caps);
+      break;
+    }
+    case GST_EVENT_FLUSH_START:
+      flush_start (state);
+      break;
+    case GST_EVENT_FLUSH_STOP:
+      flush_stop (state);
+      break;
+    case GST_EVENT_EOS:
+      queue_object (state, GST_MINI_OBJECT_CAST (gst_event_ref (event)), FALSE);
+      break;
+    default:
+      break;
+  }
+
+  return GST_PAD_PROBE_OK;
+}
+
+static GstPadProbeReturn
+query_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
+{
+  APP_STATE_T *state = (APP_STATE_T *) user_data;
+  GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info);
+  GstStructure *external_gl_context_desc = NULL;
+  gchar *platform = NULL;
+  gchar *gl_apis = NULL;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ALLOCATION:
+    {
+      platform = gst_gl_platform_to_string (GST_GL_PLATFORM_EGL);
+      gl_apis = gst_gl_api_to_string (GST_GL_API_GLES2);
+
+      external_gl_context_desc =
+          gst_structure_new ("GstVideoGLTextureUploadMeta",
+          "gst.gl.context.handle", G_TYPE_POINTER, state->context,
+          "gst.gl.context.type", G_TYPE_STRING, platform,
+          "gst.gl.context.apis", G_TYPE_STRING, gl_apis, NULL);
+      gst_query_add_allocation_meta (query,
+          GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, external_gl_context_desc);
+      gst_structure_free (external_gl_context_desc);
+
+      g_free (gl_apis);
+      g_free (platform);
+
+      GST_DEBUG ("done alocation");
+      return GST_PAD_PROBE_OK;
+      break;
+    }
+    case GST_QUERY_CONTEXT:
+    {
+      return gst_gl_handle_context_query (state->pipeline, query,
+          (GstGLDisplay **) & state->gst_display);
+      break;
+    }
+    case GST_QUERY_DRAIN:
+    {
+      flush_internal (state);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return GST_PAD_PROBE_OK;
+}
+
+static gboolean
+init_playbin_player (APP_STATE_T * state, const gchar * uri)
+{
+  GstPad *pad = NULL;
+  GstPad *ghostpad = NULL;
+  GstElement *vbin = gst_bin_new ("vbin");
+
+  /* insert a gl filter so that the GstGLBufferPool
+   * is managed automatically */
+  GstElement *glfilter = gst_element_factory_make ("glcolorscale", "glfilter");
+  GstElement *vsink = gst_element_factory_make ("fakesink", "vsink");
+  g_object_set (vsink, "sync", TRUE, "silent", TRUE, "qos", TRUE,
+      "enable-last-sample", FALSE,
+      "max-lateness", 20 * GST_MSECOND, "signal-handoffs", TRUE, NULL);
+
+  g_signal_connect (vsink, "preroll-handoff", G_CALLBACK (preroll_cb), state);
+  g_signal_connect (vsink, "handoff", G_CALLBACK (buffers_cb), state);
+
+  gst_bin_add_many (GST_BIN (vbin), glfilter, vsink, NULL);
+
+  pad = gst_element_get_static_pad (glfilter, "sink");
+  ghostpad = gst_ghost_pad_new ("sink", pad);
+  gst_object_unref (pad);
+  gst_element_add_pad (vbin, ghostpad);
+
+  pad = gst_element_get_static_pad (vsink, "sink");
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb, state,
+      NULL);
+  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb, state,
+      NULL);
+  gst_object_unref (pad);
+
+  gst_element_link (glfilter, vsink);
+
+  /* Instantiate and configure playbin */
+  state->pipeline = gst_element_factory_make ("playbin", "player");
+  g_object_set (state->pipeline, "uri", uri,
+      "video-sink", vbin, "flags",
+      GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_AUDIO, NULL);
+
+  state->vsink = gst_object_ref (vsink);
+  return TRUE;
+}
+
+static gboolean
+init_parse_launch_player (APP_STATE_T * state, const gchar * spipeline)
+{
+  GstElement *vsink;
+  GError *error = NULL;
+
+  /* ex:
+
+     ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+     h264parse !  omxh264dec ! glcolorscale ! fakesink name=vsink"
+
+     ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+     h264parse ! omxh264dec ! glcolorscale ! \
+     video/x-raw(memory:EGLImage) ! fakesink name=vsink"
+
+     ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+     h264parse ! omxh264dec ! glcolorscale ! \
+     video/x-raw(memory:GLMemory) ! fakesink name=vsink"
+
+     ./testegl "filesrc location=big_buck_bunny_720p_h264.mov ! qtdemux ! \
+     h264parse ! omxh264dec ! glcolorscale ! \
+     video/x-raw(meta:GstVideoGLTextureUploadMeta) ! \
+     fakesink name=vsink"
+
+   */
+
+  /* pipeline 1 and 2 are the same and the most efficient as glcolorscale
+   * will enter in passthrough mode and testegl will just bind the eglimage
+   * to a gl texture without any copy. */
+
+  state->pipeline = gst_parse_launch (spipeline, &error);
+
+  if (!state->pipeline) {
+    g_printerr ("Unable to instatiate pipeline '%s': %s\n",
+        spipeline, error->message);
+    return FALSE;
+  }
+
+  vsink = gst_bin_get_by_name (GST_BIN (state->pipeline), "vsink");
+
+  if (!vsink) {
+    g_printerr ("Unable to find a fakesink named 'vsink'");
+    return FALSE;
+  }
+
+  g_object_set (vsink, "sync", TRUE, "silent", TRUE, "qos", TRUE,
+      "enable-last-sample", FALSE,
+      "max-lateness", 20 * GST_MSECOND, "signal-handoffs", TRUE, NULL);
+
+  g_signal_connect (vsink, "preroll-handoff", G_CALLBACK (preroll_cb), state);
+  g_signal_connect (vsink, "handoff", G_CALLBACK (buffers_cb), state);
+
+  gst_pad_add_probe (gst_element_get_static_pad (vsink, "sink"),
+      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, events_cb, state, NULL);
+  gst_pad_add_probe (gst_element_get_static_pad (vsink, "sink"),
+      GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, query_cb, state, NULL);
+
+  state->vsink = gst_object_ref (vsink);
+  return TRUE;
+}
+
+//------------------------------------------------------------------------------
+
+static void
+report_position_duration (APP_STATE_T * state)
+{
+  gint64 position, duration;
+
+  duration = pipeline_get_duration (state);
+  position = pipeline_get_position (state);
+
+  if (position != -1) {
+    g_print ("\n position / duration: %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (position));
+  } else {
+    g_print ("\n position / duration: unknown");
+  }
+
+  if (duration != -1) {
+    g_print (" / %" GST_TIME_FORMAT, GST_TIME_ARGS (duration));
+  } else {
+    g_print (" / unknown");
+  }
+  g_print ("\n");
+}
+
+static void
+seek_forward (APP_STATE_T * state)
+{
+  gint64 position, duration;
+
+  duration = pipeline_get_duration (state);
+  position = pipeline_get_position (state);
+
+  if (position != -1) {
+    position += 30 * GST_SECOND;
+    if (duration != -1) {
+      position = MIN (position, duration);
+    }
+    pipeline_seek (state, position);
+  }
+}
+
+static void
+seek_backward (APP_STATE_T * state)
+{
+  gint64 position;
+
+  position = pipeline_get_position (state);
+
+  if (position != -1) {
+    position -= 30 * GST_SECOND;
+    position = MAX (position, 0);
+    pipeline_seek (state, position);
+  }
+}
+
+#define SKIP(t) \
+  while (*t) { \
+    if ((*t == ' ') || (*t == '\n') || (*t == '\t') || (*t == '\r')) \
+      t++; \
+    else \
+      break; \
+  }
+
+/* Process keyboard input */
+static gboolean
+handle_keyboard (GIOChannel * source, GIOCondition cond, APP_STATE_T * state)
+{
+  gchar *str = NULL;
+  char op;
+
+  if (g_io_channel_read_line (source, &str, NULL, NULL,
+          NULL) == G_IO_STATUS_NORMAL) {
+
+    gchar *cmd = str;
+    SKIP (cmd)
+        op = *cmd;
+    cmd++;
+    switch (op) {
+      case 'a':
+        if (state->animate) {
+          state->animate = FALSE;
+        } else {
+          state->animate = TRUE;
+        }
+        break;
+      case 'p':
+        pipeline_pause (state);
+        break;
+      case 'r':
+        pipeline_play (state);
+        break;
+      case 'l':
+        report_position_duration (state);
+        break;
+      case 'f':
+        seek_forward (state);
+        break;
+      case 'b':
+        seek_backward (state);
+        break;
+      case 'q':
+        flush_start (state);
+        gst_element_set_state (state->pipeline, GST_STATE_READY);
+        break;
+    }
+  }
+  g_free (str);
+  return TRUE;
+}
+
+static GstBusSyncReply
+bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data)
+{
+  return GST_BUS_PASS;
+}
+
+/* on error print the error and quit the application */
+static void
+error_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+  GError *err;
+  gchar *debug_info;
+
+  gst_message_parse_error (msg, &err, &debug_info);
+  g_printerr ("Error received from element %s: %s\n",
+      GST_OBJECT_NAME (msg->src), err->message);
+  g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
+  g_clear_error (&err);
+  g_free (debug_info);
+  flush_start (state);
+  gst_element_set_state (state->pipeline, GST_STATE_READY);
+}
+
+/* buffering */
+static void
+buffering_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+  gint percent;
+
+  gst_message_parse_buffering (msg, &percent);
+  g_print ("Buffering %3d%%\r", percent);
+  if (percent < 100)
+    pipeline_pause (state);
+  else {
+    g_print ("\n");
+    pipeline_play (state);
+  }
+}
+
+/* on EOS just quit the application */
+static void
+eos_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+  if (GST_MESSAGE_SRC (msg) == GST_OBJECT (state->pipeline)) {
+    g_print ("End-Of-Stream reached.\n");
+    gst_element_set_state (state->pipeline, GST_STATE_READY);
+  }
+}
+
+static void
+state_changed_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+  GstState old_state, new_state, pending_state;
+  if (GST_MESSAGE_SRC (msg) == GST_OBJECT (state->pipeline)) {
+    gst_message_parse_state_changed (msg, &old_state, &new_state,
+        &pending_state);
+    g_print ("State changed to %s\n", gst_element_state_get_name (new_state));
+    if (old_state == GST_STATE_PAUSED && new_state == GST_STATE_READY) {
+      g_main_loop_quit (state->main_loop);
+    }
+  }
+}
+
+static void
+qos_cb (GstBus * bus, GstMessage * msg, APP_STATE_T * state)
+{
+  GstFormat fmt = GST_FORMAT_BUFFERS;
+  gchar *name = gst_element_get_name (GST_MESSAGE_SRC (msg));
+  gst_message_parse_qos_stats (msg, &fmt, &state->rendered, &state->dropped);
+  g_print ("%s rendered: %" G_GUINT64_FORMAT " dropped: %" G_GUINT64_FORMAT
+      " %s\n",
+      name, state->rendered, state->dropped,
+      (fmt == GST_FORMAT_BUFFERS ? "frames" : "samples"));
+  g_free (name);
+}
+
+//==============================================================================
+
+static void
+close_ogl (void)
+{
+#if defined (USE_OMX_TARGET_RPI)
+  DISPMANX_UPDATE_HANDLE_T dispman_update;
+#endif
+
+  if (state->fshader) {
+    glDeleteShader (state->fshader);
+    glDetachShader (state->program, state->fshader);
+  }
+
+  if (state->vshader) {
+    glDeleteShader (state->vshader);
+    glDetachShader (state->program, state->vshader);
+  }
+
+  if (state->program)
+    glDeleteProgram (state->program);
+
+  if (state->tex)
+    glDeleteTextures (1, &state->tex);
+
+  /* clear screen */
+  glClear (GL_COLOR_BUFFER_BIT);
+  eglSwapBuffers (state->display, state->surface);
+
+  /* Release OpenGL resources */
+  eglMakeCurrent (state->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+      EGL_NO_CONTEXT);
+  eglDestroySurface (state->display, state->surface);
+  eglDestroyContext (state->display, state->context);
+  gst_object_unref (state->gst_display);
+
+#if defined (USE_OMX_TARGET_RPI)
+  dispman_update = vc_dispmanx_update_start (0);
+  vc_dispmanx_element_remove (dispman_update, state->dispman_element);
+  vc_dispmanx_update_submit_sync (dispman_update);
+  vc_dispmanx_display_close (state->dispman_display);
+#endif
+}
+
+//==============================================================================
+
+static void
+open_ogl (void)
+{
+  TRACE_VC_MEMORY ("state 0");
+
+#if defined (USE_OMX_TARGET_RPI)
+  bcm_host_init ();
+  TRACE_VC_MEMORY ("after bcm_host_init");
+#endif
+
+  /* Create surface and gl context */
+  init_ogl (state);
+  TRACE_VC_MEMORY ("after init_ogl");
+
+  /* Wrap the EGLDisplay to GstGLDisplayEGL */
+  state->gst_display = gst_gl_display_egl_new_with_egl_display (state->display);
+}
+
+static gpointer
+render_func (gpointer data)
+{
+  open_ogl ();
+  state->running = TRUE;
+
+  do {
+    handle_queued_objects (state);
+    g_usleep (0);
+  } while (state->running == TRUE);
+
+  close_ogl ();
+  return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+  GstBus *bus;
+  GOptionContext *ctx;
+  GIOChannel *io_stdin;
+  GError *err = NULL;
+  gboolean res;
+  GOptionEntry options[] = {
+    {NULL}
+  };
+  GThread *rthread;
+
+  /* Clear application state */
+  memset (state, 0, sizeof (*state));
+  state->animate = TRUE;
+  state->current_buffer = NULL;
+  state->caps = NULL;
+
+#if !GLIB_CHECK_VERSION (2, 31, 0)
+  /* must initialise the threading system before using any other GLib funtion */
+  if (!g_thread_supported ())
+    g_thread_init (NULL);
+#endif
+
+  ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
+  g_option_context_add_main_entries (ctx, options, NULL);
+  g_option_context_add_group (ctx, gst_init_get_option_group ());
+  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
+    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
+    exit (1);
+  }
+  g_option_context_free (ctx);
+
+  if (argc != 2) {
+    g_print ("Usage: %s <URI> or <PIPELINE-DESCRIPTION>\n", argv[0]);
+    exit (1);
+  }
+
+  /* Initialize GStreamer */
+  gst_init (&argc, &argv);
+
+  /* initialize inter thread comunnication */
+  init_intercom (state);
+
+  TRACE_VC_MEMORY ("state 0");
+
+  if (!(rthread = g_thread_new ("render", (GThreadFunc) render_func, NULL))) {
+    g_print ("Render thread create failed\n");
+    exit (1);
+  }
+
+  /* Initialize player */
+  if (gst_uri_is_valid (argv[1])) {
+    res = init_playbin_player (state, argv[1]);
+  } else {
+    res = init_parse_launch_player (state, argv[1]);
+  }
+
+  if (!res)
+    goto done;
+
+  /* Create a GLib Main Loop and set it to run */
+  state->main_loop = g_main_loop_new (NULL, FALSE);
+
+  /* Add a keyboard watch so we get notified of keystrokes */
+  io_stdin = g_io_channel_unix_new (fileno (stdin));
+  g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, state);
+  g_io_channel_unref (io_stdin);
+
+  /* *INDENT-OFF* */
+  g_print ("Available commands: \n"
+      "  a - Toggle animation \n"
+      "  p - Pause playback \n"
+      "  r - Resume playback \n"
+      "  l - Query position/duration\n"
+      "  f - Seek 30 seconds forward \n"
+      "  b - Seek 30 seconds backward \n"
+      "  q - Quit \n");
+  /* *INDENT-ON* */
+
+  /* Connect the bus handlers */
+  bus = gst_element_get_bus (state->pipeline);
+
+  gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, state,
+      NULL);
+
+  gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+  gst_bus_enable_sync_message_emission (bus);
+
+  g_signal_connect (G_OBJECT (bus), "message::error", (GCallback) error_cb,
+      state);
+  g_signal_connect (G_OBJECT (bus), "message::buffering",
+      (GCallback) buffering_cb, state);
+  g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback) eos_cb, state);
+  g_signal_connect (G_OBJECT (bus), "message::qos", (GCallback) qos_cb, state);
+  g_signal_connect (G_OBJECT (bus), "message::state-changed",
+      (GCallback) state_changed_cb, state);
+  gst_object_unref (bus);
+
+  /* Make player start playing */
+  gst_element_set_state (state->pipeline, GST_STATE_PLAYING);
+
+  /* Start the mainloop */
+  state->main_loop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (state->main_loop);
+
+done:
+  /* Release pipeline */
+  if (state->pipeline) {
+    gst_element_set_state (state->pipeline, GST_STATE_NULL);
+    if (state->vsink) {
+      gst_object_unref (state->vsink);
+      state->vsink = NULL;
+    }
+
+    gst_object_unref (state->pipeline);
+  }
+
+  /* Unref the mainloop */
+  if (state->main_loop) {
+    g_main_loop_unref (state->main_loop);
+  }
+
+  /* Stop rendering thread */
+  state->running = FALSE;
+  g_thread_join (rthread);
+
+  if (state->caps) {
+    gst_caps_unref (state->caps);
+    state->caps = NULL;
+  }
+
+  terminate_intercom (state);
+
+  TRACE_VC_MEMORY ("at exit");
+  return 0;
+}
index c5c5401..3872f59 100644 (file)
@@ -33,6 +33,16 @@ a basic collection of elements
 
  <release>
   <Version>
+   <revision>1.2.0</revision>
+   <branch>1.2</branch>
+   <name></name>
+   <created>2014-07-23</created>
+   <file-release rdf:resource="http://gstreamer.freedesktop.org/src/gst-omx/gst-omx-1.2.0.tar.xz" />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
    <revision>1.0.0</revision>
    <branch>1.0</branch>
    <name></name>
diff --git a/gst-omx.manifest b/gst-omx.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644 (file)
index 0000000..741f850
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS =
index b182506..5108c8c 100644 (file)
@@ -12,8 +12,11 @@ endif
 
 libgstomx_la_SOURCES = \
        gstomx.c \
+       gstomxbufferpool.c \
+       gstomxvideo.c \
        gstomxvideodec.c \
        gstomxvideoenc.c \
+       gstomxaudiodec.c \
        gstomxaudioenc.c \
        gstomxmjpegdec.c \
        gstomxmpeg4videodec.c \
@@ -26,12 +29,21 @@ libgstomx_la_SOURCES = \
        gstomxmpeg4videoenc.c \
        gstomxh264enc.c \
        gstomxh263enc.c \
-       gstomxaacenc.c
+       gstomxaacdec.c \
+       gstomxmp3dec.c \
+       gstomxaacenc.c \
+       gstomxamrdec.c \
+       gstomxaudiosink.c \
+       gstomxanalogaudiosink.c \
+       gstomxhdmiaudiosink.c   
 
 noinst_HEADERS = \
        gstomx.h \
+       gstomxbufferpool.h \
+       gstomxvideo.h \
        gstomxvideodec.h \
        gstomxvideoenc.h \
+       gstomxaudiodec.h \
        gstomxaudioenc.h \
        gstomxmjpegdec.h \
        gstomxmpeg2videodec.h \
@@ -44,7 +56,13 @@ noinst_HEADERS = \
        gstomxmpeg4videoenc.h \
        gstomxh264enc.h \
        gstomxh263enc.h \
-       gstomxaacenc.h
+       gstomxaacdec.h \
+       gstomxmp3dec.h \
+       gstomxaacenc.h \
+       gstomxamrdec.h \
+       gstomxaudiosink.h \
+       gstomxanalogaudiosink.h \
+       gstomxhdmiaudiosink.h   
 
 if !HAVE_EXTERNAL_OMX
 OMX_INCLUDEPATH = -I$(abs_srcdir)/openmax
@@ -52,17 +70,17 @@ endif
 
 libgstomx_la_CFLAGS = \
        -DGST_USE_UNSTABLE_API=1 \
-       $(CFLAGS) \
        $(OMX_INCLUDEPATH) \
+       $(GST_GL_CFLAGS) \
        $(GST_PLUGINS_BASE_CFLAGS) \
        $(GST_BASE_CFLAGS) \
        $(GST_CFLAGS) \
        $(TBM_CFLAGS) \
-       $(MM_COMMON_CFLAGS)
-
+       $(GMODULE_NO_EXPORT_CFLAGS) \
+        $(MM_COMMON_CFLAGS)
 libgstomx_la_CFLAGS += -DUSE_MM_VIDEO_BUFFER
-
 libgstomx_la_LIBADD = \
+       $(GST_GL_LIBS) \
        $(GST_PLUGINS_BASE_LIBS) \
        -lgstaudio-@GST_API_VERSION@ \
        -lgstpbutils-@GST_API_VERSION@ \
@@ -70,8 +88,8 @@ libgstomx_la_LIBADD = \
        $(GST_BASE_LIBS) \
        $(GST_LIBS) \
        $(TBM_LIBS) \
+       $(GMODULE_NO_EXPORT_LIBS) \
        $(MM_COMMON_LIBS)
-
 libgstomx_la_LDFLAGS = \
        $(GST_PLUGIN_LDFLAGS) \
        $(TBM_LDFLAGS) \
old mode 100755 (executable)
new mode 100644 (file)
index dddd0a4..5f829e9
 #include "gstomxmpeg4videoenc.h"
 #include "gstomxh264enc.h"
 #include "gstomxh263enc.h"
+#include "gstomxaacdec.h"
+#include "gstomxmp3dec.h"
 #include "gstomxaacenc.h"
+#include "gstomxamrdec.h"
+#include "gstomxanalogaudiosink.h"
+#include "gstomxhdmiaudiosink.h"
 
 GST_DEBUG_CATEGORY (gstomx_debug);
 #define GST_CAT_DEFAULT gstomx_debug
@@ -47,8 +52,6 @@ GST_DEBUG_CATEGORY (gstomx_debug);
 G_LOCK_DEFINE_STATIC (core_handles);
 static GHashTable *core_handles;
 
-
-
 GstOMXCore *
 gst_omx_core_acquire (const gchar * filename)
 {
@@ -291,8 +294,8 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
         OMX_U32 index = msg->content.port_settings_changed.port;
         GList *outports = NULL, *l, *k;
 
-        GST_ERROR_OBJECT (comp->parent, "%s settings changed (port %u)",
-            comp->name, index);
+        GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port %u)",
+            comp->name, (guint) index);
 
         /* FIXME: This probably can be done better */
 
@@ -338,7 +341,7 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
           break;
 
         GST_DEBUG_OBJECT (comp->parent, "%s port %u got buffer flags 0x%08x",
-            comp->name, port->index, flags);
+            comp->name, port->index, (guint) flags);
         if ((flags & OMX_BUFFERFLAG_EOS)
             && port->port_def.eDir == OMX_DirOutput)
           port->eos = TRUE;
@@ -348,15 +351,14 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
       case GST_OMX_MESSAGE_BUFFER_DONE:{
         GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
         GstOMXPort *port;
-        GstOMXComponent *comp;
 
         port = buf->port;
-        comp = port->comp;
 
         if (msg->content.buffer_done.empty) {
           /* Input buffer is empty again and can be used to contain new input */
-          GST_LOG_OBJECT (comp->parent, "%s port %u emptied buffer %p (%p)",
-              comp->name, port->index, buf, buf->omx_buf->pBuffer);
+          GST_LOG_OBJECT (port->comp->parent,
+              "%s port %u emptied buffer %p (%p)", port->comp->name,
+              port->index, buf, buf->omx_buf->pBuffer);
 
           /* Reset offset and filled length */
           buf->omx_buf->nOffset = 0;
@@ -370,8 +372,9 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
         } else {
           /* Output buffer contains output now or
            * the port was flushed */
-          GST_LOG_OBJECT (comp->parent, "%s port %u filled buffer %p (%p)",
-              comp->name, port->index, buf, buf->omx_buf->pBuffer);
+          GST_LOG_OBJECT (port->comp->parent,
+              "%s port %u filled buffer %p (%p)", port->comp->name, port->index,
+              buf, buf->omx_buf->pBuffer);
 
           if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS)
               && port->port_def.eDir == OMX_DirOutput)
@@ -409,6 +412,46 @@ gst_omx_component_send_message (GstOMXComponent * comp, GstOMXMessage * msg)
   g_mutex_unlock (&comp->messages_lock);
 }
 
+/* NOTE: Call with comp->lock, comp->messages_lock will be used */
+static gboolean
+gst_omx_component_wait_message (GstOMXComponent * comp, GstClockTime timeout)
+{
+  gboolean signalled;
+  gint64 wait_until = -1;
+
+  if (timeout != GST_CLOCK_TIME_NONE) {
+    gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
+
+    if (add == 0)
+      return FALSE;
+
+    wait_until = g_get_monotonic_time () + add;
+    GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
+        comp->name, add);
+  } else {
+    GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+  }
+
+  g_mutex_lock (&comp->messages_lock);
+  g_mutex_unlock (&comp->lock);
+
+  if (!g_queue_is_empty (&comp->messages)) {
+    signalled = TRUE;
+  } else if (timeout == GST_CLOCK_TIME_NONE) {
+    g_cond_wait (&comp->messages_cond, &comp->messages_lock);
+    signalled = TRUE;
+  } else {
+    signalled =
+        g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
+        wait_until);
+  }
+
+  g_mutex_unlock (&comp->messages_lock);
+  g_mutex_lock (&comp->lock);
+
+  return signalled;
+}
+
 static OMX_ERRORTYPE
 EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
     OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
@@ -443,7 +486,7 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
           msg->type = GST_OMX_MESSAGE_FLUSH;
           msg->content.flush.port = nData2;
           GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
-              msg->content.flush.port);
+              (guint) msg->content.flush.port);
 
           gst_omx_component_send_message (comp, msg);
           break;
@@ -456,7 +499,7 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
           msg->content.port_enable.port = nData2;
           msg->content.port_enable.enable = (cmd == OMX_CommandPortEnable);
           GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
-              msg->content.port_enable.port,
+              (guint) msg->content.port_enable.port,
               (msg->content.port_enable.enable ? "enabled" : "disabled"));
 
           gst_omx_component_send_message (comp, msg);
@@ -472,7 +515,7 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
       GstOMXMessage *msg;
 
       /* Yes, this really happens... */
-      if (nData2 == OMX_ErrorNone)
+      if (nData1 == OMX_ErrorNone)
         break;
 
       msg = g_slice_new (GstOMXMessage);
@@ -507,8 +550,8 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
 
       msg->type = GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED;
       msg->content.port_settings_changed.port = index;
-      GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port index: %d)",
-          comp->name, msg->content.port_settings_changed.port);
+      GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port index: %u)",
+          comp->name, (guint) msg->content.port_settings_changed.port);
 
       gst_omx_component_send_message (comp, msg);
       break;
@@ -522,8 +565,8 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
       msg->content.buffer_flag.port = nData1;
       msg->content.buffer_flag.flags = nData2;
       GST_DEBUG_OBJECT (comp->parent, "%s port %u got buffer flags 0x%08x",
-          comp->name, msg->content.buffer_flag.port,
-          msg->content.buffer_flag.flags);
+          comp->name, (guint) msg->content.buffer_flag.port,
+          (guint) msg->content.buffer_flag.flags);
 
       gst_omx_component_send_message (comp, msg);
       break;
@@ -802,7 +845,6 @@ OMX_STATETYPE
 gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout)
 {
   OMX_STATETYPE ret;
-  gint64 wait_until = -1;
   gboolean signalled = TRUE;
 
   g_return_val_if_fail (comp != NULL, OMX_StateInvalid);
@@ -825,37 +867,10 @@ gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout)
     goto done;
   }
 
-  if (timeout != GST_CLOCK_TIME_NONE) {
-    gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
-
-    if (add == 0)
-      goto done;
-
-    wait_until = g_get_monotonic_time () + add;
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
-        comp->name, add);
-  } else {
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
-  }
-
-  gst_omx_component_handle_messages (comp);
   while (signalled && comp->last_error == OMX_ErrorNone
       && comp->pending_state != OMX_StateInvalid) {
-    g_mutex_lock (&comp->messages_lock);
-    g_mutex_unlock (&comp->lock);
-    if (!g_queue_is_empty (&comp->messages)) {
-      signalled = TRUE;
-    }
-    if (timeout == GST_CLOCK_TIME_NONE) {
-      g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-      signalled = TRUE;
-    } else {
-      signalled =
-          g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
-          wait_until);
-    }
-    g_mutex_unlock (&comp->messages_lock);
-    g_mutex_lock (&comp->lock);
+
+    signalled = gst_omx_component_wait_message (comp, timeout);
     if (signalled)
       gst_omx_component_handle_messages (comp);
   };
@@ -1063,23 +1078,22 @@ gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
 }
 
 OMX_ERRORTYPE
-gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1,
-    GstOMXComponent * comp2, GstOMXPort * port2)
+gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2)
 {
+  GstOMXComponent *comp1;
+  GstOMXComponent *comp2;
   OMX_ERRORTYPE err;
 
-  g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined);
-  g_return_val_if_fail (comp1->state == OMX_StateLoaded
-      || !port1->port_def.bEnabled, OMX_ErrorUndefined);
   g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
   g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
       OMX_ErrorUndefined);
-  g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined);
-  g_return_val_if_fail (comp2->state == OMX_StateLoaded
-      || !port2->port_def.bEnabled, OMX_ErrorUndefined);
+  comp1 = port1->comp;
+
   g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
   g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
       OMX_ErrorUndefined);
+  comp2 = port2->comp;
+
   g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
 
   g_mutex_lock (&comp1->lock);
@@ -1108,23 +1122,22 @@ gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1,
 }
 
 OMX_ERRORTYPE
-gst_omx_component_close_tunnel (GstOMXComponent * comp1, GstOMXPort * port1,
-    GstOMXComponent * comp2, GstOMXPort * port2)
+gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2)
 {
+  GstOMXComponent *comp1;
+  GstOMXComponent *comp2;
   OMX_ERRORTYPE err;
 
-  g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined);
-  g_return_val_if_fail (comp1->state == OMX_StateLoaded
-      || !port1->port_def.bEnabled, OMX_ErrorUndefined);
   g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
   g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
       OMX_ErrorUndefined);
-  g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined);
-  g_return_val_if_fail (comp2->state == OMX_StateLoaded
-      || !port2->port_def.bEnabled, OMX_ErrorUndefined);
+  comp1 = port1->comp;
+
   g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
   g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
       OMX_ErrorUndefined);
+  comp2 = port2->comp;
+
   g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
   g_return_val_if_fail (port1->tunneled && port2->tunneled, OMX_ErrorUndefined);
 
@@ -1184,7 +1197,7 @@ OMX_ERRORTYPE
 gst_omx_port_update_port_definition (GstOMXPort * port,
     OMX_PARAM_PORTDEFINITIONTYPE * port_def)
 {
-  OMX_ERRORTYPE err = OMX_ErrorNone;
+  OMX_ERRORTYPE err_get, err_set = OMX_ErrorNone;
   GstOMXComponent *comp;
 
   g_return_val_if_fail (port != NULL, FALSE);
@@ -1192,16 +1205,19 @@ gst_omx_port_update_port_definition (GstOMXPort * port,
   comp = port->comp;
 
   if (port_def)
-    err =
+    err_set =
         gst_omx_component_set_parameter (comp, OMX_IndexParamPortDefinition,
         port_def);
-  gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+  err_get = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
       &port->port_def);
 
   GST_DEBUG_OBJECT (comp->parent, "Updated %s port %u definition: %s (0x%08x)",
-      comp->name, port->index, gst_omx_error_to_string (err), err);
+      comp->name, port->index, gst_omx_error_to_string (err_set), err_set);
 
-  return err;
+  if (err_set != OMX_ErrorNone)
+    return err_set;
+  else
+    return err_get;
 }
 
 /* NOTE: Uses comp->lock and comp->messages_lock */
@@ -1254,12 +1270,7 @@ retry:
           (err = comp->last_error) == OMX_ErrorNone && !port->flushing) {
         GST_DEBUG_OBJECT (comp->parent,
             "Waiting for %s output ports to reconfigure", comp->name);
-        g_mutex_lock (&comp->messages_lock);
-        g_mutex_unlock (&comp->lock);
-        if (g_queue_is_empty (&comp->messages))
-          g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-        g_mutex_unlock (&comp->messages_lock);
-        g_mutex_lock (&comp->lock);
+        gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE);
         gst_omx_component_handle_messages (comp);
       }
       goto retry;
@@ -1318,30 +1329,19 @@ retry:
    * arrives, an error happens, the port is flushing
    * or the port needs to be reconfigured.
    */
-  gst_omx_component_handle_messages (comp);
   if (g_queue_is_empty (&port->pending_buffers)) {
     GST_DEBUG_OBJECT (comp->parent, "Queue of %s port %u is empty",
         comp->name, port->index);
-    g_mutex_lock (&comp->messages_lock);
-    g_mutex_unlock (&comp->lock);
-    if (g_queue_is_empty (&comp->messages))
-      g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-    g_mutex_unlock (&comp->messages_lock);
-    g_mutex_lock (&comp->lock);
-    gst_omx_component_handle_messages (comp);
+    gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE);
 
     /* And now check everything again and maybe get a buffer */
     goto retry;
-  } else {
-    GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers",
-        comp->name, port->index);
-    _buf = g_queue_pop_head (&port->pending_buffers);
-    ret = GST_OMX_ACQUIRE_BUFFER_OK;
-    goto done;
   }
 
-  g_assert_not_reached ();
-  goto retry;
+  GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers",
+      comp->name, port->index);
+  _buf = g_queue_pop_head (&port->pending_buffers);
+  ret = GST_OMX_ACQUIRE_BUFFER_OK;
 
 done:
   g_mutex_unlock (&comp->lock);
@@ -1399,9 +1399,10 @@ gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
     goto done;
   }
 
-  if (port->flushing) {
-    GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing, not releasing "
-        "buffer", comp->name, port->index);
+  if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+    GST_DEBUG_OBJECT (comp->parent,
+        "%s port %u is flushing or disabled, not releasing " "buffer",
+        comp->name, port->index);
     g_queue_push_tail (&port->pending_buffers, buf);
     gst_omx_component_send_message (comp, NULL);
     goto done;
@@ -1414,10 +1415,8 @@ gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
   buf->used = TRUE;
 
   if (port->port_def.eDir == OMX_DirInput) {
-    GST_LOG_OBJECT (comp->parent,"Calling OMX_EmptyThisBuffer. BufHeader:[%p]\n",buf->omx_buf);
     err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf);
   } else {
-      GST_LOG_OBJECT (comp->parent,"Calling OMX_FillThisBuffer. BufHeader:[%p]\n",buf->omx_buf);
     err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
   }
   GST_DEBUG_OBJECT (comp->parent, "Released buffer %p to %s port %u: %s "
@@ -1464,7 +1463,6 @@ gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
 
   port->flushing = flush;
   if (flush) {
-    gint64 wait_until = -1;
     gboolean signalled;
     OMX_ERRORTYPE last_error;
 
@@ -1495,22 +1493,12 @@ gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
       goto done;
     }
 
-    if (timeout != GST_CLOCK_TIME_NONE) {
-      gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
-
-      if (add == 0) {
-        if (!port->flushed || (port->buffers
-                && port->buffers->len >
-                g_queue_get_length (&port->pending_buffers)))
-          err = OMX_ErrorTimeout;
-        goto done;
-      }
-
-      wait_until = g_get_monotonic_time () + add;
-      GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
-          comp->name, add);
-    } else {
-      GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+    if (timeout == 0) {
+      if (!port->flushed || (port->buffers
+              && port->buffers->len >
+              g_queue_get_length (&port->pending_buffers)))
+        err = OMX_ErrorTimeout;
+      goto done;
     }
 
     /* Retry until timeout or until an error happend or
@@ -1522,24 +1510,7 @@ gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
     while (signalled && last_error == OMX_ErrorNone && !port->flushed
         && port->buffers
         && port->buffers->len > g_queue_get_length (&port->pending_buffers)) {
-      g_mutex_lock (&comp->messages_lock);
-      g_mutex_unlock (&comp->lock);
-
-      if (!g_queue_is_empty (&comp->messages)) {
-        signalled = TRUE;
-      }
-      if (timeout == GST_CLOCK_TIME_NONE) {
-        g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-        signalled = TRUE;
-      } else {
-        signalled =
-            g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
-            wait_until);
-      }
-
-      g_mutex_unlock (&comp->messages_lock);
-      g_mutex_lock (&comp->lock);
-
+      signalled = gst_omx_component_wait_message (comp, timeout);
       if (signalled)
         gst_omx_component_handle_messages (comp);
 
@@ -1642,8 +1613,8 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
       OMX_ErrorBadParameter);
 
   GST_INFO_OBJECT (comp->parent,
-      "Allocating %d buffers of size %u for %s port %u", n,
-      port->port_def.nBufferSize, comp->name, port->index);
+      "Allocating %d buffers of size %" G_GSIZE_FORMAT " for %s port %u", n,
+      (size_t) port->port_def.nBufferSize, comp->name, (guint) port->index);
 
   if (!port->buffers)
     port->buffers = g_ptr_array_sized_new (n);
@@ -1668,7 +1639,6 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
     g_ptr_array_add (port->buffers, buf);
 
     if (buffers) {
-
       err =
           OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf,
           port->port_def.nBufferSize, l->data);
@@ -1699,10 +1669,7 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
     g_assert (buf->omx_buf->pAppPrivate == buf);
 
     /* In the beginning all buffers are not owned by the component */
-    GST_DEBUG_OBJECT (comp->parent, "Pushing pending_buffers, port:[%d], Buffer:[%p]",
-        port->index, buf);
     g_queue_push_tail (&port->pending_buffers, buf);
-
     if (buffers || images)
       l = l->next;
   }
@@ -1770,7 +1737,7 @@ gst_omx_port_tbm_allocate_dec_buffers (tbm_bufmgr bufMgr, GstOMXPort * port, int
           ptr->handle.dmabuf_fd[0] = gst_omx_tbm_get_bo_fd(ptr->handle.bo[0]);
           ptr->data[0] = gst_omx_tbm_get_bo_ptr(ptr->handle.bo[0]);
           ptr->size[0] = port->port_def.nBufferSize;
-          ptr->type = MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS;
+          ptr->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
       }
       else { /* output port */
 
@@ -1867,7 +1834,7 @@ gst_omx_port_tbm_allocate_enc_buffers (tbm_bufmgr bufMgr, GstOMXPort * port, int
           ptr->handle.bo[0] = gst_omx_tbm_allocate_bo(bufMgr, port->port_def.nBufferSize);
           ptr->handle.dmabuf_fd[0] = gst_omx_tbm_get_bo_fd(ptr->handle.bo[0]);
           ptr->handle.paddr[0] = gst_omx_tbm_get_bo_ptr(ptr->handle.bo[0]);
-          ptr->type = MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS;
+          ptr->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
           ptr->size[0] = port->port_def.nBufferSize;
           ptr->handle_num = 1;
       }
@@ -2076,13 +2043,6 @@ gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
   else
     port->disabled_pending = TRUE;
 
-  if (!enabled) {
-    /* This is also like flushing, i.e. all buffers are returned
-     * by the component and no new buffers should be passed to
-     * the component anymore */
-    port->flushing = TRUE;
-  }
-
   if (enabled)
     err =
         OMX_SendCommand (comp->handle, OMX_CommandPortEnable, port->index,
@@ -2124,7 +2084,6 @@ gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
   GstOMXComponent *comp;
   OMX_ERRORTYPE err = OMX_ErrorNone;
   OMX_ERRORTYPE last_error;
-  gint64 wait_until = -1;
   gboolean signalled;
 
   comp = port->comp;
@@ -2140,21 +2099,12 @@ gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
   GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to release all "
       "buffers", comp->name, port->index);
 
-  if (timeout != GST_CLOCK_TIME_NONE) {
-    gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
-
-    if (add == 0) {
-      if (port->buffers
-          && port->buffers->len > g_queue_get_length (&port->pending_buffers))
-        err = OMX_ErrorTimeout;
-      goto done;
-    }
-
-    wait_until = g_get_monotonic_time () + add;
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
-        comp->name, add);
-  } else {
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+  if (timeout == 0) {
+    if (!port->flushed || (port->buffers
+            && port->buffers->len >
+            g_queue_get_length (&port->pending_buffers)))
+      err = OMX_ErrorTimeout;
+    goto done;
   }
 
   /* Wait until all buffers are released by the port */
@@ -2164,20 +2114,7 @@ gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
   while (signalled && last_error == OMX_ErrorNone && (port->buffers
           && port->buffers->len >
           g_queue_get_length (&port->pending_buffers))) {
-    g_mutex_lock (&comp->messages_lock);
-    g_mutex_unlock (&comp->lock);
-    if (!g_queue_is_empty (&comp->messages)) {
-      signalled = TRUE;
-    } else if (timeout != GST_CLOCK_TIME_NONE) {
-      signalled =
-          g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
-          wait_until);
-    } else {
-      signalled = TRUE;
-      g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-    }
-    g_mutex_unlock (&comp->messages_lock);
-    g_mutex_lock (&comp->lock);
+    signalled = gst_omx_component_wait_message (comp, timeout);
     if (signalled)
       gst_omx_component_handle_messages (comp);
     last_error = comp->last_error;
@@ -2255,9 +2192,9 @@ gst_omx_port_populate_unlocked (GstOMXPort * port)
 
   gst_omx_component_handle_messages (comp);
 
-  if (port->flushing) {
-    GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing", comp->name,
-        port->index);
+  if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+    GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing or disabled",
+        comp->name, port->index);
     err = OMX_ErrorIncorrectStateOperation;
     goto done;
   }
@@ -2271,9 +2208,6 @@ gst_omx_port_populate_unlocked (GstOMXPort * port)
   if (port->port_def.eDir == OMX_DirOutput && port->buffers && !port->tunneled) {
     /* Enqueue all buffers for the component to fill */
     while ((buf = g_queue_pop_head (&port->pending_buffers))) {
-      if (!buf)
-        continue;
-
       g_assert (!buf->used);
 
       /* Reset all flags, some implementations don't
@@ -2281,7 +2215,7 @@ gst_omx_port_populate_unlocked (GstOMXPort * port)
        * valid anymore after the buffer was consumed
        */
       buf->omx_buf->nFlags = 0;
-      GST_ERROR_OBJECT(comp->parent,"Calling OMX_FillThisBuffer. buffer[%p]. function:[%s]",buf->omx_buf,__func__);
+
       err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
 
       if (err != OMX_ErrorNone) {
@@ -2327,7 +2261,6 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
 {
   GstOMXComponent *comp;
   OMX_ERRORTYPE err = OMX_ErrorNone;
-  gint64 wait_until = -1;
   gboolean signalled;
   OMX_ERRORTYPE last_error;
   gboolean enabled;
@@ -2355,20 +2288,10 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
   GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to be %s",
       comp->name, port->index, (enabled ? "enabled" : "disabled"));
 
-  if (timeout != GST_CLOCK_TIME_NONE) {
-    gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
-
-    if (add == 0) {
-      if (port->enabled_pending || port->disabled_pending)
-        err = OMX_ErrorTimeout;
-      goto done;
-    }
-
-    wait_until = g_get_monotonic_time () + add;
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
-        comp->name, add);
-  } else {
-    GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+  if (timeout == 0) {
+    if (port->enabled_pending || port->disabled_pending)
+      err = OMX_ErrorTimeout;
+    goto done;
   }
 
   /* And now wait until the enable/disable command is finished */
@@ -2379,20 +2302,7 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
   while (signalled && last_error == OMX_ErrorNone &&
       (! !port->port_def.bEnabled != ! !enabled || port->enabled_pending
           || port->disabled_pending)) {
-    g_mutex_lock (&comp->messages_lock);
-    g_mutex_unlock (&comp->lock);
-    if (!g_queue_is_empty (&comp->messages)) {
-      signalled = TRUE;
-    } else if (timeout != GST_CLOCK_TIME_NONE) {
-      signalled =
-          g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
-          wait_until);
-    } else {
-      signalled = TRUE;
-      g_cond_wait (&comp->messages_cond, &comp->messages_lock);
-    }
-    g_mutex_unlock (&comp->messages_lock);
-    g_mutex_lock (&comp->lock);
+    signalled = gst_omx_component_wait_message (comp, timeout);
     if (signalled)
       gst_omx_component_handle_messages (comp);
     last_error = comp->last_error;
@@ -2415,7 +2325,6 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
     err = last_error;
   } else {
     if (enabled) {
-      port->flushing = FALSE;
       /* Reset EOS flag */
       port->eos = FALSE;
     }
@@ -2451,18 +2360,15 @@ gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout)
 gboolean
 gst_omx_port_is_enabled (GstOMXPort * port)
 {
-  GstOMXComponent *comp;
   gboolean enabled;
 
   g_return_val_if_fail (port != NULL, FALSE);
 
-  comp = port->comp;
-
   gst_omx_port_update_port_definition (port, NULL);
   enabled = ! !port->port_def.bEnabled;
 
-  GST_DEBUG_OBJECT (comp->parent, "%s port %u is enabled: %d", comp->name,
-      port->index, enabled);
+  GST_DEBUG_OBJECT (port->comp->parent, "%s port %u is enabled: %d",
+      port->comp->name, port->index, enabled);
 
   return enabled;
 }
@@ -2517,11 +2423,14 @@ done:
 typedef GType (*GGetTypeFunction) (void);
 
 static const GGetTypeFunction types[] = {
+  gst_omx_analog_audio_sink_get_type, gst_omx_hdmi_audio_sink_get_type,
   gst_omx_mpeg2_video_dec_get_type, gst_omx_mpeg4_video_dec_get_type,
   gst_omx_h264_dec_get_type, gst_omx_h263_dec_get_type,
   gst_omx_wmv_dec_get_type, gst_omx_mpeg4_video_enc_get_type,
   gst_omx_h264_enc_get_type, gst_omx_h263_enc_get_type,
-  gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type
+  gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type,
+  gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type,
+  gst_omx_amr_dec_get_type
 #ifdef HAVE_VP8
       , gst_omx_vp8_dec_get_type
 #endif
@@ -2537,8 +2446,10 @@ struct TypeOffest
 };
 
 static const struct TypeOffest base_types[] = {
+  {gst_omx_audio_sink_get_type, G_STRUCT_OFFSET (GstOMXAudioSinkClass, cdata)},
   {gst_omx_video_dec_get_type, G_STRUCT_OFFSET (GstOMXVideoDecClass, cdata)},
   {gst_omx_video_enc_get_type, G_STRUCT_OFFSET (GstOMXVideoEncClass, cdata)},
+  {gst_omx_audio_dec_get_type, G_STRUCT_OFFSET (GstOMXAudioDecClass, cdata)},
   {gst_omx_audio_enc_get_type, G_STRUCT_OFFSET (GstOMXAudioEncClass, cdata)},
 };
 
@@ -2552,7 +2463,9 @@ gst_omx_get_configuration (void)
 const gchar *
 gst_omx_error_to_string (OMX_ERRORTYPE err)
 {
-  switch (err) {
+  guint err_u = (guint) err;
+
+  switch (err_u) {
     case OMX_ErrorNone:
       return "None";
     case OMX_ErrorInsufficientResources:
@@ -2630,11 +2543,11 @@ gst_omx_error_to_string (OMX_ERRORTYPE err)
     case OMX_ErrorTunnelingUnsupported:
       return "Tunneling unsupported";
     default:
-      if (err >= (guint32) OMX_ErrorKhronosExtensions
-          && err < (guint32) OMX_ErrorVendorStartUnused) {
+      if (err_u >= (guint) OMX_ErrorKhronosExtensions
+          && err_u < (guint) OMX_ErrorVendorStartUnused) {
         return "Khronos extension error";
-      } else if (err >= (guint32) OMX_ErrorVendorStartUnused
-          && err < (guint32) OMX_ErrorMax) {
+      } else if (err_u >= (guint) OMX_ErrorVendorStartUnused
+          && err_u < (guint) OMX_ErrorMax) {
         return "Vendor specific error";
       } else {
         return "Unknown error";
@@ -2659,9 +2572,10 @@ gst_omx_state_to_string (OMX_STATETYPE state)
     case OMX_StateWaitForResources:
       return "WaitForResources";
     default:
-      if (state >= OMX_StateKhronosExtensions)
+      if (state >= OMX_StateKhronosExtensions
+          && state < OMX_StateVendorStartUnused)
         return "KhronosExtensionState";
-      else if (state >= OMX_StateVendorStartUnused)
+      else if (state >= OMX_StateVendorStartUnused && state < OMX_StateMax)
         return "CustomVendorState";
       break;
   }
@@ -2683,9 +2597,10 @@ gst_omx_command_to_string (OMX_COMMANDTYPE cmd)
     case OMX_CommandMarkBuffer:
       return "MarkBuffer";
     default:
-      if (cmd >= OMX_CommandKhronosExtensions)
+      if (cmd >= OMX_CommandKhronosExtensions
+          && cmd < OMX_CommandVendorStartUnused)
         return "KhronosExtensionCommand";
-      else if (cmd >= OMX_CommandVendorStartUnused)
+      if (cmd >= OMX_CommandVendorStartUnused && cmd < OMX_CommandMax)
         return "VendorExtensionCommand";
       break;
   }
@@ -2725,6 +2640,8 @@ gst_omx_parse_hacks (gchar ** hacks)
       hacks_flags |= GST_OMX_HACK_DRAIN_MAY_NOT_RETURN;
     else if (g_str_equal (*hacks, "no-component-role"))
       hacks_flags |= GST_OMX_HACK_NO_COMPONENT_ROLE;
+    else if (g_str_equal (*hacks, "no-disable-outport"))
+      hacks_flags |= GST_OMX_HACK_NO_DISABLE_OUTPORT;
     else
       GST_WARNING ("Unknown hack: %s", *hacks);
     hacks++;
@@ -2967,52 +2884,57 @@ _class_init (gpointer g_class, gpointer data)
 
   /* Add pad templates */
   err = NULL;
-  if (!(template_caps =
-          g_key_file_get_string (config, element_name, "sink-template-caps",
-              &err))) {
-    GST_DEBUG
-        ("No sink template caps specified for element '%s', using default '%s'",
-        element_name, class_data->default_sink_template_caps);
-    caps = gst_caps_from_string (class_data->default_sink_template_caps);
-    g_assert (caps != NULL);
-    g_error_free (err);
-  } else {
-    caps = gst_caps_from_string (template_caps);
-    if (!caps) {
+  if (class_data->type != GST_OMX_COMPONENT_TYPE_SOURCE) {
+    if (!(template_caps =
+            g_key_file_get_string (config, element_name, "sink-template-caps",
+                &err))) {
       GST_DEBUG
-          ("Could not parse sink template caps '%s' for element '%s', using default '%s'",
-          template_caps, element_name, class_data->default_sink_template_caps);
+          ("No sink template caps specified for element '%s', using default '%s'",
+          element_name, class_data->default_sink_template_caps);
       caps = gst_caps_from_string (class_data->default_sink_template_caps);
       g_assert (caps != NULL);
+      g_error_free (err);
+    } else {
+      caps = gst_caps_from_string (template_caps);
+      if (!caps) {
+        GST_DEBUG
+            ("Could not parse sink template caps '%s' for element '%s', using default '%s'",
+            template_caps, element_name,
+            class_data->default_sink_template_caps);
+        caps = gst_caps_from_string (class_data->default_sink_template_caps);
+        g_assert (caps != NULL);
+      }
     }
+    templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
+    g_free (template_caps);
+    gst_element_class_add_pad_template (element_class, templ);
   }
-  templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
-  g_free (template_caps);
-  gst_element_class_add_pad_template (element_class, templ);
 
   err = NULL;
-  if (!(template_caps =
-          g_key_file_get_string (config, element_name, "src-template-caps",
-              &err))) {
-    GST_DEBUG
-        ("No src template caps specified for element '%s', using default '%s'",
-        element_name, class_data->default_src_template_caps);
-    caps = gst_caps_from_string (class_data->default_src_template_caps);
-    g_assert (caps != NULL);
-    g_error_free (err);
-  } else {
-    caps = gst_caps_from_string (template_caps);
-    if (!caps) {
+  if (class_data->type != GST_OMX_COMPONENT_TYPE_SINK) {
+    if (!(template_caps =
+            g_key_file_get_string (config, element_name, "src-template-caps",
+                &err))) {
       GST_DEBUG
-          ("Could not parse src template caps '%s' for element '%s', using default '%s'",
-          template_caps, element_name, class_data->default_src_template_caps);
+          ("No src template caps specified for element '%s', using default '%s'",
+          element_name, class_data->default_src_template_caps);
       caps = gst_caps_from_string (class_data->default_src_template_caps);
       g_assert (caps != NULL);
+      g_error_free (err);
+    } else {
+      caps = gst_caps_from_string (template_caps);
+      if (!caps) {
+        GST_DEBUG
+            ("Could not parse src template caps '%s' for element '%s', using default '%s'",
+            template_caps, element_name, class_data->default_src_template_caps);
+        caps = gst_caps_from_string (class_data->default_src_template_caps);
+        g_assert (caps != NULL);
+      }
     }
+    templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
+    g_free (template_caps);
+    gst_element_class_add_pad_template (element_class, templ);
   }
-  templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
-  g_free (template_caps);
-  gst_element_class_add_pad_template (element_class, templ);
 
   if ((hacks =
           g_key_file_get_string_list (config, element_name, "hacks", NULL,
@@ -3046,6 +2968,8 @@ plugin_init (GstPlugin * plugin)
   static const gchar *env_config_name[] = { "GST_OMX_CONFIG_DIR", NULL };
 
   GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-omx");
+  GST_DEBUG_CATEGORY_INIT (gst_omx_video_debug_category, "omxvideo", 0,
+      "gst-omx-video");
 
   /* Read configuration file gstomx.conf from the preferred
    * configuration directories */
index b53bc7d..eca0f73 100644 (file)
 #include <OMX_Core.h>
 #include <OMX_Component.h>
 
+#ifdef USE_OMX_TARGET_EXYNOS
 #include <tbm_type.h>
 #include <tbm_surface.h>
 #include <tbm_bufmgr.h>
+#endif
+
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#endif
+
+#ifdef HAVE_VIDEO_EXT
+#include <OMX_VideoExt.h>
+#endif
+
 #ifdef GST_OMX_STRUCT_PACKING
 #pragma pack()
 #endif
@@ -107,6 +118,11 @@ G_BEGIN_DECLS
  */
 #define GST_OMX_HACK_NO_COMPONENT_ROLE                                G_GUINT64_CONSTANT (0x0000000000000080)
 
+/* If the component doesn't allow disabling the outport while
+ * when setting the format until the output format is known.
+ */
+#define GST_OMX_HACK_NO_DISABLE_OUTPORT                               G_GUINT64_CONSTANT (0x0000000000000100)
+
 typedef struct _GstOMXCore GstOMXCore;
 typedef struct _GstOMXPort GstOMXPort;
 typedef enum _GstOMXPortDirection GstOMXPortDirection;
@@ -300,6 +316,12 @@ typedef enum {
   GST_OMX_MESSAGE_BUFFER_DONE,
 } GstOMXMessageType;
 
+typedef enum {
+  GST_OMX_COMPONENT_TYPE_SINK,
+  GST_OMX_COMPONENT_TYPE_SOURCE,
+  GST_OMX_COMPONENT_TYPE_FILTER
+} GstOmxComponentType;
+
 struct _GstOMXMessage {
   GstOMXMessageType type;
 
@@ -426,6 +448,8 @@ struct _GstOMXClassData {
   guint32 in_port_index, out_port_index;
 
   guint64 hacks;
+
+  GstOmxComponentType type;
 };
 
 GKeyFile *        gst_omx_get_configuration (void);
@@ -457,8 +481,9 @@ OMX_ERRORTYPE     gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_I
 
 OMX_ERRORTYPE     gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
 OMX_ERRORTYPE     gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config);
-OMX_ERRORTYPE     gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, GstOMXComponent * comp2, GstOMXPort * port2);
-OMX_ERRORTYPE     gst_omx_component_close_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, GstOMXComponent * comp2, GstOMXPort * port2);
+
+OMX_ERRORTYPE     gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2);
+OMX_ERRORTYPE     gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2);
 
 
 OMX_ERRORTYPE     gst_omx_port_get_port_definition (GstOMXPort * port, OMX_PARAM_PORTDEFINITIONTYPE * port_def);
@@ -492,15 +517,15 @@ void              gst_omx_set_default_role (GstOMXClassData *class_data, const g
 
 #ifdef USE_TBM
 
-/*MFC Buffer alignment macros*/\r
-#define S5P_FIMV_DEC_BUF_ALIGN                  (8 * 1024)\r
-#define S5P_FIMV_ENC_BUF_ALIGN                  (8 * 1024)\r
-#define S5P_FIMV_NV12M_HALIGN                   16\r
-#define S5P_FIMV_NV12M_LVALIGN                  16\r
-#define S5P_FIMV_NV12M_CVALIGN                  8\r
-#define S5P_FIMV_NV12MT_HALIGN                  128\r
-#define S5P_FIMV_NV12MT_VALIGN                  64\r
-#define S5P_FIMV_NV12M_SALIGN                   2048\r
+/*MFC Buffer alignment macros*/
+#define S5P_FIMV_DEC_BUF_ALIGN                  (8 * 1024)
+#define S5P_FIMV_ENC_BUF_ALIGN                  (8 * 1024)
+#define S5P_FIMV_NV12M_HALIGN                   16
+#define S5P_FIMV_NV12M_LVALIGN                  16
+#define S5P_FIMV_NV12M_CVALIGN                  8
+#define S5P_FIMV_NV12MT_HALIGN                  128
+#define S5P_FIMV_NV12MT_VALIGN                  64
+#define S5P_FIMV_NV12M_SALIGN                   2048
 #define S5P_FIMV_NV12MT_SALIGN                  8192
 
 #define ALIGN(x, a)       (((x) + (a) - 1) & ~((a) - 1))
@@ -534,7 +559,8 @@ OMX_U32           gst_omx_tbm_get_bo_fd(tbm_bo bo);
 OMX_PTR           gst_omx_tbm_get_bo_ptr(tbm_bo bo);
 
 #endif
-
+/* refered by plugin_init */
+GST_DEBUG_CATEGORY_EXTERN (gst_omx_video_debug_category);
 
 G_END_DECLS
 
diff --git a/omx/gstomxaacdec.c b/omx/gstomxaacdec.c
new file mode 100644 (file)
index 0000000..66d881d
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxaacdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_aac_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_aac_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_aac_dec_set_format (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+    GstOMXPort * port);
+static gboolean gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_aac_dec_debug_category, "omxaacdec", 0, \
+      "debug category for gst-omx aac audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAACDec, gst_omx_aac_dec,
+    GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_aac_dec_class_init (GstOMXAACDecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+  audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_aac_dec_set_format);
+  audiodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_aac_dec_is_format_change);
+  audiodec_class->get_samples_per_frame =
+      GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_samples_per_frame);
+  audiodec_class->get_channel_positions =
+      GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_channel_positions);
+
+  audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, "
+      "mpegversion=(int){2, 4}, "
+      "stream-format=(string) { raw, adts, adif, loas }, "
+      "rate=(int)[8000,48000], "
+      "channels=(int)[1,9], " "framed=(boolean) true";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX AAC Audio Decoder",
+      "Codec/Decoder/Audio",
+      "Decode AAC audio streams",
+      "Sebastian Dröge <sebastian@centricular.com>");
+
+  gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.aac");
+}
+
+static void
+gst_omx_aac_dec_init (GstOMXAACDec * self)
+{
+  /* FIXME: Other values exist too! */
+  self->spf = 1024;
+}
+
+static gboolean
+gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels, mpegversion;
+  const gchar *stream_format;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+  err = gst_omx_port_update_port_definition (port, &port_def);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to set AAC format on component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  GST_OMX_INIT_STRUCT (&aac_param);
+  aac_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
+      &aac_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get AAC parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
+      !gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  stream_format = gst_structure_get_string (s, "stream-format");
+  if (!stream_format) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  aac_param.nChannels = channels;
+  aac_param.nSampleRate = rate;
+  aac_param.nBitRate = 0;       /* unknown */
+  aac_param.nAudioBandWidth = 0;        /* decoder decision */
+  aac_param.eChannelMode = 0;   /* FIXME */
+  if (mpegversion == 2)
+    aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS;
+  else if (strcmp (stream_format, "adts") == 0)
+    aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
+  else if (strcmp (stream_format, "loas") == 0)
+    aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS;
+  else if (strcmp (stream_format, "adif") == 0)
+    aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
+  else if (strcmp (stream_format, "raw") == 0)
+    aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
+  else {
+    GST_ERROR_OBJECT (self, "Unexpected format: %s", stream_format);
+    return FALSE;
+  }
+
+  err =
+      gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAac,
+      &aac_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
+  OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels, mpegversion;
+  const gchar *stream_format;
+
+  GST_OMX_INIT_STRUCT (&aac_param);
+  aac_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
+      &aac_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get AAC parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
+      !gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  stream_format = gst_structure_get_string (s, "stream-format");
+  if (!stream_format) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  if (aac_param.nChannels != channels)
+    return TRUE;
+
+  if (aac_param.nSampleRate != rate)
+    return TRUE;
+
+  if (mpegversion == 2
+      && aac_param.eAACStreamFormat != OMX_AUDIO_AACStreamFormatMP2ADTS)
+    return TRUE;
+  if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS &&
+      strcmp (stream_format, "adts") != 0)
+    return TRUE;
+  if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4LOAS &&
+      strcmp (stream_format, "loas") != 0)
+    return TRUE;
+  if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF &&
+      strcmp (stream_format, "adif") != 0)
+    return TRUE;
+  if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW &&
+      strcmp (stream_format, "raw") != 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+static gint
+gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+  return GST_OMX_AAC_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+  OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&pcm_param);
+  pcm_param.nPortIndex = port->index;
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+      &pcm_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  /* FIXME: Rather arbitrary values here, based on what we do in gstfaac.c */
+  switch (pcm_param.nChannels) {
+    case 1:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+      break;
+    case 2:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      break;
+    case 3:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      break;
+    case 4:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
+      break;
+    case 5:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+      position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+      break;
+    case 6:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+      position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+      position[5] = GST_AUDIO_CHANNEL_POSITION_LFE1;
+      break;
+    default:
+      return FALSE;
+  }
+
+  return TRUE;
+}
diff --git a/omx/gstomxaacdec.h b/omx/gstomxaacdec.h
new file mode 100644 (file)
index 0000000..891589b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_AAC_DEC_H__
+#define __GST_OMX_AAC_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AAC_DEC \
+  (gst_omx_aac_dec_get_type())
+#define GST_OMX_AAC_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDec))
+#define GST_OMX_AAC_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass))
+#define GST_OMX_AAC_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass))
+#define GST_IS_OMX_AAC_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AAC_DEC))
+#define GST_IS_OMX_AAC_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AAC_DEC))
+
+typedef struct _GstOMXAACDec GstOMXAACDec;
+typedef struct _GstOMXAACDecClass GstOMXAACDecClass;
+
+struct _GstOMXAACDec
+{
+  GstOMXAudioDec parent;
+  gint spf;
+};
+
+struct _GstOMXAACDecClass
+{
+  GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_aac_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AAC_DEC_H__ */
+
diff --git a/omx/gstomxamrdec.c b/omx/gstomxamrdec.c
new file mode 100644 (file)
index 0000000..78567b6
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ * Copyright (C) 2014, LG Electronics, Inc. <jun.ji@lge.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxamrdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_amr_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_amr_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_amr_dec_set_format (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+    GstOMXPort * port);
+static gboolean gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_amr_dec_debug_category, "omxamrdec", 0, \
+      "debug category for gst-omx amr audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAMRDec, gst_omx_amr_dec,
+    GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_amr_dec_class_init (GstOMXAMRDecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+  audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_amr_dec_set_format);
+  audiodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_amr_dec_is_format_change);
+  audiodec_class->get_samples_per_frame =
+      GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_samples_per_frame);
+  audiodec_class->get_channel_positions =
+      GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_channel_positions);
+
+  audiodec_class->cdata.default_sink_template_caps =
+      "audio/AMR, rate=(int)8000, channels=(int)1; "
+      "audio/AMR-WB, rate=(int)16000, channels=(int)1";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX AMR Audio Decoder",
+      "Codec/Decoder/Audio",
+      "Decode AMR audio streams",
+      "Sebastian Dröge <sebastian@centricular.com>");
+
+  gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.amrnb");
+}
+
+static void
+gst_omx_amr_dec_init (GstOMXAMRDec * self)
+{
+  self->spf = -1;
+}
+
+static gboolean
+gst_omx_amr_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_AUDIO_PARAM_AMRTYPE amr_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;        /* not tested for AMRWB */
+  err = gst_omx_port_update_port_definition (port, &port_def);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to set AMR format on component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  GST_OMX_INIT_STRUCT (&amr_param);
+  amr_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
+      &amr_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get AMR parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  self->rate = rate;
+
+  if (rate == 8000)
+    self->spf = 160;            /* (8000/50) */
+  else if (rate == 16000)
+    self->spf = 320;            /* (16000/50) */
+
+  amr_param.nChannels = channels;
+  amr_param.eAMRBandMode = 0;   /*FIXME: It may require a specific value */
+  amr_param.eAMRDTXMode = 0;
+  amr_param.eAMRFrameFormat = 0;
+
+  err =
+      gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAmr,
+      &amr_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Error setting AMR parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
+  OMX_AUDIO_PARAM_AMRTYPE amr_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels;
+
+  GST_OMX_INIT_STRUCT (&amr_param);
+  amr_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
+      &amr_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get AMR parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  if (self->rate != rate)
+    return TRUE;
+
+  if (amr_param.nChannels != channels)
+    return TRUE;
+
+  return FALSE;
+}
+
+static gint
+gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+  return GST_OMX_AMR_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+  OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&pcm_param);
+  pcm_param.nPortIndex = port->index;
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+      &pcm_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+
+  g_return_val_if_fail (pcm_param.nChannels == 1, FALSE);       /* AMR supports only mono */
+
+  position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+
+  return TRUE;
+}
diff --git a/omx/gstomxamrdec.h b/omx/gstomxamrdec.h
new file mode 100644 (file)
index 0000000..7a2df33
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_AMR_DEC_H__
+#define __GST_OMX_AMR_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AMR_DEC \
+  (gst_omx_amr_dec_get_type())
+#define GST_OMX_AMR_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDec))
+#define GST_OMX_AMR_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDecClass))
+#define GST_OMX_AMR_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AMR_DEC,GstOMXAMRDecClass))
+#define GST_IS_OMX_AMR_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AMR_DEC))
+#define GST_IS_OMX_AMR_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AMR_DEC))
+
+typedef struct _GstOMXAMRDec GstOMXAMRDec;
+typedef struct _GstOMXAMRDecClass GstOMXAMRDecClass;
+
+struct _GstOMXAMRDec
+{
+  GstOMXAudioDec parent;
+  gint spf;
+  gint rate;
+};
+
+struct _GstOMXAMRDecClass
+{
+  GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_amr_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AMR_DEC_H__ */
+
diff --git a/omx/gstomxanalogaudiosink.c b/omx/gstomxanalogaudiosink.c
new file mode 100644 (file)
index 0000000..7c8c885
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxanalogaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_analog_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_analog_audio_sink_debug_category
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_analog_audio_sink_debug_category, \
+      "omxanalogaudiosink", 0, "debug category for gst-omx analog audio sink");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAnalogAudioSink, gst_omx_analog_audio_sink,
+    GST_TYPE_OMX_AUDIO_SINK, DEBUG_INIT);
+
+static void
+gst_omx_analog_audio_sink_class_init (GstOMXAnalogAudioSinkClass * klass)
+{
+  GstOMXAudioSinkClass *audiosink_class = GST_OMX_AUDIO_SINK_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  audiosink_class->cdata.default_sink_template_caps = "audio/x-raw, "
+      "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+      "layout = (string) interleaved, "
+      "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ] ";
+  audiosink_class->destination = "local";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX Analog Audio Sink",
+      "Sink/Audio", "Output analog audio", "Josep Torra <josep@fluendo.com>");
+
+  gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.local");
+}
+
+static void
+gst_omx_analog_audio_sink_init (GstOMXAnalogAudioSink * self)
+{
+}
diff --git a/omx/gstomxanalogaudiosink.h b/omx/gstomxanalogaudiosink.h
new file mode 100644 (file)
index 0000000..7f57048
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_ANALOG_AUDIO_SINK_H__
+#define __GST_OMX_ANALOG_AUDIO_SINK_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiosink.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_ANALOG_AUDIO_SINK \
+  (gst_omx_analog_audio_sink_get_type())
+#define GST_OMX_ANALOG_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSink))
+#define GST_OMX_ANALOG_AUDIO_SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSinkClass))
+#define GST_OMX_ANALOG_AUDIO_SINK_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK,GstOMXAnalogAudioSinkClass))
+#define GST_IS_OMX_ANALOG_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_ANALOG_AUDIO_SINK))
+#define GST_IS_OMX_ANALOG_AUDIO_SINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_ANALOG_AUDIO_SINK))
+
+typedef struct _GstOMXAnalogAudioSink GstOMXAnalogAudioSink;
+typedef struct _GstOMXAnalogAudioSinkClass GstOMXAnalogAudioSinkClass;
+
+struct _GstOMXAnalogAudioSink
+{
+  GstOMXAudioSink parent;
+};
+
+struct _GstOMXAnalogAudioSinkClass
+{
+  GstOMXAudioSinkClass parent_class;
+};
+
+GType gst_omx_analog_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_ANALOG_AUDIO_SINK_H__ */
+
diff --git a/omx/gstomxaudiodec.c b/omx/gstomxaudiodec.c
new file mode 100644 (file)
index 0000000..9b84555
--- /dev/null
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include <string.h>
+
+#include "gstomxaudiodec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_audio_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_audio_dec_debug_category
+
+/* prototypes */
+static void gst_omx_audio_dec_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_omx_audio_dec_change_state (GstElement * element,
+    GstStateChange transition);
+
+static gboolean gst_omx_audio_dec_open (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_close (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_start (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_stop (GstAudioDecoder * decoder);
+static gboolean gst_omx_audio_dec_set_format (GstAudioDecoder * decoder,
+    GstCaps * caps);
+static void gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard);
+static GstFlowReturn gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder,
+    GstBuffer * buffer);
+static GstFlowReturn gst_omx_audio_dec_drain (GstOMXAudioDec * self);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_audio_dec_debug_category, "omxaudiodec", 0, \
+      "debug category for gst-omx audio decoder base class");
+
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXAudioDec, gst_omx_audio_dec,
+    GST_TYPE_AUDIO_DECODER, DEBUG_INIT);
+
+static void
+gst_omx_audio_dec_class_init (GstOMXAudioDecClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstAudioDecoderClass *audio_decoder_class = GST_AUDIO_DECODER_CLASS (klass);
+
+  gobject_class->finalize = gst_omx_audio_dec_finalize;
+
+  element_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_omx_audio_dec_change_state);
+
+  audio_decoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_open);
+  audio_decoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_close);
+  audio_decoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_start);
+  audio_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_stop);
+  audio_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_audio_dec_flush);
+  audio_decoder_class->set_format =
+      GST_DEBUG_FUNCPTR (gst_omx_audio_dec_set_format);
+  audio_decoder_class->handle_frame =
+      GST_DEBUG_FUNCPTR (gst_omx_audio_dec_handle_frame);
+
+  klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+  klass->cdata.default_src_template_caps =
+      "audio/x-raw, "
+      "rate = (int) [ 1, MAX ], "
+      "channels = (int) [ 1, " G_STRINGIFY (OMX_AUDIO_MAXCHANNELS) " ], "
+      "format = (string) " GST_AUDIO_FORMATS_ALL;
+}
+
+static void
+gst_omx_audio_dec_init (GstOMXAudioDec * self)
+{
+  gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (self), TRUE);
+  gst_audio_decoder_set_drainable (GST_AUDIO_DECODER (self), TRUE);
+  gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
+      (self), TRUE);
+  GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (self));
+
+  g_mutex_init (&self->drain_lock);
+  g_cond_init (&self->drain_cond);
+
+  self->output_adapter = gst_adapter_new ();
+}
+
+static gboolean
+gst_omx_audio_dec_open (GstAudioDecoder * decoder)
+{
+  GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+  GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+  gint in_port_index, out_port_index;
+
+  GST_DEBUG_OBJECT (self, "Opening decoder");
+
+  self->dec =
+      gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+      klass->cdata.component_name, klass->cdata.component_role,
+      klass->cdata.hacks);
+  self->started = FALSE;
+
+  if (!self->dec)
+    return FALSE;
+
+  if (gst_omx_component_get_state (self->dec,
+          GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+    return FALSE;
+
+  in_port_index = klass->cdata.in_port_index;
+  out_port_index = klass->cdata.out_port_index;
+
+  if (in_port_index == -1 || out_port_index == -1) {
+    OMX_PORT_PARAM_TYPE param;
+    OMX_ERRORTYPE err;
+
+    GST_OMX_INIT_STRUCT (&param);
+
+    err =
+        gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioInit,
+        &param);
+    if (err != OMX_ErrorNone) {
+      GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      /* Fallback */
+      in_port_index = 0;
+      out_port_index = 1;
+    } else {
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
+      in_port_index = param.nStartPortNumber + 0;
+      out_port_index = param.nStartPortNumber + 1;
+    }
+  }
+  self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
+  self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
+
+  if (!self->dec_in_port || !self->dec_out_port)
+    return FALSE;
+
+  GST_DEBUG_OBJECT (self, "Opened decoder");
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_shutdown (GstOMXAudioDec * self)
+{
+  OMX_STATETYPE state;
+
+  GST_DEBUG_OBJECT (self, "Shutting down decoder");
+
+  state = gst_omx_component_get_state (self->dec, 0);
+  if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+    if (state > OMX_StateIdle) {
+      gst_omx_component_set_state (self->dec, OMX_StateIdle);
+      gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+    }
+    gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+    gst_omx_port_deallocate_buffers (self->dec_in_port);
+    gst_omx_port_deallocate_buffers (self->dec_out_port);
+    if (state > OMX_StateLoaded)
+      gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_close (GstAudioDecoder * decoder)
+{
+  GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+
+  GST_DEBUG_OBJECT (self, "Closing decoder");
+
+  if (!gst_omx_audio_dec_shutdown (self))
+    return FALSE;
+
+  self->dec_in_port = NULL;
+  self->dec_out_port = NULL;
+  if (self->dec)
+    gst_omx_component_free (self->dec);
+  self->dec = NULL;
+
+  self->started = FALSE;
+
+  GST_DEBUG_OBJECT (self, "Closed decoder");
+
+  return TRUE;
+}
+
+static void
+gst_omx_audio_dec_finalize (GObject * object)
+{
+  GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (object);
+
+  g_mutex_clear (&self->drain_lock);
+  g_cond_clear (&self->drain_cond);
+
+  if (self->output_adapter)
+    gst_object_unref (self->output_adapter);
+  self->output_adapter = NULL;
+
+  G_OBJECT_CLASS (gst_omx_audio_dec_parent_class)->finalize (object);
+}
+
+static GstStateChangeReturn
+gst_omx_audio_dec_change_state (GstElement * element, GstStateChange transition)
+{
+  GstOMXAudioDec *self;
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+  g_return_val_if_fail (GST_IS_OMX_AUDIO_DEC (element),
+      GST_STATE_CHANGE_FAILURE);
+  self = GST_OMX_AUDIO_DEC (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      self->downstream_flow_ret = GST_FLOW_OK;
+      self->draining = FALSE;
+      self->started = FALSE;
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (self->dec_in_port)
+        gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+      if (self->dec_out_port)
+        gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+      g_mutex_lock (&self->drain_lock);
+      self->draining = FALSE;
+      g_cond_broadcast (&self->drain_cond);
+      g_mutex_unlock (&self->drain_lock);
+      break;
+    default:
+      break;
+  }
+
+  ret =
+      GST_ELEMENT_CLASS (gst_omx_audio_dec_parent_class)->change_state
+      (element, transition);
+
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      self->downstream_flow_ret = GST_FLOW_FLUSHING;
+      self->started = FALSE;
+
+      if (!gst_omx_audio_dec_shutdown (self))
+        ret = GST_STATE_CHANGE_FAILURE;
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static void
+gst_omx_audio_dec_loop (GstOMXAudioDec * self)
+{
+  GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+  GstOMXPort *port = self->dec_out_port;
+  GstOMXBuffer *buf = NULL;
+  GstFlowReturn flow_ret = GST_FLOW_OK;
+  GstOMXAcquireBufferReturn acq_return;
+  OMX_ERRORTYPE err;
+  gint spf;
+
+  acq_return = gst_omx_port_acquire_buffer (port, &buf);
+  if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+    goto component_error;
+  } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+    goto flushing;
+  } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) {
+    goto eos;
+  }
+
+  if (!gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (self)) ||
+      acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+    OMX_PARAM_PORTDEFINITIONTYPE port_def;
+    OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+    GstAudioChannelPosition omx_position[OMX_AUDIO_MAXCHANNELS];
+    GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+    gint i;
+
+    GST_DEBUG_OBJECT (self, "Port settings have changed, updating caps");
+
+    /* Reallocate all buffers */
+    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE
+        && gst_omx_port_is_enabled (port)) {
+      err = gst_omx_port_set_enabled (port, FALSE);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_deallocate_buffers (port);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+    }
+
+    /* Just update caps */
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+    gst_omx_port_get_port_definition (port, &port_def);
+    g_assert (port_def.format.audio.eEncoding == OMX_AUDIO_CodingPCM);
+
+    GST_OMX_INIT_STRUCT (&pcm_param);
+    pcm_param.nPortIndex = self->dec_out_port->index;
+    err =
+        gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioPcm,
+        &pcm_param);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self, "Failed to get PCM parameters: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      goto caps_failed;
+    }
+
+    g_assert (pcm_param.ePCMMode == OMX_AUDIO_PCMModeLinear);
+    g_assert (pcm_param.bInterleaved == OMX_TRUE);
+
+    gst_audio_info_init (&self->info);
+
+    for (i = 0; i < pcm_param.nChannels; i++) {
+      switch (pcm_param.eChannelMapping[i]) {
+        case OMX_AUDIO_ChannelLF:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+          break;
+        case OMX_AUDIO_ChannelRF:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+          break;
+        case OMX_AUDIO_ChannelCF:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+          break;
+        case OMX_AUDIO_ChannelLS:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
+          break;
+        case OMX_AUDIO_ChannelRS:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
+          break;
+        case OMX_AUDIO_ChannelLFE:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
+          break;
+        case OMX_AUDIO_ChannelCS:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
+          break;
+        case OMX_AUDIO_ChannelLR:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+          break;
+        case OMX_AUDIO_ChannelRR:
+          omx_position[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+          break;
+        case OMX_AUDIO_ChannelNone:
+        default:
+          /* This will break the outer loop too as the
+           * i == pcm_param.nChannels afterwards */
+          for (i = 0; i < pcm_param.nChannels; i++)
+            omx_position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+          break;
+      }
+    }
+    if (pcm_param.nChannels == 1
+        && omx_position[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER)
+      omx_position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+
+    if (omx_position[0] == GST_AUDIO_CHANNEL_POSITION_NONE
+        && klass->get_channel_positions) {
+      GST_WARNING_OBJECT (self,
+          "Failed to get a valid channel layout, trying fallback");
+      klass->get_channel_positions (self, self->dec_out_port, omx_position);
+    }
+
+    memcpy (self->position, omx_position, sizeof (omx_position));
+    gst_audio_channel_positions_to_valid_order (self->position,
+        pcm_param.nChannels);
+    self->needs_reorder =
+        (memcmp (self->position, omx_position,
+            sizeof (GstAudioChannelPosition) * pcm_param.nChannels) != 0);
+    if (self->needs_reorder)
+      gst_audio_get_channel_reorder_map (pcm_param.nChannels, self->position,
+          omx_position, self->reorder_map);
+
+    gst_audio_info_set_format (&self->info,
+        gst_audio_format_build_integer (pcm_param.eNumData ==
+            OMX_NumericalDataSigned,
+            pcm_param.eEndian ==
+            OMX_EndianLittle ? G_LITTLE_ENDIAN : G_BIG_ENDIAN,
+            pcm_param.nBitPerSample, pcm_param.nBitPerSample),
+        pcm_param.nSamplingRate, pcm_param.nChannels, self->position);
+
+    GST_DEBUG_OBJECT (self,
+        "Setting output state: format %s, rate %u, channels %u",
+        gst_audio_format_to_string (self->info.finfo->format),
+        (guint) pcm_param.nSamplingRate, (guint) pcm_param.nChannels);
+
+    if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (self),
+            &self->info)
+        || !gst_audio_decoder_negotiate (GST_AUDIO_DECODER (self))) {
+      if (buf)
+        gst_omx_port_release_buffer (port, buf);
+      goto caps_failed;
+    }
+
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+      err = gst_omx_port_set_enabled (port, TRUE);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_allocate_buffers (port);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_populate (port);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+
+      err = gst_omx_port_mark_reconfigured (port);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+    }
+
+    /* Now get a buffer */
+    if (acq_return != GST_OMX_ACQUIRE_BUFFER_OK) {
+      return;
+    }
+  }
+
+  g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
+  if (!buf) {
+    g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+    goto eos;
+  }
+
+  /* This prevents a deadlock between the srcpad stream
+   * lock and the audiocodec stream lock, if ::reset()
+   * is called at the wrong time
+   */
+  if (gst_omx_port_is_flushing (port)) {
+    GST_DEBUG_OBJECT (self, "Flushing");
+    gst_omx_port_release_buffer (port, buf);
+    goto flushing;
+  }
+
+  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+      (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
+
+  GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+  spf = klass->get_samples_per_frame (self, self->dec_out_port);
+
+  if (buf->omx_buf->nFilledLen > 0) {
+    GstBuffer *outbuf;
+    GstMapInfo minfo;
+
+    GST_DEBUG_OBJECT (self, "Handling output data");
+
+    if (buf->omx_buf->nFilledLen % self->info.bpf != 0) {
+      gst_omx_port_release_buffer (port, buf);
+      goto invalid_buffer;
+    }
+
+    outbuf =
+        gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (self),
+        buf->omx_buf->nFilledLen);
+
+    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
+    if (self->needs_reorder) {
+      gint i, n_samples, c, n_channels;
+      gint *reorder_map = self->reorder_map;
+      gint16 *dest, *source;
+
+      dest = (gint16 *) minfo.data;
+      source = (gint16 *) (buf->omx_buf->pBuffer + buf->omx_buf->nOffset);
+      n_samples = buf->omx_buf->nFilledLen / self->info.bpf;
+      n_channels = self->info.channels;
+
+      for (i = 0; i < n_samples; i++) {
+        for (c = 0; c < n_channels; c++) {
+          dest[i * n_channels + reorder_map[c]] = source[i * n_channels + c];
+        }
+      }
+    } else {
+      memcpy (minfo.data, buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+          buf->omx_buf->nFilledLen);
+    }
+    gst_buffer_unmap (outbuf, &minfo);
+
+    if (spf != -1) {
+      gst_adapter_push (self->output_adapter, outbuf);
+    } else {
+      flow_ret =
+          gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, 1);
+    }
+  }
+
+  GST_DEBUG_OBJECT (self, "Read frame from component");
+
+  if (spf != -1) {
+    GstBuffer *outbuf;
+    guint avail = gst_adapter_available (self->output_adapter);
+    guint nframes;
+
+    /* We take a multiple of codec frames and push
+     * them downstream
+     */
+    avail /= self->info.bpf;
+    nframes = avail / spf;
+    avail = nframes * spf;
+    avail *= self->info.bpf;
+
+    if (avail > 0) {
+      outbuf = gst_adapter_take_buffer (self->output_adapter, avail);
+      flow_ret =
+          gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
+          nframes);
+    }
+  }
+
+  GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
+
+  if (buf) {
+    err = gst_omx_port_release_buffer (port, buf);
+    if (err != OMX_ErrorNone)
+      goto release_error;
+  }
+
+  self->downstream_flow_ret = flow_ret;
+
+  if (flow_ret != GST_FLOW_OK)
+    goto flow_error;
+
+  GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+  return;
+
+component_error:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+        ("OpenMAX component in error state %s (0x%08x)",
+            gst_omx_component_get_last_error_string (self->dec),
+            gst_omx_component_get_last_error (self->dec)));
+    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    self->downstream_flow_ret = GST_FLOW_ERROR;
+    self->started = FALSE;
+    return;
+  }
+
+flushing:
+  {
+    GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    self->downstream_flow_ret = GST_FLOW_FLUSHING;
+    self->started = FALSE;
+    return;
+  }
+
+eos:
+  {
+    spf = klass->get_samples_per_frame (self, self->dec_out_port);
+    if (spf != -1) {
+      GstBuffer *outbuf;
+      guint avail = gst_adapter_available (self->output_adapter);
+      guint nframes;
+
+      /* On EOS we take the complete adapter content, no matter
+       * if it is a multiple of the codec frame size or not.
+       */
+      avail /= self->info.bpf;
+      nframes = (avail + spf - 1) / spf;
+      avail *= self->info.bpf;
+
+      if (avail > 0) {
+        outbuf = gst_adapter_take_buffer (self->output_adapter, avail);
+        flow_ret =
+            gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
+            nframes);
+      }
+    }
+
+    g_mutex_lock (&self->drain_lock);
+    if (self->draining) {
+      GST_DEBUG_OBJECT (self, "Drained");
+      self->draining = FALSE;
+      g_cond_broadcast (&self->drain_cond);
+      flow_ret = GST_FLOW_OK;
+      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    } else {
+      GST_DEBUG_OBJECT (self, "Component signalled EOS");
+      flow_ret = GST_FLOW_EOS;
+    }
+    g_mutex_unlock (&self->drain_lock);
+
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+    self->downstream_flow_ret = flow_ret;
+
+    /* Here we fallback and pause the task for the EOS case */
+    if (flow_ret != GST_FLOW_OK)
+      goto flow_error;
+
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+    return;
+  }
+
+flow_error:
+  {
+    if (flow_ret == GST_FLOW_EOS) {
+      GST_DEBUG_OBJECT (self, "EOS");
+
+      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
+          gst_event_new_eos ());
+      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+      self->started = FALSE;
+    } else if (flow_ret < GST_FLOW_EOS) {
+      GST_ELEMENT_ERROR (self, STREAM, FAILED,
+          ("Internal data stream error."), ("stream stopped, reason %s",
+              gst_flow_get_name (flow_ret)));
+
+      gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
+          gst_event_new_eos ());
+      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+      self->started = FALSE;
+    } else if (flow_ret == GST_FLOW_FLUSHING) {
+      GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+      gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+      self->started = FALSE;
+    }
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+    return;
+  }
+
+reconfigure_error:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Unable to reconfigure output port"));
+    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    self->downstream_flow_ret = GST_FLOW_ERROR;
+    self->started = FALSE;
+    return;
+  }
+
+invalid_buffer:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Invalid sized input buffer"));
+    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+    self->started = FALSE;
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+    return;
+  }
+
+caps_failed:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
+    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+    self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
+    self->started = FALSE;
+    return;
+  }
+release_error:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Failed to relase output buffer to component: %s (0x%08x)",
+            gst_omx_error_to_string (err), err));
+    gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self), gst_event_new_eos ());
+    gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
+    self->downstream_flow_ret = GST_FLOW_ERROR;
+    self->started = FALSE;
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+    return;
+  }
+}
+
+static gboolean
+gst_omx_audio_dec_start (GstAudioDecoder * decoder)
+{
+  GstOMXAudioDec *self;
+
+  self = GST_OMX_AUDIO_DEC (decoder);
+
+  self->last_upstream_ts = 0;
+  self->downstream_flow_ret = GST_FLOW_OK;
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_stop (GstAudioDecoder * decoder)
+{
+  GstOMXAudioDec *self;
+
+  self = GST_OMX_AUDIO_DEC (decoder);
+
+  GST_DEBUG_OBJECT (self, "Stopping decoder");
+
+  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+  gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
+
+  if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
+    gst_omx_component_set_state (self->dec, OMX_StateIdle);
+
+  self->downstream_flow_ret = GST_FLOW_FLUSHING;
+  self->started = FALSE;
+
+  g_mutex_lock (&self->drain_lock);
+  self->draining = FALSE;
+  g_cond_broadcast (&self->drain_cond);
+  g_mutex_unlock (&self->drain_lock);
+
+  gst_adapter_flush (self->output_adapter,
+      gst_adapter_available (self->output_adapter));
+
+  gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+
+  gst_buffer_replace (&self->codec_data, NULL);
+
+  GST_DEBUG_OBJECT (self, "Stopped decoder");
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
+{
+  GstOMXAudioDec *self;
+  GstOMXAudioDecClass *klass;
+  GstStructure *s;
+  const GValue *codec_data;
+  gboolean is_format_change = FALSE;
+  gboolean needs_disable = FALSE;
+
+  self = GST_OMX_AUDIO_DEC (decoder);
+  klass = GST_OMX_AUDIO_DEC_GET_CLASS (decoder);
+
+  GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, caps);
+
+  /* Check if the caps change is a real format change or if only irrelevant
+   * parts of the caps have changed or nothing at all.
+   */
+  if (klass->is_format_change)
+    is_format_change = klass->is_format_change (self, self->dec_in_port, caps);
+
+  needs_disable =
+      gst_omx_component_get_state (self->dec,
+      GST_CLOCK_TIME_NONE) != OMX_StateLoaded;
+  /* If the component is not in Loaded state and a real format change happens
+   * we have to disable the port and re-allocate all buffers. If no real
+   * format change happened we can just exit here.
+   */
+  if (needs_disable && !is_format_change) {
+    GST_DEBUG_OBJECT (self,
+        "Already running and caps did not change the format");
+    return TRUE;
+  }
+
+  if (needs_disable && is_format_change) {
+    GstOMXPort *out_port = self->dec_out_port;
+
+    GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
+
+    gst_omx_audio_dec_drain (self);
+    gst_omx_audio_dec_flush (decoder, FALSE);
+    gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
+
+    if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+      GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+      gst_omx_audio_dec_stop (GST_AUDIO_DECODER (self));
+      gst_omx_audio_dec_close (GST_AUDIO_DECODER (self));
+      GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+      if (!gst_omx_audio_dec_open (GST_AUDIO_DECODER (self)))
+        return FALSE;
+      needs_disable = FALSE;
+    } else {
+      if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (self->dec_in_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (self->dec_in_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
+
+    GST_DEBUG_OBJECT (self, "Decoder drained and disabled");
+  }
+
+  if (klass->set_format) {
+    if (!klass->set_format (self, self->dec_in_port, caps)) {
+      GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
+      return FALSE;
+    }
+  }
+
+  GST_DEBUG_OBJECT (self, "Updating outport port definition");
+  if (gst_omx_port_update_port_definition (self->dec_out_port,
+          NULL) != OMX_ErrorNone)
+    return FALSE;
+
+  /* Get codec data from caps */
+  gst_buffer_replace (&self->codec_data, NULL);
+  s = gst_caps_get_structure (caps, 0);
+  codec_data = gst_structure_get_value (s, "codec_data");
+  if (codec_data) {
+    /* Vorbis and some other codecs have multiple buffers in
+     * the stream-header field */
+    self->codec_data = gst_value_get_buffer (codec_data);
+    if (self->codec_data)
+      gst_buffer_ref (self->codec_data);
+  }
+
+  GST_DEBUG_OBJECT (self, "Enabling component");
+
+  if (needs_disable) {
+    if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
+      return FALSE;
+    if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+      return FALSE;
+
+    if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->dec_out_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
+
+    if (gst_omx_port_wait_enabled (self->dec_in_port,
+            5 * GST_SECOND) != OMX_ErrorNone)
+      return FALSE;
+    if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
+      return FALSE;
+  } else {
+    if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      /* Disable output port */
+      if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->dec_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_component_set_state (self->dec,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+        return FALSE;
+    } else {
+      if (gst_omx_component_set_state (self->dec,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+        return FALSE;
+    }
+
+    if (gst_omx_component_get_state (self->dec,
+            GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+      return FALSE;
+
+    if (gst_omx_component_set_state (self->dec,
+            OMX_StateExecuting) != OMX_ErrorNone)
+      return FALSE;
+
+    if (gst_omx_component_get_state (self->dec,
+            GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+      return FALSE;
+  }
+
+  /* Unset flushing to allow ports to accept data again */
+  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+  if (gst_omx_component_get_last_error (self->dec) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Component in error state: %s (0x%08x)",
+        gst_omx_component_get_last_error_string (self->dec),
+        gst_omx_component_get_last_error (self->dec));
+    return FALSE;
+  }
+
+  self->downstream_flow_ret = GST_FLOW_OK;
+
+  return TRUE;
+}
+
+static void
+gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard)
+{
+  GstOMXAudioDec *self = GST_OMX_AUDIO_DEC (decoder);
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  GST_DEBUG_OBJECT (self, "Flushing decoder");
+
+  if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
+    return;
+
+  /* 0) Pause the components */
+  if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
+    gst_omx_component_set_state (self->dec, OMX_StatePause);
+    gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+  }
+
+  /* 1) Wait until the srcpad loop is stopped,
+   * unlock GST_AUDIO_DECODER_STREAM_LOCK to prevent deadlocks
+   * caused by using this lock from inside the loop function */
+  GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+  gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
+  GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
+  GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+  /* 2) Flush the ports */
+  GST_DEBUG_OBJECT (self, "flushing ports");
+  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+  /* 3) Resume components */
+  gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+  gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+
+  /* 4) Unset flushing to allow ports to accept data again */
+  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
+  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+
+  err = gst_omx_port_populate (self->dec_out_port);
+
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (self, "Failed to populate output port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+  }
+
+  /* Reset our state */
+  gst_adapter_flush (self->output_adapter,
+      gst_adapter_available (self->output_adapter));
+  self->last_upstream_ts = 0;
+  self->downstream_flow_ret = GST_FLOW_OK;
+  self->started = FALSE;
+  GST_DEBUG_OBJECT (self, "Flush finished");
+}
+
+static GstFlowReturn
+gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
+{
+  GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+  GstOMXAudioDec *self;
+  GstOMXPort *port;
+  GstOMXBuffer *buf;
+  GstBuffer *codec_data = NULL;
+  guint offset = 0;
+  GstClockTime timestamp, duration;
+  OMX_ERRORTYPE err;
+  GstMapInfo minfo;
+
+  self = GST_OMX_AUDIO_DEC (decoder);
+
+  GST_DEBUG_OBJECT (self, "Handling frame");
+
+  if (self->downstream_flow_ret != GST_FLOW_OK) {
+    return self->downstream_flow_ret;
+  }
+
+  if (!self->started) {
+    GST_DEBUG_OBJECT (self, "Starting task");
+    gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self),
+        (GstTaskFunction) gst_omx_audio_dec_loop, decoder, NULL);
+  }
+
+  if (inbuf == NULL)
+    return gst_omx_audio_dec_drain (self);
+
+  /* Make sure to keep a reference to the input here,
+   * it can be unreffed from the other thread if
+   * finish_frame() is called */
+  gst_buffer_ref (inbuf);
+
+  timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+  duration = GST_BUFFER_DURATION (inbuf);
+
+  port = self->dec_in_port;
+
+  gst_buffer_map (inbuf, &minfo, GST_MAP_READ);
+
+  while (offset < minfo.size) {
+    /* Make sure to release the base class stream lock, otherwise
+     * _loop() can't call _finish_frame() and we might block forever
+     * because no input buffers are released */
+    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+    acq_ret = gst_omx_port_acquire_buffer (port, &buf);
+
+    if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+      GST_AUDIO_DECODER_STREAM_LOCK (self);
+      goto component_error;
+    } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+      GST_AUDIO_DECODER_STREAM_LOCK (self);
+      goto flushing;
+    } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+      /* Reallocate all buffers */
+      err = gst_omx_port_set_enabled (port, FALSE);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_deallocate_buffers (port);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_set_enabled (port, TRUE);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_allocate_buffers (port);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_mark_reconfigured (port);
+      if (err != OMX_ErrorNone) {
+        GST_AUDIO_DECODER_STREAM_LOCK (self);
+        goto reconfigure_error;
+      }
+
+      /* Now get a new buffer and fill it */
+      GST_AUDIO_DECODER_STREAM_LOCK (self);
+      continue;
+    }
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+    g_assert (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+
+    if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <= 0) {
+      gst_omx_port_release_buffer (port, buf);
+      goto full_buffer;
+    }
+
+    if (self->downstream_flow_ret != GST_FLOW_OK) {
+      gst_omx_port_release_buffer (port, buf);
+      goto flow_error;
+    }
+
+    if (self->codec_data) {
+      GST_DEBUG_OBJECT (self, "Passing codec data to the component");
+
+      codec_data = self->codec_data;
+
+      if (buf->omx_buf->nAllocLen - buf->omx_buf->nOffset <
+          gst_buffer_get_size (codec_data)) {
+        gst_omx_port_release_buffer (port, buf);
+        goto too_large_codec_data;
+      }
+
+      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
+      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+      buf->omx_buf->nFilledLen = gst_buffer_get_size (codec_data);
+      gst_buffer_extract (codec_data, 0,
+          buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+          buf->omx_buf->nFilledLen);
+
+      if (GST_CLOCK_TIME_IS_VALID (timestamp))
+        buf->omx_buf->nTimeStamp =
+            gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
+      else
+        buf->omx_buf->nTimeStamp = 0;
+      buf->omx_buf->nTickCount = 0;
+
+      self->started = TRUE;
+      err = gst_omx_port_release_buffer (port, buf);
+      gst_buffer_replace (&self->codec_data, NULL);
+      if (err != OMX_ErrorNone)
+        goto release_error;
+      /* Acquire new buffer for the actual frame */
+      continue;
+    }
+
+    /* Now handle the frame */
+    GST_DEBUG_OBJECT (self, "Passing frame offset %d to the component", offset);
+
+    /* Copy the buffer content in chunks of size as requested
+     * by the port */
+    buf->omx_buf->nFilledLen =
+        MIN (minfo.size - offset,
+        buf->omx_buf->nAllocLen - buf->omx_buf->nOffset);
+    gst_buffer_extract (inbuf, offset,
+        buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
+        buf->omx_buf->nFilledLen);
+
+    if (timestamp != GST_CLOCK_TIME_NONE) {
+      buf->omx_buf->nTimeStamp =
+          gst_util_uint64_scale (timestamp, OMX_TICKS_PER_SECOND, GST_SECOND);
+      self->last_upstream_ts = timestamp;
+    } else {
+      buf->omx_buf->nTimeStamp = 0;
+    }
+
+    if (duration != GST_CLOCK_TIME_NONE && offset == 0) {
+      buf->omx_buf->nTickCount =
+          gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
+      self->last_upstream_ts += duration;
+    } else {
+      buf->omx_buf->nTickCount = 0;
+    }
+
+    if (offset == 0)
+      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+
+    /* TODO: Set flags
+     *   - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside
+     *     the segment
+     */
+
+    offset += buf->omx_buf->nFilledLen;
+
+    if (offset == minfo.size)
+      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+
+    self->started = TRUE;
+    err = gst_omx_port_release_buffer (port, buf);
+    if (err != OMX_ErrorNone)
+      goto release_error;
+  }
+  gst_buffer_unmap (inbuf, &minfo);
+  gst_buffer_unref (inbuf);
+
+  GST_DEBUG_OBJECT (self, "Passed frame to component");
+
+  return self->downstream_flow_ret;
+
+full_buffer:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+        ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
+            (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
+    return GST_FLOW_ERROR;
+  }
+
+flow_error:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    return self->downstream_flow_ret;
+  }
+
+too_large_codec_data:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
+        ("codec_data larger than supported by OpenMAX port "
+            "(%" G_GSIZE_FORMAT " > %u)", gst_buffer_get_size (codec_data),
+            (guint) self->dec_in_port->port_def.nBufferSize));
+    return GST_FLOW_ERROR;
+  }
+
+component_error:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+        ("OpenMAX component in error state %s (0x%08x)",
+            gst_omx_component_get_last_error_string (self->dec),
+            gst_omx_component_get_last_error (self->dec)));
+    return GST_FLOW_ERROR;
+  }
+
+flushing:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+    return GST_FLOW_FLUSHING;
+  }
+reconfigure_error:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Unable to reconfigure input port"));
+    return GST_FLOW_ERROR;
+  }
+release_error:
+  {
+    gst_buffer_unmap (inbuf, &minfo);
+    gst_buffer_unref (inbuf);
+
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Failed to relase input buffer to component: %s (0x%08x)",
+            gst_omx_error_to_string (err), err));
+
+    return GST_FLOW_ERROR;
+  }
+}
+
+static GstFlowReturn
+gst_omx_audio_dec_drain (GstOMXAudioDec * self)
+{
+  GstOMXAudioDecClass *klass;
+  GstOMXBuffer *buf;
+  GstOMXAcquireBufferReturn acq_ret;
+  OMX_ERRORTYPE err;
+
+  GST_DEBUG_OBJECT (self, "Draining component");
+
+  klass = GST_OMX_AUDIO_DEC_GET_CLASS (self);
+
+  if (!self->started) {
+    GST_DEBUG_OBJECT (self, "Component not started yet");
+    return GST_FLOW_OK;
+  }
+  self->started = FALSE;
+
+  if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+    GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+    return GST_FLOW_OK;
+  }
+
+  /* Make sure to release the base class stream lock, otherwise
+   * _loop() can't call _finish_frame() and we might block forever
+   * because no input buffers are released */
+  GST_AUDIO_DECODER_STREAM_UNLOCK (self);
+
+  /* Send an EOS buffer to the component and let the base
+   * class drop the EOS event. We will send it later when
+   * the EOS buffer arrives on the output port. */
+  acq_ret = gst_omx_port_acquire_buffer (self->dec_in_port, &buf);
+  if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+    GST_ERROR_OBJECT (self, "Failed to acquire buffer for draining: %d",
+        acq_ret);
+    return GST_FLOW_ERROR;
+  }
+
+  g_mutex_lock (&self->drain_lock);
+  self->draining = TRUE;
+  buf->omx_buf->nFilledLen = 0;
+  buf->omx_buf->nTimeStamp =
+      gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
+      GST_SECOND);
+  buf->omx_buf->nTickCount = 0;
+  buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
+  err = gst_omx_port_release_buffer (self->dec_in_port, buf);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    g_mutex_unlock (&self->drain_lock);
+    GST_AUDIO_DECODER_STREAM_LOCK (self);
+    return GST_FLOW_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (self, "Waiting until component is drained");
+
+  if (G_UNLIKELY (self->dec->hacks & GST_OMX_HACK_DRAIN_MAY_NOT_RETURN)) {
+    gint64 wait_until = g_get_monotonic_time () + G_TIME_SPAN_SECOND / 2;
+
+    if (!g_cond_wait_until (&self->drain_cond, &self->drain_lock, wait_until))
+      GST_WARNING_OBJECT (self, "Drain timed out");
+    else
+      GST_DEBUG_OBJECT (self, "Drained component");
+
+  } else {
+    g_cond_wait (&self->drain_cond, &self->drain_lock);
+    GST_DEBUG_OBJECT (self, "Drained component");
+  }
+
+  g_mutex_unlock (&self->drain_lock);
+  GST_AUDIO_DECODER_STREAM_LOCK (self);
+
+  gst_adapter_flush (self->output_adapter,
+      gst_adapter_available (self->output_adapter));
+  self->started = FALSE;
+
+  return GST_FLOW_OK;
+}
diff --git a/omx/gstomxaudiodec.h b/omx/gstomxaudiodec.h
new file mode 100644 (file)
index 0000000..0f4adc6
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_AUDIO_DEC_H__
+#define __GST_OMX_AUDIO_DEC_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiodecoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AUDIO_DEC \
+  (gst_omx_audio_dec_get_type())
+#define GST_OMX_AUDIO_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDec))
+#define GST_OMX_AUDIO_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDecClass))
+#define GST_OMX_AUDIO_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AUDIO_DEC,GstOMXAudioDecClass))
+#define GST_IS_OMX_AUDIO_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AUDIO_DEC))
+#define GST_IS_OMX_AUDIO_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AUDIO_DEC))
+
+typedef struct _GstOMXAudioDec GstOMXAudioDec;
+typedef struct _GstOMXAudioDecClass GstOMXAudioDecClass;
+
+struct _GstOMXAudioDec
+{
+  GstAudioDecoder parent;
+
+  /* < protected > */
+  GstOMXComponent *dec;
+  GstOMXPort *dec_in_port, *dec_out_port;
+  
+  GstBufferPool *in_port_pool, *out_port_pool;
+
+  /* < private > */
+  GstAudioInfo info;
+  GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS];
+  gint reorder_map[OMX_AUDIO_MAXCHANNELS];
+  gboolean needs_reorder;
+  GstBuffer *codec_data;
+  /* TRUE if the component is configured and saw
+   * the first buffer */
+  gboolean started;
+
+  GstClockTime last_upstream_ts;
+
+  /* Draining state */
+  GMutex drain_lock;
+  GCond drain_cond;
+  /* TRUE if EOS buffers shouldn't be forwarded */
+  gboolean draining;
+
+  GstAdapter *output_adapter;
+
+  GstFlowReturn downstream_flow_ret;
+};
+
+struct _GstOMXAudioDecClass
+{
+  GstAudioDecoderClass parent_class;
+
+  GstOMXClassData cdata;
+
+  gboolean (*is_format_change) (GstOMXAudioDec * self, GstOMXPort * port, GstCaps * caps);
+  gboolean (*set_format)       (GstOMXAudioDec * self, GstOMXPort * port, GstCaps * caps);
+  gint     (*get_samples_per_frame) (GstOMXAudioDec * self, GstOMXPort * port);
+  gboolean (*get_channel_positions) (GstOMXAudioDec * self, GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+};
+
+GType gst_omx_audio_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AUDIO_DEC_H__ */
index 9718f8f..8724f5e 100644 (file)
@@ -37,12 +37,12 @@ static GstStateChangeReturn
 gst_omx_audio_enc_change_state (GstElement * element,
     GstStateChange transition);
 
+static gboolean gst_omx_audio_enc_open (GstAudioEncoder * encoder);
+static gboolean gst_omx_audio_enc_close (GstAudioEncoder * encoder);
 static gboolean gst_omx_audio_enc_start (GstAudioEncoder * encoder);
 static gboolean gst_omx_audio_enc_stop (GstAudioEncoder * encoder);
 static gboolean gst_omx_audio_enc_set_format (GstAudioEncoder * encoder,
     GstAudioInfo * info);
-static gboolean gst_omx_audio_enc_sink_event (GstAudioEncoder * encoder,
-    GstEvent * event);
 static GstFlowReturn gst_omx_audio_enc_handle_frame (GstAudioEncoder *
     encoder, GstBuffer * buffer);
 static void gst_omx_audio_enc_flush (GstAudioEncoder * encoder);
@@ -75,6 +75,8 @@ gst_omx_audio_enc_class_init (GstOMXAudioEncClass * klass)
   element_class->change_state =
       GST_DEBUG_FUNCPTR (gst_omx_audio_enc_change_state);
 
+  audio_encoder_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_open);
+  audio_encoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_close);
   audio_encoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_start);
   audio_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_stop);
   audio_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_audio_enc_flush);
@@ -82,9 +84,8 @@ gst_omx_audio_enc_class_init (GstOMXAudioEncClass * klass)
       GST_DEBUG_FUNCPTR (gst_omx_audio_enc_set_format);
   audio_encoder_class->handle_frame =
       GST_DEBUG_FUNCPTR (gst_omx_audio_enc_handle_frame);
-  audio_encoder_class->sink_event =
-      GST_DEBUG_FUNCPTR (gst_omx_audio_enc_sink_event);
 
+  klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_sink_template_caps = "audio/x-raw, "
       "rate = (int) [ 1, MAX ], "
       "channels = (int) [ 1, " G_STRINGIFY (OMX_AUDIO_MAXCHANNELS) " ], "
@@ -100,8 +101,9 @@ gst_omx_audio_enc_init (GstOMXAudioEnc * self)
 }
 
 static gboolean
-gst_omx_audio_enc_open (GstOMXAudioEnc * self)
+gst_omx_audio_enc_open (GstAudioEncoder * encoder)
 {
+  GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (encoder);
   GstOMXAudioEncClass *klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
   gint in_port_index, out_port_index;
 
@@ -137,8 +139,8 @@ gst_omx_audio_enc_open (GstOMXAudioEnc * self)
       in_port_index = 0;
       out_port_index = 1;
     } else {
-      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
-          param.nStartPortNumber);
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
       in_port_index = param.nStartPortNumber + 0;
       out_port_index = param.nStartPortNumber + 1;
     }
@@ -178,8 +180,10 @@ gst_omx_audio_enc_shutdown (GstOMXAudioEnc * self)
 }
 
 static gboolean
-gst_omx_audio_enc_close (GstOMXAudioEnc * self)
+gst_omx_audio_enc_close (GstAudioEncoder * encoder)
 {
+  GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (encoder);
+
   GST_DEBUG_OBJECT (self, "Closing encoder");
 
   if (!gst_omx_audio_enc_shutdown (self))
@@ -217,8 +221,6 @@ gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
-      if (!gst_omx_audio_enc_open (self))
-        ret = GST_STATE_CHANGE_FAILURE;
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       self->downstream_flow_ret = GST_FLOW_OK;
@@ -243,9 +245,6 @@ gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
   ret =
       GST_ELEMENT_CLASS (gst_omx_audio_enc_parent_class)->change_state (element,
       transition);
@@ -264,8 +263,6 @@ gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
         ret = GST_STATE_CHANGE_FAILURE;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
-      if (!gst_omx_audio_enc_close (self))
-        ret = GST_STATE_CHANGE_FAILURE;
       break;
     default:
       break;
@@ -381,8 +378,8 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
     goto eos;
   }
 
-  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
-      buf->omx_buf->nTimeStamp);
+  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+      (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
 
   /* This prevents a deadlock between the srcpad stream
    * lock and the videocodec stream lock, if ::reset()
@@ -513,6 +510,8 @@ eos:
       flow_ret = GST_FLOW_EOS;
     }
     g_mutex_unlock (&self->drain_lock);
+
+    GST_AUDIO_ENCODER_STREAM_LOCK (self);
     self->downstream_flow_ret = flow_ret;
 
     /* Here we fallback and pause the task for the EOS case */
@@ -531,15 +530,20 @@ flow_error:
       gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
-    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
+      self->started = FALSE;
+    } else if (flow_ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."),
           ("stream stopped, reason %s", gst_flow_get_name (flow_ret)));
 
       gst_pad_push_event (GST_AUDIO_ENCODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+      self->started = FALSE;
+    } else if (flow_ret == GST_FLOW_FLUSHING) {
+      GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+      gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
+      self->started = FALSE;
     }
-    self->started = FALSE;
     GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
     return;
   }
@@ -584,7 +588,6 @@ gst_omx_audio_enc_start (GstAudioEncoder * encoder)
   self = GST_OMX_AUDIO_ENC (encoder);
 
   self->last_upstream_ts = 0;
-  self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
 
   return TRUE;
@@ -609,7 +612,6 @@ gst_omx_audio_enc_stop (GstAudioEncoder * encoder)
 
   self->downstream_flow_ret = GST_FLOW_FLUSHING;
   self->started = FALSE;
-  self->eos = FALSE;
 
   g_mutex_lock (&self->drain_lock);
   self->draining = FALSE;
@@ -664,26 +666,37 @@ gst_omx_audio_enc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
     gst_pad_stop_task (GST_AUDIO_ENCODER_SRC_PAD (encoder));
     GST_AUDIO_ENCODER_STREAM_LOCK (self);
 
-    if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_buffers_released (self->enc_in_port,
-            5 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_buffers_released (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_enabled (self->enc_in_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_enabled (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
+    if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+      GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
+      gst_omx_audio_enc_stop (GST_AUDIO_ENCODER (self));
+      gst_omx_audio_enc_close (GST_AUDIO_ENCODER (self));
+      GST_AUDIO_ENCODER_STREAM_LOCK (self);
+
+      if (!gst_omx_audio_enc_open (GST_AUDIO_ENCODER (self)))
+        return FALSE;
+      needs_disable = FALSE;
+    } else {
+      if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (self->enc_in_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (self->enc_in_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
 
     GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
   }
@@ -775,26 +788,51 @@ gst_omx_audio_enc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
       return FALSE;
     if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
       return FALSE;
+
+    if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
+
     if (gst_omx_port_wait_enabled (self->enc_in_port,
             5 * GST_SECOND) != OMX_ErrorNone)
       return FALSE;
     if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
       return FALSE;
   } else {
-    if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone)
-      return FALSE;
-
-    /* Need to allocate buffers to reach Idle state */
-    if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
-      return FALSE;
-
-    /* And disable output port */
-    if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-
-    if (gst_omx_port_wait_enabled (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
+    if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      /* Disable output port */
+      if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_component_set_state (self->enc,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
+    } else {
+      if (gst_omx_component_set_state (self->enc,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+        return FALSE;
+    }
 
     if (gst_omx_component_get_state (self->enc,
             GST_CLOCK_TIME_NONE) != OMX_StateIdle)
@@ -838,8 +876,6 @@ gst_omx_audio_enc_flush (GstAudioEncoder * encoder)
 
   GST_DEBUG_OBJECT (self, "Resetting encoder");
 
-  gst_omx_audio_enc_drain (self);
-
   gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
   gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
 
@@ -856,7 +892,7 @@ gst_omx_audio_enc_flush (GstAudioEncoder * encoder)
   /* Start the srcpad loop again */
   self->last_upstream_ts = 0;
   self->downstream_flow_ret = GST_FLOW_OK;
-  self->eos = FALSE;
+  self->started = FALSE;
   gst_pad_start_task (GST_AUDIO_ENCODER_SRC_PAD (self),
       (GstTaskFunction) gst_omx_audio_enc_loop, encoder, NULL);
 }
@@ -875,17 +911,12 @@ gst_omx_audio_enc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
 
   self = GST_OMX_AUDIO_ENC (encoder);
 
-  if (self->eos) {
-    GST_WARNING_OBJECT (self, "Got frame after EOS");
-    return GST_FLOW_EOS;
-  }
-
   if (self->downstream_flow_ret != GST_FLOW_OK) {
     return self->downstream_flow_ret;
   }
 
   if (inbuf == NULL)
-    return GST_FLOW_OK;
+    return gst_omx_audio_enc_drain (self);
 
   GST_DEBUG_OBJECT (self, "Handling frame");
 
@@ -1001,6 +1032,9 @@ gst_omx_audio_enc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
     if (duration != GST_CLOCK_TIME_NONE) {
       buf->omx_buf->nTickCount =
           gst_util_uint64_scale (buf->omx_buf->nFilledLen, duration, size);
+      buf->omx_buf->nTickCount =
+          gst_util_uint64_scale (buf->omx_buf->nTickCount,
+          OMX_TICKS_PER_SECOND, GST_SECOND);
       self->last_upstream_ts += duration;
     }
 
@@ -1019,7 +1053,7 @@ full_buffer:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
-            buf->omx_buf->nOffset, buf->omx_buf->nAllocLen));
+            (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
     return GST_FLOW_ERROR;
   }
 component_error:
@@ -1051,77 +1085,6 @@ release_error:
   }
 }
 
-static gboolean
-gst_omx_audio_enc_sink_event (GstAudioEncoder * encoder, GstEvent * event)
-{
-  GstOMXAudioEnc *self;
-  GstOMXAudioEncClass *klass;
-  OMX_ERRORTYPE err;
-
-  self = GST_OMX_AUDIO_ENC (encoder);
-  klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
-
-  if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
-    GstOMXBuffer *buf;
-    GstOMXAcquireBufferReturn acq_ret;
-
-    GST_DEBUG_OBJECT (self, "Sending EOS to the component");
-
-    /* Don't send EOS buffer twice, this doesn't work */
-    if (self->eos) {
-      GST_DEBUG_OBJECT (self, "Component is already EOS");
-      return TRUE;
-    }
-    self->eos = TRUE;
-
-    if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
-      GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
-
-      /* Insert a NULL into the queue to signal EOS */
-      g_mutex_lock (&self->enc->lock);
-      g_queue_push_tail (&self->enc_out_port->pending_buffers, NULL);
-      g_mutex_unlock (&self->enc->lock);
-      g_mutex_lock (&self->enc->messages_lock);
-      g_cond_broadcast (&self->enc->messages_cond);
-      g_mutex_unlock (&self->enc->messages_lock);
-      return TRUE;
-    }
-
-    /* Make sure to release the base class stream lock, otherwise
-     * _loop() can't call _finish_frame() and we might block forever
-     * because no input buffers are released */
-    GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
-
-    /* Send an EOS buffer to the component and let the base
-     * class drop the EOS event. We will send it later when
-     * the EOS buffer arrives on the output port. */
-    acq_ret = gst_omx_port_acquire_buffer (self->enc_in_port, &buf);
-    if (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK) {
-      buf->omx_buf->nFilledLen = 0;
-      buf->omx_buf->nTimeStamp =
-          gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
-          GST_SECOND);
-      buf->omx_buf->nTickCount = 0;
-      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
-      err = gst_omx_port_release_buffer (self->enc_in_port, buf);
-      if (err != OMX_ErrorNone) {
-        GST_ERROR_OBJECT (self, "Failed to send EOS to component: %s (0x%08x)",
-            gst_omx_error_to_string (err), err);
-      } else {
-        GST_DEBUG_OBJECT (self, "Sent EOS to the component");
-      }
-    } else {
-      GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", acq_ret);
-    }
-
-    GST_AUDIO_ENCODER_STREAM_LOCK (self);
-
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
 static GstFlowReturn
 gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
 {
@@ -1140,12 +1103,6 @@ gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
   }
   self->started = FALSE;
 
-  /* Don't send EOS buffer twice, this doesn't work */
-  if (self->eos) {
-    GST_DEBUG_OBJECT (self, "Component is EOS already");
-    return GST_FLOW_OK;
-  }
-
   if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
     GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
     return GST_FLOW_OK;
index f7527be..8fe5369 100644 (file)
@@ -60,9 +60,6 @@ struct _GstOMXAudioEnc
 
   GstClockTime last_upstream_ts;
 
-  /* TRUE if upstream is EOS */
-  gboolean eos;
-
   /* Draining state */
   GMutex drain_lock;
   GCond drain_cond;
diff --git a/omx/gstomxaudiosink.c b/omx/gstomxaudiosink.c
new file mode 100644 (file)
index 0000000..1739739
--- /dev/null
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+
+#include <math.h>
+
+#include "gstomxaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_audio_sink_debug_category
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_audio_sink_debug_category, "omxaudiosink", \
+      0, "debug category for gst-omx audio sink base class");
+
+#define DEFAULT_PROP_MUTE       FALSE
+#define DEFAULT_PROP_VOLUME     1.0
+
+#define VOLUME_MAX_DOUBLE       10.0
+#define OUT_CHANNELS(num_channels) ((num_channels) > 4 ? 8: (num_channels) > 2 ? 4: (num_channels))
+
+enum
+{
+  PROP_0,
+  PROP_MUTE,
+  PROP_VOLUME
+};
+
+#define gst_omx_audio_sink_parent_class parent_class
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXAudioSink, gst_omx_audio_sink,
+    GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL);
+    DEBUG_INIT);
+
+#define transform_3_4(type) \
+static inline void \
+transform_3_4_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+  g##type *src = (g##type *) psrc; \
+  g##type *dst = (g##type *) pdst; \
+  for (; len > 0; len--) { \
+    dst[0] = src[0]; \
+    dst[1] = src[1]; \
+    dst[2] = src[2]; \
+    dst[3] = 0; \
+    src += 3; \
+    dst += 4; \
+  } \
+}
+
+#define transform_5_8(type) \
+static inline void \
+transform_5_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+  g##type *src = (g##type *) psrc; \
+  g##type *dst = (g##type *) pdst; \
+  for (; len > 0; len--) { \
+    dst[0] = src[0]; \
+    dst[1] = src[1]; \
+    dst[2] = src[2]; \
+    dst[3] = src[3]; \
+    dst[4] = src[4]; \
+    dst[5] = 0; \
+    dst[6] = 0; \
+    dst[7] = 0; \
+    src += 5; \
+    dst += 8; \
+  } \
+}
+
+#define transform_6_8(type) \
+static inline void \
+transform_6_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+  g##type *src = (g##type *) psrc; \
+  g##type *dst = (g##type *) pdst; \
+  for (; len > 0; len--) { \
+    dst[0] = src[0]; \
+    dst[1] = src[1]; \
+    dst[2] = src[2]; \
+    dst[3] = src[3]; \
+    dst[4] = src[4]; \
+    dst[5] = src[5]; \
+    dst[6] = 0; \
+    dst[7] = 0; \
+    src += 6; \
+    dst += 8; \
+  } \
+}
+
+#define transform_7_8(type) \
+static inline void \
+transform_7_8_##type (gpointer psrc, gpointer pdst, guint len) \
+{ \
+  g##type *src = (g##type *) psrc; \
+  g##type *dst = (g##type *) pdst; \
+  for (; len > 0; len--) { \
+    dst[0] = src[0]; \
+    dst[1] = src[1]; \
+    dst[2] = src[2]; \
+    dst[3] = src[3]; \
+    dst[4] = src[4]; \
+    dst[5] = src[5]; \
+    dst[6] = src[6]; \
+    dst[7] = 0; \
+    src += 7; \
+    dst += 8; \
+  } \
+}
+
+transform_3_4 (int16);
+transform_5_8 (int16);
+transform_6_8 (int16);
+transform_7_8 (int16);
+
+transform_3_4 (int32);
+transform_5_8 (int32);
+transform_6_8 (int32);
+transform_7_8 (int32);
+
+static void inline
+transform (guint in_chan, guint width, gpointer psrc, gpointer pdst, guint len)
+{
+  guint out_chan = OUT_CHANNELS (in_chan);
+  if (width == 16) {
+    switch (out_chan) {
+      case 4:
+        if (in_chan == 3) {
+          transform_3_4_int16 (psrc, pdst, len);
+        } else {
+          g_assert (FALSE);
+        }
+        break;
+      case 8:
+        switch (in_chan) {
+          case 5:
+            transform_5_8_int16 (psrc, pdst, len);
+            break;
+          case 6:
+            transform_6_8_int16 (psrc, pdst, len);
+            break;
+          case 7:
+            transform_7_8_int16 (psrc, pdst, len);
+            break;
+          default:
+            g_assert (FALSE);
+        }
+        break;
+      default:
+        g_assert (FALSE);
+    }
+  } else if (width == 32) {
+    switch (out_chan) {
+      case 4:
+        if (in_chan == 3) {
+          transform_3_4_int32 (psrc, pdst, len);
+        } else {
+          g_assert (FALSE);
+        }
+        break;
+      case 8:
+        switch (in_chan) {
+          case 5:
+            transform_5_8_int32 (psrc, pdst, len);
+            break;
+          case 6:
+            transform_6_8_int32 (psrc, pdst, len);
+            break;
+          case 7:
+            transform_7_8_int32 (psrc, pdst, len);
+            break;
+          default:
+            g_assert (FALSE);
+        }
+        break;
+      default:
+        g_assert (FALSE);
+    }
+  } else {
+    g_assert (FALSE);
+  }
+}
+
+static void
+gst_omx_audio_sink_mute_set (GstOMXAudioSink * self, gboolean mute)
+{
+  if (self->comp) {
+    OMX_ERRORTYPE err;
+    OMX_AUDIO_CONFIG_MUTETYPE param;
+
+    GST_OMX_INIT_STRUCT (&param);
+    param.nPortIndex = self->in_port->index;
+    param.bMute = (mute ? OMX_TRUE : OMX_FALSE);
+    err = gst_omx_component_set_config (self->comp,
+        OMX_IndexConfigAudioMute, &param);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self, "Failed to set mute to %d: %s (0x%08x)",
+          param.bMute, gst_omx_error_to_string (err), err);
+    }
+  }
+  self->mute = mute;
+}
+
+static void
+gst_omx_audio_sink_volume_set (GstOMXAudioSink * self, gdouble volume)
+{
+  if (self->comp) {
+    OMX_ERRORTYPE err;
+    OMX_AUDIO_CONFIG_VOLUMETYPE param;
+    GST_OMX_INIT_STRUCT (&param);
+    param.nPortIndex = self->in_port->index;
+    param.bLinear = OMX_TRUE;
+    param.sVolume.nValue = volume * 100;
+    err = gst_omx_component_set_config (self->comp,
+        OMX_IndexConfigAudioVolume, &param);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self, "Failed to set volume to %d: %s (0x%08x)",
+          (gint) param.sVolume.nValue, gst_omx_error_to_string (err), err);
+    }
+  }
+  self->volume = volume;
+}
+
+static gboolean
+gst_omx_audio_sink_open (GstAudioSink * audiosink)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  GstOMXAudioSinkClass *klass = GST_OMX_AUDIO_SINK_GET_CLASS (self);
+  gint port_index;
+  OMX_ERRORTYPE err;
+
+  GST_DEBUG_OBJECT (self, "Opening audio sink");
+
+  self->comp =
+      gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+      klass->cdata.component_name, klass->cdata.component_role,
+      klass->cdata.hacks);
+
+  if (!self->comp)
+    return FALSE;
+
+  if (gst_omx_component_get_state (self->comp,
+          GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+    return FALSE;
+
+  port_index = klass->cdata.in_port_index;
+
+  if (port_index == -1) {
+    OMX_PORT_PARAM_TYPE param;
+
+    GST_OMX_INIT_STRUCT (&param);
+
+    err =
+        gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+        &param);
+    if (err != OMX_ErrorNone) {
+      GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      /* Fallback */
+      port_index = 0;
+    } else {
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
+      port_index = param.nStartPortNumber + 0;
+    }
+  }
+  self->in_port = gst_omx_component_add_port (self->comp, port_index);
+
+  port_index = klass->cdata.out_port_index;
+
+  if (port_index == -1) {
+    OMX_PORT_PARAM_TYPE param;
+
+    GST_OMX_INIT_STRUCT (&param);
+
+    err =
+        gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+        &param);
+    if (err != OMX_ErrorNone) {
+      GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      /* Fallback */
+      port_index = 0;
+    } else {
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
+      port_index = param.nStartPortNumber + 1;
+    }
+  }
+  self->out_port = gst_omx_component_add_port (self->comp, port_index);
+
+  if (!self->in_port || !self->out_port)
+    return FALSE;
+
+  err = gst_omx_port_set_enabled (self->in_port, FALSE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to disable port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  err = gst_omx_port_set_enabled (self->out_port, FALSE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to disable port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (self, "Opened audio sink");
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_close (GstAudioSink * audiosink)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  OMX_STATETYPE state;
+
+  GST_DEBUG_OBJECT (self, "Closing audio sink");
+
+  state = gst_omx_component_get_state (self->comp, 0);
+  if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+    if (state > OMX_StateIdle) {
+      gst_omx_component_set_state (self->comp, OMX_StateIdle);
+      gst_omx_component_get_state (self->comp, 5 * GST_SECOND);
+    }
+    gst_omx_component_set_state (self->comp, OMX_StateLoaded);
+    gst_omx_port_deallocate_buffers (self->in_port);
+    if (state > OMX_StateLoaded)
+      gst_omx_component_get_state (self->comp, 5 * GST_SECOND);
+  }
+
+  self->in_port = NULL;
+  self->out_port = NULL;
+  if (self->comp)
+    gst_omx_component_free (self->comp);
+  self->comp = NULL;
+
+  GST_DEBUG_OBJECT (self, "Closed audio sink");
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_parse_spec (GstOMXAudioSink * self,
+    GstAudioRingBufferSpec * spec)
+{
+  self->iec61937 = FALSE;
+  self->endianness = GST_AUDIO_INFO_ENDIANNESS (&spec->info);
+  self->rate = GST_AUDIO_INFO_RATE (&spec->info);
+  self->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+  self->width = GST_AUDIO_INFO_WIDTH (&spec->info);
+  self->is_signed = GST_AUDIO_INFO_IS_SIGNED (&spec->info);
+  self->is_float = GST_AUDIO_INFO_IS_FLOAT (&spec->info);
+
+  switch (spec->type) {
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW:
+    {
+      guint out_channels = OUT_CHANNELS (self->channels);
+
+      self->samples = spec->segsize / self->channels / (self->width >> 3);
+      if (self->channels == out_channels) {
+        self->buffer_size = spec->segsize;
+      } else {
+        self->buffer_size = (spec->segsize / self->channels) * out_channels;
+      }
+      break;
+    }
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
+      self->iec61937 = TRUE;
+      self->endianness = G_LITTLE_ENDIAN;
+      self->channels = 2;
+      self->width = 16;
+      self->is_signed = TRUE;
+      self->is_float = FALSE;
+      self->buffer_size = spec->segsize;
+      break;
+    default:
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static inline void
+channel_mapping (GstAudioRingBufferSpec * spec,
+    OMX_AUDIO_CHANNELTYPE * eChannelMapping)
+{
+  gint i, nchan = GST_AUDIO_INFO_CHANNELS (&spec->info);
+
+  for (i = 0; i < nchan; i++) {
+    OMX_AUDIO_CHANNELTYPE pos;
+
+    switch (GST_AUDIO_INFO_POSITION (&spec->info, i)) {
+      case GST_AUDIO_CHANNEL_POSITION_MONO:
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER:
+        pos = OMX_AUDIO_ChannelCF;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT:
+        pos = OMX_AUDIO_ChannelLF;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT:
+        pos = OMX_AUDIO_ChannelRF;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT:
+        pos = OMX_AUDIO_ChannelLS;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT:
+        pos = OMX_AUDIO_ChannelRS;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_LFE1:
+        pos = OMX_AUDIO_ChannelLFE;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER:
+        pos = OMX_AUDIO_ChannelCS;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT:
+        pos = OMX_AUDIO_ChannelLR;
+        break;
+      case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT:
+        pos = OMX_AUDIO_ChannelRR;
+        break;
+      default:
+        pos = OMX_AUDIO_ChannelNone;
+        break;
+    }
+    eChannelMapping[i] = pos;
+  }
+}
+
+static inline const gchar *
+ch2str (OMX_AUDIO_CHANNELTYPE ch)
+{
+  switch (ch) {
+    case OMX_AUDIO_ChannelNone:
+      return "OMX_AUDIO_ChannelNone";
+    case OMX_AUDIO_ChannelLF:
+      return "OMX_AUDIO_ChannelLF";
+    case OMX_AUDIO_ChannelRF:
+      return "OMX_AUDIO_ChannelRF";
+    case OMX_AUDIO_ChannelCF:
+      return "OMX_AUDIO_ChannelCF";
+    case OMX_AUDIO_ChannelLS:
+      return "OMX_AUDIO_ChannelLS";
+    case OMX_AUDIO_ChannelRS:
+      return "OMX_AUDIO_ChannelRS";
+    case OMX_AUDIO_ChannelLFE:
+      return "OMX_AUDIO_ChannelLFE";
+    case OMX_AUDIO_ChannelCS:
+      return "OMX_AUDIO_ChannelCS";
+    case OMX_AUDIO_ChannelLR:
+      return "OMX_AUDIO_ChannelLR";
+    case OMX_AUDIO_ChannelRR:
+      return "OMX_AUDIO_ChannelRR";
+    default:
+      return "Invalid value";
+  }
+}
+
+static inline gboolean
+gst_omx_audio_sink_configure_pcm (GstOMXAudioSink * self,
+    GstAudioRingBufferSpec * spec)
+{
+  OMX_AUDIO_PARAM_PCMMODETYPE param;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = self->in_port->index;
+  param.nChannels = OUT_CHANNELS (self->channels);
+  param.eNumData =
+      (self->is_signed ? OMX_NumericalDataSigned : OMX_NumericalDataUnsigned);
+  param.eEndian =
+      ((self->endianness ==
+          G_LITTLE_ENDIAN) ? OMX_EndianLittle : OMX_EndianBig);
+  param.bInterleaved = OMX_TRUE;
+  param.nBitPerSample = self->width;
+  param.nSamplingRate = self->rate;
+
+  if (self->is_float) {
+    /* This is cherrypicked from xbmc but it doesn't seems to be valid on my RPI.
+     * https://github.com/xbmc/xbmc/blob/master/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
+     */
+    param.ePCMMode = (OMX_AUDIO_PCMMODETYPE) 0x8000;
+  } else {
+    param.ePCMMode = OMX_AUDIO_PCMModeLinear;
+  }
+
+  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW) {
+    channel_mapping (spec, &param.eChannelMapping[0]);
+  }
+
+  GST_DEBUG_OBJECT (self, "Setting PCM parameters");
+  GST_DEBUG_OBJECT (self, "  nChannels: %u", (guint) param.nChannels);
+  GST_DEBUG_OBJECT (self, "  eNumData: %s",
+      (param.eNumData == OMX_NumericalDataSigned ? "signed" : "unsigned"));
+  GST_DEBUG_OBJECT (self, "  eEndian: %s",
+      (param.eEndian == OMX_EndianLittle ? "little endian" : "big endian"));
+  GST_DEBUG_OBJECT (self, "  bInterleaved: %d", param.bInterleaved);
+  GST_DEBUG_OBJECT (self, "  nBitPerSample: %u", (guint) param.nBitPerSample);
+  GST_DEBUG_OBJECT (self, "  nSamplingRate: %u", (guint) param.nSamplingRate);
+  GST_DEBUG_OBJECT (self, "  ePCMMode: %04x", param.ePCMMode);
+  GST_DEBUG_OBJECT (self, "  eChannelMapping: {%s, %s, %s, %s, %s, %s, %s, %s}",
+      ch2str (param.eChannelMapping[0]), ch2str (param.eChannelMapping[1]),
+      ch2str (param.eChannelMapping[2]), ch2str (param.eChannelMapping[3]),
+      ch2str (param.eChannelMapping[4]), ch2str (param.eChannelMapping[5]),
+      ch2str (param.eChannelMapping[6]), ch2str (param.eChannelMapping[7]));
+
+  err =
+      gst_omx_component_set_parameter (self->comp, OMX_IndexParamAudioPcm,
+      &param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set PCM parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_audio_sink_prepare (GstAudioSink * audiosink,
+    GstAudioRingBufferSpec * spec)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_ERRORTYPE err;
+
+  if (!gst_omx_audio_sink_parse_spec (self, spec))
+    goto spec_parse;
+
+  gst_omx_port_get_port_definition (self->in_port, &port_def);
+
+  port_def.nBufferSize = self->buffer_size;
+  /* Only allocate a min number of buffers for transfers from our ringbuffer to
+   * the hw ringbuffer as we want to keep our small */
+  port_def.nBufferCountActual = MAX (port_def.nBufferCountMin, 2);
+  port_def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+  GST_DEBUG_OBJECT (self, "Updating outport port definition");
+  GST_DEBUG_OBJECT (self, "  nBufferSize: %u", (guint) port_def.nBufferSize);
+  GST_DEBUG_OBJECT (self, "  nBufferCountActual: %u", (guint)
+      port_def.nBufferCountActual);
+  GST_DEBUG_OBJECT (self, "  audio.eEncoding: 0x%08x",
+      port_def.format.audio.eEncoding);
+
+  err = gst_omx_port_update_port_definition (self->in_port, &port_def);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to configure port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto configuration;
+  }
+
+  if (!gst_omx_audio_sink_configure_pcm (self, spec)) {
+    goto configuration;
+  }
+
+  err = gst_omx_component_set_state (self->comp, OMX_StateIdle);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set state idle: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  err = gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, FALSE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set port not flushing: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  err = gst_omx_port_set_enabled (self->in_port, TRUE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to enable port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  GST_DEBUG_OBJECT (self, "Allocate buffers");
+  err = gst_omx_port_allocate_buffers (self->in_port);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed on buffer allocation: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  err = gst_omx_port_wait_enabled (self->in_port, 5 * GST_SECOND);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "port not enabled: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  err = gst_omx_port_mark_reconfigured (self->in_port);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Couln't mark port as reconfigured: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  err = gst_omx_component_set_state (self->comp, OMX_StatePause);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set state paused: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto activation;
+  }
+
+  if (gst_omx_component_get_state (self->comp,
+          GST_CLOCK_TIME_NONE) != OMX_StatePause)
+    goto activation;
+
+  /* Configure some parameters */
+  GST_OBJECT_LOCK (self);
+  gst_omx_audio_sink_mute_set (self, self->mute);
+  gst_omx_audio_sink_volume_set (self, self->volume);
+  GST_OBJECT_UNLOCK (self);
+
+#if defined (USE_OMX_TARGET_RPI)
+  {
+    GstOMXAudioSinkClass *klass = GST_OMX_AUDIO_SINK_GET_CLASS (self);
+    OMX_ERRORTYPE err;
+    OMX_CONFIG_BRCMAUDIODESTINATIONTYPE param;
+
+    if (klass->destination
+        && strlen (klass->destination) < sizeof (param.sName)) {
+      GST_DEBUG_OBJECT (self, "Setting destination: %s", klass->destination);
+      GST_OMX_INIT_STRUCT (&param);
+      strcpy ((char *) param.sName, klass->destination);
+      err = gst_omx_component_set_config (self->comp,
+          OMX_IndexConfigBrcmAudioDestination, &param);
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self,
+            "Failed to configuring destination: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        goto activation;
+      }
+    }
+  }
+#endif
+
+  return TRUE;
+
+  /* ERRORS */
+spec_parse:
+  {
+    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+        ("Error parsing spec"));
+    return FALSE;
+  }
+
+configuration:
+  {
+    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+        ("Configuration failed"));
+    return FALSE;
+  }
+activation:
+  {
+    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, (NULL),
+        ("Component activation failed"));
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_omx_audio_sink_unprepare (GstAudioSink * audiosink)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  OMX_ERRORTYPE err;
+
+  if (gst_omx_component_get_state (self->comp, 0) == OMX_StateIdle)
+    return TRUE;
+
+  err = gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, TRUE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set port flushing: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto failed;
+  }
+
+  err = gst_omx_component_set_state (self->comp, OMX_StateIdle);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set state idle: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto failed;
+  }
+
+  err = gst_omx_port_set_enabled (self->in_port, FALSE);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to set port disabled: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto failed;
+  }
+
+  err = gst_omx_port_wait_buffers_released (self->in_port, 5 * GST_SECOND);
+  if (err != OMX_ErrorNone) {
+    goto failed;
+  }
+
+  err = gst_omx_port_deallocate_buffers (self->in_port);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Couldn't deallocate buffers: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    goto failed;
+  }
+
+  err = gst_omx_port_wait_enabled (self->in_port, 1 * GST_SECOND);
+  if (err != OMX_ErrorNone) {
+    goto failed;
+  }
+
+  gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+
+  return TRUE;
+
+  /* ERRORS */
+failed:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+        ("OpenMAX component in error state %s (0x%08x)",
+            gst_omx_component_get_last_error_string (self->comp),
+            gst_omx_component_get_last_error (self->comp)));
+    return FALSE;
+  }
+}
+
+static GstOMXBuffer *
+gst_omx_audio_sink_acquire_buffer (GstOMXAudioSink * self)
+{
+  GstOMXAcquireBufferReturn acq_ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+  GstOMXPort *port = self->in_port;
+  OMX_ERRORTYPE err;
+  GstOMXBuffer *buf = NULL;
+
+  while (!buf) {
+    acq_ret = gst_omx_port_acquire_buffer (port, &buf);
+    if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
+      goto component_error;
+    } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+      GST_DEBUG_OBJECT (self, "Flushing...");
+      goto flushing;
+    } else if (acq_ret == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+      GST_DEBUG_OBJECT (self, "Reconfigure...");
+      /* Reallocate all buffers */
+      err = gst_omx_port_set_enabled (port, FALSE);
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self, "Failed to set port disabled: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_buffers_released (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_deallocate_buffers (port);
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self, "Couldn't deallocate buffers: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_enabled (port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_set_enabled (port, TRUE);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_allocate_buffers (port);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_wait_enabled (port, 5 * GST_SECOND);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+
+      err = gst_omx_port_mark_reconfigured (port);
+      if (err != OMX_ErrorNone) {
+        goto reconfigure_error;
+      }
+      continue;
+    }
+  }
+
+  return buf;
+
+  /* ERRORS */
+component_error:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
+        ("OpenMAX component in error state %s (0x%08x)",
+            gst_omx_component_get_last_error_string (self->comp),
+            gst_omx_component_get_last_error (self->comp)));
+    return NULL;
+  }
+reconfigure_error:
+  {
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Unable to reconfigure input port"));
+    return NULL;
+  }
+flushing:
+  {
+    return NULL;
+  }
+}
+
+static gint
+gst_omx_audio_sink_write (GstAudioSink * audiosink, gpointer data, guint length)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  GstOMXBuffer *buf;
+  OMX_ERRORTYPE err;
+
+  GST_LOG_OBJECT (self, "received audio samples buffer of %u bytes", length);
+
+  GST_OMX_AUDIO_SINK_LOCK (self);
+
+  if (!(buf = gst_omx_audio_sink_acquire_buffer (self))) {
+    goto beach;
+  }
+
+  if (buf->omx_buf->nAllocLen == length) {
+    memcpy (buf->omx_buf->pBuffer + buf->omx_buf->nOffset, data, length);
+  } else {
+    transform (self->channels, self->width, data,
+        buf->omx_buf->pBuffer + buf->omx_buf->nOffset, self->samples);
+  }
+  buf->omx_buf->nFilledLen = buf->omx_buf->nAllocLen;
+
+  err = gst_omx_port_release_buffer (self->in_port, buf);
+  if (err != OMX_ErrorNone)
+    goto release_error;
+
+beach:
+
+  GST_OMX_AUDIO_SINK_UNLOCK (self);
+
+  return length;
+
+  /* ERRORS */
+release_error:
+  {
+    GST_OMX_AUDIO_SINK_UNLOCK (self);
+    GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
+        ("Failed to relase input buffer to component: %s (0x%08x)",
+            gst_omx_error_to_string (err), err));
+    return 0;
+  }
+}
+
+static guint
+gst_omx_audio_sink_delay (GstAudioSink * audiosink)
+{
+#if defined (USE_OMX_TARGET_RPI)
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  OMX_PARAM_U32TYPE param;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = self->in_port->index;
+  param.nU32 = 0;
+  err = gst_omx_component_get_config (self->comp,
+      OMX_IndexConfigAudioRenderingLatency, &param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Failed to get rendering latency: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    param.nU32 = 0;
+  }
+
+  GST_DEBUG_OBJECT (self, "reported delay %u samples", (guint) param.nU32);
+  return param.nU32;
+#else
+  return 0;
+#endif
+}
+
+static void
+gst_omx_audio_sink_reset (GstAudioSink * audiosink)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiosink);
+  OMX_STATETYPE state;
+
+  GST_DEBUG_OBJECT (self, "Flushing sink");
+
+  gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, TRUE);
+
+  GST_OMX_AUDIO_SINK_LOCK (self);
+  if ((state = gst_omx_component_get_state (self->comp, 0)) > OMX_StatePause) {
+    gst_omx_component_set_state (self->comp, OMX_StatePause);
+    gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+  }
+
+  gst_omx_component_set_state (self->comp, state);
+  gst_omx_component_get_state (self->comp, GST_CLOCK_TIME_NONE);
+
+  gst_omx_port_set_flushing (self->in_port, 5 * GST_SECOND, FALSE);
+
+  GST_OMX_AUDIO_SINK_UNLOCK (self);
+}
+
+static GstBuffer *
+gst_omx_audio_sink_payload (GstAudioBaseSink * audiobasesink, GstBuffer * buf)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (audiobasesink);
+
+  if (self->iec61937) {
+    GstBuffer *out;
+    gint framesize;
+    GstMapInfo iinfo, oinfo;
+    GstAudioRingBufferSpec *spec = &audiobasesink->ringbuffer->spec;
+
+    framesize = gst_audio_iec61937_frame_size (spec);
+    if (framesize <= 0)
+      return NULL;
+
+    out = gst_buffer_new_and_alloc (framesize);
+
+    gst_buffer_map (buf, &iinfo, GST_MAP_READ);
+    gst_buffer_map (out, &oinfo, GST_MAP_WRITE);
+
+    if (!gst_audio_iec61937_payload (iinfo.data, iinfo.size,
+            oinfo.data, oinfo.size, spec, G_BIG_ENDIAN)) {
+      gst_buffer_unref (out);
+      return NULL;
+    }
+
+    gst_buffer_unmap (buf, &iinfo);
+    gst_buffer_unmap (out, &oinfo);
+
+    gst_buffer_copy_into (out, buf, GST_BUFFER_COPY_METADATA, 0, -1);
+    return out;
+  }
+
+  return gst_buffer_ref (buf);
+}
+
+static gboolean
+gst_omx_audio_sink_accept_caps (GstOMXAudioSink * self, GstCaps * caps)
+{
+  GstPad *pad = GST_BASE_SINK (self)->sinkpad;
+  GstCaps *pad_caps;
+  GstStructure *st;
+  gboolean ret = FALSE;
+  GstAudioRingBufferSpec spec = { 0 };
+
+  pad_caps = gst_pad_query_caps (pad, caps);
+  if (!pad_caps || gst_caps_is_empty (pad_caps)) {
+    if (pad_caps)
+      gst_caps_unref (pad_caps);
+    ret = FALSE;
+    goto done;
+  }
+  gst_caps_unref (pad_caps);
+
+  /* If we've not got fixed caps, creating a stream might fail, so let's just
+   * return from here with default acceptcaps behaviour */
+  if (!gst_caps_is_fixed (caps))
+    goto done;
+
+  /* parse helper expects this set, so avoid nasty warning
+   * will be set properly later on anyway  */
+  spec.latency_time = GST_SECOND;
+  if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
+    goto done;
+
+  /* Make sure input is framed (one frame per buffer) and can be payloaded */
+  switch (spec.type) {
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_AC3:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_EAC3:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_DTS:
+    case GST_AUDIO_RING_BUFFER_FORMAT_TYPE_MPEG:
+    {
+      gboolean framed = FALSE, parsed = FALSE;
+      st = gst_caps_get_structure (caps, 0);
+
+      gst_structure_get_boolean (st, "framed", &framed);
+      gst_structure_get_boolean (st, "parsed", &parsed);
+      if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
+        goto done;
+    }
+    default:{
+    }
+  }
+  ret = TRUE;
+
+done:
+  gst_caps_replace (&spec.caps, NULL);
+  return ret;
+}
+
+static gboolean
+gst_omx_audio_sink_query (GstBaseSink * basesink, GstQuery * query)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (basesink);
+  gboolean ret;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ACCEPT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_query_parse_accept_caps (query, &caps);
+      ret = gst_omx_audio_sink_accept_caps (self, caps);
+      gst_query_set_accept_caps_result (query, ret);
+      ret = TRUE;
+      break;
+    }
+    default:
+      ret = GST_BASE_SINK_CLASS (parent_class)->query (basesink, query);
+      break;
+  }
+  return ret;
+}
+
+static void
+gst_omx_audio_sink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+  switch (prop_id) {
+    case PROP_MUTE:
+    {
+      gboolean mute = g_value_get_boolean (value);
+      GST_OBJECT_LOCK (self);
+      if (self->mute != mute) {
+        gst_omx_audio_sink_mute_set (self, mute);
+      }
+      GST_OBJECT_UNLOCK (self);
+      break;
+    }
+    case PROP_VOLUME:
+    {
+      gdouble volume = g_value_get_double (value);
+      GST_OBJECT_LOCK (self);
+      if (volume != self->volume) {
+        gst_omx_audio_sink_volume_set (self, volume);
+      }
+      GST_OBJECT_UNLOCK (self);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_omx_audio_sink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+  switch (prop_id) {
+    case PROP_MUTE:
+      GST_OBJECT_LOCK (self);
+      g_value_set_boolean (value, self->mute);
+      GST_OBJECT_UNLOCK (self);
+      break;
+    case PROP_VOLUME:
+      GST_OBJECT_LOCK (self);
+      g_value_set_double (value, self->volume);
+      GST_OBJECT_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstStateChangeReturn
+gst_omx_audio_sink_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (element);
+  OMX_ERRORTYPE err;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+    {
+      GST_DEBUG_OBJECT (self, "going to PLAYING state");
+      err = gst_omx_component_set_state (self->comp, OMX_StateExecuting);
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self, "Failed to set state executing: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        return GST_STATE_CHANGE_FAILURE;
+      }
+
+      if (gst_omx_component_get_state (self->comp,
+              GST_CLOCK_TIME_NONE) != OMX_StateExecuting) {
+        return GST_STATE_CHANGE_FAILURE;
+      }
+      GST_DEBUG_OBJECT (self, "in PLAYING state");
+      break;
+    }
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+    {
+      GST_DEBUG_OBJECT (self, "going to PAUSED state");
+      err = gst_omx_component_set_state (self->comp, OMX_StatePause);
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self, "Failed to set state paused: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        return GST_STATE_CHANGE_FAILURE;
+      }
+
+      if (gst_omx_component_get_state (self->comp,
+              GST_CLOCK_TIME_NONE) != OMX_StatePause) {
+        return GST_STATE_CHANGE_FAILURE;
+      }
+      GST_DEBUG_OBJECT (self, "in PAUSED state");
+      break;
+    }
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static void
+gst_omx_audio_sink_finalize (GObject * object)
+{
+  GstOMXAudioSink *self = GST_OMX_AUDIO_SINK (object);
+
+  g_mutex_clear (&self->lock);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_omx_audio_sink_class_init (GstOMXAudioSinkClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass);
+  GstAudioBaseSinkClass *baudiosink_class = GST_AUDIO_BASE_SINK_CLASS (klass);
+  GstAudioSinkClass *audiosink_class = GST_AUDIO_SINK_CLASS (klass);
+
+  gobject_class->set_property = gst_omx_audio_sink_set_property;
+  gobject_class->get_property = gst_omx_audio_sink_get_property;
+  gobject_class->finalize = gst_omx_audio_sink_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_MUTE,
+      g_param_spec_boolean ("mute", "Mute", "mute channel",
+          DEFAULT_PROP_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_VOLUME,
+      g_param_spec_double ("volume", "Volume", "volume factor, 1.0=100%",
+          0.0, VOLUME_MAX_DOUBLE, DEFAULT_PROP_VOLUME,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  element_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_omx_audio_sink_change_state);
+
+  basesink_class->query = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_query);
+
+  baudiosink_class->payload = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_payload);
+
+  audiosink_class->open = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_open);
+  audiosink_class->close = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_close);
+  audiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_prepare);
+  audiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_unprepare);
+  audiosink_class->write = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_write);
+  audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_delay);
+  audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_omx_audio_sink_reset);
+
+
+  klass->cdata.type = GST_OMX_COMPONENT_TYPE_SINK;
+}
+
+static void
+gst_omx_audio_sink_init (GstOMXAudioSink * self)
+{
+  g_mutex_init (&self->lock);
+
+  self->mute = DEFAULT_PROP_MUTE;
+  self->volume = DEFAULT_PROP_VOLUME;
+
+  /* For the Raspberry PI there's a big hw buffer and 400 ms seems a good
+   * size for our ringbuffer. OpenSL ES Sink also allocates a buffer of 400 ms
+   * in Android so I guess that this should be a sane value for OpenMax in
+   * general. */
+  GST_AUDIO_BASE_SINK (self)->buffer_time = 400000;
+  gst_audio_base_sink_set_provide_clock (GST_AUDIO_BASE_SINK (self), TRUE);
+}
diff --git a/omx/gstomxaudiosink.h b/omx/gstomxaudiosink.h
new file mode 100644 (file)
index 0000000..481b18a
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_AUDIO_SINK_H__
+#define __GST_OMX_AUDIO_SINK_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AUDIO_SINK \
+  (gst_omx_audio_sink_get_type())
+#define GST_OMX_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSink))
+#define GST_OMX_AUDIO_SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSinkClass))
+#define GST_OMX_AUDIO_SINK_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AUDIO_SINK,GstOMXAudioSinkClass))
+#define GST_IS_OMX_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AUDIO_SINK))
+#define GST_IS_OMX_AUDIO_SINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AUDIO_SINK))
+#define GST_OMX_AUDIO_SINK_CAST(obj)      ((GstOMXAudioSink *) (obj))
+
+#define GST_OMX_AUDIO_SINK_GET_LOCK(obj)       (&GST_OMX_AUDIO_SINK_CAST (obj)->lock)
+#define GST_OMX_AUDIO_SINK_LOCK(obj)       (g_mutex_lock (GST_OMX_AUDIO_SINK_GET_LOCK (obj)))
+#define GST_OMX_AUDIO_SINK_UNLOCK(obj)    (g_mutex_unlock (GST_OMX_AUDIO_SINK_GET_LOCK (obj)))
+
+#define PASSTHROUGH_CAPS \
+    "audio/x-ac3, framed = (boolean) true;" \
+    "audio/x-eac3, framed = (boolean) true; " \
+    "audio/x-dts, framed = (boolean) true, " \
+      "block-size = (int) { 512, 1024, 2048 }; " \
+    "audio/mpeg, mpegversion = (int) 1, " \
+      "mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true;"
+
+typedef struct _GstOMXAudioSink GstOMXAudioSink;
+typedef struct _GstOMXAudioSinkClass GstOMXAudioSinkClass;
+
+struct _GstOMXAudioSink
+{
+  GstAudioSink parent;
+
+  /* < protected > */
+  GstOMXComponent *comp;
+  GstOMXPort *in_port, *out_port;
+  
+  gboolean mute;
+  gdouble volume;
+
+  gboolean iec61937;
+  guint endianness;
+  guint rate;
+  guint channels;
+  guint width;
+  gboolean is_signed;
+  gboolean is_float;
+
+  guint buffer_size;
+  guint samples;
+
+  GMutex lock;
+};
+
+struct _GstOMXAudioSinkClass
+{
+  GstAudioSinkClass parent_class;
+
+  GstOMXClassData cdata;
+  const gchar * destination;
+};
+
+GType gst_omx_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AUDIO_SINK_H__ */
+
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
new file mode 100644 (file)
index 0000000..c425684
--- /dev/null
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxbufferpool.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_pool_debug_category);
+#define GST_CAT_DEFAULT gst_omx_buffer_pool_debug_category
+
+typedef struct _GstOMXMemory GstOMXMemory;
+typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator;
+typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass;
+
+struct _GstOMXMemory
+{
+  GstMemory mem;
+
+  GstOMXBuffer *buf;
+};
+
+struct _GstOMXMemoryAllocator
+{
+  GstAllocator parent;
+};
+
+struct _GstOMXMemoryAllocatorClass
+{
+  GstAllocatorClass parent_class;
+};
+
+#define GST_OMX_MEMORY_TYPE "openmax"
+
+static GstMemory *
+gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size,
+    GstAllocationParams * params)
+{
+  g_assert_not_reached ();
+  return NULL;
+}
+
+static void
+gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
+{
+  GstOMXMemory *omem = (GstOMXMemory *) mem;
+
+  /* TODO: We need to remember which memories are still used
+   * so we can wait until everything is released before allocating
+   * new memory
+   */
+
+  g_slice_free (GstOMXMemory, omem);
+}
+
+static gpointer
+gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
+{
+  GstOMXMemory *omem = (GstOMXMemory *) mem;
+
+  return omem->buf->omx_buf->pBuffer + omem->mem.offset;
+}
+
+static void
+gst_omx_memory_unmap (GstMemory * mem)
+{
+}
+
+static GstMemory *
+gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
+{
+  g_assert_not_reached ();
+  return NULL;
+}
+
+GType gst_omx_memory_allocator_get_type (void);
+G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator,
+    GST_TYPE_ALLOCATOR);
+
+#define GST_TYPE_OMX_MEMORY_ALLOCATOR   (gst_omx_memory_allocator_get_type())
+#define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR))
+
+static void
+gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass)
+{
+  GstAllocatorClass *allocator_class;
+
+  allocator_class = (GstAllocatorClass *) klass;
+
+  allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy;
+  allocator_class->free = gst_omx_memory_allocator_free;
+}
+
+static void
+gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator)
+{
+  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+
+  alloc->mem_type = GST_OMX_MEMORY_TYPE;
+  alloc->mem_map = gst_omx_memory_map;
+  alloc->mem_unmap = gst_omx_memory_unmap;
+  alloc->mem_share = gst_omx_memory_share;
+
+  /* default copy & is_span */
+
+  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+static GstMemory *
+gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
+    GstOMXBuffer * buf)
+{
+  GstOMXMemory *mem;
+  gint align;
+
+  /* FIXME: We don't allow sharing because we need to know
+   * when the memory becomes unused and can only then put
+   * it back to the pool. Which is done in the pool's release
+   * function
+   */
+  flags |= GST_MEMORY_FLAG_NO_SHARE;
+
+  /* GStreamer uses a bitmask for the alignment while
+   * OMX uses the alignment itself. So we have to convert
+   * here */
+  align = buf->port->port_def.nBufferAlignment;
+  if (align > 0)
+    align -= 1;
+  if (((align + 1) & align) != 0) {
+    GST_WARNING ("Invalid alignment that is not a power of two: %u",
+        (guint) buf->port->port_def.nBufferAlignment);
+    align = 0;
+  }
+
+  mem = g_slice_new (GstOMXMemory);
+  /* the shared memory is always readonly */
+  gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
+      buf->omx_buf->nAllocLen, align, 0, buf->omx_buf->nAllocLen);
+
+  mem->buf = buf;
+
+  return GST_MEMORY_CAST (mem);
+}
+
+/* Buffer pool for the buffers of an OpenMAX port.
+ *
+ * This pool is only used if we either passed buffers from another
+ * pool to the OMX port or provide the OMX buffers directly to other
+ * elements.
+ *
+ *
+ * A buffer is in the pool if it is currently owned by the port,
+ * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside
+ * the pool after it was taken from the port after it was handled
+ * by the port, i.e. {Empty,Fill}BufferDone.
+ *
+ * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
+ * by someone else and (temporarily) passed to this pool
+ * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of
+ * the buffer will be overriden, and restored in free_buffer(). Other
+ * buffers are just freed there.
+ *
+ * The pool always has a fixed number of minimum and maximum buffers
+ * and these are allocated while starting the pool and released afterwards.
+ * They correspond 1:1 to the OMX buffers of the port, which are allocated
+ * before the pool is started.
+ *
+ * Acquiring a buffer from this pool happens after the OMX buffer has
+ * been acquired from the port. gst_buffer_pool_acquire_buffer() is
+ * supposed to return the buffer that corresponds to the OMX buffer.
+ *
+ * For buffers provided to upstream, the buffer will be passed to
+ * the component manually when it arrives and then unreffed. If the
+ * buffer is released before reaching the component it will be just put
+ * back into the pool as if EmptyBufferDone has happened. If it was
+ * passed to the component, it will be back into the pool when it was
+ * released and EmptyBufferDone has happened.
+ *
+ * For buffers provided to downstream, the buffer will be returned
+ * back to the component (OMX_FillThisBuffer()) when it is released.
+ */
+
+static GQuark gst_omx_buffer_data_quark = 0;
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_buffer_pool_debug_category, "omxbufferpool", 0, \
+      "debug category for gst-omx buffer pool base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXBufferPool, gst_omx_buffer_pool,
+    GST_TYPE_BUFFER_POOL, DEBUG_INIT);
+
+static void gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool,
+    GstBuffer * buffer);
+
+static gboolean
+gst_omx_buffer_pool_start (GstBufferPool * bpool)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+  /* Only allow to start the pool if we still are attached
+   * to a component and port */
+  GST_OBJECT_LOCK (pool);
+  if (!pool->component || !pool->port) {
+    GST_OBJECT_UNLOCK (pool);
+    return FALSE;
+  }
+  GST_OBJECT_UNLOCK (pool);
+
+  return
+      GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
+}
+
+static gboolean
+gst_omx_buffer_pool_stop (GstBufferPool * bpool)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+  gint i = 0;
+
+  /* When not using the default GstBufferPool::GstAtomicQueue then
+   * GstBufferPool::free_buffer is not called while stopping the pool
+   * (because the queue is empty) */
+  for (i = 0; i < pool->buffers->len; i++)
+    GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
+        (bpool, g_ptr_array_index (pool->buffers, i));
+
+  /* Remove any buffers that are there */
+  if(pool->buffers)
+      g_ptr_array_set_size (pool->buffers, 0);
+
+  if (pool->caps)
+    gst_caps_unref (pool->caps);
+  pool->caps = NULL;
+
+  pool->add_videometa = FALSE;
+
+  return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
+}
+
+static const gchar **
+gst_omx_buffer_pool_get_options (GstBufferPool * bpool)
+{
+  static const gchar *raw_video_options[] =
+      { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
+  static const gchar *options[] = { NULL };
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+  GST_OBJECT_LOCK (pool);
+  if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
+      && pool->port->port_def.format.video.eCompressionFormat ==
+      OMX_VIDEO_CodingUnused) {
+    GST_OBJECT_UNLOCK (pool);
+    return raw_video_options;
+  }
+  GST_OBJECT_UNLOCK (pool);
+
+  return options;
+}
+
+static gboolean
+gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+  GstCaps *caps;
+
+  GST_OBJECT_LOCK (pool);
+
+  if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
+    goto wrong_config;
+
+  if (caps == NULL)
+    goto no_caps;
+
+  if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
+      && pool->port->port_def.format.video.eCompressionFormat ==
+      OMX_VIDEO_CodingUnused) {
+    GstVideoInfo info;
+
+    /* now parse the caps from the config */
+    if (!gst_video_info_from_caps (&info, caps))
+      goto wrong_video_caps;
+
+    /* enable metadata based on config of the pool */
+    pool->add_videometa =
+        gst_buffer_pool_config_has_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+    pool->video_info = info;
+  }
+
+  if (pool->caps)
+    gst_caps_unref (pool->caps);
+  pool->caps = gst_caps_ref (caps);
+
+  GST_OBJECT_UNLOCK (pool);
+
+  return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
+      (bpool, config);
+
+  /* ERRORS */
+wrong_config:
+  {
+    GST_OBJECT_UNLOCK (pool);
+    GST_WARNING_OBJECT (pool, "invalid config");
+    return FALSE;
+  }
+no_caps:
+  {
+    GST_OBJECT_UNLOCK (pool);
+    GST_WARNING_OBJECT (pool, "no caps in config");
+    return FALSE;
+  }
+wrong_video_caps:
+  {
+    GST_OBJECT_UNLOCK (pool);
+    GST_WARNING_OBJECT (pool,
+        "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+    return FALSE;
+  }
+}
+
+static GstFlowReturn
+gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
+    GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+  GstBuffer *buf;
+  GstOMXBuffer *omx_buf;
+
+  g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
+
+  omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index);
+  g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR);
+
+  if (pool->other_pool) {
+    guint i, n;
+
+    buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
+    g_assert (pool->other_pool == buf->pool);
+    gst_object_replace ((GstObject **) & buf->pool, NULL);
+
+    n = gst_buffer_n_memory (buf);
+    for (i = 0; i < n; i++) {
+      GstMemory *mem = gst_buffer_peek_memory (buf, i);
+
+      /* FIXME: We don't allow sharing because we need to know
+       * when the memory becomes unused and can only then put
+       * it back to the pool. Which is done in the pool's release
+       * function
+       */
+      GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE);
+    }
+
+    if (pool->add_videometa) {
+      GstVideoMeta *meta;
+
+      meta = gst_buffer_get_video_meta (buf);
+      if (!meta) {
+        gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE,
+            GST_VIDEO_INFO_FORMAT (&pool->video_info),
+            GST_VIDEO_INFO_WIDTH (&pool->video_info),
+            GST_VIDEO_INFO_HEIGHT (&pool->video_info));
+      }
+    }
+
+    pool->need_copy = FALSE;
+  } else {
+    GstMemory *mem;
+    const guint nstride = pool->port->port_def.format.video.nStride;
+    const guint nslice = pool->port->port_def.format.video.nSliceHeight;
+    gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
+    gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+
+    mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
+    buf = gst_buffer_new ();
+    gst_buffer_append_memory (buf, mem);
+    g_ptr_array_add (pool->buffers, buf);
+
+    switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
+      case GST_VIDEO_FORMAT_ABGR:
+      case GST_VIDEO_FORMAT_ARGB:
+      case GST_VIDEO_FORMAT_RGB16:
+      case GST_VIDEO_FORMAT_BGR16:
+      case GST_VIDEO_FORMAT_YUY2:
+      case GST_VIDEO_FORMAT_UYVY:
+      case GST_VIDEO_FORMAT_YVYU:
+      case GST_VIDEO_FORMAT_GRAY8:
+        break;
+      case GST_VIDEO_FORMAT_I420:
+        stride[1] = nstride / 2;
+        offset[1] = offset[0] + stride[0] * nslice;
+        stride[2] = nstride / 2;
+        offset[2] = offset[1] + (stride[1] * nslice / 2);
+        break;
+      case GST_VIDEO_FORMAT_NV12:
+      case GST_VIDEO_FORMAT_NV16:
+        stride[1] = nstride;
+        offset[1] = offset[0] + stride[0] * nslice;
+        break;
+       case GST_VIDEO_FORMAT_SN12:
+       case GST_VIDEO_FORMAT_ST12:
+          offset[0] = 0;
+          stride[0] = pool->port->port_def.format.video.nStride;
+          offset[1] =
+              stride[0] * pool->port->port_def.format.video.nSliceHeight;
+          stride[1] = pool->port->port_def.format.video.nStride;
+          break;               
+      default:
+        g_assert_not_reached ();
+        break;
+    }
+
+    if (pool->add_videometa) {
+      pool->need_copy = FALSE;
+    } else {
+      GstVideoInfo info;
+      gboolean need_copy = FALSE;
+      gint i;
+
+      gst_video_info_init (&info);
+      gst_video_info_set_format (&info,
+          GST_VIDEO_INFO_FORMAT (&pool->video_info),
+          GST_VIDEO_INFO_WIDTH (&pool->video_info),
+          GST_VIDEO_INFO_HEIGHT (&pool->video_info));
+
+      for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) {
+        if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) {
+          need_copy = TRUE;
+          break;
+        }
+      }
+
+      pool->need_copy = need_copy;
+    }
+
+    if (pool->need_copy || pool->add_videometa) {
+      /* We always add the videometa. It's the job of the user
+       * to copy the buffer if pool->need_copy is TRUE
+       */
+      gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+          GST_VIDEO_INFO_FORMAT (&pool->video_info),
+          GST_VIDEO_INFO_WIDTH (&pool->video_info),
+          GST_VIDEO_INFO_HEIGHT (&pool->video_info),
+          GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
+    }
+  }
+
+  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
+      gst_omx_buffer_data_quark, omx_buf, NULL);
+
+  *buffer = buf;
+
+  pool->current_buffer_index++;
+
+  return GST_FLOW_OK;
+}
+
+static void
+gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+  /* If the buffers belong to another pool, restore them now */
+  GST_OBJECT_LOCK (pool);
+  if (pool->other_pool) {
+    gst_object_replace ((GstObject **) & buffer->pool,
+        (GstObject *) pool->other_pool);
+  }
+  GST_OBJECT_UNLOCK (pool);
+
+  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
+      gst_omx_buffer_data_quark, NULL, NULL);
+
+  GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
+      buffer);
+}
+
+static GstFlowReturn
+gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
+    GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
+{
+  GstFlowReturn ret;
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+
+  if (pool->port->port_def.eDir == OMX_DirOutput) {
+    GstBuffer *buf;
+
+    g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
+
+    buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
+    g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+    *buffer = buf;
+    ret = GST_FLOW_OK;
+
+    /* If it's our own memory we have to set the sizes */
+    if (!pool->other_pool) {
+      GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
+
+      g_assert (mem
+          && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
+      mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
+      mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
+    }
+  } else {
+    /* Acquire any buffer that is available to be filled by upstream */
+    ret =
+        GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
+        (bpool, buffer, params);
+  }
+
+  return ret;
+}
+
+static void
+gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+  OMX_ERRORTYPE err;
+  GstOMXBuffer *omx_buf;
+
+  g_assert (pool->component && pool->port);
+
+  if (!pool->allocating && !pool->deactivated) {
+    omx_buf =
+        gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
+        gst_omx_buffer_data_quark);
+    if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
+      /* Release back to the port, can be filled again */
+      err = gst_omx_port_release_buffer (pool->port, omx_buf);
+      if (err != OMX_ErrorNone) {
+        GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
+            ("Failed to relase output buffer to component: %s (0x%08x)",
+                gst_omx_error_to_string (err), err));
+      }
+    } else if (!omx_buf->used) {
+      /* TODO: Implement.
+       *
+       * If not used (i.e. was not passed to the component) this should do
+       * the same as EmptyBufferDone.
+       * If it is used (i.e. was passed to the component) this should do
+       * nothing until EmptyBufferDone.
+       *
+       * EmptyBufferDone should release the buffer to the pool so it can
+       * be allocated again
+       *
+       * Needs something to call back here in EmptyBufferDone, like keeping
+       * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
+       * would ensure that the buffer is always unused when this is called.
+       */
+      g_assert_not_reached ();
+      GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
+          (bpool, buffer);
+    }
+  }
+}
+
+static void
+gst_omx_buffer_pool_finalize (GObject * object)
+{
+  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
+
+  if (pool->element)
+    gst_object_unref (pool->element);
+  pool->element = NULL;
+
+  if (pool->buffers)
+    g_ptr_array_unref (pool->buffers);
+  pool->buffers = NULL;
+
+  if (pool->other_pool)
+    gst_object_unref (pool->other_pool);
+  pool->other_pool = NULL;
+
+  if (pool->allocator)
+    gst_object_unref (pool->allocator);
+  pool->allocator = NULL;
+
+  if (pool->caps)
+    gst_caps_unref (pool->caps);
+  pool->caps = NULL;
+
+  G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
+}
+
+static void
+gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
+
+  gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
+
+  gobject_class->finalize = gst_omx_buffer_pool_finalize;
+  gstbufferpool_class->start = gst_omx_buffer_pool_start;
+  gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
+  gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
+  gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
+  gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
+  gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
+  gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
+  gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
+}
+
+static void
+gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
+{
+  pool->buffers = g_ptr_array_new ();
+  pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
+}
+
+GstBufferPool *
+gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
+    GstOMXPort * port)
+{
+  GstOMXBufferPool *pool;
+
+  pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
+  pool->element = gst_object_ref (element);
+  pool->component = component;
+  pool->port = port;
+
+  return GST_BUFFER_POOL (pool);
+}
diff --git a/omx/gstomxbufferpool.h b/omx/gstomxbufferpool.h
new file mode 100644 (file)
index 0000000..76f9680
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *   Author: Christian König <christian.koenig@amd.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_BUFFER_POOL_H__
+#define __GST_OMX_BUFFER_POOL_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_BUFFER_POOL \
+  (gst_omx_buffer_pool_get_type())
+#define GST_OMX_BUFFER_POOL(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_BUFFER_POOL,GstOMXBufferPool))
+#define GST_IS_OMX_BUFFER_POOL(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_BUFFER_POOL))
+
+typedef struct _GstOMXBufferPool GstOMXBufferPool;
+typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass;
+
+struct _GstOMXBufferPool
+{
+  GstVideoBufferPool parent;
+
+  GstElement *element;
+
+  GstCaps *caps;
+  gboolean add_videometa;
+  gboolean need_copy;
+  GstVideoInfo video_info;
+
+  /* Owned by element, element has to stop this pool before
+   * it destroys component or port */
+  GstOMXComponent *component;
+  GstOMXPort *port;
+
+  /* For handling OpenMAX allocated memory */
+  GstAllocator *allocator;
+
+  /* Set from outside this pool */
+  /* TRUE if we're currently allocating all our buffers */
+  gboolean allocating;
+  /* TRUE if the pool is not used anymore */
+  gboolean deactivated;
+
+  /* For populating the pool from another one */
+  GstBufferPool *other_pool;
+  GPtrArray *buffers;
+
+  /* Used during acquire for output ports to
+   * specify which buffer has to be retrieved
+   * and during alloc, which buffer has to be
+   * wrapped
+   */
+  gint current_buffer_index;
+};
+
+struct _GstOMXBufferPoolClass
+{
+  GstVideoBufferPoolClass parent_class;
+};
+
+GType gst_omx_buffer_pool_get_type (void);
+
+GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_BUFFER_POOL_H__ */
index e3c1a99..8385372 100644 (file)
@@ -189,8 +189,9 @@ gst_omx_h263_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
         "Setting profile/level not supported by component");
   } else if (err != OMX_ErrorNone) {
     GST_ERROR_OBJECT (self,
-        "Error setting profile %d and level %d: %s (0x%08x)", param.eProfile,
-        param.eLevel, gst_omx_error_to_string (err), err);
+        "Error setting profile %u and level %u: %s (0x%08x)",
+        (guint) param.eProfile, (guint) param.eLevel,
+        gst_omx_error_to_string (err), err);
     return FALSE;
   }
 
@@ -261,7 +262,7 @@ gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
 
     switch (param.eLevel) {
@@ -288,7 +289,7 @@ gst_omx_h263_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
 
     gst_caps_set_simple (caps,
index 2581889..2132d9f 100644 (file)
@@ -83,6 +83,31 @@ static gboolean
 gst_omx_h264_dec_is_format_change (GstOMXVideoDec * dec,
     GstOMXPort * port, GstVideoCodecState * state)
 {
+  GstCaps *old_caps = NULL;
+  GstCaps *new_caps = state->caps;
+  GstStructure *old_structure, *new_structure;
+  const gchar *old_profile, *old_level, *new_profile, *new_level;
+
+  if (dec->input_state) {
+    old_caps = dec->input_state->caps;
+  }
+
+  if (!old_caps) {
+    return FALSE;
+  }
+
+  old_structure = gst_caps_get_structure (old_caps, 0);
+  new_structure = gst_caps_get_structure (new_caps, 0);
+  old_profile = gst_structure_get_string (old_structure, "profile");
+  old_level = gst_structure_get_string (old_structure, "level");
+  new_profile = gst_structure_get_string (new_structure, "profile");
+  new_level = gst_structure_get_string (new_structure, "level");
+
+  if (g_strcmp0 (old_profile, new_profile) != 0
+      || g_strcmp0 (old_level, new_level) != 0) {
+    return TRUE;
+  }
+
   return FALSE;
 }
 
index 9adac04..aa33ae5 100644 (file)
 
 #include "gstomxh264enc.h"
 
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#include <OMX_Index.h>
+#endif
+
 GST_DEBUG_CATEGORY_STATIC (gst_omx_h264_enc_debug_category);
 #define GST_CAT_DEFAULT gst_omx_h264_enc_debug_category
 
@@ -36,30 +41,85 @@ static GstCaps *gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc,
     GstOMXPort * port, GstVideoCodecState * state);
 static GstFlowReturn gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc *
     self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
+static gboolean gst_omx_h264_enc_flush (GstVideoEncoder * enc);
+static gboolean gst_omx_h264_enc_stop (GstVideoEncoder * enc);
+static void gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_omx_h264_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
 enum
 {
-  PROP_0
+  PROP_0,
+#ifdef USE_OMX_TARGET_RPI
+  PROP_INLINESPSPPSHEADERS,
+#endif
+  PROP_PERIODICITYOFIDRFRAMES,
+  PROP_INTERVALOFCODINGINTRAFRAMES
 };
 
+#ifdef USE_OMX_TARGET_RPI
+#define GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT      TRUE
+#endif
+#define GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT    (0xffffffff)
+#define GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT (0xffffffff)
+
+
 /* class initialization */
 
 #define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_omx_h264_enc_debug_category, "omxh264enc", 0, \
       "debug category for gst-omx video encoder base class");
 
+#define parent_class gst_omx_h264_enc_parent_class
 G_DEFINE_TYPE_WITH_CODE (GstOMXH264Enc, gst_omx_h264_enc,
     GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
 
 static void
 gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
   GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
 
   videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_set_format);
   videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h264_enc_get_caps);
 
+  gobject_class->set_property = gst_omx_h264_enc_set_property;
+  gobject_class->get_property = gst_omx_h264_enc_get_property;
+
+#ifdef USE_OMX_TARGET_RPI
+  g_object_class_install_property (gobject_class, PROP_INLINESPSPPSHEADERS,
+      g_param_spec_boolean ("inline-header",
+          "Inline SPS/PPS headers before IDR",
+          "Inline SPS/PPS header before IDR",
+          GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+#endif
+
+  g_object_class_install_property (gobject_class, PROP_PERIODICITYOFIDRFRAMES,
+      g_param_spec_uint ("periodicty-idr", "Target Bitrate",
+          "Periodicity of IDR frames (0xffffffff=component default)",
+          0, G_MAXUINT,
+          GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+
+  g_object_class_install_property (gobject_class,
+      PROP_INTERVALOFCODINGINTRAFRAMES,
+      g_param_spec_uint ("interval-intraframes",
+          "Interval of coding Intra frames",
+          "Interval of coding Intra frames (0xffffffff=component default)", 0,
+          G_MAXUINT,
+          GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+          GST_PARAM_MUTABLE_READY));
+
+  basevideoenc_class->flush = gst_omx_h264_enc_flush;
+  basevideoenc_class->stop = gst_omx_h264_enc_stop;
+
   videoenc_class->cdata.default_src_template_caps = "video/x-h264, "
       "width=(int) [ 16, 4096 ], " "height=(int) [ 16, 4096 ]";
   videoenc_class->handle_output_frame =
@@ -75,8 +135,86 @@ gst_omx_h264_enc_class_init (GstOMXH264EncClass * klass)
 }
 
 static void
+gst_omx_h264_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
+
+  switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+    case PROP_INLINESPSPPSHEADERS:
+      self->inline_sps_pps_headers = g_value_get_boolean (value);
+      break;
+#endif
+    case PROP_PERIODICITYOFIDRFRAMES:
+      self->periodicty_idr = g_value_get_uint (value);
+      break;
+    case PROP_INTERVALOFCODINGINTRAFRAMES:
+      self->interval_intraframes = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_omx_h264_enc_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstOMXH264Enc *self = GST_OMX_H264_ENC (object);
+
+  switch (prop_id) {
+#ifdef USE_OMX_TARGET_RPI
+    case PROP_INLINESPSPPSHEADERS:
+      g_value_set_boolean (value, self->inline_sps_pps_headers);
+      break;
+#endif
+    case PROP_PERIODICITYOFIDRFRAMES:
+      g_value_set_uint (value, self->periodicty_idr);
+      break;
+    case PROP_INTERVALOFCODINGINTRAFRAMES:
+      g_value_set_uint (value, self->interval_intraframes);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_omx_h264_enc_init (GstOMXH264Enc * self)
 {
+#ifdef USE_OMX_TARGET_RPI
+  self->inline_sps_pps_headers =
+      GST_OMX_H264_VIDEO_ENC_INLINE_SPS_PPS_HEADERS_DEFAULT;
+#endif
+  self->periodicty_idr =
+      GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT;
+  self->interval_intraframes =
+      GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT;
+}
+
+static gboolean
+gst_omx_h264_enc_flush (GstVideoEncoder * enc)
+{
+  GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
+  g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+  self->headers = NULL;
+
+  return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc);
+}
+
+static gboolean
+gst_omx_h264_enc_stop (GstVideoEncoder * enc)
+{
+  GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
+  g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref);
+  self->headers = NULL;
+
+  return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc);
 }
 
 static gboolean
@@ -87,9 +225,88 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
   GstCaps *peercaps;
   OMX_PARAM_PORTDEFINITIONTYPE port_def;
   OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+  OMX_VIDEO_CONFIG_AVCINTRAPERIOD config_avcintraperiod;
+#ifdef USE_OMX_TARGET_RPI
+  OMX_CONFIG_PORTBOOLEANTYPE config_inline_header;
+#endif
   OMX_ERRORTYPE err;
   const gchar *profile_string, *level_string;
 
+#ifdef USE_OMX_TARGET_RPI
+  GST_OMX_INIT_STRUCT (&config_inline_header);
+  config_inline_header.nPortIndex =
+      GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't get OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  if (self->inline_sps_pps_headers) {
+    config_inline_header.bEnabled = OMX_TRUE;
+  } else {
+    config_inline_header.bEnabled = OMX_FALSE;
+  }
+
+  err =
+      gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &config_inline_header);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "can't set OMX_IndexParamBrcmVideoAVCInlineHeaderEnable %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+#endif
+
+  if (self->periodicty_idr !=
+      GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT
+      || self->interval_intraframes !=
+      GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+
+
+    GST_OMX_INIT_STRUCT (&config_avcintraperiod);
+    config_avcintraperiod.nPortIndex =
+        GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+    err =
+        gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+        OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self,
+          "can't get OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      return FALSE;
+    }
+
+    GST_DEBUG_OBJECT (self, "default nPFrames:%u, nIDRPeriod:%u",
+        (guint) config_avcintraperiod.nPFrames,
+        (guint) config_avcintraperiod.nIDRPeriod);
+
+    if (self->periodicty_idr !=
+        GST_OMX_H264_VIDEO_ENC_PERIODICITY_OF_IDR_FRAMES_DEFAULT) {
+      config_avcintraperiod.nIDRPeriod = self->periodicty_idr;
+    }
+
+    if (self->interval_intraframes !=
+        GST_OMX_H264_VIDEO_ENC_INTERVAL_OF_CODING_INTRA_FRAMES_DEFAULT) {
+      config_avcintraperiod.nPFrames = self->interval_intraframes;
+    }
+
+    err =
+        gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+        OMX_IndexConfigVideoAVCIntraPeriod, &config_avcintraperiod);
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (self,
+          "can't set OMX_IndexConfigVideoAVCIntraPeriod %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      return FALSE;
+    }
+  }
+
   gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
       &port_def);
   port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
@@ -192,8 +409,9 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
         "Setting profile/level not supported by component");
   } else if (err != OMX_ErrorNone) {
     GST_ERROR_OBJECT (self,
-        "Error setting profile %d and level %d: %s (0x%08x)", param.eProfile,
-        param.eLevel, gst_omx_error_to_string (err), err);
+        "Error setting profile %u and level %u: %s (0x%08x)",
+        (guint) param.eProfile, (guint) param.eLevel,
+        gst_omx_error_to_string (err), err);
     return FALSE;
   }
 
@@ -258,7 +476,7 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
 
     switch (param.eLevel) {
@@ -312,7 +530,7 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
     gst_caps_set_simple (caps,
         "profile", G_TYPE_STRING, profile, "level", G_TYPE_STRING, level, NULL);
@@ -322,9 +540,11 @@ gst_omx_h264_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
 }
 
 static GstFlowReturn
-gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
+gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port,
     GstOMXBuffer * buf, GstVideoCodecFrame * frame)
 {
+  GstOMXH264Enc *self = GST_OMX_H264_ENC (enc);
+
   if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
     /* The codec data is SPS/PPS with a startcode => bytestream stream format
      * For bytestream stream format the SPS/PPS is only in-stream and not
@@ -333,12 +553,10 @@ gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
     if (buf->omx_buf->nFilledLen >= 4 &&
         GST_READ_UINT32_BE (buf->omx_buf->pBuffer +
             buf->omx_buf->nOffset) == 0x00000001) {
-      GList *l = NULL;
       GstBuffer *hdrs;
       GstMapInfo map = GST_MAP_INFO_INIT;
 
       GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
-      buf->omx_buf->nFlags &= ~OMX_BUFFERFLAG_CODECCONFIG;
 
       hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
 
@@ -347,13 +565,20 @@ gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
           buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
           buf->omx_buf->nFilledLen);
       gst_buffer_unmap (hdrs, &map);
-      l = g_list_append (l, hdrs);
-      gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), l);
+      self->headers = g_list_append (self->headers, hdrs);
+
+      if (frame)
+        gst_video_codec_frame_unref (frame);
+
+      return GST_FLOW_OK;
     }
+  } else if (self->headers) {
+    gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers);
+    self->headers = NULL;
   }
 
   return
       GST_OMX_VIDEO_ENC_CLASS
-      (gst_omx_h264_enc_parent_class)->handle_output_frame (self, port, buf,
+      (gst_omx_h264_enc_parent_class)->handle_output_frame (enc, port, buf,
       frame);
 }
index 5d43e5b..03326e1 100644 (file)
@@ -45,6 +45,14 @@ typedef struct _GstOMXH264EncClass GstOMXH264EncClass;
 struct _GstOMXH264Enc
 {
   GstOMXVideoEnc parent;
+
+#ifdef USE_OMX_TARGET_RPI
+  gboolean inline_sps_pps_headers;
+#endif
+  guint32 periodicty_idr;
+  guint32 interval_intraframes;
+
+  GList *headers;
 };
 
 struct _GstOMXH264EncClass
diff --git a/omx/gstomxhdmiaudiosink.c b/omx/gstomxhdmiaudiosink.c
new file mode 100644 (file)
index 0000000..211b719
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxhdmiaudiosink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_hdmi_audio_sink_debug_category);
+#define GST_CAT_DEFAULT gst_omx_hdmi_audio_sink_debug_category
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_hdmi_audio_sink_debug_category, \
+      "omxhdmiaudiosink", 0, "debug category for gst-omx hdmi audio sink");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXHdmiAudioSink, gst_omx_hdmi_audio_sink,
+    GST_TYPE_OMX_AUDIO_SINK, DEBUG_INIT);
+
+static void
+gst_omx_hdmi_audio_sink_class_init (GstOMXHdmiAudioSinkClass * klass)
+{
+  GstOMXAudioSinkClass *audiosink_class = GST_OMX_AUDIO_SINK_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  audiosink_class->cdata.default_sink_template_caps = "audio/x-raw, "
+      "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+      "layout = (string) interleaved, "
+      "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+      PASSTHROUGH_CAPS;
+  audiosink_class->destination = "hdmi";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX HDMI Audio Sink",
+      "Sink/Audio",
+      "Output audio through HDMI", "Josep Torra <josep@fluendo.com>");
+
+  gst_omx_set_default_role (&audiosink_class->cdata, "audio_render.hdmi");
+}
+
+static void
+gst_omx_hdmi_audio_sink_init (GstOMXHdmiAudioSink * self)
+{
+}
diff --git a/omx/gstomxhdmiaudiosink.h b/omx/gstomxhdmiaudiosink.h
new file mode 100644 (file)
index 0000000..e45e56b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014, Fluendo, S.A.
+ * Copyright (C) 2014, Metrological Media Innovations B.V.
+ *   Author: Josep Torra <josep@fluendo.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_HDMI_AUDIO_SINK_H__
+#define __GST_OMX_HDMI_AUDIO_SINK_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiosink.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_HDMI_AUDIO_SINK \
+  (gst_omx_hdmi_audio_sink_get_type())
+#define GST_OMX_HDMI_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSink))
+#define GST_OMX_HDMI_AUDIO_SINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSinkClass))
+#define GST_OMX_HDMI_AUDIO_SINK_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK,GstOMXHdmiAudioSinkClass))
+#define GST_IS_OMX_HDMI_AUDIO_SINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_HDMI_AUDIO_SINK))
+#define GST_IS_OMX_HDMI_AUDIO_SINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_HDMI_AUDIO_SINK))
+
+typedef struct _GstOMXHdmiAudioSink GstOMXHdmiAudioSink;
+typedef struct _GstOMXHdmiAudioSinkClass GstOMXHdmiAudioSinkClass;
+
+struct _GstOMXHdmiAudioSink
+{
+  GstOMXAudioSink parent;
+};
+
+struct _GstOMXHdmiAudioSinkClass
+{
+  GstOMXAudioSinkClass parent_class;
+};
+
+GType gst_omx_hdmi_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_HDMI_AUDIO_SINK_H__ */
+
diff --git a/omx/gstomxmp3dec.c b/omx/gstomxmp3dec.c
new file mode 100644 (file)
index 0000000..5a143d5
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmp3dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mp3_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mp3_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mp3_dec_set_format (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gboolean gst_omx_mp3_dec_is_format_change (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstCaps * caps);
+static gint gst_omx_mp3_dec_get_samples_per_frame (GstOMXAudioDec * dec,
+    GstOMXPort * port);
+static gboolean gst_omx_mp3_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_mp3_dec_debug_category, "omxmp3dec", 0, \
+      "debug category for gst-omx mp3 audio decoder");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMP3Dec, gst_omx_mp3_dec,
+    GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
+
+
+static void
+gst_omx_mp3_dec_class_init (GstOMXMP3DecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
+
+  audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_set_format);
+  audiodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_is_format_change);
+  audiodec_class->get_samples_per_frame =
+      GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_get_samples_per_frame);
+  audiodec_class->get_channel_positions =
+      GST_DEBUG_FUNCPTR (gst_omx_mp3_dec_get_channel_positions);
+
+  audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, "
+      "mpegversion=(int)1, "
+      "layer=(int)3, "
+      "mpegaudioversion=(int)[1,3], "
+      "rate=(int)[8000,48000], "
+      "channels=(int)[1,2], " "parsed=(boolean) true";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX MP3 Audio Decoder",
+      "Codec/Decoder/Audio",
+      "Decode MP3 audio streams",
+      "Sebastian Dröge <sebastian@centricular.com>");
+
+  gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.mp3");
+}
+
+static void
+gst_omx_mp3_dec_init (GstOMXMP3Dec * self)
+{
+  self->spf = -1;
+}
+
+static gboolean
+gst_omx_mp3_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXMP3Dec *self = GST_OMX_MP3_DEC (dec);
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels, layer, mpegaudioversion;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
+  err = gst_omx_port_update_port_definition (port, &port_def);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to set MP3 format on component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  GST_OMX_INIT_STRUCT (&mp3_param);
+  mp3_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioMp3,
+      &mp3_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get MP3 parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion) ||
+      !gst_structure_get_int (s, "layer", &layer) ||
+      !gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  self->spf = (mpegaudioversion == 1 ? 1152 : 576);
+
+  mp3_param.nChannels = channels;
+  mp3_param.nBitRate = 0;       /* unknown */
+  mp3_param.nSampleRate = rate;
+  mp3_param.nAudioBandWidth = 0;        /* decoder decision */
+  mp3_param.eChannelMode = 0;   /* FIXME */
+  if (mpegaudioversion == 1)
+    mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
+  else if (mpegaudioversion == 2)
+    mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2Layer3;
+  else
+    mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2_5Layer3;
+
+  err =
+      gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioMp3,
+      &mp3_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self, "Error setting MP3 parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_omx_mp3_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
+    GstCaps * caps)
+{
+  GstOMXMP3Dec *self = GST_OMX_MP3_DEC (dec);
+  OMX_AUDIO_PARAM_MP3TYPE mp3_param;
+  OMX_ERRORTYPE err;
+  GstStructure *s;
+  gint rate, channels, layer, mpegaudioversion;
+
+  GST_OMX_INIT_STRUCT (&mp3_param);
+  mp3_param.nPortIndex = port->index;
+
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioMp3,
+      &mp3_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (self,
+        "Failed to get MP3 parameters from component: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  s = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion) ||
+      !gst_structure_get_int (s, "layer", &layer) ||
+      !gst_structure_get_int (s, "rate", &rate) ||
+      !gst_structure_get_int (s, "channels", &channels)) {
+    GST_ERROR_OBJECT (self, "Incomplete caps");
+    return FALSE;
+  }
+
+  if (mp3_param.nChannels != channels)
+    return TRUE;
+
+  if (mp3_param.nSampleRate != rate)
+    return TRUE;
+
+  if (mpegaudioversion == 1
+      && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP1Layer3)
+    return TRUE;
+  if (mpegaudioversion == 2
+      && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP2Layer3)
+    return TRUE;
+  if (mpegaudioversion == 3
+      && mp3_param.eFormat != OMX_AUDIO_MP3StreamFormatMP2_5Layer3)
+    return TRUE;
+
+  return FALSE;
+}
+
+static gint
+gst_omx_mp3_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
+{
+  return GST_OMX_MP3_DEC (dec)->spf;
+}
+
+static gboolean
+gst_omx_mp3_dec_get_channel_positions (GstOMXAudioDec * dec,
+    GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
+{
+  OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&pcm_param);
+  pcm_param.nPortIndex = port->index;
+  err =
+      gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
+      &pcm_param);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  switch (pcm_param.nChannels) {
+    case 1:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+      break;
+    case 2:
+      position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      break;
+    default:
+      return FALSE;
+  }
+
+  return TRUE;
+}
diff --git a/omx/gstomxmp3dec.h b/omx/gstomxmp3dec.h
new file mode 100644 (file)
index 0000000..4f07659
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_MP3_DEC_H__
+#define __GST_OMX_MP3_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxaudiodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MP3_DEC \
+  (gst_omx_mp3_dec_get_type())
+#define GST_OMX_MP3_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MP3_DEC,GstOMXMP3Dec))
+#define GST_OMX_MP3_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MP3_DEC,GstOMXMP3DecClass))
+#define GST_OMX_MP3_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MP3_DEC,GstOMXMP3DecClass))
+#define GST_IS_OMX_MP3_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MP3_DEC))
+#define GST_IS_OMX_MP3_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MP3_DEC))
+
+typedef struct _GstOMXMP3Dec GstOMXMP3Dec;
+typedef struct _GstOMXMP3DecClass GstOMXMP3DecClass;
+
+struct _GstOMXMP3Dec
+{
+  GstOMXAudioDec parent;
+  gint spf;
+};
+
+struct _GstOMXMP3DecClass
+{
+  GstOMXAudioDecClass parent_class;
+};
+
+GType gst_omx_mp3_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MP3_DEC_H__ */
+
index 15b8ce7..f5eaa0a 100644 (file)
@@ -199,8 +199,9 @@ gst_omx_mpeg4_video_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
         "Setting profile/level not supported by component");
   } else if (err != OMX_ErrorNone) {
     GST_ERROR_OBJECT (self,
-        "Error setting profile %d and level %d: %s (0x%08x)", param.eProfile,
-        param.eLevel, gst_omx_error_to_string (err), err);
+        "Error setting profile %u and level %u: %s (0x%08x)",
+        (guint) param.eProfile, (guint) param.eLevel,
+        gst_omx_error_to_string (err), err);
     return FALSE;
   }
 
@@ -294,7 +295,7 @@ gst_omx_mpeg4_video_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
 
     switch (param.eLevel) {
@@ -324,7 +325,7 @@ gst_omx_mpeg4_video_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
         break;
       default:
         g_assert_not_reached ();
-        break;
+        return NULL;
     }
 
     gst_caps_set_simple (caps,
diff --git a/omx/gstomxvideo.c b/omx/gstomxvideo.c
new file mode 100644 (file)
index 0000000..7cd6755
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> *
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *   Author: Christian König <christian.koenig@amd.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxvideo.h"
+
+GST_DEBUG_CATEGORY (gst_omx_video_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_debug_category
+
+GstVideoFormat
+gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat)
+{
+  GstVideoFormat format;
+
+  switch (omx_colorformat) {
+    case OMX_COLOR_FormatL8:
+      format = GST_VIDEO_FORMAT_GRAY8;
+      break;
+    case OMX_COLOR_FormatYUV420Planar:
+    case OMX_COLOR_FormatYUV420PackedPlanar:
+      format = GST_VIDEO_FORMAT_I420;
+      break;
+    case OMX_COLOR_FormatYUV420SemiPlanar:
+      format = GST_VIDEO_FORMAT_NV12;
+      break;
+    case OMX_COLOR_FormatYUV422SemiPlanar:
+      format = GST_VIDEO_FORMAT_NV16;
+      break;
+    case OMX_COLOR_FormatYCbYCr:
+      format = GST_VIDEO_FORMAT_YUY2;
+      break;
+    case OMX_COLOR_FormatYCrYCb:
+      format = GST_VIDEO_FORMAT_YVYU;
+      break;
+    case OMX_COLOR_FormatCbYCrY:
+      format = GST_VIDEO_FORMAT_UYVY;
+      break;
+    case OMX_COLOR_Format32bitARGB8888:
+      /* There is a mismatch in omxil specification 4.2.1 between
+       * OMX_COLOR_Format32bitARGB8888 and its description
+       * Follow the description */
+      format = GST_VIDEO_FORMAT_ABGR;
+      break;
+    case OMX_COLOR_Format32bitBGRA8888:
+      /* Same issue as OMX_COLOR_Format32bitARGB8888 */
+      format = GST_VIDEO_FORMAT_ARGB;
+      break;
+    case OMX_COLOR_Format16bitRGB565:
+      format = GST_VIDEO_FORMAT_RGB16;
+      break;
+    case OMX_COLOR_Format16bitBGR565:
+      format = GST_VIDEO_FORMAT_BGR16;
+      break;
+    case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
+#ifdef USE_MM_VIDEO_BUFFER
+      format = GST_VIDEO_FORMAT_SN12;
+#else
+      format = GST_VIDEO_FORMAT_ST12;
+#endif
+      break;
+    default:
+      format = GST_VIDEO_FORMAT_UNKNOWN;
+      break;
+  }
+
+  return format;
+}
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  GstOMXComponent *comp = port->comp;
+  OMX_VIDEO_PARAM_PORTFORMATTYPE param;
+  OMX_ERRORTYPE err;
+  GList *negotiation_map = NULL;
+  gint old_index;
+  GstOMXVideoNegotiationMap *m;
+  GstVideoFormat f;
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = port->index;
+  param.nIndex = 0;
+  if (!state || state->info.fps_n == 0)
+    param.xFramerate = 0;
+  else
+    param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
+
+  old_index = -1;
+  do {
+    err =
+        gst_omx_component_get_parameter (comp,
+        OMX_IndexParamVideoPortFormat, &param);
+
+    /* FIXME: Workaround for Bellagio that simply always
+     * returns the same value regardless of nIndex and
+     * never returns OMX_ErrorNoMore
+     */
+    if (old_index == param.nIndex)
+      break;
+
+    if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
+      f = gst_omx_video_get_format_from_omx (param.eColorFormat);
+
+      if (f != GST_VIDEO_FORMAT_UNKNOWN) {
+        m = g_slice_new (GstOMXVideoNegotiationMap);
+        m->format = f;
+        m->type = param.eColorFormat;
+        negotiation_map = g_list_append (negotiation_map, m);
+        GST_DEBUG_OBJECT (comp->parent,
+            "Component supports %s (%d) at index %u",
+            gst_video_format_to_string (f), param.eColorFormat,
+            (guint) param.nIndex);
+      } else {
+        GST_DEBUG_OBJECT (comp->parent,
+            "Component supports unsupported color format %d at index %u",
+            param.eColorFormat, (guint) param.nIndex);
+      }
+    }
+    old_index = param.nIndex++;
+  } while (err == OMX_ErrorNone);
+
+  return negotiation_map;
+}
+
+GstCaps *
+gst_omx_video_get_caps_for_map (GList * map)
+{
+  GstCaps *caps = gst_caps_new_empty ();
+  GList *l;
+
+  for (l = map; l; l = l->next) {
+    GstOMXVideoNegotiationMap *entry = l->data;
+
+    gst_caps_append_structure (caps,
+        gst_structure_new ("video/x-raw",
+            "format", G_TYPE_STRING,
+            gst_video_format_to_string (entry->format), NULL));
+  }
+  return caps;
+}
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m)
+{
+  g_slice_free (GstOMXVideoNegotiationMap, m);
+}
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames)
+{
+  GstVideoCodecFrame *best = NULL;
+  GstClockTimeDiff best_diff = G_MAXINT64;
+  GstClockTime timestamp;
+  GList *l;
+
+  timestamp =
+      gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
+      OMX_TICKS_PER_SECOND);
+
+  for (l = frames; l; l = l->next) {
+    GstVideoCodecFrame *tmp = l->data;
+    GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (timestamp, tmp->pts));
+
+    if (diff < best_diff) {
+      best = tmp;
+      best_diff = diff;
+
+      if (diff == 0)
+        break;
+    }
+  }
+
+  if (best)
+    gst_video_codec_frame_ref (best);
+
+  g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
+  g_list_free (frames);
+
+  return best;
+}
diff --git a/omx/gstomxvideo.h b/omx/gstomxvideo.h
new file mode 100644 (file)
index 0000000..f146df7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *   Author: Christian König <christian.koenig@amd.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_VIDEO_H__
+#define __GST_OMX_VIDEO_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideodecoder.h>
+#include <gst/video/gstvideoencoder.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  GstVideoFormat format;
+  OMX_COLOR_FORMATTYPE type;
+} GstOMXVideoNegotiationMap;
+
+GstVideoFormat
+gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat);
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+    GstVideoCodecState * state);
+
+GstCaps * gst_omx_video_get_caps_for_map(GList * map);
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m);
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VIDEO_H__ */
old mode 100755 (executable)
new mode 100644 (file)
index d3f341f..813962b
 #include "config.h"
 #endif
 
-//#define CODEC_DEC_OUTPUT_DUMP
 #include <gst/gst.h>
-#include <gst/video/gstvideometa.h>
-#include <gst/video/gstvideopool.h>
-#include <string.h>
-#if defined(CODEC_DEC_OUTPUT_DUMP)
-#include <stdio.h> /* for dump */
-#endif
-
-#include "gstomxvideodec.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
-#define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
-
-typedef struct _GstOMXMemory GstOMXMemory;
-typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator;
-typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass;
-
-
-struct _GstOMXMemory
-{
-  GstMemory mem;
-
-  GstOMXBuffer *buf;
-};
-
-struct _GstOMXMemoryAllocator
-{
-  GstAllocator parent;
-};
-
-struct _GstOMXMemoryAllocatorClass
-{
-  GstAllocatorClass parent_class;
-};
-
-#define GST_OMX_MEMORY_TYPE "openmax"
-
-static GstMemory *
-gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size,
-    GstAllocationParams * params)
-{
-  g_assert_not_reached ();
-  return NULL;
-}
-
-static void
-gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
-{
-  GstOMXMemory *omem = (GstOMXMemory *) mem;
-
-  /* TODO: We need to remember which memories are still used
-   * so we can wait until everything is released before allocating
-   * new memory
-   */
-
-  g_slice_free (GstOMXMemory, omem);
-}
-
-static gpointer
-gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
-{
-  GstOMXMemory *omem = (GstOMXMemory *) mem;
-
-  return omem->buf->omx_buf->pBuffer + omem->mem.offset;
-}
-
-static void
-gst_omx_memory_unmap (GstMemory * mem)
-{
-}
-
-static GstMemory *
-gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
-{
-  g_assert_not_reached ();
-  return NULL;
-}
-
-GType gst_omx_memory_allocator_get_type (void);
-G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator,
-    GST_TYPE_ALLOCATOR);
-
-#define GST_TYPE_OMX_MEMORY_ALLOCATOR   (gst_omx_memory_allocator_get_type())
-#define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR))
-
-static void
-gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass)
-{
-  GstAllocatorClass *allocator_class;
-
-  allocator_class = (GstAllocatorClass *) klass;
-
-  allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy;
-  allocator_class->free = gst_omx_memory_allocator_free;
-}
-
-static void
-gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator)
-{
-  GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
-
-  alloc->mem_type = GST_OMX_MEMORY_TYPE;
-  alloc->mem_map = gst_omx_memory_map;
-  alloc->mem_unmap = gst_omx_memory_unmap;
-  alloc->mem_share = gst_omx_memory_share;
-
-  /* default copy & is_span */
-
-  GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
-}
-
-static GstMemory *
-gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
-    GstOMXBuffer * buf)
-{
-  GstOMXMemory *mem;
-
-  /* FIXME: We don't allow sharing because we need to know
-   * when the memory becomes unused and can only then put
-   * it back to the pool. Which is done in the pool's release
-   * function
-   */
-  flags |= GST_MEMORY_FLAG_NO_SHARE;
-
-  mem = g_slice_new (GstOMXMemory);
-  /* the shared memory is always readonly */
-  gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
-      buf->omx_buf->nAllocLen, buf->port->port_def.nBufferAlignment,
-      0, buf->omx_buf->nAllocLen);
-
-  mem->buf = buf;
-
-  return GST_MEMORY_CAST (mem);
-}
-
-/* Buffer pool for the buffers of an OpenMAX port.
- *
- * This pool is only used if we either passed buffers from another
- * pool to the OMX port or provide the OMX buffers directly to other
- * elements.
- *
- *
- * A buffer is in the pool if it is currently owned by the port,
- * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside
- * the pool after it was taken from the port after it was handled
- * by the port, i.e. {Empty,Fill}BufferDone.
- *
- * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
- * by someone else and (temporarily) passed to this pool
- * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of
- * the buffer will be overriden, and restored in free_buffer(). Other
- * buffers are just freed there.
- *
- * The pool always has a fixed number of minimum and maximum buffers
- * and these are allocated while starting the pool and released afterwards.
- * They correspond 1:1 to the OMX buffers of the port, which are allocated
- * before the pool is started.
- *
- * Acquiring a buffer from this pool happens after the OMX buffer has
- * been acquired from the port. gst_buffer_pool_acquire_buffer() is
- * supposed to return the buffer that corresponds to the OMX buffer.
- *
- * For buffers provided to upstream, the buffer will be passed to
- * the component manually when it arrives and then unreffed. If the
- * buffer is released before reaching the component it will be just put
- * back into the pool as if EmptyBufferDone has happened. If it was
- * passed to the component, it will be back into the pool when it was
- * released and EmptyBufferDone has happened.
- *
- * For buffers provided to downstream, the buffer will be returned
- * back to the component (OMX_FillThisBuffer()) when it is released.
- */
-
-static GQuark gst_omx_buffer_data_quark = 0;
-
-#define GST_OMX_BUFFER_POOL(pool) ((GstOMXBufferPool *) pool)
-typedef struct _GstOMXBufferPool GstOMXBufferPool;
-typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass;
-
-struct _GstOMXBufferPool
-{
-  GstVideoBufferPool parent;
-
-  GstElement *element;
-
-  GstCaps *caps;
-  gboolean add_videometa;
-  GstVideoInfo video_info;
-
-  /* Owned by element, element has to stop this pool before
-   * it destroys component or port */
-  GstOMXComponent *component;
-  GstOMXPort *port;
-
-  GstAllocator *allocator;
-
-  /* Set from outside this pool */
-  /* TRUE if we're currently allocating all our buffers */
-  gboolean allocating;
-
-  /* TRUE if the pool is not used anymore */
-  gboolean deactivated;
-
-  /* For populating the pool from another one */
-  GstBufferPool *other_pool;
-  GPtrArray *buffers;
-
-  /* Used during acquire for output ports to
-   * specify which buffer has to be retrieved
-   * and during alloc, which buffer has to be
-   * wrapped
-   */
-  gint current_buffer_index;
-};
-
-struct _GstOMXBufferPoolClass
-{
-  GstVideoBufferPoolClass parent_class;
-};
-
-GType gst_omx_buffer_pool_get_type (void);
-
-G_DEFINE_TYPE (GstOMXBufferPool, gst_omx_buffer_pool, GST_TYPE_BUFFER_POOL);
-
-static gboolean
-gst_omx_buffer_pool_start (GstBufferPool * bpool)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-
-  /* Only allow to start the pool if we still are attached
-   * to a component and port */
-  GST_OBJECT_LOCK (pool);
-  if (!pool->component || !pool->port) {
-    GST_OBJECT_UNLOCK (pool);
-    return FALSE;
-  }
-  GST_OBJECT_UNLOCK (pool);
-
-  return
-      GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
-}
-
-static gboolean
-gst_omx_buffer_pool_stop (GstBufferPool * bpool)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-
-  /* Remove any buffers that are there */
-  if(pool->buffers)
-      g_ptr_array_set_size (pool->buffers, 0);
-
-  if (pool->caps)
-    gst_caps_unref (pool->caps);
-  pool->caps = NULL;
-
-  pool->add_videometa = FALSE;
-
-  return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
-}
-
-static const gchar **
-gst_omx_buffer_pool_get_options (GstBufferPool * bpool)
-{
-  static const gchar *raw_video_options[] =
-      { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
-  static const gchar *options[] = { NULL };
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-
-  GST_OBJECT_LOCK (pool);
-  if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
-      && pool->port->port_def.format.video.eCompressionFormat ==
-      OMX_VIDEO_CodingUnused) {
-    GST_OBJECT_UNLOCK (pool);
-    return raw_video_options;
-  }
-  GST_OBJECT_UNLOCK (pool);
-
-  return options;
-}
-
-static gboolean
-gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-  GstCaps *caps;
-
-  GST_OBJECT_LOCK (pool);
-
-  if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
-    goto wrong_config;
-
-  if (caps == NULL)
-    goto no_caps;
-
-  if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
-      && pool->port->port_def.format.video.eCompressionFormat ==
-      OMX_VIDEO_CodingUnused) {
-    GstVideoInfo info;
-
-    /* now parse the caps from the config */
-    if (!gst_video_info_from_caps (&info, caps))
-      goto wrong_video_caps;
-
-    /* enable metadata based on config of the pool */
-    pool->add_videometa =
-        gst_buffer_pool_config_has_option (config,
-        GST_BUFFER_POOL_OPTION_VIDEO_META);
-
-    pool->video_info = info;
-  }
-
-  if (pool->caps)
-    gst_caps_unref (pool->caps);
-  pool->caps = gst_caps_ref (caps);
-
-  GST_OBJECT_UNLOCK (pool);
-
-  return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
-      (bpool, config);
-
-  /* ERRORS */
-wrong_config:
-  {
-    GST_OBJECT_UNLOCK (pool);
-    GST_WARNING_OBJECT (pool, "invalid config");
-    return FALSE;
-  }
-no_caps:
-  {
-    GST_OBJECT_UNLOCK (pool);
-    GST_WARNING_OBJECT (pool, "no caps in config");
-    return FALSE;
-  }
-wrong_video_caps:
-  {
-    GST_OBJECT_UNLOCK (pool);
-    GST_WARNING_OBJECT (pool,
-        "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
-    return FALSE;
-  }
-}
-
-static GstFlowReturn
-gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
-    GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-  GstBuffer *buf;
-  GstOMXBuffer *omx_buf;
-
-  g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
-
-  omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index);
-  g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR);
-
-  if (pool->other_pool) {
-    guint i, n;
-
-    buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
-    g_assert (pool->other_pool == buf->pool);
-    gst_object_replace ((GstObject **) & buf->pool, NULL);
-
-    n = gst_buffer_n_memory (buf);
-    for (i = 0; i < n; i++) {
-      GstMemory *mem = gst_buffer_peek_memory (buf, i);
-
-      /* FIXME: We don't allow sharing because we need to know
-       * when the memory becomes unused and can only then put
-       * it back to the pool. Which is done in the pool's release
-       * function
-       */
-      GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE);
-    }
-
-    if (pool->add_videometa) {
-      GstVideoMeta *meta;
-
-      meta = gst_buffer_get_video_meta (buf);
-      if (!meta) {
-        gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE,
-            GST_VIDEO_INFO_FORMAT (&pool->video_info),
-            GST_VIDEO_INFO_WIDTH (&pool->video_info),
-            GST_VIDEO_INFO_HEIGHT (&pool->video_info));
-      }
-    }
-  } else {
-    GstMemory *mem;
-
-    mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
-    buf = gst_buffer_new ();
-    gst_buffer_append_memory (buf, mem);
-    g_ptr_array_add (pool->buffers, buf);
-
-    if (pool->add_videometa) {
-      gsize offset[4] = { 0, };
-      gint stride[4] = { 0, };
-
-      switch (pool->video_info.finfo->format) {
-        case GST_VIDEO_FORMAT_I420:
-          offset[0] = 0;
-          stride[0] = pool->port->port_def.format.video.nStride;
-          offset[1] =
-              stride[0] * pool->port->port_def.format.video.nSliceHeight;
-          stride[1] = pool->port->port_def.format.video.nStride / 2;
-          offset[2] =
-              offset[1] +
-              stride[1] * (pool->port->port_def.format.video.nSliceHeight / 2);
-          stride[2] = pool->port->port_def.format.video.nStride / 2;
-          break;
-        case GST_VIDEO_FORMAT_NV12:
-        case GST_VIDEO_FORMAT_SN12:
-        case GST_VIDEO_FORMAT_ST12:
-          offset[0] = 0;
-          stride[0] = pool->port->port_def.format.video.nStride;
-          offset[1] =
-              stride[0] * pool->port->port_def.format.video.nSliceHeight;
-          stride[1] = pool->port->port_def.format.video.nStride;
-          break;
-        default:
-          g_assert_not_reached ();
-          break;
-      }
-
-      gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
-          GST_VIDEO_INFO_FORMAT (&pool->video_info),
-          GST_VIDEO_INFO_WIDTH (&pool->video_info),
-          GST_VIDEO_INFO_HEIGHT (&pool->video_info),
-          GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
-    }
-  }
-
-  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
-      gst_omx_buffer_data_quark, omx_buf, NULL);
-
-  *buffer = buf;
-
-  pool->current_buffer_index++;
-
-  return GST_FLOW_OK;
-}
-
-static void
-gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-
-  /* If the buffers belong to another pool, restore them now */
-  GST_OBJECT_LOCK (pool);
-  if (pool->other_pool) {
-    gst_object_replace ((GstObject **) & buffer->pool,
-        (GstObject *) pool->other_pool);
-  }
-  GST_OBJECT_UNLOCK (pool);
 
-  gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
-      gst_omx_buffer_data_quark, NULL, NULL);
-
-  GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
-      buffer);
-}
-
-static GstFlowReturn
-gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
-    GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
-{
-  GstFlowReturn ret;
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-
-  if (pool->port->port_def.eDir == OMX_DirOutput) {
-    GstBuffer *buf;
-
-    g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
-
-    buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
-    g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-    *buffer = buf;
-    ret = GST_FLOW_OK;
-
-    /* If it's our own memory we have to set the sizes */
-    if (!pool->other_pool) {
-      GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
-
-      g_assert (mem
-          && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
-      mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
-      mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
-    }
-  } else {
-    /* Acquire any buffer that is available to be filled by upstream */
-    ret =
-        GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
-        (bpool, buffer, params);
-  }
-
-  return ret;
-}
-
-static void
-gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
-  OMX_ERRORTYPE err;
-  GstOMXBuffer *omx_buf;
-
-  g_assert (pool->component && pool->port);
-
-  if (!pool->allocating && !pool->deactivated) {
-    omx_buf =
-        gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
-        gst_omx_buffer_data_quark);
-    if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
-      /* Release back to the port, can be filled again */
-      err = gst_omx_port_release_buffer (pool->port, omx_buf);
-      if (err != OMX_ErrorNone) {
-        GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
-            ("Failed to relase output buffer to component: %s (0x%08x)",
-                gst_omx_error_to_string (err), err));
-      }
-    } else if (!omx_buf->used) {
-      /* TODO: Implement.
-       *
-       * If not used (i.e. was not passed to the component) this should do
-       * the same as EmptyBufferDone.
-       * If it is used (i.e. was passed to the component) this should do
-       * nothing until EmptyBufferDone.
-       *
-       * EmptyBufferDone should release the buffer to the pool so it can
-       * be allocated again
-       *
-       * Needs something to call back here in EmptyBufferDone, like keeping
-       * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
-       * would ensure that the buffer is always unused when this is called.
-       */
-      g_assert_not_reached ();
-      GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
-          (bpool, buffer);
-    }
-  }
-}
-
-static void
-gst_omx_buffer_pool_finalize (GObject * object)
-{
-  GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
-
-  if (pool->element)
-    gst_object_unref (pool->element);
-  pool->element = NULL;
-
-  if (pool->buffers)
-    g_ptr_array_unref (pool->buffers);
-  pool->buffers = NULL;
-
-  if (pool->other_pool)
-    gst_object_unref (pool->other_pool);
-  pool->other_pool = NULL;
-
-  if (pool->allocator)
-    gst_object_unref (pool->allocator);
-  pool->allocator = NULL;
-
-  if (pool->caps)
-    gst_caps_unref (pool->caps);
-  pool->caps = NULL;
-
-  G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
-}
-
-static void
-gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
-{
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-  GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
-
-  gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
-
-  gobject_class->finalize = gst_omx_buffer_pool_finalize;
-  gstbufferpool_class->start = gst_omx_buffer_pool_start;
-  gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
-  gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
-  gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
-  gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
-  gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
-  gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
-  gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
-}
+#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+#ifndef __VCCOREVER__
+#define __VCCOREVER__ 0x04000000
+#endif
 
-static void
-gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
-{
-  pool->buffers = g_ptr_array_new ();
-  pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
-}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#pragma GCC optimize ("gnu89-inline")
+#endif
 
-static GstBufferPool *
-gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
-    GstOMXPort * port)
-{
-  GstOMXBufferPool *pool;
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+#include <gst/gl/gl.h>
+#include <gst/gl/egl/gsteglimagememory.h>
+#endif
 
-  pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
-  pool->element = gst_object_ref (element);
-  pool->component = component;
-  pool->port = port;
+#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
+#pragma GCC reset_options
+#pragma GCC diagnostic pop
+#endif
 
-  return GST_BUFFER_POOL (pool);
-}
+#include <string.h>
 
-typedef struct _BufferIdentification BufferIdentification;
-struct _BufferIdentification
-{
-  guint64 timestamp;
-};
+#include "gstomxbufferpool.h"
+#include "gstomxvideo.h"
+#include "gstomxvideodec.h"
 
-static void
-buffer_identification_free (BufferIdentification * id)
-{
-  g_slice_free (BufferIdentification, id);
-}
+GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
 
 /* prototypes */
 static void gst_omx_video_dec_finalize (GObject * object);
@@ -658,16 +68,14 @@ static gboolean gst_omx_video_dec_start (GstVideoDecoder * decoder);
 static gboolean gst_omx_video_dec_stop (GstVideoDecoder * decoder);
 static gboolean gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
     GstVideoCodecState * state);
-static gboolean gst_omx_video_dec_reset (GstVideoDecoder * decoder,
-    gboolean hard);
+static gboolean gst_omx_video_dec_flush (GstVideoDecoder * decoder);
 static GstFlowReturn gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
     GstVideoCodecFrame * frame);
 static GstFlowReturn gst_omx_video_dec_finish (GstVideoDecoder * decoder);
 static gboolean gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec,
     GstQuery * query);
 
-static GstFlowReturn gst_omx_video_dec_drain (GstOMXVideoDec * self,
-    gboolean is_eos);
+static GstFlowReturn gst_omx_video_dec_drain (GstOMXVideoDec * self);
 
 static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec *
     self);
@@ -705,7 +113,7 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
   video_decoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_dec_close);
   video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_dec_start);
   video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_dec_stop);
-  video_decoder_class->reset = GST_DEBUG_FUNCPTR (gst_omx_video_dec_reset);
+  video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_dec_flush);
   video_decoder_class->set_format =
       GST_DEBUG_FUNCPTR (gst_omx_video_dec_set_format);
   video_decoder_class->handle_frame =
@@ -714,7 +122,13 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
   video_decoder_class->decide_allocation =
       GST_DEBUG_FUNCPTR (gst_omx_video_dec_decide_allocation);
 
-  klass->cdata.default_src_template_caps = "video/x-raw, "
+  klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
+  klass->cdata.default_src_template_caps =
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+      GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE,
+      "RGBA") "; "
+#endif
+      "video/x-raw, "
       "width = " GST_VIDEO_SIZE_RANGE ", "
       "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE;
 }
@@ -723,6 +137,9 @@ static void
 gst_omx_video_dec_init (GstOMXVideoDec * self)
 {
   gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
+  gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
+      (self), TRUE);
+  GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self));
 
   g_mutex_init (&self->drain_lock);
   g_cond_init (&self->drain_cond);
@@ -774,8 +191,8 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
       in_port_index = 0;
       out_port_index = 1;
     } else {
-      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
-          param.nStartPortNumber);
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
       in_port_index = param.nStartPortNumber + 0;
       out_port_index = param.nStartPortNumber + 1;
     }
@@ -794,9 +211,55 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
     return FALSE;
    }
 #endif
-
   GST_DEBUG_OBJECT (self, "Opened decoder");
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  GST_DEBUG_OBJECT (self, "Opening EGL renderer");
+  self->egl_render =
+      gst_omx_component_new (GST_OBJECT_CAST (self), klass->cdata.core_name,
+      "OMX.broadcom.egl_render", NULL, klass->cdata.hacks);
+
+  if (!self->egl_render)
+    return FALSE;
+
+  if (gst_omx_component_get_state (self->egl_render,
+          GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
+    return FALSE;
+
+  {
+    OMX_PORT_PARAM_TYPE param;
+    OMX_ERRORTYPE err;
+
+    GST_OMX_INIT_STRUCT (&param);
+
+    err =
+        gst_omx_component_get_parameter (self->egl_render,
+        OMX_IndexParamVideoInit, &param);
+    if (err != OMX_ErrorNone) {
+      GST_WARNING_OBJECT (self, "Couldn't get port information: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+      /* Fallback */
+      in_port_index = 0;
+      out_port_index = 1;
+    } else {
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
+          param.nStartPortNumber);
+      in_port_index = param.nStartPortNumber + 0;
+      out_port_index = param.nStartPortNumber + 1;
+    }
+  }
+
+  self->egl_in_port =
+      gst_omx_component_add_port (self->egl_render, in_port_index);
+  self->egl_out_port =
+      gst_omx_component_add_port (self->egl_render, out_port_index);
+
+  if (!self->egl_in_port || !self->egl_out_port)
+    return FALSE;
+
+  GST_DEBUG_OBJECT (self, "Opened EGL renderer");
+#endif
+
   return TRUE;
 }
 
@@ -807,6 +270,31 @@ gst_omx_video_dec_shutdown (GstOMXVideoDec * self)
 
   GST_DEBUG_OBJECT (self, "Shutting down decoder");
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  state = gst_omx_component_get_state (self->egl_render, 0);
+  if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
+    if (state > OMX_StateIdle) {
+      gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+      gst_omx_component_set_state (self->dec, OMX_StateIdle);
+      gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+      gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+    }
+    gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+    gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+
+    gst_omx_port_deallocate_buffers (self->dec_in_port);
+    gst_omx_video_dec_deallocate_output_buffers (self);
+    gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+    if (state > OMX_StateLoaded) {
+      gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+      gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+    }
+  }
+
+  /* Otherwise we didn't use EGL and just fall back to 
+   * shutting down the decoder */
+#endif
+
   state = gst_omx_component_get_state (self->dec, 0);
   if (state > OMX_StateLoaded || state == OMX_StateInvalid) {
     if (state > OMX_StateIdle) {
@@ -853,6 +341,14 @@ gst_omx_video_dec_close (GstVideoDecoder * decoder)
     gst_omx_component_free (self->dec);
   self->dec = NULL;
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  self->egl_in_port = NULL;
+  self->egl_out_port = NULL;
+  if (self->egl_render)
+    gst_omx_component_free (self->egl_render);
+  self->egl_render = NULL;
+#endif
+
   self->started = FALSE;
 
   GST_DEBUG_OBJECT (self, "Closed decoder");
@@ -896,6 +392,12 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
         gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
       if (self->dec_out_port)
         gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+      if (self->egl_in_port)
+        gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+      if (self->egl_out_port)
+        gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+#endif
 
       g_mutex_lock (&self->drain_lock);
       self->draining = FALSE;
@@ -903,163 +405,37 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition)
       g_mutex_unlock (&self->drain_lock);
       break;
     default:
-      break;
-  }
-
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
-  ret =
-      GST_ELEMENT_CLASS (gst_omx_video_dec_parent_class)->change_state
-      (element, transition);
-
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      self->downstream_flow_ret = GST_FLOW_FLUSHING;
-      self->started = FALSE;
-
-      if (!gst_omx_video_dec_shutdown (self))
-        ret = GST_STATE_CHANGE_FAILURE;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-#define MAX_FRAME_DIST_TICKS  (5 * OMX_TICKS_PER_SECOND)
-#define MAX_FRAME_DIST_FRAMES (100)
-
-static GstVideoCodecFrame *
-_find_nearest_frame (GstOMXVideoDec * self, GstOMXBuffer * buf)
-{
-  GList *l, *best_l = NULL;
-  GList *finish_frames = NULL;
-  GstVideoCodecFrame *best = NULL;
-  guint64 best_timestamp = 0;
-  guint64 best_diff = G_MAXUINT64;
-  BufferIdentification *best_id = NULL;
-  GList *frames;
-
-  frames = gst_video_decoder_get_frames (GST_VIDEO_DECODER (self));
-
-  for (l = frames; l; l = l->next) {
-    GstVideoCodecFrame *tmp = l->data;
-    BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-    guint64 timestamp, diff;
-
-    /* This happens for frames that were just added but
-     * which were not passed to the component yet. Ignore
-     * them here!
-     */
-    if (!id)
-      continue;
-
-    timestamp = id->timestamp;
-
-    if (timestamp > buf->omx_buf->nTimeStamp)
-      diff = timestamp - buf->omx_buf->nTimeStamp;
-    else
-      diff = buf->omx_buf->nTimeStamp - timestamp;
-
-    if (best == NULL || diff < best_diff) {
-      best = tmp;
-      best_timestamp = timestamp;
-      best_diff = diff;
-      best_l = l;
-      best_id = id;
-
-      /* For frames without timestamp we simply take the first frame */
-      if ((buf->omx_buf->nTimeStamp == 0 && timestamp == 0) || diff == 0)
-        break;
-    }
-  }
-
-  if (best_id) {
-    for (l = frames; l && l != best_l; l = l->next) {
-      GstVideoCodecFrame *tmp = l->data;
-      BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-      guint64 diff_ticks, diff_frames;
-
-      /* This happens for frames that were just added but
-       * which were not passed to the component yet. Ignore
-       * them here!
-       */
-      if (!id)
-        continue;
-
-      if (id->timestamp > best_timestamp)
-        break;
-
-      if (id->timestamp == 0 || best_timestamp == 0)
-        diff_ticks = 0;
-      else
-        diff_ticks = best_timestamp - id->timestamp;
-      diff_frames = best->system_frame_number - tmp->system_frame_number;
-
-      if (diff_ticks > MAX_FRAME_DIST_TICKS
-          || diff_frames > MAX_FRAME_DIST_FRAMES) {
-        finish_frames =
-            g_list_prepend (finish_frames, gst_video_codec_frame_ref (tmp));
-      }
-    }
-  }
-
-  if (finish_frames) {
-    g_warning ("Too old frames, bug in decoder -- please file a bug");
-    for (l = finish_frames; l; l = l->next) {
-      gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), l->data);
-    }
-  }
-
-  if (best)
-    gst_video_codec_frame_ref (best);
-
-  g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
-  g_list_free (frames);
-
-  return best;
-}
-
-#ifdef CODEC_DEC_OUTPUT_DUMP /* for decoder output dump */
-static inline void
-decoder_output_dump(GstOMXVideoDec *self, MMVideoBuffer *outbuf)
-{
-  char *temp = (char *)outbuf->data[0];
-  int i = 0;
-  char filename[100]={0};
-  FILE *fp = NULL;
-  int ret =0;
+      break;
+  }
 
-  GST_ERROR_OBJECT (self, "codec dec output dump start. w = %d, h = %d", outbuf->width[0], outbuf->height[0]);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
 
-  sprintf(filename, "/opt/usr/dec_output_dump_%d_%d.yuv", outbuf->stride_width[0], outbuf->height[0]);
-  fp = fopen(filename, "ab");
+  ret =
+      GST_ELEMENT_CLASS (gst_omx_video_dec_parent_class)->change_state
+      (element, transition);
 
-  for (i = 0; i < outbuf->height[0]; i++) {
-    ret = fwrite(temp, outbuf->width[0], 1, fp);
-    temp += outbuf->stride_width[0];
-  }
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
 
-  temp = (char *)outbuf->data[1];
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      self->downstream_flow_ret = GST_FLOW_FLUSHING;
+      self->started = FALSE;
 
-  for(i = 0; i < outbuf->height[1]; i++) {
-   ret = fwrite(temp, outbuf->width[1], 1, fp);
-    temp += outbuf->stride_width[1];
+      if (!gst_omx_video_dec_shutdown (self))
+        ret = GST_STATE_CHANGE_FAILURE;
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
+    default:
+      break;
   }
 
-  GST_ERROR_OBJECT (self,"codec dec output dumped!! ret = %d", ret);
-  fclose(fp);
+  return ret;
 }
-#endif
 
 static gboolean
 gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
@@ -1074,8 +450,9 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
 
   if (vinfo->width != port_def->format.video.nFrameWidth ||
       vinfo->height != port_def->format.video.nFrameHeight) {
-    GST_ERROR_OBJECT (self, "Resolution do not match. port: %dx%d vinfo: %dx%d",
-        port_def->format.video.nFrameWidth, port_def->format.video.nFrameHeight,
+    GST_ERROR_OBJECT (self, "Resolution do not match: port=%ux%u vinfo=%dx%d",
+        (guint) port_def->format.video.nFrameWidth,
+        (guint) port_def->format.video.nFrameHeight,
         vinfo->width, vinfo->height);
     goto done;
   }
@@ -1085,7 +462,11 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
   if (gst_buffer_get_size (outbuf) == inbuf->omx_buf->nFilledLen) {
     GstMapInfo map = GST_MAP_INFO_INIT;
 
-    gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+    if (!gst_buffer_map (outbuf, &map, GST_MAP_WRITE)) {
+      GST_ERROR_OBJECT (self, "Failed to map output buffer");
+      goto done;
+    }
+
     memcpy (map.data,
         inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset,
         inbuf->omx_buf->nFilledLen);
@@ -1096,100 +477,59 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
 #endif  //ENS:a
 
   /* Different strides */
-
-  switch (vinfo->finfo->format) {
-    case GST_VIDEO_FORMAT_I420:{
-      gint i, j, height, width;
-      guint8 *src, *dest;
-      gint src_stride, dest_stride;
-
-      gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE);
-      for (i = 0; i < 3; i++) {
-        if (i == 0) {
-          src_stride = port_def->format.video.nStride;
-          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-
-          /* XXX: Try this if no stride was set */
-          if (src_stride == 0)
-            src_stride = dest_stride;
-        } else {
-          src_stride = port_def->format.video.nStride / 2;
-          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-
-          /* XXX: Try this if no stride was set */
-          if (src_stride == 0)
-            src_stride = dest_stride;
-        }
-
-        src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
-        if (i > 0)
-          src +=
-              port_def->format.video.nSliceHeight *
-              port_def->format.video.nStride;
-        if (i == 2)
-          src +=
-              (port_def->format.video.nSliceHeight / 2) *
-              (port_def->format.video.nStride / 2);
-
-        dest = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
-        height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
-        width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i);
-
-        for (j = 0; j < height; j++) {
-          memcpy (dest, src, width);
-          src += src_stride;
-          dest += dest_stride;
-        }
-      }
-      gst_video_frame_unmap (&frame);
-      ret = TRUE;
-      break;
-    }
-    case GST_VIDEO_FORMAT_NV12:{
-      gint i, j, height, width;
-      guint8 *src, *dest;
-      gint src_stride, dest_stride;
-
-      gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE);
-      for (i = 0; i < 2; i++) {
-        if (i == 0) {
-          src_stride = port_def->format.video.nStride;
-          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-
-          /* XXX: Try this if no stride was set */
-          if (src_stride == 0)
-            src_stride = dest_stride;
-        } else {
-          src_stride = port_def->format.video.nStride;
-          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&frame, i);
-
-          /* XXX: Try this if no stride was set */
-          if (src_stride == 0)
-            src_stride = dest_stride;
-        }
-
-        src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
-        if (i == 1)
-          src +=
-              port_def->format.video.nSliceHeight *
-              port_def->format.video.nStride;
-
-        dest = GST_VIDEO_FRAME_COMP_DATA (&frame, i);
-        height = GST_VIDEO_FRAME_COMP_HEIGHT (&frame, i);
-        width = GST_VIDEO_FRAME_COMP_WIDTH (&frame, i) * (i == 0 ? 1 : 2);
-
-        for (j = 0; j < height; j++) {
-          memcpy (dest, src, width);
-          src += src_stride;
-          dest += dest_stride;
-        }
-      }
-      gst_video_frame_unmap (&frame);
-      ret = TRUE;
-      break;
-    }
-    case GST_VIDEO_FORMAT_SN12:
-    case GST_VIDEO_FORMAT_ST12:{
+  if (gst_video_frame_map (&frame, vinfo, outbuf, GST_MAP_WRITE)) {
+    const guint nstride = port_def->format.video.nStride;
+    const guint nslice = port_def->format.video.nSliceHeight;
+    guint src_stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
+    guint src_size[GST_VIDEO_MAX_PLANES] = { nstride * nslice, 0, };
+    gint dst_width[GST_VIDEO_MAX_PLANES] = { 0, };
+    gint dst_height[GST_VIDEO_MAX_PLANES] =
+        { GST_VIDEO_INFO_HEIGHT (vinfo), 0, };
+    const guint8 *src;
+    guint p;
+
+    switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+      case GST_VIDEO_FORMAT_ABGR:
+      case GST_VIDEO_FORMAT_ARGB:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 4;
+        break;
+      case GST_VIDEO_FORMAT_RGB16:
+      case GST_VIDEO_FORMAT_BGR16:
+      case GST_VIDEO_FORMAT_YUY2:
+      case GST_VIDEO_FORMAT_UYVY:
+      case GST_VIDEO_FORMAT_YVYU:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo) * 2;
+        break;
+      case GST_VIDEO_FORMAT_GRAY8:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+        break;
+      case GST_VIDEO_FORMAT_I420:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+        src_stride[1] = nstride / 2;
+        src_size[1] = (src_stride[1] * nslice) / 2;
+        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+        src_stride[2] = nstride / 2;
+        src_size[2] = (src_stride[1] * nslice) / 2;
+        dst_width[2] = GST_VIDEO_INFO_WIDTH (vinfo) / 2;
+        dst_height[2] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+        break;
+      case GST_VIDEO_FORMAT_NV12:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+        src_stride[1] = nstride;
+        src_size[1] = src_stride[1] * nslice / 2;
+        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo) / 2;
+        break;
+      case GST_VIDEO_FORMAT_NV16:
+        dst_width[0] = GST_VIDEO_INFO_WIDTH (vinfo);
+        src_stride[1] = nstride;
+        src_size[1] = src_stride[1] * nslice;
+        dst_width[1] = GST_VIDEO_INFO_WIDTH (vinfo);
+        dst_height[1] = GST_VIDEO_INFO_HEIGHT (vinfo);
+        break;
+      case GST_VIDEO_FORMAT_SN12:
+      case GST_VIDEO_FORMAT_ST12:{
         GstMemory *mem_imgb = NULL;
         void *imgb_data = NULL;
 #ifdef USE_MM_VIDEO_BUFFER
@@ -1207,7 +547,7 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
           GST_WARNING_OBJECT (self, "dec output buf has TBM_BO buf_share_method");
         }
 #ifdef CODEC_DEC_OUTPUT_DUMP
-      decoder_output_dump(self, out_imgb);
+       decoder_output_dump(self, out_imgb);
 #endif
 #else
         SCMN_IMGB *out_imgb = NULL;
@@ -1240,12 +580,34 @@ gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
         ret = TRUE;
         break;
     }
-    default:
-      GST_ERROR_OBJECT (self, "Unsupported format");
-      goto done;
-      break;
-  }
 
+      default:
+        g_assert_not_reached ();
+        break;
+    }
+
+    src = inbuf->omx_buf->pBuffer + inbuf->omx_buf->nOffset;
+    for (p = 0; p < GST_VIDEO_INFO_N_PLANES (vinfo); p++) {
+      const guint8 *data;
+      guint8 *dst;
+      guint h;
+
+      dst = GST_VIDEO_FRAME_PLANE_DATA (&frame, p);
+      data = src;
+      for (h = 0; h < dst_height[p]; h++) {
+        memcpy (dst, data, dst_width[p]);
+        dst += GST_VIDEO_INFO_PLANE_STRIDE (vinfo, p);
+        data += src_stride[p];
+      }
+      src += src_size[p];
+    }
+
+    gst_video_frame_unmap (&frame);
+    ret = TRUE;
+  } else {
+    GST_ERROR_OBJECT (self, "Can't map output buffer to frame");
+    goto done;
+  }
 
 done:
   if (ret) {
@@ -1276,18 +638,29 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
   GstVideoCodecState *state =
       gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  port = self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
   port = self->dec_out_port;
+#endif
 
   pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (self));
-  /* FIXME: Enable this once there's a way to request downstream to
-   * release all our buffers, e.g.
-   * http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=release-pool */
   if (pool) {
     GstAllocator *allocator;
 
     config = gst_buffer_pool_get_config (pool);
-    gst_buffer_pool_config_get_params (config, &caps, NULL, &min, &max);
-    gst_buffer_pool_config_get_allocator (config, &allocator, NULL);
+    if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min, &max)) {
+      GST_ERROR_OBJECT (self, "Can't get buffer pool params");
+      gst_structure_free (config);
+      err = OMX_ErrorUndefined;
+      goto done;
+    }
+    if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL)) {
+      GST_ERROR_OBJECT (self, "Can't get buffer pool allocator");
+      gst_structure_free (config);
+      err = OMX_ErrorUndefined;
+      goto done;
+    }
 
     /* Need at least 2 buffers for anything meaningful */
     min = MAX (MAX (min, port->port_def.nBufferCountMin), 4);
@@ -1302,9 +675,15 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
 
     add_videometa = gst_buffer_pool_config_has_option (config,
         GST_BUFFER_POOL_OPTION_VIDEO_META);
+    gst_structure_free (config);
 
-    /* TODO: Implement something here */
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+    eglimage = self->eglimage && (allocator
+        && g_strcmp0 (allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0);
+#else
+    /* TODO: Implement something that works for other targets too */
     eglimage = FALSE;
+#endif
     caps = caps ? gst_caps_ref (caps) : NULL;
 
     GST_DEBUG_OBJECT (self, "Trying to use pool %p with caps %" GST_PTR_FORMAT
@@ -1316,14 +695,150 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
     GST_DEBUG_OBJECT (self, "No pool available, not negotiated yet");
   }
 
-  min = max = port->port_def.nBufferCountMin;
-  if (caps){
-    GST_LOG_OBJECT(self,"gst-omx: Creating our own outport buffer pool. min:[%d], max:[%d]",min,max);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  /* Will retry without EGLImage */
+  if (self->eglimage && !eglimage) {
+    GST_DEBUG_OBJECT (self,
+        "Wanted to use EGLImage but downstream doesn't support it");
+    err = OMX_ErrorUndefined;
+    goto done;
+  }
+#endif
+
+  if (caps)
     self->out_port_pool =
         gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port);
-  }
 
-  /* TODO: Implement EGLImage handling and usage of other downstream buffers */
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (eglimage) {
+    GList *buffers = NULL;
+    GList *images = NULL;
+    gint i;
+    GstBufferPoolAcquireParams params = { 0, };
+    EGLDisplay egl_display = EGL_NO_DISPLAY;
+
+    GST_DEBUG_OBJECT (self, "Trying to allocate %d EGLImages", min);
+
+    for (i = 0; i < min; i++) {
+      GstBuffer *buffer;
+      GstMemory *mem;
+
+      if (gst_buffer_pool_acquire_buffer (pool, &buffer, &params) != GST_FLOW_OK
+          || gst_buffer_n_memory (buffer) != 1
+          || !(mem = gst_buffer_peek_memory (buffer, 0))
+          || g_strcmp0 (mem->allocator->mem_type,
+              GST_EGL_IMAGE_MEMORY_TYPE) != 0) {
+        GST_INFO_OBJECT (self, "Failed to allocated %d-th EGLImage", i);
+        g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+        g_list_free (images);
+        buffers = NULL;
+        images = NULL;
+        /* TODO: For non-RPi targets we want to use the normal memory code below */
+        /* Retry without EGLImage */
+        err = OMX_ErrorUndefined;
+        goto done;
+      }
+
+      buffers = g_list_append (buffers, buffer);
+      gst_egl_image_memory_set_orientation (mem,
+          GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP);
+      images = g_list_append (images, gst_egl_image_memory_get_image (mem));
+      if (egl_display == EGL_NO_DISPLAY)
+        egl_display = gst_egl_image_memory_get_display (mem);
+    }
+
+    GST_DEBUG_OBJECT (self, "Allocated %d EGLImages successfully", min);
+
+    /* Everything went fine? */
+    if (eglimage) {
+      GST_DEBUG_OBJECT (self, "Setting EGLDisplay");
+      self->egl_out_port->port_def.format.video.pNativeWindow = egl_display;
+      err =
+          gst_omx_port_update_port_definition (self->egl_out_port,
+          &self->egl_out_port->port_def);
+      if (err != OMX_ErrorNone) {
+        GST_INFO_OBJECT (self,
+            "Failed to set EGLDisplay on port: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+        g_list_free (images);
+        /* TODO: For non-RPi targets we want to use the normal memory code below */
+        /* Retry without EGLImage */
+        goto done;
+      } else {
+        GList *l;
+
+        if (min != port->port_def.nBufferCountActual) {
+          err = gst_omx_port_update_port_definition (port, NULL);
+          if (err == OMX_ErrorNone) {
+            port->port_def.nBufferCountActual = min;
+            err = gst_omx_port_update_port_definition (port, &port->port_def);
+          }
+
+          if (err != OMX_ErrorNone) {
+            GST_INFO_OBJECT (self,
+                "Failed to configure %u output buffers: %s (0x%08x)", min,
+                gst_omx_error_to_string (err), err);
+            g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+            g_list_free (images);
+            /* TODO: For non-RPi targets we want to use the normal memory code below */
+            /* Retry without EGLImage */
+
+            goto done;
+          }
+        }
+
+        if (!gst_omx_port_is_enabled (port)) {
+          err = gst_omx_port_set_enabled (port, TRUE);
+          if (err != OMX_ErrorNone) {
+            GST_INFO_OBJECT (self,
+                "Failed to enable port: %s (0x%08x)",
+                gst_omx_error_to_string (err), err);
+            g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+            g_list_free (images);
+            /* TODO: For non-RPi targets we want to use the normal memory code below */
+            /* Retry without EGLImage */
+            goto done;
+          }
+        }
+
+        err = gst_omx_port_use_eglimages (port, images);
+        g_list_free (images);
+
+        if (err != OMX_ErrorNone) {
+          GST_INFO_OBJECT (self,
+              "Failed to pass EGLImages to port: %s (0x%08x)",
+              gst_omx_error_to_string (err), err);
+          g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+          /* TODO: For non-RPi targets we want to use the normal memory code below */
+          /* Retry without EGLImage */
+          goto done;
+        }
+
+        err = gst_omx_port_wait_enabled (port, 2 * GST_SECOND);
+        if (err != OMX_ErrorNone) {
+          GST_INFO_OBJECT (self,
+              "Failed to wait until port is enabled: %s (0x%08x)",
+              gst_omx_error_to_string (err), err);
+          g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
+          /* TODO: For non-RPi targets we want to use the normal memory code below */
+          /* Retry without EGLImage */
+          goto done;
+        }
+
+        GST_DEBUG_OBJECT (self, "Populating internal buffer pool");
+        GST_OMX_BUFFER_POOL (self->out_port_pool)->other_pool =
+            GST_BUFFER_POOL (gst_object_ref (pool));
+        for (l = buffers; l; l = l->next) {
+          g_ptr_array_add (GST_OMX_BUFFER_POOL (self->out_port_pool)->buffers,
+              l->data);
+        }
+        g_list_free (buffers);
+        /* All good and done, set caps below */
+      }
+    }
+  }
+#endif
 
   /* If not using EGLImage or trying to use EGLImage failed */
   if (!eglimage) {
@@ -1366,8 +881,15 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
           min);
       min = port->port_def.nBufferCountMin;
 
-      if (!was_enabled)
-        gst_omx_port_set_enabled (port, FALSE);
+      if (!was_enabled) {
+        err = gst_omx_port_set_enabled (port, FALSE);
+        if (err != OMX_ErrorNone) {
+          GST_INFO_OBJECT (self,
+              "Failed to disable port again: %s (0x%08x)",
+              gst_omx_error_to_string (err), err);
+          goto done;
+        }
+      }
 
       if (min != port->port_def.nBufferCountActual) {
         err = gst_omx_port_update_port_definition (port, NULL);
@@ -1390,7 +912,7 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
       err = gst_omx_port_allocate_buffers (port);
 #endif
       /* Can't provide buffers downstream in this case */
-      //gst_caps_replace (&caps, NULL);
+      gst_caps_replace (&caps, NULL);
     }
 
     if (err != OMX_ErrorNone) {
@@ -1467,19 +989,349 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
 
   if (self->out_port_pool) {
     gst_buffer_pool_set_active (self->out_port_pool, FALSE);
+#if 0
+    gst_buffer_pool_wait_released (self->out_port_pool);
+#endif
     GST_OMX_BUFFER_POOL (self->out_port_pool)->deactivated = TRUE;
     gst_object_unref (self->out_port_pool);
     self->out_port_pool = NULL;
   }
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  err =
+      gst_omx_port_deallocate_buffers (self->
+      eglimage ? self->egl_out_port : self->dec_out_port);
+#else
   err = gst_omx_port_deallocate_buffers (self->dec_out_port);
+#endif
+
+  return err;
+}
+
+static OMX_ERRORTYPE
+gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
+{
+  GstOMXPort *port;
+  OMX_ERRORTYPE err;
+  GstVideoCodecState *state;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  GstVideoFormat format;
+
+  /* At this point the decoder output port is disabled */
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  {
+    OMX_STATETYPE egl_state;
+
+    if (self->eglimage) {
+      /* Nothing to do here, we could however fall back to non-EGLImage in theory */
+      port = self->egl_out_port;
+      err = OMX_ErrorNone;
+      goto enable_port;
+    } else {
+      /* Set up egl_render */
+
+      self->eglimage = TRUE;
+
+      gst_omx_port_get_port_definition (self->dec_out_port, &port_def);
+      GST_VIDEO_DECODER_STREAM_LOCK (self);
+      state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
+          GST_VIDEO_FORMAT_RGBA, port_def.format.video.nFrameWidth,
+          port_def.format.video.nFrameHeight, self->input_state);
+
+      /* at this point state->caps is NULL */
+      if (state->caps)
+        gst_caps_unref (state->caps);
+      state->caps = gst_video_info_to_caps (&state->info);
+      gst_caps_set_features (state->caps, 0,
+          gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE, NULL));
+
+      /* try to negotiate with caps feature */
+      if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+
+        GST_DEBUG_OBJECT (self,
+            "Failed to negotiate with feature %s",
+            GST_CAPS_FEATURE_MEMORY_EGL_IMAGE);
+
+        if (state->caps)
+          gst_caps_replace (&state->caps, NULL);
+
+        /* fallback: try to use EGLImage even if it is not in the caps feature */
+        if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+          gst_video_codec_state_unref (state);
+          GST_ERROR_OBJECT (self, "Failed to negotiate RGBA for EGLImage");
+          GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+          goto no_egl;
+        }
+      }
+
+      gst_video_codec_state_unref (state);
+      GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+      /* Now link it all together */
+
+      err = gst_omx_port_set_enabled (self->egl_in_port, FALSE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_set_enabled (self->egl_out_port, FALSE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_wait_enabled (self->egl_out_port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      {
+#define OMX_IndexParamBrcmVideoEGLRenderDiscardMode 0x7f0000db
+        OMX_CONFIG_PORTBOOLEANTYPE discardMode;
+        memset (&discardMode, 0, sizeof (discardMode));
+        discardMode.nSize = sizeof (discardMode);
+        discardMode.nPortIndex = 220;
+        discardMode.nVersion.nVersion = OMX_VERSION;
+        discardMode.bEnabled = OMX_FALSE;
+        if (gst_omx_component_set_parameter (self->egl_render,
+                OMX_IndexParamBrcmVideoEGLRenderDiscardMode,
+                &discardMode) != OMX_ErrorNone)
+          goto no_egl;
+#undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
+      }
+
+      err = gst_omx_setup_tunnel (self->dec_out_port, self->egl_in_port);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_set_enabled (self->egl_in_port, TRUE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_wait_enabled (self->egl_in_port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      if (gst_omx_component_get_state (self->egl_render,
+              GST_CLOCK_TIME_NONE) != OMX_StateIdle)
+        goto no_egl;
+
+      err = gst_omx_video_dec_allocate_output_buffers (self);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      if (gst_omx_component_set_state (self->egl_render,
+              OMX_StateExecuting) != OMX_ErrorNone)
+        goto no_egl;
+
+      if (gst_omx_component_get_state (self->egl_render,
+              GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
+        goto no_egl;
+
+      err =
+          gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err =
+          gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err =
+          gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_populate (self->egl_out_port);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_set_enabled (self->dec_out_port, TRUE);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+
+      err = gst_omx_port_mark_reconfigured (self->dec_out_port);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      err = gst_omx_port_mark_reconfigured (self->egl_out_port);
+      if (err != OMX_ErrorNone)
+        goto no_egl;
+
+      goto done;
+    }
+
+  no_egl:
+
+    gst_omx_port_set_enabled (self->dec_out_port, FALSE);
+    gst_omx_port_wait_enabled (self->dec_out_port, 1 * GST_SECOND);
+    egl_state = gst_omx_component_get_state (self->egl_render, 0);
+    if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
+      if (egl_state > OMX_StateIdle) {
+        gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+        gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+      }
+      gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+
+      gst_omx_video_dec_deallocate_output_buffers (self);
+      gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+
+      if (egl_state > OMX_StateLoaded) {
+        gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+      }
+    }
+
+    /* After this egl_render should be deactivated
+     * and the decoder's output port disabled */
+    self->eglimage = FALSE;
+  }
+#endif
+  port = self->dec_out_port;
+
+  /* Update caps */
+  GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  g_assert (port_def.format.video.eCompressionFormat == OMX_VIDEO_CodingUnused);
+
+  format =
+      gst_omx_video_get_format_from_omx (port_def.format.video.eColorFormat);
+
+  if (format == GST_VIDEO_FORMAT_UNKNOWN) {
+    GST_ERROR_OBJECT (self, "Unsupported color format: %d",
+        port_def.format.video.eColorFormat);
+    GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+    err = OMX_ErrorUndefined;
+    goto done;
+  }
+
+  GST_DEBUG_OBJECT (self,
+      "Setting output state: format %s (%d), width %u, height %u",
+      gst_video_format_to_string (format),
+      port_def.format.video.eColorFormat,
+      (guint) port_def.format.video.nFrameWidth,
+      (guint) port_def.format.video.nFrameHeight);
+
+  state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
+      format, port_def.format.video.nFrameWidth,
+      port_def.format.video.nFrameHeight, self->input_state);
+
+  if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+    gst_video_codec_state_unref (state);
+    GST_ERROR_OBJECT (self, "Failed to negotiate");
+    err = OMX_ErrorUndefined;
+    GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+    goto done;
+  }
+
+  gst_video_codec_state_unref (state);
+
+  GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+enable_port:
+#endif
+  err = gst_omx_video_dec_allocate_output_buffers (self);
+  if (err != OMX_ErrorNone)
+    goto done;
+
+  err = gst_omx_port_populate (port);
+  if (err != OMX_ErrorNone)
+    goto done;
+
+  err = gst_omx_port_mark_reconfigured (port);
+  if (err != OMX_ErrorNone)
+    goto done;
+
+done:
+
+  return err;
+}
+
+static void
+gst_omx_video_dec_clean_older_frames (GstOMXVideoDec * self,
+    GstOMXBuffer * buf, GList * frames)
+{
+  GList *l;
+  GstClockTime timestamp;
+
+  timestamp = gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
+      OMX_TICKS_PER_SECOND);
+
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    /* We could release all frames stored with pts < timestamp since the
+     * decoder will likely output frames in display order */
+    for (l = frames; l; l = l->next) {
+      GstVideoCodecFrame *tmp = l->data;
+
+      if (tmp->pts < timestamp) {
+        gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
+        GST_LOG_OBJECT (self,
+            "discarding ghost frame %p (#%d) PTS:%" GST_TIME_FORMAT " DTS:%"
+            GST_TIME_FORMAT, tmp, tmp->system_frame_number,
+            GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
+      } else {
+        gst_video_codec_frame_unref (tmp);
+      }
+    }
+  } else {
+    /* We will release all frames with invalid timestamp because we don't even
+     * know if they will be output some day. */
+    for (l = frames; l; l = l->next) {
+      GstVideoCodecFrame *tmp = l->data;
+
+      if (!GST_CLOCK_TIME_IS_VALID (tmp->pts)) {
+        gst_video_decoder_release_frame (GST_VIDEO_DECODER (self), tmp);
+        GST_LOG_OBJECT (self,
+            "discarding frame %p (#%d) with invalid PTS:%" GST_TIME_FORMAT
+            " DTS:%" GST_TIME_FORMAT, tmp, tmp->system_frame_number,
+            GST_TIME_ARGS (tmp->pts), GST_TIME_ARGS (tmp->dts));
+      } else {
+        gst_video_codec_frame_unref (tmp);
+      }
+    }
+  }
+
+  g_list_free (frames);
+}
+
+static GstBuffer *
+copy_frame (const GstVideoInfo * info, GstBuffer * outbuf)
+{
+  GstVideoInfo out_info, tmp_info;
+  GstBuffer *tmpbuf;
+  GstVideoFrame out_frame, tmp_frame;
 
-  return err;
+  out_info = *info;
+  tmp_info = *info;
+
+  tmpbuf = gst_buffer_new_and_alloc (out_info.size);
+
+  gst_video_frame_map (&out_frame, &out_info, outbuf, GST_MAP_READ);
+  gst_video_frame_map (&tmp_frame, &tmp_info, tmpbuf, GST_MAP_WRITE);
+  gst_video_frame_copy (&tmp_frame, &out_frame);
+  gst_video_frame_unmap (&out_frame);
+  gst_video_frame_unmap (&tmp_frame);
+
+  gst_buffer_unref (outbuf);
+
+  return tmpbuf;
 }
 
 static void
 gst_omx_video_dec_loop (GstOMXVideoDec * self)
 {
-  GstOMXPort *port = self->dec_out_port;
+  GstOMXPort *port;
   GstOMXBuffer *buf = NULL;
   GstVideoCodecFrame *frame;
   GstFlowReturn flow_ret = GST_FLOW_OK;
@@ -1487,6 +1339,12 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
   GstClockTimeDiff deadline;
   OMX_ERRORTYPE err;
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  port = self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+  port = self->dec_out_port;
+#endif
+
   acq_return = gst_omx_port_acquire_buffer (port, &buf);
   if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
     goto component_error;
@@ -1524,79 +1382,55 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
         goto reconfigure_error;
     }
 
-    GST_VIDEO_DECODER_STREAM_LOCK (self);
+    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+      /* We have the possibility to reconfigure everything now */
+      err = gst_omx_video_dec_reconfigure_output_port (self);
+      if (err != OMX_ErrorNone)
+        goto reconfigure_error;
+    } else {
+      /* Just update caps */
+      GST_VIDEO_DECODER_STREAM_LOCK (self);
 
-    gst_omx_port_get_port_definition (port, &port_def);
-    g_assert (port_def.format.video.eCompressionFormat ==
-        OMX_VIDEO_CodingUnused);
+      gst_omx_port_get_port_definition (port, &port_def);
+      g_assert (port_def.format.video.eCompressionFormat ==
+          OMX_VIDEO_CodingUnused);
 
-    switch (port_def.format.video.eColorFormat) {
-      case OMX_COLOR_FormatYUV420Planar:
-      case OMX_COLOR_FormatYUV420PackedPlanar:
-        GST_ERROR_OBJECT (self, "Output is I420 (%d)",
-            port_def.format.video.eColorFormat);
-        format = GST_VIDEO_FORMAT_I420;
-        break;
-      case OMX_COLOR_FormatYUV420SemiPlanar:
-        GST_ERROR_OBJECT (self, "Output is NV12 (%d)",
-            port_def.format.video.eColorFormat);
-        format = GST_VIDEO_FORMAT_NV12;
-        break;
-      case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
-#ifdef USE_MM_VIDEO_BUFFER
-        GST_LOG_OBJECT (self, "Output is SN12 (%d)",
-            port_def.format.video.eColorFormat);
-        format = GST_VIDEO_FORMAT_SN12;
-#else
-        GST_LOG_OBJECT (self, "Output is ST12 (%d)",
-            port_def.format.video.eColorFormat);
-        format = GST_VIDEO_FORMAT_ST12;
-#endif
-        break;
-      default:
+      format =
+          gst_omx_video_get_format_from_omx (port_def.format.
+          video.eColorFormat);
+
+      if (format == GST_VIDEO_FORMAT_UNKNOWN) {
         GST_ERROR_OBJECT (self, "Unsupported color format: %d",
             port_def.format.video.eColorFormat);
         if (buf)
-          gst_omx_port_release_buffer (self->dec_out_port, buf);
+          gst_omx_port_release_buffer (port, buf);
         GST_VIDEO_DECODER_STREAM_UNLOCK (self);
         goto caps_failed;
-        break;
-    }
-
-    GST_DEBUG_OBJECT (self,
-        "Setting output state: format %s, width %lu, height %lu",
-        gst_video_format_to_string (format),
-        port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight);
-
-    state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
-        format, port_def.format.video.nFrameWidth,
-        port_def.format.video.nFrameHeight, self->input_state);
-
-    /* Take framerate and pixel-aspect-ratio from sinkpad caps */
+      }
 
-    if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
-      if (buf)
-        gst_omx_port_release_buffer (self->dec_out_port, buf);
-      gst_video_codec_state_unref (state);
-      goto caps_failed;
-    }
+      GST_DEBUG_OBJECT (self,
+          "Setting output state: format %s (%d), width %u, height %u",
+          gst_video_format_to_string (format),
+          port_def.format.video.eColorFormat,
+          (guint) port_def.format.video.nFrameWidth,
+          (guint) port_def.format.video.nFrameHeight);
 
-    gst_video_codec_state_unref (state);
+      state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
+          format, port_def.format.video.nFrameWidth,
+          port_def.format.video.nFrameHeight, self->input_state);
 
-    GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+      /* Take framerate and pixel-aspect-ratio from sinkpad caps */
 
-    if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
-      err = gst_omx_video_dec_allocate_output_buffers (self);
-      if (err != OMX_ErrorNone)
-        goto reconfigure_error;
+      if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
+        if (buf)
+          gst_omx_port_release_buffer (port, buf);
+        gst_video_codec_state_unref (state);
+        goto caps_failed;
+      }
 
-      err = gst_omx_port_populate (port);
-      if (err != OMX_ErrorNone)
-        goto reconfigure_error;
+      gst_video_codec_state_unref (state);
 
-      err = gst_omx_port_mark_reconfigured (port);
-      if (err != OMX_ErrorNone)
-        goto reconfigure_error;
+      GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     }
 
     /* Now get a buffer */
@@ -1611,17 +1445,27 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
    * lock and the videocodec stream lock, if ::reset()
    * is called at the wrong time
    */
-  if (gst_omx_port_is_flushing (self->dec_out_port)) {
-    GST_ERROR_OBJECT (self, "Flushing");
-    gst_omx_port_release_buffer (self->dec_out_port, buf);
+  if (gst_omx_port_is_flushing (port)) {
+    GST_DEBUG_OBJECT (self, "Flushing");
+    gst_omx_port_release_buffer (port, buf);
     goto flushing;
   }
 
-  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08lx %" G_GUINT64_FORMAT,
-      buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
+  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+      (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
 
   GST_VIDEO_DECODER_STREAM_LOCK (self);
-  frame = _find_nearest_frame (self, buf);
+  frame = gst_omx_video_find_nearest_frame (buf,
+      gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
+
+  /* So we have a timestamped OMX buffer and get, or not, corresponding frame.
+   * Assuming decoder output frames in display order, frames preceding this
+   * frame could be discarded as they seems useless due to e.g interlaced
+   * stream, corrupted input data...
+   * In any cases, not likely to be seen again. so drop it before they pile up
+   * and use all the memory. */
+  gst_omx_video_dec_clean_older_frames (self, buf,
+      gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
 
   if (frame
       && (deadline = gst_video_decoder_get_max_decode_time
@@ -1631,8 +1475,8 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
         GST_TIME_ARGS (-deadline));
     flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
     frame = NULL;
-  } else if (!frame && buf->omx_buf->nFilledLen > 0) {
-    GstBuffer *outbuf;
+  } else if (!frame && (buf->omx_buf->nFilledLen > 0 || buf->eglimage)) {
+    GstBuffer *outbuf = NULL;
 
     /* This sometimes happens at EOS or if the input is not properly framed,
      * let's handle it gracefully by allocating a new buffer for the current
@@ -1662,6 +1506,12 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
         gst_omx_port_release_buffer (port, buf);
         goto invalid_buffer;
       }
+
+      if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+        outbuf =
+            copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+            outbuf);
+
       buf = NULL;
     } else {
       outbuf =
@@ -1674,9 +1524,10 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
     }
 
     flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
-  } else if (buf->omx_buf->nFilledLen > 0) {
+  } else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
     if (self->out_port_pool) {
       gint i, n;
+      GstBuffer *outbuf;
       GstBufferPoolAcquireParams params = { 0, };
 
       n = port->buffers->len;
@@ -1691,7 +1542,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
       GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
       flow_ret =
           gst_buffer_pool_acquire_buffer (self->out_port_pool,
-          &frame->output_buffer, &params);
+          &outbuf, &params);
       if (flow_ret != GST_FLOW_OK) {
         flow_ret =
             gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
@@ -1699,14 +1550,14 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
         gst_omx_port_release_buffer (port, buf);
         goto invalid_buffer;
       }
-      if(!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) {
-        gst_buffer_replace (&frame->output_buffer, NULL);
-        flow_ret =
-            gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
-        frame = NULL;
-        gst_omx_port_release_buffer (port, buf);
-        goto invalid_buffer;
-      }
+
+      if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+        outbuf =
+            copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+            outbuf);
+
+      frame->output_buffer = outbuf;
+
       flow_ret =
           gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
       frame = NULL;
@@ -1782,6 +1633,13 @@ eos:
   {
     g_mutex_lock (&self->drain_lock);
     if (self->draining) {
+      GstQuery *query = gst_query_new_drain ();
+
+      /* Drain the pipeline to reclaim all memories back to the pool */
+      if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (self), query))
+        GST_DEBUG_OBJECT (self, "drain query failed");
+      gst_query_unref (query);
+
       GST_DEBUG_OBJECT (self, "Drained");
       self->draining = FALSE;
       g_cond_broadcast (&self->drain_cond);
@@ -1792,6 +1650,8 @@ eos:
       flow_ret = GST_FLOW_EOS;
     }
     g_mutex_unlock (&self->drain_lock);
+
+    GST_VIDEO_DECODER_STREAM_LOCK (self);
     self->downstream_flow_ret = flow_ret;
 
     /* Here we fallback and pause the task for the EOS case */
@@ -1811,7 +1671,8 @@ flow_error:
       gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
-    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
+      self->started = FALSE;
+    } else if (flow_ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (self, STREAM, FAILED,
           ("Internal data stream error."), ("stream stopped, reason %s",
               gst_flow_get_name (flow_ret)));
@@ -1819,8 +1680,12 @@ flow_error:
       gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
+      self->started = FALSE;
+    } else if (flow_ret == GST_FLOW_FLUSHING) {
+      GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+      gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
+      self->started = FALSE;
     }
-    self->started = FALSE;
     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     return;
   }
@@ -1880,7 +1745,6 @@ gst_omx_video_dec_start (GstVideoDecoder * decoder)
   self = GST_OMX_VIDEO_DEC (decoder);
 
   self->last_upstream_ts = 0;
-  self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
 
   return TRUE;
@@ -1898,14 +1762,22 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+  gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+#endif
+
   gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
 
   if (gst_omx_component_get_state (self->dec, 0) > OMX_StateIdle)
     gst_omx_component_set_state (self->dec, OMX_StateIdle);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (gst_omx_component_get_state (self->egl_render, 0) > OMX_StateIdle)
+    gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+#endif
 
   self->downstream_flow_ret = GST_FLOW_FLUSHING;
   self->started = FALSE;
-  self->eos = FALSE;
 
   g_mutex_lock (&self->drain_lock);
   self->draining = FALSE;
@@ -1913,6 +1785,9 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
   g_mutex_unlock (&self->drain_lock);
 
   gst_omx_component_get_state (self->dec, 5 * GST_SECOND);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  gst_omx_component_get_state (self->egl_render, 1 * GST_SECOND);
+#endif
 
   gst_buffer_replace (&self->codec_data, NULL);
 
@@ -1925,100 +1800,6 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
   return TRUE;
 }
 
-typedef struct
-{
-  GstVideoFormat format;
-  OMX_COLOR_FORMATTYPE type;
-} VideoNegotiationMap;
-
-static void
-video_negotiation_map_free (VideoNegotiationMap * m)
-{
-  g_slice_free (VideoNegotiationMap, m);
-}
-
-static GList *
-gst_omx_video_dec_get_supported_colorformats (GstOMXVideoDec * self)
-{
-  GstOMXPort *port = self->dec_out_port;
-  GstVideoCodecState *state = self->input_state;
-  OMX_VIDEO_PARAM_PORTFORMATTYPE param;
-  OMX_ERRORTYPE err;
-  GList *negotiation_map = NULL;
-  gint old_index;
-
-  GST_OMX_INIT_STRUCT (&param);
-  param.nPortIndex = port->index;
-  param.nIndex = 0;
-  if (!state || state->info.fps_n == 0)
-    param.xFramerate = 0;
-  else
-    param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
-
-  old_index = -1;
-  do {
-    VideoNegotiationMap *m;
-
-    err =
-        gst_omx_component_get_parameter (self->dec,
-        OMX_IndexParamVideoPortFormat, &param);
-
-    /* FIXME: Workaround for Bellagio that simply always
-     * returns the same value regardless of nIndex and
-     * never returns OMX_ErrorNoMore
-     */
-    if (old_index == param.nIndex)
-      break;
-
-    if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
-      switch (param.eColorFormat) {
-        case OMX_COLOR_FormatYUV420Planar:
-        case OMX_COLOR_FormatYUV420PackedPlanar:
-          m = g_slice_new (VideoNegotiationMap);
-          m->format = GST_VIDEO_FORMAT_I420;
-          m->type = param.eColorFormat;
-          negotiation_map = g_list_append (negotiation_map, m);
-          GST_DEBUG_OBJECT (self, "Component supports I420 (%d) at index %lu",
-              param.eColorFormat, param.nIndex);
-          break;
-        case OMX_COLOR_FormatYUV420SemiPlanar:
-          m = g_slice_new (VideoNegotiationMap);
-          m->format = GST_VIDEO_FORMAT_NV12;
-          m->type = param.eColorFormat;
-          negotiation_map = g_list_append (negotiation_map, m);
-          GST_DEBUG_OBJECT (self, "Component supports NV12 (%d) at index %lu",
-              param.eColorFormat, param.nIndex);
-          break;
-        case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
-            m = g_slice_new (VideoNegotiationMap);
-#ifdef USE_MM_VIDEO_BUFFER
-            m->format = GST_VIDEO_FORMAT_SN12;
-            m->type = param.eColorFormat;
-            negotiation_map = g_list_append (negotiation_map, m);
-            GST_DEBUG_OBJECT (self, "Component supports SN12 (%d) at index %d",
-                param.eColorFormat, param.nIndex);
-#else
-            m->format = GST_VIDEO_FORMAT_ST12;
-            m->type = param.eColorFormat;
-            negotiation_map = g_list_append (negotiation_map, m);
-            GST_DEBUG_OBJECT (self, "Component supports ST12 (%d) at index %d",
-                param.eColorFormat, param.nIndex);
-#endif
-            break;
-
-        default:
-          GST_DEBUG_OBJECT (self,
-              "Component supports unsupported color format %d at index %lu",
-              param.eColorFormat, param.nIndex);
-          break;
-      }
-    }
-    old_index = param.nIndex++;
-  } while (err == OMX_ErrorNone);
-
-  return negotiation_map;
-}
-
 static gboolean
 gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
 {
@@ -2030,8 +1811,6 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   GstVideoFormat format;
   GstStructure *s;
   const gchar *format_str;
-  gchar *format_tmp;
-  int i;
 #ifdef USE_TBM
   EnableGemBuffersParams gemBuffers;
 #endif
@@ -2046,16 +1825,11 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   GST_DEBUG_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
       intersection);
 
-  negotiation_map = gst_omx_video_dec_get_supported_colorformats (self);
-  comp_supported_caps = gst_caps_new_empty ();
-  for (l = negotiation_map; l; l = l->next) {
-    VideoNegotiationMap *map = l->data;
+  negotiation_map =
+      gst_omx_video_get_supported_colorformats (self->dec_out_port,
+      self->input_state);
 
-    gst_caps_append_structure (comp_supported_caps,
-        gst_structure_new ("video/x-raw",
-            "format", G_TYPE_STRING,
-            gst_video_format_to_string (map->format), NULL));
-  }
+  comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
 
   if (!gst_caps_is_empty (comp_supported_caps)) {
     GstCaps *tmp;
@@ -2070,38 +1844,23 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
     gst_caps_unref (intersection);
     GST_ERROR_OBJECT (self, "Empty caps");
     g_list_free_full (negotiation_map,
-        (GDestroyNotify) video_negotiation_map_free);
+        (GDestroyNotify) gst_omx_video_negotiation_map_free);
     return FALSE;
   }
 
-  for(i=0; i<gst_caps_get_size(intersection); i++)
-  {
-      s = gst_caps_get_structure (intersection, i);
-      format_tmp = gst_structure_get_string (s, "format");
-
-      if(!strncmp(format_tmp, "S", 1)) {
-          format_str = format_tmp;
-          GST_DEBUG_OBJECT (self, "SEC format found");
-          break;
-      }
-  }
-
-  if(!format_str) {
-    intersection = gst_caps_truncate (intersection);
-    intersection = gst_caps_fixate (intersection);
-
-    s = gst_caps_get_structure (intersection, 0);
-    format_str = gst_structure_get_string (s, "format");
-    GST_DEBUG_OBJECT (self, "first structure will be fixated");
-  }
+  intersection = gst_caps_truncate (intersection);
+  intersection = gst_caps_fixate (intersection);
 
+  s = gst_caps_get_structure (intersection, 0);
+  format_str = gst_structure_get_string (s, "format");
   if (!format_str ||
       (format =
           gst_video_format_from_string (format_str)) ==
       GST_VIDEO_FORMAT_UNKNOWN) {
     GST_ERROR_OBJECT (self, "Invalid caps: %" GST_PTR_FORMAT, intersection);
+    gst_caps_unref (intersection);
     g_list_free_full (negotiation_map,
-        (GDestroyNotify) video_negotiation_map_free);
+        (GDestroyNotify) gst_omx_video_negotiation_map_free);
     return FALSE;
   }
 
@@ -2109,7 +1868,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   param.nPortIndex = self->dec_out_port->index;
 
   for (l = negotiation_map; l; l = l->next) {
-    VideoNegotiationMap *m = l->data;
+    GstOMXVideoNegotiationMap *m = l->data;
 
     if (m->format == format) {
       param.eColorFormat = m->type;
@@ -2123,7 +1882,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   /* We must find something here */
   g_assert (l != NULL);
   g_list_free_full (negotiation_map,
-      (GDestroyNotify) video_negotiation_map_free);
+      (GDestroyNotify) gst_omx_video_negotiation_map_free);
 
   err =
       gst_omx_component_set_parameter (self->dec,
@@ -2148,6 +1907,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
         gst_omx_error_to_string (err), err);
   }
 #endif
+  gst_caps_unref (intersection);
   return (err == OMX_ErrorNone);
 }
 
@@ -2200,17 +1960,18 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
   }
 
   if (needs_disable && is_format_change) {
-    GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+    GstOMXPort *out_port =
+        self->eglimage ? self->egl_out_port : self->dec_out_port;
+#else
+    GstOMXPort *out_port = self->dec_out_port;
+#endif
 
-    gst_omx_video_dec_drain (self, FALSE);
-    gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+    GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
 
-    /* Wait until the srcpad loop is finished,
-     * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
-     * caused by using this lock from inside the loop function */
-    GST_VIDEO_DECODER_STREAM_UNLOCK (self);
-    gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
-    GST_VIDEO_DECODER_STREAM_LOCK (self);
+    gst_omx_video_dec_drain (self);
+    gst_omx_video_dec_flush (decoder);
+    gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
 
     if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
       GST_VIDEO_DECODER_STREAM_UNLOCK (self);
@@ -2222,14 +1983,23 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
         return FALSE;
       needs_disable = FALSE;
     } else {
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+      if (self->eglimage) {
+        gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+        gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+        gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+        gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+      }
+#endif
+
       if (gst_omx_port_set_enabled (self->dec_in_port, FALSE) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
+      if (gst_omx_port_set_enabled (out_port, FALSE) != OMX_ErrorNone)
         return FALSE;
       if (gst_omx_port_wait_buffers_released (self->dec_in_port,
               5 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_wait_buffers_released (self->dec_out_port,
+      if (gst_omx_port_wait_buffers_released (out_port,
               1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
       if (gst_omx_port_deallocate_buffers (self->dec_in_port) != OMX_ErrorNone)
@@ -2239,9 +2009,40 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
       if (gst_omx_port_wait_enabled (self->dec_in_port,
               1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
-      if (gst_omx_port_wait_enabled (self->dec_out_port,
-              1 * GST_SECOND) != OMX_ErrorNone)
+      if (gst_omx_port_wait_enabled (out_port, 1 * GST_SECOND) != OMX_ErrorNone)
         return FALSE;
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+      if (self->eglimage) {
+        OMX_STATETYPE egl_state;
+
+        egl_state = gst_omx_component_get_state (self->egl_render, 0);
+        if (egl_state > OMX_StateLoaded || egl_state == OMX_StateInvalid) {
+
+          if (egl_state > OMX_StateIdle) {
+            gst_omx_component_set_state (self->egl_render, OMX_StateIdle);
+            gst_omx_component_set_state (self->dec, OMX_StateIdle);
+            egl_state = gst_omx_component_get_state (self->egl_render,
+                5 * GST_SECOND);
+            gst_omx_component_get_state (self->dec, 1 * GST_SECOND);
+          }
+          gst_omx_component_set_state (self->egl_render, OMX_StateLoaded);
+          gst_omx_component_set_state (self->dec, OMX_StateLoaded);
+
+          gst_omx_close_tunnel (self->dec_out_port, self->egl_in_port);
+
+          if (egl_state > OMX_StateLoaded) {
+            gst_omx_component_get_state (self->egl_render, 5 * GST_SECOND);
+          }
+
+          gst_omx_component_set_state (self->dec, OMX_StateIdle);
+
+          gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+          gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+        }
+        self->eglimage = FALSE;
+      }
+#endif
     }
     if (self->input_state)
       gst_video_codec_state_unref (self->input_state);
@@ -2291,53 +2092,62 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
       return FALSE;
 #endif
 
+    if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      if (gst_omx_port_set_enabled (self->dec_out_port, TRUE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->dec_out_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
+
     if (gst_omx_port_wait_enabled (self->dec_in_port,
             5 * GST_SECOND) != OMX_ErrorNone)
       return FALSE;
-
     if (gst_omx_port_mark_reconfigured (self->dec_in_port) != OMX_ErrorNone)
       return FALSE;
   } else {
     if (!gst_omx_video_dec_negotiate (self))
       GST_LOG_OBJECT (self, "Negotiation failed, will get output format later");
 
-    if (gst_omx_component_set_state (self->dec, OMX_StateIdle) != OMX_ErrorNone)
-      return FALSE;
+    if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      /* Disable output port */
+      if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
 
-    /* Need to allocate buffers to reach Idle state */
-#ifdef USE_TBM
-    if(gst_omx_port_tbm_allocate_dec_buffers(self->hTBMBufMgr,self->dec_in_port,0) != OMX_ErrorNone)
-     return FALSE;
-#else
-    if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
-      return FALSE;
-#endif
+      if (gst_omx_port_wait_enabled (self->dec_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_component_set_state (self->dec,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+        return FALSE;
+    } else {
+      if (gst_omx_component_set_state (self->dec,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+      if (gst_omx_port_allocate_buffers (self->dec_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
+        return FALSE;
+    }
 
-#ifdef USE_TBM
-    if(gst_omx_port_tbm_allocate_dec_buffers(self->hTBMBufMgr,self->dec_out_port,
-        self->dec_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
-     return FALSE;
-#else
-    if (gst_omx_port_allocate_buffers (self->dec_out_port) != OMX_ErrorNone)
-      return FALSE;
-#endif
-#if 0
-    GST_ERROR_OBJECT (self, "\n6. DISABLE OUTPUT PORT\n");
-    /* And disable output port */
-    if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-    GST_ERROR_OBJECT (self, "\n7. DISABLE OUTPUT PORT WAIT\n");
-    if (gst_omx_port_wait_enabled (self->dec_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-#endif
     if (gst_omx_component_get_state (self->dec,
             GST_CLOCK_TIME_NONE) != OMX_StateIdle)
       return FALSE;
+
     if (gst_omx_component_set_state (self->dec,
             OMX_StateExecuting) != OMX_ErrorNone)
       return FALSE;
-    GST_ERROR_OBJECT (self, "\n9. GET COMPONENT STATE\n");
+
     if (gst_omx_component_get_state (self->dec,
             GST_CLOCK_TIME_NONE) != OMX_StateExecuting)
       return FALSE;
@@ -2354,50 +2164,92 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
     return FALSE;
   }
 
-  /* Start the srcpad loop again */
-  GST_DEBUG_OBJECT (self, "Starting task again");
-
   self->downstream_flow_ret = GST_FLOW_OK;
-  gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
-
   return TRUE;
 }
 
 static gboolean
-gst_omx_video_dec_reset (GstVideoDecoder * decoder, gboolean hard)
+gst_omx_video_dec_flush (GstVideoDecoder * decoder)
 {
-  GstOMXVideoDec *self;
-
-  self = GST_OMX_VIDEO_DEC (decoder);
+  GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (decoder);
+  OMX_ERRORTYPE err = OMX_ErrorNone;
 
-  /* FIXME: Handle different values of hard */
+  GST_DEBUG_OBJECT (self, "Flushing decoder");
 
-  GST_DEBUG_OBJECT (self, "Resetting decoder");
+  if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
+    return TRUE;
 
-  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
-  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+  /* 0) Pause the components */
+  if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
+    gst_omx_component_set_state (self->dec, OMX_StatePause);
+    gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+  }
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (self->eglimage) {
+    if (gst_omx_component_get_state (self->egl_render, 0) == OMX_StateExecuting) {
+      gst_omx_component_set_state (self->egl_render, OMX_StatePause);
+      gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+    }
+  }
+#endif
 
-  /* Wait until the srcpad loop is finished,
+  /* 1) Wait until the srcpad loop is stopped,
    * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
    * caused by using this lock from inside the loop function */
   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
-  GST_PAD_STREAM_LOCK (GST_VIDEO_DECODER_SRC_PAD (self));
-  GST_PAD_STREAM_UNLOCK (GST_VIDEO_DECODER_SRC_PAD (self));
+  gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
+  GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
   GST_VIDEO_DECODER_STREAM_LOCK (self);
 
+  /* 2) Flush the ports */
+  GST_DEBUG_OBJECT (self, "flushing ports");
+  gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
+  gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
+
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (self->eglimage) {
+    gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, TRUE);
+    gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, TRUE);
+  }
+#endif
+
+  /* 3) Resume components */
+  gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+  gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (self->eglimage) {
+    gst_omx_component_set_state (self->egl_render, OMX_StateExecuting);
+    gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+  }
+#endif
+
+  /* 4) Unset flushing to allow ports to accept data again */
   gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
   gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
-  gst_omx_port_populate (self->dec_out_port);
 
-  /* Start the srcpad loop again */
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  if (self->eglimage) {
+    gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
+    gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
+    err = gst_omx_port_populate (self->egl_out_port);
+    gst_omx_port_mark_reconfigured (self->egl_out_port);
+  } else {
+    err = gst_omx_port_populate (self->dec_out_port);
+  }
+#else
+  err = gst_omx_port_populate (self->dec_out_port);
+#endif
+
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (self, "Failed to populate output port: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+  }
+
+  /* Reset our state */
   self->last_upstream_ts = 0;
-  self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
-  gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
-
-  GST_DEBUG_OBJECT (self, "Reset decoder");
+  self->started = FALSE;
+  GST_DEBUG_OBJECT (self, "Flush finished");
 
   return TRUE;
 }
@@ -2421,15 +2273,14 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
 
   GST_DEBUG_OBJECT (self, "Handling frame");
 
-  if (self->eos) {
-    GST_WARNING_OBJECT (self, "Got frame after EOS");
-    gst_video_codec_frame_unref (frame);
-    return GST_FLOW_EOS;
-  }
-
-  if (!self->started && !GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
-    gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
-    return GST_FLOW_OK;
+  if (!self->started) {
+    if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
+      gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+      return GST_FLOW_OK;
+    }
+    GST_DEBUG_OBJECT (self, "Starting task");
+    gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
+        (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
   }
 
   timestamp = frame->pts;
@@ -2619,22 +2470,14 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
 
     if (duration != GST_CLOCK_TIME_NONE && offset == 0) {
       buf->omx_buf->nTickCount =
-          gst_util_uint64_scale (buf->omx_buf->nFilledLen, duration, size);
+          gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
       self->last_upstream_ts += duration;
     } else {
       buf->omx_buf->nTickCount = 0;
     }
 
-    if (offset == 0) {
-      BufferIdentification *id = g_slice_new0 (BufferIdentification);
-
-      if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
-        buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
-
-      id->timestamp = buf->omx_buf->nTimeStamp;
-      gst_video_codec_frame_set_user_data (frame, id,
-          (GDestroyNotify) buffer_identification_free);
-    }
+    if (offset == 0 && GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
+      buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
 
     /* TODO: Set flags
      *   - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside
@@ -2663,7 +2506,7 @@ full_buffer:
     gst_video_codec_frame_unref (frame);
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
-            buf->omx_buf->nOffset, buf->omx_buf->nAllocLen));
+            (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
     return GST_FLOW_ERROR;
   }
 
@@ -2678,9 +2521,9 @@ too_large_codec_data:
   {
     gst_video_codec_frame_unref (frame);
     GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL),
-        ("codec_data larger than supported by OpenMAX port (%u > %u)",
-            gst_buffer_get_size (codec_data),
-            self->dec_in_port->port_def.nBufferSize));
+        ("codec_data larger than supported by OpenMAX port "
+            "(%" G_GSIZE_FORMAT " > %u)", gst_buffer_get_size (codec_data),
+            (guint) self->dec_in_port->port_def.nBufferSize));
     return GST_FLOW_ERROR;
   }
 
@@ -2724,11 +2567,11 @@ gst_omx_video_dec_finish (GstVideoDecoder * decoder)
 
   self = GST_OMX_VIDEO_DEC (decoder);
 
-  return gst_omx_video_dec_drain (self, TRUE);
+  return gst_omx_video_dec_drain (self);
 }
 
 static GstFlowReturn
-gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
+gst_omx_video_dec_drain (GstOMXVideoDec * self)
 {
   GstOMXVideoDecClass *klass;
   GstOMXBuffer *buf;
@@ -2745,14 +2588,6 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
   }
   self->started = FALSE;
 
-  /* Don't send EOS buffer twice, this doesn't work */
-  if (self->eos) {
-    GST_DEBUG_OBJECT (self, "Component is EOS already");
-    return GST_FLOW_OK;
-  }
-  if (is_eos)
-    self->eos = TRUE;
-
   if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
     GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
     return GST_FLOW_OK;
@@ -2786,6 +2621,7 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
   if (err != OMX_ErrorNone) {
     GST_ERROR_OBJECT (self, "Failed to drain component: %s (0x%08x)",
         gst_omx_error_to_string (err), err);
+    g_mutex_unlock (&self->drain_lock);
     GST_VIDEO_DECODER_STREAM_LOCK (self);
     return GST_FLOW_ERROR;
   }
@@ -2819,6 +2655,50 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
   GstBufferPool *pool;
   GstStructure *config;
 
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
+  {
+    GstCaps *caps;
+    gint i, n;
+    GstVideoInfo info;
+
+    gst_query_parse_allocation (query, &caps, NULL);
+    if (caps && gst_video_info_from_caps (&info, caps)
+        && info.finfo->format == GST_VIDEO_FORMAT_RGBA) {
+      gboolean found = FALSE;
+      GstCapsFeatures *feature = gst_caps_get_features (caps, 0);
+      /* Prefer an EGLImage allocator if available and we want to use it */
+      n = gst_query_get_n_allocation_params (query);
+      for (i = 0; i < n; i++) {
+        GstAllocator *allocator;
+        GstAllocationParams params;
+
+        gst_query_parse_nth_allocation_param (query, i, &allocator, &params);
+        if (allocator) {
+          if (g_strcmp0 (allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0) {
+            found = TRUE;
+            gst_query_set_nth_allocation_param (query, 0, allocator, &params);
+            while (gst_query_get_n_allocation_params (query) > 1)
+              gst_query_remove_nth_allocation_param (query, 1);
+          }
+
+          gst_object_unref (allocator);
+
+          if (found)
+            break;
+        }
+      }
+
+      /* if try to negotiate with caps feature memory:EGLImage
+       * and if allocator is not of type memory EGLImage then fails */
+      if (feature
+          && gst_caps_features_contains (feature,
+              GST_CAPS_FEATURE_MEMORY_EGL_IMAGE) && !found) {
+        return FALSE;
+      }
+    }
+  }
+#endif
+
   if (!GST_VIDEO_DECODER_CLASS
       (gst_omx_video_dec_parent_class)->decide_allocation (bdec, query))
     return FALSE;
@@ -2837,4 +2717,3 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
 
   return TRUE;
 }
-
index 2a0c9b9..7e047be 100644 (file)
 #ifndef __GST_OMX_VIDEO_DEC_H__
 #define __GST_OMX_VIDEO_DEC_H__
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <gst/video/gstvideodecoder.h>
@@ -68,7 +72,7 @@ struct _GstOMXVideoDec
   /* < protected > */
   GstOMXComponent *dec;
   GstOMXPort *dec_in_port, *dec_out_port;
-
+  
   GstBufferPool *in_port_pool, *out_port_pool;
 
   /* < private > */
@@ -86,14 +90,16 @@ struct _GstOMXVideoDec
   /* TRUE if EOS buffers shouldn't be forwarded */
   gboolean draining;
 
-  /* TRUE if upstream is EOS */
-  gboolean eos;
-
   GstFlowReturn downstream_flow_ret;
 #ifdef USE_TBM
   gint drm_fd;
   tbm_bufmgr hTBMBufMgr;
 #endif
+#ifdef USE_OMX_TARGET_RPI
+  GstOMXComponent *egl_render;
+  GstOMXPort *egl_in_port, *egl_out_port;
+  gboolean eglimage;
+#endif
 };
 
 struct _GstOMXVideoDecClass
old mode 100755 (executable)
new mode 100644 (file)
index 60963c3..941f03d
 #include <gst/video/gstvideometa.h>
 #include <string.h>
 
+#include "gstomxvideo.h"
 #include "gstomxvideoenc.h"
 
-//#define CODEC_ENC_INPUT_DUMP
+#ifdef USE_OMX_TARGET_RPI
+#include <OMX_Broadcom.h>
+#include <OMX_Index.h>
+#endif
+
 GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
 #define GST_CAT_DEFAULT gst_omx_video_enc_debug_category
 
 #define GST_TYPE_OMX_VIDEO_ENC_CONTROL_RATE (gst_omx_video_enc_control_rate_get_type ())
-
-#ifdef CODEC_ENC_INPUT_DUMP
-#include <stdio.h>
-#endif
-
 static GType
 gst_omx_video_enc_control_rate_get_type (void)
 {
@@ -61,18 +61,6 @@ gst_omx_video_enc_control_rate_get_type (void)
   return qtype;
 }
 
-typedef struct _BufferIdentification BufferIdentification;
-struct _BufferIdentification
-{
-  guint64 timestamp;
-};
-
-static void
-buffer_identification_free (BufferIdentification * id)
-{
-  g_slice_free (BufferIdentification, id);
-}
-
 /* prototypes */
 static void gst_omx_video_enc_finalize (GObject * object);
 static void gst_omx_video_enc_set_property (GObject * object, guint prop_id,
@@ -91,8 +79,7 @@ static gboolean gst_omx_video_enc_start (GstVideoEncoder * encoder);
 static gboolean gst_omx_video_enc_stop (GstVideoEncoder * encoder);
 static gboolean gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     GstVideoCodecState * state);
-static gboolean gst_omx_video_enc_reset (GstVideoEncoder * encoder,
-    gboolean hard);
+static gboolean gst_omx_video_enc_flush (GstVideoEncoder * encoder);
 static GstFlowReturn gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
     GstVideoCodecFrame * frame);
 static gboolean gst_omx_video_enc_finish (GstVideoEncoder * encoder);
@@ -101,8 +88,7 @@ static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
 static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
     GstCaps * filter);
 
-static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self,
-    gboolean at_eos);
+static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
 
 static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
     self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
@@ -188,7 +174,7 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
   video_encoder_class->close = GST_DEBUG_FUNCPTR (gst_omx_video_enc_close);
   video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_omx_video_enc_start);
   video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_omx_video_enc_stop);
-  video_encoder_class->reset = GST_DEBUG_FUNCPTR (gst_omx_video_enc_reset);
+  video_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_omx_video_enc_flush);
   video_encoder_class->set_format =
       GST_DEBUG_FUNCPTR (gst_omx_video_enc_set_format);
   video_encoder_class->handle_frame =
@@ -198,6 +184,7 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
       GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
   video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
 
+  klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_sink_template_caps = "video/x-raw, "
       "width = " GST_VIDEO_SIZE_RANGE ", "
       "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE;
@@ -223,36 +210,6 @@ gst_omx_video_enc_init (GstOMXVideoEnc * self)
 #endif
 }
 
-#ifdef CODEC_ENC_INPUT_DUMP
-static inline void
-gst_omx_video_enc_input_dump (MMVideoBuffer *inbuf)
-{
-  char *temp = (char *)inbuf->data[0];
-  int i = 0;
-  char filename[100]={0};
-  FILE *fp = NULL;
-
-  GST_WARNING ("codec enc input dump start. w = %d, h = %d", inbuf->width[0], inbuf->height[0]);
-
-  sprintf(filename, "/opt/usr/media/Videos/enc_input_dump_%d_%d.yuv", inbuf->width[0], inbuf->height[0]);
-  fp = fopen(filename, "ab");
-
-  for (i = 0; i < inbuf->height[0]; i++) {
-      fwrite(temp, inbuf->width[0], 1, fp);
-      temp += inbuf->stride_width[0];
-  }
-
-  temp = (char*)inbuf->data[0] + inbuf->stride_width[0] * inbuf->stride_height[0];
-
-  for(i = 0; i < inbuf->height[1] ; i++) {
-      fwrite(temp, inbuf->width[1], 1, fp);
-      temp += inbuf->stride_width[1];
-  }
-  GST_WARNING ("codec encoder input dumped!!");
-  fclose(fp);
-}
-#endif
-
 static gboolean
 gst_omx_video_enc_open (GstVideoEncoder * encoder)
 {
@@ -292,8 +249,8 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
       in_port_index = 0;
       out_port_index = 1;
     } else {
-      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u", param.nPorts,
-          param.nStartPortNumber);
+      GST_DEBUG_OBJECT (self, "Detected %u ports, starting at %u",
+          (guint) param.nPorts, (guint) param.nStartPortNumber);
       in_port_index = param.nStartPortNumber + 0;
       out_port_index = param.nStartPortNumber + 1;
     }
@@ -596,100 +553,6 @@ gst_omx_video_enc_change_state (GstElement * element, GstStateChange transition)
   return ret;
 }
 
-#define MAX_FRAME_DIST_TICKS  (5 * OMX_TICKS_PER_SECOND)
-#define MAX_FRAME_DIST_FRAMES (100)
-
-static GstVideoCodecFrame *
-_find_nearest_frame (GstOMXVideoEnc * self, GstOMXBuffer * buf)
-{
-  GList *l, *best_l = NULL;
-  GList *finish_frames = NULL;
-  GstVideoCodecFrame *best = NULL;
-  guint64 best_timestamp = 0;
-  guint64 best_diff = G_MAXUINT64;
-  BufferIdentification *best_id = NULL;
-  GList *frames;
-
-  frames = gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self));
-
-  for (l = frames; l; l = l->next) {
-    GstVideoCodecFrame *tmp = l->data;
-    BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-    guint64 timestamp, diff;
-
-    /* This happens for frames that were just added but
-     * which were not passed to the component yet. Ignore
-     * them here!
-     */
-    if (!id)
-      continue;
-
-    timestamp = id->timestamp;
-
-    if (timestamp > buf->omx_buf->nTimeStamp)
-      diff = timestamp - buf->omx_buf->nTimeStamp;
-    else
-      diff = buf->omx_buf->nTimeStamp - timestamp;
-
-    if (best == NULL || diff < best_diff) {
-      best = tmp;
-      best_timestamp = timestamp;
-      best_diff = diff;
-      best_l = l;
-      best_id = id;
-
-      /* For frames without timestamp we simply take the first frame */
-      if ((buf->omx_buf->nTimeStamp == 0 && timestamp == 0) || diff == 0)
-        break;
-    }
-  }
-
-  if (best_id) {
-    for (l = frames; l && l != best_l; l = l->next) {
-      GstVideoCodecFrame *tmp = l->data;
-      BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
-      guint64 diff_ticks, diff_frames;
-
-      /* This happens for frames that were just added but
-       * which were not passed to the component yet. Ignore
-       * them here!
-       */
-      if (!id)
-        continue;
-
-      if (id->timestamp > best_timestamp)
-        break;
-
-      if (id->timestamp == 0 || best_timestamp == 0)
-        diff_ticks = 0;
-      else
-        diff_ticks = best_timestamp - id->timestamp;
-      diff_frames = best->system_frame_number - tmp->system_frame_number;
-
-      if (diff_ticks > MAX_FRAME_DIST_TICKS
-          || diff_frames > MAX_FRAME_DIST_FRAMES) {
-        finish_frames =
-            g_list_prepend (finish_frames, gst_video_codec_frame_ref (tmp));
-      }
-    }
-  }
-
-  if (finish_frames) {
-    g_warning ("Too old frames, bug in encoder -- please file a bug");
-    for (l = finish_frames; l; l = l->next) {
-      gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), l->data);
-    }
-  }
-
-  if (best)
-    gst_video_codec_frame_ref (best);
-
-  g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
-  g_list_free (frames);
-
-  return best;
-}
-
 static GstFlowReturn
 gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
     GstOMXBuffer * buf, GstVideoCodecFrame * frame)
@@ -718,6 +581,7 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
         gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
         self->input_state);
     state->codec_data = codec_data;
+    gst_video_codec_state_unref (state);
     if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
       gst_video_codec_frame_unref (frame);
       return GST_FLOW_NOT_NEGOTIATED;
@@ -887,7 +751,7 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
   g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
 
   /* This prevents a deadlock between the srcpad stream
-   * lock and the videocodec stream lock, if ::reset()
+   * lock and the videocodec stream lock, if ::flush()
    * is called at the wrong time
    */
   if (gst_omx_port_is_flushing (self->enc_out_port)) {
@@ -896,11 +760,12 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
     goto flushing;
   }
 
-  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
-      buf->omx_buf->nTimeStamp);
+  GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %" G_GUINT64_FORMAT,
+      (guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
 
   GST_VIDEO_ENCODER_STREAM_LOCK (self);
-  frame = _find_nearest_frame (self, buf);
+  frame = gst_omx_video_find_nearest_frame (buf,
+      gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self)));
 
   g_assert (klass->handle_output_frame);
   flow_ret = klass->handle_output_frame (self, self->enc_out_port, buf, frame);
@@ -957,6 +822,8 @@ eos:
       flow_ret = GST_FLOW_EOS;
     }
     g_mutex_unlock (&self->drain_lock);
+
+    GST_VIDEO_ENCODER_STREAM_LOCK (self);
     self->downstream_flow_ret = flow_ret;
 
     /* Here we fallback and pause the task for the EOS case */
@@ -975,15 +842,20 @@ flow_error:
       gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
-    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
+      self->started = FALSE;
+    } else if (flow_ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."),
           ("stream stopped, reason %s", gst_flow_get_name (flow_ret)));
 
       gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
+      self->started = FALSE;
+    } else if (flow_ret == GST_FLOW_FLUSHING) {
+      GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
+      gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
+      self->started = FALSE;
     }
-    self->started = FALSE;
     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
     return;
   }
@@ -1028,7 +900,6 @@ gst_omx_video_enc_start (GstVideoEncoder * encoder)
   self = GST_OMX_VIDEO_ENC (encoder);
 
   self->last_upstream_ts = 0;
-  self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
 
   return TRUE;
@@ -1053,7 +924,6 @@ gst_omx_video_enc_stop (GstVideoEncoder * encoder)
 
   self->downstream_flow_ret = GST_FLOW_FLUSHING;
   self->started = FALSE;
-  self->eos = FALSE;
 
   if (self->input_state)
     gst_video_codec_state_unref (self->input_state);
@@ -1069,99 +939,6 @@ gst_omx_video_enc_stop (GstVideoEncoder * encoder)
   return TRUE;
 }
 
-typedef struct
-{
-  GstVideoFormat format;
-  OMX_COLOR_FORMATTYPE type;
-} VideoNegotiationMap;
-
-static void
-video_negotiation_map_free (VideoNegotiationMap * m)
-{
-  g_slice_free (VideoNegotiationMap, m);
-}
-
-static GList *
-gst_omx_video_enc_get_supported_colorformats (GstOMXVideoEnc * self)
-{
-  GstOMXPort *port = self->enc_in_port;
-  GstVideoCodecState *state = self->input_state;
-  OMX_VIDEO_PARAM_PORTFORMATTYPE param;
-  OMX_ERRORTYPE err;
-  GList *negotiation_map = NULL;
-  gint old_index;
-
-  GST_OMX_INIT_STRUCT (&param);
-  param.nPortIndex = port->index;
-  param.nIndex = 0;
-  if (!state || state->info.fps_n == 0)
-    param.xFramerate = 0;
-  else
-    param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
-
-  old_index = -1;
-  do {
-    VideoNegotiationMap *m;
-
-    err =
-        gst_omx_component_get_parameter (self->enc,
-        OMX_IndexParamVideoPortFormat, &param);
-
-    /* FIXME: Workaround for Bellagio that simply always
-     * returns the same value regardless of nIndex and
-     * never returns OMX_ErrorNoMore
-     */
-    if (old_index == param.nIndex)
-      break;
-
-    if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
-      switch (param.eColorFormat) {
-        case OMX_COLOR_FormatYUV420Planar:
-        case OMX_COLOR_FormatYUV420PackedPlanar:
-          m = g_slice_new (VideoNegotiationMap);
-          m->format = GST_VIDEO_FORMAT_I420;
-          m->type = param.eColorFormat;
-          negotiation_map = g_list_append (negotiation_map, m);
-          GST_DEBUG_OBJECT (self, "Component supports I420 (%d) at index %d",
-              param.eColorFormat, param.nIndex);
-          break;
-        case OMX_COLOR_FormatYUV420SemiPlanar:
-          m = g_slice_new (VideoNegotiationMap);
-          m->format = GST_VIDEO_FORMAT_NV12;
-          m->type = param.eColorFormat;
-          negotiation_map = g_list_append (negotiation_map, m);
-          GST_DEBUG_OBJECT (self, "Component supports NV12 (%d) at index %d",
-              param.eColorFormat, param.nIndex);
-          break;
-        case OMX_EXT_COLOR_FormatNV12LPhysicalAddress:
-            m = g_slice_new (VideoNegotiationMap);
-            m->format = GST_VIDEO_FORMAT_SN12;
-            m->type = param.eColorFormat;
-            negotiation_map = g_list_append (negotiation_map, m);
-            GST_DEBUG_OBJECT (self, "Component supports SN12 (%d) at index %d",
-                param.eColorFormat, param.nIndex);
-            break;
-        case OMX_EXT_COLOR_FormatNV12TPhysicalAddress:
-            m = g_slice_new (VideoNegotiationMap);
-            m->format = GST_VIDEO_FORMAT_ST12;
-            m->type = param.eColorFormat;
-            negotiation_map = g_list_append (negotiation_map, m);
-            GST_DEBUG_OBJECT (self, "Component supports ST12 (%d) at index %d",
-                param.eColorFormat, param.nIndex);
-            break;
-        default:
-          GST_DEBUG_OBJECT (self,
-              "Component supports unsupported color format %d at index %d",
-              param.eColorFormat, param.nIndex);
-          break;
-      }
-    }
-    old_index = param.nIndex++;
-  } while (err == OMX_ErrorNone);
-
-  return negotiation_map;
-}
-
 static gboolean
 gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     GstVideoCodecState * state)
@@ -1190,7 +967,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
    */
   if (needs_disable) {
     GST_DEBUG_OBJECT (self, "Need to disable and drain encoder");
-    gst_omx_video_enc_drain (self, FALSE);
+    gst_omx_video_enc_drain (self);
     gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
 
     /* Wait until the srcpad loop is finished,
@@ -1200,31 +977,44 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
     GST_VIDEO_ENCODER_STREAM_LOCK (self);
 
-    if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_buffers_released (self->enc_in_port,
-            5 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_buffers_released (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_enabled (self->enc_in_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
-    if (gst_omx_port_wait_enabled (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
-      return FALSE;
+    if (klass->cdata.hacks & GST_OMX_HACK_NO_COMPONENT_RECONFIGURE) {
+      GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
+      gst_omx_video_enc_stop (GST_VIDEO_ENCODER (self));
+      gst_omx_video_enc_close (GST_VIDEO_ENCODER (self));
+      GST_VIDEO_ENCODER_STREAM_LOCK (self);
+
+      if (!gst_omx_video_enc_open (GST_VIDEO_ENCODER (self)))
+        return FALSE;
+      needs_disable = FALSE;
+    } else {
+      if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (self->enc_in_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_buffers_released (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (self->enc_in_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
 
     GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
   }
 
-  negotiation_map = gst_omx_video_enc_get_supported_colorformats (self);
+  negotiation_map =
+      gst_omx_video_get_supported_colorformats (self->enc_in_port,
+      self->input_state);
   if (!negotiation_map) {
     /* Fallback */
     switch (info->finfo->format) {
@@ -1242,7 +1032,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     }
   } else {
     for (l = negotiation_map; l; l = l->next) {
-      VideoNegotiationMap *m = l->data;
+      GstOMXVideoNegotiationMap *m = l->data;
 
       if (m->format == info->finfo->format) {
         port_def.format.video.eColorFormat = m->type;
@@ -1250,7 +1040,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
       }
     }
     g_list_free_full (negotiation_map,
-        (GDestroyNotify) video_negotiation_map_free);
+        (GDestroyNotify) gst_omx_video_negotiation_map_free);
   }
 
   port_def.format.video.nFrameWidth = info->width;
@@ -1307,6 +1097,44 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
           &port_def) != OMX_ErrorNone)
     return FALSE;
 
+#ifdef USE_OMX_TARGET_RPI
+  /* aspect ratio */
+  {
+    OMX_ERRORTYPE err;
+    OMX_CONFIG_POINTTYPE aspect_ratio_param;
+
+    GST_OMX_INIT_STRUCT (&aspect_ratio_param);
+    aspect_ratio_param.nPortIndex = self->enc_out_port->index;
+
+    err = gst_omx_component_get_parameter (self->enc,
+        OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
+
+    if (err == OMX_ErrorNone) {
+
+      aspect_ratio_param.nX = info->par_n;
+      aspect_ratio_param.nY = info->par_d;
+
+      err =
+          gst_omx_component_set_parameter (self->enc,
+          OMX_IndexParamBrcmPixelAspectRatio, &aspect_ratio_param);
+
+      if (err == OMX_ErrorUnsupportedIndex) {
+        GST_WARNING_OBJECT (self,
+            "Setting aspect ratio parameters not supported by the component");
+      } else if (err == OMX_ErrorUnsupportedSetting) {
+        GST_WARNING_OBJECT (self,
+            "Setting aspect ratio %u %u not supported by the component",
+            aspect_ratio_param.nX, aspect_ratio_param.nY);
+      } else if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (self,
+            "Failed to set aspect ratio: %s (0x%08x)",
+            gst_omx_error_to_string (err), err);
+        return FALSE;
+      }
+    }
+  }
+#endif // USE_OMX_TARGET_RPI
+
   if (klass->set_format) {
     if (!klass->set_format (self, self->enc_in_port, state)) {
       GST_ERROR_OBJECT (self, "Subclass failed to set the new format");
@@ -1319,6 +1147,21 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
           NULL) != OMX_ErrorNone)
     return FALSE;
 
+  if (self->target_bitrate != 0xffffffff) {
+    OMX_VIDEO_PARAM_BITRATETYPE config;
+    OMX_ERRORTYPE err;
+
+    GST_OMX_INIT_STRUCT (&config);
+    config.nPortIndex = self->enc_out_port->index;
+    config.nTargetBitrate = self->target_bitrate;
+    config.eControlRate = self->control_rate;
+    err = gst_omx_component_set_parameter (self->enc,
+        OMX_IndexParamVideoBitrate, &config);
+    if (err != OMX_ErrorNone)
+      GST_ERROR_OBJECT (self, "Failed to set bitrate parameter: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+  }
+
   GST_DEBUG_OBJECT (self, "Enabling component");
   if (needs_disable) {
     if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
@@ -1331,39 +1174,63 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
     if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
       return FALSE;
 #endif
+    if ((klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      if (gst_omx_port_set_enabled (self->enc_out_port, TRUE) != OMX_ErrorNone)
+        return FALSE;
+      if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              5 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+    }
+
     if (gst_omx_port_wait_enabled (self->enc_in_port,
             5 * GST_SECOND) != OMX_ErrorNone)
       return FALSE;
     if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
       return FALSE;
   } else {
-    if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone)
-      return FALSE;
+    if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
+      /* Disable output port */
+      if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_port_wait_enabled (self->enc_out_port,
+              1 * GST_SECOND) != OMX_ErrorNone)
+        return FALSE;
+
+      if (gst_omx_component_set_state (self->enc,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
+
+      /* Need to allocate buffers to reach Idle state */
+
+      if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
+    } else {
+      if (gst_omx_component_set_state (self->enc,
+              OMX_StateIdle) != OMX_ErrorNone)
+        return FALSE;
 
-    /* Need to allocate buffers to reach Idle state */
+      /* Need to allocate buffers to reach Idle state */
 #ifdef USE_TBM
     if(gst_omx_port_tbm_allocate_enc_buffers(self->hTBMBufMgr,self->enc_in_port,
         self->enc_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
         return FALSE;
-#else
-    if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
-      return FALSE;
+#else    
+      if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+        return FALSE;
 #endif
 
-#ifdef EXYNOS_SPECIFIC
-    /*Specific for exynos processors*/
-    /*if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)*/
+#ifdef USE_TBM
     if(gst_omx_port_tbm_allocate_enc_buffers(self->hTBMBufMgr,self->enc_out_port,
-        self->enc_in_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
-#else
-    /* And disable output port */
-    if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone)
-      return FALSE;
-
-    if (gst_omx_port_wait_enabled (self->enc_out_port,
-            1 * GST_SECOND) != OMX_ErrorNone)
+        self->enc_out_port->port_def.format.video.eCompressionFormat) != OMX_ErrorNone)
+#else          
+      if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone)
 #endif
-      return FALSE;
+        return FALSE;
+    }
 
     if (gst_omx_component_get_state (self->enc,
             GST_CLOCK_TIME_NONE) != OMX_StateIdle)
@@ -1403,13 +1270,16 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
 }
 
 static gboolean
-gst_omx_video_enc_reset (GstVideoEncoder * encoder, gboolean hard)
+gst_omx_video_enc_flush (GstVideoEncoder * encoder)
 {
   GstOMXVideoEnc *self;
 
   self = GST_OMX_VIDEO_ENC (encoder);
 
-  GST_DEBUG_OBJECT (self, "Resetting encoder");
+  GST_DEBUG_OBJECT (self, "Flushing encoder");
+
+  if (gst_omx_component_get_state (self->enc, 0) == OMX_StateLoaded)
+    return TRUE;
 
   gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE);
   gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
@@ -1428,7 +1298,6 @@ gst_omx_video_enc_reset (GstVideoEncoder * encoder, gboolean hard)
 
   /* Start the srcpad loop again */
   self->last_upstream_ts = 0;
-  self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
   gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
       (GstTaskFunction) gst_omx_video_enc_loop, encoder, NULL);
@@ -1671,12 +1540,6 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
 
   GST_DEBUG_OBJECT (self, "Handling frame");
 
-  if (self->eos) {
-    GST_WARNING_OBJECT (self, "Got frame after EOS");
-    gst_video_codec_frame_unref (frame);
-    return GST_FLOW_EOS;
-  }
-
   if (self->downstream_flow_ret != GST_FLOW_OK) {
     gst_video_codec_frame_unref (frame);
     return self->downstream_flow_ret;
@@ -1685,7 +1548,6 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
   port = self->enc_in_port;
 
   while (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
-    BufferIdentification *id;
     GstClockTime timestamp, duration;
 
     /* Make sure to release the base class stream lock, otherwise
@@ -1776,6 +1638,18 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
     GST_DEBUG_OBJECT (self, "Handling frame");
 
     if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
+#ifdef USE_OMX_TARGET_RPI
+      OMX_CONFIG_BOOLEANTYPE config;
+
+      GST_OMX_INIT_STRUCT (&config);
+      config.bEnabled = OMX_TRUE;
+
+      GST_DEBUG_OBJECT (self, "Forcing a keyframe (iframe on the RPi)");
+
+      err =
+          gst_omx_component_set_config (self->enc,
+          OMX_IndexConfigBrcmVideoRequestIFrame, &config);
+#else
       OMX_CONFIG_INTRAREFRESHVOPTYPE config;
 
       GST_OMX_INIT_STRUCT (&config);
@@ -1786,6 +1660,7 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
       err =
           gst_omx_component_set_config (self->enc,
           OMX_IndexConfigVideoIntraVOPRefresh, &config);
+#endif
       if (err != OMX_ErrorNone)
         GST_ERROR_OBJECT (self, "Failed to force a keyframe: %s (0x%08x)",
             gst_omx_error_to_string (err), err);
@@ -1808,16 +1683,12 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
     duration = frame->duration;
     if (duration != GST_CLOCK_TIME_NONE) {
       buf->omx_buf->nTickCount =
-          gst_util_uint64_scale (buf->omx_buf->nFilledLen, duration,
-          gst_buffer_get_size (frame->input_buffer));
+          gst_util_uint64_scale (duration, OMX_TICKS_PER_SECOND, GST_SECOND);
       self->last_upstream_ts += duration;
+    } else {
+      buf->omx_buf->nTickCount = 0;
     }
 
-    id = g_slice_new0 (BufferIdentification);
-    id->timestamp = buf->omx_buf->nTimeStamp;
-    gst_video_codec_frame_set_user_data (frame, id,
-        (GDestroyNotify) buffer_identification_free);
-
     self->started = TRUE;
     err = gst_omx_port_release_buffer (port, buf);
     if (err != OMX_ErrorNone)
@@ -1834,7 +1705,7 @@ full_buffer:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Got OpenMAX buffer with no free space (%p, %u/%u)", buf,
-            buf->omx_buf->nOffset, buf->omx_buf->nAllocLen));
+            (guint) buf->omx_buf->nOffset, (guint) buf->omx_buf->nAllocLen));
     gst_video_codec_frame_unref (frame);
     return GST_FLOW_ERROR;
   }
@@ -1892,11 +1763,11 @@ gst_omx_video_enc_finish (GstVideoEncoder * encoder)
 
   self = GST_OMX_VIDEO_ENC (encoder);
 
-  return gst_omx_video_enc_drain (self, TRUE);
+  return gst_omx_video_enc_drain (self);
 }
 
 static GstFlowReturn
-gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos)
+gst_omx_video_enc_drain (GstOMXVideoEnc * self)
 {
   GstOMXVideoEncClass *klass;
   GstOMXBuffer *buf;
@@ -1913,14 +1784,6 @@ gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos)
   }
   self->started = FALSE;
 
-  /* Don't send EOS buffer twice, this doesn't work */
-  if (self->eos) {
-    GST_DEBUG_OBJECT (self, "Component is EOS already");
-    return GST_FLOW_OK;
-  }
-  if (at_eos)
-    self->eos = TRUE;
-
   if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
     GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
     return GST_FLOW_OK;
@@ -1983,22 +1846,18 @@ static GstCaps *
 gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
 {
   GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
-  GList *negotiation_map = NULL, *l;
+  GList *negotiation_map = NULL;
   GstCaps *comp_supported_caps;
 
   if (!self->enc)
     return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
 
-  negotiation_map = gst_omx_video_enc_get_supported_colorformats (self);
-  comp_supported_caps = gst_caps_new_empty ();
-  for (l = negotiation_map; l; l = l->next) {
-    VideoNegotiationMap *map = l->data;
-
-    gst_caps_append_structure (comp_supported_caps,
-        gst_structure_new ("video/x-raw",
-            "format", G_TYPE_STRING,
-            gst_video_format_to_string (map->format), NULL));
-  }
+  negotiation_map =
+      gst_omx_video_get_supported_colorformats (self->enc_in_port,
+      self->input_state);
+  comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
+  g_list_free_full (negotiation_map,
+      (GDestroyNotify) gst_omx_video_negotiation_map_free);
 
   if (!gst_caps_is_empty (comp_supported_caps)) {
     GstCaps *ret =
old mode 100755 (executable)
new mode 100644 (file)
index 9ac7f17..8266d84
@@ -68,9 +68,6 @@ struct _GstOMXVideoEnc
   /* TRUE if EOS buffers shouldn't be forwarded */
   gboolean draining;
 
-  /* TRUE if upstream is EOS */
-  gboolean eos;
-
   /* properties */
   guint32 control_rate;
   guint32 target_bitrate;
index 4c4d40c..f99f4ce 100644 (file)
@@ -27,7 +27,7 @@
 G_BEGIN_DECLS
 
 #define GST_TYPE_OMX_VP8_DEC \
-  (gst_omx_VP8_dec_get_type())
+  (gst_omx_vp8_dec_get_type())
 #define GST_OMX_VP8_DEC(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_VP8_DEC,GstOMXVP8Dec))
 #define GST_OMX_VP8_DEC_CLASS(klass) \
diff --git a/packaging/common.tar.bz2 b/packaging/common.tar.bz2
deleted file mode 100644 (file)
index a18ecc8..0000000
Binary files a/packaging/common.tar.bz2 and /dev/null differ
diff --git a/packaging/gitmodules.sh b/packaging/gitmodules.sh
deleted file mode 100755 (executable)
index 1de5a67..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#! /bin/sh
-# @author: Philippe Coval <mailto:philippe.coval@eurogiciel.com>
-# @description: manage git submodules with git-build-package-rpm
-
-set -x
-set -e
-
-cat .gitmodules || return 1
-
-
-git submodule status | awk '{ print $2 }' | while read dir  ; do
-    name=$(basename "$dir" )
-    echo "name="
-    echo "dir=$dir"
-    git submodule init
-    git submodule update
-
-    tar cjvf "./packaging/${name}.tar.bz2" "${dir}"
-
-    cat<<EOF
-# Please add "SourceN: $name.tar.bz2" and "%setup -q -T -D -a N" to "packaging/*.spec"
-EOF
-
-done
-
old mode 100755 (executable)
new mode 100644 (file)
index 33218c8..96d930f
@@ -1,12 +1,10 @@
 Name:           gst-omx
 Summary:        GStreamer plug-in that allows communication with OpenMAX IL components
-Version:        1.0.0
-Release:        5
+Version:        1.2.0
+Release:        1
 License:        LGPL-2.1+
 Group:          Multimedia/Framework
-Source0:        %{name}-%{version}.tar.gz
-Source100:      common.tar.bz2
-Source1001:     gst-omx.manifest
+Source:        %{name}-%{version}.tar.gz
 BuildRequires:  which
 BuildRequires:  pkgconfig(gstreamer-1.0)
 BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
@@ -18,19 +16,19 @@ gst-openmax is a GStreamer plug-in that allows communication with OpenMAX IL com
 Multiple OpenMAX IL implementations can be used.
 
 %prep
-%setup -q
-%setup -q -T -D -a 100
-cp %{SOURCE1001} .
+%setup -q -n %{name}-%{version} 
 
 %build
 ./autogen.sh --noconfigure
 
-%ifarch %{arm}
 export CFLAGS+=" -DEXYNOS_SPECIFIC"
 export CFLAGS+=" -DUSE_TBM"
-%endif
 
+%ifarch aarch64
+%configure --disable-static --prefix=/usr --with-omx-target=exynos64
+%else
 %configure --disable-static --prefix=/usr --with-omx-target=exynos
+%endif
 
 make %{?jobs:-j%jobs}
 
@@ -48,3 +46,4 @@ cp COPYING %{buildroot}/usr/share/license/%{name}
 /etc/xdg/gstomx.conf
 /usr/share/license/%{name}
 
+