opusparse: add opusparse element
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Tue, 15 Nov 2011 19:53:33 +0000 (19:53 +0000)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Wed, 16 Nov 2011 17:58:15 +0000 (17:58 +0000)
A very simple element that parses Opus streams from the ad hoc
framing used by the Opus test vectors.

ext/opus/Makefile.am
ext/opus/gstopus.c
ext/opus/gstopusparse.c [new file with mode: 0644]
ext/opus/gstopusparse.h [new file with mode: 0644]

index 57e1692..6fe723e 100644 (file)
@@ -1,6 +1,6 @@
 plugin_LTLIBRARIES = libgstopus.la
 
-libgstopus_la_SOURCES = gstopus.c gstopusdec.c gstopusenc.c
+libgstopus_la_SOURCES = gstopus.c gstopusdec.c gstopusenc.c gstopusparse.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 
+noinst_HEADERS = gstopusenc.h gstopusdec.h gstopusparse.h
index 65e9dcd..c5f68a1 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "gstopusdec.h"
 #include "gstopusenc.h"
+#include "gstopusparse.h"
 
 #include <gst/tag/tag.h>
 
@@ -38,6 +39,10 @@ plugin_init (GstPlugin * plugin)
           GST_TYPE_OPUS_DEC))
     return FALSE;
 
+  if (!gst_element_register (plugin, "opusparse", GST_RANK_NONE,
+          GST_TYPE_OPUS_PARSE))
+    return FALSE;
+
   gst_tag_register_musicbrainz_tags ();
 
   return TRUE;
diff --git a/ext/opus/gstopusparse.c b/ext/opus/gstopusparse.c
new file mode 100644 (file)
index 0000000..c946875
--- /dev/null
@@ -0,0 +1,158 @@
+/* GStreamer
+ * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2008 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-opusparse
+ * @see_also: opusenc, opusdec
+ *
+ * This element parses OPUS packets.
+ *
+ * <refsect2>
+ * <title>Example pipelines</title>
+ * |[
+ * gst-launch -v filesrc location=opusdata ! opusparse ! opusdec ! audioconvert ! audioresample ! alsasink
+ * ]| Decode and plays an unmuxed Opus file.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <opus/opus.h>
+#include "gstopusparse.h"
+
+GST_DEBUG_CATEGORY_STATIC (opusparse_debug);
+#define GST_CAT_DEFAULT opusparse_debug
+
+#define MAX_PAYLOAD_BYTES 1500
+
+static GstStaticPadTemplate opus_parse_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-opus, framed = (boolean) true")
+    );
+
+static GstStaticPadTemplate opus_parse_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-opus")
+    );
+
+G_DEFINE_TYPE (GstOpusParse, gst_opus_parse, GST_TYPE_BASE_PARSE);
+
+static gboolean gst_opus_parse_start (GstBaseParse * parse);
+static gboolean gst_opus_parse_check_valid_frame (GstBaseParse * base,
+    GstBaseParseFrame * frame, guint * frame_size, gint * skip);
+
+static void
+gst_opus_parse_class_init (GstOpusParseClass * klass)
+{
+  GstBaseParseClass *bpclass;
+  GstElementClass *element_class;
+
+  bpclass = (GstBaseParseClass *) klass;
+  element_class = (GstElementClass *) klass;
+
+  bpclass->start = GST_DEBUG_FUNCPTR (gst_opus_parse_start);
+  bpclass->check_valid_frame =
+      GST_DEBUG_FUNCPTR (gst_opus_parse_check_valid_frame);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&opus_parse_src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&opus_parse_sink_factory));
+  gst_element_class_set_details_simple (element_class, "Opus audio parser",
+      "Codec/Parser/Audio",
+      "parses opus audio streams",
+      "Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>");
+
+  GST_DEBUG_CATEGORY_INIT (opusparse_debug, "opusparse", 0,
+      "opus parsing element");
+}
+
+static void
+gst_opus_parse_init (GstOpusParse * parse)
+{
+}
+
+static gboolean
+gst_opus_parse_start (GstBaseParse * base)
+{
+  GstOpusParse *parse = GST_OPUS_PARSE (base);
+  GstCaps *caps;
+
+  caps = gst_caps_from_string ("audio/x-opus");
+  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (parse)), caps);
+  gst_caps_unref (caps);
+
+  return TRUE;
+}
+
+static gboolean
+gst_opus_parse_check_valid_frame (GstBaseParse * base,
+    GstBaseParseFrame * frame, guint * frame_size, gint * skip)
+{
+  GstOpusParse *parse;
+  guint8 *data;
+  gsize size;
+  guint32 packet_size;
+  int ret = FALSE;
+  int channels, bandwidth;
+
+  parse = GST_OPUS_PARSE (base);
+
+  data = GST_BUFFER_DATA (frame->buffer);
+  size = GST_BUFFER_SIZE (frame->buffer);
+  GST_DEBUG_OBJECT (parse, "Checking for frame, %u bytes in buffer", size);
+  if (size < 4) {
+    GST_DEBUG_OBJECT (parse, "Too small");
+    goto beach;
+  }
+  packet_size = GST_READ_UINT32_BE (data);
+  GST_DEBUG_OBJECT (parse, "Packet size: %u bytes", packet_size);
+  if (packet_size > MAX_PAYLOAD_BYTES) {
+    GST_DEBUG_OBJECT (parse, "Too large");
+    goto beach;
+  }
+  if (packet_size > size - 4) {
+    GST_DEBUG_OBJECT (parse, "Truncated");
+    goto beach;
+  }
+
+  channels = opus_packet_get_nb_channels (data + 8);
+  bandwidth = opus_packet_get_bandwidth (data + 8);
+  if (channels < 0 || bandwidth < 0) {
+    GST_DEBUG_OBJECT (parse, "It looked like a packet, but it is not");
+    goto beach;
+  }
+
+  GST_DEBUG_OBJECT (parse, "Got Opus packet, %d bytes");
+
+  *skip = 8;
+  *frame_size = packet_size;
+  ret = TRUE;
+
+beach:
+  return ret;
+}
diff --git a/ext/opus/gstopusparse.h b/ext/opus/gstopusparse.h
new file mode 100644 (file)
index 0000000..5f9f884
--- /dev/null
@@ -0,0 +1,55 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) <2008> 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_OPUS_PARSE_H__
+#define __GST_OPUS_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OPUS_PARSE \
+  (gst_opus_parse_get_type())
+#define GST_OPUS_PARSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPUS_PARSE,GstOpusParse))
+#define GST_OPUS_PARSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPUS_PARSE,GstOpusParseClass))
+#define GST_IS_OPUS_PARSE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPUS_PARSE))
+#define GST_IS_OPUS_PARSE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPUS_PARSE))
+
+typedef struct _GstOpusParse GstOpusParse;
+typedef struct _GstOpusParseClass GstOpusParseClass;
+
+struct _GstOpusParse {
+  GstBaseParse       element;
+};
+
+struct _GstOpusParseClass {
+  GstBaseParseClass parent_class;
+};
+
+GType gst_opus_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OPUS_PARSE_H__ */