diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2013-07-14 12:56:33 +0200 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2013-07-14 12:57:09 +0200 |
commit | edfcc936c71f04396d751d6a1e26ed3f47d2cd76 (patch) | |
tree | 34339688099ea368bc1362b84b1b3610dcca6e3c | |
parent | 921e9840af479d38d6189e800de97b88ecd3c822 (diff) |
New upstream development snapshot.debian/1.1.2-1
-rw-r--r-- | debian/changelog | 5 | ||||
-rw-r--r-- | debian/control | 4 | ||||
-rw-r--r-- | debian/patches/03_git-2013-04-26.patch | 8465 | ||||
-rw-r--r-- | debian/patches/04_gstreamer-1.0.patch | 18 | ||||
-rw-r--r-- | debian/patches/series | 2 |
5 files changed, 6 insertions, 8488 deletions
diff --git a/debian/changelog b/debian/changelog index 6886ea5..a38066c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,12 @@ -gst-libav1.0 (1.0.7-3) UNRELEASED; urgency=low +gst-libav1.0 (1.1.2-1) experimental; urgency=low * debian/control, debian/README.Debian, debian/watch: + Replace all occurences of ffmpeg with libav (Closes: #707216). + * New upstream development snapshot: + + debian/control: + - Build depend on GStreamer and gst-plugins-base >= 1.1.2. -- Sebastian Dröge <slomo@debian.org> Wed, 08 May 2013 11:55:06 +0200 diff --git a/debian/control b/debian/control index 7d6f713..0003f95 100644 --- a/debian/control +++ b/debian/control @@ -18,8 +18,8 @@ Build-Depends: debhelper (>= 9), zlib1g-dev, libglib2.0-dev (>= 2.32), pkg-config (>= 0.11.0), - libgstreamer1.0-dev (>= 1.0.0), - libgstreamer-plugins-base1.0-dev (>= 1.0.0), + libgstreamer1.0-dev (>= 1.1.2), + libgstreamer-plugins-base1.0-dev (>= 1.1.2), liborc-0.4-dev (>= 1:0.4.16), libavcodec-dev (>= 6:9~beta2), libavformat-dev (>= 6:9~beta2), diff --git a/debian/patches/03_git-2013-04-26.patch b/debian/patches/03_git-2013-04-26.patch deleted file mode 100644 index d1c6f1a..0000000 --- a/debian/patches/03_git-2013-04-26.patch +++ /dev/null @@ -1,8465 +0,0 @@ -diff --git a/ext/Makefile.am b/ext/Makefile.am -index bbdb9f0..16718f6 100644 ---- a/ext/Makefile.am -+++ b/ext/Makefile.am -@@ -1 +1,4 @@ --SUBDIRS = libav libswscale -+# disable/skip avvideoscale until someone makes it work -+SUBDIRS = libav -+ -+DIST_SUBDIRS = libav libswscale -diff --git a/ext/libav/Makefile.am b/ext/libav/Makefile.am -index a1e51f4..24d0eb9 100644 ---- a/ext/libav/Makefile.am -+++ b/ext/libav/Makefile.am -@@ -10,9 +10,9 @@ libgstlibav_la_SOURCES = gstav.c \ - gstavprotocol.c \ - gstavcodecmap.c \ - gstavutils.c \ -- gstavenc.c \ -+ gstavaudenc.c \ - gstavvidenc.c \ -- gstavdec.c \ -+ gstavauddec.c \ - gstavviddec.c \ - gstavcfg.c \ - gstavdemux.c \ -@@ -40,7 +40,9 @@ noinst_HEADERS = \ - gstav.h \ - gstavcodecmap.h \ - gstavutils.h \ -- gstavenc.h \ -+ gstavauddec.h \ -+ gstavviddec.h \ -+ gstavaudenc.h \ - gstavvidenc.h \ - gstavcfg.h \ -- gstavpipe.h -+ gstavprotocol.h -diff --git a/ext/libav/gstav.c b/ext/libav/gstav.c -index 8c88a13..7884a51 100644 ---- a/ext/libav/gstav.c -+++ b/ext/libav/gstav.c -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - /* First, include the header file for the plugin, to bring in the -@@ -45,7 +45,7 @@ gst_ffmpeg_avcodec_open (AVCodecContext * avctx, AVCodec * codec) - int ret; - - g_static_mutex_lock (&gst_avcodec_mutex); -- ret = avcodec_open (avctx, codec); -+ ret = avcodec_open2 (avctx, codec, NULL); - g_static_mutex_unlock (&gst_avcodec_mutex); - - return ret; -@@ -69,7 +69,7 @@ gst_ffmpeg_av_find_stream_info (AVFormatContext * ic) - int ret; - - g_static_mutex_lock (&gst_avcodec_mutex); -- ret = av_find_stream_info (ic); -+ ret = avformat_find_stream_info (ic, NULL); - g_static_mutex_unlock (&gst_avcodec_mutex); - - return ret; -@@ -83,9 +83,6 @@ gst_ffmpeg_log_callback (void *ptr, int level, const char *fmt, va_list vl) - gint len = strlen (fmt); - gchar *fmt2 = NULL; - -- if (_shut_up_I_am_probing) -- return; -- - switch (level) { - case AV_LOG_QUIET: - gst_level = GST_LEVEL_NONE; -@@ -117,10 +114,6 @@ gst_ffmpeg_log_callback (void *ptr, int level, const char *fmt, va_list vl) - } - #endif - --#ifndef GST_DISABLE_GST_DEBUG --gboolean _shut_up_I_am_probing = FALSE; --#endif -- - static gboolean - plugin_init (GstPlugin * plugin) - { -@@ -145,13 +138,9 @@ plugin_init (GstPlugin * plugin) - gst_ffmpegscale_register (plugin); - #endif - #if 0 -- gst_ffmpegcsp_register (plugin); - gst_ffmpegaudioresample_register (plugin); - #endif - -- av_register_protocol2 (&gstreamer_protocol, sizeof (URLProtocol)); -- av_register_protocol2 (&gstpipe_protocol, sizeof (URLProtocol)); -- - /* Now we can return the pointer to the newly created Plugin object. */ - return TRUE; - } -diff --git a/ext/libav/gstav.h b/ext/libav/gstav.h -index 5cd69a5..82e2972 100644 ---- a/ext/libav/gstav.h -+++ b/ext/libav/gstav.h -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - /* First, include the header file for the plugin, to bring in the -@@ -36,21 +36,16 @@ GST_DEBUG_CATEGORY_EXTERN (ffmpeg_debug); - - G_BEGIN_DECLS - --#ifndef GST_DISABLE_GST_DEBUG --extern gboolean _shut_up_I_am_probing; --#endif -- - extern gboolean gst_ffmpegdemux_register (GstPlugin * plugin); - extern gboolean gst_ffmpegauddec_register (GstPlugin * plugin); - extern gboolean gst_ffmpegviddec_register (GstPlugin * plugin); - extern gboolean gst_ffmpegaudenc_register (GstPlugin * plugin); - extern gboolean gst_ffmpegvidenc_register (GstPlugin * plugin); - extern gboolean gst_ffmpegmux_register (GstPlugin * plugin); --extern gboolean gst_ffmpegcsp_register (GstPlugin * plugin); - #if 0 - extern gboolean gst_ffmpegscale_register (GstPlugin * plugin); --#endif - extern gboolean gst_ffmpegaudioresample_register (GstPlugin * plugin); -+#endif - extern gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin); - - int gst_ffmpeg_avcodec_open (AVCodecContext *avctx, AVCodec *codec); -@@ -59,9 +54,6 @@ int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic); - - G_END_DECLS - --extern URLProtocol gstreamer_protocol; --extern URLProtocol gstpipe_protocol; -- - /* use GST_FFMPEG URL_STREAMHEADER with URL_WRONLY if the first - * buffer should be used as streamheader property on the pad's caps. */ - #define GST_FFMPEG_URL_STREAMHEADER 16 -diff --git a/ext/libav/gstavauddec.c b/ext/libav/gstavauddec.c -new file mode 100644 -index 0000000..e6646af ---- /dev/null -+++ b/ext/libav/gstavauddec.c -@@ -0,0 +1,893 @@ -+/* GStreamer -+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -+ * Copyright (C) <2012> 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 Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include <assert.h> -+#include <string.h> -+ -+#include <libavcodec/avcodec.h> -+ -+#include <gst/gst.h> -+ -+#include "gstav.h" -+#include "gstavcodecmap.h" -+#include "gstavutils.h" -+#include "gstavauddec.h" -+ -+GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); -+ -+/* A number of function prototypes are given so we can refer to them later. */ -+static void gst_ffmpegauddec_base_init (GstFFMpegAudDecClass * klass); -+static void gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass); -+static void gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec); -+static void gst_ffmpegauddec_finalize (GObject * object); -+ -+static gboolean gst_ffmpegauddec_stop (GstAudioDecoder * decoder); -+static void gst_ffmpegauddec_flush (GstAudioDecoder * decoder, gboolean hard); -+static gboolean gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, -+ GstCaps * caps); -+static GstFlowReturn gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, -+ GstBuffer * inbuf); -+ -+static gboolean gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, -+ gboolean force); -+ -+static void gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec); -+ -+#define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("avdec-params") -+ -+static GstElementClass *parent_class = NULL; -+ -+static void -+gst_ffmpegauddec_base_init (GstFFMpegAudDecClass * klass) -+{ -+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -+ GstPadTemplate *sinktempl, *srctempl; -+ GstCaps *sinkcaps, *srccaps; -+ AVCodec *in_plugin; -+ gchar *longname, *description; -+ -+ in_plugin = -+ (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), -+ GST_FFDEC_PARAMS_QDATA); -+ g_assert (in_plugin != NULL); -+ -+ /* construct the element details struct */ -+ longname = g_strdup_printf ("libav %s decoder", in_plugin->long_name); -+ description = g_strdup_printf ("libav %s decoder", in_plugin->name); -+ gst_element_class_set_metadata (element_class, longname, -+ "Codec/Decoder/Audio", description, -+ "Wim Taymans <wim.taymans@gmail.com>, " -+ "Ronald Bultje <rbultje@ronald.bitfreak.net>, " -+ "Edward Hervey <bilboed@bilboed.com>"); -+ g_free (longname); -+ g_free (description); -+ -+ /* get the caps */ -+ sinkcaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, FALSE); -+ if (!sinkcaps) { -+ GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name); -+ sinkcaps = gst_caps_from_string ("unknown/unknown"); -+ } -+ srccaps = gst_ffmpeg_codectype_to_audio_caps (NULL, -+ in_plugin->id, FALSE, in_plugin); -+ if (!srccaps) { -+ GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name); -+ srccaps = gst_caps_from_string ("audio/x-raw"); -+ } -+ -+ /* pad templates */ -+ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -+ GST_PAD_ALWAYS, sinkcaps); -+ srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps); -+ -+ gst_element_class_add_pad_template (element_class, srctempl); -+ gst_element_class_add_pad_template (element_class, sinktempl); -+ -+ klass->in_plugin = in_plugin; -+ klass->srctempl = srctempl; -+ klass->sinktempl = sinktempl; -+} -+ -+static void -+gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass) -+{ -+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -+ GstAudioDecoderClass *gstaudiodecoder_class = GST_AUDIO_DECODER_CLASS (klass); -+ -+ parent_class = g_type_class_peek_parent (klass); -+ -+ gobject_class->finalize = gst_ffmpegauddec_finalize; -+ -+ gstaudiodecoder_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegauddec_stop); -+ gstaudiodecoder_class->set_format = -+ GST_DEBUG_FUNCPTR (gst_ffmpegauddec_set_format); -+ gstaudiodecoder_class->handle_frame = -+ GST_DEBUG_FUNCPTR (gst_ffmpegauddec_handle_frame); -+ gstaudiodecoder_class->flush = GST_DEBUG_FUNCPTR (gst_ffmpegauddec_flush); -+} -+ -+static void -+gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec) -+{ -+ GstFFMpegAudDecClass *klass = -+ (GstFFMpegAudDecClass *) G_OBJECT_GET_CLASS (ffmpegdec); -+ -+ /* some ffmpeg data */ -+ ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin); -+ ffmpegdec->opened = FALSE; -+ -+ gst_audio_decoder_set_drainable (GST_AUDIO_DECODER (ffmpegdec), TRUE); -+ gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (ffmpegdec), TRUE); -+} -+ -+static void -+gst_ffmpegauddec_finalize (GObject * object) -+{ -+ GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) object; -+ -+ if (ffmpegdec->context != NULL) -+ av_free (ffmpegdec->context); -+ ffmpegdec->context = NULL; -+ -+ G_OBJECT_CLASS (parent_class)->finalize (object); -+} -+ -+/* With LOCK */ -+static void -+gst_ffmpegauddec_close (GstFFMpegAudDec * ffmpegdec) -+{ -+ GST_LOG_OBJECT (ffmpegdec, "closing libav codec"); -+ -+ gst_caps_replace (&ffmpegdec->last_caps, NULL); -+ gst_buffer_replace (&ffmpegdec->outbuf, NULL); -+ -+ gst_ffmpeg_avcodec_close (ffmpegdec->context); -+ ffmpegdec->opened = FALSE; -+ -+ if (ffmpegdec->context->extradata) { -+ av_free (ffmpegdec->context->extradata); -+ ffmpegdec->context->extradata = NULL; -+ } -+} -+ -+static gboolean -+gst_ffmpegauddec_stop (GstAudioDecoder * decoder) -+{ -+ GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder; -+ -+ GST_OBJECT_LOCK (ffmpegdec); -+ gst_ffmpegauddec_close (ffmpegdec); -+ GST_OBJECT_UNLOCK (ffmpegdec); -+ gst_audio_info_init (&ffmpegdec->info); -+ gst_caps_replace (&ffmpegdec->last_caps, NULL); -+ -+ return TRUE; -+} -+ -+/* with LOCK */ -+static gboolean -+gst_ffmpegauddec_open (GstFFMpegAudDec * ffmpegdec) -+{ -+ GstFFMpegAudDecClass *oclass; -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0) -+ goto could_not_open; -+ -+ ffmpegdec->opened = TRUE; -+ -+ GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d", -+ oclass->in_plugin->name, oclass->in_plugin->id); -+ -+ gst_audio_info_init (&ffmpegdec->info); -+ -+ return TRUE; -+ -+ /* ERRORS */ -+could_not_open: -+ { -+ gst_ffmpegauddec_close (ffmpegdec); -+ GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec", -+ oclass->in_plugin->name); -+ return FALSE; -+ } -+} -+ -+typedef struct -+{ -+ GstBuffer *buffer; -+ GstMapInfo map; -+} BufferInfo; -+ -+/* called when ffmpeg wants us to allocate a buffer to write the decoded frame -+ * into. We try to give it memory from our pool */ -+static int -+gst_ffmpegauddec_get_buffer (AVCodecContext * context, AVFrame * frame) -+{ -+ GstFFMpegAudDec *ffmpegdec; -+ GstAudioInfo *info; -+ BufferInfo *buffer_info; -+ -+ ffmpegdec = (GstFFMpegAudDec *) context->opaque; -+ if (G_UNLIKELY (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE))) -+ goto negotiate_failed; -+ -+ /* Always use the default allocator for planar audio formats because -+ * we will have to copy and deinterleave later anyway */ -+ if (av_sample_fmt_is_planar (ffmpegdec->context->sample_fmt)) -+ goto fallback; -+ -+ info = gst_audio_decoder_get_audio_info (GST_AUDIO_DECODER (ffmpegdec)); -+ -+ buffer_info = g_slice_new (BufferInfo); -+ buffer_info->buffer = -+ gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (ffmpegdec), -+ frame->nb_samples * info->bpf); -+ gst_buffer_map (buffer_info->buffer, &buffer_info->map, GST_MAP_WRITE); -+ frame->opaque = buffer_info; -+ frame->data[0] = buffer_info->map.data; -+ frame->extended_data = frame->data; -+ frame->linesize[0] = buffer_info->map.size; -+ frame->type = FF_BUFFER_TYPE_USER; -+ -+ return 0; -+ /* fallbacks */ -+negotiate_failed: -+ { -+ GST_DEBUG_OBJECT (ffmpegdec, "negotiate failed"); -+ goto fallback; -+ } -+fallback: -+ { -+ return avcodec_default_get_buffer (context, frame); -+ } -+} -+ -+static gboolean -+gst_ffmpegauddec_set_format (GstAudioDecoder * decoder, GstCaps * caps) -+{ -+ GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder; -+ GstFFMpegAudDecClass *oclass; -+ gboolean ret = TRUE; -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ GST_DEBUG_OBJECT (ffmpegdec, "setcaps called"); -+ -+ GST_OBJECT_LOCK (ffmpegdec); -+ -+ if (ffmpegdec->last_caps && gst_caps_is_equal (ffmpegdec->last_caps, caps)) { -+ GST_DEBUG_OBJECT (ffmpegdec, "same caps"); -+ GST_OBJECT_UNLOCK (ffmpegdec); -+ return TRUE; -+ } -+ -+ gst_caps_replace (&ffmpegdec->last_caps, caps); -+ -+ /* close old session */ -+ if (ffmpegdec->opened) { -+ GST_OBJECT_UNLOCK (ffmpegdec); -+ gst_ffmpegauddec_drain (ffmpegdec); -+ GST_OBJECT_LOCK (ffmpegdec); -+ gst_ffmpegauddec_close (ffmpegdec); -+ } -+ -+ /* get size and so */ -+ gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id, -+ oclass->in_plugin->type, caps, ffmpegdec->context); -+ -+ /* workaround encoder bugs */ -+ ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT; -+ ffmpegdec->context->err_recognition = 1; -+ -+ ffmpegdec->context->opaque = ffmpegdec; -+ ffmpegdec->context->get_buffer = gst_ffmpegauddec_get_buffer; -+ ffmpegdec->context->reget_buffer = NULL; -+ ffmpegdec->context->release_buffer = NULL; -+ -+ /* open codec - we don't select an output pix_fmt yet, -+ * simply because we don't know! We only get it -+ * during playback... */ -+ if (!gst_ffmpegauddec_open (ffmpegdec)) -+ goto open_failed; -+ -+done: -+ GST_OBJECT_UNLOCK (ffmpegdec); -+ -+ return ret; -+ -+ /* ERRORS */ -+open_failed: -+ { -+ GST_DEBUG_OBJECT (ffmpegdec, "Failed to open"); -+ ret = FALSE; -+ goto done; -+ } -+} -+ -+static gboolean -+gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force) -+{ -+ GstFFMpegAudDecClass *oclass; -+ gint depth; -+ GstAudioFormat format; -+ GstAudioChannelPosition pos[64] = { 0, }; -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ depth = av_smp_format_depth (ffmpegdec->context->sample_fmt) * 8; -+ format = gst_ffmpeg_smpfmt_to_audioformat (ffmpegdec->context->sample_fmt); -+ if (format == GST_AUDIO_FORMAT_UNKNOWN) -+ goto no_caps; -+ -+ if (!force && ffmpegdec->info.rate == -+ ffmpegdec->context->sample_rate && -+ ffmpegdec->info.channels == ffmpegdec->context->channels && -+ ffmpegdec->info.finfo->depth == depth) -+ return TRUE; -+ -+ GST_DEBUG_OBJECT (ffmpegdec, -+ "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)", -+ ffmpegdec->info.rate, ffmpegdec->info.channels, -+ ffmpegdec->info.finfo->depth, -+ ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth); -+ -+ gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context->channel_layout, -+ ffmpegdec->context->channels, pos); -+ memcpy (ffmpegdec->ffmpeg_layout, pos, -+ sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels); -+ -+ /* Get GStreamer channel layout */ -+ gst_audio_channel_positions_to_valid_order (pos, -+ ffmpegdec->context->channels); -+ ffmpegdec->needs_reorder = -+ memcmp (pos, ffmpegdec->ffmpeg_layout, -+ sizeof (pos[0]) * ffmpegdec->context->channels) != 0; -+ gst_audio_info_set_format (&ffmpegdec->info, format, -+ ffmpegdec->context->sample_rate, ffmpegdec->context->channels, pos); -+ -+ if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (ffmpegdec), -+ &ffmpegdec->info)) -+ goto caps_failed; -+ -+ return TRUE; -+ -+ /* ERRORS */ -+no_caps: -+ { -+#ifdef HAVE_LIBAV_UNINSTALLED -+ /* using internal ffmpeg snapshot */ -+ GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, -+ ("Could not find GStreamer caps mapping for libav codec '%s'.", -+ oclass->in_plugin->name), (NULL)); -+#else -+ /* using external ffmpeg */ -+ GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, -+ ("Could not find GStreamer caps mapping for libav codec '%s', and " -+ "you are using an external libavcodec. This is most likely due to " -+ "a packaging problem and/or libavcodec having been upgraded to a " -+ "version that is not compatible with this version of " -+ "gstreamer-libav. Make sure your gstreamer-libav and libavcodec " -+ "packages come from the same source/repository.", -+ oclass->in_plugin->name), (NULL)); -+#endif -+ return FALSE; -+ } -+caps_failed: -+ { -+ GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL), -+ ("Could not set caps for libav decoder (%s), not fixed?", -+ oclass->in_plugin->name)); -+ -+ return FALSE; -+ } -+} -+ -+static void -+gst_avpacket_init (AVPacket * packet, guint8 * data, guint size) -+{ -+ memset (packet, 0, sizeof (AVPacket)); -+ packet->data = data; -+ packet->size = size; -+} -+ -+static gint -+gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec, -+ AVCodec * in_plugin, guint8 * data, guint size, -+ GstBuffer ** outbuf, GstFlowReturn * ret) -+{ -+ gint len = -1; -+ gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE; -+ AVPacket packet; -+ AVFrame frame; -+ -+ GST_DEBUG_OBJECT (ffmpegdec, "size: %d", size); -+ -+ gst_avpacket_init (&packet, data, size); -+ memset (&frame, 0, sizeof (frame)); -+ avcodec_get_frame_defaults (&frame); -+ len = avcodec_decode_audio4 (ffmpegdec->context, &frame, &have_data, &packet); -+ -+ GST_DEBUG_OBJECT (ffmpegdec, -+ "Decode audio: len=%d, have_data=%d", len, have_data); -+ -+ if (len >= 0 && have_data > 0) { -+ BufferInfo *buffer_info = frame.opaque; -+ gint nsamples, channels, byte_per_sample; -+ gsize output_size; -+ -+ if (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)) { -+ *outbuf = NULL; -+ *ret = GST_FLOW_NOT_NEGOTIATED; -+ len = -1; -+ goto beach; -+ } -+ -+ channels = ffmpegdec->info.channels; -+ nsamples = frame.nb_samples; -+ byte_per_sample = ffmpegdec->info.finfo->width / 8; -+ -+ /* frame.linesize[0] might contain padding, allocate only what's needed */ -+ output_size = nsamples * byte_per_sample * channels; -+ -+ GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer"); -+ if (buffer_info) { -+ *outbuf = buffer_info->buffer; -+ gst_buffer_unmap (buffer_info->buffer, &buffer_info->map); -+ g_slice_free (BufferInfo, buffer_info); -+ frame.opaque = NULL; -+ } else if (av_sample_fmt_is_planar (ffmpegdec->context->sample_fmt) -+ && channels > 1) { -+ gint i, j; -+ GstMapInfo minfo; -+ -+ /* note: linesize[0] might contain padding, allocate only what's needed */ -+ *outbuf = -+ gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER -+ (ffmpegdec), output_size); -+ -+ gst_buffer_map (*outbuf, &minfo, GST_MAP_WRITE); -+ -+ switch (ffmpegdec->info.finfo->width) { -+ case 8:{ -+ guint8 *odata = minfo.data; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ odata[j] = ((const guint8 *) frame.extended_data[j])[i]; -+ } -+ odata += channels; -+ } -+ break; -+ } -+ case 16:{ -+ guint16 *odata = (guint16 *) minfo.data; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ odata[j] = ((const guint16 *) frame.extended_data[j])[i]; -+ } -+ odata += channels; -+ } -+ break; -+ } -+ case 32:{ -+ guint32 *odata = (guint32 *) minfo.data; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ odata[j] = ((const guint32 *) frame.extended_data[j])[i]; -+ } -+ odata += channels; -+ } -+ break; -+ } -+ case 64:{ -+ guint64 *odata = (guint64 *) minfo.data; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ odata[j] = ((const guint64 *) frame.extended_data[j])[i]; -+ } -+ odata += channels; -+ } -+ break; -+ } -+ default: -+ g_assert_not_reached (); -+ break; -+ } -+ gst_buffer_unmap (*outbuf, &minfo); -+ } else { -+ *outbuf = -+ gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER -+ (ffmpegdec), output_size); -+ gst_buffer_fill (*outbuf, 0, frame.data[0], output_size); -+ } -+ -+ GST_DEBUG_OBJECT (ffmpegdec, "Buffer created. Size: %d", have_data); -+ -+ /* Reorder channels to the GStreamer channel order */ -+ if (ffmpegdec->needs_reorder) { -+ *outbuf = gst_buffer_make_writable (*outbuf); -+ gst_audio_buffer_reorder_channels (*outbuf, ffmpegdec->info.finfo->format, -+ ffmpegdec->info.channels, ffmpegdec->ffmpeg_layout, -+ ffmpegdec->info.position); -+ } -+ } else { -+ *outbuf = NULL; -+ } -+ -+beach: -+ GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d", -+ *ret, *outbuf, len); -+ return len; -+} -+ -+/* gst_ffmpegauddec_frame: -+ * ffmpegdec: -+ * data: pointer to the data to decode -+ * size: size of data in bytes -+ * got_data: 0 if no data was decoded, != 0 otherwise. -+ * in_time: timestamp of data -+ * in_duration: duration of data -+ * ret: GstFlowReturn to return in the chain function -+ * -+ * Decode the given frame and pushes it downstream. -+ * -+ * Returns: Number of bytes used in decoding, -1 on error/failure. -+ */ -+ -+static gint -+gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec, -+ guint8 * data, guint size, gint * got_data, GstFlowReturn * ret) -+{ -+ GstFFMpegAudDecClass *oclass; -+ GstBuffer *outbuf = NULL; -+ gint have_data = 0, len = 0; -+ -+ if (G_UNLIKELY (ffmpegdec->context->codec == NULL)) -+ goto no_codec; -+ -+ GST_LOG_OBJECT (ffmpegdec, "data:%p, size:%d", data, size); -+ -+ *ret = GST_FLOW_OK; -+ ffmpegdec->context->frame_number++; -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ len = -+ gst_ffmpegauddec_audio_frame (ffmpegdec, oclass->in_plugin, data, size, -+ &outbuf, ret); -+ -+ if (outbuf) -+ have_data = 1; -+ -+ if (len < 0 || have_data < 0) { -+ GST_WARNING_OBJECT (ffmpegdec, -+ "avdec_%s: decoding error (len: %d, have_data: %d)", -+ oclass->in_plugin->name, len, have_data); -+ *got_data = 0; -+ goto beach; -+ } else if (len == 0 && have_data == 0) { -+ *got_data = 0; -+ goto beach; -+ } else { -+ /* this is where I lost my last clue on ffmpeg... */ -+ *got_data = 1; -+ } -+ -+ if (outbuf) { -+ GST_LOG_OBJECT (ffmpegdec, "Decoded data, now storing buffer %p", outbuf); -+ -+ if (ffmpegdec->outbuf) -+ ffmpegdec->outbuf = gst_buffer_append (ffmpegdec->outbuf, outbuf); -+ else -+ ffmpegdec->outbuf = outbuf; -+ } else { -+ GST_DEBUG_OBJECT (ffmpegdec, "We didn't get a decoded buffer"); -+ } -+ -+beach: -+ return len; -+ -+ /* ERRORS */ -+no_codec: -+ { -+ GST_ERROR_OBJECT (ffmpegdec, "no codec context"); -+ return -1; -+ } -+} -+ -+static void -+gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec) -+{ -+ GstFFMpegAudDecClass *oclass; -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) { -+ gint have_data, len, try = 0; -+ -+ GST_LOG_OBJECT (ffmpegdec, -+ "codec has delay capabilities, calling until libav has drained everything"); -+ -+ do { -+ GstFlowReturn ret; -+ -+ len = gst_ffmpegauddec_frame (ffmpegdec, NULL, 0, &have_data, &ret); -+ if (len < 0 || have_data == 0) -+ break; -+ } while (try++ < 10); -+ } -+ -+ if (ffmpegdec->outbuf) -+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), -+ ffmpegdec->outbuf, 1); -+ ffmpegdec->outbuf = NULL; -+} -+ -+static void -+gst_ffmpegauddec_flush (GstAudioDecoder * decoder, gboolean hard) -+{ -+ GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) decoder; -+ -+ if (ffmpegdec->opened) { -+ avcodec_flush_buffers (ffmpegdec->context); -+ } -+} -+ -+static GstFlowReturn -+gst_ffmpegauddec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf) -+{ -+ GstFFMpegAudDec *ffmpegdec; -+ GstFFMpegAudDecClass *oclass; -+ guint8 *data, *bdata; -+ GstMapInfo map; -+ gint size, bsize, len, have_data; -+ GstFlowReturn ret = GST_FLOW_OK; -+ -+ ffmpegdec = (GstFFMpegAudDec *) decoder; -+ -+ if (G_UNLIKELY (!ffmpegdec->opened)) -+ goto not_negotiated; -+ -+ if (inbuf == NULL) { -+ gst_ffmpegauddec_drain (ffmpegdec); -+ return GST_FLOW_OK; -+ } -+ -+ inbuf = gst_buffer_ref (inbuf); -+ -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ -+ GST_LOG_OBJECT (ffmpegdec, -+ "Received new data of size %" G_GSIZE_FORMAT ", offset:%" G_GUINT64_FORMAT -+ ", ts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT, -+ gst_buffer_get_size (inbuf), GST_BUFFER_OFFSET (inbuf), -+ GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)), -+ GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf))); -+ -+ /* workarounds, functions write to buffers: -+ * libavcodec/svq1.c:svq1_decode_frame writes to the given buffer. -+ * libavcodec/svq3.c:svq3_decode_slice_header too. -+ * ffmpeg devs know about it and will fix it (they said). */ -+ if (oclass->in_plugin->id == CODEC_ID_SVQ1 || -+ oclass->in_plugin->id == CODEC_ID_SVQ3) { -+ inbuf = gst_buffer_make_writable (inbuf); -+ } -+ -+ gst_buffer_map (inbuf, &map, GST_MAP_READ); -+ -+ bdata = map.data; -+ bsize = map.size; -+ -+ do { -+ data = bdata; -+ size = bsize; -+ -+ /* decode a frame of audio now */ -+ len = gst_ffmpegauddec_frame (ffmpegdec, data, size, &have_data, &ret); -+ -+ if (ret != GST_FLOW_OK) { -+ GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s", -+ gst_flow_get_name (ret)); -+ /* bad flow return, make sure we discard all data and exit */ -+ bsize = 0; -+ break; -+ } -+ -+ if (len == 0 && !have_data) { -+ /* nothing was decoded, this could be because no data was available or -+ * because we were skipping frames. -+ * If we have no context we must exit and wait for more data, we keep the -+ * data we tried. */ -+ GST_LOG_OBJECT (ffmpegdec, "Decoding didn't return any data, breaking"); -+ break; -+ } else if (len < 0) { -+ /* a decoding error happened, we must break and try again with next data. */ -+ GST_LOG_OBJECT (ffmpegdec, "Decoding error, breaking"); -+ bsize = 0; -+ break; -+ } -+ /* prepare for the next round, for codecs with a context we did this -+ * already when using the parser. */ -+ bsize -= len; -+ bdata += len; -+ -+ GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0). bsize:%d , bdata:%p", -+ bsize, bdata); -+ } while (bsize > 0); -+ -+ gst_buffer_unmap (inbuf, &map); -+ gst_buffer_unref (inbuf); -+ -+ if (ffmpegdec->outbuf) -+ ret = -+ gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (ffmpegdec), -+ ffmpegdec->outbuf, 1); -+ ffmpegdec->outbuf = NULL; -+ -+ if (bsize > 0) { -+ GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize); -+ } -+ -+ return ret; -+ -+ /* ERRORS */ -+not_negotiated: -+ { -+ oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -+ GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL), -+ ("avdec_%s: input format was not set before data start", -+ oclass->in_plugin->name)); -+ return GST_FLOW_NOT_NEGOTIATED; -+ } -+} -+ -+gboolean -+gst_ffmpegauddec_register (GstPlugin * plugin) -+{ -+ GTypeInfo typeinfo = { -+ sizeof (GstFFMpegAudDecClass), -+ (GBaseInitFunc) gst_ffmpegauddec_base_init, -+ NULL, -+ (GClassInitFunc) gst_ffmpegauddec_class_init, -+ NULL, -+ NULL, -+ sizeof (GstFFMpegAudDec), -+ 0, -+ (GInstanceInitFunc) gst_ffmpegauddec_init, -+ }; -+ GType type; -+ AVCodec *in_plugin; -+ gint rank; -+ -+ in_plugin = av_codec_next (NULL); -+ -+ GST_LOG ("Registering decoders"); -+ -+ while (in_plugin) { -+ gchar *type_name; -+ gchar *plugin_name; -+ -+ /* only decoders */ -+ if (!av_codec_is_decoder (in_plugin) -+ || in_plugin->type != AVMEDIA_TYPE_AUDIO) { -+ goto next; -+ } -+ -+ /* no quasi-codecs, please */ -+ if (in_plugin->id >= CODEC_ID_PCM_S16LE && -+ in_plugin->id <= CODEC_ID_PCM_BLURAY) { -+ goto next; -+ } -+ -+ /* No decoders depending on external libraries (we don't build them, but -+ * people who build against an external ffmpeg might have them. -+ * We have native gstreamer plugins for all of those libraries anyway. */ -+ if (!strncmp (in_plugin->name, "lib", 3)) { -+ GST_DEBUG -+ ("Not using external library decoder %s. Use the gstreamer-native ones instead.", -+ in_plugin->name); -+ goto next; -+ } -+ -+ GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name); -+ -+ /* no codecs for which we're GUARANTEED to have better alternatives */ -+ /* MP1 : Use MP3 for decoding */ -+ /* MP2 : Use MP3 for decoding */ -+ /* Theora: Use libtheora based theoradec */ -+ if (!strcmp (in_plugin->name, "vorbis") || -+ !strcmp (in_plugin->name, "wavpack") || -+ !strcmp (in_plugin->name, "mp1") || -+ !strcmp (in_plugin->name, "mp2") || -+ !strcmp (in_plugin->name, "libfaad") || -+ !strcmp (in_plugin->name, "mpeg4aac") || -+ !strcmp (in_plugin->name, "ass") || -+ !strcmp (in_plugin->name, "srt") || -+ !strcmp (in_plugin->name, "pgssub") || -+ !strcmp (in_plugin->name, "dvdsub") || -+ !strcmp (in_plugin->name, "dvbsub")) { -+ GST_LOG ("Ignoring decoder %s", in_plugin->name); -+ goto next; -+ } -+ -+ /* construct the type */ -+ plugin_name = g_strdup ((gchar *) in_plugin->name); -+ g_strdelimit (plugin_name, NULL, '_'); -+ type_name = g_strdup_printf ("avdec_%s", plugin_name); -+ g_free (plugin_name); -+ -+ type = g_type_from_name (type_name); -+ -+ if (!type) { -+ /* create the gtype now */ -+ type = -+ g_type_register_static (GST_TYPE_AUDIO_DECODER, type_name, &typeinfo, -+ 0); -+ g_type_set_qdata (type, GST_FFDEC_PARAMS_QDATA, (gpointer) in_plugin); -+ } -+ -+ /* (Ronald) MPEG-4 gets a higher priority because it has been well- -+ * tested and by far outperforms divxdec/xviddec - so we prefer it. -+ * msmpeg4v3 same, as it outperforms divxdec for divx3 playback. -+ * VC1/WMV3 are not working and thus unpreferred for now. */ -+ switch (in_plugin->id) { -+ case CODEC_ID_RA_144: -+ case CODEC_ID_RA_288: -+ case CODEC_ID_COOK: -+ rank = GST_RANK_PRIMARY; -+ break; -+ /* SIPR: decoder should have a higher rank than realaudiodec. -+ */ -+ case CODEC_ID_SIPR: -+ rank = GST_RANK_SECONDARY; -+ break; -+ case CODEC_ID_MP3: -+ rank = GST_RANK_NONE; -+ break; -+ default: -+ rank = GST_RANK_MARGINAL; -+ break; -+ } -+ if (!gst_element_register (plugin, type_name, rank, type)) { -+ g_warning ("Failed to register %s", type_name); -+ g_free (type_name); -+ return FALSE; -+ } -+ -+ g_free (type_name); -+ -+ next: -+ in_plugin = av_codec_next (in_plugin); -+ } -+ -+ GST_LOG ("Finished Registering decoders"); -+ -+ return TRUE; -+} -diff --git a/ext/libav/gstavauddec.h b/ext/libav/gstavauddec.h -new file mode 100644 -index 0000000..23d11fd ---- /dev/null -+++ b/ext/libav/gstavauddec.h -@@ -0,0 +1,73 @@ -+/* GStreamer -+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+#ifndef __GST_FFMPEGAUDDEC_H__ -+#define __GST_FFMPEGAUDDEC_H__ -+ -+G_BEGIN_DECLS -+ -+#include <gst/gst.h> -+#include <gst/audio/audio.h> -+#include <gst/audio/gstaudiodecoder.h> -+#include <libavcodec/avcodec.h> -+ -+typedef struct _GstFFMpegAudDec GstFFMpegAudDec; -+struct _GstFFMpegAudDec -+{ -+ GstAudioDecoder parent; -+ -+ /* decoding */ -+ AVCodecContext *context; -+ gboolean opened; -+ -+ /* prevent reopening the decoder on GST_EVENT_CAPS when caps are same as last time. */ -+ GstCaps *last_caps; -+ -+ /* Stores current buffers to push as GstAudioDecoder wants 1:1 mapping for input/output buffers */ -+ GstBuffer *outbuf; -+ -+ /* current output format */ -+ GstAudioInfo info; -+ GstAudioChannelPosition ffmpeg_layout[64]; -+ gboolean needs_reorder; -+}; -+ -+typedef struct _GstFFMpegAudDecClass GstFFMpegAudDecClass; -+ -+struct _GstFFMpegAudDecClass -+{ -+ GstAudioDecoderClass parent_class; -+ -+ AVCodec *in_plugin; -+ GstPadTemplate *srctempl, *sinktempl; -+}; -+ -+#define GST_TYPE_FFMPEGDEC \ -+ (gst_ffmpegauddec_get_type()) -+#define GST_FFMPEGDEC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegAudDec)) -+#define GST_FFMPEGAUDDEC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegAudDecClass)) -+#define GST_IS_FFMPEGDEC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) -+#define GST_IS_FFMPEGAUDDEC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) -+ -+G_END_DECLS -+ -+#endif -diff --git a/ext/libav/gstavaudenc.c b/ext/libav/gstavaudenc.c -new file mode 100644 -index 0000000..2db08bb ---- /dev/null -+++ b/ext/libav/gstavaudenc.c -@@ -0,0 +1,752 @@ -+/* GStreamer -+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -+ * Copyright (C) <2012> 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 Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include <assert.h> -+#include <string.h> -+/* for stats file handling */ -+#include <stdio.h> -+#include <glib/gstdio.h> -+#include <errno.h> -+ -+#include <libavcodec/avcodec.h> -+ -+#include <gst/gst.h> -+ -+#include "gstav.h" -+#include "gstavcodecmap.h" -+#include "gstavutils.h" -+#include "gstavaudenc.h" -+ -+#define DEFAULT_AUDIO_BITRATE 128000 -+ -+enum -+{ -+ /* FILL ME */ -+ LAST_SIGNAL -+}; -+ -+enum -+{ -+ PROP_0, -+ PROP_BIT_RATE, -+ PROP_RTP_PAYLOAD_SIZE, -+}; -+ -+/* A number of function prototypes are given so we can refer to them later. */ -+static void gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass); -+static void gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass); -+static void gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc); -+static void gst_ffmpegaudenc_finalize (GObject * object); -+ -+static GstCaps *gst_ffmpegaudenc_getcaps (GstAudioEncoder * encoder, -+ GstCaps * filter); -+static gboolean gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, -+ GstAudioInfo * info); -+static GstFlowReturn gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, -+ GstBuffer * inbuf); -+static gboolean gst_ffmpegaudenc_stop (GstAudioEncoder * encoder); -+static void gst_ffmpegaudenc_flush (GstAudioEncoder * encoder); -+ -+static void gst_ffmpegaudenc_set_property (GObject * object, -+ guint prop_id, const GValue * value, GParamSpec * pspec); -+static void gst_ffmpegaudenc_get_property (GObject * object, -+ guint prop_id, GValue * value, GParamSpec * pspec); -+ -+#define GST_FFENC_PARAMS_QDATA g_quark_from_static_string("avenc-params") -+ -+static GstElementClass *parent_class = NULL; -+ -+/*static guint gst_ffmpegaudenc_signals[LAST_SIGNAL] = { 0 }; */ -+ -+static void -+gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass) -+{ -+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -+ AVCodec *in_plugin; -+ GstPadTemplate *srctempl = NULL, *sinktempl = NULL; -+ GstCaps *srccaps = NULL, *sinkcaps = NULL; -+ gchar *longname, *description; -+ -+ in_plugin = -+ (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), -+ GST_FFENC_PARAMS_QDATA); -+ g_assert (in_plugin != NULL); -+ -+ /* construct the element details struct */ -+ longname = g_strdup_printf ("libav %s encoder", in_plugin->long_name); -+ description = g_strdup_printf ("libav %s encoder", in_plugin->name); -+ gst_element_class_set_metadata (element_class, longname, -+ "Codec/Encoder/Audio", description, -+ "Wim Taymans <wim.taymans@gmail.com>, " -+ "Ronald Bultje <rbultje@ronald.bitfreak.net>"); -+ g_free (longname); -+ g_free (description); -+ -+ if (!(srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE))) { -+ GST_DEBUG ("Couldn't get source caps for encoder '%s'", in_plugin->name); -+ srccaps = gst_caps_new_empty_simple ("unknown/unknown"); -+ } -+ -+ sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL, -+ in_plugin->id, TRUE, in_plugin); -+ if (!sinkcaps) { -+ GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name); -+ sinkcaps = gst_caps_new_empty_simple ("unknown/unknown"); -+ } -+ -+ /* pad templates */ -+ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -+ GST_PAD_ALWAYS, sinkcaps); -+ srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps); -+ -+ gst_element_class_add_pad_template (element_class, srctempl); -+ gst_element_class_add_pad_template (element_class, sinktempl); -+ -+ klass->in_plugin = in_plugin; -+ klass->srctempl = srctempl; -+ klass->sinktempl = sinktempl; -+ -+ return; -+} -+ -+static void -+gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass) -+{ -+ GObjectClass *gobject_class; -+ GstAudioEncoderClass *gstaudioencoder_class; -+ -+ gobject_class = (GObjectClass *) klass; -+ gstaudioencoder_class = (GstAudioEncoderClass *) klass; -+ -+ parent_class = g_type_class_peek_parent (klass); -+ -+ gobject_class->set_property = gst_ffmpegaudenc_set_property; -+ gobject_class->get_property = gst_ffmpegaudenc_get_property; -+ -+ /* FIXME: could use -1 for a sensible per-codec defaults */ -+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE, -+ g_param_spec_int ("bitrate", "Bit Rate", -+ "Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE, -+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -+ -+ gobject_class->finalize = gst_ffmpegaudenc_finalize; -+ -+ gstaudioencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_stop); -+ gstaudioencoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_getcaps); -+ gstaudioencoder_class->flush = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_flush); -+ gstaudioencoder_class->set_format = -+ GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_set_format); -+ gstaudioencoder_class->handle_frame = -+ GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_handle_frame); -+} -+ -+static void -+gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc) -+{ -+ GstFFMpegAudEncClass *klass = -+ (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc); -+ -+ /* ffmpeg objects */ -+ ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin); -+ ffmpegaudenc->opened = FALSE; -+ -+ gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE); -+} -+ -+static void -+gst_ffmpegaudenc_finalize (GObject * object) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) object; -+ -+ /* clean up remaining allocated data */ -+ av_free (ffmpegaudenc->context); -+ -+ G_OBJECT_CLASS (parent_class)->finalize (object); -+} -+ -+static gboolean -+gst_ffmpegaudenc_stop (GstAudioEncoder * encoder) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder; -+ -+ /* close old session */ -+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -+ ffmpegaudenc->opened = FALSE; -+ -+ return TRUE; -+} -+ -+static void -+gst_ffmpegaudenc_flush (GstAudioEncoder * encoder) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder; -+ -+ if (ffmpegaudenc->opened) { -+ avcodec_flush_buffers (ffmpegaudenc->context); -+ } -+} -+ -+static GstCaps * -+gst_ffmpegaudenc_getcaps (GstAudioEncoder * encoder, GstCaps * filter) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder; -+ GstCaps *caps = NULL; -+ -+ GST_DEBUG_OBJECT (ffmpegaudenc, "getting caps"); -+ -+ /* audio needs no special care */ -+ caps = gst_audio_encoder_proxy_getcaps (encoder, NULL, filter); -+ -+ GST_DEBUG_OBJECT (ffmpegaudenc, "audio caps, return %" GST_PTR_FORMAT, caps); -+ -+ return caps; -+} -+ -+static gboolean -+gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder; -+ GstCaps *other_caps; -+ GstCaps *allowed_caps; -+ GstCaps *icaps; -+ gsize frame_size; -+ GstFFMpegAudEncClass *oclass = -+ (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc); -+ -+ /* close old session */ -+ if (ffmpegaudenc->opened) { -+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -+ ffmpegaudenc->opened = FALSE; -+ } -+ -+ /* if we set it in _getcaps we should set it also in _link */ -+ ffmpegaudenc->context->strict_std_compliance = -1; -+ -+ /* user defined properties */ -+ if (ffmpegaudenc->bitrate > 0) { -+ GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d", -+ ffmpegaudenc->bitrate); -+ ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate; -+ ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate; -+ } else { -+ GST_INFO_OBJECT (ffmpegaudenc, "Using avcontext default bitrate %d", -+ ffmpegaudenc->context->bit_rate); -+ } -+ -+ /* RTP payload used for GOB production (for Asterisk) */ -+ if (ffmpegaudenc->rtp_payload_size) { -+ ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size; -+ } -+ -+ /* some other defaults */ -+ ffmpegaudenc->context->rc_strategy = 2; -+ ffmpegaudenc->context->b_frame_strategy = 0; -+ ffmpegaudenc->context->coder_type = 0; -+ ffmpegaudenc->context->context_model = 0; -+ ffmpegaudenc->context->scenechange_threshold = 0; -+ ffmpegaudenc->context->inter_threshold = 0; -+ -+ /* fetch pix_fmt and so on */ -+ gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context); -+ if (!ffmpegaudenc->context->time_base.den) { -+ ffmpegaudenc->context->time_base.den = GST_AUDIO_INFO_RATE (info); -+ ffmpegaudenc->context->time_base.num = 1; -+ ffmpegaudenc->context->ticks_per_frame = 1; -+ } -+ -+ if (ffmpegaudenc->context->channel_layout) { -+ gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout, -+ ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout); -+ ffmpegaudenc->needs_reorder = -+ (memcmp (ffmpegaudenc->ffmpeg_layout, info->position, -+ sizeof (GstAudioChannelPosition) * -+ ffmpegaudenc->context->channels) != 0); -+ } -+ -+ /* open codec */ -+ if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) { -+ if (ffmpegaudenc->context->priv_data) -+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -+ GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec", -+ oclass->in_plugin->name); -+ return FALSE; -+ } -+ -+ /* some codecs support more than one format, first auto-choose one */ -+ GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ..."); -+ allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder)); -+ if (!allowed_caps) { -+ GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps"); -+ /* we need to copy because get_allowed_caps returns a ref, and -+ * get_pad_template_caps doesn't */ -+ allowed_caps = -+ gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder)); -+ } -+ GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps); -+ gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id, -+ oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context); -+ -+ /* try to set this caps on the other side */ -+ other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id, -+ ffmpegaudenc->context, TRUE); -+ -+ if (!other_caps) { -+ gst_caps_unref (allowed_caps); -+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -+ GST_DEBUG ("Unsupported codec - no caps found"); -+ return FALSE; -+ } -+ -+ icaps = gst_caps_intersect (allowed_caps, other_caps); -+ gst_caps_unref (allowed_caps); -+ gst_caps_unref (other_caps); -+ if (gst_caps_is_empty (icaps)) { -+ gst_caps_unref (icaps); -+ return FALSE; -+ } -+ icaps = gst_caps_truncate (icaps); -+ -+ if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc), -+ icaps)) { -+ gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -+ gst_caps_unref (icaps); -+ return FALSE; -+ } -+ gst_caps_unref (icaps); -+ -+ frame_size = ffmpegaudenc->context->frame_size; -+ if (frame_size > 1) { -+ gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc), -+ frame_size); -+ gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc), -+ frame_size); -+ gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1); -+ } else { -+ gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc), -+ 0); -+ gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc), -+ 0); -+ gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0); -+ } -+ -+ /* success! */ -+ ffmpegaudenc->opened = TRUE; -+ -+ return TRUE; -+} -+ -+ -+static GstFlowReturn -+gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc, -+ guint8 * audio_in, guint in_size, gint * have_data) -+{ -+ GstAudioEncoder *enc; -+ AVCodecContext *ctx; -+ gint res; -+ GstFlowReturn ret; -+ GstAudioInfo *info; -+ AVPacket pkt; -+ AVFrame frame; -+ gboolean planar; -+ -+ enc = GST_AUDIO_ENCODER (ffmpegaudenc); -+ -+ ctx = ffmpegaudenc->context; -+ -+ GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer "); -+ -+ memset (&pkt, 0, sizeof (pkt)); -+ memset (&frame, 0, sizeof (frame)); -+ avcodec_get_frame_defaults (&frame); -+ -+ info = gst_audio_encoder_get_audio_info (enc); -+ planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt); -+ -+ if (planar && info->channels > 1) { -+ gint channels, nsamples; -+ gint i, j; -+ -+ nsamples = frame.nb_samples = in_size / info->bpf; -+ channels = info->channels; -+ -+ if (info->channels > AV_NUM_DATA_POINTERS) { -+ frame.extended_data = g_new (uint8_t *, info->channels); -+ } else { -+ frame.extended_data = frame.data; -+ } -+ -+ frame.extended_data[0] = g_malloc (in_size); -+ frame.linesize[0] = in_size / channels; -+ for (i = 1; i < channels; i++) -+ frame.extended_data[i] = frame.extended_data[i - 1] + frame.linesize[0]; -+ -+ switch (info->finfo->width) { -+ case 8:{ -+ const guint8 *idata = (const guint8 *) audio_in; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ ((guint8 *) frame.extended_data[j])[i] = idata[j]; -+ } -+ idata += channels; -+ } -+ break; -+ } -+ case 16:{ -+ const guint16 *idata = (const guint16 *) audio_in; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ ((guint16 *) frame.extended_data[j])[i] = idata[j]; -+ } -+ idata += channels; -+ } -+ break; -+ } -+ case 32:{ -+ const guint32 *idata = (const guint32 *) audio_in; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ ((guint32 *) frame.extended_data[j])[i] = idata[j]; -+ } -+ idata += channels; -+ } -+ -+ break; -+ } -+ case 64:{ -+ const guint64 *idata = (const guint64 *) audio_in; -+ -+ for (i = 0; i < nsamples; i++) { -+ for (j = 0; j < channels; j++) { -+ ((guint64 *) frame.extended_data[j])[i] = idata[j]; -+ } -+ idata += channels; -+ } -+ -+ break; -+ } -+ default: -+ g_assert_not_reached (); -+ break; -+ } -+ -+ } else { -+ frame.data[0] = audio_in; -+ frame.extended_data = frame.data; -+ frame.linesize[0] = in_size; -+ frame.nb_samples = in_size / info->bpf; -+ } -+ -+ res = avcodec_encode_audio2 (ctx, &pkt, &frame, have_data); -+ if (planar && info->channels > 1) -+ g_free (frame.data[0]); -+ if (frame.extended_data != frame.data) -+ g_free (frame.extended_data); -+ -+ if (res < 0) { -+ char error_str[128] = { 0, }; -+ -+ av_strerror (res, error_str, sizeof (error_str)); -+ GST_ERROR_OBJECT (enc, "Failed to encode buffer: %d - %s", res, error_str); -+ return GST_FLOW_OK; -+ } -+ GST_LOG_OBJECT (ffmpegaudenc, "got output size %d", res); -+ -+ if (*have_data) { -+ GstBuffer *outbuf; -+ const AVCodec *codec; -+ -+ GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt.size); -+ -+ outbuf = -+ gst_buffer_new_wrapped_full (0, pkt.data, pkt.size, 0, pkt.size, -+ pkt.data, av_free); -+ -+ codec = ffmpegaudenc->context->codec; -+ if ((codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { -+ ret = gst_audio_encoder_finish_frame (enc, outbuf, -1); -+ } else { -+ ret = gst_audio_encoder_finish_frame (enc, outbuf, frame.nb_samples); -+ } -+ } else { -+ GST_LOG_OBJECT (ffmpegaudenc, "no output produced"); -+ ret = GST_FLOW_OK; -+ } -+ -+ return ret; -+} -+ -+static void -+gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc) -+{ -+ GstFFMpegAudEncClass *oclass; -+ -+ oclass = (GstFFMpegAudEncClass *) (G_OBJECT_GET_CLASS (ffmpegaudenc)); -+ -+ if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) { -+ gint have_data, try = 0; -+ -+ GST_LOG_OBJECT (ffmpegaudenc, -+ "codec has delay capabilities, calling until libav has drained everything"); -+ -+ do { -+ GstFlowReturn ret; -+ -+ ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, NULL, 0, &have_data); -+ if (ret != GST_FLOW_OK || have_data == 0) -+ break; -+ } while (try++ < 10); -+ } -+} -+ -+static GstFlowReturn -+gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc; -+ gsize size; -+ GstFlowReturn ret; -+ guint8 *in_data; -+ GstMapInfo map; -+ gint have_data; -+ -+ ffmpegaudenc = (GstFFMpegAudEnc *) encoder; -+ -+ if (G_UNLIKELY (!ffmpegaudenc->opened)) -+ goto not_negotiated; -+ -+ if (!inbuf) { -+ gst_ffmpegaudenc_drain (ffmpegaudenc); -+ return GST_FLOW_OK; -+ } -+ -+ inbuf = gst_buffer_ref (inbuf); -+ -+ GST_DEBUG_OBJECT (ffmpegaudenc, -+ "Received time %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT -+ ", size %" G_GSIZE_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), -+ GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), gst_buffer_get_size (inbuf)); -+ -+ /* Reorder channels to the GStreamer channel order */ -+ if (ffmpegaudenc->needs_reorder) { -+ GstAudioInfo *info = gst_audio_encoder_get_audio_info (encoder); -+ -+ inbuf = gst_buffer_make_writable (inbuf); -+ gst_audio_buffer_reorder_channels (inbuf, info->finfo->format, -+ info->channels, info->position, ffmpegaudenc->ffmpeg_layout); -+ } -+ -+ gst_buffer_map (inbuf, &map, GST_MAP_READ); -+ in_data = map.data; -+ size = map.size; -+ ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, in_data, size, &have_data); -+ gst_buffer_unmap (inbuf, &map); -+ gst_buffer_unref (inbuf); -+ -+ if (ret != GST_FLOW_OK) -+ goto push_failed; -+ -+ return GST_FLOW_OK; -+ -+ /* ERRORS */ -+not_negotiated: -+ { -+ GST_ELEMENT_ERROR (ffmpegaudenc, CORE, NEGOTIATION, (NULL), -+ ("not configured to input format before data start")); -+ gst_buffer_unref (inbuf); -+ return GST_FLOW_NOT_NEGOTIATED; -+ } -+push_failed: -+ { -+ GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to push buffer %d (%s)", ret, -+ gst_flow_get_name (ret)); -+ return ret; -+ } -+} -+ -+static void -+gst_ffmpegaudenc_set_property (GObject * object, -+ guint prop_id, const GValue * value, GParamSpec * pspec) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc; -+ -+ /* Get a pointer of the right type. */ -+ ffmpegaudenc = (GstFFMpegAudEnc *) (object); -+ -+ if (ffmpegaudenc->opened) { -+ GST_WARNING_OBJECT (ffmpegaudenc, -+ "Can't change properties once decoder is setup !"); -+ return; -+ } -+ -+ /* Check the argument id to see which argument we're setting. */ -+ switch (prop_id) { -+ case PROP_BIT_RATE: -+ ffmpegaudenc->bitrate = g_value_get_int (value); -+ break; -+ case PROP_RTP_PAYLOAD_SIZE: -+ ffmpegaudenc->rtp_payload_size = g_value_get_int (value); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+/* The set function is simply the inverse of the get fuction. */ -+static void -+gst_ffmpegaudenc_get_property (GObject * object, -+ guint prop_id, GValue * value, GParamSpec * pspec) -+{ -+ GstFFMpegAudEnc *ffmpegaudenc; -+ -+ /* It's not null if we got it, but it might not be ours */ -+ ffmpegaudenc = (GstFFMpegAudEnc *) (object); -+ -+ switch (prop_id) { -+ case PROP_BIT_RATE: -+ g_value_set_int (value, ffmpegaudenc->bitrate); -+ break; -+ break; -+ case PROP_RTP_PAYLOAD_SIZE: -+ g_value_set_int (value, ffmpegaudenc->rtp_payload_size); -+ break; -+ default: -+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -+ break; -+ } -+} -+ -+gboolean -+gst_ffmpegaudenc_register (GstPlugin * plugin) -+{ -+ GTypeInfo typeinfo = { -+ sizeof (GstFFMpegAudEncClass), -+ (GBaseInitFunc) gst_ffmpegaudenc_base_init, -+ NULL, -+ (GClassInitFunc) gst_ffmpegaudenc_class_init, -+ NULL, -+ NULL, -+ sizeof (GstFFMpegAudEnc), -+ 0, -+ (GInstanceInitFunc) gst_ffmpegaudenc_init, -+ }; -+ GType type; -+ AVCodec *in_plugin; -+ -+ -+ GST_LOG ("Registering encoders"); -+ -+ in_plugin = av_codec_next (NULL); -+ while (in_plugin) { -+ gchar *type_name; -+ guint rank; -+ -+ /* Skip non-AV codecs */ -+ if (in_plugin->type != AVMEDIA_TYPE_AUDIO) -+ goto next; -+ -+ /* no quasi codecs, please */ -+ if ((in_plugin->id >= CODEC_ID_PCM_S16LE && -+ in_plugin->id <= CODEC_ID_PCM_BLURAY)) { -+ goto next; -+ } -+ -+ /* No encoders depending on external libraries (we don't build them, but -+ * people who build against an external ffmpeg might have them. -+ * We have native gstreamer plugins for all of those libraries anyway. */ -+ if (!strncmp (in_plugin->name, "lib", 3)) { -+ GST_DEBUG -+ ("Not using external library encoder %s. Use the gstreamer-native ones instead.", -+ in_plugin->name); -+ goto next; -+ } -+ -+ /* only encoders */ -+ if (!av_codec_is_encoder (in_plugin)) { -+ goto next; -+ } -+ -+ /* FIXME : We should have a method to know cheaply whether we have a mapping -+ * for the given plugin or not */ -+ -+ GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name); -+ -+ /* no codecs for which we're GUARANTEED to have better alternatives */ -+ if (!strcmp (in_plugin->name, "vorbis") -+ || !strcmp (in_plugin->name, "flac")) { -+ GST_LOG ("Ignoring encoder %s", in_plugin->name); -+ goto next; -+ } -+ -+ /* construct the type */ -+ type_name = g_strdup_printf ("avenc_%s", in_plugin->name); -+ -+ type = g_type_from_name (type_name); -+ -+ if (!type) { -+ -+ /* create the glib type now */ -+ type = -+ g_type_register_static (GST_TYPE_AUDIO_ENCODER, type_name, &typeinfo, -+ 0); -+ g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin); -+ -+ { -+ static const GInterfaceInfo preset_info = { -+ NULL, -+ NULL, -+ NULL -+ }; -+ g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info); -+ } -+ } -+ -+ switch (in_plugin->id) { -+ /* avenc_aac: see https://bugzilla.gnome.org/show_bug.cgi?id=691617 */ -+ case CODEC_ID_AAC: -+ rank = GST_RANK_NONE; -+ break; -+ default: -+ rank = GST_RANK_SECONDARY; -+ break; -+ } -+ -+ if (!gst_element_register (plugin, type_name, rank, type)) { -+ g_free (type_name); -+ return FALSE; -+ } -+ -+ g_free (type_name); -+ -+ next: -+ in_plugin = av_codec_next (in_plugin); -+ } -+ -+ GST_LOG ("Finished registering encoders"); -+ -+ return TRUE; -+} -diff --git a/ext/libav/gstavaudenc.h b/ext/libav/gstavaudenc.h -new file mode 100644 -index 0000000..b01184f ---- /dev/null -+++ b/ext/libav/gstavaudenc.h -@@ -0,0 +1,77 @@ -+/* GStreamer -+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+ -+/* First, include the header file for the plugin, to bring in the -+ * object definition and other useful things. -+ */ -+ -+#ifndef __GST_FFMPEGAUDENC_H__ -+#define __GST_FFMPEGAUDENC_H__ -+ -+G_BEGIN_DECLS -+ -+#include <gst/gst.h> -+#include <gst/audio/gstaudioencoder.h> -+#include <libavcodec/avcodec.h> -+ -+typedef struct _GstFFMpegAudEnc GstFFMpegAudEnc; -+ -+struct _GstFFMpegAudEnc -+{ -+ GstAudioEncoder parent; -+ -+ AVCodecContext *context; -+ gboolean opened; -+ -+ /* cache */ -+ gint bitrate; -+ gint rtp_payload_size; -+ -+ /* other settings are copied over straight, -+ * include a context here, rather than copy-and-past it from avcodec.h */ -+ AVCodecContext config; -+ -+ GstAudioChannelPosition ffmpeg_layout[64]; -+ gboolean needs_reorder; -+}; -+ -+typedef struct _GstFFMpegAudEncClass GstFFMpegAudEncClass; -+ -+struct _GstFFMpegAudEncClass -+{ -+ GstAudioEncoderClass parent_class; -+ -+ AVCodec *in_plugin; -+ GstPadTemplate *srctempl, *sinktempl; -+}; -+ -+#define GST_TYPE_FFMPEGAUDENC \ -+ (gst_ffmpegaudenc_get_type()) -+#define GST_FFMPEGAUDENC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGAUDENC,GstFFMpegAudEnc)) -+#define GST_FFMPEGAUDENC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGAUDENC,GstFFMpegAudEncClass)) -+#define GST_IS_FFMPEGAUDENC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGAUDENC)) -+#define GST_IS_FFMPEGAUDENC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGAUDENC)) -+ -+G_END_DECLS -+ -+#endif /* __GST_FFMPEGAUDENC_H__ */ -diff --git a/ext/libav/gstavcfg.c b/ext/libav/gstavcfg.c -index 5ee23dd..1d7c9d7 100644 ---- a/ext/libav/gstavcfg.c -+++ b/ext/libav/gstavcfg.c -@@ -16,8 +16,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - -@@ -147,7 +147,6 @@ gst_ffmpeg_dct_algo_get_type (void) - {FF_DCT_FASTINT, "Fast Integer", "fastint"}, - {FF_DCT_INT, "Accurate Integer", "int"}, - {FF_DCT_MMX, "MMX", "mmx"}, -- {FF_DCT_MLIB, "MLIB", "mlib"}, - {FF_DCT_ALTIVEC, "ALTIVEC", "altivec"}, - {FF_DCT_FAAN, "FAAN", "faan"}, - {0, NULL, NULL}, -@@ -173,8 +172,6 @@ gst_ffmpeg_idct_algo_get_type (void) - {FF_IDCT_SIMPLE, "Simple", "simple"}, - {FF_IDCT_SIMPLEMMX, "Simple MMX", "simplemmx"}, - {FF_IDCT_LIBMPEG2MMX, "LIBMPEG2MMX", "libmpeg2mmx"}, -- {FF_IDCT_PS2, "PS2", "ps2"}, -- {FF_IDCT_MLIB, "MLIB", "mlib"}, - {FF_IDCT_ARM, "ARM", "arm"}, - {FF_IDCT_ALTIVEC, "ALTIVEC", "altivec"}, - {FF_IDCT_SH4, "SH4", "sh4"}, -@@ -263,16 +260,11 @@ gst_ffmpeg_flags_get_type (void) - - if (!ffmpeg_flags_type) { - static const GFlagsValue ffmpeg_flags[] = { -- {CODEC_FLAG_OBMC, "Use overlapped block motion compensation (h263+)", -- "obmc"}, - {CODEC_FLAG_QSCALE, "Use fixed qscale", "qscale"}, - {CODEC_FLAG_4MV, "Allow 4 MV per MB", "4mv"}, -- {CODEC_FLAG_H263P_AIV, "H.263 alternative inter VLC", "aiv"}, - {CODEC_FLAG_QPEL, "Quartel Pel Motion Compensation", "qpel"}, - {CODEC_FLAG_GMC, "GMC", "gmc"}, - {CODEC_FLAG_MV0, "Always try a MB with MV (0,0)", "mv0"}, -- {CODEC_FLAG_PART, -- "Store MV, DC and AC coefficients in seperate partitions", "part"}, - {CODEC_FLAG_LOOP_FILTER, "Loop filter", "loop-filter"}, - {CODEC_FLAG_GRAY, "Only decode/encode grayscale", "gray"}, - {CODEC_FLAG_NORMALIZE_AQP, -@@ -282,13 +274,9 @@ gst_ffmpeg_flags_get_type (void) - "global-headers"}, - {CODEC_FLAG_AC_PRED, "H263 Advanced Intra Coding / MPEG4 AC prediction", - "aic"}, -- {CODEC_FLAG_H263P_UMV, "Unlimited Motion Vector", "umv"}, - {CODEC_FLAG_CBP_RD, "Rate Distoration Optimization for CBP", "cbp-rd"}, - {CODEC_FLAG_QP_RD, "Rate Distoration Optimization for QP selection", - "qp-rd"}, -- {CODEC_FLAG_H263P_SLICE_STRUCT, "H263 slice struct", "ss"}, -- {CODEC_FLAG_SVCD_SCAN_OFFSET, -- "Reserve space for SVCD scan offset user data", "scanoffset"}, - {CODEC_FLAG_CLOSED_GOP, "Closed GOP", "closedgop"}, - {0, NULL, NULL}, - }; -@@ -750,10 +738,8 @@ gst_ffmpeg_cfg_install_property (GstFFMpegVidEncClass * klass, guint base) - prop_id = base; - g_return_if_fail (base > 0); - -- ctx = avcodec_alloc_context (); -- if (ctx) -- avcodec_get_context_defaults (ctx); -- else -+ ctx = avcodec_alloc_context3 (klass->in_plugin); -+ if (!ctx) - g_warning ("could not get context"); - - for (list = property_list; list; list = list->next) { -diff --git a/ext/libav/gstavcfg.h b/ext/libav/gstavcfg.h -index 5251eb2..2aef665 100644 ---- a/ext/libav/gstavcfg.h -+++ b/ext/libav/gstavcfg.h -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - -diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c -index 7b28800..cac15ee 100644 ---- a/ext/libav/gstavcodecmap.c -+++ b/ext/libav/gstavcodecmap.c -@@ -15,8 +15,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -27,6 +27,7 @@ - - #include <gst/gst.h> - #include <libavcodec/avcodec.h> -+#include <libavutil/channel_layout.h> - - #include "gstav.h" - #include "gstavcodecmap.h" -@@ -35,44 +36,6 @@ - #include <gst/audio/audio.h> - #include <gst/pbutils/codec-utils.h> - --/* -- * Read a palette from a caps. -- */ -- --static void --gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context) --{ -- GstStructure *str = gst_caps_get_structure (caps, 0); -- const GValue *palette_v; -- GstBuffer *palette; -- -- /* do we have a palette? */ -- if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) { -- palette = gst_value_get_buffer (palette_v); -- GST_DEBUG ("got palette data %p", palette); -- if (gst_buffer_get_size (palette) >= AVPALETTE_SIZE) { -- if (context->palctrl) -- av_free (context->palctrl); -- context->palctrl = av_malloc (sizeof (AVPaletteControl)); -- context->palctrl->palette_changed = 1; -- gst_buffer_extract (palette, 0, context->palctrl->palette, -- AVPALETTE_SIZE); -- GST_DEBUG ("extracted palette data"); -- } -- } --} -- --static void --gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context) --{ -- if (context->palctrl) { -- GstBuffer *palette = gst_buffer_new_and_alloc (AVPALETTE_SIZE); -- -- gst_buffer_fill (palette, 0, context->palctrl->palette, AVPALETTE_SIZE); -- gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL); -- } --} -- - /* IMPORTANT: Keep this sorted by the ffmpeg channel masks */ - static const struct - { -@@ -80,34 +43,60 @@ static const struct - GstAudioChannelPosition gst; - } _ff_to_gst_layout[] = { - { -- CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { -- CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { -- CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { -- CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1}, { -- CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { -- CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { -- CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { -- CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { -- CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { -- CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { -- CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { -- CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_CENTER}, { -- CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT}, { -- CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER}, { -- CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT}, { -- CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT}, { -- CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER}, { -- CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT}, { -- CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { -- CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} -+ AV_CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { -+ AV_CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { -+ AV_CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { -+ AV_CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1}, { -+ AV_CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { -+ AV_CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { -+ AV_CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { -+ AV_CH_FRONT_RIGHT_OF_CENTER, -+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { -+ AV_CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { -+ AV_CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { -+ AV_CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { -+ AV_CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_CENTER}, { -+ AV_CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT}, { -+ AV_CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER}, { -+ AV_CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT}, { -+ AV_CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT}, { -+ AV_CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER}, { -+ AV_CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT}, { -+ AV_CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { -+ AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} - }; - -+static guint64 -+gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos, -+ gint channels) -+{ -+ gint i, j; -+ guint64 ret = 0; -+ gint channels_found = 0; -+ -+ if (!pos) -+ return 0; -+ -+ for (i = 0; i < channels; i++) { -+ for (j = 0; j < G_N_ELEMENTS (_ff_to_gst_layout); j++) { -+ if (_ff_to_gst_layout[j].gst == pos[i]) { -+ ret |= _ff_to_gst_layout[j].ff; -+ channels_found++; -+ break; -+ } -+ } -+ } -+ -+ if (channels_found != channels) -+ return 0; -+ return ret; -+} -+ - gboolean --gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, -+gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels, - GstAudioChannelPosition * pos) - { -- guint nchannels = 0, channels = context->channels; -- guint64 channel_layout = context->channel_layout; -+ guint nchannels = 0; - gboolean none_layout = FALSE; - - if (channel_layout == 0) { -@@ -170,6 +159,52 @@ gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, - return TRUE; - } - -+static void -+gst_ffmpeg_video_set_pix_fmts (GstCaps * caps, const enum AVPixelFormat *fmts) -+{ -+ GValue va = { 0, }; -+ GValue v = { 0, }; -+ GstVideoFormat format; -+ -+ if (!fmts || fmts[0] == -1) { -+ gint i; -+ -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, G_TYPE_STRING); -+ for (i = 0; i <= PIX_FMT_NB; i++) { -+ format = gst_ffmpeg_pixfmt_to_videoformat (i); -+ if (format == GST_VIDEO_FORMAT_UNKNOWN) -+ continue; -+ g_value_set_string (&v, gst_video_format_to_string (format)); -+ gst_value_list_append_value (&va, &v); -+ } -+ gst_caps_set_value (caps, "format", &va); -+ g_value_unset (&v); -+ g_value_unset (&va); -+ return; -+ } -+ -+ /* Only a single format */ -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, G_TYPE_STRING); -+ while (*fmts != -1) { -+ format = gst_ffmpeg_pixfmt_to_videoformat (*fmts); -+ if (format != GST_VIDEO_FORMAT_UNKNOWN) { -+ g_value_set_string (&v, gst_video_format_to_string (format)); -+ gst_value_list_append_value (&va, &v); -+ } -+ fmts++; -+ } -+ if (gst_value_list_get_size (&va) == 1) { -+ /* The single value is still in v */ -+ gst_caps_set_value (caps, "format", &v); -+ } else if (gst_value_list_get_size (&va) > 1) { -+ gst_caps_set_value (caps, "format", &va); -+ } -+ g_value_unset (&v); -+ g_value_unset (&va); -+} -+ - /* this macro makes a caps width fixed or unfixed width/height - * properties depending on whether we've got a context. - * -@@ -179,10 +214,10 @@ gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, - * but I'm too lazy today. Maybe later. - */ - static GstCaps * --gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, -- gboolean encode, const char *mimetype, const char *fieldname, ...) -+gst_ff_vid_caps_new (AVCodecContext * context, AVCodec * codec, -+ enum CodecID codec_id, gboolean encode, const char *mimetype, -+ const char *fieldname, ...) - { -- GstStructure *structure = NULL; - GstCaps *caps = NULL; - va_list var_args; - gint i; -@@ -252,32 +287,58 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, - { - static struct - { -- guint32 csp; -+ const gchar *csp; - gint width, height; - gint par_n, par_d; - gint framerate_n, framerate_d; - } profiles[] = { - { -- GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 10, 11, 30000, 1001}, { -- GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 40, 33, 30000, 1001}, { -- GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 59, 54, 25, 1}, { -- GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 118, 81, 25, 1}, { -- GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 59, 54, 25, 1}, { -- GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 118, 81, 25, 1} -- }; -+ "Y41B", 720, 480, 8, 9, 30000, 1001}, { -+ "Y41B", 720, 480, 32, 27, 30000, 1001}, { -+ "Y42B", 720, 480, 8, 9, 30000, 1001}, { -+ "Y42B", 720, 480, 32, 27, 30000, 1001}, { -+ "I420", 720, 576, 16, 15, 25, 1}, { -+ "I420", 720, 576, 64, 45, 25, 1}, { -+ "Y41B", 720, 576, 16, 15, 25, 1}, { -+ "Y41B", 720, 576, 64, 45, 25, 1}, { -+ "Y42B", 720, 576, 16, 15, 25, 1}, { -+ "Y42B", 720, 576, 64, 45, 25, 1}, { -+ "Y42B", 1280, 1080, 1, 1, 30000, 1001}, { -+ "Y42B", 1280, 1080, 3, 2, 30000, 1001}, { -+ "Y42B", 1440, 1080, 1, 1, 25, 1}, { -+ "Y42B", 1440, 1080, 4, 3, 25, 1}, { -+ "Y42B", 960, 720, 1, 1, 60000, 1001}, { -+ "Y42B", 960, 720, 4, 3, 60000, 1001}, { -+ "Y42B", 960, 720, 1, 1, 50, 1}, { -+ "Y42B", 960, 720, 4, 3, 50, 1},}; - GstCaps *temp; - gint n_sizes = G_N_ELEMENTS (profiles); - -- caps = gst_caps_new_empty (); -- for (i = 0; i < n_sizes; i++) { -- temp = gst_caps_new_simple (mimetype, -- "width", G_TYPE_INT, profiles[i].width, -- "height", G_TYPE_INT, profiles[i].height, -- "framerate", GST_TYPE_FRACTION, profiles[i].framerate_n, -- profiles[i].framerate_d, "pixel-aspect-ratio", GST_TYPE_FRACTION, -- profiles[i].par_n, profiles[i].par_d, NULL); -- -- gst_caps_append (caps, temp); -+ if (strcmp (mimetype, "video/x-raw") == 0) { -+ caps = gst_caps_new_empty (); -+ for (i = 0; i < n_sizes; i++) { -+ temp = gst_caps_new_simple (mimetype, -+ "format", G_TYPE_STRING, profiles[i].csp, -+ "width", G_TYPE_INT, profiles[i].width, -+ "height", G_TYPE_INT, profiles[i].height, -+ "framerate", GST_TYPE_FRACTION, profiles[i].framerate_n, -+ profiles[i].framerate_d, "pixel-aspect-ratio", -+ GST_TYPE_FRACTION, profiles[i].par_n, profiles[i].par_d, NULL); -+ -+ gst_caps_append (caps, temp); -+ } -+ } else { -+ caps = gst_caps_new_empty (); -+ for (i = 0; i < n_sizes; i++) { -+ temp = gst_caps_new_simple (mimetype, -+ "width", G_TYPE_INT, profiles[i].width, -+ "height", G_TYPE_INT, profiles[i].height, -+ "framerate", GST_TYPE_FRACTION, profiles[i].framerate_n, -+ profiles[i].framerate_d, "pixel-aspect-ratio", -+ GST_TYPE_FRACTION, profiles[i].par_n, profiles[i].par_d, NULL); -+ -+ gst_caps_append (caps, temp); -+ } - } - break; - } -@@ -294,7 +355,40 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, - break; - } - default: -+ { -+ if (codec && codec->supported_framerates -+ && codec->supported_framerates[0].num != 0 -+ && codec->supported_framerates[0].den != 0) { -+ GValue va = { 0, }; -+ GValue v = { 0, }; -+ const AVRational *rates = codec->supported_framerates; -+ -+ if (rates[1].num == 0 && rates[1].den == 0) { -+ caps = -+ gst_caps_new_simple (mimetype, "framerate", GST_TYPE_FRACTION, -+ rates[0].num, rates[0].den, NULL); -+ } else { -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, GST_TYPE_FRACTION); -+ -+ while (rates->num != 0 && rates->den != 0) { -+ gst_value_set_fraction (&v, rates->num, rates->den); -+ gst_value_list_append_value (&va, &v); -+ rates++; -+ } -+ -+ caps = gst_caps_new_simple (mimetype, NULL, NULL, NULL); -+ gst_caps_set_value (caps, "framerate", &va); -+ g_value_unset (&va); -+ g_value_unset (&v); -+ } -+ -+ } else { -+ caps = gst_caps_new_empty_simple (mimetype); -+ } -+ - break; -+ } - } - } - -@@ -302,27 +396,84 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, - * default unfixed setting */ - if (!caps) { - GST_DEBUG ("Creating default caps"); -- caps = gst_caps_new_simple (mimetype, NULL, NULL, NULL); -+ caps = gst_caps_new_empty_simple (mimetype); - } - -- for (i = 0; i < gst_caps_get_size (caps); i++) { -- va_start (var_args, fieldname); -- structure = gst_caps_get_structure (caps, i); -- gst_structure_set_valist (structure, fieldname, var_args); -- va_end (var_args); -- } -+ va_start (var_args, fieldname); -+ gst_caps_set_simple_valist (caps, fieldname, var_args); -+ va_end (var_args); - - return caps; - } - -+static gint -+get_nbits_set (guint64 n) -+{ -+ gint i, x; -+ -+ x = 0; -+ for (i = 0; i < 64; i++) { -+ if ((n & (G_GUINT64_CONSTANT (1) << i))) -+ x++; -+ } -+ -+ return x; -+} -+ -+static void -+gst_ffmpeg_audio_set_sample_fmts (GstCaps * caps, -+ const enum AVSampleFormat *fmts) -+{ -+ GValue va = { 0, }; -+ GValue v = { 0, }; -+ GstAudioFormat format; -+ -+ if (!fmts || fmts[0] == -1) { -+ gint i; -+ -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, G_TYPE_STRING); -+ for (i = 0; i <= AV_SAMPLE_FMT_DBL; i++) { -+ format = gst_ffmpeg_smpfmt_to_audioformat (i); -+ if (format == GST_AUDIO_FORMAT_UNKNOWN) -+ continue; -+ g_value_set_string (&v, gst_audio_format_to_string (format)); -+ gst_value_list_append_value (&va, &v); -+ } -+ gst_caps_set_value (caps, "format", &va); -+ g_value_unset (&v); -+ g_value_unset (&va); -+ return; -+ } -+ -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, G_TYPE_STRING); -+ while (*fmts != -1) { -+ format = gst_ffmpeg_smpfmt_to_audioformat (*fmts); -+ if (format != GST_AUDIO_FORMAT_UNKNOWN) { -+ g_value_set_string (&v, gst_audio_format_to_string (format)); -+ gst_value_list_append_value (&va, &v); -+ } -+ fmts++; -+ } -+ if (gst_value_list_get_size (&va) == 1) { -+ /* The single value is still in v */ -+ gst_caps_set_value (caps, "format", &v); -+ } else if (gst_value_list_get_size (&va) > 1) { -+ gst_caps_set_value (caps, "format", &va); -+ } -+ g_value_unset (&v); -+ g_value_unset (&va); -+} -+ - /* same for audio - now with channels/sample rate - */ - static GstCaps * --gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, -- gboolean encode, const char *mimetype, const char *fieldname, ...) -+gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, -+ enum CodecID codec_id, gboolean encode, const char *mimetype, -+ const char *fieldname, ...) - { - GstCaps *caps = NULL; -- GstStructure *structure = NULL; - gint i; - va_list var_args; - -@@ -334,7 +485,8 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, - "rate", G_TYPE_INT, context->sample_rate, - "channels", G_TYPE_INT, context->channels, NULL); - -- if (gst_ffmpeg_channel_layout_to_gst (context, pos)) { -+ if (gst_ffmpeg_channel_layout_to_gst (context->channel_layout, -+ context->channels, pos)) { - guint64 mask; - - if (gst_audio_channel_positions_to_mask (pos, context->channels, FALSE, -@@ -422,10 +574,6 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, - break; - } - -- /* TODO: handle context->channel_layouts here to set -- * the list of channel layouts supported by the encoder. -- * Unfortunately no encoder uses this yet.... -- */ - /* regardless of encode/decode, open up channels if applicable */ - /* Until decoders/encoders expose the maximum number of channels - * they support, we whitelist them here. */ -@@ -438,15 +586,40 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, - break; - } - -- if (maxchannels == 1) -- caps = gst_caps_new_simple (mimetype, -- "channels", G_TYPE_INT, maxchannels, NULL); -- else -- caps = gst_caps_new_simple (mimetype, -- "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); -+ if (codec && codec->channel_layouts) { -+ const uint64_t *layouts = codec->channel_layouts; -+ GstAudioChannelPosition pos[64]; -+ -+ caps = gst_caps_new_empty (); -+ while (*layouts) { -+ gint nbits_set = get_nbits_set (*layouts); -+ -+ if (gst_ffmpeg_channel_layout_to_gst (*layouts, nbits_set, pos)) { -+ guint64 mask; -+ -+ if (gst_audio_channel_positions_to_mask (pos, nbits_set, FALSE, -+ &mask)) { -+ GstCaps *tmp = -+ gst_caps_new_simple (mimetype, "channel-mask", GST_TYPE_BITMASK, -+ mask, -+ "channels", G_TYPE_INT, nbits_set, NULL); -+ -+ gst_caps_append (caps, tmp); -+ } -+ } -+ layouts++; -+ } -+ } else { -+ if (maxchannels == 1) -+ caps = gst_caps_new_simple (mimetype, -+ "channels", G_TYPE_INT, maxchannels, NULL); -+ else -+ caps = gst_caps_new_simple (mimetype, -+ "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); -+ } -+ - if (n_rates) { - GValue list = { 0, }; -- GstStructure *structure; - - g_value_init (&list, GST_TYPE_LIST); - for (i = 0; i < n_rates; i++) { -@@ -457,21 +630,41 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, - gst_value_list_append_value (&list, &v); - g_value_unset (&v); - } -- structure = gst_caps_get_structure (caps, 0); -- gst_structure_set_value (structure, "rate", &list); -+ gst_caps_set_value (caps, "rate", &list); - g_value_unset (&list); -- } else -+ } else if (codec && codec->supported_samplerates -+ && codec->supported_samplerates[0]) { -+ GValue va = { 0, }; -+ GValue v = { 0, }; -+ -+ if (!codec->supported_samplerates[1]) { -+ gst_caps_set_simple (caps, "rate", G_TYPE_INT, -+ codec->supported_samplerates[0], NULL); -+ } else { -+ const int *rates = codec->supported_samplerates; -+ -+ g_value_init (&va, GST_TYPE_LIST); -+ g_value_init (&v, G_TYPE_INT); -+ -+ while (*rates) { -+ g_value_set_int (&v, *rates); -+ gst_value_list_append_value (&va, &v); -+ rates++; -+ } -+ gst_caps_set_value (caps, "rate", &va); -+ g_value_unset (&va); -+ g_value_unset (&v); -+ } -+ } else { - gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL); -+ } - } else { - caps = gst_caps_new_empty_simple (mimetype); - } - -- for (i = 0; i < gst_caps_get_size (caps); i++) { -- va_start (var_args, fieldname); -- structure = gst_caps_get_structure (caps, i); -- gst_structure_set_valist (structure, fieldname, var_args); -- va_end (var_args); -- } -+ va_start (var_args, fieldname); -+ gst_caps_set_simple_valist (caps, fieldname, var_args); -+ va_end (var_args); - - return caps; - } -@@ -504,7 +697,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - switch (codec_id) { - case CODEC_ID_MPEG1VIDEO: - /* FIXME: bitrate */ -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/mpeg", -+ caps = gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/mpeg", - "mpegversion", G_TYPE_INT, 1, - "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); - break; -@@ -512,9 +705,10 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_MPEG2VIDEO: - if (encode) { - /* FIXME: bitrate */ -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/mpeg", -- "mpegversion", G_TYPE_INT, 2, -- "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/mpeg", -+ "mpegversion", G_TYPE_INT, 2, "systemstream", G_TYPE_BOOLEAN, FALSE, -+ NULL); - } else { - /* decode both MPEG-1 and MPEG-2; width/height/fps are all in - * the MPEG video stream headers, so may be omitted from caps. */ -@@ -530,23 +724,25 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_H263: - if (encode) { -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-h263", -- "variant", G_TYPE_STRING, "itu", -- "h263version", G_TYPE_STRING, "h263", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-h263", "variant", G_TYPE_STRING, "itu", "h263version", -+ G_TYPE_STRING, "h263", NULL); - } else { - /* don't pass codec_id, we can decode other variants with the H263 - * decoder that don't have specific size requirements - */ - caps = -- gst_ff_vid_caps_new (context, CODEC_ID_NONE, encode, "video/x-h263", -- "variant", G_TYPE_STRING, "itu", NULL); -+ gst_ff_vid_caps_new (context, NULL, CODEC_ID_NONE, encode, -+ "video/x-h263", "variant", G_TYPE_STRING, "itu", NULL); - } - break; - - case CODEC_ID_H263P: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-h263", -- "variant", G_TYPE_STRING, "itu", -- "h263version", G_TYPE_STRING, "h263p", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-h263", -+ "variant", G_TYPE_STRING, "itu", "h263version", G_TYPE_STRING, -+ "h263p", NULL); - if (encode && context) { - - gst_caps_set_simple (caps, -@@ -560,13 +756,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_H263I: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-intel-h263", -- "variant", G_TYPE_STRING, "intel", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-intel-h263", "variant", G_TYPE_STRING, "intel", NULL); - break; - - case CODEC_ID_H261: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-h261", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-h261", -+ NULL); - break; - - case CODEC_ID_RV10: -@@ -593,7 +790,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - /* FIXME: context->sub_id must be filled in during decoding */ - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "video/x-pn-realvideo", "systemstream", G_TYPE_BOOLEAN, FALSE, - "rmversion", G_TYPE_INT, version, NULL); - if (context) { -@@ -609,20 +806,21 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_MP1: - /* FIXME: bitrate */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", -+ caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", - "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_MP2: - /* FIXME: bitrate */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", -+ caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", - "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL); - break; - - case CODEC_ID_MP3: - if (encode) { - /* FIXME: bitrate */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", - "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL); - } else { - /* Decodes MPEG-1 layer 1/2/3. Samplerate, channels et al are -@@ -635,14 +833,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_MUSEPACK7: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 7, - NULL); - break; - - case CODEC_ID_MUSEPACK8: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 8, - NULL); - break; -@@ -650,41 +848,44 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_AC3: - /* FIXME: bitrate */ - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-ac3", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-ac3", -+ NULL); - break; - - case CODEC_ID_EAC3: - /* FIXME: bitrate */ - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-eac3", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-eac3", -+ NULL); - break; - - case CODEC_ID_TRUEHD: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-true-hd", -- NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, -+ "audio/x-true-hd", NULL); - break; - - case CODEC_ID_ATRAC1: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-vnd.sony.atrac1", NULL); - break; - - case CODEC_ID_ATRAC3: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-vnd.sony.atrac3", NULL); - break; - - case CODEC_ID_DTS: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dts", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dts", -+ NULL); - break; - - case CODEC_ID_APE: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-ffmpeg-parsed-ape", NULL); - if (context) { - gst_caps_set_simple (caps, -@@ -694,12 +895,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_MLP: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mlp", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mlp", -+ NULL); - break; - - case CODEC_ID_IMC: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-imc", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-imc", -+ NULL); - break; - - /* MJPEG is normal JPEG, Motion-JPEG and Quicktime MJPEG-A. MJPEGB -@@ -710,18 +913,20 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_MJPEG: - case CODEC_ID_LJPEG: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/jpeg", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/jpeg", -+ NULL); - break; - - case CODEC_ID_SP5X: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/sp5x", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/sp5x", -+ NULL); - break; - - case CODEC_ID_MJPEGB: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-mjpeg-b", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-mjpeg-b", NULL); - break; - - case CODEC_ID_MPEG4: -@@ -731,41 +936,42 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - switch (context->codec_tag) { - case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'): - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-divx", -- "divxversion", G_TYPE_INT, 5, NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-divx", "divxversion", G_TYPE_INT, 5, NULL); - break; - case GST_MAKE_FOURCC ('m', 'p', '4', 'v'): - default: - /* FIXME: bitrate */ -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/mpeg", -- "systemstream", G_TYPE_BOOLEAN, FALSE, -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/mpeg", "systemstream", G_TYPE_BOOLEAN, FALSE, - "mpegversion", G_TYPE_INT, 4, NULL); - break; - } - } else { - /* The trick here is to separate xvid, divx, mpeg4, 3ivx et al */ -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/mpeg", -- "mpegversion", G_TYPE_INT, 4, -- "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/mpeg", -+ "mpegversion", G_TYPE_INT, 4, "systemstream", G_TYPE_BOOLEAN, FALSE, -+ NULL); - if (encode) { -- gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id, encode, -- "video/x-divx", "divxversion", G_TYPE_INT, 5, NULL)); -+ gst_caps_append (caps, gst_ff_vid_caps_new (context, NULL, codec_id, -+ encode, "video/x-divx", "divxversion", G_TYPE_INT, 5, NULL)); - } else { -- gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id, encode, -- "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, -- NULL)); -- gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id, encode, -- "video/x-xvid", NULL)); -- gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id, encode, -- "video/x-3ivx", NULL)); -+ gst_caps_append (caps, gst_ff_vid_caps_new (context, NULL, codec_id, -+ encode, "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, -+ 5, NULL)); -+ gst_caps_append (caps, gst_ff_vid_caps_new (context, NULL, codec_id, -+ encode, "video/x-xvid", NULL)); -+ gst_caps_append (caps, gst_ff_vid_caps_new (context, NULL, codec_id, -+ encode, "video/x-3ivx", NULL)); - } - } - break; - - case CODEC_ID_RAWVIDEO: - caps = -- gst_ffmpeg_codectype_to_caps (AVMEDIA_TYPE_VIDEO, context, codec_id, -- encode); -+ gst_ffmpeg_codectype_to_video_caps (context, codec_id, encode, NULL); - break; - - case CODEC_ID_MSMPEG4V1: -@@ -775,11 +981,12 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - gint version = 41 + codec_id - CODEC_ID_MSMPEG4V1; - - /* encode-FIXME: bitrate */ -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-msmpeg", -- "msmpegversion", G_TYPE_INT, version, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-msmpeg", "msmpegversion", G_TYPE_INT, version, NULL); - if (!encode && codec_id == CODEC_ID_MSMPEG4V3) { -- gst_caps_append (caps, gst_ff_vid_caps_new (context, codec_id, encode, -- "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL)); -+ gst_caps_append (caps, gst_ff_vid_caps_new (context, NULL, codec_id, -+ encode, "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL)); - } - } - break; -@@ -789,30 +996,34 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - { - gint version = (codec_id == CODEC_ID_WMV1) ? 1 : 2; - -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-wmv", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-wmv", - "wmvversion", G_TYPE_INT, version, NULL); - } - break; - - case CODEC_ID_FLV1: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-flash-video", -- "flvversion", G_TYPE_INT, 1, NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-flash-video", "flvversion", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_SVQ1: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-svq", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-svq", - "svqversion", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_SVQ3: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-svq", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-svq", - "svqversion", G_TYPE_INT, 3, NULL); - break; - - case CODEC_ID_DVAUDIO: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dv", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dv", -+ NULL); - break; - - case CODEC_ID_DVVIDEO: -@@ -846,11 +1057,13 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - format = "I420"; - break; - } -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-dv", -- "systemstream", G_TYPE_BOOLEAN, FALSE, -- "format", G_TYPE_STRING, format, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-dv", -+ "systemstream", G_TYPE_BOOLEAN, FALSE, "format", G_TYPE_STRING, -+ format, NULL); - } else { -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-dv", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-dv", - "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); - } - } -@@ -862,21 +1075,24 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - gint version = (codec_id == CODEC_ID_WMAV1) ? 1 : 2; - - if (context) { -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", -- "wmaversion", G_TYPE_INT, version, -- "block_align", G_TYPE_INT, context->block_align, -- "bitrate", G_TYPE_INT, context->bit_rate, NULL); -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", -+ "wmaversion", G_TYPE_INT, version, "block_align", G_TYPE_INT, -+ context->block_align, "bitrate", G_TYPE_INT, context->bit_rate, -+ NULL); - } else { -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", -- "wmaversion", G_TYPE_INT, version, -- "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT, -- "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL); -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", -+ "wmaversion", G_TYPE_INT, version, "block_align", -+ GST_TYPE_INT_RANGE, 0, G_MAXINT, "bitrate", GST_TYPE_INT_RANGE, 0, -+ G_MAXINT, NULL); - } - } - break; - case CODEC_ID_WMAPRO: - { -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", - "wmaversion", G_TYPE_INT, 3, NULL); - break; - } -@@ -884,7 +1100,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_WMAVOICE: - { - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wms", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wms", -+ NULL); - break; - } - -@@ -893,15 +1110,16 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - { - gint version = (codec_id == CODEC_ID_MACE3) ? 3 : 6; - -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mace", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mace", - "maceversion", G_TYPE_INT, version, NULL); - } - break; - - case CODEC_ID_HUFFYUV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-huffyuv", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-huffyuv", NULL); - if (context) { - gst_caps_set_simple (caps, - "bpp", G_TYPE_INT, context->bits_per_coded_sample, NULL); -@@ -910,84 +1128,93 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_CYUV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "video/x-compressed-yuv", NULL); - break; - - case CODEC_ID_H264: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-h264", -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-h264", - "alignment", G_TYPE_STRING, "au", NULL); - break; - - case CODEC_ID_INDEO5: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-indeo", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-indeo", - "indeoversion", G_TYPE_INT, 5, NULL); - break; - - case CODEC_ID_INDEO4: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-indeo", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-indeo", - "indeoversion", G_TYPE_INT, 4, NULL); - break; - - case CODEC_ID_INDEO3: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-indeo", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-indeo", - "indeoversion", G_TYPE_INT, 3, NULL); - break; - - case CODEC_ID_INDEO2: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-indeo", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-indeo", - "indeoversion", G_TYPE_INT, 2, NULL); - break; - - case CODEC_ID_FLASHSV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "video/x-flash-screen", NULL); - break; - - case CODEC_ID_VP3: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp3", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-vp3", -+ NULL); - break; - - case CODEC_ID_VP5: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp5", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-vp5", -+ NULL); - break; - - case CODEC_ID_VP6: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp6", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-vp6", -+ NULL); - break; - - case CODEC_ID_VP6F: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp6-flash", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-vp6-flash", NULL); - break; - - case CODEC_ID_VP6A: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp6-alpha", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-vp6-alpha", NULL); - break; - - case CODEC_ID_VP8: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vp8", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-vp8", -+ NULL); - break; - - case CODEC_ID_THEORA: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-theora", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-theora", NULL); - break; - - case CODEC_ID_AAC: - { - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", -+ NULL); - - if (!encode) { - GValue arr = { 0, }; -@@ -1029,45 +1256,50 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - } - case CODEC_ID_AAC_LATM: /* LATM/LOAS AAC syntax */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", -+ caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", - "mpegversion", G_TYPE_INT, 4, "stream-format", G_TYPE_STRING, "loas", - NULL); - break; - - case CODEC_ID_ASV1: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-asus", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-asus", - "asusversion", G_TYPE_INT, 1, NULL); - break; - case CODEC_ID_ASV2: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-asus", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-asus", - "asusversion", G_TYPE_INT, 2, NULL); - break; - - case CODEC_ID_FFV1: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-ffv", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-ffv", - "ffvversion", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_4XM: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-4xm", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-4xm", -+ NULL); - break; - - case CODEC_ID_XAN_WC3: - case CODEC_ID_XAN_WC4: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-xan", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-xan", - "wcversion", G_TYPE_INT, 3 - CODEC_ID_XAN_WC3 + codec_id, NULL); - break; - - case CODEC_ID_CLJR: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "video/x-cirrus-logic-accupak", NULL); - break; - - case CODEC_ID_FRAPS: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-fraps", -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-fraps", - NULL); - break; - -@@ -1078,26 +1310,28 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - - case CODEC_ID_VCR1: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-ati-vcr", -- "vcrversion", G_TYPE_INT, 1, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-ati-vcr", "vcrversion", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_RPZA: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-apple-video", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-apple-video", NULL); - break; - - case CODEC_ID_CINEPAK: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-cinepak", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-cinepak", NULL); - break; - - /* WS_VQA belogns here (order) */ - - case CODEC_ID_MSRLE: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-rle", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-rle", - "layout", G_TYPE_STRING, "microsoft", NULL); - if (context) { - gst_caps_set_simple (caps, -@@ -1108,7 +1342,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - - case CODEC_ID_QTRLE: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-rle", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-rle", - "layout", G_TYPE_STRING, "quicktime", NULL); - if (context) { - gst_caps_set_simple (caps, -@@ -1120,54 +1355,59 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_MSVIDEO1: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "video/x-msvideocodec", "msvideoversion", G_TYPE_INT, 1, NULL); - break; - - case CODEC_ID_WMV3: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-wmv", -- "wmvversion", G_TYPE_INT, 3, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-wmv", -+ "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WMV3", NULL); - break; - case CODEC_ID_VC1: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "video/x-wmv", -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-wmv", - "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL); - break; - case CODEC_ID_QDM2: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-qdm2", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-qdm2", -+ NULL); - break; - - case CODEC_ID_MSZH: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-mszh", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-mszh", -+ NULL); - break; - - case CODEC_ID_ZLIB: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-zlib", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-zlib", -+ NULL); - break; - - case CODEC_ID_TRUEMOTION1: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-truemotion", -- "trueversion", G_TYPE_INT, 1, NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-truemotion", "trueversion", G_TYPE_INT, 1, NULL); - break; - case CODEC_ID_TRUEMOTION2: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-truemotion", -- "trueversion", G_TYPE_INT, 2, NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-truemotion", "trueversion", G_TYPE_INT, 2, NULL); - break; - - case CODEC_ID_ULTI: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-ultimotion", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-ultimotion", NULL); - break; - - case CODEC_ID_TSCC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-camtasia", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-camtasia", NULL); - if (context) { - gst_caps_set_simple (caps, - "depth", G_TYPE_INT, (gint) context->bits_per_coded_sample, NULL); -@@ -1178,142 +1418,164 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_KMVC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-kmvc", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-kmvc", -+ NULL); - break; - - case CODEC_ID_NUV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-nuv", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-nuv", -+ NULL); - break; - - case CODEC_ID_GIF: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "image/gif", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/gif", -+ NULL); - break; - - case CODEC_ID_PNG: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "image/png", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/png", -+ NULL); - break; - - case CODEC_ID_PPM: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "image/ppm", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/ppm", -+ NULL); - break; - - case CODEC_ID_PBM: -- caps = gst_ff_vid_caps_new (context, codec_id, encode, "image/pbm", NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/pbm", -+ NULL); - break; - - case CODEC_ID_PAM: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "image/x-portable-anymap", NULL); - break; - - case CODEC_ID_PGM: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, - "image/x-portable-graymap", NULL); - break; - - case CODEC_ID_PCX: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/x-pcx", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/x-pcx", -+ NULL); - break; - - case CODEC_ID_SGI: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/x-sgi", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/x-sgi", -+ NULL); - break; - - case CODEC_ID_TARGA: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/x-tga", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/x-tga", -+ NULL); - break; - - case CODEC_ID_TIFF: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/tiff", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "image/tiff", -+ NULL); - break; - - case CODEC_ID_SUNRAST: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "image/x-sun-raster", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "image/x-sun-raster", NULL); - break; - - case CODEC_ID_SMC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-smc", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-smc", -+ NULL); - break; - - case CODEC_ID_QDRAW: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-qdrw", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-qdrw", -+ NULL); - break; - - case CODEC_ID_DNXHD: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-dnxhd", -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-dnxhd", - NULL); - break; - - case CODEC_ID_PRORES: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-prores", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-prores", NULL); - break; - - case CODEC_ID_MIMIC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-mimic", -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-mimic", - NULL); - break; - - case CODEC_ID_VMNC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-vmnc", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-vmnc", -+ NULL); - break; - - case CODEC_ID_TRUESPEECH: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-truespeech", -- NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, -+ "audio/x-truespeech", NULL); - break; - - case CODEC_ID_QCELP: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/qcelp", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/qcelp", -+ NULL); - break; - - case CODEC_ID_AMV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-amv", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-amv", -+ NULL); - break; - - case CODEC_ID_AASC: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-aasc", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-aasc", -+ NULL); - break; - - case CODEC_ID_LOCO: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-loco", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-loco", -+ NULL); - break; - - case CODEC_ID_ZMBV: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-zmbv", NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, "video/x-zmbv", -+ NULL); - break; - - case CODEC_ID_LAGARITH: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-lagarith", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-lagarith", NULL); - break; - - case CODEC_ID_CSCD: - caps = -- gst_ff_vid_caps_new (context, codec_id, encode, "video/x-camstudio", -- NULL); -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, -+ "video/x-camstudio", NULL); - if (context) { - gst_caps_set_simple (caps, - "depth", G_TYPE_INT, (gint) context->bits_per_coded_sample, NULL); -@@ -1328,8 +1590,6 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_FLIC: - case CODEC_ID_VMDVIDEO: - case CODEC_ID_VMDAUDIO: -- case CODEC_ID_SONIC: -- case CODEC_ID_SONIC_LS: - case CODEC_ID_SNOW: - case CODEC_ID_VIXL: - case CODEC_ID_QPEG: -@@ -1379,7 +1639,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - } - -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-raw", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-raw", - "format", G_TYPE_STRING, gst_audio_format_to_string (format), - "layout", G_TYPE_STRING, "interleaved", NULL); - } -@@ -1387,18 +1648,20 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_PCM_MULAW: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mulaw", -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mulaw", - NULL); - break; - - case CODEC_ID_PCM_ALAW: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-alaw", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-alaw", -+ NULL); - break; - - case CODEC_ID_ADPCM_G722: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/G722", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/G722", -+ NULL); - if (context) - gst_caps_set_simple (caps, - "block_align", G_TYPE_INT, context->block_align, -@@ -1408,7 +1671,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - case CODEC_ID_ADPCM_G726: - { - /* the G726 decoder can also handle G721 */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-adpcm", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-adpcm", - "layout", G_TYPE_STRING, "g726", NULL); - if (context) - gst_caps_set_simple (caps, -@@ -1541,7 +1805,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - /* FIXME: someone please check whether we need additional properties - * in this caps definition. */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-adpcm", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-adpcm", - "layout", G_TYPE_STRING, layout, NULL); - if (context) - gst_caps_set_simple (caps, -@@ -1551,34 +1816,39 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - - case CODEC_ID_AMR_NB: -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/AMR", NULL); -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/AMR", -+ NULL); - break; - - case CODEC_ID_AMR_WB: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/AMR-WB", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/AMR-WB", -+ NULL); - break; - - case CODEC_ID_GSM: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-gsm", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-gsm", -+ NULL); - break; - - case CODEC_ID_GSM_MS: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/ms-gsm", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/ms-gsm", -+ NULL); - break; - - case CODEC_ID_NELLYMOSER: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-nellymoser", -- NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, -+ "audio/x-nellymoser", NULL); - break; - - case CODEC_ID_SIPR: - { - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-sipro", -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-sipro", - NULL); - if (context) { - gst_caps_set_simple (caps, -@@ -1610,7 +1880,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - /* FIXME: properties? */ - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, - "audio/x-pn-realaudio", "raversion", G_TYPE_INT, version, NULL); - if (context) { - gst_caps_set_simple (caps, -@@ -1647,7 +1917,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - /* FIXME: someone please check whether we need additional properties - * in this caps definition. */ -- caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dpcm", -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dpcm", - "layout", G_TYPE_STRING, layout, NULL); - if (context) - gst_caps_set_simple (caps, -@@ -1662,7 +1933,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - - case CODEC_ID_ALAC: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-alac", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-alac", -+ NULL); - if (context) { - gst_caps_set_simple (caps, - "samplesize", G_TYPE_INT, context->bits_per_coded_sample, NULL); -@@ -1677,6 +1949,10 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - } - break; - -+ case CODEC_ID_S302M: -+ caps = gst_caps_new_empty_simple ("audio/x-smpte-302m"); -+ break; -+ - case CODEC_ID_DVD_SUBTITLE: - case CODEC_ID_DVB_SUBTITLE: - caps = NULL; -@@ -1686,7 +1962,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - case CODEC_ID_TTA: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-tta", NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-tta", -+ NULL); - if (context) { - gst_caps_set_simple (caps, - "samplesize", G_TYPE_INT, context->bits_per_coded_sample, NULL); -@@ -1694,8 +1971,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - break; - case CODEC_ID_TWINVQ: - caps = -- gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-twin-vq", -- NULL); -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, -+ "audio/x-twin-vq", NULL); - break; - default: - GST_DEBUG ("Unknown codec ID %d, please add mapping here", codec_id); -@@ -1714,12 +1991,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - switch (codec->type) { - case AVMEDIA_TYPE_VIDEO: - mime = g_strdup_printf ("video/x-gst-av-%s", codec->name); -- caps = gst_ff_vid_caps_new (context, codec_id, encode, mime, NULL); -+ caps = -+ gst_ff_vid_caps_new (context, NULL, codec_id, encode, mime, NULL); - g_free (mime); - break; - case AVMEDIA_TYPE_AUDIO: - mime = g_strdup_printf ("audio/x-gst-av-%s", codec->name); -- caps = gst_ff_aud_caps_new (context, codec_id, encode, mime, NULL); -+ caps = -+ gst_ff_aud_caps_new (context, NULL, codec_id, encode, mime, NULL); - if (context) - gst_caps_set_simple (caps, - "block_align", G_TYPE_INT, context->block_align, -@@ -1743,11 +2022,6 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - gst_buffer_unref (data); - } - -- /* palette */ -- if (context) { -- gst_ffmpeg_set_palette (caps, context); -- } -- - GST_LOG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps); - - } else { -@@ -1764,7 +2038,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - * See below for usefullness - */ - --GstCaps * -+static GstCaps * - gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, - enum CodecID codec_id) - { -@@ -1774,7 +2048,7 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, - format = gst_ffmpeg_pixfmt_to_videoformat (pix_fmt); - - if (format != GST_VIDEO_FORMAT_UNKNOWN) { -- caps = gst_ff_vid_caps_new (context, codec_id, TRUE, "video/x-raw", -+ caps = gst_ff_vid_caps_new (context, NULL, codec_id, TRUE, "video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL); - } - -@@ -1787,41 +2061,55 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, - return caps; - } - --/* Convert a FFMPEG Sample Format and optional AVCodecContext -- * to a GstCaps. If the context is ommitted, no fixed values -- * for video/audio size will be included in the GstCaps -- * -- * See below for usefullness -- */ -- --static GstCaps * --gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, -- AVCodecContext * context, enum CodecID codec_id) -+GstAudioFormat -+gst_ffmpeg_smpfmt_to_audioformat (enum AVSampleFormat sample_fmt) - { -- GstCaps *caps = NULL; -- GstAudioFormat format; -- - switch (sample_fmt) { -+ case AV_SAMPLE_FMT_U8: -+ case AV_SAMPLE_FMT_U8P: -+ return GST_AUDIO_FORMAT_U8; -+ break; - case AV_SAMPLE_FMT_S16: -- format = GST_AUDIO_FORMAT_S16; -+ case AV_SAMPLE_FMT_S16P: -+ return GST_AUDIO_FORMAT_S16; - break; - case AV_SAMPLE_FMT_S32: -- format = GST_AUDIO_FORMAT_S32; -+ case AV_SAMPLE_FMT_S32P: -+ return GST_AUDIO_FORMAT_S32; - break; - case AV_SAMPLE_FMT_FLT: -- format = GST_AUDIO_FORMAT_F32; -+ case AV_SAMPLE_FMT_FLTP: -+ return GST_AUDIO_FORMAT_F32; - break; - case AV_SAMPLE_FMT_DBL: -- format = GST_AUDIO_FORMAT_F64; -+ case AV_SAMPLE_FMT_DBLP: -+ return GST_AUDIO_FORMAT_F64; - break; - default: - /* .. */ -- format = GST_AUDIO_FORMAT_UNKNOWN; -+ return GST_AUDIO_FORMAT_UNKNOWN; - break; - } -+} -+ -+/* Convert a FFMPEG Sample Format and optional AVCodecContext -+ * to a GstCaps. If the context is ommitted, no fixed values -+ * for video/audio size will be included in the GstCaps -+ * -+ * See below for usefullness -+ */ -+ -+static GstCaps * -+gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, -+ AVCodecContext * context, AVCodec * codec, enum CodecID codec_id) -+{ -+ GstCaps *caps = NULL; -+ GstAudioFormat format; -+ -+ format = gst_ffmpeg_smpfmt_to_audioformat (sample_fmt); - - if (format != GST_AUDIO_FORMAT_UNKNOWN) { -- caps = gst_ff_aud_caps_new (context, codec_id, TRUE, "audio/x-raw", -+ caps = gst_ff_aud_caps_new (context, codec, codec_id, TRUE, "audio/x-raw", - "format", G_TYPE_STRING, gst_audio_format_to_string (format), - "layout", G_TYPE_STRING, "interleaved", NULL); - GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps); -@@ -1832,6 +2120,22 @@ gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, - return caps; - } - -+static gboolean -+caps_has_field (GstCaps * caps, const gchar * field) -+{ -+ guint i, n; -+ -+ n = gst_caps_get_size (caps); -+ for (i = 0; i < n; i++) { -+ GstStructure *s = gst_caps_get_structure (caps, i); -+ -+ if (gst_structure_has_field (s, field)) -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ - GstCaps * - gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context, - enum CodecID codec_id, gboolean encode, AVCodec * codec) -@@ -1846,32 +2150,17 @@ gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context, - - if (context) { - /* Specific codec context */ -- caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec_id); -- } else if (codec && codec->sample_fmts) { -- GstCaps *temp; -- int i; -- -- caps = gst_caps_new_empty (); -- for (i = 0; codec->sample_fmts[i] != -1; i++) { -- temp = -- gst_ffmpeg_smpfmt_to_caps (codec->sample_fmts[i], context, codec_id); -- if (temp != NULL) -- gst_caps_append (caps, temp); -- } -+ caps = -+ gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec, -+ codec_id); - } else { -- GstCaps *temp; -- enum AVSampleFormat i; -- AVCodecContext ctx = { 0, }; -- -- ctx.channels = -1; -- caps = gst_caps_new_empty (); -- for (i = 0; i <= AV_SAMPLE_FMT_DBL; i++) { -- temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id); -- if (temp != NULL) { -- gst_caps_append (caps, temp); -- } -- } -+ caps = gst_ff_aud_caps_new (context, codec, codec_id, encode, "audio/x-raw", -+ "layout", G_TYPE_STRING, "interleaved", NULL); -+ if (!caps_has_field (caps, "format")) -+ gst_ffmpeg_audio_set_sample_fmts (caps, -+ codec ? codec->sample_fmts : NULL); - } -+ - return caps; - } - -@@ -1887,50 +2176,12 @@ gst_ffmpeg_codectype_to_video_caps (AVCodecContext * context, - if (context) { - caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, context, codec_id); - } else { -- GstCaps *temp; -- enum PixelFormat i; -- AVCodecContext ctx = { 0, }; -- -- caps = gst_caps_new_empty (); -- for (i = 0; i < PIX_FMT_NB; i++) { -- ctx.width = -1; -- ctx.pix_fmt = i; -- temp = gst_ffmpeg_pixfmt_to_caps (i, encode ? &ctx : NULL, codec_id); -- if (temp != NULL) { -- gst_caps_append (caps, temp); -- } -- } -- } -- return caps; --} -- --/* Convert a FFMPEG codec Type and optional AVCodecContext -- * to a GstCaps. If the context is ommitted, no fixed values -- * for video/audio size will be included in the GstCaps -- * -- * AVMediaType is primarily meant for uncompressed data GstCaps! -- */ -- --GstCaps * --gst_ffmpeg_codectype_to_caps (enum AVMediaType codec_type, -- AVCodecContext * context, enum CodecID codec_id, gboolean encode) --{ -- GstCaps *caps; -- -- switch (codec_type) { -- case AVMEDIA_TYPE_VIDEO: -- caps = -- gst_ffmpeg_codectype_to_video_caps (context, codec_id, encode, NULL); -- break; -- case AVMEDIA_TYPE_AUDIO: -- caps = -- gst_ffmpeg_codectype_to_audio_caps (context, codec_id, encode, NULL); -- break; -- default: -- caps = NULL; -- break; -+ caps = -+ gst_ff_vid_caps_new (context, codec, codec_id, encode, "video/x-raw", -+ NULL); -+ if (!caps_has_field (caps, "format")) -+ gst_ffmpeg_video_set_pix_fmts (caps, codec ? codec->pix_fmts : NULL); - } -- - return caps; - } - -@@ -2033,8 +2284,6 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps, - context->sample_aspect_ratio.num); - } - -- gst_ffmpeg_get_palette (caps, context); -- - if (!raw) - return; - -@@ -2182,6 +2431,11 @@ static const PixToFmt pixtofmttable[] = { - {GST_VIDEO_FORMAT_I420_10BE, PIX_FMT_YUV420P10BE}, - {GST_VIDEO_FORMAT_I422_10LE, PIX_FMT_YUV422P10LE}, - {GST_VIDEO_FORMAT_I422_10BE, PIX_FMT_YUV422P10BE}, -+ {GST_VIDEO_FORMAT_Y444_10LE, PIX_FMT_YUV444P10LE}, -+ {GST_VIDEO_FORMAT_Y444_10BE, PIX_FMT_YUV444P10BE}, -+ {GST_VIDEO_FORMAT_GBR, PIX_FMT_GBRP}, -+ {GST_VIDEO_FORMAT_GBR_10LE, PIX_FMT_GBRP10LE}, -+ {GST_VIDEO_FORMAT_GBR_10BE, PIX_FMT_GBRP10BE}, - }; - - GstVideoFormat -@@ -2230,6 +2484,112 @@ gst_ffmpeg_videoinfo_to_context (GstVideoInfo * info, AVCodecContext * context) - gst_ffmpeg_videoformat_to_pixfmt (GST_VIDEO_INFO_FORMAT (info)); - } - -+void -+gst_ffmpeg_audioinfo_to_context (GstAudioInfo * info, AVCodecContext * context) -+{ -+ const AVCodec *codec; -+ const enum AVSampleFormat *smpl_fmts; -+ enum AVSampleFormat smpl_fmt = -1; -+ -+ context->channels = info->channels; -+ context->sample_rate = info->rate; -+ context->channel_layout = -+ gst_ffmpeg_channel_positions_to_layout (info->position, info->channels); -+ -+ codec = context->codec; -+ -+ smpl_fmts = codec->sample_fmts; -+ -+ switch (info->finfo->format) { -+ case GST_AUDIO_FORMAT_F32: -+ if (smpl_fmts) { -+ while (*smpl_fmts != -1) { -+ if (*smpl_fmts == AV_SAMPLE_FMT_FLT) { -+ smpl_fmt = *smpl_fmts; -+ break; -+ } else if (*smpl_fmts == AV_SAMPLE_FMT_FLTP) { -+ smpl_fmt = *smpl_fmts; -+ } -+ -+ smpl_fmts++; -+ } -+ } else { -+ smpl_fmt = AV_SAMPLE_FMT_FLT; -+ } -+ break; -+ case GST_AUDIO_FORMAT_F64: -+ if (smpl_fmts) { -+ while (*smpl_fmts != -1) { -+ if (*smpl_fmts == AV_SAMPLE_FMT_DBL) { -+ smpl_fmt = *smpl_fmts; -+ break; -+ } else if (*smpl_fmts == AV_SAMPLE_FMT_DBLP) { -+ smpl_fmt = *smpl_fmts; -+ } -+ -+ smpl_fmts++; -+ } -+ } else { -+ smpl_fmt = AV_SAMPLE_FMT_DBL; -+ } -+ break; -+ case GST_AUDIO_FORMAT_S32: -+ if (smpl_fmts) { -+ while (*smpl_fmts != -1) { -+ if (*smpl_fmts == AV_SAMPLE_FMT_S32) { -+ smpl_fmt = *smpl_fmts; -+ break; -+ } else if (*smpl_fmts == AV_SAMPLE_FMT_S32P) { -+ smpl_fmt = *smpl_fmts; -+ } -+ -+ smpl_fmts++; -+ } -+ } else { -+ smpl_fmt = AV_SAMPLE_FMT_S32; -+ } -+ break; -+ case GST_AUDIO_FORMAT_S16: -+ if (smpl_fmts) { -+ while (*smpl_fmts != -1) { -+ if (*smpl_fmts == AV_SAMPLE_FMT_S16) { -+ smpl_fmt = *smpl_fmts; -+ break; -+ } else if (*smpl_fmts == AV_SAMPLE_FMT_S16P) { -+ smpl_fmt = *smpl_fmts; -+ } -+ -+ smpl_fmts++; -+ } -+ } else { -+ smpl_fmt = AV_SAMPLE_FMT_S16; -+ } -+ break; -+ case GST_AUDIO_FORMAT_U8: -+ if (smpl_fmts) { -+ while (*smpl_fmts != -1) { -+ if (*smpl_fmts == AV_SAMPLE_FMT_U8) { -+ smpl_fmt = *smpl_fmts; -+ break; -+ } else if (*smpl_fmts == AV_SAMPLE_FMT_U8P) { -+ smpl_fmt = *smpl_fmts; -+ } -+ -+ smpl_fmts++; -+ } -+ } else { -+ smpl_fmt = AV_SAMPLE_FMT_U8; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ g_assert (smpl_fmt != -1); -+ -+ context->sample_fmt = smpl_fmt; -+} -+ - /* Convert a GstCaps and a FFMPEG codec Type to a - * AVCodecContext. If the context is ommitted, no fixed values - * for video/audio size will be included in the context -diff --git a/ext/libav/gstavcodecmap.h b/ext/libav/gstavcodecmap.h -index 52e5bec..01ce9b1 100644 ---- a/ext/libav/gstavcodecmap.h -+++ b/ext/libav/gstavcodecmap.h -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifndef __GST_FFMPEG_CODECMAP_H__ -@@ -41,11 +41,6 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, - */ - - GstCaps * --gst_ffmpeg_codectype_to_caps (enum AVMediaType codec_type, -- AVCodecContext *context, -- enum CodecID codec_id, -- gboolean encode); --GstCaps * - gst_ffmpeg_codectype_to_audio_caps (AVCodecContext *context, - enum CodecID codec_id, - gboolean encode, -@@ -91,9 +86,15 @@ void - gst_ffmpeg_videoinfo_to_context (GstVideoInfo *info, - AVCodecContext *context); - -+void -+gst_ffmpeg_audioinfo_to_context (GstAudioInfo *info, -+ AVCodecContext *context); -+ - GstVideoFormat gst_ffmpeg_pixfmt_to_videoformat (enum PixelFormat pixfmt); - enum PixelFormat gst_ffmpeg_videoformat_to_pixfmt (GstVideoFormat format); - -+GstAudioFormat gst_ffmpeg_smpfmt_to_audioformat (enum AVSampleFormat sample_fmt); -+ - /* - * _formatid_to_caps () is meant for muxers/demuxers, it - * transforms a name (ffmpeg way of ID'ing these, why don't -@@ -104,19 +105,6 @@ enum PixelFormat gst_ffmpeg_videoformat_to_pixfmt (GstVideoFormat format); - GstCaps * - gst_ffmpeg_formatid_to_caps (const gchar *format_name); - --GstVideoFormat --gst_ffmpeg_pixfmt_to_video_format (enum PixelFormat pix_fmt); -- --/* Convert a FFMPEG Pixel Format and optional AVCodecContext -- * to a GstCaps. If the context is ommitted, no fixed values -- * for video/audio size will be included in the GstCaps -- * -- * See below for usefullness -- */ -- --GstCaps * --gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, enum CodecID codec_id); -- - /* - * _formatid_get_codecids () can be used to get the codecIDs - * (CODEC_ID_NONE-terminated list) that fit that specific -@@ -131,7 +119,7 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name, - - - gboolean --gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, -+gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels, - GstAudioChannelPosition * pos); - - #endif /* __GST_FFMPEG_CODECMAP_H__ */ -diff --git a/ext/libav/gstavdec.c b/ext/libav/gstavdec.c -deleted file mode 100644 -index 8291099..0000000 ---- a/ext/libav/gstavdec.c -+++ /dev/null -@@ -1,1457 +0,0 @@ --/* GStreamer -- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * 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 -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- --#ifdef HAVE_CONFIG_H --#include "config.h" --#endif -- --#include <assert.h> --#include <string.h> -- --#include <libavcodec/avcodec.h> -- --#include <gst/gst.h> -- --#include "gstav.h" --#include "gstavcodecmap.h" --#include "gstavutils.h" -- --GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); -- --typedef struct _GstFFMpegAudDec GstFFMpegAudDec; -- --#define MAX_TS_MASK 0xff -- --/* for each incomming buffer we keep all timing info in a structure like this. -- * We keep a circular array of these structures around to store the timing info. -- * The index in the array is what we pass as opaque data (to pictures) and -- * pts (to parsers) so that ffmpeg can remember them for us. */ --typedef struct --{ -- gint idx; -- GstClockTime dts; -- GstClockTime pts; -- GstClockTime duration; -- gint64 offset; --} GstTSInfo; -- --struct _GstFFMpegAudDec --{ -- GstElement element; -- -- /* We need to keep track of our pads, so we do so here. */ -- GstPad *srcpad; -- GstPad *sinkpad; -- -- /* decoding */ -- AVCodecContext *context; -- gboolean opened; -- -- /* current output format */ -- gint channels, samplerate, depth; -- GstAudioChannelPosition ffmpeg_layout[64], gst_layout[64]; -- -- gboolean discont; -- gboolean clear_ts; -- -- /* for tracking DTS/PTS */ -- GstClockTime next_out; -- -- /* parsing */ -- gboolean turnoff_parser; /* used for turning off aac raw parsing -- * See bug #566250 */ -- AVCodecParserContext *pctx; -- GstBuffer *pcache; -- -- /* clipping segment */ -- GstSegment segment; -- -- GstTSInfo ts_info[MAX_TS_MASK + 1]; -- gint ts_idx; -- -- /* reverse playback queue */ -- GList *queued; -- -- /* prevent reopening the decoder on GST_EVENT_CAPS when caps are same as last time. */ -- GstCaps *last_caps; --}; -- --typedef struct _GstFFMpegAudDecClass GstFFMpegAudDecClass; -- --struct _GstFFMpegAudDecClass --{ -- GstElementClass parent_class; -- -- AVCodec *in_plugin; -- GstPadTemplate *srctempl, *sinktempl; --}; -- --#define GST_TS_INFO_NONE &ts_info_none --static const GstTSInfo ts_info_none = { -1, -1, -1, -1 }; -- --static const GstTSInfo * --gst_ts_info_store (GstFFMpegAudDec * dec, GstClockTime dts, GstClockTime pts, -- GstClockTime duration, gint64 offset) --{ -- gint idx = dec->ts_idx; -- dec->ts_info[idx].idx = idx; -- dec->ts_info[idx].dts = dts; -- dec->ts_info[idx].pts = pts; -- dec->ts_info[idx].duration = duration; -- dec->ts_info[idx].offset = offset; -- dec->ts_idx = (idx + 1) & MAX_TS_MASK; -- -- return &dec->ts_info[idx]; --} -- --static const GstTSInfo * --gst_ts_info_get (GstFFMpegAudDec * dec, gint idx) --{ -- if (G_UNLIKELY (idx < 0 || idx > MAX_TS_MASK)) -- return GST_TS_INFO_NONE; -- -- return &dec->ts_info[idx]; --} -- --#define GST_TYPE_FFMPEGDEC \ -- (gst_ffmpegauddec_get_type()) --#define GST_FFMPEGDEC(obj) \ -- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegAudDec)) --#define GST_FFMPEGAUDDEC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegAudDecClass)) --#define GST_IS_FFMPEGDEC(obj) \ -- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) --#define GST_IS_FFMPEGAUDDEC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) -- --/* A number of function prototypes are given so we can refer to them later. */ --static void gst_ffmpegauddec_base_init (GstFFMpegAudDecClass * klass); --static void gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass); --static void gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec); --static void gst_ffmpegauddec_finalize (GObject * object); -- --static gboolean gst_ffmpegauddec_setcaps (GstFFMpegAudDec * ffmpegdec, -- GstCaps * caps); --static gboolean gst_ffmpegauddec_sink_event (GstPad * pad, GstObject * parent, -- GstEvent * event); --static gboolean gst_ffmpegauddec_sink_query (GstPad * pad, GstObject * parent, -- GstQuery * query); --static GstFlowReturn gst_ffmpegauddec_chain (GstPad * pad, GstObject * parent, -- GstBuffer * buf); -- --static GstStateChangeReturn gst_ffmpegauddec_change_state (GstElement * element, -- GstStateChange transition); -- --static gboolean gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, -- gboolean force); -- --static void gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec); -- --#define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("avdec-params") -- --static GstElementClass *parent_class = NULL; -- --static void --gst_ffmpegauddec_base_init (GstFFMpegAudDecClass * klass) --{ -- GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -- GstPadTemplate *sinktempl, *srctempl; -- GstCaps *sinkcaps, *srccaps; -- AVCodec *in_plugin; -- gchar *longname, *description; -- -- in_plugin = -- (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), -- GST_FFDEC_PARAMS_QDATA); -- g_assert (in_plugin != NULL); -- -- /* construct the element details struct */ -- longname = g_strdup_printf ("libav %s decoder", in_plugin->long_name); -- description = g_strdup_printf ("libav %s decoder", in_plugin->name); -- gst_element_class_set_metadata (element_class, longname, -- "Codec/Decoder/Audio", description, -- "Wim Taymans <wim.taymans@gmail.com>, " -- "Ronald Bultje <rbultje@ronald.bitfreak.net>, " -- "Edward Hervey <bilboed@bilboed.com>"); -- g_free (longname); -- g_free (description); -- -- /* get the caps */ -- sinkcaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, FALSE); -- if (!sinkcaps) { -- GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name); -- sinkcaps = gst_caps_from_string ("unknown/unknown"); -- } -- srccaps = gst_ffmpeg_codectype_to_audio_caps (NULL, -- in_plugin->id, FALSE, in_plugin); -- if (!srccaps) { -- GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name); -- srccaps = gst_caps_from_string ("unknown/unknown"); -- } -- -- /* pad templates */ -- sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -- GST_PAD_ALWAYS, sinkcaps); -- srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps); -- -- gst_element_class_add_pad_template (element_class, srctempl); -- gst_element_class_add_pad_template (element_class, sinktempl); -- -- klass->in_plugin = in_plugin; -- klass->srctempl = srctempl; -- klass->sinktempl = sinktempl; --} -- --static void --gst_ffmpegauddec_class_init (GstFFMpegAudDecClass * klass) --{ -- GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); -- -- parent_class = g_type_class_peek_parent (klass); -- -- gobject_class->finalize = gst_ffmpegauddec_finalize; -- -- gstelement_class->change_state = gst_ffmpegauddec_change_state; --} -- --static void --gst_ffmpegauddec_init (GstFFMpegAudDec * ffmpegdec) --{ -- GstFFMpegAudDecClass *oclass; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- /* setup pads */ -- ffmpegdec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink"); -- gst_pad_set_query_function (ffmpegdec->sinkpad, -- GST_DEBUG_FUNCPTR (gst_ffmpegauddec_sink_query)); -- gst_pad_set_event_function (ffmpegdec->sinkpad, -- GST_DEBUG_FUNCPTR (gst_ffmpegauddec_sink_event)); -- gst_pad_set_chain_function (ffmpegdec->sinkpad, -- GST_DEBUG_FUNCPTR (gst_ffmpegauddec_chain)); -- gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->sinkpad); -- -- ffmpegdec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src"); -- gst_pad_use_fixed_caps (ffmpegdec->srcpad); -- gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->srcpad); -- -- /* some ffmpeg data */ -- ffmpegdec->context = avcodec_alloc_context (); -- ffmpegdec->pctx = NULL; -- ffmpegdec->pcache = NULL; -- ffmpegdec->opened = FALSE; -- -- gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME); --} -- --static void --gst_ffmpegauddec_finalize (GObject * object) --{ -- GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) object; -- -- if (ffmpegdec->context != NULL) -- av_free (ffmpegdec->context); -- -- G_OBJECT_CLASS (parent_class)->finalize (object); --} -- --static void --gst_ffmpegauddec_reset_ts (GstFFMpegAudDec * ffmpegdec) --{ -- ffmpegdec->next_out = GST_CLOCK_TIME_NONE; --} -- --/* with LOCK */ --static void --gst_ffmpegauddec_close (GstFFMpegAudDec * ffmpegdec) --{ -- if (!ffmpegdec->opened) -- return; -- -- GST_LOG_OBJECT (ffmpegdec, "closing libav codec"); -- -- gst_caps_replace (&ffmpegdec->last_caps, NULL); -- -- if (ffmpegdec->context->priv_data) -- gst_ffmpeg_avcodec_close (ffmpegdec->context); -- ffmpegdec->opened = FALSE; -- -- if (ffmpegdec->context->palctrl) { -- av_free (ffmpegdec->context->palctrl); -- ffmpegdec->context->palctrl = NULL; -- } -- -- if (ffmpegdec->context->extradata) { -- av_free (ffmpegdec->context->extradata); -- ffmpegdec->context->extradata = NULL; -- } -- -- if (ffmpegdec->pctx) { -- if (ffmpegdec->pcache) { -- gst_buffer_unref (ffmpegdec->pcache); -- ffmpegdec->pcache = NULL; -- } -- av_parser_close (ffmpegdec->pctx); -- ffmpegdec->pctx = NULL; -- } --} -- --/* with LOCK */ --static gboolean --gst_ffmpegauddec_open (GstFFMpegAudDec * ffmpegdec) --{ -- GstFFMpegAudDecClass *oclass; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0) -- goto could_not_open; -- -- ffmpegdec->opened = TRUE; -- -- GST_LOG_OBJECT (ffmpegdec, "Opened libav codec %s, id %d", -- oclass->in_plugin->name, oclass->in_plugin->id); -- -- if (!ffmpegdec->turnoff_parser) { -- ffmpegdec->pctx = av_parser_init (oclass->in_plugin->id); -- if (ffmpegdec->pctx) -- GST_LOG_OBJECT (ffmpegdec, "Using parser %p", ffmpegdec->pctx); -- else -- GST_LOG_OBJECT (ffmpegdec, "No parser for codec"); -- } else { -- GST_LOG_OBJECT (ffmpegdec, "Parser deactivated for format"); -- } -- -- ffmpegdec->samplerate = 0; -- ffmpegdec->channels = 0; -- ffmpegdec->depth = 0; -- -- gst_ffmpegauddec_reset_ts (ffmpegdec); -- -- return TRUE; -- -- /* ERRORS */ --could_not_open: -- { -- gst_ffmpegauddec_close (ffmpegdec); -- GST_DEBUG_OBJECT (ffmpegdec, "avdec_%s: Failed to open libav codec", -- oclass->in_plugin->name); -- return FALSE; -- } --} -- --static gboolean --gst_ffmpegauddec_setcaps (GstFFMpegAudDec * ffmpegdec, GstCaps * caps) --{ -- GstFFMpegAudDecClass *oclass; -- GstStructure *structure; -- gboolean ret = TRUE; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- GST_DEBUG_OBJECT (ffmpegdec, "setcaps called"); -- -- GST_OBJECT_LOCK (ffmpegdec); -- -- /* close old session */ -- if (ffmpegdec->opened) { -- GST_OBJECT_UNLOCK (ffmpegdec); -- gst_ffmpegauddec_drain (ffmpegdec); -- GST_OBJECT_LOCK (ffmpegdec); -- gst_ffmpegauddec_close (ffmpegdec); -- -- /* and reset the defaults that were set when a context is created */ -- avcodec_get_context_defaults (ffmpegdec->context); -- } -- -- /* default is to let format decide if it needs a parser */ -- ffmpegdec->turnoff_parser = FALSE; -- -- /* get size and so */ -- gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id, -- oclass->in_plugin->type, caps, ffmpegdec->context); -- -- /* get pixel aspect ratio if it's set */ -- structure = gst_caps_get_structure (caps, 0); -- -- /* for AAC we only use av_parse if not on stream-format==raw or ==loas */ -- if (oclass->in_plugin->id == CODEC_ID_AAC -- || oclass->in_plugin->id == CODEC_ID_AAC_LATM) { -- const gchar *format = gst_structure_get_string (structure, "stream-format"); -- -- if (format == NULL || strcmp (format, "raw") == 0) { -- ffmpegdec->turnoff_parser = TRUE; -- } -- } -- -- /* for FLAC, don't parse if it's already parsed */ -- if (oclass->in_plugin->id == CODEC_ID_FLAC) { -- if (gst_structure_has_field (structure, "streamheader")) -- ffmpegdec->turnoff_parser = TRUE; -- } -- -- /* workaround encoder bugs */ -- ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT; -- ffmpegdec->context->error_recognition = 1; -- -- /* open codec - we don't select an output pix_fmt yet, -- * simply because we don't know! We only get it -- * during playback... */ -- if (!gst_ffmpegauddec_open (ffmpegdec)) -- goto open_failed; -- --done: -- GST_OBJECT_UNLOCK (ffmpegdec); -- -- return ret; -- -- /* ERRORS */ --open_failed: -- { -- GST_DEBUG_OBJECT (ffmpegdec, "Failed to open"); -- ret = FALSE; -- goto done; -- } --} -- --static gboolean --gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force) --{ -- GstFFMpegAudDecClass *oclass; -- GstCaps *caps; -- gint depth; -- GstAudioChannelPosition pos[64] = { 0, }; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- depth = av_smp_format_depth (ffmpegdec->context->sample_fmt); -- gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context, pos); -- -- if (!force && ffmpegdec->samplerate == -- ffmpegdec->context->sample_rate && -- ffmpegdec->channels == ffmpegdec->context->channels && -- ffmpegdec->depth == depth) -- return TRUE; -- -- GST_DEBUG_OBJECT (ffmpegdec, -- "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)", -- ffmpegdec->samplerate, ffmpegdec->channels, -- ffmpegdec->depth, -- ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth); -- -- ffmpegdec->samplerate = ffmpegdec->context->sample_rate; -- ffmpegdec->channels = ffmpegdec->context->channels; -- ffmpegdec->depth = depth; -- memcpy (ffmpegdec->ffmpeg_layout, pos, -- sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels); -- -- /* Get GStreamer channel layout */ -- memcpy (ffmpegdec->gst_layout, -- ffmpegdec->ffmpeg_layout, -- sizeof (GstAudioChannelPosition) * ffmpegdec->channels); -- gst_audio_channel_positions_to_valid_order (ffmpegdec->gst_layout, -- ffmpegdec->channels); -- -- caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, -- ffmpegdec->context, oclass->in_plugin->id, FALSE); -- -- if (caps == NULL) -- goto no_caps; -- -- GST_LOG_OBJECT (ffmpegdec, "output caps %" GST_PTR_FORMAT, caps); -- -- if (!gst_pad_set_caps (ffmpegdec->srcpad, caps)) -- goto caps_failed; -- -- gst_caps_unref (caps); -- -- return TRUE; -- -- /* ERRORS */ --no_caps: -- { --#ifdef HAVE_LIBAV_UNINSTALLED -- /* using internal ffmpeg snapshot */ -- GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, -- ("Could not find GStreamer caps mapping for libav codec '%s'.", -- oclass->in_plugin->name), (NULL)); --#else -- /* using external ffmpeg */ -- GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, -- ("Could not find GStreamer caps mapping for libav codec '%s', and " -- "you are using an external libavcodec. This is most likely due to " -- "a packaging problem and/or libavcodec having been upgraded to a " -- "version that is not compatible with this version of " -- "gstreamer-libav. Make sure your gstreamer-libav and libavcodec " -- "packages come from the same source/repository.", -- oclass->in_plugin->name), (NULL)); --#endif -- return FALSE; -- } --caps_failed: -- { -- GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL), -- ("Could not set caps for libav decoder (%s), not fixed?", -- oclass->in_plugin->name)); -- gst_caps_unref (caps); -- -- return FALSE; -- } --} -- --static void --clear_queued (GstFFMpegAudDec * ffmpegdec) --{ -- g_list_foreach (ffmpegdec->queued, (GFunc) gst_mini_object_unref, NULL); -- g_list_free (ffmpegdec->queued); -- ffmpegdec->queued = NULL; --} -- --static GstFlowReturn --flush_queued (GstFFMpegAudDec * ffmpegdec) --{ -- GstFlowReturn res = GST_FLOW_OK; -- -- while (ffmpegdec->queued) { -- GstBuffer *buf = GST_BUFFER_CAST (ffmpegdec->queued->data); -- -- GST_LOG_OBJECT (ffmpegdec, "pushing buffer %p, offset %" -- G_GUINT64_FORMAT ", timestamp %" -- GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf, -- GST_BUFFER_OFFSET (buf), -- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), -- GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); -- -- /* iterate ouput queue an push downstream */ -- res = gst_pad_push (ffmpegdec->srcpad, buf); -- -- ffmpegdec->queued = -- g_list_delete_link (ffmpegdec->queued, ffmpegdec->queued); -- } -- return res; --} -- --static void --gst_avpacket_init (AVPacket * packet, guint8 * data, guint size) --{ -- memset (packet, 0, sizeof (AVPacket)); -- packet->data = data; -- packet->size = size; --} -- --/* returns TRUE if buffer is within segment, else FALSE. -- * if Buffer is on segment border, it's timestamp and duration will be clipped */ --static gboolean --clip_audio_buffer (GstFFMpegAudDec * dec, GstBuffer * buf, GstClockTime in_ts, -- GstClockTime in_dur) --{ -- GstClockTime stop; -- gint64 diff; -- guint64 ctime, cstop; -- gboolean res = TRUE; -- gsize size, offset; -- -- size = gst_buffer_get_size (buf); -- offset = 0; -- -- GST_LOG_OBJECT (dec, -- "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT -- ", size %" G_GSIZE_FORMAT, GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur), -- size); -- -- /* can't clip without TIME segment */ -- if (G_UNLIKELY (dec->segment.format != GST_FORMAT_TIME)) -- goto beach; -- -- /* we need a start time */ -- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (in_ts))) -- goto beach; -- -- /* trust duration */ -- stop = in_ts + in_dur; -- -- res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, in_ts, stop, &ctime, -- &cstop); -- if (G_UNLIKELY (!res)) -- goto out_of_segment; -- -- /* see if some clipping happened */ -- if (G_UNLIKELY ((diff = ctime - in_ts) > 0)) { -- /* bring clipped time to bytes */ -- diff = -- gst_util_uint64_scale_int (diff, dec->samplerate, -- GST_SECOND) * (dec->depth * dec->channels); -- -- GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %" -- G_GINT64_FORMAT " bytes", GST_TIME_ARGS (ctime), diff); -- -- offset += diff; -- size -= diff; -- } -- if (G_UNLIKELY ((diff = stop - cstop) > 0)) { -- /* bring clipped time to bytes */ -- diff = -- gst_util_uint64_scale_int (diff, dec->samplerate, -- GST_SECOND) * (dec->depth * dec->channels); -- -- GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %" -- G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff); -- -- size -= diff; -- } -- gst_buffer_resize (buf, offset, size); -- GST_BUFFER_TIMESTAMP (buf) = ctime; -- GST_BUFFER_DURATION (buf) = cstop - ctime; -- --beach: -- GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : "")); -- return res; -- -- /* ERRORS */ --out_of_segment: -- { -- GST_LOG_OBJECT (dec, "out of segment"); -- goto beach; -- } --} -- --static gint --gst_ffmpegauddec_audio_frame (GstFFMpegAudDec * ffmpegdec, -- AVCodec * in_plugin, guint8 * data, guint size, -- const GstTSInfo * dec_info, GstBuffer ** outbuf, GstFlowReturn * ret) --{ -- gint len = -1; -- gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE; -- GstClockTime out_pts, out_duration; -- GstMapInfo map; -- gint64 out_offset; -- int16_t *odata; -- AVPacket packet; -- -- GST_DEBUG_OBJECT (ffmpegdec, -- "size:%d, offset:%" G_GINT64_FORMAT ", dts:%" GST_TIME_FORMAT ", pts:%" -- GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT ", ffmpegdec->next_out:%" -- GST_TIME_FORMAT, size, dec_info->offset, GST_TIME_ARGS (dec_info->dts), -- GST_TIME_ARGS (dec_info->pts), GST_TIME_ARGS (dec_info->duration), -- GST_TIME_ARGS (ffmpegdec->next_out)); -- -- *outbuf = new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE); -- -- gst_buffer_map (*outbuf, &map, GST_MAP_WRITE); -- odata = (int16_t *) map.data; -- -- gst_avpacket_init (&packet, data, size); -- len = avcodec_decode_audio3 (ffmpegdec->context, odata, &have_data, &packet); -- -- GST_DEBUG_OBJECT (ffmpegdec, -- "Decode audio: len=%d, have_data=%d", len, have_data); -- -- if (len >= 0 && have_data > 0) { -- GstAudioFormat fmt; -- -- /* Buffer size */ -- gst_buffer_unmap (*outbuf, &map); -- gst_buffer_resize (*outbuf, 0, have_data); -- -- GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer"); -- if (!gst_ffmpegauddec_negotiate (ffmpegdec, FALSE)) { -- gst_buffer_unref (*outbuf); -- *outbuf = NULL; -- len = -1; -- goto beach; -- } -- -- /* -- * Timestamps: -- * -- * 1) Copy input timestamp if valid -- * 2) else interpolate from previous input timestamp -- */ -- /* always take timestamps from the input buffer if any */ -- if (GST_CLOCK_TIME_IS_VALID (dec_info->pts)) { -- out_pts = dec_info->pts; -- } else { -- out_pts = ffmpegdec->next_out; -- } -- -- /* -- * Duration: -- * -- * 1) calculate based on number of samples -- */ -- out_duration = gst_util_uint64_scale (have_data, GST_SECOND, -- ffmpegdec->depth * ffmpegdec->channels * ffmpegdec->samplerate); -- -- /* offset: -- * -- * Just copy -- */ -- out_offset = dec_info->offset; -- -- GST_DEBUG_OBJECT (ffmpegdec, -- "Buffer created. Size:%d , pts:%" GST_TIME_FORMAT " , duration:%" -- GST_TIME_FORMAT, have_data, -- GST_TIME_ARGS (out_pts), GST_TIME_ARGS (out_duration)); -- -- GST_BUFFER_PTS (*outbuf) = out_pts; -- GST_BUFFER_DURATION (*outbuf) = out_duration; -- GST_BUFFER_OFFSET (*outbuf) = out_offset; -- -- /* the next timestamp we'll use when interpolating */ -- if (GST_CLOCK_TIME_IS_VALID (out_pts)) -- ffmpegdec->next_out = out_pts + out_duration; -- -- /* now see if we need to clip the buffer against the segment boundaries. */ -- if (G_UNLIKELY (!clip_audio_buffer (ffmpegdec, *outbuf, out_pts, -- out_duration))) -- goto clipped; -- -- -- /* Reorder channels to the GStreamer channel order */ -- /* Only the width really matters here... and it's stored as depth */ -- fmt = -- gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, -- ffmpegdec->depth * 8, ffmpegdec->depth * 8); -- -- gst_audio_buffer_reorder_channels (*outbuf, fmt, -- ffmpegdec->channels, ffmpegdec->ffmpeg_layout, ffmpegdec->gst_layout); -- } else { -- gst_buffer_unmap (*outbuf, &map); -- gst_buffer_unref (*outbuf); -- *outbuf = NULL; -- } -- --beach: -- GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d", -- *ret, *outbuf, len); -- return len; -- -- /* ERRORS */ --clipped: -- { -- GST_DEBUG_OBJECT (ffmpegdec, "buffer clipped"); -- gst_buffer_unref (*outbuf); -- *outbuf = NULL; -- goto beach; -- } --} -- --/* gst_ffmpegauddec_frame: -- * ffmpegdec: -- * data: pointer to the data to decode -- * size: size of data in bytes -- * got_data: 0 if no data was decoded, != 0 otherwise. -- * in_time: timestamp of data -- * in_duration: duration of data -- * ret: GstFlowReturn to return in the chain function -- * -- * Decode the given frame and pushes it downstream. -- * -- * Returns: Number of bytes used in decoding, -1 on error/failure. -- */ -- --static gint --gst_ffmpegauddec_frame (GstFFMpegAudDec * ffmpegdec, -- guint8 * data, guint size, gint * got_data, const GstTSInfo * dec_info, -- GstFlowReturn * ret) --{ -- GstFFMpegAudDecClass *oclass; -- GstBuffer *outbuf = NULL; -- gint have_data = 0, len = 0; -- -- if (G_UNLIKELY (ffmpegdec->context->codec == NULL)) -- goto no_codec; -- -- GST_LOG_OBJECT (ffmpegdec, "data:%p, size:%d, id:%d", data, size, -- dec_info->idx); -- -- *ret = GST_FLOW_OK; -- ffmpegdec->context->frame_number++; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- len = -- gst_ffmpegauddec_audio_frame (ffmpegdec, oclass->in_plugin, data, size, -- dec_info, &outbuf, ret); -- -- /* if we did not get an output buffer and we have a pending discont, don't -- * clear the input timestamps, we will put them on the next buffer because -- * else we might create the first buffer with a very big timestamp gap. */ -- if (outbuf == NULL && ffmpegdec->discont) { -- GST_DEBUG_OBJECT (ffmpegdec, "no buffer but keeping timestamp"); -- ffmpegdec->clear_ts = FALSE; -- } -- -- if (outbuf) -- have_data = 1; -- -- if (len < 0 || have_data < 0) { -- GST_WARNING_OBJECT (ffmpegdec, -- "avdec_%s: decoding error (len: %d, have_data: %d)", -- oclass->in_plugin->name, len, have_data); -- *got_data = 0; -- goto beach; -- } else if (len == 0 && have_data == 0) { -- *got_data = 0; -- goto beach; -- } else { -- /* this is where I lost my last clue on ffmpeg... */ -- *got_data = 1; -- } -- -- if (outbuf) { -- GST_LOG_OBJECT (ffmpegdec, -- "Decoded data, now pushing buffer %p with offset %" G_GINT64_FORMAT -- ", timestamp %" GST_TIME_FORMAT " and duration %" GST_TIME_FORMAT, -- outbuf, GST_BUFFER_OFFSET (outbuf), -- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), -- GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); -- -- /* mark pending discont */ -- if (ffmpegdec->discont) { -- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); -- ffmpegdec->discont = FALSE; -- } -- if (ffmpegdec->segment.rate > 0.0) { -- /* and off we go */ -- *ret = gst_pad_push (ffmpegdec->srcpad, outbuf); -- } else { -- /* reverse playback, queue frame till later when we get a discont. */ -- GST_DEBUG_OBJECT (ffmpegdec, "queued frame"); -- ffmpegdec->queued = g_list_prepend (ffmpegdec->queued, outbuf); -- *ret = GST_FLOW_OK; -- } -- } else { -- GST_DEBUG_OBJECT (ffmpegdec, "We didn't get a decoded buffer"); -- } -- --beach: -- return len; -- -- /* ERRORS */ --no_codec: -- { -- GST_ERROR_OBJECT (ffmpegdec, "no codec context"); -- return -1; -- } --} -- --static void --gst_ffmpegauddec_drain (GstFFMpegAudDec * ffmpegdec) --{ -- GstFFMpegAudDecClass *oclass; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) { -- gint have_data, len, try = 0; -- -- GST_LOG_OBJECT (ffmpegdec, -- "codec has delay capabilities, calling until libav has drained everything"); -- -- do { -- GstFlowReturn ret; -- -- len = -- gst_ffmpegauddec_frame (ffmpegdec, NULL, 0, &have_data, &ts_info_none, -- &ret); -- if (len < 0 || have_data == 0) -- break; -- } while (try++ < 10); -- } -- if (ffmpegdec->segment.rate < 0.0) { -- /* if we have some queued frames for reverse playback, flush them now */ -- flush_queued (ffmpegdec); -- } --} -- --static void --gst_ffmpegauddec_flush_pcache (GstFFMpegAudDec * ffmpegdec) --{ -- if (ffmpegdec->pctx) { -- gint size, bsize; -- guint8 *data; -- guint8 bdata[FF_INPUT_BUFFER_PADDING_SIZE]; -- -- bsize = FF_INPUT_BUFFER_PADDING_SIZE; -- memset (bdata, 0, bsize); -- -- /* parse some dummy data to work around some ffmpeg weirdness where it keeps -- * the previous pts around */ -- av_parser_parse2 (ffmpegdec->pctx, ffmpegdec->context, -- &data, &size, bdata, bsize, -1, -1, -1); -- ffmpegdec->pctx->pts = -1; -- ffmpegdec->pctx->dts = -1; -- } -- -- if (ffmpegdec->pcache) { -- gst_buffer_unref (ffmpegdec->pcache); -- ffmpegdec->pcache = NULL; -- } --} -- --static gboolean --gst_ffmpegauddec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) --{ -- GstFFMpegAudDec *ffmpegdec; -- gboolean ret = FALSE; -- -- ffmpegdec = (GstFFMpegAudDec *) parent; -- -- GST_DEBUG_OBJECT (ffmpegdec, "Handling %s event", -- GST_EVENT_TYPE_NAME (event)); -- -- switch (GST_EVENT_TYPE (event)) { -- case GST_EVENT_EOS: -- { -- gst_ffmpegauddec_drain (ffmpegdec); -- break; -- } -- case GST_EVENT_FLUSH_STOP: -- { -- if (ffmpegdec->opened) { -- avcodec_flush_buffers (ffmpegdec->context); -- } -- gst_ffmpegauddec_reset_ts (ffmpegdec); -- gst_ffmpegauddec_flush_pcache (ffmpegdec); -- gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME); -- clear_queued (ffmpegdec); -- break; -- } -- case GST_EVENT_CAPS: -- { -- GstCaps *caps; -- -- gst_event_parse_caps (event, &caps); -- -- if (!ffmpegdec->last_caps -- || !gst_caps_is_equal (ffmpegdec->last_caps, caps)) { -- ret = gst_ffmpegauddec_setcaps (ffmpegdec, caps); -- if (ret) { -- gst_caps_replace (&ffmpegdec->last_caps, caps); -- } -- } else { -- ret = TRUE; -- } -- -- gst_event_unref (event); -- goto done; -- } -- case GST_EVENT_SEGMENT: -- { -- GstSegment segment; -- -- gst_event_copy_segment (event, &segment); -- -- switch (segment.format) { -- case GST_FORMAT_TIME: -- /* fine, our native segment format */ -- break; -- case GST_FORMAT_BYTES: -- { -- gint bit_rate; -- -- bit_rate = ffmpegdec->context->bit_rate; -- -- /* convert to time or fail */ -- if (!bit_rate) -- goto no_bitrate; -- -- GST_DEBUG_OBJECT (ffmpegdec, "bitrate: %d", bit_rate); -- -- /* convert values to TIME */ -- if (segment.start != -1) -- segment.start = -- gst_util_uint64_scale_int (segment.start, GST_SECOND, bit_rate); -- if (segment.stop != -1) -- segment.stop = -- gst_util_uint64_scale_int (segment.stop, GST_SECOND, bit_rate); -- if (segment.time != -1) -- segment.time = -- gst_util_uint64_scale_int (segment.time, GST_SECOND, bit_rate); -- -- /* unref old event */ -- gst_event_unref (event); -- -- /* create new converted time segment */ -- segment.format = GST_FORMAT_TIME; -- /* FIXME, bitrate is not good enough too find a good stop, let's -- * hope start and time were 0... meh. */ -- segment.stop = -1; -- event = gst_event_new_segment (&segment); -- break; -- } -- default: -- /* invalid format */ -- goto invalid_format; -- } -- -- GST_DEBUG_OBJECT (ffmpegdec, "SEGMENT in time %" GST_SEGMENT_FORMAT, -- &segment); -- -- /* and store the values */ -- gst_segment_copy_into (&segment, &ffmpegdec->segment); -- break; -- } -- default: -- break; -- } -- -- /* and push segment downstream */ -- ret = gst_pad_push_event (ffmpegdec->srcpad, event); -- --done: -- -- return ret; -- -- /* ERRORS */ --no_bitrate: -- { -- GST_WARNING_OBJECT (ffmpegdec, "no bitrate to convert BYTES to TIME"); -- gst_event_unref (event); -- goto done; -- } --invalid_format: -- { -- GST_WARNING_OBJECT (ffmpegdec, "unknown format received in NEWSEGMENT"); -- gst_event_unref (event); -- goto done; -- } --} -- --static gboolean --gst_ffmpegauddec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) --{ -- GstFFMpegAudDec *ffmpegdec; -- gboolean ret = FALSE; -- -- ffmpegdec = (GstFFMpegAudDec *) parent; -- -- GST_DEBUG_OBJECT (ffmpegdec, "Handling %s query", -- GST_QUERY_TYPE_NAME (query)); -- -- switch (GST_QUERY_TYPE (query)) { -- case GST_QUERY_ACCEPT_CAPS: -- { -- GstPadTemplate *templ; -- -- ret = FALSE; -- if ((templ = GST_PAD_PAD_TEMPLATE (pad))) { -- GstCaps *tcaps; -- -- if ((tcaps = GST_PAD_TEMPLATE_CAPS (templ))) { -- GstCaps *caps; -- -- gst_query_parse_accept_caps (query, &caps); -- gst_query_set_accept_caps_result (query, -- gst_caps_is_subset (caps, tcaps)); -- ret = TRUE; -- } -- } -- break; -- } -- default: -- ret = gst_pad_query_default (pad, parent, query); -- break; -- } -- return ret; --} -- --static GstFlowReturn --gst_ffmpegauddec_chain (GstPad * pad, GstObject * parent, GstBuffer * inbuf) --{ -- GstFFMpegAudDec *ffmpegdec; -- GstFFMpegAudDecClass *oclass; -- guint8 *data, *bdata; -- GstMapInfo map; -- gint size, bsize, len, have_data; -- GstFlowReturn ret = GST_FLOW_OK; -- GstClockTime in_pts, in_dts, in_duration; -- gboolean discont; -- gint64 in_offset; -- const GstTSInfo *in_info; -- const GstTSInfo *dec_info; -- -- ffmpegdec = (GstFFMpegAudDec *) parent; -- -- if (G_UNLIKELY (!ffmpegdec->opened)) -- goto not_negotiated; -- -- discont = GST_BUFFER_IS_DISCONT (inbuf); -- -- /* The discont flags marks a buffer that is not continuous with the previous -- * buffer. This means we need to clear whatever data we currently have. We let -- * ffmpeg continue with the data that it has. We currently drain the old -- * frames that might be inside the decoder and we clear any partial data in -- * the pcache, we might be able to remove the drain and flush too. */ -- if (G_UNLIKELY (discont)) { -- GST_DEBUG_OBJECT (ffmpegdec, "received DISCONT"); -- /* drain what we have queued */ -- gst_ffmpegauddec_drain (ffmpegdec); -- gst_ffmpegauddec_flush_pcache (ffmpegdec); -- ffmpegdec->discont = TRUE; -- gst_ffmpegauddec_reset_ts (ffmpegdec); -- } -- /* by default we clear the input timestamp after decoding each frame so that -- * interpollation can work. */ -- ffmpegdec->clear_ts = TRUE; -- -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- -- /* parse cache joining. If there is cached data */ -- if (ffmpegdec->pcache) { -- /* join with previous data */ -- GST_LOG_OBJECT (ffmpegdec, "join parse cache"); -- inbuf = gst_buffer_append (ffmpegdec->pcache, inbuf); -- /* no more cached data, we assume we can consume the complete cache */ -- ffmpegdec->pcache = NULL; -- } -- -- in_dts = GST_BUFFER_DTS (inbuf); -- in_pts = GST_BUFFER_PTS (inbuf); -- in_duration = GST_BUFFER_DURATION (inbuf); -- in_offset = GST_BUFFER_OFFSET (inbuf); -- -- /* get handle to timestamp info, we can pass this around to ffmpeg */ -- in_info = -- gst_ts_info_store (ffmpegdec, in_dts, in_pts, in_duration, in_offset); -- -- GST_LOG_OBJECT (ffmpegdec, -- "Received new data of size %u, offset:%" G_GUINT64_FORMAT ", ts:%" -- GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT ", info %d", -- gst_buffer_get_size (inbuf), GST_BUFFER_OFFSET (inbuf), -- GST_TIME_ARGS (in_pts), GST_TIME_ARGS (in_duration), in_info->idx); -- -- /* workarounds, functions write to buffers: -- * libavcodec/svq1.c:svq1_decode_frame writes to the given buffer. -- * libavcodec/svq3.c:svq3_decode_slice_header too. -- * ffmpeg devs know about it and will fix it (they said). */ -- if (oclass->in_plugin->id == CODEC_ID_SVQ1 || -- oclass->in_plugin->id == CODEC_ID_SVQ3) { -- inbuf = gst_buffer_make_writable (inbuf); -- } -- -- gst_buffer_map (inbuf, &map, GST_MAP_READ); -- -- bdata = map.data; -- bsize = map.size; -- -- GST_LOG_OBJECT (ffmpegdec, -- "Received new data of size %u, offset:%" G_GUINT64_FORMAT ", dts:%" -- GST_TIME_FORMAT ", pts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT -- ", info %d", bsize, in_offset, GST_TIME_ARGS (in_dts), -- GST_TIME_ARGS (in_pts), GST_TIME_ARGS (in_duration), in_info->idx); -- -- do { -- /* parse, if at all possible */ -- if (ffmpegdec->pctx) { -- gint res; -- -- GST_LOG_OBJECT (ffmpegdec, -- "Calling av_parser_parse2 with offset %" G_GINT64_FORMAT ", ts:%" -- GST_TIME_FORMAT " size %d", in_offset, GST_TIME_ARGS (in_pts), bsize); -- -- /* feed the parser. We pass the timestamp info so that we can recover all -- * info again later */ -- res = av_parser_parse2 (ffmpegdec->pctx, ffmpegdec->context, -- &data, &size, bdata, bsize, in_info->idx, in_info->idx, in_offset); -- -- GST_LOG_OBJECT (ffmpegdec, -- "parser returned res %d and size %d, id %" G_GINT64_FORMAT, res, size, -- (gint64) ffmpegdec->pctx->pts); -- -- /* store pts for decoding */ -- if (ffmpegdec->pctx->pts != AV_NOPTS_VALUE && ffmpegdec->pctx->pts != -1) -- dec_info = gst_ts_info_get (ffmpegdec, ffmpegdec->pctx->pts); -- else { -- /* ffmpeg sometimes loses track after a flush, help it by feeding a -- * valid start time */ -- ffmpegdec->pctx->pts = in_info->idx; -- ffmpegdec->pctx->dts = in_info->idx; -- dec_info = in_info; -- } -- -- GST_LOG_OBJECT (ffmpegdec, "consuming %d bytes. id %d", size, -- dec_info->idx); -- -- if (res) { -- /* there is output, set pointers for next round. */ -- bsize -= res; -- bdata += res; -- } else { -- /* Parser did not consume any data, make sure we don't clear the -- * timestamp for the next round */ -- ffmpegdec->clear_ts = FALSE; -- } -- -- /* if there is no output, we must break and wait for more data. also the -- * timestamp in the context is not updated. */ -- if (size == 0) { -- if (bsize > 0) -- continue; -- else -- break; -- } -- } else { -- data = bdata; -- size = bsize; -- -- dec_info = in_info; -- } -- -- /* decode a frame of audio now */ -- len = -- gst_ffmpegauddec_frame (ffmpegdec, data, size, &have_data, dec_info, -- &ret); -- -- if (ret != GST_FLOW_OK) { -- GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s", -- gst_flow_get_name (ret)); -- /* bad flow return, make sure we discard all data and exit */ -- bsize = 0; -- break; -- } -- if (!ffmpegdec->pctx) { -- if (len == 0 && !have_data) { -- /* nothing was decoded, this could be because no data was available or -- * because we were skipping frames. -- * If we have no context we must exit and wait for more data, we keep the -- * data we tried. */ -- GST_LOG_OBJECT (ffmpegdec, "Decoding didn't return any data, breaking"); -- break; -- } else if (len < 0) { -- /* a decoding error happened, we must break and try again with next data. */ -- GST_LOG_OBJECT (ffmpegdec, "Decoding error, breaking"); -- bsize = 0; -- break; -- } -- /* prepare for the next round, for codecs with a context we did this -- * already when using the parser. */ -- bsize -= len; -- bdata += len; -- } else { -- if (len == 0) { -- /* nothing was decoded, this could be because no data was available or -- * because we were skipping frames. Since we have a parser we can -- * continue with the next frame */ -- GST_LOG_OBJECT (ffmpegdec, -- "Decoding didn't return any data, trying next"); -- } else if (len < 0) { -- /* we have a context that will bring us to the next frame */ -- GST_LOG_OBJECT (ffmpegdec, "Decoding error, trying next"); -- } -- } -- -- /* make sure we don't use the same old timestamp for the next frame and let -- * the interpollation take care of it. */ -- if (ffmpegdec->clear_ts) { -- in_dts = GST_CLOCK_TIME_NONE; -- in_pts = GST_CLOCK_TIME_NONE; -- in_duration = GST_CLOCK_TIME_NONE; -- in_offset = GST_BUFFER_OFFSET_NONE; -- in_info = GST_TS_INFO_NONE; -- } else { -- ffmpegdec->clear_ts = TRUE; -- } -- -- GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0). bsize:%d , bdata:%p", -- bsize, bdata); -- } while (bsize > 0); -- -- gst_buffer_unmap (inbuf, &map); -- -- /* keep left-over */ -- if (ffmpegdec->pctx && bsize > 0) { -- in_pts = GST_BUFFER_PTS (inbuf); -- in_dts = GST_BUFFER_DTS (inbuf); -- in_offset = GST_BUFFER_OFFSET (inbuf); -- -- GST_LOG_OBJECT (ffmpegdec, -- "Keeping %d bytes of data with offset %" G_GINT64_FORMAT ", pts %" -- GST_TIME_FORMAT, bsize, in_offset, GST_TIME_ARGS (in_pts)); -- -- ffmpegdec->pcache = gst_buffer_copy_region (inbuf, GST_BUFFER_COPY_ALL, -- gst_buffer_get_size (inbuf) - bsize, bsize); -- /* we keep timestamp, even though all we really know is that the correct -- * timestamp is not below the one from inbuf */ -- GST_BUFFER_PTS (ffmpegdec->pcache) = in_pts; -- GST_BUFFER_DTS (ffmpegdec->pcache) = in_dts; -- GST_BUFFER_OFFSET (ffmpegdec->pcache) = in_offset; -- } else if (bsize > 0) { -- GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize); -- } -- gst_buffer_unref (inbuf); -- -- return ret; -- -- /* ERRORS */ --not_negotiated: -- { -- oclass = (GstFFMpegAudDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec)); -- GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL), -- ("avdec_%s: input format was not set before data start", -- oclass->in_plugin->name)); -- gst_buffer_unref (inbuf); -- return GST_FLOW_NOT_NEGOTIATED; -- } --} -- --static GstStateChangeReturn --gst_ffmpegauddec_change_state (GstElement * element, GstStateChange transition) --{ -- GstFFMpegAudDec *ffmpegdec = (GstFFMpegAudDec *) element; -- GstStateChangeReturn ret; -- -- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); -- -- switch (transition) { -- case GST_STATE_CHANGE_PAUSED_TO_READY: -- GST_OBJECT_LOCK (ffmpegdec); -- gst_ffmpegauddec_close (ffmpegdec); -- GST_OBJECT_UNLOCK (ffmpegdec); -- clear_queued (ffmpegdec); -- break; -- default: -- break; -- } -- -- return ret; --} -- --gboolean --gst_ffmpegauddec_register (GstPlugin * plugin) --{ -- GTypeInfo typeinfo = { -- sizeof (GstFFMpegAudDecClass), -- (GBaseInitFunc) gst_ffmpegauddec_base_init, -- NULL, -- (GClassInitFunc) gst_ffmpegauddec_class_init, -- NULL, -- NULL, -- sizeof (GstFFMpegAudDec), -- 0, -- (GInstanceInitFunc) gst_ffmpegauddec_init, -- }; -- GType type; -- AVCodec *in_plugin; -- gint rank; -- -- in_plugin = av_codec_next (NULL); -- -- GST_LOG ("Registering decoders"); -- -- while (in_plugin) { -- gchar *type_name; -- gchar *plugin_name; -- -- /* only decoders */ -- if (!in_plugin->decode || in_plugin->type != AVMEDIA_TYPE_AUDIO) { -- goto next; -- } -- -- /* no quasi-codecs, please */ -- if (in_plugin->id >= CODEC_ID_PCM_S16LE && -- in_plugin->id <= CODEC_ID_PCM_BLURAY) { -- goto next; -- } -- -- /* No decoders depending on external libraries (we don't build them, but -- * people who build against an external ffmpeg might have them. -- * We have native gstreamer plugins for all of those libraries anyway. */ -- if (!strncmp (in_plugin->name, "lib", 3)) { -- GST_DEBUG -- ("Not using external library decoder %s. Use the gstreamer-native ones instead.", -- in_plugin->name); -- goto next; -- } -- -- GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name); -- -- /* no codecs for which we're GUARANTEED to have better alternatives */ -- /* MP1 : Use MP3 for decoding */ -- /* MP2 : Use MP3 for decoding */ -- /* Theora: Use libtheora based theoradec */ -- if (!strcmp (in_plugin->name, "vorbis") || -- !strcmp (in_plugin->name, "wavpack") || -- !strcmp (in_plugin->name, "mp1") || -- !strcmp (in_plugin->name, "mp2") || -- !strcmp (in_plugin->name, "libfaad") || -- !strcmp (in_plugin->name, "mpeg4aac") || -- !strcmp (in_plugin->name, "ass") || -- !strcmp (in_plugin->name, "srt") || -- !strcmp (in_plugin->name, "pgssub") || -- !strcmp (in_plugin->name, "dvdsub") || -- !strcmp (in_plugin->name, "dvbsub")) { -- GST_LOG ("Ignoring decoder %s", in_plugin->name); -- goto next; -- } -- -- /* construct the type */ -- plugin_name = g_strdup ((gchar *) in_plugin->name); -- g_strdelimit (plugin_name, NULL, '_'); -- type_name = g_strdup_printf ("avdec_%s", plugin_name); -- g_free (plugin_name); -- -- type = g_type_from_name (type_name); -- -- if (!type) { -- /* create the gtype now */ -- type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0); -- g_type_set_qdata (type, GST_FFDEC_PARAMS_QDATA, (gpointer) in_plugin); -- } -- -- /* (Ronald) MPEG-4 gets a higher priority because it has been well- -- * tested and by far outperforms divxdec/xviddec - so we prefer it. -- * msmpeg4v3 same, as it outperforms divxdec for divx3 playback. -- * VC1/WMV3 are not working and thus unpreferred for now. */ -- switch (in_plugin->id) { -- case CODEC_ID_RA_144: -- case CODEC_ID_RA_288: -- case CODEC_ID_COOK: -- rank = GST_RANK_PRIMARY; -- break; -- /* SIPR: decoder should have a higher rank than realaudiodec. -- */ -- case CODEC_ID_SIPR: -- rank = GST_RANK_SECONDARY; -- break; -- case CODEC_ID_MP3: -- rank = GST_RANK_NONE; -- break; -- default: -- rank = GST_RANK_MARGINAL; -- break; -- } -- if (!gst_element_register (plugin, type_name, rank, type)) { -- g_warning ("Failed to register %s", type_name); -- g_free (type_name); -- return FALSE; -- } -- -- g_free (type_name); -- -- next: -- in_plugin = av_codec_next (in_plugin); -- } -- -- GST_LOG ("Finished Registering decoders"); -- -- return TRUE; --} -diff --git a/ext/libav/gstavdeinterlace.c b/ext/libav/gstavdeinterlace.c -index 65961f6..faa81bb 100644 ---- a/ext/libav/gstavdeinterlace.c -+++ b/ext/libav/gstavdeinterlace.c -@@ -16,8 +16,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -203,7 +203,7 @@ gst_ffmpegdeinterlace_sink_setcaps (GstPad * pad, GstCaps * caps) - } - gst_ffmpegdeinterlace_update_passthrough (deinterlace); - -- ctx = avcodec_alloc_context (); -+ ctx = avcodec_alloc_context3 (NULL); - ctx->width = deinterlace->width; - ctx->height = deinterlace->height; - ctx->pix_fmt = PIX_FMT_NB; -diff --git a/ext/libav/gstavdemux.c b/ext/libav/gstavdemux.c -index bee67a5..de0341f 100644 ---- a/ext/libav/gstavdemux.c -+++ b/ext/libav/gstavdemux.c -@@ -15,8 +15,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -32,7 +32,7 @@ - #include "gstav.h" - #include "gstavcodecmap.h" - #include "gstavutils.h" --#include "gstavpipe.h" -+#include "gstavprotocol.h" - - #define MAX_STREAMS 20 - -@@ -332,7 +332,14 @@ gst_ffmpegdemux_close (GstFFMpegDemux * demux) - demux->audiopads = 0; - - /* close demuxer context from ffmpeg */ -- av_close_input_file (demux->context); -+ if (demux->seekable) -+ gst_ffmpegdata_close (demux->context->pb); -+ else -+ gst_ffmpeg_pipe_close (demux->context->pb); -+ demux->context->pb = NULL; -+ avformat_close_input (&demux->context); -+ if (demux->context) -+ avformat_free_context (demux->context); - demux->context = NULL; - - GST_OBJECT_LOCK (demux); -@@ -995,7 +1002,7 @@ gst_ffmpegdemux_get_stream (GstFFMpegDemux * demux, AVStream * avstream) - - - stream_id = -- gst_pad_create_stream_id_printf (pad, GST_ELEMENT_CAST (demux), "%u", -+ gst_pad_create_stream_id_printf (pad, GST_ELEMENT_CAST (demux), "%03u", - avstream->index); - gst_pad_push_event (pad, gst_event_new_stream_start (stream_id)); - g_free (stream_id); -@@ -1115,9 +1122,9 @@ gst_ffmpegdemux_read_tags (GstFFMpegDemux * demux) - static gboolean - gst_ffmpegdemux_open (GstFFMpegDemux * demux) - { -+ AVIOContext *iocontext = NULL; - GstFFMpegDemuxClass *oclass = - (GstFFMpegDemuxClass *) G_OBJECT_GET_CLASS (demux); -- gchar *location; - gint res, n_streams, i; - #if 0 - /* Re-enable once converted to new AVMetaData API -@@ -1133,15 +1140,14 @@ gst_ffmpegdemux_open (GstFFMpegDemux * demux) - - /* open via our input protocol hack */ - if (demux->seekable) -- location = g_strdup_printf ("gstreamer://%p", demux->sinkpad); -+ res = gst_ffmpegdata_open (demux->sinkpad, AVIO_FLAG_READ, &iocontext); - else -- location = g_strdup_printf ("gstpipe://%p", &demux->ffpipe); -- GST_DEBUG_OBJECT (demux, "about to call av_open_input_file %s", location); -+ res = gst_ffmpeg_pipe_open (&demux->ffpipe, AVIO_FLAG_READ, &iocontext); - -- res = av_open_input_file (&demux->context, location, -- oclass->in_plugin, 0, NULL); -+ demux->context = avformat_alloc_context (); -+ demux->context->pb = iocontext; -+ res = avformat_open_input (&demux->context, NULL, oclass->in_plugin, NULL); - -- g_free (location); - GST_DEBUG_OBJECT (demux, "av_open_input returned %d", res); - if (res < 0) - goto open_failed; -diff --git a/ext/libav/gstavenc.c b/ext/libav/gstavenc.c -deleted file mode 100644 -index 312787e..0000000 ---- a/ext/libav/gstavenc.c -+++ /dev/null -@@ -1,825 +0,0 @@ --/* GStreamer -- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * 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 -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- --#ifdef HAVE_CONFIG_H --#include "config.h" --#endif -- --#include <assert.h> --#include <string.h> --/* for stats file handling */ --#include <stdio.h> --#include <glib/gstdio.h> --#include <errno.h> -- --#include <libavcodec/avcodec.h> -- --#include <gst/gst.h> -- --#include "gstav.h" --#include "gstavcodecmap.h" --#include "gstavutils.h" --#include "gstavenc.h" -- --#define DEFAULT_AUDIO_BITRATE 128000 -- --enum --{ -- /* FILL ME */ -- LAST_SIGNAL --}; -- --enum --{ -- ARG_0, -- ARG_BIT_RATE, -- ARG_BUFSIZE, -- ARG_RTP_PAYLOAD_SIZE, --}; -- --/* A number of function prototypes are given so we can refer to them later. */ --static void gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass); --static void gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass); --static void gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc); --static void gst_ffmpegaudenc_finalize (GObject * object); -- --static gboolean gst_ffmpegaudenc_setcaps (GstFFMpegAudEnc * ffmpegenc, -- GstCaps * caps); --static GstCaps *gst_ffmpegaudenc_getcaps (GstFFMpegAudEnc * ffmpegenc, -- GstCaps * filter); --static GstFlowReturn gst_ffmpegaudenc_chain_audio (GstPad * pad, -- GstObject * parent, GstBuffer * buffer); --static gboolean gst_ffmpegaudenc_query_sink (GstPad * pad, GstObject * parent, -- GstQuery * query); --static gboolean gst_ffmpegaudenc_event_sink (GstPad * pad, GstObject * parent, -- GstEvent * event); -- --static void gst_ffmpegaudenc_set_property (GObject * object, -- guint prop_id, const GValue * value, GParamSpec * pspec); --static void gst_ffmpegaudenc_get_property (GObject * object, -- guint prop_id, GValue * value, GParamSpec * pspec); -- --static GstStateChangeReturn gst_ffmpegaudenc_change_state (GstElement * element, -- GstStateChange transition); -- --#define GST_FFENC_PARAMS_QDATA g_quark_from_static_string("avenc-params") -- --static GstElementClass *parent_class = NULL; -- --/*static guint gst_ffmpegaudenc_signals[LAST_SIGNAL] = { 0 }; */ -- --static void --gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass) --{ -- GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -- AVCodec *in_plugin; -- GstPadTemplate *srctempl = NULL, *sinktempl = NULL; -- GstCaps *srccaps = NULL, *sinkcaps = NULL; -- gchar *longname, *description; -- -- in_plugin = -- (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), -- GST_FFENC_PARAMS_QDATA); -- g_assert (in_plugin != NULL); -- -- /* construct the element details struct */ -- longname = g_strdup_printf ("libav %s encoder", in_plugin->long_name); -- description = g_strdup_printf ("libav %s encoder", in_plugin->name); -- gst_element_class_set_metadata (element_class, longname, -- "Codec/Encoder/Audio", description, -- "Wim Taymans <wim.taymans@gmail.com>, " -- "Ronald Bultje <rbultje@ronald.bitfreak.net>"); -- g_free (longname); -- g_free (description); -- -- if (!(srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE))) { -- GST_DEBUG ("Couldn't get source caps for encoder '%s'", in_plugin->name); -- srccaps = gst_caps_new_empty_simple ("unknown/unknown"); -- } -- -- sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL, -- in_plugin->id, TRUE, in_plugin); -- if (!sinkcaps) { -- GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name); -- sinkcaps = gst_caps_new_empty_simple ("unknown/unknown"); -- } -- -- /* pad templates */ -- sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -- GST_PAD_ALWAYS, sinkcaps); -- srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps); -- -- gst_element_class_add_pad_template (element_class, srctempl); -- gst_element_class_add_pad_template (element_class, sinktempl); -- -- klass->in_plugin = in_plugin; -- klass->srctempl = srctempl; -- klass->sinktempl = sinktempl; -- klass->sinkcaps = NULL; -- -- return; --} -- --static void --gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass) --{ -- GObjectClass *gobject_class; -- GstElementClass *gstelement_class; -- -- gobject_class = (GObjectClass *) klass; -- gstelement_class = (GstElementClass *) klass; -- -- parent_class = g_type_class_peek_parent (klass); -- -- gobject_class->set_property = gst_ffmpegaudenc_set_property; -- gobject_class->get_property = gst_ffmpegaudenc_get_property; -- -- /* FIXME: could use -1 for a sensible per-codec defaults */ -- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE, -- g_param_spec_int ("bitrate", "Bit Rate", -- "Target Audio Bitrate", 0, G_MAXINT, DEFAULT_AUDIO_BITRATE, -- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -- -- gstelement_class->change_state = gst_ffmpegaudenc_change_state; -- -- gobject_class->finalize = gst_ffmpegaudenc_finalize; --} -- --static void --gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc) --{ -- GstFFMpegAudEncClass *oclass = -- (GstFFMpegAudEncClass *) (G_OBJECT_GET_CLASS (ffmpegaudenc)); -- -- /* setup pads */ -- ffmpegaudenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink"); -- gst_pad_set_event_function (ffmpegaudenc->sinkpad, -- gst_ffmpegaudenc_event_sink); -- gst_pad_set_query_function (ffmpegaudenc->sinkpad, -- gst_ffmpegaudenc_query_sink); -- gst_pad_set_chain_function (ffmpegaudenc->sinkpad, -- gst_ffmpegaudenc_chain_audio); -- -- ffmpegaudenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src"); -- gst_pad_use_fixed_caps (ffmpegaudenc->srcpad); -- -- /* ffmpeg objects */ -- ffmpegaudenc->context = avcodec_alloc_context (); -- ffmpegaudenc->opened = FALSE; -- -- gst_element_add_pad (GST_ELEMENT (ffmpegaudenc), ffmpegaudenc->sinkpad); -- gst_element_add_pad (GST_ELEMENT (ffmpegaudenc), ffmpegaudenc->srcpad); -- -- ffmpegaudenc->adapter = gst_adapter_new (); --} -- --static void --gst_ffmpegaudenc_finalize (GObject * object) --{ -- GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) object; -- -- -- /* close old session */ -- if (ffmpegaudenc->opened) { -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- ffmpegaudenc->opened = FALSE; -- } -- -- /* clean up remaining allocated data */ -- av_free (ffmpegaudenc->context); -- -- g_object_unref (ffmpegaudenc->adapter); -- -- G_OBJECT_CLASS (parent_class)->finalize (object); --} -- --static GstCaps * --gst_ffmpegaudenc_getcaps (GstFFMpegAudEnc * ffmpegaudenc, GstCaps * filter) --{ -- GstCaps *caps = NULL; -- -- GST_DEBUG_OBJECT (ffmpegaudenc, "getting caps"); -- -- /* audio needs no special care */ -- caps = gst_pad_get_pad_template_caps (ffmpegaudenc->sinkpad); -- -- if (filter) { -- GstCaps *tmp; -- tmp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); -- gst_caps_unref (caps); -- caps = tmp; -- } -- -- GST_DEBUG_OBJECT (ffmpegaudenc, -- "audio caps, return template %" GST_PTR_FORMAT, caps); -- -- return caps; --} -- --static gboolean --gst_ffmpegaudenc_setcaps (GstFFMpegAudEnc * ffmpegaudenc, GstCaps * caps) --{ -- GstCaps *other_caps; -- GstCaps *allowed_caps; -- GstCaps *icaps; -- GstFFMpegAudEncClass *oclass = -- (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc); -- -- /* close old session */ -- if (ffmpegaudenc->opened) { -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- ffmpegaudenc->opened = FALSE; -- } -- -- /* set defaults */ -- avcodec_get_context_defaults (ffmpegaudenc->context); -- -- /* if we set it in _getcaps we should set it also in _link */ -- ffmpegaudenc->context->strict_std_compliance = -1; -- -- /* user defined properties */ -- if (ffmpegaudenc->bitrate > 0) { -- GST_INFO_OBJECT (ffmpegaudenc, "Setting avcontext to bitrate %d", -- ffmpegaudenc->bitrate); -- ffmpegaudenc->context->bit_rate = ffmpegaudenc->bitrate; -- ffmpegaudenc->context->bit_rate_tolerance = ffmpegaudenc->bitrate; -- } else { -- GST_INFO_OBJECT (ffmpegaudenc, "Using avcontext default bitrate %d", -- ffmpegaudenc->context->bit_rate); -- } -- -- /* RTP payload used for GOB production (for Asterisk) */ -- if (ffmpegaudenc->rtp_payload_size) { -- ffmpegaudenc->context->rtp_payload_size = ffmpegaudenc->rtp_payload_size; -- } -- -- /* some other defaults */ -- ffmpegaudenc->context->rc_strategy = 2; -- ffmpegaudenc->context->b_frame_strategy = 0; -- ffmpegaudenc->context->coder_type = 0; -- ffmpegaudenc->context->context_model = 0; -- ffmpegaudenc->context->scenechange_threshold = 0; -- ffmpegaudenc->context->inter_threshold = 0; -- -- -- /* fetch pix_fmt and so on */ -- gst_ffmpeg_caps_with_codectype (oclass->in_plugin->type, -- caps, ffmpegaudenc->context); -- if (!ffmpegaudenc->context->time_base.den) { -- ffmpegaudenc->context->time_base.den = 25; -- ffmpegaudenc->context->time_base.num = 1; -- ffmpegaudenc->context->ticks_per_frame = 1; -- } -- -- /* open codec */ -- if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) { -- if (ffmpegaudenc->context->priv_data) -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- if (ffmpegaudenc->context->stats_in) -- g_free (ffmpegaudenc->context->stats_in); -- GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec", -- oclass->in_plugin->name); -- return FALSE; -- } -- -- /* second pass stats buffer no longer needed */ -- if (ffmpegaudenc->context->stats_in) -- g_free (ffmpegaudenc->context->stats_in); -- -- /* some codecs support more than one format, first auto-choose one */ -- GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ..."); -- allowed_caps = gst_pad_get_allowed_caps (ffmpegaudenc->srcpad); -- if (!allowed_caps) { -- GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps"); -- /* we need to copy because get_allowed_caps returns a ref, and -- * get_pad_template_caps doesn't */ -- allowed_caps = gst_pad_get_pad_template_caps (ffmpegaudenc->srcpad); -- } -- GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps); -- gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id, -- oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context); -- -- /* try to set this caps on the other side */ -- other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id, -- ffmpegaudenc->context, TRUE); -- -- if (!other_caps) { -- gst_caps_unref (allowed_caps); -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- GST_DEBUG ("Unsupported codec - no caps found"); -- return FALSE; -- } -- -- icaps = gst_caps_intersect (allowed_caps, other_caps); -- gst_caps_unref (allowed_caps); -- gst_caps_unref (other_caps); -- if (gst_caps_is_empty (icaps)) { -- gst_caps_unref (icaps); -- return FALSE; -- } -- -- if (gst_caps_get_size (icaps) > 1) { -- GstCaps *newcaps; -- -- newcaps = -- gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (icaps, -- 0)), NULL); -- gst_caps_unref (icaps); -- icaps = newcaps; -- } -- -- if (!gst_pad_set_caps (ffmpegaudenc->srcpad, icaps)) { -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- gst_caps_unref (icaps); -- return FALSE; -- } -- gst_caps_unref (icaps); -- -- /* success! */ -- ffmpegaudenc->opened = TRUE; -- -- return TRUE; --} -- -- --static GstFlowReturn --gst_ffmpegaudenc_encode_audio (GstFFMpegAudEnc * ffmpegaudenc, -- guint8 * audio_in, guint in_size, guint max_size, GstClockTime timestamp, -- GstClockTime duration, gboolean discont) --{ -- GstBuffer *outbuf; -- AVCodecContext *ctx; -- GstMapInfo map; -- gint res; -- GstFlowReturn ret; -- -- ctx = ffmpegaudenc->context; -- -- /* We need to provide at least ffmpegs minimal buffer size */ -- outbuf = gst_buffer_new_and_alloc (max_size + FF_MIN_BUFFER_SIZE); -- gst_buffer_map (outbuf, &map, GST_MAP_WRITE); -- -- GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer of max size %d", max_size); -- if (ffmpegaudenc->buffer_size != max_size) -- ffmpegaudenc->buffer_size = max_size; -- -- res = avcodec_encode_audio (ctx, map.data, max_size, (short *) audio_in); -- -- if (res < 0) { -- gst_buffer_unmap (outbuf, &map); -- GST_ERROR_OBJECT (ffmpegaudenc, "Failed to encode buffer: %d", res); -- gst_buffer_unref (outbuf); -- return GST_FLOW_OK; -- } -- GST_LOG_OBJECT (ffmpegaudenc, "got output size %d", res); -- gst_buffer_unmap (outbuf, &map); -- gst_buffer_resize (outbuf, 0, res); -- -- GST_BUFFER_TIMESTAMP (outbuf) = timestamp; -- GST_BUFFER_DURATION (outbuf) = duration; -- if (discont) -- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); -- -- GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d, timestamp %" GST_TIME_FORMAT, -- res, GST_TIME_ARGS (timestamp)); -- -- ret = gst_pad_push (ffmpegaudenc->srcpad, outbuf); -- -- return ret; --} -- --static GstFlowReturn --gst_ffmpegaudenc_chain_audio (GstPad * pad, GstObject * parent, -- GstBuffer * inbuf) --{ -- GstFFMpegAudEnc *ffmpegaudenc; -- GstFFMpegAudEncClass *oclass; -- AVCodecContext *ctx; -- GstClockTime timestamp, duration; -- gsize size, frame_size; -- gint osize; -- GstFlowReturn ret; -- gint out_size; -- gboolean discont; -- guint8 *in_data; -- -- ffmpegaudenc = (GstFFMpegAudEnc *) parent; -- oclass = (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc); -- -- if (G_UNLIKELY (!ffmpegaudenc->opened)) -- goto not_negotiated; -- -- ctx = ffmpegaudenc->context; -- -- size = gst_buffer_get_size (inbuf); -- timestamp = GST_BUFFER_TIMESTAMP (inbuf); -- duration = GST_BUFFER_DURATION (inbuf); -- discont = GST_BUFFER_IS_DISCONT (inbuf); -- -- GST_DEBUG_OBJECT (ffmpegaudenc, -- "Received time %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT -- ", size %" G_GSIZE_FORMAT, GST_TIME_ARGS (timestamp), -- GST_TIME_ARGS (duration), size); -- -- frame_size = ctx->frame_size; -- osize = av_get_bits_per_sample_format (ctx->sample_fmt) / 8; -- -- if (frame_size > 1) { -- /* we have a frame_size, feed the encoder multiples of this frame size */ -- guint avail, frame_bytes; -- -- if (discont) { -- GST_LOG_OBJECT (ffmpegaudenc, "DISCONT, clear adapter"); -- gst_adapter_clear (ffmpegaudenc->adapter); -- ffmpegaudenc->discont = TRUE; -- } -- -- if (gst_adapter_available (ffmpegaudenc->adapter) == 0) { -- /* lock on to new timestamp */ -- GST_LOG_OBJECT (ffmpegaudenc, "taking buffer timestamp %" GST_TIME_FORMAT, -- GST_TIME_ARGS (timestamp)); -- ffmpegaudenc->adapter_ts = timestamp; -- ffmpegaudenc->adapter_consumed = 0; -- } else { -- GstClockTime upstream_time; -- GstClockTime consumed_time; -- guint64 bytes; -- -- /* use timestamp at head of the adapter */ -- consumed_time = -- gst_util_uint64_scale (ffmpegaudenc->adapter_consumed, GST_SECOND, -- ctx->sample_rate); -- timestamp = ffmpegaudenc->adapter_ts + consumed_time; -- GST_LOG_OBJECT (ffmpegaudenc, "taking adapter timestamp %" GST_TIME_FORMAT -- " and adding consumed time %" GST_TIME_FORMAT, -- GST_TIME_ARGS (ffmpegaudenc->adapter_ts), -- GST_TIME_ARGS (consumed_time)); -- -- /* check with upstream timestamps, if too much deviation, -- * forego some timestamp perfection in favour of upstream syncing -- * (particularly in case these do not happen to come in multiple -- * of frame size) */ -- upstream_time = -- gst_adapter_prev_timestamp (ffmpegaudenc->adapter, &bytes); -- if (GST_CLOCK_TIME_IS_VALID (upstream_time)) { -- GstClockTimeDiff diff; -- -- upstream_time += -- gst_util_uint64_scale (bytes, GST_SECOND, -- ctx->sample_rate * osize * ctx->channels); -- diff = upstream_time - timestamp; -- /* relaxed difference, rather than half a sample or so ... */ -- if (diff > GST_SECOND / 10 || diff < -GST_SECOND / 10) { -- GST_DEBUG_OBJECT (ffmpegaudenc, "adapter timestamp drifting, " -- "taking upstream timestamp %" GST_TIME_FORMAT, -- GST_TIME_ARGS (upstream_time)); -- timestamp = upstream_time; -- /* samples corresponding to bytes */ -- ffmpegaudenc->adapter_consumed = bytes / (osize * ctx->channels); -- ffmpegaudenc->adapter_ts = upstream_time - -- gst_util_uint64_scale (ffmpegaudenc->adapter_consumed, GST_SECOND, -- ctx->sample_rate); -- ffmpegaudenc->discont = TRUE; -- } -- } -- } -- -- GST_LOG_OBJECT (ffmpegaudenc, "pushing buffer in adapter"); -- gst_adapter_push (ffmpegaudenc->adapter, inbuf); -- -- /* first see how many bytes we need to feed to the decoder. */ -- frame_bytes = frame_size * osize * ctx->channels; -- avail = gst_adapter_available (ffmpegaudenc->adapter); -- -- GST_LOG_OBJECT (ffmpegaudenc, "frame_bytes %u, avail %u", frame_bytes, -- avail); -- -- /* while there is more than a frame size in the adapter, consume it */ -- while (avail >= frame_bytes) { -- GST_LOG_OBJECT (ffmpegaudenc, "taking %u bytes from the adapter", -- frame_bytes); -- -- /* Note that we take frame_bytes and add frame_size. -- * Makes sense when resyncing because you don't have to count channels -- * or samplesize to divide by the samplerate */ -- -- /* take an audio buffer out of the adapter */ -- in_data = (guint8 *) gst_adapter_map (ffmpegaudenc->adapter, frame_bytes); -- ffmpegaudenc->adapter_consumed += frame_size; -- -- /* calculate timestamp and duration relative to start of adapter and to -- * the amount of samples we consumed */ -- duration = -- gst_util_uint64_scale (ffmpegaudenc->adapter_consumed, GST_SECOND, -- ctx->sample_rate); -- duration -= (timestamp - ffmpegaudenc->adapter_ts); -- -- /* 4 times the input size should be big enough... */ -- out_size = frame_bytes * 4; -- -- ret = -- gst_ffmpegaudenc_encode_audio (ffmpegaudenc, in_data, frame_bytes, -- out_size, timestamp, duration, ffmpegaudenc->discont); -- -- gst_adapter_unmap (ffmpegaudenc->adapter); -- gst_adapter_flush (ffmpegaudenc->adapter, frame_bytes); -- -- if (ret != GST_FLOW_OK) -- goto push_failed; -- -- /* advance the adapter timestamp with the duration */ -- timestamp += duration; -- -- ffmpegaudenc->discont = FALSE; -- avail = gst_adapter_available (ffmpegaudenc->adapter); -- } -- GST_LOG_OBJECT (ffmpegaudenc, "%u bytes left in the adapter", avail); -- } else { -- GstMapInfo map; -- /* we have no frame_size, feed the encoder all the data and expect a fixed -- * output size */ -- int coded_bps = av_get_bits_per_sample (oclass->in_plugin->id); -- -- GST_LOG_OBJECT (ffmpegaudenc, "coded bps %d, osize %d", coded_bps, osize); -- -- out_size = size / osize; -- if (coded_bps) -- out_size = (out_size * coded_bps) / 8; -- -- gst_buffer_map (inbuf, &map, GST_MAP_READ); -- in_data = map.data; -- size = map.size; -- ret = gst_ffmpegaudenc_encode_audio (ffmpegaudenc, in_data, size, out_size, -- timestamp, duration, discont); -- gst_buffer_unmap (inbuf, &map); -- gst_buffer_unref (inbuf); -- -- if (ret != GST_FLOW_OK) -- goto push_failed; -- } -- -- return GST_FLOW_OK; -- -- /* ERRORS */ --not_negotiated: -- { -- GST_ELEMENT_ERROR (ffmpegaudenc, CORE, NEGOTIATION, (NULL), -- ("not configured to input format before data start")); -- gst_buffer_unref (inbuf); -- return GST_FLOW_NOT_NEGOTIATED; -- } --push_failed: -- { -- GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to push buffer %d (%s)", ret, -- gst_flow_get_name (ret)); -- return ret; -- } --} -- --static gboolean --gst_ffmpegaudenc_event_sink (GstPad * pad, GstObject * parent, GstEvent * event) --{ -- GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) parent; -- -- switch (GST_EVENT_TYPE (event)) { -- case GST_EVENT_CAPS: -- { -- GstCaps *caps; -- gboolean ret; -- -- gst_event_parse_caps (event, &caps); -- ret = gst_ffmpegaudenc_setcaps (ffmpegaudenc, caps); -- gst_event_unref (event); -- return ret; -- } -- default: -- break; -- } -- -- return gst_pad_event_default (pad, parent, event); --} -- --static gboolean --gst_ffmpegaudenc_query_sink (GstPad * pad, GstObject * parent, GstQuery * query) --{ -- GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) parent; -- gboolean res = FALSE; -- -- switch (GST_QUERY_TYPE (query)) { -- case GST_QUERY_CAPS: -- { -- GstCaps *filter, *caps; -- -- gst_query_parse_caps (query, &filter); -- caps = gst_ffmpegaudenc_getcaps (ffmpegaudenc, filter); -- gst_query_set_caps_result (query, caps); -- gst_caps_unref (caps); -- res = TRUE; -- break; -- } -- default: -- res = gst_pad_query_default (pad, parent, query); -- break; -- } -- -- return res; --} -- --static void --gst_ffmpegaudenc_set_property (GObject * object, -- guint prop_id, const GValue * value, GParamSpec * pspec) --{ -- GstFFMpegAudEnc *ffmpegaudenc; -- -- /* Get a pointer of the right type. */ -- ffmpegaudenc = (GstFFMpegAudEnc *) (object); -- -- if (ffmpegaudenc->opened) { -- GST_WARNING_OBJECT (ffmpegaudenc, -- "Can't change properties once decoder is setup !"); -- return; -- } -- -- /* Check the argument id to see which argument we're setting. */ -- switch (prop_id) { -- case ARG_BIT_RATE: -- ffmpegaudenc->bitrate = g_value_get_int (value); -- break; -- case ARG_BUFSIZE: -- break; -- case ARG_RTP_PAYLOAD_SIZE: -- ffmpegaudenc->rtp_payload_size = g_value_get_int (value); -- break; -- default: -- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -- break; -- } --} -- --/* The set function is simply the inverse of the get fuction. */ --static void --gst_ffmpegaudenc_get_property (GObject * object, -- guint prop_id, GValue * value, GParamSpec * pspec) --{ -- GstFFMpegAudEnc *ffmpegaudenc; -- -- /* It's not null if we got it, but it might not be ours */ -- ffmpegaudenc = (GstFFMpegAudEnc *) (object); -- -- switch (prop_id) { -- case ARG_BIT_RATE: -- g_value_set_int (value, ffmpegaudenc->bitrate); -- break; -- break; -- case ARG_BUFSIZE: -- g_value_set_int (value, ffmpegaudenc->buffer_size); -- break; -- case ARG_RTP_PAYLOAD_SIZE: -- g_value_set_int (value, ffmpegaudenc->rtp_payload_size); -- break; -- default: -- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -- break; -- } --} -- --static GstStateChangeReturn --gst_ffmpegaudenc_change_state (GstElement * element, GstStateChange transition) --{ -- GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) element; -- GstStateChangeReturn result; -- -- switch (transition) { -- default: -- break; -- } -- -- result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); -- -- switch (transition) { -- case GST_STATE_CHANGE_PAUSED_TO_READY: -- if (ffmpegaudenc->opened) { -- gst_ffmpeg_avcodec_close (ffmpegaudenc->context); -- ffmpegaudenc->opened = FALSE; -- } -- gst_adapter_clear (ffmpegaudenc->adapter); -- break; -- default: -- break; -- } -- return result; --} -- --gboolean --gst_ffmpegaudenc_register (GstPlugin * plugin) --{ -- GTypeInfo typeinfo = { -- sizeof (GstFFMpegAudEncClass), -- (GBaseInitFunc) gst_ffmpegaudenc_base_init, -- NULL, -- (GClassInitFunc) gst_ffmpegaudenc_class_init, -- NULL, -- NULL, -- sizeof (GstFFMpegAudEnc), -- 0, -- (GInstanceInitFunc) gst_ffmpegaudenc_init, -- }; -- GType type; -- AVCodec *in_plugin; -- -- -- GST_LOG ("Registering encoders"); -- -- in_plugin = av_codec_next (NULL); -- while (in_plugin) { -- gchar *type_name; -- -- /* Skip non-AV codecs */ -- if (in_plugin->type != AVMEDIA_TYPE_AUDIO) -- goto next; -- -- /* no quasi codecs, please */ -- if ((in_plugin->id >= CODEC_ID_PCM_S16LE && -- in_plugin->id <= CODEC_ID_PCM_BLURAY)) { -- goto next; -- } -- -- /* No encoders depending on external libraries (we don't build them, but -- * people who build against an external ffmpeg might have them. -- * We have native gstreamer plugins for all of those libraries anyway. */ -- if (!strncmp (in_plugin->name, "lib", 3)) { -- GST_DEBUG -- ("Not using external library encoder %s. Use the gstreamer-native ones instead.", -- in_plugin->name); -- goto next; -- } -- -- /* only encoders */ -- if (!in_plugin->encode) { -- goto next; -- } -- -- /* FIXME : We should have a method to know cheaply whether we have a mapping -- * for the given plugin or not */ -- -- GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name); -- -- /* no codecs for which we're GUARANTEED to have better alternatives */ -- if (!strcmp (in_plugin->name, "vorbis") -- || !strcmp (in_plugin->name, "flac")) { -- GST_LOG ("Ignoring encoder %s", in_plugin->name); -- goto next; -- } -- -- /* construct the type */ -- type_name = g_strdup_printf ("avenc_%s", in_plugin->name); -- -- type = g_type_from_name (type_name); -- -- if (!type) { -- -- /* create the glib type now */ -- type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0); -- g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin); -- -- { -- static const GInterfaceInfo preset_info = { -- NULL, -- NULL, -- NULL -- }; -- g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info); -- } -- } -- -- if (!gst_element_register (plugin, type_name, GST_RANK_SECONDARY, type)) { -- g_free (type_name); -- return FALSE; -- } -- -- g_free (type_name); -- -- next: -- in_plugin = av_codec_next (in_plugin); -- } -- -- GST_LOG ("Finished registering encoders"); -- -- return TRUE; --} -diff --git a/ext/libav/gstavenc.h b/ext/libav/gstavenc.h -deleted file mode 100644 -index 019b168..0000000 ---- a/ext/libav/gstavenc.h -+++ /dev/null -@@ -1,82 +0,0 @@ --/* GStreamer -- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * 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 -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- --/* First, include the header file for the plugin, to bring in the -- * object definition and other useful things. -- */ -- --#ifndef __GST_FFMPEGAUDENC_H__ --#define __GST_FFMPEGAUDENC_H__ -- --G_BEGIN_DECLS -- --#include <gst/base/gstadapter.h> -- --typedef struct _GstFFMpegAudEnc GstFFMpegAudEnc; -- --struct _GstFFMpegAudEnc --{ -- GstElement element; -- -- /* We need to keep track of our pads, so we do so here. */ -- GstPad *srcpad; -- GstPad *sinkpad; -- -- AVCodecContext *context; -- gboolean opened; -- GstClockTime adapter_ts; -- guint64 adapter_consumed; -- GstAdapter *adapter; -- gboolean discont; -- -- /* cache */ -- gint bitrate; -- gint buffer_size; -- gint rtp_payload_size; -- -- /* other settings are copied over straight, -- * include a context here, rather than copy-and-past it from avcodec.h */ -- AVCodecContext config; --}; -- --typedef struct _GstFFMpegAudEncClass GstFFMpegAudEncClass; -- --struct _GstFFMpegAudEncClass --{ -- GstElementClass parent_class; -- -- AVCodec *in_plugin; -- GstPadTemplate *srctempl, *sinktempl; -- GstCaps *sinkcaps; --}; -- --#define GST_TYPE_FFMPEGAUDENC \ -- (gst_ffmpegaudenc_get_type()) --#define GST_FFMPEGAUDENC(obj) \ -- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGAUDENC,GstFFMpegAudEnc)) --#define GST_FFMPEGAUDENC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGAUDENC,GstFFMpegAudEncClass)) --#define GST_IS_FFMPEGAUDENC(obj) \ -- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGAUDENC)) --#define GST_IS_FFMPEGAUDENC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGAUDENC)) -- --G_END_DECLS -- --#endif /* __GST_FFMPEGAUDENC_H__ */ -diff --git a/ext/libav/gstavmux.c b/ext/libav/gstavmux.c -index d9e8969..b302270 100644 ---- a/ext/libav/gstavmux.c -+++ b/ext/libav/gstavmux.c -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -24,12 +24,14 @@ - #include <string.h> - - #include <libavformat/avformat.h> -+#include <libavutil/opt.h> - #include <gst/gst.h> - #include <gst/base/gstcollectpads.h> - - #include "gstav.h" - #include "gstavcodecmap.h" - #include "gstavutils.h" -+#include "gstavprotocol.h" - - typedef struct _GstFFMpegMux GstFFMpegMux; - typedef struct _GstFFMpegMuxPad GstFFMpegMuxPad; -@@ -57,8 +59,8 @@ struct _GstFFMpegMux - /*< private > */ - /* event_function is the collectpads default eventfunction */ - GstPadEventFunction event_function; -- int preload; - int max_delay; -+ int preload; - }; - - typedef struct _GstFFMpegMuxClass GstFFMpegMuxClass; -@@ -89,12 +91,6 @@ enum - - enum - { -- ARG_0, -- /* FILL ME */ --}; -- --enum --{ - PROP_0, - PROP_PRELOAD, - PROP_MAXDELAY -@@ -301,8 +297,8 @@ gst_ffmpegmux_class_init (GstFFMpegMuxClass * klass) - - g_object_class_install_property (gobject_class, PROP_PRELOAD, - g_param_spec_int ("preload", "preload", -- "Set the initial demux-decode delay (in microseconds)", 0, G_MAXINT, -- 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -+ "Set the initial demux-decode delay (in microseconds)", -+ 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_MAXDELAY, - g_param_spec_int ("maxdelay", "maxdelay", -@@ -329,17 +325,13 @@ gst_ffmpegmux_init (GstFFMpegMux * ffmpegmux, GstFFMpegMuxClass * g_class) - gst_collect_pads_set_function (ffmpegmux->collect, - (GstCollectPadsFunction) gst_ffmpegmux_collected, ffmpegmux); - -- ffmpegmux->context = g_new0 (AVFormatContext, 1); -+ ffmpegmux->context = avformat_alloc_context (); - ffmpegmux->context->oformat = oclass->in_plugin; - ffmpegmux->context->nb_streams = 0; -- g_snprintf (ffmpegmux->context->filename, -- sizeof (ffmpegmux->context->filename), -- "gstreamer://%p", ffmpegmux->srcpad); - ffmpegmux->opened = FALSE; - - ffmpegmux->videopads = 0; - ffmpegmux->audiopads = 0; -- ffmpegmux->preload = 0; - ffmpegmux->max_delay = 0; - } - -@@ -391,7 +383,9 @@ gst_ffmpegmux_finalize (GObject * object) - { - GstFFMpegMux *ffmpegmux = (GstFFMpegMux *) object; - -- g_free (ffmpegmux->context); -+ avformat_free_context (ffmpegmux->context); -+ ffmpegmux->context = NULL; -+ - gst_object_unref (ffmpegmux->collect); - - if (G_OBJECT_CLASS (parent_class)->finalize) -@@ -445,10 +439,10 @@ gst_ffmpegmux_request_new_pad (GstElement * element, - gst_element_add_pad (element, pad); - - /* AVStream needs to be created */ -- st = av_new_stream (ffmpegmux->context, collect_pad->padnum); -+ st = avformat_new_stream (ffmpegmux->context, NULL); -+ st->id = collect_pad->padnum; - st->codec->codec_type = type; - st->codec->codec_id = CODEC_ID_NONE; /* this is a check afterwards */ -- st->stream_copy = 1; /* we're not the actual encoder */ - st->codec->bit_rate = bitrate; - st->codec->frame_size = framesize; - /* we fill in codec during capsnego */ -@@ -480,7 +474,7 @@ gst_ffmpegmux_setcaps (GstPad * pad, GstCaps * caps) - collect_pad = (GstFFMpegMuxPad *) gst_pad_get_element_private (pad); - - st = ffmpegmux->context->streams[collect_pad->padnum]; -- ffmpegmux->context->preload = ffmpegmux->preload; -+ av_opt_set_int (&ffmpegmux->context, "preload", ffmpegmux->preload, 0); - ffmpegmux->context->max_delay = ffmpegmux->max_delay; - - /* for the format-specific guesses, we'll go to -@@ -554,7 +548,7 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data) - - /* open "file" (gstreamer protocol to next element) */ - if (!ffmpegmux->opened) { -- int open_flags = URL_WRONLY; -+ int open_flags = AVIO_FLAG_WRITE; - - /* we do need all streams to have started capsnego, - * or things will go horribly wrong */ -@@ -648,21 +642,15 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data) - open_flags |= GST_FFMPEG_URL_STREAMHEADER; - } - -- if (url_fopen (&ffmpegmux->context->pb, -- ffmpegmux->context->filename, open_flags) < 0) { -+ if (gst_ffmpegdata_open (ffmpegmux->srcpad, open_flags, -+ &ffmpegmux->context->pb) < 0) { - GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, TOO_LAZY, (NULL), - ("Failed to open stream context in avmux")); - return GST_FLOW_ERROR; - } - -- if (av_set_parameters (ffmpegmux->context, NULL) < 0) { -- GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, INIT, (NULL), -- ("Failed to initialize muxer")); -- return GST_FLOW_ERROR; -- } -- - /* now open the mux format */ -- if (av_write_header (ffmpegmux->context) < 0) { -+ if (avformat_write_header (ffmpegmux->context, NULL) < 0) { - GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, SETTINGS, (NULL), - ("Failed to write file header - check codec settings")); - return GST_FLOW_ERROR; -@@ -672,7 +660,7 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data) - ffmpegmux->opened = TRUE; - - /* flush the header so it will be used as streamheader */ -- put_flush_packet (ffmpegmux->context->pb); -+ avio_flush (ffmpegmux->context->pb); - } - - /* take the one with earliest timestamp, -@@ -779,8 +767,8 @@ gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data) - /* close down */ - av_write_trailer (ffmpegmux->context); - ffmpegmux->opened = FALSE; -- put_flush_packet (ffmpegmux->context->pb); -- url_fclose (ffmpegmux->context->pb); -+ avio_flush (ffmpegmux->context->pb); -+ gst_ffmpegdata_close (ffmpegmux->context->pb); - gst_pad_push_event (ffmpegmux->srcpad, gst_event_new_eos ()); - return GST_FLOW_EOS; - } -@@ -818,7 +806,7 @@ gst_ffmpegmux_change_state (GstElement * element, GstStateChange transition) - gst_tag_setter_reset_tags (GST_TAG_SETTER (ffmpegmux)); - if (ffmpegmux->opened) { - ffmpegmux->opened = FALSE; -- url_fclose (ffmpegmux->context->pb); -+ gst_ffmpegdata_close (ffmpegmux->context->pb); - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: -diff --git a/ext/libav/gstavpipe.h b/ext/libav/gstavpipe.h -deleted file mode 100644 -index 5ded77f..0000000 ---- a/ext/libav/gstavpipe.h -+++ /dev/null -@@ -1,72 +0,0 @@ --/* GStreamer -- * Copyright (C) <2006> Mark Nauwelaerts <manauw@skynet.be> -- * -- * This library is free software; you can redistribute it and/or -- * modify it under the terms of the GNU Library General Public -- * License as published by the Free Software Foundation; either -- * version 2 of the License, or (at your option) any later version. -- * -- * 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 -- * Library General Public License for more details. -- * -- * You should have received a copy of the GNU Library General Public -- * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -- */ -- -- --#ifndef __GST_FFMPEGPIPE_H__ --#define __GST_FFMPEGPIPE_H__ -- --#include <gst/base/gstadapter.h> --#include "gstav.h" -- --G_BEGIN_DECLS -- --/* pipe protocol helpers */ --#define GST_FFMPEG_PIPE_MUTEX_LOCK(m) G_STMT_START { \ -- GST_LOG_OBJECT (m, "locking tlock from thread %p", g_thread_self ()); \ -- g_mutex_lock (&m->tlock); \ -- GST_LOG_OBJECT (m, "locked tlock from thread %p", g_thread_self ()); \ --} G_STMT_END -- --#define GST_FFMPEG_PIPE_MUTEX_UNLOCK(m) G_STMT_START { \ -- GST_LOG_OBJECT (m, "unlocking tlock from thread %p", g_thread_self ()); \ -- g_mutex_unlock (&m->tlock); \ --} G_STMT_END -- --#define GST_FFMPEG_PIPE_WAIT(m) G_STMT_START { \ -- GST_LOG_OBJECT (m, "thread %p waiting", g_thread_self ()); \ -- g_cond_wait (&m->cond, &m->tlock); \ --} G_STMT_END -- --#define GST_FFMPEG_PIPE_SIGNAL(m) G_STMT_START { \ -- GST_LOG_OBJECT (m, "signalling from thread %p", g_thread_self ()); \ -- g_cond_signal (&m->cond); \ --} G_STMT_END -- --typedef struct _GstFFMpegPipe GstFFMpegPipe; -- --struct _GstFFMpegPipe --{ -- /* lock for syncing */ -- GMutex tlock; -- /* with TLOCK */ -- /* signals counterpart thread to have a look */ -- GCond cond; -- /* seen eos */ -- gboolean eos; -- /* flowreturn obtained by src task */ -- GstFlowReturn srcresult; -- /* adpater collecting data */ -- GstAdapter *adapter; -- /* amount needed in adapter by src task */ -- guint needed; --}; -- --G_END_DECLS -- --#endif /* __GST_FFMPEGPIPE_H__ */ -diff --git a/ext/libav/gstavprotocol.c b/ext/libav/gstavprotocol.c -index 9c4b052..5d01eaa 100644 ---- a/ext/libav/gstavprotocol.c -+++ b/ext/libav/gstavprotocol.c -@@ -14,8 +14,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -29,7 +29,7 @@ - #include <gst/gst.h> - - #include "gstav.h" --#include "gstavpipe.h" -+#include "gstavprotocol.h" - - typedef struct _GstProtocolInfo GstProtocolInfo; - -@@ -43,63 +43,14 @@ struct _GstProtocolInfo - }; - - static int --gst_ffmpegdata_open (URLContext * h, const char *filename, int flags) --{ -- GstProtocolInfo *info; -- GstPad *pad; -- -- GST_LOG ("Opening %s", filename); -- -- info = g_new0 (GstProtocolInfo, 1); -- -- info->set_streamheader = flags & GST_FFMPEG_URL_STREAMHEADER; -- flags &= ~GST_FFMPEG_URL_STREAMHEADER; -- h->flags &= ~GST_FFMPEG_URL_STREAMHEADER; -- -- /* we don't support R/W together */ -- if (flags != URL_RDONLY && flags != URL_WRONLY) { -- GST_WARNING ("Only read-only or write-only are supported"); -- return -EINVAL; -- } -- -- if (sscanf (&filename[12], "%p", &pad) != 1) { -- GST_WARNING ("could not decode pad from %s", filename); -- return -EIO; -- } -- -- /* make sure we're a pad and that we're of the right type */ -- g_return_val_if_fail (GST_IS_PAD (pad), -EINVAL); -- -- switch (flags) { -- case URL_RDONLY: -- g_return_val_if_fail (GST_PAD_IS_SINK (pad), -EINVAL); -- break; -- case URL_WRONLY: -- g_return_val_if_fail (GST_PAD_IS_SRC (pad), -EINVAL); -- break; -- } -- -- info->eos = FALSE; -- info->pad = pad; -- info->offset = 0; -- -- h->priv_data = (void *) info; -- h->is_streamed = FALSE; -- h->max_packet_size = 0; -- -- return 0; --} -- --static int --gst_ffmpegdata_peek (URLContext * h, unsigned char *buf, int size) -+gst_ffmpegdata_peek (void *priv_data, unsigned char *buf, int size) - { - GstProtocolInfo *info; - GstBuffer *inbuf = NULL; - GstFlowReturn ret; - int total = 0; - -- g_return_val_if_fail (h->flags == URL_RDONLY, AVERROR (EIO)); -- info = (GstProtocolInfo *) h->priv_data; -+ info = (GstProtocolInfo *) priv_data; - - GST_DEBUG ("Pulling %d bytes at position %" G_GUINT64_FORMAT, size, - info->offset); -@@ -131,17 +82,17 @@ gst_ffmpegdata_peek (URLContext * h, unsigned char *buf, int size) - } - - static int --gst_ffmpegdata_read (URLContext * h, unsigned char *buf, int size) -+gst_ffmpegdata_read (void *priv_data, unsigned char *buf, int size) - { - gint res; - GstProtocolInfo *info; - -- info = (GstProtocolInfo *) h->priv_data; -+ info = (GstProtocolInfo *) priv_data; - - GST_DEBUG ("Reading %d bytes of data at position %" G_GUINT64_FORMAT, size, - info->offset); - -- res = gst_ffmpegdata_peek (h, buf, size); -+ res = gst_ffmpegdata_peek (priv_data, buf, size); - if (res >= 0) - info->offset += res; - -@@ -151,15 +102,13 @@ gst_ffmpegdata_read (URLContext * h, unsigned char *buf, int size) - } - - static int --gst_ffmpegdata_write (URLContext * h, const unsigned char *buf, int size) -+gst_ffmpegdata_write (void *priv_data, uint8_t * buf, int size) - { - GstProtocolInfo *info; - GstBuffer *outbuf; - - GST_DEBUG ("Writing %d bytes", size); -- info = (GstProtocolInfo *) h->priv_data; -- -- g_return_val_if_fail (h->flags != URL_RDONLY, -EIO); -+ info = (GstProtocolInfo *) priv_data; - - /* create buffer and push data further */ - outbuf = gst_buffer_new_and_alloc (size); -@@ -174,7 +123,7 @@ gst_ffmpegdata_write (URLContext * h, const unsigned char *buf, int size) - } - - static int64_t --gst_ffmpegdata_seek (URLContext * h, int64_t pos, int whence) -+gst_ffmpegdata_seek (void *priv_data, int64_t pos, int whence) - { - GstProtocolInfo *info; - guint64 newpos = 0, oldpos; -@@ -182,76 +131,68 @@ gst_ffmpegdata_seek (URLContext * h, int64_t pos, int whence) - GST_DEBUG ("Seeking to %" G_GINT64_FORMAT ", whence=%d", - (gint64) pos, whence); - -- info = (GstProtocolInfo *) h->priv_data; -+ info = (GstProtocolInfo *) priv_data; - - /* TODO : if we are push-based, we need to return sensible info */ - -- switch (h->flags) { -- case URL_RDONLY: -- { -- /* sinkpad */ -- switch (whence) { -- case SEEK_SET: -- newpos = (guint64) pos; -- break; -- case SEEK_CUR: -- newpos = info->offset + pos; -- break; -- case SEEK_END: -- case AVSEEK_SIZE: -- /* ffmpeg wants to know the current end position in bytes ! */ -- { -- gint64 duration; -- -- GST_DEBUG ("Seek end"); -- -- if (gst_pad_is_linked (info->pad)) -- if (gst_pad_query_duration (GST_PAD_PEER (info->pad), -- GST_FORMAT_BYTES, &duration)) -- newpos = ((guint64) duration) + pos; -- } -- break; -- default: -- g_assert (0); -- break; -+ if (GST_PAD_IS_SINK (info->pad)) { -+ /* sinkpad */ -+ switch (whence) { -+ case SEEK_SET: -+ newpos = (guint64) pos; -+ break; -+ case SEEK_CUR: -+ newpos = info->offset + pos; -+ break; -+ case SEEK_END: -+ case AVSEEK_SIZE: -+ /* ffmpeg wants to know the current end position in bytes ! */ -+ { -+ gint64 duration; -+ -+ GST_DEBUG ("Seek end"); -+ -+ if (gst_pad_is_linked (info->pad)) -+ if (gst_pad_query_duration (GST_PAD_PEER (info->pad), -+ GST_FORMAT_BYTES, &duration)) -+ newpos = ((guint64) duration) + pos; - } -- /* FIXME : implement case for push-based behaviour */ -- if (whence != AVSEEK_SIZE) -- info->offset = newpos; -+ break; -+ default: -+ g_assert (0); -+ break; - } -- break; -- case URL_WRONLY: -- { -- GstSegment segment; -- -- oldpos = info->offset; -- -- /* srcpad */ -- switch (whence) { -- case SEEK_SET: -- { -- info->offset = (guint64) pos; -- break; -- } -- case SEEK_CUR: -- info->offset += pos; -- break; -- default: -- break; -+ /* FIXME : implement case for push-based behaviour */ -+ if (whence != AVSEEK_SIZE) -+ info->offset = newpos; -+ } else if (GST_PAD_IS_SRC (info->pad)) { -+ GstSegment segment; -+ -+ oldpos = info->offset; -+ -+ /* srcpad */ -+ switch (whence) { -+ case SEEK_SET: -+ { -+ info->offset = (guint64) pos; -+ break; - } -- newpos = info->offset; -+ case SEEK_CUR: -+ info->offset += pos; -+ break; -+ default: -+ break; -+ } -+ newpos = info->offset; - -- if (newpos != oldpos) { -- gst_segment_init (&segment, GST_FORMAT_BYTES); -- segment.start = newpos; -- segment.time = newpos; -- gst_pad_push_event (info->pad, gst_event_new_segment (&segment)); -- } -- break; -+ if (newpos != oldpos) { -+ gst_segment_init (&segment, GST_FORMAT_BYTES); -+ segment.start = newpos; -+ segment.time = newpos; -+ gst_pad_push_event (info->pad, gst_event_new_segment (&segment)); - } -- default: -- g_assert (0); -- break; -+ } else { -+ g_assert_not_reached (); - } - - GST_DEBUG ("Now at offset %" G_GUINT64_FORMAT " (returning %" G_GUINT64_FORMAT -@@ -259,84 +200,90 @@ gst_ffmpegdata_seek (URLContext * h, int64_t pos, int whence) - return newpos; - } - --static int --gst_ffmpegdata_close (URLContext * h) -+int -+gst_ffmpegdata_close (AVIOContext * h) - { - GstProtocolInfo *info; - -- info = (GstProtocolInfo *) h->priv_data; -+ info = (GstProtocolInfo *) h->opaque; - if (info == NULL) - return 0; - - GST_LOG ("Closing file"); - -- switch (h->flags) { -- case URL_WRONLY: -- { -- /* send EOS - that closes down the stream */ -- gst_pad_push_event (info->pad, gst_event_new_eos ()); -- break; -- } -- default: -- break; -+ if (GST_PAD_IS_SRC (info->pad)) { -+ /* send EOS - that closes down the stream */ -+ gst_pad_push_event (info->pad, gst_event_new_eos ()); - } - - /* clean up data */ - g_free (info); -- h->priv_data = NULL; -+ h->opaque = NULL; -+ -+ av_freep (&h->buffer); -+ av_free (h); - - return 0; - } - -+int -+gst_ffmpegdata_open (GstPad * pad, int flags, AVIOContext ** context) -+{ -+ GstProtocolInfo *info; -+ static const int buffer_size = 4096; -+ unsigned char *buffer = NULL; - --URLProtocol gstreamer_protocol = { -- /*.name = */ "gstreamer", -- /*.url_open = */ gst_ffmpegdata_open, -- /*.url_read = */ gst_ffmpegdata_read, -- /*.url_write = */ gst_ffmpegdata_write, -- /*.url_seek = */ gst_ffmpegdata_seek, -- /*.url_close = */ gst_ffmpegdata_close, --}; -+ info = g_new0 (GstProtocolInfo, 1); - -+ info->set_streamheader = flags & GST_FFMPEG_URL_STREAMHEADER; -+ flags &= ~GST_FFMPEG_URL_STREAMHEADER; - --/* specialized protocol for cross-thread pushing, -- * based on ffmpeg's pipe protocol */ -+ /* we don't support R/W together */ -+ if ((flags & AVIO_FLAG_WRITE) && (flags & AVIO_FLAG_READ)) { -+ GST_WARNING ("Only read-only or write-only are supported"); -+ return -EINVAL; -+ } - --static int --gst_ffmpeg_pipe_open (URLContext * h, const char *filename, int flags) --{ -- GstFFMpegPipe *ffpipe; -+ /* make sure we're a pad and that we're of the right type */ -+ g_return_val_if_fail (GST_IS_PAD (pad), -EINVAL); - -- GST_LOG ("Opening %s", filename); -+ if ((flags & AVIO_FLAG_READ)) -+ g_return_val_if_fail (GST_PAD_IS_SINK (pad), -EINVAL); -+ if ((flags & AVIO_FLAG_WRITE)) -+ g_return_val_if_fail (GST_PAD_IS_SRC (pad), -EINVAL); - -- /* we don't support W together */ -- if (flags != URL_RDONLY) { -- GST_WARNING ("Only read-only is supported"); -- return -EINVAL; -- } -+ info->eos = FALSE; -+ info->pad = pad; -+ info->offset = 0; - -- if (sscanf (&filename[10], "%p", &ffpipe) != 1) { -- GST_WARNING ("could not decode pipe info from %s", filename); -- return -EIO; -+ buffer = av_malloc (buffer_size); -+ if (buffer == NULL) { -+ GST_WARNING ("Failed to allocate buffer"); -+ return -ENOMEM; - } - -- /* sanity check */ -- g_return_val_if_fail (GST_IS_ADAPTER (ffpipe->adapter), -EINVAL); -- -- h->priv_data = (void *) ffpipe; -- h->is_streamed = TRUE; -- h->max_packet_size = 0; -+ *context = -+ avio_alloc_context (buffer, buffer_size, flags, (void *) info, -+ gst_ffmpegdata_read, gst_ffmpegdata_write, gst_ffmpegdata_seek); -+ (*context)->seekable = AVIO_SEEKABLE_NORMAL; -+ if (!(flags & AVIO_FLAG_WRITE)) { -+ (*context)->buf_ptr = (*context)->buf_end; -+ (*context)->write_flag = 0; -+ } - - return 0; - } - -+/* specialized protocol for cross-thread pushing, -+ * based on ffmpeg's pipe protocol */ -+ - static int --gst_ffmpeg_pipe_read (URLContext * h, unsigned char *buf, int size) -+gst_ffmpeg_pipe_read (void *priv_data, uint8_t * buf, int size) - { - GstFFMpegPipe *ffpipe; - guint available; - -- ffpipe = (GstFFMpegPipe *) h->priv_data; -+ ffpipe = (GstFFMpegPipe *) priv_data; - - GST_LOG ("requested size %d", size); - -@@ -366,21 +313,38 @@ gst_ffmpeg_pipe_read (URLContext * h, unsigned char *buf, int size) - return size; - } - --static int --gst_ffmpeg_pipe_close (URLContext * h) -+int -+gst_ffmpeg_pipe_close (AVIOContext * h) - { - GST_LOG ("Closing pipe"); - -- h->priv_data = NULL; -+ h->opaque = NULL; -+ av_freep (&h->buffer); -+ av_free (h); - - return 0; - } - --URLProtocol gstpipe_protocol = { -- "gstpipe", -- gst_ffmpeg_pipe_open, -- gst_ffmpeg_pipe_read, -- NULL, -- NULL, -- gst_ffmpeg_pipe_close, --}; -+int -+gst_ffmpeg_pipe_open (GstFFMpegPipe * ffpipe, int flags, AVIOContext ** context) -+{ -+ static const int buffer_size = 4096; -+ unsigned char *buffer = NULL; -+ -+ /* sanity check */ -+ g_return_val_if_fail (GST_IS_ADAPTER (ffpipe->adapter), -EINVAL); -+ -+ buffer = av_malloc (buffer_size); -+ if (buffer == NULL) { -+ GST_WARNING ("Failed to allocate buffer"); -+ return -ENOMEM; -+ } -+ -+ *context = -+ avio_alloc_context (buffer, buffer_size, 0, (void *) ffpipe, -+ gst_ffmpeg_pipe_read, NULL, NULL); -+ (*context)->seekable = 0; -+ (*context)->buf_ptr = (*context)->buf_end; -+ -+ return 0; -+} -diff --git a/ext/libav/gstavprotocol.h b/ext/libav/gstavprotocol.h -new file mode 100644 -index 0000000..f4b2ba8 ---- /dev/null -+++ b/ext/libav/gstavprotocol.h -@@ -0,0 +1,78 @@ -+/* GStreamer -+ * Copyright (C) <2006> Mark Nauwelaerts <manauw@skynet.be> -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+ -+ -+#ifndef __GST_FFMPEGPROTOCOL_H__ -+#define __GST_FFMPEGPROTOCOL_H__ -+ -+#include <gst/base/gstadapter.h> -+#include "gstav.h" -+ -+G_BEGIN_DECLS -+ -+/* pipe protocol helpers */ -+#define GST_FFMPEG_PIPE_MUTEX_LOCK(m) G_STMT_START { \ -+ GST_LOG_OBJECT (m, "locking tlock from thread %p", g_thread_self ()); \ -+ g_mutex_lock (&m->tlock); \ -+ GST_LOG_OBJECT (m, "locked tlock from thread %p", g_thread_self ()); \ -+} G_STMT_END -+ -+#define GST_FFMPEG_PIPE_MUTEX_UNLOCK(m) G_STMT_START { \ -+ GST_LOG_OBJECT (m, "unlocking tlock from thread %p", g_thread_self ()); \ -+ g_mutex_unlock (&m->tlock); \ -+} G_STMT_END -+ -+#define GST_FFMPEG_PIPE_WAIT(m) G_STMT_START { \ -+ GST_LOG_OBJECT (m, "thread %p waiting", g_thread_self ()); \ -+ g_cond_wait (&m->cond, &m->tlock); \ -+} G_STMT_END -+ -+#define GST_FFMPEG_PIPE_SIGNAL(m) G_STMT_START { \ -+ GST_LOG_OBJECT (m, "signalling from thread %p", g_thread_self ()); \ -+ g_cond_signal (&m->cond); \ -+} G_STMT_END -+ -+typedef struct _GstFFMpegPipe GstFFMpegPipe; -+ -+struct _GstFFMpegPipe -+{ -+ /* lock for syncing */ -+ GMutex tlock; -+ /* with TLOCK */ -+ /* signals counterpart thread to have a look */ -+ GCond cond; -+ /* seen eos */ -+ gboolean eos; -+ /* flowreturn obtained by src task */ -+ GstFlowReturn srcresult; -+ /* adpater collecting data */ -+ GstAdapter *adapter; -+ /* amount needed in adapter by src task */ -+ guint needed; -+}; -+ -+int gst_ffmpeg_pipe_open (GstFFMpegPipe *ffpipe, int flags, AVIOContext ** context); -+int gst_ffmpeg_pipe_close (AVIOContext * h); -+ -+int gst_ffmpegdata_open (GstPad * pad, int flags, AVIOContext ** context); -+int gst_ffmpegdata_close (AVIOContext * h); -+ -+G_END_DECLS -+ -+#endif /* __GST_FFMPEGPROTOCOL_H__ */ -diff --git a/ext/libav/gstavutils.c b/ext/libav/gstavutils.c -index f7a80f6..403a6b6 100644 ---- a/ext/libav/gstavutils.c -+++ b/ext/libav/gstavutils.c -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -25,6 +25,11 @@ - #ifdef __APPLE__ - #include <sys/sysctl.h> - #endif -+#ifdef __MINGW32__ -+#include <stdlib.h> -+#endif -+ -+#include <libavutil/mem.h> - - G_CONST_RETURN gchar * - gst_ffmpeg_get_codecid_longname (enum CodecID codec_id) -@@ -44,16 +49,21 @@ av_smp_format_depth (enum AVSampleFormat smp_fmt) - gint depth = -1; - switch (smp_fmt) { - case AV_SAMPLE_FMT_U8: -+ case AV_SAMPLE_FMT_U8P: - depth = 1; - break; - case AV_SAMPLE_FMT_S16: -+ case AV_SAMPLE_FMT_S16P: - depth = 2; - break; - case AV_SAMPLE_FMT_S32: -+ case AV_SAMPLE_FMT_S32P: - case AV_SAMPLE_FMT_FLT: -+ case AV_SAMPLE_FMT_FLTP: - depth = 4; - break; - case AV_SAMPLE_FMT_DBL: -+ case AV_SAMPLE_FMT_DBLP: - depth = 8; - break; - default: -@@ -476,7 +486,6 @@ gst_ffmpeg_auto_max_threads (void) - if (n < 1) - n = 1; - -- GST_INFO ("threads: %d", n); - g_once_init_leave (&n_threads, n); - } - -diff --git a/ext/libav/gstavutils.h b/ext/libav/gstavutils.h -index ebe49fb..97415eb 100644 ---- a/ext/libav/gstavutils.h -+++ b/ext/libav/gstavutils.h -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifndef __GST_FFMPEG_UTILS_H__ -diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c -index 7675a71..f2b5b38 100644 ---- a/ext/libav/gstavviddec.c -+++ b/ext/libav/gstavviddec.c -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -35,78 +35,17 @@ - #include "gstav.h" - #include "gstavcodecmap.h" - #include "gstavutils.h" -+#include "gstavviddec.h" - - GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); - --typedef struct _GstFFMpegVidDec GstFFMpegVidDec; -- - #define MAX_TS_MASK 0xff - --struct _GstFFMpegVidDec --{ -- GstVideoDecoder parent; -- -- GstVideoCodecState *input_state; -- GstVideoCodecState *output_state; -- -- /* decoding */ -- AVCodecContext *context; -- AVFrame *picture; -- gboolean opened; -- -- /* current context */ -- enum PixelFormat ctx_pix_fmt; -- gint ctx_width; -- gint ctx_height; -- gint ctx_par_n; -- gint ctx_par_d; -- gint ctx_ticks; -- gint ctx_time_d; -- gint ctx_time_n; -- gint ctx_interlaced; -- -- guint8 *padded; -- guint padded_size; -- -- gboolean current_dr; /* if direct rendering is enabled */ -- -- /* some properties */ -- enum AVDiscard skip_frame; -- gint lowres; -- gboolean direct_rendering; -- gboolean debug_mv; -- int max_threads; -- -- gboolean is_realvideo; -- -- GstCaps *last_caps; --}; -- --typedef struct _GstFFMpegVidDecClass GstFFMpegVidDecClass; -- --struct _GstFFMpegVidDecClass --{ -- GstVideoDecoderClass parent_class; -- -- AVCodec *in_plugin; --}; -- --#define GST_TYPE_FFMPEGDEC \ -- (gst_ffmpegviddec_get_type()) --#define GST_FFMPEGDEC(obj) \ -- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegVidDec)) --#define GST_FFMPEGVIDDEC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegVidDecClass)) --#define GST_IS_FFMPEGDEC(obj) \ -- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) --#define GST_IS_FFMPEGVIDDEC_CLASS(klass) \ -- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) -- - #define DEFAULT_LOWRES 0 - #define DEFAULT_SKIPFRAME 0 - #define DEFAULT_DIRECT_RENDERING TRUE - #define DEFAULT_DEBUG_MV FALSE --#define DEFAULT_MAX_THREADS 1 -+#define DEFAULT_MAX_THREADS 0 - - enum - { -@@ -234,7 +173,12 @@ gst_ffmpegviddec_base_init (GstFFMpegVidDecClass * klass) - GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name); - sinkcaps = gst_caps_new_empty_simple ("unknown/unknown"); - } -- srccaps = gst_caps_new_empty_simple ("video/x-raw"); -+ srccaps = gst_ffmpeg_codectype_to_video_caps (NULL, -+ in_plugin->id, FALSE, in_plugin); -+ if (!srccaps) { -+ GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name); -+ srccaps = gst_caps_from_string ("video/x-raw"); -+ } - - /* pad templates */ - sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -@@ -301,8 +245,11 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass) - static void - gst_ffmpegviddec_init (GstFFMpegVidDec * ffmpegdec) - { -+ GstFFMpegVidDecClass *klass = -+ (GstFFMpegVidDecClass *) G_OBJECT_GET_CLASS (ffmpegdec); -+ - /* some ffmpeg data */ -- ffmpegdec->context = avcodec_alloc_context (); -+ ffmpegdec->context = avcodec_alloc_context3 (klass->in_plugin); - ffmpegdec->picture = avcodec_alloc_frame (); - ffmpegdec->opened = FALSE; - ffmpegdec->skip_frame = ffmpegdec->lowres = 0; -@@ -321,10 +268,7 @@ gst_ffmpegviddec_finalize (GObject * object) - ffmpegdec->context = NULL; - } - -- if (ffmpegdec->picture != NULL) { -- av_free (ffmpegdec->picture); -- ffmpegdec->picture = NULL; -- } -+ avcodec_free_frame (&ffmpegdec->picture); - - G_OBJECT_CLASS (parent_class)->finalize (object); - } -@@ -334,9 +278,6 @@ gst_ffmpegviddec_finalize (GObject * object) - static void - gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec) - { -- if (!ffmpegdec->opened) -- return; -- - GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec"); - - gst_caps_replace (&ffmpegdec->last_caps, NULL); -@@ -345,10 +286,7 @@ gst_ffmpegviddec_close (GstFFMpegVidDec * ffmpegdec) - gst_ffmpeg_avcodec_close (ffmpegdec->context); - ffmpegdec->opened = FALSE; - -- if (ffmpegdec->context->palctrl) { -- av_free (ffmpegdec->context->palctrl); -- ffmpegdec->context->palctrl = NULL; -- } -+ gst_buffer_replace (&ffmpegdec->palette, NULL); - - if (ffmpegdec->context->extradata) { - av_free (ffmpegdec->context->extradata); -@@ -397,6 +335,25 @@ could_not_open: - } - } - -+static void -+gst_ffmpegviddec_get_palette (GstFFMpegVidDec * ffmpegdec, -+ GstVideoCodecState * state) -+{ -+ GstStructure *str = gst_caps_get_structure (state->caps, 0); -+ const GValue *palette_v; -+ GstBuffer *palette; -+ -+ /* do we have a palette? */ -+ if ((palette_v = gst_structure_get_value (str, "palette_data"))) { -+ palette = gst_value_get_buffer (palette_v); -+ GST_DEBUG ("got palette data %p", palette); -+ if (gst_buffer_get_size (palette) >= AVPALETTE_SIZE) { -+ gst_buffer_replace (&ffmpegdec->palette, palette); -+ } -+ } -+} -+ -+ - static gboolean - gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - GstVideoCodecState * state) -@@ -428,9 +385,6 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - gst_ffmpegviddec_drain (ffmpegdec); - GST_OBJECT_LOCK (ffmpegdec); - gst_ffmpegviddec_close (ffmpegdec); -- -- /* and reset the defaults that were set when a context is created */ -- avcodec_get_context_defaults (ffmpegdec->context); - } - - gst_caps_replace (&ffmpegdec->last_caps, state->caps); -@@ -452,6 +406,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - GST_LOG_OBJECT (ffmpegdec, "size after %dx%d", ffmpegdec->context->width, - ffmpegdec->context->height); - -+ gst_ffmpegviddec_get_palette (ffmpegdec, state); -+ - if (!ffmpegdec->context->time_base.den || !ffmpegdec->context->time_base.num) { - GST_DEBUG_OBJECT (ffmpegdec, "forcing 25/1 framerate"); - ffmpegdec->context->time_base.num = 1; -@@ -460,7 +416,7 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - - /* workaround encoder bugs */ - ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT; -- ffmpegdec->context->error_recognition = 1; -+ ffmpegdec->context->err_recognition = 1; - - /* for slow cpus */ - ffmpegdec->context->lowres = ffmpegdec->lowres; -@@ -471,30 +427,16 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - ffmpegdec->context->debug_mv = ffmpegdec->debug_mv; - - { -- const gchar *env = g_getenv ("GST_AVVIDDEC_MAX_THREADS"); -- int max_threads = ffmpegdec->max_threads; - GstQuery *query; - gboolean is_live; - -- if (env != NULL) { -- if (g_str_equal (env, "auto")) -- max_threads = 0; -- else -- max_threads = MAX (atoi (env), 0); -- -- if (max_threads != 1) { -- GST_WARNING_OBJECT (ffmpegdec, "max threads forced to %d, this might " -- "lead to decoding errors or artefacts", max_threads); -- } -- } -- -- if (max_threads == 0) { -+ if (ffmpegdec->max_threads == 0) { - if (!(oclass->in_plugin->capabilities & CODEC_CAP_AUTO_THREADS)) - ffmpegdec->context->thread_count = gst_ffmpeg_auto_max_threads (); - else - ffmpegdec->context->thread_count = 0; - } else -- ffmpegdec->context->thread_count = max_threads; -+ ffmpegdec->context->thread_count = ffmpegdec->max_threads; - - query = gst_query_new_latency (); - is_live = FALSE; -@@ -505,11 +447,10 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, - } - gst_query_unref (query); - -- /* Slice based threading is broken in libav 0.8 */ - if (is_live) -- ffmpegdec->context->thread_type = 0; /* FF_THREAD_SLICE */ -+ ffmpegdec->context->thread_type = FF_THREAD_SLICE; - else -- ffmpegdec->context->thread_type = /* FF_THREAD_SLICE | */ FF_THREAD_FRAME; -+ ffmpegdec->context->thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME; - } - - /* open codec - we don't select an output pix_fmt yet, -@@ -683,6 +624,7 @@ fallback: - duplicate_frame: - { - GST_WARNING_OBJECT (ffmpegdec, "already alloc'ed output buffer for frame"); -+ gst_video_codec_frame_unref (frame); - return -1; - } - no_frame: -@@ -1155,12 +1097,12 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, - /* now decode the frame */ - gst_avpacket_init (&packet, data, size); - -- if (ffmpegdec->context->palctrl) { -+ if (ffmpegdec->palette) { - guint8 *pal; - - pal = av_packet_new_side_data (&packet, AV_PKT_DATA_PALETTE, - AVPALETTE_SIZE); -- memcpy (pal, ffmpegdec->context->palctrl->palette, AVPALETTE_SIZE); -+ gst_buffer_extract (ffmpegdec->palette, 0, pal, AVPALETTE_SIZE); - GST_DEBUG_OBJECT (ffmpegdec, "copy pal %p %p", &packet, pal); - } - -@@ -1358,10 +1300,9 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder, - gboolean do_padding; - - GST_LOG_OBJECT (ffmpegdec, -- "Received new data of size %u, dts %" GST_TIME_FORMAT ", pts:%" -- GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT, -- gst_buffer_get_size (frame->input_buffer), -- GST_TIME_ARGS (frame->dts), -+ "Received new data of size %" G_GSIZE_FORMAT ", dts %" GST_TIME_FORMAT -+ ", pts:%" GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT, -+ gst_buffer_get_size (frame->input_buffer), GST_TIME_ARGS (frame->dts), - GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->duration)); - - if (!gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ)) { -@@ -1723,7 +1664,8 @@ gst_ffmpegviddec_register (GstPlugin * plugin) - gchar *plugin_name; - - /* only video decoders */ -- if (!in_plugin->decode || in_plugin->type != AVMEDIA_TYPE_VIDEO) -+ if (!av_codec_is_decoder (in_plugin) -+ || in_plugin->type != AVMEDIA_TYPE_VIDEO) - goto next; - - /* no quasi-codecs, please */ -diff --git a/ext/libav/gstavviddec.h b/ext/libav/gstavviddec.h -new file mode 100644 -index 0000000..c8649c4 ---- /dev/null -+++ b/ext/libav/gstavviddec.h -@@ -0,0 +1,93 @@ -+/* GStreamer -+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Library General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * 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 -+ * Library General Public License for more details. -+ * -+ * You should have received a copy of the GNU Library General Public -+ * License along with this library; if not, write to the -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. -+ */ -+#ifndef __GST_FFMPEGVIDDEC_H__ -+#define __GST_FFMPEGVIDDEC_H__ -+ -+G_BEGIN_DECLS -+ -+#include <gst/gst.h> -+#include <gst/video/video.h> -+#include <gst/video/gstvideodecoder.h> -+#include <libavcodec/avcodec.h> -+ -+typedef struct _GstFFMpegVidDec GstFFMpegVidDec; -+struct _GstFFMpegVidDec -+{ -+ GstVideoDecoder parent; -+ -+ GstVideoCodecState *input_state; -+ GstVideoCodecState *output_state; -+ -+ /* decoding */ -+ AVCodecContext *context; -+ AVFrame *picture; -+ gboolean opened; -+ -+ /* current context */ -+ enum PixelFormat ctx_pix_fmt; -+ gint ctx_width; -+ gint ctx_height; -+ gint ctx_par_n; -+ gint ctx_par_d; -+ gint ctx_ticks; -+ gint ctx_time_d; -+ gint ctx_time_n; -+ gint ctx_interlaced; -+ GstBuffer *palette; -+ -+ guint8 *padded; -+ guint padded_size; -+ -+ gboolean current_dr; /* if direct rendering is enabled */ -+ -+ /* some properties */ -+ enum AVDiscard skip_frame; -+ gint lowres; -+ gboolean direct_rendering; -+ gboolean debug_mv; -+ int max_threads; -+ -+ gboolean is_realvideo; -+ -+ GstCaps *last_caps; -+}; -+ -+typedef struct _GstFFMpegVidDecClass GstFFMpegVidDecClass; -+ -+struct _GstFFMpegVidDecClass -+{ -+ GstVideoDecoderClass parent_class; -+ -+ AVCodec *in_plugin; -+}; -+ -+#define GST_TYPE_FFMPEGDEC \ -+ (gst_ffmpegviddec_get_type()) -+#define GST_FFMPEGDEC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegVidDec)) -+#define GST_FFMPEGVIDDEC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegVidDecClass)) -+#define GST_IS_FFMPEGDEC(obj) \ -+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC)) -+#define GST_IS_FFMPEGVIDDEC_CLASS(klass) \ -+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC)) -+ -+G_END_DECLS -+ -+#endif -diff --git a/ext/libav/gstavvidenc.c b/ext/libav/gstavvidenc.c -index b747613..7b24c45 100644 ---- a/ext/libav/gstavvidenc.c -+++ b/ext/libav/gstavvidenc.c -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -56,13 +56,13 @@ enum - - enum - { -- ARG_0, -- ARG_BIT_RATE, -- ARG_GOP_SIZE, -- ARG_ME_METHOD, -- ARG_BUFSIZE, -- ARG_RTP_PAYLOAD_SIZE, -- ARG_CFG_BASE -+ PROP_0, -+ PROP_BIT_RATE, -+ PROP_GOP_SIZE, -+ PROP_ME_METHOD, -+ PROP_BUFSIZE, -+ PROP_RTP_PAYLOAD_SIZE, -+ PROP_CFG_BASE - }; - - #define GST_TYPE_ME_METHOD (gst_ffmpegvidenc_me_method_get_type()) -@@ -98,6 +98,8 @@ static gboolean gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, - GstVideoCodecState * state); - static gboolean gst_ffmpegvidenc_propose_allocation (GstVideoEncoder * encoder, - GstQuery * query); -+static gboolean gst_ffmpegvidenc_reset (GstVideoEncoder * encoder, -+ gboolean hard); - - static GstCaps *gst_ffmpegvidenc_getcaps (GstVideoEncoder * encoder, - GstCaps * filter); -@@ -144,7 +146,12 @@ gst_ffmpegvidenc_base_init (GstFFMpegVidEncClass * klass) - srccaps = gst_caps_new_empty_simple ("unknown/unknown"); - } - -- sinkcaps = gst_caps_new_empty_simple ("video/x-raw"); -+ sinkcaps = gst_ffmpeg_codectype_to_video_caps (NULL, -+ in_plugin->id, TRUE, in_plugin); -+ if (!sinkcaps) { -+ GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name); -+ sinkcaps = gst_caps_new_empty_simple ("unknown/unknown"); -+ } - - /* pad templates */ - sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, -@@ -157,7 +164,6 @@ gst_ffmpegvidenc_base_init (GstFFMpegVidEncClass * klass) - klass->in_plugin = in_plugin; - klass->srctempl = srctempl; - klass->sinktempl = sinktempl; -- klass->sinkcaps = NULL; - - return; - } -@@ -178,30 +184,30 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) - - /* FIXME: could use -1 for a sensible per-codec default based on - * e.g. input resolution and framerate */ -- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE, -+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BIT_RATE, - g_param_spec_int ("bitrate", "Bit Rate", - "Target Video Bitrate", 0, G_MAXINT, DEFAULT_VIDEO_BITRATE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GOP_SIZE, -+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GOP_SIZE, - g_param_spec_int ("gop-size", "GOP Size", - "Number of frames within one GOP", 0, G_MAXINT, - DEFAULT_VIDEO_GOP_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ME_METHOD, -+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ME_METHOD, - g_param_spec_enum ("me-method", "ME Method", "Motion Estimation Method", - GST_TYPE_ME_METHOD, ME_EPZS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - -- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFSIZE, -+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFSIZE, - g_param_spec_int ("buffer-size", "Buffer Size", - "Size of the video buffers", 0, G_MAXINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (G_OBJECT_CLASS (klass), -- ARG_RTP_PAYLOAD_SIZE, g_param_spec_int ("rtp-payload-size", -+ PROP_RTP_PAYLOAD_SIZE, g_param_spec_int ("rtp-payload-size", - "RTP Payload Size", "Target GOB length", 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* register additional properties, possibly dependent on the exact CODEC */ -- gst_ffmpeg_cfg_install_property (klass, ARG_CFG_BASE); -+ gst_ffmpeg_cfg_install_property (klass, PROP_CFG_BASE); - - venc_class->stop = gst_ffmpegvidenc_stop; - venc_class->finish = gst_ffmpegvidenc_finish; -@@ -209,6 +215,7 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) - venc_class->getcaps = gst_ffmpegvidenc_getcaps; - venc_class->set_format = gst_ffmpegvidenc_set_format; - venc_class->propose_allocation = gst_ffmpegvidenc_propose_allocation; -+ venc_class->reset = gst_ffmpegvidenc_reset; - - gobject_class->finalize = gst_ffmpegvidenc_finalize; - } -@@ -216,8 +223,11 @@ gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass) - static void - gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc) - { -+ GstFFMpegVidEncClass *klass = -+ (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc); -+ - /* ffmpeg objects */ -- ffmpegenc->context = avcodec_alloc_context (); -+ ffmpegenc->context = avcodec_alloc_context3 (klass->in_plugin); - ffmpegenc->picture = avcodec_alloc_frame (); - ffmpegenc->opened = FALSE; - -@@ -243,15 +253,9 @@ gst_ffmpegvidenc_finalize (GObject * object) - - gst_ffmpeg_cfg_finalize (ffmpegenc); - -- /* close old session */ -- if (ffmpegenc->opened) { -- gst_ffmpeg_avcodec_close (ffmpegenc->context); -- ffmpegenc->opened = FALSE; -- } -- - /* clean up remaining allocated data */ - av_free (ffmpegenc->context); -- av_free (ffmpegenc->picture); -+ avcodec_free_frame (&ffmpegenc->picture); - - g_free (ffmpegenc->filename); - -@@ -262,117 +266,13 @@ static GstCaps * - gst_ffmpegvidenc_getcaps (GstVideoEncoder * encoder, GstCaps * filter) - { - GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; -- GstFFMpegVidEncClass *oclass = -- (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc); -- AVCodecContext *ctx = NULL; -- enum PixelFormat pixfmt; - GstCaps *caps = NULL; -- gint i; - - GST_DEBUG_OBJECT (ffmpegenc, "getting caps"); - -- /* cached */ -- if (oclass->sinkcaps) { -- caps = gst_video_encoder_proxy_getcaps (encoder, oclass->sinkcaps, filter); -- GST_DEBUG_OBJECT (ffmpegenc, "return cached caps %" GST_PTR_FORMAT, caps); -- return caps; -- } -- -- /* create cache etc. */ -- -- /* shut up the logging while we autoprobe; we don't want warnings and -- * errors about unsupported formats */ -- /* FIXME: if someone cares about this disabling the logging for other -- * instances/threads/..., one could investigate if there is a way to -- * set this as a struct member on the av context, and check it from the -- * log handler */ --#ifndef GST_DISABLE_GST_DEBUG -- _shut_up_I_am_probing = TRUE; --#endif -- GST_DEBUG_OBJECT (ffmpegenc, "probing caps"); -- i = pixfmt = 0; -- /* check pixfmt until deemed finished */ -- for (pixfmt = 0;; pixfmt++) { -- GstCaps *tmpcaps; -- -- /* override looping all pixfmt if codec declares pixfmts; -- * these may not properly check and report supported pixfmt during _init */ -- if (oclass->in_plugin->pix_fmts) { -- if ((pixfmt = oclass->in_plugin->pix_fmts[i++]) == PIX_FMT_NONE) { -- GST_DEBUG_OBJECT (ffmpegenc, -- "At the end of official pixfmt for this codec, breaking out"); -- break; -- } -- GST_DEBUG_OBJECT (ffmpegenc, -- "Got an official pixfmt [%d], attempting to get caps", pixfmt); -- tmpcaps = gst_ffmpeg_pixfmt_to_caps (pixfmt, NULL, oclass->in_plugin->id); -- if (tmpcaps) { -- GST_DEBUG_OBJECT (ffmpegenc, "Got caps, breaking out"); -- if (!caps) -- caps = gst_caps_new_empty (); -- gst_caps_append (caps, tmpcaps); -- continue; -- } -- GST_DEBUG_OBJECT (ffmpegenc, -- "Couldn't figure out caps without context, trying again with a context"); -- } -- -- GST_DEBUG_OBJECT (ffmpegenc, "pixfmt :%d", pixfmt); -- if (pixfmt >= PIX_FMT_NB) { -- GST_WARNING ("Invalid pixfmt, breaking out"); -- break; -- } -- -- /* need to start with a fresh codec_context each time around, since -- * codec_close may have released stuff causing the next pass to segfault */ -- ctx = avcodec_alloc_context (); -- if (!ctx) { -- GST_DEBUG_OBJECT (ffmpegenc, "no context"); -- break; -- } -- -- /* set some default properties */ -- ctx->width = DEFAULT_WIDTH; -- ctx->height = DEFAULT_HEIGHT; -- ctx->time_base.num = 1; -- ctx->time_base.den = 25; -- ctx->ticks_per_frame = 1; -- ctx->bit_rate = DEFAULT_VIDEO_BITRATE; -- /* makes it silent */ -- ctx->strict_std_compliance = -1; -- -- ctx->pix_fmt = pixfmt; -- -- GST_DEBUG ("Attempting to open codec"); -- if (gst_ffmpeg_avcodec_open (ctx, oclass->in_plugin) >= 0 && -- ctx->pix_fmt == pixfmt) { -- ctx->width = -1; -- if (!caps) -- caps = gst_caps_new_empty (); -- tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx, -- oclass->in_plugin->id, TRUE); -- if (tmpcaps) -- gst_caps_append (caps, tmpcaps); -- else -- GST_LOG_OBJECT (ffmpegenc, -- "Couldn't get caps for oclass->in_plugin->name:%s", -- oclass->in_plugin->name); -- gst_ffmpeg_avcodec_close (ctx); -- } else { -- GST_DEBUG_OBJECT (ffmpegenc, "Opening codec failed with pixfmt : %d", -- pixfmt); -- } -- if (ctx->priv_data) -- gst_ffmpeg_avcodec_close (ctx); -- av_free (ctx); -- } --#ifndef GST_DISABLE_GST_DEBUG -- _shut_up_I_am_probing = FALSE; --#endif -- -- oclass->sinkcaps = caps; -- -- return gst_video_encoder_proxy_getcaps (encoder, caps, filter); -+ caps = gst_video_encoder_proxy_getcaps (encoder, NULL, filter); -+ GST_DEBUG_OBJECT (ffmpegenc, "return caps %" GST_PTR_FORMAT, caps); -+ return caps; - } - - static gboolean -@@ -394,9 +294,6 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, - ffmpegenc->opened = FALSE; - } - -- /* set defaults */ -- avcodec_get_context_defaults (ffmpegenc->context); -- - /* if we set it in _getcaps we should set it also in _link */ - ffmpegenc->context->strict_std_compliance = -1; - -@@ -546,16 +443,7 @@ gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder, - gst_caps_unref (icaps); - return FALSE; - } -- -- if (gst_caps_get_size (icaps) > 1) { -- GstCaps *newcaps; -- -- newcaps = -- gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (icaps, -- 0)), NULL); -- gst_caps_unref (icaps); -- icaps = newcaps; -- } -+ icaps = gst_caps_truncate (icaps); - - /* Store input state and set output state */ - if (ffmpegenc->input_state) -@@ -796,24 +684,28 @@ gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send) - (("Could not write to file \"%s\"."), ffmpegenc->filename), - GST_ERROR_SYSTEM); - -- if (gst_video_encoder_allocate_output_frame (GST_VIDEO_ENCODER (ffmpegenc), -- frame, ret_size) != GST_FLOW_OK) { -+ if (send) { -+ if (gst_video_encoder_allocate_output_frame (GST_VIDEO_ENCODER -+ (ffmpegenc), frame, ret_size) != GST_FLOW_OK) { - #ifndef GST_DISABLE_GST_DEBUG -- GstFFMpegVidEncClass *oclass = -- (GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); -- GST_WARNING_OBJECT (ffmpegenc, -- "avenc_%s: failed to allocate buffer", oclass->in_plugin->name); -+ GstFFMpegVidEncClass *oclass = -+ (GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); -+ GST_WARNING_OBJECT (ffmpegenc, -+ "avenc_%s: failed to allocate buffer", oclass->in_plugin->name); - #endif /* GST_DISABLE_GST_DEBUG */ -- gst_video_codec_frame_unref (frame); -- break; -- } -- outbuf = frame->output_buffer; -- gst_buffer_fill (outbuf, 0, ffmpegenc->working_buf, ret_size); -+ gst_video_codec_frame_unref (frame); -+ break; -+ } -+ outbuf = frame->output_buffer; -+ gst_buffer_fill (outbuf, 0, ffmpegenc->working_buf, ret_size); - -- if (ffmpegenc->context->coded_frame->key_frame) -- GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame); -+ if (ffmpegenc->context->coded_frame->key_frame) -+ GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame); - -- gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame); -+ gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame); -+ } else { -+ gst_video_codec_frame_unref (frame); -+ } - } - } - -@@ -835,18 +727,18 @@ gst_ffmpegvidenc_set_property (GObject * object, - - /* Check the argument id to see which argument we're setting. */ - switch (prop_id) { -- case ARG_BIT_RATE: -+ case PROP_BIT_RATE: - ffmpegenc->bitrate = g_value_get_int (value); - break; -- case ARG_GOP_SIZE: -+ case PROP_GOP_SIZE: - ffmpegenc->gop_size = g_value_get_int (value); - break; -- case ARG_ME_METHOD: -+ case PROP_ME_METHOD: - ffmpegenc->me_method = g_value_get_enum (value); - break; -- case ARG_BUFSIZE: -+ case PROP_BUFSIZE: - break; -- case ARG_RTP_PAYLOAD_SIZE: -+ case PROP_RTP_PAYLOAD_SIZE: - ffmpegenc->rtp_payload_size = g_value_get_int (value); - break; - default: -@@ -867,19 +759,19 @@ gst_ffmpegvidenc_get_property (GObject * object, - ffmpegenc = (GstFFMpegVidEnc *) (object); - - switch (prop_id) { -- case ARG_BIT_RATE: -+ case PROP_BIT_RATE: - g_value_set_int (value, ffmpegenc->bitrate); - break; -- case ARG_GOP_SIZE: -+ case PROP_GOP_SIZE: - g_value_set_int (value, ffmpegenc->gop_size); - break; -- case ARG_ME_METHOD: -+ case PROP_ME_METHOD: - g_value_set_enum (value, ffmpegenc->me_method); - break; -- case ARG_BUFSIZE: -+ case PROP_BUFSIZE: - g_value_set_int (value, ffmpegenc->buffer_size); - break; -- case ARG_RTP_PAYLOAD_SIZE: -+ case PROP_RTP_PAYLOAD_SIZE: - g_value_set_int (value, ffmpegenc->rtp_payload_size); - break; - default: -@@ -890,15 +782,26 @@ gst_ffmpegvidenc_get_property (GObject * object, - } - - static gboolean --gst_ffmpegvidenc_stop (GstVideoEncoder * encoder) -+gst_ffmpegvidenc_reset (GstVideoEncoder * encoder, gboolean hard) - { - GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; - -- gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE); - if (ffmpegenc->opened) { -- gst_ffmpeg_avcodec_close (ffmpegenc->context); -- ffmpegenc->opened = FALSE; -+ avcodec_flush_buffers (ffmpegenc->context); - } -+ -+ return TRUE; -+} -+ -+static gboolean -+gst_ffmpegvidenc_stop (GstVideoEncoder * encoder) -+{ -+ GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; -+ -+ gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE); -+ gst_ffmpeg_avcodec_close (ffmpegenc->context); -+ ffmpegenc->opened = FALSE; -+ - if (ffmpegenc->file) { - fclose (ffmpegenc->file); - ffmpegenc->file = NULL; -@@ -971,7 +874,8 @@ gst_ffmpegvidenc_register (GstPlugin * plugin) - } - - /* only video encoders */ -- if (!in_plugin->encode || in_plugin->type != AVMEDIA_TYPE_VIDEO) -+ if (!av_codec_is_encoder (in_plugin) -+ || in_plugin->type != AVMEDIA_TYPE_VIDEO) - goto next; - - /* FIXME : We should have a method to know cheaply whether we have a mapping -diff --git a/ext/libav/gstavvidenc.h b/ext/libav/gstavvidenc.h -index eb201b3..d19dc39 100644 ---- a/ext/libav/gstavvidenc.h -+++ b/ext/libav/gstavvidenc.h -@@ -13,8 +13,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - /* First, include the header file for the plugin, to bring in the -@@ -26,7 +26,9 @@ - - G_BEGIN_DECLS - -+#include <gst/gst.h> - #include <gst/video/gstvideoencoder.h> -+#include <libavcodec/avcodec.h> - - typedef struct _GstFFMpegVidEnc GstFFMpegVidEnc; - -@@ -76,7 +78,6 @@ struct _GstFFMpegVidEncClass - - AVCodec *in_plugin; - GstPadTemplate *srctempl, *sinktempl; -- GstCaps *sinkcaps; - }; - - #define GST_TYPE_FFMPEGVIDENC \ -diff --git a/ext/libswscale/gstffmpegscale.c b/ext/libswscale/gstffmpegscale.c -index ce980a8..a2b0248 100644 ---- a/ext/libswscale/gstffmpegscale.c -+++ b/ext/libswscale/gstffmpegscale.c -@@ -15,8 +15,8 @@ - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the -- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- * Boston, MA 02111-1307, USA. -+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -+ * Boston, MA 02110-1301, USA. - */ - - #ifdef HAVE_CONFIG_H -@@ -246,44 +246,15 @@ gst_ffmpegscale_caps_remove_format_info (GstCaps * caps) - { - int i; - GstStructure *structure; -- GstCaps *rgbcaps; -- GstCaps *graycaps; - - caps = gst_caps_copy (caps); - - for (i = 0; i < gst_caps_get_size (caps); i++) { - structure = gst_caps_get_structure (caps, i); - -- gst_structure_set_name (structure, "video/x-raw-yuv"); - gst_structure_remove_field (structure, "format"); -- gst_structure_remove_field (structure, "endianness"); -- gst_structure_remove_field (structure, "depth"); -- gst_structure_remove_field (structure, "bpp"); -- gst_structure_remove_field (structure, "red_mask"); -- gst_structure_remove_field (structure, "green_mask"); -- gst_structure_remove_field (structure, "blue_mask"); -- gst_structure_remove_field (structure, "alpha_mask"); -- gst_structure_remove_field (structure, "palette_data"); - } - -- rgbcaps = gst_caps_copy (caps); -- -- for (i = 0; i < gst_caps_get_size (rgbcaps); i++) { -- structure = gst_caps_get_structure (rgbcaps, i); -- -- gst_structure_set_name (structure, "video/x-raw-rgb"); -- } -- graycaps = gst_caps_copy (caps); -- -- for (i = 0; i < gst_caps_get_size (graycaps); i++) { -- structure = gst_caps_get_structure (graycaps, i); -- -- gst_structure_set_name (structure, "video/x-raw-gray"); -- } -- -- gst_caps_append (caps, graycaps); -- gst_caps_append (caps, rgbcaps); -- - return caps; - } - -diff --git a/gst-libs/ext/Makefile.am b/gst-libs/ext/Makefile.am -index b1054e1..12f35c8 100644 ---- a/gst-libs/ext/Makefile.am -+++ b/gst-libs/ext/Makefile.am -@@ -23,7 +23,7 @@ clean-local: - - dist-clean: - cd libav && $(MAKE) distclean -- rm -rf $(TMP_DIST_DIR) -+ rm -rf libav/$(TMP_DIST_DIR) - rm -f Makefile - rm -f libav/.version - rm -f libav/.config -@@ -36,19 +36,19 @@ maintainer-clean: distclean - maintainerclean: maintainer-clean - - dist-local: -- GIT_DIR=libav/.git git checkout-index --prefix=../$(TMP_DIST_DIR)/libav/ -a -- touch $(TMP_DIST_DIR)/libav/config.mak -+ GIT_DIR=libav/.git git checkout-index --prefix=$(TMP_DIST_DIR)/libav/ -a -+ touch libav/$(TMP_DIST_DIR)/libav/config.mak - echo "Patching libav ./configure" -- sed -e '/Unknown option/ {N;N;s/exit 1//; }' $(TMP_DIST_DIR)/libav/configure > $(TMP_DIST_DIR)/libav/configure.tmp -- mv $(TMP_DIST_DIR)/libav/configure.tmp $(TMP_DIST_DIR)/libav/configure -- chmod +x $(TMP_DIST_DIR)/libav/configure -+ sed -e '/Unknown option/ {N;N;s/exit 1//; }' libav/$(TMP_DIST_DIR)/libav/configure > libav/$(TMP_DIST_DIR)/libav/configure.tmp -+ mv libav/$(TMP_DIST_DIR)/libav/configure.tmp libav/$(TMP_DIST_DIR)/libav/configure -+ chmod +x libav/$(TMP_DIST_DIR)/libav/configure - - distdir: dist-local -- cp -r $(TMP_DIST_DIR)/libav ${distdir} -+ cp -r libav/$(TMP_DIST_DIR)/libav ${distdir} - cp -f $(top_srcdir)/gst-libs/ext/Makefile.am $(top_srcdir)/gst-libs/ext/Makefile.in ${distdir} -- rm -rf $(TMP_DIST_DIR) -+ rm -rf libav/$(TMP_DIST_DIR) - - dist: dist-local -- cd $(TMP_DIST_DIR) && tar -czf libav.tar.gz libav -- mv $(TMP_DIST_DIR)/libav.tar.gz ./ -- rm -rf $(TMP_DIST_DIR) -+ cd libav/$(TMP_DIST_DIR) && tar -czf libav.tar.gz libav -+ mv libav/$(TMP_DIST_DIR)/libav.tar.gz ./ -+ rm -rf libav/$(TMP_DIST_DIR) diff --git a/debian/patches/04_gstreamer-1.0.patch b/debian/patches/04_gstreamer-1.0.patch deleted file mode 100644 index ef78e88..0000000 --- a/debian/patches/04_gstreamer-1.0.patch +++ /dev/null @@ -1,18 +0,0 @@ -Index: gst-libav1.0/ext/libav/gstavcodecmap.c -=================================================================== ---- gst-libav1.0.orig/ext/libav/gstavcodecmap.c 2012-12-18 11:46:01.518162985 +0100 -+++ gst-libav1.0/ext/libav/gstavcodecmap.c 2012-12-18 11:46:14.610162737 +0100 -@@ -2426,12 +2426,7 @@ - {GST_VIDEO_FORMAT_I420_10LE, PIX_FMT_YUV420P10LE}, - {GST_VIDEO_FORMAT_I420_10BE, PIX_FMT_YUV420P10BE}, - {GST_VIDEO_FORMAT_I422_10LE, PIX_FMT_YUV422P10LE}, -- {GST_VIDEO_FORMAT_I422_10BE, PIX_FMT_YUV422P10BE}, -- {GST_VIDEO_FORMAT_Y444_10LE, PIX_FMT_YUV444P10LE}, -- {GST_VIDEO_FORMAT_Y444_10BE, PIX_FMT_YUV444P10BE}, -- {GST_VIDEO_FORMAT_GBR, PIX_FMT_GBRP}, -- {GST_VIDEO_FORMAT_GBR_10LE, PIX_FMT_GBRP10LE}, -- {GST_VIDEO_FORMAT_GBR_10BE, PIX_FMT_GBRP10BE}, -+ {GST_VIDEO_FORMAT_I422_10BE, PIX_FMT_YUV422P10BE} - }; - - GstVideoFormat diff --git a/debian/patches/series b/debian/patches/series index 2238249..cea5087 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,2 @@ 02_plugin-dependencies.patch -03_git-2013-04-26.patch -04_gstreamer-1.0.patch 99_ltmain_as-needed.patch |