Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 19 May 2011 09:31:53 +0000 (11:31 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 19 May 2011 09:31:53 +0000 (11:31 +0200)
common
ext/alsa/gstalsasrc.c
ext/vorbis/gstvorbisdec.c
gst-libs/gst/video/video.c
gst-libs/gst/video/video.h
tests/check/libs/video.c

diff --git a/common b/common
index 46dfcea..9e5bbd5 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 46dfcea233cf6df83e3771d8a8066e87d614f893
+Subproject commit 9e5bbd508588961696e70c38e764492e0312ec4c
index 1932401..14eb95d 100644 (file)
@@ -195,13 +195,11 @@ gst_alsasrc_class_init (GstAlsaSrcClass * klass)
   GstElementClass *gstelement_class;
   GstBaseSrcClass *gstbasesrc_class;
   GstAudioSrcClass *gstaudiosrc_class;
-  GstBaseAudioSrcClass *gstbaseaudiosrc_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
   gstbasesrc_class = (GstBaseSrcClass *) klass;
   gstaudiosrc_class = (GstAudioSrcClass *) klass;
-  gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
 
   gobject_class->finalize = gst_alsasrc_finalize;
   gobject_class->get_property = gst_alsasrc_get_property;
index 71e3ff1..3e28f6d 100644 (file)
@@ -979,6 +979,77 @@ wrong_samples:
 }
 
 static GstFlowReturn
+vorbis_dec_handle_header_buffer (GstVorbisDec * vd, GstBuffer * buffer)
+{
+  ogg_packet *packet;
+  ogg_packet_wrapper packet_wrapper;
+
+  gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer);
+  packet = gst_ogg_packet_from_wrapper (&packet_wrapper);
+
+  return vorbis_handle_header_packet (vd, packet);
+}
+
+
+#define MIN_NUM_HEADERS 3
+static GstFlowReturn
+vorbis_dec_handle_header_caps (GstVorbisDec * vd, GstBuffer * buffer)
+{
+  GstFlowReturn result = GST_FLOW_OK;
+  GstCaps *caps = GST_PAD_CAPS (vd->sinkpad);
+  GstStructure *s = gst_caps_get_structure (caps, 0);
+  const GValue *array = gst_structure_get_value (s, "streamheader");
+
+  if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) {
+    const GValue *value = NULL;
+    GstBuffer *buf = NULL;
+
+    /* initial header */
+    value = gst_value_array_get_value (array, 0);
+    buf = gst_value_get_buffer (value);
+    if (!buf)
+      goto null_buffer;
+    result = vorbis_dec_handle_header_buffer (vd, buf);
+
+    /* comment header */
+    if (result == GST_FLOW_OK) {
+      value = gst_value_array_get_value (array, 1);
+      buf = gst_value_get_buffer (value);
+      if (!buf)
+        goto null_buffer;
+      result = vorbis_dec_handle_header_buffer (vd, buf);
+    }
+
+    /* bitstream codebook header */
+    if (result == GST_FLOW_OK) {
+      value = gst_value_array_get_value (array, 2);
+      buf = gst_value_get_buffer (value);
+      if (!buf)
+        goto null_buffer;
+      result = vorbis_dec_handle_header_buffer (vd, buf);
+    }
+  } else
+    goto array_error;
+
+done:
+  return (result != GST_FLOW_OK ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK);
+
+array_error:
+  {
+    GST_WARNING_OBJECT (vd, "streamheader array not found");
+    result = GST_FLOW_ERROR;
+    goto done;
+  }
+
+null_buffer:
+  {
+    GST_WARNING_OBJECT (vd, "streamheader with null buffer received");
+    result = GST_FLOW_ERROR;
+    goto done;
+  }
+}
+
+static GstFlowReturn
 vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer)
 {
   ogg_packet *packet;
@@ -1015,6 +1086,13 @@ vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer)
   } else {
     GstClockTime timestamp, duration;
 
+    /* try to find header in caps so we can initialize the decoder */
+    if (!vd->initialized) {
+      result = vorbis_dec_handle_header_caps (vd, buffer);
+      if (result != GST_FLOW_OK)
+        goto invalid_caps_header;
+    }
+
     timestamp = GST_BUFFER_TIMESTAMP (buffer);
     duration = GST_BUFFER_DURATION (buffer);
 
@@ -1043,6 +1121,13 @@ empty_header:
     vd->discont = TRUE;
     goto done;
   }
+
+invalid_caps_header:
+  {
+    GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL),
+        ("invalid streamheader in caps"));
+    goto done;
+  }
 }
 
 /*
index b7479eb..73093e6 100644 (file)
@@ -348,7 +348,7 @@ gst_video_parse_caps_chroma_site (GstCaps * caps)
  * Returns: TRUE if @caps was parsed correctly.
  */
 gboolean
-gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
+gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format,
     int *width, int *height)
 {
   GstStructure *structure;
@@ -2090,6 +2090,36 @@ gst_video_format_get_size (GstVideoFormat format, int width, int height)
 }
 
 /**
+ * gst_video_get_size_from_caps:
+ * @caps: a pointer to #GstCaps
+ * @size: a pointer to a gint that will be assigned the size (in bytes) of a video frame with the given caps
+ *
+ * Calculates the total number of bytes in the raw video format for the given
+ * caps.  This number should be used when allocating a buffer for raw video.
+ *
+ * Since: 0.10.34
+ *
+ * Returns: %TRUE if the size could be calculated from the caps
+ */
+gboolean
+gst_video_get_size_from_caps (const GstCaps * caps, gint * size)
+{
+  GstVideoFormat format = 0;
+  gint width = 0, height = 0;
+
+  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
+  g_return_val_if_fail (size != NULL, FALSE);
+
+  if (gst_video_format_parse_caps (caps, &format, &width, &height) == FALSE) {
+    GST_WARNING ("Could not parse caps: %" GST_PTR_FORMAT, caps);
+    return FALSE;
+  }
+
+  *size = gst_video_format_get_size (format, width, height);
+  return TRUE;
+}
+
+/**
  * gst_video_format_convert:
  * @format: a #GstVideoFormat
  * @width: the width of video
index e0dce17..60d73f4 100644 (file)
@@ -446,8 +446,8 @@ gboolean gst_video_calculate_display_ratio (guint *dar_n, guint *dar_d,
             guint video_par_n, guint video_par_d, 
             guint display_par_n, guint display_par_d);
 
-gboolean gst_video_format_parse_caps (GstCaps *caps, GstVideoFormat *format,
-    int *width, int *height);
+gboolean gst_video_format_parse_caps (const GstCaps *caps,
+    GstVideoFormat *format, int *width, int *height);
 gboolean gst_video_format_parse_caps_interlaced (GstCaps *caps, gboolean *interlaced);
 gboolean gst_video_parse_caps_framerate (GstCaps *caps,
     int *fps_n, int *fps_d);
@@ -480,6 +480,7 @@ int gst_video_format_get_component_height (GstVideoFormat format, int component,
 int gst_video_format_get_component_offset (GstVideoFormat format, int component,
     int width, int height);
 int gst_video_format_get_size (GstVideoFormat format, int width, int height);
+gboolean gst_video_get_size_from_caps (const GstCaps * caps, gint * size);
 gboolean gst_video_format_convert (GstVideoFormat format, int width, int height,
     int fps_n, int fps_d,
     GstFormat src_format, gint64 src_value,
index fc5c674..977c5dc 100644 (file)
@@ -752,6 +752,28 @@ GST_START_TEST (test_convert_frame_async)
 
 GST_END_TEST;
 
+GST_START_TEST (test_video_size_from_caps)
+{
+  gint size;
+  guint32 fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
+  GstCaps *caps = gst_caps_new_simple ("video/x-raw-yuv",
+      "format", GST_TYPE_FOURCC, fourcc,
+      "width", G_TYPE_INT, 640,
+      "height", G_TYPE_INT, 480,
+      "framerate", GST_TYPE_FRACTION, 25, 1,
+      NULL);
+
+  fail_unless (gst_video_get_size_from_caps (caps, &size));
+  fail_unless (size ==
+      gst_video_format_get_size (gst_video_format_from_fourcc (fourcc), 640,
+          480));
+  fail_unless (size == (640 * 480 * 12 / 8));
+
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
 static Suite *
 video_suite (void)
 {
@@ -767,6 +789,7 @@ video_suite (void)
   tcase_add_test (tc_chain, test_events);
   tcase_add_test (tc_chain, test_convert_frame);
   tcase_add_test (tc_chain, test_convert_frame_async);
+  tcase_add_test (tc_chain, test_video_size_from_caps);
 
   return s;
 }