From: Vincent Penquerc'h Date: Sun, 20 Nov 2011 09:52:46 +0000 (+0000) Subject: opus: make opusparse set headers on caps X-Git-Tag: 1.19.3~511^2~3035^2~116^2~12 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7030b04f5e1af896f25aa7de974089de25351172;p=platform%2Fupstream%2Fgstreamer.git opus: make opusparse set headers on caps Header-on-caps code moved to a new shared location to avoid duplicating the code. --- diff --git a/ext/opus/Makefile.am b/ext/opus/Makefile.am index 6fe723e..88845a3 100644 --- a/ext/opus/Makefile.am +++ b/ext/opus/Makefile.am @@ -1,6 +1,6 @@ plugin_LTLIBRARIES = libgstopus.la -libgstopus_la_SOURCES = gstopus.c gstopusdec.c gstopusenc.c gstopusparse.c +libgstopus_la_SOURCES = gstopus.c gstopusdec.c gstopusenc.c gstopusparse.c gstopusheader.c libgstopus_la_CFLAGS = \ -DGST_USE_UNSTABLE_API \ $(GST_PLUGINS_BASE_CFLAGS) \ @@ -15,4 +15,4 @@ libgstopus_la_LIBADD = \ libgstopus_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(LIBM) libgstopus_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gstopusenc.h gstopusdec.h gstopusparse.h +noinst_HEADERS = gstopusenc.h gstopusdec.h gstopusparse.h gstopusheader.h diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index 2f8dc5b..f13490e 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -1,6 +1,7 @@ /* GStreamer Opus Encoder * Copyright (C) <1999> Erik Walthinsen * Copyright (C) <2008> Sebastian Dröge + * Copyright (C) <2011> Vincent Penquerc'h * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -46,9 +47,8 @@ #include #include -#include -#include #include +#include "gstopusheader.h" #include "gstopusenc.h" GST_DEBUG_CATEGORY_STATIC (opusenc_debug); @@ -414,61 +414,6 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) return TRUE; } -static GstBuffer * -gst_opus_enc_create_id_buffer (GstOpusEnc * enc) -{ - GstBuffer *buffer; - GstByteWriter bw; - - gst_byte_writer_init (&bw); - - /* See http://wiki.xiph.org/OggOpus */ - gst_byte_writer_put_data (&bw, (const guint8 *) "OpusHead", 8); - gst_byte_writer_put_uint8 (&bw, 0); /* version number */ - gst_byte_writer_put_uint8 (&bw, enc->n_channels); - gst_byte_writer_put_uint16_le (&bw, 0); /* pre-skip *//* TODO: endianness ? */ - gst_byte_writer_put_uint32_le (&bw, enc->sample_rate); - gst_byte_writer_put_uint16_le (&bw, 0); /* output gain *//* TODO: endianness ? */ - gst_byte_writer_put_uint8 (&bw, 0); /* channel mapping *//* TODO: what is this ? */ - - buffer = gst_byte_writer_reset_and_get_buffer (&bw); - - GST_BUFFER_OFFSET (buffer) = 0; - GST_BUFFER_OFFSET_END (buffer) = 0; - - return buffer; -} - -static GstBuffer * -gst_opus_enc_create_metadata_buffer (GstOpusEnc * enc) -{ - const GstTagList *tags; - GstTagList *empty_tags = NULL; - GstBuffer *comments = NULL; - - tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)); - - GST_DEBUG_OBJECT (enc, "tags = %" GST_PTR_FORMAT, tags); - - if (tags == NULL) { - /* FIXME: better fix chain of callers to not write metadata at all, - * if there is none */ - empty_tags = gst_tag_list_new (); - tags = empty_tags; - } - comments = - gst_tag_list_to_vorbiscomment_buffer (tags, (const guint8 *) "OpusTags", - 8, "Encoded with GStreamer Opusenc"); - - GST_BUFFER_OFFSET (comments) = 0; - GST_BUFFER_OFFSET_END (comments) = 0; - - if (empty_tags) - gst_tag_list_free (empty_tags); - - return comments; -} - static gboolean gst_opus_enc_setup (GstOpusEnc * enc) { @@ -644,63 +589,6 @@ done: return ret; } -/* - * (really really) FIXME: move into core (dixit tpm) - */ -/** - * _gst_caps_set_buffer_array: - * @caps: a #GstCaps - * @field: field in caps to set - * @buf: header buffers - * - * Adds given buffers to an array of buffers set as the given @field - * on the given @caps. List of buffer arguments must be NULL-terminated. - * - * Returns: input caps with a streamheader field added, or NULL if some error - */ -static GstCaps * -_gst_caps_set_buffer_array (GstCaps * caps, const gchar * field, - GstBuffer * buf, ...) -{ - GstStructure *structure = NULL; - va_list va; - GValue array = { 0 }; - GValue value = { 0 }; - - g_return_val_if_fail (caps != NULL, NULL); - g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); - g_return_val_if_fail (field != NULL, NULL); - - caps = gst_caps_make_writable (caps); - structure = gst_caps_get_structure (caps, 0); - - g_value_init (&array, GST_TYPE_ARRAY); - - va_start (va, buf); - /* put buffers in a fixed list */ - while (buf) { - g_assert (gst_buffer_is_writable (buf)); - - /* mark buffer */ - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); - - g_value_init (&value, GST_TYPE_BUFFER); - buf = gst_buffer_copy (buf); - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); - gst_value_set_buffer (&value, buf); - gst_buffer_unref (buf); - gst_value_array_append_value (&array, &value); - g_value_unset (&value); - - buf = va_arg (va, GstBuffer *); - } - - gst_structure_set_value (structure, field, &array); - g_value_unset (&array); - - return caps; -} - static GstFlowReturn gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf) { @@ -711,32 +599,20 @@ gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf) GST_DEBUG_OBJECT (enc, "handle_frame"); if (!enc->header_sent) { - /* Opus streams in Ogg begin with two headers; the initial header (with - most of the codec setup parameters) which is mandated by the Ogg - bitstream spec. The second header holds any comment fields. */ - GstBuffer *buf1, *buf2; GstCaps *caps; - /* create header buffers */ - buf1 = gst_opus_enc_create_id_buffer (enc); - buf2 = gst_opus_enc_create_metadata_buffer (enc); + g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL); + enc->headers = NULL; + + gst_opus_header_create_caps (&caps, &enc->headers, enc->n_channels, + enc->sample_rate, gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc))); - /* mark and put on caps */ - caps = gst_caps_from_string ("audio/x-opus"); - caps = _gst_caps_set_buffer_array (caps, "streamheader", buf1, buf2, NULL); /* negotiate with these caps */ GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps); gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps); - /* push out buffers */ - /* store buffers for later pre_push sending */ - g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL); - enc->headers = NULL; - GST_DEBUG_OBJECT (enc, "storing header buffers"); - enc->headers = g_slist_prepend (enc->headers, buf2); - enc->headers = g_slist_prepend (enc->headers, buf1); enc->header_sent = TRUE; } diff --git a/ext/opus/gstopusheader.c b/ext/opus/gstopusheader.c new file mode 100644 index 0000000..b430b7d --- /dev/null +++ b/ext/opus/gstopusheader.c @@ -0,0 +1,163 @@ +/* GStreamer Opus Encoder + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2008> Sebastian Dröge + * Copyright (C) <2011> Vincent Penquerc'h + * + * 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 +#include +#include "gstopusheader.h" + +static GstBuffer * +gst_opus_enc_create_id_buffer (gint nchannels, gint sample_rate) +{ + GstBuffer *buffer; + GstByteWriter bw; + + gst_byte_writer_init (&bw); + + /* See http://wiki.xiph.org/OggOpus */ + gst_byte_writer_put_data (&bw, (const guint8 *) "OpusHead", 8); + gst_byte_writer_put_uint8 (&bw, 0); /* version number */ + gst_byte_writer_put_uint8 (&bw, nchannels); + gst_byte_writer_put_uint16_le (&bw, 0); /* pre-skip *//* TODO: endianness ? */ + gst_byte_writer_put_uint32_le (&bw, sample_rate); + gst_byte_writer_put_uint16_le (&bw, 0); /* output gain *//* TODO: endianness ? */ + gst_byte_writer_put_uint8 (&bw, 0); /* channel mapping *//* TODO: what is this ? */ + + buffer = gst_byte_writer_reset_and_get_buffer (&bw); + + GST_BUFFER_OFFSET (buffer) = 0; + GST_BUFFER_OFFSET_END (buffer) = 0; + + return buffer; +} + +static GstBuffer * +gst_opus_enc_create_metadata_buffer (const GstTagList * tags) +{ + GstTagList *empty_tags = NULL; + GstBuffer *comments = NULL; + + GST_DEBUG ("tags = %" GST_PTR_FORMAT, tags); + + if (tags == NULL) { + /* FIXME: better fix chain of callers to not write metadata at all, + * if there is none */ + empty_tags = gst_tag_list_new (); + tags = empty_tags; + } + comments = + gst_tag_list_to_vorbiscomment_buffer (tags, (const guint8 *) "OpusTags", + 8, "Encoded with GStreamer Opusenc"); + + GST_BUFFER_OFFSET (comments) = 0; + GST_BUFFER_OFFSET_END (comments) = 0; + + if (empty_tags) + gst_tag_list_free (empty_tags); + + return comments; +} + +/* + * (really really) FIXME: move into core (dixit tpm) + */ +/** + * _gst_caps_set_buffer_array: + * @caps: a #GstCaps + * @field: field in caps to set + * @buf: header buffers + * + * Adds given buffers to an array of buffers set as the given @field + * on the given @caps. List of buffer arguments must be NULL-terminated. + * + * Returns: input caps with a streamheader field added, or NULL if some error + */ +static GstCaps * +_gst_caps_set_buffer_array (GstCaps * caps, const gchar * field, + GstBuffer * buf, ...) +{ + GstStructure *structure = NULL; + va_list va; + GValue array = { 0 }; + GValue value = { 0 }; + + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (gst_caps_is_fixed (caps), NULL); + g_return_val_if_fail (field != NULL, NULL); + + caps = gst_caps_make_writable (caps); + structure = gst_caps_get_structure (caps, 0); + + g_value_init (&array, GST_TYPE_ARRAY); + + va_start (va, buf); + /* put buffers in a fixed list */ + while (buf) { + g_assert (gst_buffer_is_writable (buf)); + + /* mark buffer */ + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_copy (buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + + buf = va_arg (va, GstBuffer *); + } + + gst_structure_set_value (structure, field, &array); + g_value_unset (&array); + + return caps; +} + +void +gst_opus_header_create_caps (GstCaps ** caps, GSList ** headers, gint nchannels, + gint sample_rate, const GstTagList * tags) +{ + GstBuffer *buf1, *buf2; + + g_return_if_fail (caps); + g_return_if_fail (headers && !*headers); + g_return_if_fail (nchannels > 0); + g_return_if_fail (sample_rate >= 0); /* 0 -> unset */ + + /* Opus streams in Ogg begin with two headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. */ + + /* create header buffers */ + buf1 = gst_opus_enc_create_id_buffer (nchannels, sample_rate); + buf2 = gst_opus_enc_create_metadata_buffer (tags); + + /* mark and put on caps */ + *caps = gst_caps_from_string ("audio/x-opus"); + *caps = _gst_caps_set_buffer_array (*caps, "streamheader", buf1, buf2, NULL); + + *headers = g_slist_prepend (*headers, buf2); + *headers = g_slist_prepend (*headers, buf1); +} diff --git a/ext/opus/gstopusheader.h b/ext/opus/gstopusheader.h new file mode 100644 index 0000000..4679083 --- /dev/null +++ b/ext/opus/gstopusheader.h @@ -0,0 +1,32 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2008> Sebastian Dröge + * + * 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_OPUS_HEADER_H__ +#define __GST_OPUS_HEADER_H__ + +#include + +G_BEGIN_DECLS + +extern void gst_opus_header_create_caps (GstCaps **caps, GSList **headers, gint nchannels, gint sample_rate, const GstTagList *tags); + +G_END_DECLS + +#endif /* __GST_OPUS_HEADER_H__ */