Adding gst-omx version 1.2.0 base code.
Signed-off-by: Barun Kr. Singh <barun.singh@samsung.com>
Change-Id: I61a89aff3b294b993fc4c5540a492a51b886bf76
+++ /dev/null
-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
+=== 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>
+++ /dev/null
-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.
-
-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
-This is gst-omx 1.0.0
+This is gst-omx 1.2.0
-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.
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 ====
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
+++ /dev/null
-Subproject commit 04c7a1ec1b9ced0b4359b3bbb2d8dc87bc7642c8
--- /dev/null
+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
--- /dev/null
+#!/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>.*$//'
+
--- /dev/null
+# 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
+}
--- /dev/null
+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
--- /dev/null
+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.
--- /dev/null
+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
+])
--- /dev/null
+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])
+ ])
+])
--- /dev/null
+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])
+])
+
--- /dev/null
+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
+])
--- /dev/null
+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)
+])
--- /dev/null
+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])
+])
+
--- /dev/null
+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
+])
--- /dev/null
+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])
+])
--- /dev/null
+## ------------------------
+## 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
+])
--- /dev/null
+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)
+])
--- /dev/null
+##### 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"
+])
+])
--- /dev/null
+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, µ) != 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
+])
--- /dev/null
+# 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])
+
--- /dev/null
+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
+])
--- /dev/null
+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
+ ])
+])
--- /dev/null
+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
+])
--- /dev/null
+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
+])
--- /dev/null
+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])
+])
--- /dev/null
+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)
+])
--- /dev/null
+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
+])
--- /dev/null
+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)
+])
--- /dev/null
+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
+])
+
--- /dev/null
+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])
+])
--- /dev/null
+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])
+])
--- /dev/null
+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)
+])
--- /dev/null
+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"
+])
--- /dev/null
+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
+])
--- /dev/null
+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
+])
--- /dev/null
+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
--- /dev/null
+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)
+])
--- /dev/null
+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)
+])
--- /dev/null
+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")
+])
--- /dev/null
+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
+])
--- /dev/null
+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])
+])
--- /dev/null
+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"])
+])
--- /dev/null
+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])
+])
--- /dev/null
+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"
+])
+
--- /dev/null
+# 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
-SUBDIRS = bellagio rpi exynos
+SUBDIRS = bellagio rpi exynos exynos64
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
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
-[omxmpeg2videodec]
+[omxdec_mpeg2]
type-name=GstOMXMPEG2VideoDec
core-name=/usr/lib/libExynosOMX_Core.so
component-name=OMX.Exynos.MPEG2.Decoder
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
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
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
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
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
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
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
in-port-index=0
out-port-index=1
hacks=no-component-role
+
--- /dev/null
+EXTRA_DIST = gstomx.conf
+
+if USE_OMX_TARGET_EXYNOS64
+configdir = $(sysconfdir)/xdg
+config_DATA = gstomx.conf
+endif
--- /dev/null
+[omxdec_mpeg2]
+type-name=GstOMXMPEG2VideoDec
+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
+
+[omxdec_mpeg4]
+type-name=GstOMXMPEG4VideoDec
+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
+
+[omxdec_h263]
+type-name=GstOMXH263Dec
+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
+
+[omxdec_h264]
+type-name=GstOMXH264Dec
+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
+
+[omxdec_vc1]
+type-name=GstOMXWMVDec
+core-name=/usr/lib64/libExynosOMX_Core.so
+component-name=OMX.Exynos.WMV.Decoder
+rank=256
+in-port-index=0
+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]
+
+[omxenc_h264]
+type-name=GstOMXH264Enc
+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
+
+[omxenc_mpeg4]
+type-name=GstOMXMPEG4VideoEnc
+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
+
+[omxenc_h263]
+type-name=GstOMXH263Enc
+core-name=/usr/lib64/libExynosOMX_Core.so
+component-name=OMX.Exynos.H263.Encoder
+rank=258
+in-port-index=0
+out-port-index=1
+hacks=no-component-role
+++ /dev/null
-EXTRA_DIST = gstomx.conf
-
-if USE_OMX_TARGET_ODROID
-configdir = $(sysconfdir)/xdg
-config_DATA = gstomx.conf
-endif
+++ /dev/null
-[omxmpeg2videodec]
-type-name=GstOMXMPEG2VideoDec
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.MPEG2.Decoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxmpeg4videodec]
-type-name=GstOMXMPEG4VideoDec
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.MPEG4.Decoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxh263dec]
-type-name=GstOMXH263Dec
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.H263.Decoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxh264dec]
-type-name=GstOMXH264Dec
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.AVC.Decoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxvc1dec]
-type-name=GstOMXWMVDec
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.WMV.Decoder
-rank=256
-in-port-index=0
-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]
-type-name=GstOMXH264Enc
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.AVC.Encoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxmpeg4enc]
-type-name=GstOMXMPEG4VideoEnc
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.MPEG4.Encoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
-
-[omxh263enc]
-type-name=GstOMXH263Enc
-core-name=/usr/lib/libExynosOMX_Core.so
-component-name=OMX.Exynos.H263.Encoder
-rank=258
-in-port-index=0
-out-port-index=1
-hacks=no-component-role
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
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
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
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
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
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
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
[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
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}
+
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)
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 ****
dnl *** check for arguments to configure ***
+AG_GST_ARG_DISABLE_FATAL_WARNINGS
+
AG_GST_ARG_DEBUG
AG_GST_ARG_PROFILING
AG_GST_ARG_VALGRIND
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)
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`"
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],
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
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])
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])
;;
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)]),
["${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
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)"
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 ***
config/bellagio/Makefile
config/rpi/Makefile
config/exynos/Makefile
+config/exynos64/Makefile
+examples/Makefile
+examples/egl/Makefile
)
AC_OUTPUT
--- /dev/null
+if HAVE_GST_GL
+SUBDIRS = egl
+endif
+
+DIST_SUBDIRS = egl
--- /dev/null
+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)
+
--- /dev/null
+/*
+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,
+};
+
--- /dev/null
+/*
+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;
+}
</GitRepository>
</repository>
+ <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>
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
libgstomx_la_SOURCES = \
gstomx.c \
+ gstomxbufferpool.c \
+ gstomxvideo.c \
gstomxvideodec.c \
gstomxvideoenc.c \
+ gstomxaudiodec.c \
gstomxaudioenc.c \
gstomxmjpegdec.c \
gstomxmpeg4videodec.c \
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 \
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
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@ \
$(GST_BASE_LIBS) \
$(GST_LIBS) \
$(TBM_LIBS) \
+ $(GMODULE_NO_EXPORT_LIBS) \
$(MM_COMMON_LIBS)
-
libgstomx_la_LDFLAGS = \
$(GST_PLUGIN_LDFLAGS) \
$(TBM_LDFLAGS) \
#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
G_LOCK_DEFINE_STATIC (core_handles);
static GHashTable *core_handles;
-
-
GstOMXCore *
gst_omx_core_acquire (const gchar * filename)
{
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 */
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;
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;
} 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)
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)
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;
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);
GstOMXMessage *msg;
/* Yes, this really happens... */
- if (nData2 == OMX_ErrorNone)
+ if (nData1 == OMX_ErrorNone)
break;
msg = g_slice_new (GstOMXMessage);
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;
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;
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);
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);
};
}
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);
}
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);
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);
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 */
(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;
* 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);
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;
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 "
port->flushing = flush;
if (flush) {
- gint64 wait_until = -1;
gboolean signalled;
OMX_ERRORTYPE last_error;
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
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);
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);
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);
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;
}
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 */
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;
}
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,
GstOMXComponent *comp;
OMX_ERRORTYPE err = OMX_ErrorNone;
OMX_ERRORTYPE last_error;
- gint64 wait_until = -1;
gboolean signalled;
comp = port->comp;
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 */
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;
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;
}
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
* 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) {
{
GstOMXComponent *comp;
OMX_ERRORTYPE err = OMX_ErrorNone;
- gint64 wait_until = -1;
gboolean signalled;
OMX_ERRORTYPE last_error;
gboolean enabled;
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 */
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;
err = last_error;
} else {
if (enabled) {
- port->flushing = FALSE;
/* Reset EOS flag */
port->eos = FALSE;
}
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;
}
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
};
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)},
};
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:
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";
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;
}
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;
}
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++;
/* 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,
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 */
#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
*/
#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;
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;
guint32 in_port_index, out_port_index;
guint64 hacks;
+
+ GstOmxComponentType type;
};
GKeyFile * gst_omx_get_configuration (void);
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);
#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))
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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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)
+{
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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 (¶m);
+
+ err =
+ gst_omx_component_get_parameter (self->dec, OMX_IndexParamAudioInit,
+ ¶m);
+ 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;
+}
--- /dev/null
+/*
+ * 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__ */
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);
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);
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) " ], "
}
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;
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;
}
}
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))
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;
break;
}
- if (ret == GST_STATE_CHANGE_FAILURE)
- return ret;
-
ret =
GST_ELEMENT_CLASS (gst_omx_audio_enc_parent_class)->change_state (element,
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;
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()
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 */
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;
}
self = GST_OMX_AUDIO_ENC (encoder);
self->last_upstream_ts = 0;
- self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
self->downstream_flow_ret = GST_FLOW_FLUSHING;
self->started = FALSE;
- self->eos = FALSE;
g_mutex_lock (&self->drain_lock);
self->draining = FALSE;
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");
}
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)
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);
/* 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);
}
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");
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;
}
{
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:
}
}
-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)
{
}
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;
GstClockTime last_upstream_ts;
- /* TRUE if upstream is EOS */
- gboolean eos;
-
/* Draining state */
GMutex drain_lock;
GCond drain_cond;
--- /dev/null
+/*
+ * 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 (¶m);
+ param.nPortIndex = self->in_port->index;
+ param.bMute = (mute ? OMX_TRUE : OMX_FALSE);
+ err = gst_omx_component_set_config (self->comp,
+ OMX_IndexConfigAudioMute, ¶m);
+ 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 (¶m);
+ 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, ¶m);
+ 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 (¶m);
+
+ err =
+ gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+ ¶m);
+ 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 (¶m);
+
+ err =
+ gst_omx_component_get_parameter (self->comp, OMX_IndexParamAudioInit,
+ ¶m);
+ 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 (¶m);
+ 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, ¶m.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,
+ ¶m);
+ 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 (¶m);
+ strcpy ((char *) param.sName, klass->destination);
+ err = gst_omx_component_set_config (self->comp,
+ OMX_IndexConfigBrcmAudioDestination, ¶m);
+ 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 (¶m);
+ param.nPortIndex = self->in_port->index;
+ param.nU32 = 0;
+ err = gst_omx_component_get_config (self->comp,
+ OMX_IndexConfigAudioRenderingLatency, ¶m);
+ 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);
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
"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;
}
break;
default:
g_assert_not_reached ();
- break;
+ return NULL;
}
switch (param.eLevel) {
break;
default:
g_assert_not_reached ();
- break;
+ return NULL;
}
gst_caps_set_simple (caps,
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;
}
#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
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 =
gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.avc");
}
+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
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;
"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;
}
break;
default:
g_assert_not_reached ();
- break;
+ return NULL;
}
switch (param.eLevel) {
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);
}
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
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);
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);
}
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
--- /dev/null
+/*
+ * 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)
+{
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
+
"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;
}
break;
default:
g_assert_not_reached ();
- break;
+ return NULL;
}
switch (param.eLevel) {
break;
default:
g_assert_not_reached ();
- break;
+ return NULL;
}
gst_caps_set_simple (caps,
--- /dev/null
+/*
+ * 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 (¶m);
+ 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, ¶m);
+
+ /* 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;
+}
--- /dev/null
+/*
+ * 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__ */
#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);
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);
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 =
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;
}
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);
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;
}
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 (¶m);
+
+ err =
+ gst_omx_component_get_parameter (self->egl_render,
+ OMX_IndexParamVideoInit, ¶m);
+ 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;
}
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) {
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");
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;
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,
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;
}
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);
#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
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;
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) {
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);
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
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, ¶ms) != 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) {
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);
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) {
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;
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;
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 */
* 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
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
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 =
}
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;
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, ¶ms);
+ &outbuf, ¶ms);
if (flow_ret != GST_FLOW_OK) {
flow_ret =
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
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;
{
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);
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 */
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)));
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;
}
self = GST_OMX_VIDEO_DEC (decoder);
self->last_upstream_ts = 0;
- self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
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);
+#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;
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);
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 (¶m);
- 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, ¶m);
-
- /* 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)
{
GstVideoFormat format;
GstStructure *s;
const gchar *format_str;
- gchar *format_tmp;
- int i;
#ifdef USE_TBM
EnableGemBuffersParams gemBuffers;
#endif
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;
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;
}
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;
/* 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,
gst_omx_error_to_string (err), err);
}
#endif
+ gst_caps_unref (intersection);
return (err == OMX_ErrorNone);
}
}
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);
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)
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);
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;
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;
}
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;
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
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;
}
{
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;
}
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;
}
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;
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;
}
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, ¶ms);
+ 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, ¶ms);
+ 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;
return TRUE;
}
-
#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>
/* < protected > */
GstOMXComponent *dec;
GstOMXPort *dec_in_port, *dec_out_port;
-
+
GstBufferPool *in_port_pool, *out_port_pool;
/* < private > */
/* 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
#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)
{
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,
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);
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);
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 =
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;
#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)
{
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;
}
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)
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;
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)) {
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);
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 */
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;
}
self = GST_OMX_VIDEO_ENC (encoder);
self->last_upstream_ts = 0;
- self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
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);
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 (¶m);
- 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, ¶m);
-
- /* 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)
*/
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,
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) {
}
} 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;
}
}
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;
&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");
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)
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)
}
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);
/* 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);
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;
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
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);
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);
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)
{
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;
}
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;
}
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;
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 =
/* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining;
- /* TRUE if upstream is EOS */
- gboolean eos;
-
/* properties */
guint32 control_rate;
guint32 target_bitrate;
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) \
+++ /dev/null
-#! /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
-
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)
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}
/etc/xdg/gstomx.conf
/usr/share/license/%{name}
+