Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 3 Aug 2011 16:25:30 +0000 (18:25 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 3 Aug 2011 16:25:30 +0000 (18:25 +0200)
Conflicts:
ext/pulse/pulsesink.c
ext/pulse/pulsesrc.c
gst/audioparsers/gstac3parse.c
gst/rtp/gstrtph264depay.c
gst/rtp/gstrtph264pay.c
gst/rtpmanager/gstrtpssrcdemux.c

18 files changed:
1  2 
configure.ac
ext/jack/gstjackaudiosink.c
ext/pulse/pulsesink.c
ext/pulse/pulsesrc.c
gst/audioparsers/gstac3parse.c
gst/auparse/gstauparse.c
gst/isomp4/qtdemux.c
gst/matroska/matroska-demux.c
gst/multifile/gstmultifilesink.c
gst/multipart/multipartdemux.c
gst/multipart/multipartmux.c
gst/rtp/gstrtph264depay.c
gst/rtp/gstrtph264pay.c
gst/rtp/gstrtpjpegpay.c
gst/rtpmanager/gstrtpssrcdemux.c
gst/rtpmanager/rtpsession.c
gst/rtsp/gstrtspsrc.c
sys/v4l2/gstv4l2object.c

diff --cc configure.ac
Simple merge
Simple merge
@@@ -1584,68 -1736,125 +1733,70 @@@ static GstStateChangeReturn gst_pulsesi
  # define ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
  #endif
  
 -GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
 -
 -#define _do_init(type) \
 -  gst_pulsesink_init_contexts (); \
 -  gst_pulsesink_init_interfaces (type);
 -
 -GST_BOILERPLATE_FULL (GstPulseSink, gst_pulsesink, GstBaseAudioSink,
 -    GST_TYPE_BASE_AUDIO_SINK, _do_init);
 -
 -static gboolean
 -gst_pulsesink_interface_supported (GstImplementsInterface *
 -    iface, GType interface_type)
 -{
 -  GstPulseSink *this = GST_PULSESINK_CAST (iface);
 -
 -  if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
 -    return TRUE;
 -  if (interface_type == GST_TYPE_STREAM_VOLUME)
 -    return TRUE;
 -
 -  return FALSE;
 -}
 -
 -static void
 -gst_pulsesink_implements_interface_init (GstImplementsInterfaceClass * klass)
 -{
 -  klass->supported = gst_pulsesink_interface_supported;
 -}
 -
 -static void
 -gst_pulsesink_init_interfaces (GType type)
 -{
 -  static const GInterfaceInfo implements_iface_info = {
 -    (GInterfaceInitFunc) gst_pulsesink_implements_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo probe_iface_info = {
 -    (GInterfaceInitFunc) gst_pulsesink_property_probe_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo svol_iface_info = {
 -    NULL, NULL, NULL
 -  };
 -
 -  g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
 -  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
 -      &implements_iface_info);
 -  g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
 -      &probe_iface_info);
 -}
 -
 -static void
 -gst_pulsesink_base_init (gpointer g_class)
 -{
 -  static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
 -      GST_PAD_SINK,
 -      GST_PAD_ALWAYS,
 -      GST_STATIC_CAPS ("audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 16, "
 -          "depth = (int) 16, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-float, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "width = (int) 32, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 32, "
 -          "depth = (int) 32, "
 -          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 24, "
 -          "depth = (int) 24, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 32, "
 -          "depth = (int) 24, "
 -          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "signed = (boolean) FALSE, "
 -          "width = (int) 8, "
 -          "depth = (int) 8, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-alaw, "
 -          "rate = (int) [ 1, MAX], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-mulaw, "
 -          "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
 +static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
 +    GST_PAD_SINK,
 +    GST_PAD_ALWAYS,
 +    GST_STATIC_CAPS ("audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 16, "
 +        "depth = (int) 16, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-float, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "width = (int) 32, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 32, "
 +        "depth = (int) 32, "
 +        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- #ifdef HAVE_PULSE_0_9_15
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 24, "
 +        "depth = (int) 24, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 32, "
 +        "depth = (int) 24, "
 +        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
- #endif
 +        "audio/x-raw-int, "
 +        "signed = (boolean) FALSE, "
 +        "width = (int) 8, "
 +        "depth = (int) 8, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-alaw, "
 +        "rate = (int) [ 1, MAX], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-mulaw, "
-         "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
-     );
++        "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
+ #ifdef HAVE_PULSE_1_0
 -          "audio/x-ac3, framed = (boolean) true;"
 -          "audio/x-eac3, framed = (boolean) true; "
 -          "audio/x-dts, framed = (boolean) true, "
 -          "  block_size = (int) { 512, 1024, 2048 }; "
 -          "audio/mpeg, mpegversion = (int)1, "
 -          "  mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true; "
++        "audio/x-ac3, framed = (boolean) true;"
++        "audio/x-eac3, framed = (boolean) true; "
++        "audio/x-dts, framed = (boolean) true, "
++        "  block_size = (int) { 512, 1024, 2048 }; "
++        "audio/mpeg, mpegversion = (int)1, "
++        "  mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true; "
+ #endif
 -      ));
++    ));
  
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 +GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
  
- #define _do_init(type) \
-   gst_pulsesink_init_contexts (); \
-   gst_pulsesink_init_interfaces (type);
 -  gst_element_class_set_details_simple (element_class,
 -      "PulseAudio Audio Sink",
 -      "Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&pad_template));
 -}
 +#define gst_pulsesink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstPulseSink, gst_pulsesink, GST_TYPE_BASE_AUDIO_SINK,
 +    gst_pulsesink_init_contexts ();
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
 +        gst_pulsesink_property_probe_interface_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL)
 +    );
  
  static GstRingBuffer *
  gst_pulsesink_create_ringbuffer (GstBaseAudioSink * sink)
@@@ -1800,7 -2046,182 +1994,182 @@@ server_dead
  }
  
  static void
 -gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
+ gst_pulsesink_sink_info_cb (pa_context * c, const pa_sink_info * i, int eol,
+     void *userdata)
+ {
+   GstPulseRingBuffer *pbuf;
+   GstPulseSink *psink;
+ #ifdef HAVE_PULSE_1_0
+   GList *l;
+   guint8 j;
+ #endif
+   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
+   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
+   if (!i)
+     goto done;
+   g_free (psink->device_description);
+   psink->device_description = g_strdup (i->description);
+ #ifdef HAVE_PULSE_1_0
+   g_mutex_lock (psink->sink_formats_lock);
+   for (l = g_list_first (psink->sink_formats); l; l = g_list_next (l))
+     pa_format_info_free ((pa_format_info *) l->data);
+   g_list_free (psink->sink_formats);
+   psink->sink_formats = NULL;
+   for (j = 0; j < i->n_formats; j++)
+     psink->sink_formats = g_list_prepend (psink->sink_formats,
+         pa_format_info_copy (i->formats[j]));
+   g_mutex_unlock (psink->sink_formats_lock);
+ #endif
+ done:
+   pa_threaded_mainloop_signal (mainloop, 0);
+ }
+ #ifdef HAVE_PULSE_1_0
+ static gboolean
+ gst_pulsesink_pad_acceptcaps (GstPad * pad, GstCaps * caps)
+ {
+   GstPulseSink *psink = GST_PULSESINK (gst_pad_get_parent_element (pad));
+   GstPulseRingBuffer *pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK
+       (psink)->ringbuffer);
+   GstCaps *pad_caps;
+   GstStructure *st;
+   gboolean ret = FALSE;
+   GstRingBufferSpec spec = { 0 };
+   pa_stream *stream = NULL;
+   pa_operation *o = NULL;
+   pa_channel_map channel_map;
+   pa_stream_flags_t flags;
+   pa_format_info *format = NULL, *formats[1];
+   guint channels;
+   pad_caps = gst_pad_get_caps_reffed (pad);
+   if (pad_caps) {
+     ret = gst_caps_can_intersect (pad_caps, caps);
+     gst_caps_unref (pad_caps);
+   }
+   /* Either template caps didn't match, or we're still in NULL state */
+   if (!ret || !pbuf->context)
+     goto done;
+   /* If we've not got fixed caps, creating a stream might fail, so let's just
+    * return from here with default acceptcaps behaviour */
+   if (!gst_caps_is_fixed (caps))
+     goto done;
+   ret = FALSE;
+   pa_threaded_mainloop_lock (mainloop);
+   spec.latency_time = GST_BASE_AUDIO_SINK (psink)->latency_time;
+   if (!gst_ring_buffer_parse_caps (&spec, caps))
+     goto out;
+   if (!gst_pulse_fill_format_info (&spec, &format, &channels))
+     goto out;
+   /* Make sure input is framed (one frame per buffer) and can be payloaded */
+   if (!pa_format_info_is_pcm (format)) {
+     gboolean framed = FALSE, parsed = FALSE;
+     st = gst_caps_get_structure (caps, 0);
+     gst_structure_get_boolean (st, "framed", &framed);
+     gst_structure_get_boolean (st, "parsed", &parsed);
+     if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
+       goto out;
+   }
+   /* initialize the channel map */
+   if (pa_format_info_is_pcm (format) &&
+       gst_pulse_gst_to_channel_map (&channel_map, &spec))
+     pa_format_info_set_channel_map (format, &channel_map);
+   if (pbuf->stream) {
+     /* We're already in PAUSED or above, so just reuse this stream to query
+      * sink formats and use those. */
+     GList *i;
+     if (!(o = pa_context_get_sink_info_by_name (pbuf->context, psink->device,
+                 gst_pulsesink_sink_info_cb, pbuf)))
+       goto info_failed;
+     while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
+       pa_threaded_mainloop_wait (mainloop);
+       if (gst_pulsering_is_dead (psink, pbuf, TRUE))
+         goto out;
+     }
+     g_mutex_lock (psink->sink_formats_lock);
+     for (i = g_list_first (psink->sink_formats); i; i = g_list_next (i)) {
+       if (pa_format_info_is_compatible ((pa_format_info *) i->data, format)) {
+         ret = TRUE;
+         break;
+       }
+     }
+     g_mutex_unlock (psink->sink_formats_lock);
+   } else {
+     /* We're in READY, let's connect a stream to see if the format is
+      * accpeted by whatever sink we're routed to */
+     formats[0] = format;
+     if (!(stream = pa_stream_new_extended (pbuf->context, "pulsesink probe",
+                 formats, 1, psink->proplist)))
+       goto out;
+     /* construct the flags */
+     flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
+         PA_STREAM_ADJUST_LATENCY | PA_STREAM_START_CORKED;
+     pa_stream_set_state_callback (stream, gst_pulsering_stream_state_cb, pbuf);
+     if (pa_stream_connect_playback (stream, psink->device, NULL, flags, NULL,
+             NULL) < 0)
+       goto out;
+     ret = gst_pulsering_wait_for_stream_ready (psink, stream);
+   }
+ out:
+   if (format)
+     pa_format_info_free (format);
+   if (o)
+     pa_operation_unref (o);
+   if (stream) {
+     pa_stream_set_state_callback (stream, NULL, NULL);
+     pa_stream_disconnect (stream);
+     pa_stream_unref (stream);
+   }
+   pa_threaded_mainloop_unlock (mainloop);
+ done:
+   gst_object_unref (psink);
+   return ret;
+ info_failed:
+   {
+     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
+         ("pa_context_get_sink_input_info() failed: %s",
+             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
+     goto out;
+   }
+ }
+ #endif
+ static void
 +gst_pulsesink_init (GstPulseSink * pulsesink)
  {
    pulsesink->server = NULL;
    pulsesink->device = NULL;
@@@ -225,13 -287,20 +229,26 @@@ gst_pulsesrc_class_init (GstPulseSrcCla
        g_param_spec_boxed ("stream-properties", "stream properties",
            "list of pulseaudio stream properties",
            GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 -
+   /**
+    * GstPulseSrc:source-output-index
+    *
+    * The index of the PulseAudio source output corresponding to this element.
+    *
+    * Since: 0.10.31
+    */
+   g_object_class_install_property (gobject_class,
+       PROP_SOURCE_OUTPUT_INDEX,
+       g_param_spec_uint ("source-output-index", "source output index",
+           "The index of the PulseAudio source output corresponding to this "
+           "record stream", 0, G_MAXUINT, PA_INVALID_INDEX,
+           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 +
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "PulseAudio Audio Source",
 +      "Source/Audio",
 +      "Captures audio from a PulseAudio server", "Lennart Poettering");
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&pad_template));
  }
  
  static void
@@@ -163,21 -163,15 +163,23 @@@ static gboolean gst_ac3_parse_check_val
      GstBaseParseFrame * frame, guint * size, gint * skipsize);
  static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
+ static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
+     GstEvent * event);
  
 -GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
 +#define gst_ac3_parse_parent_class parent_class
 +G_DEFINE_TYPE (GstAc3Parse, gst_ac3_parse, GST_TYPE_BASE_PARSE);
  
  static void
 -gst_ac3_parse_base_init (gpointer klass)
 +gst_ac3_parse_class_init (GstAc3ParseClass * klass)
  {
 +  GObjectClass *object_class = G_OBJECT_CLASS (klass);
    GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 +  GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
 +
 +  GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
 +      "AC3 audio stream parser");
 +
 +  object_class->finalize = gst_ac3_parse_finalize;
  
    gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&sink_template));
@@@ -237,20 -246,65 +242,70 @@@ gst_ac3_parse_stop (GstBaseParse * pars
    return TRUE;
  }
  
+ static void
+ gst_ac3_parse_set_alignment (GstAc3Parse * ac3parse, gboolean eac)
+ {
+   GstCaps *caps;
+   GstStructure *st;
+   const gchar *str = NULL;
+   int i;
+   if (G_LIKELY (!eac))
+     goto done;
+   caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (ac3parse));
+   if (!caps)
+     goto done;
+   for (i = 0; i < gst_caps_get_size (caps); i++) {
+     st = gst_caps_get_structure (caps, i);
+     if (!g_str_equal (gst_structure_get_name (st), "audio/x-eac3"))
+       continue;
+     if ((str = gst_structure_get_string (st, "alignment"))) {
+       if (g_str_equal (str, "iec61937")) {
+         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_IEC61937);
+         GST_DEBUG_OBJECT (ac3parse, "picked iec61937 alignment");
+       } else if (g_str_equal (str, "frame") == 0) {
+         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+         GST_DEBUG_OBJECT (ac3parse, "picked frame alignment");
+       } else {
+         g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+         GST_WARNING_OBJECT (ac3parse, "unknown alignment: %s", str);
+       }
+       break;
+     }
+   }
+   if (caps)
+     gst_caps_unref (caps);
+ done:
+   /* default */
+   if (ac3parse->align == GST_AC3_PARSE_ALIGN_NONE) {
+     g_atomic_int_set (&ac3parse->align, GST_AC3_PARSE_ALIGN_FRAME);
+     GST_DEBUG_OBJECT (ac3parse, "picked syncframe alignment");
+   }
+ }
  static gboolean
  gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
-     guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+     gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
+     guint * sid)
  {
 -  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
 +  GstBitReader bits;
 +  gpointer data;
 +  gsize size;
    guint8 fscod, frmsizcod, bsid, acmod, lfe_on;
 +  gboolean ret = FALSE;
  
    GST_LOG_OBJECT (ac3parse, "parsing ac3");
  
 +  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 +  gst_bit_reader_init (&bits, data, size);
+   gst_bit_reader_skip_unchecked (&bits, skip * 8);
  
    gst_bit_reader_skip_unchecked (&bits, 16 + 16);
    fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
@@@ -304,19 -353,16 +359,21 @@@ cleanup
  
  static gboolean
  gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
-     guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
+     gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
+     guint * sid)
  {
 -  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
 +  GstBitReader bits;
 +  gpointer data;
 +  gsize size;
    guint16 frmsiz, sample_rate, blocks;
    guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
 +  gboolean ret = FALSE;
  
    GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
  
 +  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 +  gst_bit_reader_init (&bits, data, size);
+   gst_bit_reader_skip_unchecked (&bits, skip * 8);
  
    gst_bit_reader_skip_unchecked (&bits, 16);
    strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp     */
@@@ -371,18 -412,14 +428,20 @@@ gst_ac3_parse_frame_header (GstAc3Pars
      guint * framesize, guint * rate, guint * chans, guint * blocks,
      guint * sid, gboolean * eac)
  {
 -  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
 +  GstBitReader bits;
    guint16 sync;
    guint8 bsid;
 +  gpointer data;
 +  gsize size;
 +  gboolean ret = FALSE;
 +
 +  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 +  gst_bit_reader_init (&bits, data, size);
  
 -  GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", GST_BUFFER_DATA (buf), 16);
 +  GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", data, MIN (size, 16));
  
+   gst_bit_reader_skip_unchecked (&bits, skip * 8);
    sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
    gst_bit_reader_skip_unchecked (&bits, 16 + 8);
    bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
    if (bsid <= 10) {
      if (eac)
        *eac = FALSE;
-     ret = gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
-         blocks, sid);
 -    return gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate,
++    ret = gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate,
+         chans, blocks, sid);
 +    goto cleanup;
-   }
-   if (bsid <= 16) {
+   } else if (bsid <= 16) {
      if (eac)
        *eac = TRUE;
-     ret = gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
-         blocks, sid);
 -    return gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate,
++    ret = gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate,
+         chans, blocks, sid);
 +    goto cleanup;
+   } else {
+     GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
+     return FALSE;
    }
 +
 +  GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
 +
 +cleanup:
 +  gst_buffer_unmap (buf, data, size);
 +
 +  return ret;
  }
  
  static gboolean
@@@ -422,20 -451,17 +482,22 @@@ gst_ac3_parse_check_valid_frame (GstBas
  {
    GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
    GstBuffer *buf = frame->buffer;
 -  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
 +  GstByteReader reader;
    gint off;
-   gboolean lost_sync, draining;
+   gboolean lost_sync, draining, eac, more = FALSE;
+   guint frmsiz, blocks, sid;
+   gint have_blocks = 0;
 +  gpointer data;
 +  gsize size;
 +  gboolean ret = FALSE;
  
 -  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
 -    return FALSE;
 +  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 +
 +  if (G_UNLIKELY (size < 6))
 +    goto cleanup;
  
    off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
 -      0, GST_BUFFER_SIZE (buf));
 +      0, size);
  
    GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
  
    }
  
    /* make sure the values in the frame header look sane */
-   if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
-           NULL, NULL, NULL)) {
+   if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, NULL, NULL,
+           &blocks, &sid, &eac)) {
      *skipsize = off + 2;
 -    return FALSE;
 +    goto cleanup;
    }
  
+   *framesize = frmsiz;
+   if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
+           GST_AC3_PARSE_ALIGN_NONE))
+     gst_ac3_parse_set_alignment (ac3parse, eac);
    GST_LOG_OBJECT (parse, "got frame");
  
    lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
@@@ -528,6 -595,10 +636,9 @@@ gst_ac3_parse_parse_frame (GstBasePars
      GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
          "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
          "channels", G_TYPE_INT, chans, NULL);
 -    gst_buffer_set_caps (buf, caps);
+     gst_caps_set_simple (caps, "alignment", G_TYPE_STRING,
+         g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937 ?
+         "iec61937" : "frame", NULL);
      gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
      gst_caps_unref (caps);
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -96,8 -95,26 +96,10 @@@ static GstBuffer *gst_rtp_h264_depay_pr
      GstBuffer * buf);
  static gboolean gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * filter,
      GstCaps * caps);
+ static gboolean gst_rtp_h264_depay_handle_event (GstBaseRTPDepayload * depay,
+     GstEvent * event);
  
  static void
 -gst_rtp_h264_depay_base_init (gpointer klass)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 -
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&gst_rtp_h264_depay_src_template));
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&gst_rtp_h264_depay_sink_template));
 -
 -  gst_element_class_set_details_simple (element_class, "RTP H264 depayloader",
 -      "Codec/Depayloader/Network/RTP",
 -      "Extracts H264 video from RTP packets (RFC 3984)",
 -      "Wim Taymans <wim.taymans@gmail.com>");
 -}
 -
 -static void
  gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
  {
    GObjectClass *gobject_class;
@@@ -598,10 -664,9 +658,11 @@@ gst_rtp_h264_depay_process (GstBaseRTPD
  
      timestamp = GST_BUFFER_TIMESTAMP (buf);
  
 -    payload_len = gst_rtp_buffer_get_payload_len (buf);
 -    payload = gst_rtp_buffer_get_payload (buf);
 -    marker = gst_rtp_buffer_get_marker (buf);
 +    gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
 +
 +    payload_len = gst_rtp_buffer_get_payload_len (&rtp);
 +    payload = gst_rtp_buffer_get_payload (&rtp);
++    marker = gst_rtp_buffer_get_marker (&rtp);
  
      GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);
  
            outdata[2] = nalu_size >> 8;
            outdata[3] = nalu_size & 0xff;
          }
 -        outdata += sizeof (sync_bytes);
 -        memcpy (outdata, payload, nalu_size);
 +        memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
 +        gst_buffer_unmap (outbuf, outdata, outsize);
  
-         gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
+         gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp, marker);
          break;
        }
      }
@@@ -420,9 -418,9 +420,10 @@@ gst_rtp_h264_pay_setcaps (GstBaseRTPPay
    GstRtpH264Pay *rtph264pay;
    GstStructure *str;
    const GValue *value;
 -  guint8 *data;
 -  guint size;
 +  guint8 *data, *bdata;
 +  gsize size, bsize;
 +  GstBuffer *buffer;
+   const gchar *alignment;
  
    rtph264pay = GST_RTP_H264_PAY (basepayload);
  
     * NALs */
    gst_basertppayload_set_options (basepayload, "video", TRUE, "H264", 90000);
  
+   alignment = gst_structure_get_string (str, "alignment");
+   if (alignment && !strcmp (alignment, "au"))
+     rtph264pay->au_alignment = TRUE;
+   else
+     rtph264pay->au_alignment = FALSE;
    /* packetized AVC video has a codec_data */
    if ((value = gst_structure_get_value (str, "codec_data"))) {
 -    GstBuffer *buffer;
      guint num_sps, num_pps;
      gint i, nal_size;
  
@@@ -793,10 -784,9 +800,10 @@@ gst_rtp_h264_pay_send_sps_pps (GstBaseR
  
      GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
      /* resend SPS */
 +    data = gst_buffer_map (sps_buf, &size, NULL, GST_MAP_READ);
      ret = gst_rtp_h264_pay_payload_nal (basepayload,
-         data, size, timestamp, sps_buf);
 -        GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp,
 -        sps_buf, FALSE);
++        data, size, timestamp, sps_buf, FALSE);
 +    gst_buffer_unmap (sps_buf, data, size);
      /* Not critical here; but throw a warning */
      if (ret != GST_FLOW_OK)
        GST_WARNING ("Problem pushing SPS");
  
      GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
      /* resend PPS */
 +    data = gst_buffer_map (pps_buf, &size, NULL, GST_MAP_READ);
      ret = gst_rtp_h264_pay_payload_nal (basepayload,
-         data, size, timestamp, pps_buf);
 -        GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp,
 -        pps_buf, FALSE);
++        data, size, timestamp, pps_buf, FALSE);
 +    gst_buffer_unmap (pps_buf, data, size);
      /* Not critical here; but throw a warning */
      if (ret != GST_FLOW_OK)
        GST_WARNING ("Problem pushing PPS");
@@@ -907,11 -891,9 +914,11 @@@ gst_rtp_h264_pay_payload_nal (GstBaseRT
        outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
      }
  
 +    gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
 +
      /* only set the marker bit on packets containing access units */
-     if (IS_ACCESS_UNIT (nalType)) {
+     if (IS_ACCESS_UNIT (nalType) && end_of_au) {
 -      gst_rtp_buffer_set_marker (outbuf, 1);
 +      gst_rtp_buffer_set_marker (&rtp, 1);
      }
  
      /* timestamp the outbuffer */
          end = 1;
        }
        if (IS_ACCESS_UNIT (nalType)) {
-         gst_rtp_buffer_set_marker (&rtp, end);
 -        gst_rtp_buffer_set_marker (outbuf, end && end_of_au);
++        gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
        }
  
        /* FU indicator */
Simple merge
@@@ -513,7 -514,7 +509,8 @@@ gst_rtp_ssrc_demux_chain (GstPad * pad
    GstRtpSsrcDemux *demux;
    guint32 ssrc;
    GstRtpSsrcDemuxPad *dpad;
 +  GstRTPBuffer rtp;
+   GstPad *srcpad;
  
    demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));
  
@@@ -561,7 -567,7 +565,8 @@@ gst_rtp_ssrc_demux_rtcp_chain (GstPad 
    guint32 ssrc;
    GstRtpSsrcDemuxPad *dpad;
    GstRTCPPacket packet;
 +  GstRTCPBuffer rtcp;
+   GstPad *srcpad;
  
    demux = GST_RTP_SSRC_DEMUX (GST_OBJECT_PARENT (pad));
  
Simple merge
Simple merge
Simple merge