Merge branch 'master' into 0.11
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 10 Jan 2012 13:32:32 +0000 (14:32 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 10 Jan 2012 13:32:32 +0000 (14:32 +0100)
Conflicts:
ext/cairo/gsttextoverlay.c
ext/pulse/pulseaudiosink.c
gst/audioparsers/gstaacparse.c
gst/avi/gstavimux.c
gst/flv/gstflvmux.c
gst/interleave/interleave.c
gst/isomp4/gstqtmux.c
gst/matroska/matroska-demux.c
gst/matroska/matroska-mux.c
gst/matroska/matroska-mux.h
gst/matroska/matroska-read-common.c
gst/multifile/gstmultifilesink.c
gst/multipart/multipartmux.c
gst/shapewipe/gstshapewipe.c
gst/smpte/gstsmpte.c
gst/udp/gstmultiudpsink.c
gst/videobox/gstvideobox.c
gst/videocrop/gstaspectratiocrop.c
gst/videomixer/videomixer.c
gst/videomixer/videomixer2.c
gst/wavparse/gstwavparse.c
po/ja.po
po/lv.po
po/sr.po
tests/check/Makefile.am
tests/check/elements/qtmux.c
tests/check/elements/rgvolume.c

68 files changed:
1  2 
Makefile.am
configure.ac
ext/cairo/gsttextoverlay.c
ext/dv/gstdvdemux.c
ext/flac/gstflacdec.c
ext/gdk_pixbuf/gstgdkpixbufsink.c
ext/jack/gstjackaudiosink.c
ext/jack/gstjackaudiosink.h
ext/jack/gstjackaudiosrc.c
ext/jack/gstjackaudiosrc.h
ext/jpeg/gstjpegdec.c
ext/pulse/pulsesink.c
ext/soup/gstsouphttpclientsink.c
ext/wavpack/gstwavpackparse.c
gst/alpha/gstalpha.c
gst/alpha/gstalpha.h
gst/audiofx/audiochebband.c
gst/audiofx/audiocheblimit.c
gst/audiofx/audiofirfilter.c
gst/audiofx/audioiirfilter.c
gst/audiofx/audiowsincband.c
gst/audiofx/audiowsinclimit.c
gst/audioparsers/gstaacparse.c
gst/audioparsers/gstac3parse.c
gst/avi/gstavidemux.c
gst/avi/gstavimux.c
gst/equalizer/gstiirequalizer.c
gst/flv/gstflvdemux.c
gst/flv/gstflvmux.c
gst/imagefreeze/gstimagefreeze.c
gst/interleave/interleave.c
gst/isomp4/gstqtmoovrecover.c
gst/isomp4/gstqtmux.c
gst/isomp4/gstqtmux.h
gst/isomp4/qtdemux.c
gst/matroska/matroska-demux.c
gst/matroska/matroska-demux.h
gst/matroska/matroska-mux.c
gst/matroska/matroska-mux.h
gst/matroska/matroska-read-common.c
gst/multifile/gstmultifilesink.c
gst/multipart/multipartmux.c
gst/multipart/multipartmux.h
gst/rtpmanager/gstrtpbin.c
gst/rtpmanager/gstrtpjitterbuffer.c
gst/rtpmanager/gstrtpsession.c
gst/rtpmanager/gstrtpssrcdemux.c
gst/rtpmanager/rtpsession.c
gst/rtsp/gstrtspsrc.c
gst/smpte/gstsmpte.c
gst/udp/gstmultiudpsink.c
gst/udp/gstudpsrc.c
gst/videocrop/gstaspectratiocrop.c
gst/videomixer/videomixer2.c
gst/wavparse/gstwavparse.c
gst/wavparse/gstwavparse.h
sys/oss4/oss4-mixer.c
sys/v4l2/gstv4l2bufferpool.c
sys/v4l2/gstv4l2videooverlay.c
sys/waveform/gstwaveformsink.c
sys/ximage/gstximagesrc.c
tests/check/Makefile.am
tests/check/elements/qtmux.c
tests/check/elements/rgvolume.c
tests/check/elements/souphttpsrc.c
tests/icles/gdkpixbufsink-test.c
tests/icles/v4l2src-test.c
tests/icles/videocrop-test.c

diff --cc Makefile.am
Simple merge
diff --cc configure.ac
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -143,8 -157,12 +143,10 @@@ GST_STATIC_PAD_TEMPLATE ("sink"
      );
  
  static GstStaticCaps gst_alpha_alpha_caps =
 -    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")
 -    ";" GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_ABGR ";"
 -    GST_VIDEO_CAPS_RGBA);
 +GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
  
+ /* FIXME: why do we need our own lock for this? */
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
  #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
    GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
    g_static_mutex_lock (&alpha->lock); \
    GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
    g_static_mutex_unlock (&alpha->lock); \
  } G_STMT_END
+ #else
+ #define GST_ALPHA_LOCK(alpha) G_STMT_START { \
+   GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
+   g_mutex_lock (&alpha->lock); \
+   GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
+ } G_STMT_END
+ #define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
+   GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
+   g_mutex_unlock (&alpha->lock); \
+ } G_STMT_END
+ #endif
  
 -static gboolean gst_alpha_start (GstBaseTransform * trans);
 -static gboolean gst_alpha_get_unit_size (GstBaseTransform * btrans,
 -    GstCaps * caps, guint * size);
  static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
 -    GstPadDirection direction, GstCaps * caps);
 -static gboolean gst_alpha_set_caps (GstBaseTransform * btrans,
 -    GstCaps * incaps, GstCaps * outcaps);
 -static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
 -    GstBuffer * in, GstBuffer * out);
 +    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
  static void gst_alpha_before_transform (GstBaseTransform * btrans,
      GstBuffer * buf);
  
@@@ -69,8 -70,14 +69,12 @@@ struct _GstAlph
    /* <private> */
  
    /* caps */
+ #if !GLIB_CHECK_VERSION (2, 31, 0)
    GStaticMutex lock;
+ #else
+   GMutex lock;
+ #endif
  
 -  GstVideoFormat in_format, out_format;
 -  gint width, height;
    gboolean in_sdtv, out_sdtv;
  
    /* properties */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -612,6 -945,19 +950,18 @@@ gst_aac_parse_check_valid_frame (GstBas
            needed_data);
      }
  
 -        GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_DRAINING (parse),
 -        framesize, &needed_data);
+   } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
+     guint needed_data = 1024;
+     ret = gst_aac_parse_check_loas_frame (aacparse, data,
++        size, GST_BASE_PARSE_DRAINING (parse), framesize, &needed_data);
+     if (!ret) {
+       GST_DEBUG ("buffer didn't contain valid frame");
+       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+           needed_data);
+     }
    } else {
      GST_DEBUG ("buffer didn't contain valid frame");
      gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
@@@ -659,36 -1002,59 +1009,70 @@@ gst_aac_parse_parse_frame (GstBasePars
    aacparse = GST_AAC_PARSE (parse);
    buffer = frame->buffer;
  
-   if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
-     return ret;
+   if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
+     /* see above */
+     frame->overhead = 7;
  
-   /* see above */
-   frame->overhead = 7;
 -    gst_aac_parse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
++    data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
++    gst_aac_parse_parse_adts_header (aacparse, data,
+         &rate, &channels, NULL, NULL);
++    gst_buffer_unmap (buffer, data, size);
 +
-   data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
-   gst_aac_parse_parse_adts_header (aacparse, data,
-       &rate, &channels, NULL, NULL);
-   gst_buffer_unmap (buffer, data, size);
-   GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
+     GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
  
-   if (G_UNLIKELY (rate != aacparse->sample_rate
-           || channels != aacparse->channels)) {
-     GstCaps *sinkcaps;
+     if (G_UNLIKELY (rate != aacparse->sample_rate
+             || channels != aacparse->channels)) {
++      GstCaps *sinkcaps;
 +
-     aacparse->sample_rate = rate;
-     aacparse->channels = channels;
+       aacparse->sample_rate = rate;
+       aacparse->channels = channels;
  
-     sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
-     if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
-       /* If linking fails, we need to return appropriate error */
 -      if (!gst_aac_parse_set_src_caps (aacparse,
 -              GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
++      sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
++      if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
+         /* If linking fails, we need to return appropriate error */
+         ret = GST_FLOW_NOT_LINKED;
+       }
 +      gst_caps_unref (sinkcaps);
-       ret = GST_FLOW_NOT_LINKED;
+       gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
+           aacparse->sample_rate, aacparse->frame_samples, 2, 2);
      }
-     gst_caps_unref (sinkcaps);
+   } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
+     gboolean setcaps = FALSE;
+     /* see above */
+     frame->overhead = 3;
 -    if (!gst_aac_parse_read_loas_config (aacparse, GST_BUFFER_DATA (buffer),
 -            GST_BUFFER_SIZE (buffer), &rate, &channels, NULL)) {
++    data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
++    if (!gst_aac_parse_read_loas_config (aacparse, data, size, &rate, &channels,
++            NULL)) {
+       GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
+     } else if (G_UNLIKELY (rate != aacparse->sample_rate
+             || channels != aacparse->channels)) {
+       aacparse->sample_rate = rate;
+       aacparse->channels = channels;
+       setcaps = TRUE;
+       GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
+           channels);
+     }
++    gst_buffer_unmap (buffer, data, size);
+     /* We want to set caps both at start, and when rate/channels change.
+        Since only some LOAS frames have that info, we may receive frames
+        before knowing about rate/channels. */
 -    if (setcaps || !GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (aacparse))) {
 -      if (!gst_aac_parse_set_src_caps (aacparse,
 -              GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
++    if (setcaps
++        || !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
++      GstCaps *sinkcaps =
++          gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
++      if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
+         /* If linking fails, we need to return appropriate error */
+         ret = GST_FLOW_NOT_LINKED;
+       }
++      gst_caps_unref (sinkcaps);
  
-     gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
-         aacparse->sample_rate, aacparse->frame_samples, 2, 2);
+       gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
+           aacparse->sample_rate, aacparse->frame_samples, 2, 2);
+     }
    }
  
    return ret;
@@@ -324,9 -321,11 +324,11 @@@ gst_ac3_parse_frame_header_ac3 (GstAc3P
  
    /* spec not quite clear here: decoder should decode if less than 8,
     * but seemingly only defines 6 and 8 cases */
-   if (bsid > 8) {
+   /* Files with 9 and 10 happen, and seem to comply with the <= 8
+      format, so let them through. The spec says nothing about 9 and 10 */
+   if (bsid > 10) {
      GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
 -    return FALSE;
 +    goto cleanup;
    } else if (bsid != 8 && bsid != 6) {
      GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid);
    }
Simple merge
@@@ -188,14 -190,17 +188,14 @@@ static GstStaticPadTemplate audio_sink_
          "wmaversion = (int) [ 1, 2 ] ")
      );
  
 -static void gst_avi_mux_base_init (gpointer g_class);
 -static void gst_avi_mux_class_init (GstAviMuxClass * klass);
 -static void gst_avi_mux_init (GstAviMux * avimux);
  static void gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free);
  
- static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads * pads,
+ static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads2 * pads,
      GstAviMux * avimux);
- static gboolean gst_avi_mux_handle_event (GstPad * pad, GstObject * parent,
-     GstEvent * event);
+ static gboolean gst_avi_mux_handle_event (GstCollectPads2 * pad,
+     GstCollectData2 * data, GstEvent * event, gpointer user_data);
  static GstPad *gst_avi_mux_request_new_pad (GstElement * element,
 -    GstPadTemplate * templ, const gchar * name);
 +    GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
  static void gst_avi_mux_release_pad (GstElement * element, GstPad * pad);
  static void gst_avi_mux_set_property (GObject * object,
      guint prop_id, const GValue * value, GParamSpec * pspec);
@@@ -977,16 -1027,10 +980,10 @@@ gst_avi_mux_request_new_pad (GstElemen
  
    g_free (name);
  
-   avipad->collect = gst_collect_pads_add_pad (avimux->collect,
-       newpad, sizeof (GstAviCollectData), NULL);
+   avipad->collect = gst_collect_pads2_add_pad (avimux->collect,
+       newpad, sizeof (GstAviCollectData));
    ((GstAviCollectData *) (avipad->collect))->avipad = avipad;
-   /* FIXME: hacked way to override/extend the event function of
-    * GstCollectPads; because it sets its own event function giving the
-    * element no access to events */
-   avimux->collect_event = GST_PAD_EVENTFUNC (newpad);
-   gst_pad_set_event_function (newpad,
-       GST_DEBUG_FUNCPTR (gst_avi_mux_handle_event));
 +
    if (!gst_element_add_pad (element, newpad))
      goto pad_add_failed;
  
@@@ -1833,35 -1858,14 +1830,36 @@@ gst_avi_mux_restart_file (GstAviMux * a
  
  /* handle events (search) */
  static gboolean
- gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
+ gst_avi_mux_handle_event (GstCollectPads2 * pads, GstCollectData2 * data,
+     GstEvent * event, gpointer user_data)
  {
    GstAviMux *avimux;
-   gboolean ret = TRUE;
++  gboolean ret = FALSE;
  
-   avimux = GST_AVI_MUX (parent);
+   avimux = GST_AVI_MUX (user_data);
  
    switch (GST_EVENT_TYPE (event)) {
-       collect_pad = (GstAviCollectData *) gst_pad_get_element_private (pad);
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +      GstAviCollectData *collect_pad;
 +      GstAviVideoPad *avipad;
 +
 +      gst_event_parse_caps (event, &caps);
 +
 +      /* find stream data */
-         ret = gst_avi_mux_vidsink_set_caps (pad, caps);
++      collect_pad = (GstAviCollectData *) data;
 +      g_assert (collect_pad);
 +      avipad = (GstAviVideoPad *) collect_pad->avipad;
 +      g_assert (avipad);
 +
 +      if (avipad->parent.is_video) {
-         ret = gst_avi_mux_audsink_set_caps (pad, caps);
++        ret = gst_avi_mux_vidsink_set_caps (GST_PAD (avipad), caps);
 +      } else {
++        ret = gst_avi_mux_audsink_set_caps (GST_PAD (avipad), caps);
 +      }
 +      break;
 +    }
      case GST_EVENT_TAG:{
        GstTagList *list;
        GstTagSetter *setter = GST_TAG_SETTER (avimux);
        break;
    }
  
-   /* now GstCollectPads can take care of the rest, e.g. EOS */
-   if (ret)
-     ret = avimux->collect_event (pad, parent, event);
+   /* now GstCollectPads2 can take care of the rest, e.g. EOS */
 -  return FALSE;
 +  return ret;
  }
  
  /* send extra 'padding' data */
@@@ -1907,11 -1903,10 +1902,11 @@@ gst_avi_mux_do_buffer (GstAviMux * avim
    GstBuffer *data, *header;
    gulong total_size, pad_bytes = 0;
    guint flags;
 +  gsize datasize;
  
-   data = gst_collect_pads_pop (avimux->collect, avipad->collect);
+   data = gst_collect_pads2_pop (avimux->collect, avipad->collect);
    /* arrange downstream running time */
 -  data = gst_buffer_make_metadata_writable (data);
 +  data = gst_buffer_make_writable (data);
    GST_BUFFER_TIMESTAMP (data) =
        gst_segment_to_running_time (&avipad->collect->segment,
        GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (data));
Simple merge
Simple merge
@@@ -89,17 -99,17 +89,21 @@@ G_DEFINE_TYPE_WITH_CODE (GstFlvMux, gst
  
  static void gst_flv_mux_finalize (GObject * object);
  static GstFlowReturn
- gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data);
+ gst_flv_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
+     GstBuffer * buf, gpointer user_data);
+ static gboolean
+ gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+     GstEvent * event, gpointer user_data);
  
 -static gboolean gst_flv_mux_handle_src_event (GstPad * pad, GstEvent * event);
 +static gboolean gst_flv_mux_handle_src_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
  static GstPad *gst_flv_mux_request_new_pad (GstElement * element,
 -    GstPadTemplate * templ, const gchar * name);
 +    GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps);
  static void gst_flv_mux_release_pad (GstElement * element, GstPad * pad);
  
 +static gboolean gst_flv_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps);
 +static gboolean gst_flv_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps);
 +
  static void gst_flv_mux_get_property (GObject * object,
      guint prop_id, GValue * value, GParamSpec * pspec);
  static void gst_flv_mux_set_property (GObject * object,
@@@ -273,34 -268,12 +281,34 @@@ gst_flv_mux_handle_src_event (GstPad * 
  }
  
  static gboolean
- gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
-     GstEvent * event)
+ gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+     GstEvent * event, gpointer user_data)
  {
-   GstFlvMux *mux = GST_FLV_MUX (parent);
-   gboolean ret = TRUE;
+   GstFlvMux *mux = GST_FLV_MUX (user_data);
++  gboolean ret = FALSE;
  
    switch (GST_EVENT_TYPE (event)) {
-       flvpad = (GstFlvPad *) gst_pad_get_element_private (pad);
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +      GstFlvPad *flvpad;
 +
 +      gst_event_parse_caps (event, &caps);
 +
 +      /* find stream data */
-         ret = gst_flv_mux_video_pad_setcaps (pad, caps);
++      flvpad = (GstFlvPad *) data;
 +      g_assert (flvpad);
 +
 +      if (flvpad->video) {
-         ret = gst_flv_mux_audio_pad_setcaps (pad, caps);
++        ret = gst_flv_mux_video_pad_setcaps (data->pad, caps);
 +      } else {
++        ret = gst_flv_mux_audio_pad_setcaps (data->pad, caps);
 +      }
 +      /* and eat */
 +      ret = FALSE;
 +      gst_event_unref (event);
 +      break;
 +    }
      case GST_EVENT_TAG:{
        GstTagList *list;
        GstTagSetter *setter = GST_TAG_SETTER (mux);
        break;
    }
  
-   /* now GstCollectPads can take care of the rest, e.g. EOS */
-   if (ret)
-     ret = mux->collect_event (pad, parent, event);
+   /* now GstCollectPads2 can take care of the rest, e.g. EOS */
 -  return FALSE;
 +  return ret;
  }
  
  static gboolean
@@@ -573,14 -546,7 +578,6 @@@ gst_flv_mux_request_new_pad (GstElemen
    cpad->video_codec_data = NULL;
    gst_flv_mux_reset_pad (mux, cpad, video);
  
-   /* FIXME: hacked way to override/extend the event function of
-    * GstCollectPads; because it sets its own event function giving the
-    * element no access to events.
-    */
-   mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (pad);
-   gst_pad_set_event_function (pad,
-       GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event));
 -  gst_pad_set_setcaps_function (pad, setcapsfunc);
    gst_pad_set_active (pad, TRUE);
    gst_element_add_pad (element, pad);
  
@@@ -777,15 -750,22 +778,18 @@@ tags
      }
    }
  
+   if (!full)
+     goto end;
    if (mux->duration == GST_CLOCK_TIME_NONE) {
      GSList *l;
 -
 -    GstFormat fmt = GST_FORMAT_TIME;
      guint64 dur;
  
      for (l = mux->collect->data; l; l = l->next) {
-       GstCollectData *cdata = l->data;
+       GstCollectData2 *cdata = l->data;
  
 -      fmt = GST_FORMAT_TIME;
 -
 -      if (gst_pad_query_peer_duration (cdata->pad, &fmt, (gint64 *) & dur) &&
 -          fmt == GST_FORMAT_TIME && dur != GST_CLOCK_TIME_NONE) {
 +      if (gst_pad_peer_query_duration (cdata->pad, GST_FORMAT_TIME,
 +              (gint64 *) & dur) && dur != GST_CLOCK_TIME_NONE) {
          if (mux->duration == GST_CLOCK_TIME_NONE)
            mux->duration = dur;
          else
      tags_written++;
    }
  
 -  tmp = gst_buffer_new_and_alloc (2 + 0 + 1);
 -  data = GST_BUFFER_DATA (tmp);
+ end:
+   if (!tags_written) {
+     gst_buffer_unref (script_tag);
+     script_tag = NULL;
+     goto exit;
+   }
 +  _gst_buffer_new_and_alloc (2 + 0 + 1, &tmp, &data);
    data[0] = 0;                  /* 0 byte size */
    data[1] = 0;
    data[2] = 9;                  /* end marker */
    script_tag = gst_buffer_join (script_tag, tmp);
    tags_written++;
  
 -  tmp = gst_buffer_new_and_alloc (4);
 -  data = GST_BUFFER_DATA (tmp);
 -  GST_WRITE_UINT32_BE (data, GST_BUFFER_SIZE (script_tag));
 +  _gst_buffer_new_and_alloc (4, &tmp, &data);
 +  GST_WRITE_UINT32_BE (data, gst_buffer_get_size (script_tag));
    script_tag = gst_buffer_join (script_tag, tmp);
  
 -  data = GST_BUFFER_DATA (script_tag);
 -  data[1] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 16) & 0xff;
 -  data[2] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 8) & 0xff;
 -  data[3] = ((GST_BUFFER_SIZE (script_tag) - 11 - 4) >> 0) & 0xff;
 +  data = gst_buffer_map (script_tag, NULL, NULL, GST_MAP_WRITE);
 +  data[1] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 16) & 0xff;
 +  data[2] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 8) & 0xff;
 +  data[3] = ((gst_buffer_get_size (script_tag) - 11 - 4) >> 0) & 0xff;
  
    GST_WRITE_UINT32_BE (data + 11 + 13 + 1, tags_written);
 +  gst_buffer_unmap (script_tag, data, -1);
  
+ exit:
    return script_tag;
  }
  
@@@ -1295,7 -1265,7 +1296,8 @@@ gst_flv_mux_rewrite_header (GstFlvMux 
    GList *l;
    guint32 index_len, allocate_size;
    guint32 i, index_skip;
 +  GstSegment segment;
+   GstClockTime dur;
  
    if (mux->streamable)
      return GST_FLOW_OK;
@@@ -1426,12 -1402,8 +1432,10 @@@ gst_flv_mux_handle_buffer (GstCollectPa
    GstFlvPad *best;
    GstClockTime best_time;
    GstFlowReturn ret;
-   GSList *sl;
-   gboolean eos = TRUE;
  
    if (mux->state == GST_FLV_MUX_STATE_HEADER) {
 +    GstSegment segment;
 +
      if (mux->collect->data == NULL) {
        GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
            ("No input streams configured"));
    if (!mux->streamable && GST_CLOCK_TIME_IS_VALID (best_time)
        && best_time / GST_MSECOND > G_MAXINT32) {
      GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS");
-     eos = TRUE;
+     gst_buffer_unref (buffer);
+     buffer = NULL;
+     best = NULL;
    }
  
-   if (!eos && best) {
-     return gst_flv_mux_write_buffer (mux, best);
-   } else if (eos) {
+   if (best) {
+     return gst_flv_mux_write_buffer (mux, best, buffer);
+   } else {
      gst_flv_mux_rewrite_header (mux);
      gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
 -    return GST_FLOW_UNEXPECTED;
 +    return GST_FLOW_EOS;
-   } else {
-     return GST_FLOW_OK;
    }
  }
  
Simple merge
Simple merge
Simple merge
@@@ -2537,54 -2522,16 +2540,16 @@@ gst_qt_mux_handle_buffer (GstCollectPad
    }
  
    if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
 -    return GST_FLOW_UNEXPECTED;
 +    return GST_FLOW_EOS;
  
-   /* select the best buffer */
-   walk = qtmux->collect->data;
-   while (walk) {
-     GstQTPad *pad;
-     GstCollectData *data;
-     data = (GstCollectData *) walk->data;
-     pad = (GstQTPad *) data;
-     walk = g_slist_next (walk);
-     buf = gst_collect_pads_peek (pads, data);
-     if (buf == NULL) {
-       GST_LOG_OBJECT (qtmux, "Pad %s has no buffers",
-           GST_PAD_NAME (pad->collect.pad));
-       continue;
-     }
-     time = GST_BUFFER_TIMESTAMP (buf);
-     gst_buffer_unref (buf);
-     /* invalid should pass */
-     if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
-       time =
-           gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME, time);
-       if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
-         GST_DEBUG_OBJECT (qtmux, "clipping buffer on pad %s outside segment",
-             GST_PAD_NAME (data->pad));
-         buf = gst_collect_pads_pop (pads, data);
-         gst_buffer_unref (buf);
-         return GST_FLOW_OK;
-       }
-     }
-     if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time) ||
-         (GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
-       best_pad = pad;
-       best_time = time;
-     }
-   }
+   best_pad = (GstQTPad *) cdata;
  
+   /* clipping already converted to running time */
    if (best_pad != NULL) {
+     g_assert (buf);
+     best_time = GST_BUFFER_TIMESTAMP (buf);
      GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
          GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
-     buf = gst_collect_pads_pop (pads, &best_pad->collect);
-     buf = gst_buffer_make_writable (buf);
-     GST_BUFFER_TIMESTAMP (buf) = best_time;
      ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
    } else {
      ret = gst_qt_mux_stop_file (qtmux);
@@@ -3284,30 -3229,15 +3249,30 @@@ refuse_renegotiation
  }
  
  static gboolean
- gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+ gst_qt_mux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+     GstEvent * event, gpointer user_data)
  {
-   gboolean ret;
    GstQTMux *qtmux;
    guint32 avg_bitrate = 0, max_bitrate = 0;
+   GstPad *pad = data->pad;
  
-   qtmux = GST_QT_MUX_CAST (parent);
+   qtmux = GST_QT_MUX_CAST (user_data);
    switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +      GstQTPad *collect_pad;
 +
 +      gst_event_parse_caps (event, &caps);
 +
 +      /* find stream data */
 +      collect_pad = (GstQTPad *) gst_pad_get_element_private (pad);
 +      g_assert (collect_pad);
 +      g_assert (collect_pad->set_caps);
 +
 +      collect_pad->set_caps (pad, caps);
 +      break;
 +    }
      case GST_EVENT_TAG:{
        GstTagList *list;
        GstTagSetter *setter = GST_TAG_SETTER (qtmux);
@@@ -3418,18 -3339,12 +3383,10 @@@ gst_qt_mux_request_new_pad (GstElement 
  
    /* set up pad functions */
    if (audio)
 -    gst_pad_set_setcaps_function (newpad,
 -        GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
 +    collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps);
    else
 -    gst_pad_set_setcaps_function (newpad,
 -        GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
 +    collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
  
-   /* FIXME: hacked way to override/extend the event function of
-    * GstCollectPads; because it sets its own event function giving the
-    * element no access to events.
-    */
-   qtmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
-   gst_pad_set_event_function (newpad,
-       GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event));
    gst_pad_set_active (newpad, TRUE);
    gst_element_add_pad (element, newpad);
  
Simple merge
Simple merge
@@@ -1356,10 -1375,12 +1362,12 @@@ gst_matroska_demux_query (GstMatroskaDe
          GST_OBJECT_LOCK (demux);
          if (context)
            gst_query_set_position (query, GST_FORMAT_TIME,
-               context->pos - demux->stream_start_time);
+               MAX (context->pos, demux->stream_start_time) -
+               demux->stream_start_time);
          else
            gst_query_set_position (query, GST_FORMAT_TIME,
-               demux->common.segment.position - demux->stream_start_time);
 -              MAX (demux->common.segment.last_stop, demux->stream_start_time) -
++              MAX (demux->common.segment.position, demux->stream_start_time) -
+               demux->stream_start_time);
          GST_OBJECT_UNLOCK (demux);
        } else if (format == GST_FORMAT_DEFAULT && context
            && context->default_duration) {
@@@ -1737,11 -1746,14 +1745,14 @@@ gst_matroska_demux_search_pos (GstMatro
    /* estimate using start and current position */
    GST_OBJECT_LOCK (demux);
    opos = demux->common.offset - demux->common.ebml_segment_start;
 -  otime = demux->common.segment.last_stop;
 +  otime = demux->common.segment.position;
    GST_OBJECT_UNLOCK (demux);
  
+   /* sanitize */
+   time = MAX (time, demux->stream_start_time);
    /* avoid division by zero in first estimation below */
-   if (otime == 0)
+   if (otime <= demux->stream_start_time)
      otime = time;
  
  retry:
@@@ -1918,9 -1930,19 +1929,17 @@@ gst_matroska_demux_handle_seek_event (G
     * segment when we close the current segment. */
    memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment));
  
 -  if (!demux->streaming && !demux->common.index &&
 -      demux->invalid_duration) {
 -    gst_segment_set_duration (&seeksegment, GST_FORMAT_TIME,
 -        GST_CLOCK_TIME_NONE);
+   /* pull mode without index means that the actual duration is not known,
+    * we might be playing a file that's still being recorded
+    * so, invalidate our current duration, which is only a moving target,
+    * and should not be used to clamp anything */
++  if (!demux->streaming && !demux->common.index && demux->invalid_duration) {
++    seeksegment.duration = GST_CLOCK_TIME_NONE;
+   }
    if (event) {
      GST_DEBUG_OBJECT (demux, "configuring seek");
 -    gst_segment_set_seek (&seeksegment, rate, format, flags,
 +    gst_segment_do_seek (&seeksegment, rate, format, flags,
          cur_type, cur, stop_type, stop, &update);
      /* compensate for clip start time */
      if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
      }
    }
  
 -  gst_segment_set_duration (&seeksegment, GST_FORMAT_TIME,
 -      demux->common.segment.duration);
+   /* restore segment duration (if any effect),
+    * would be determined again when parsing, but anyway ... */
++  seeksegment.duration = demux->common.segment.duration;
    flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
    keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
  
    GST_OBJECT_LOCK (demux);
    track = gst_matroska_read_common_get_seek_track (&demux->common, track);
    if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, track,
 -              seeksegment.last_stop, &demux->seek_index, &demux->seek_entry)) ==
 +              seeksegment.position, &demux->seek_index, &demux->seek_entry)) ==
        NULL) {
      /* pull mode without index can scan later on */
-     if (demux->common.index || demux->streaming) {
+     if (demux->streaming) {
        GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
        GST_OBJECT_UNLOCK (demux);
        return FALSE;
@@@ -1989,12 -2016,11 +2012,12 @@@ next
    GST_PAD_STREAM_LOCK (demux->common.sinkpad);
  
    /* pull mode without index can do some scanning */
-   if (!demux->streaming && !demux->common.index) {
+   if (!demux->streaming && !entry) {
      /* need to stop flushing upstream as we need it next */
      if (flush)
 -      gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop ());
 -    entry = gst_matroska_demux_search_pos (demux, seeksegment.last_stop);
 +      gst_pad_push_event (demux->common.sinkpad,
 +          gst_event_new_flush_stop (TRUE));
 +    entry = gst_matroska_demux_search_pos (demux, seeksegment.position);
      /* keep local copy */
      if (entry) {
        scan_entry = *entry;
    if (keyunit) {
      GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %"
          GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
-     seeksegment.start = entry->time;
-     seeksegment.position = entry->time;
-     seeksegment.time = entry->time - demux->stream_start_time;
+     seeksegment.start = MAX (entry->time, demux->stream_start_time);
 -    seeksegment.last_stop = seeksegment.start;
++    seeksegment.position = seeksegment.start;
+     seeksegment.time = seeksegment.start - demux->stream_start_time;
    }
  
  exit:
@@@ -3342,17 -3320,16 +3365,17 @@@ gst_matroska_demux_parse_blockgroup_or_
              "Setting stream start time to %" GST_TIME_FORMAT,
              GST_TIME_ARGS (lace_time));
        }
 -      clace_time = MAX (lace_time, demux->stream_start_time);
 -      gst_segment_set_newsegment (&demux->common.segment, FALSE,
 -          demux->common.segment.rate, GST_FORMAT_TIME, clace_time,
 -          GST_CLOCK_TIME_NONE, clace_time - demux->stream_start_time);
 +      if (GST_CLOCK_TIME_IS_VALID (segment->stop))
 +        segment_duration = segment->stop - segment->start;
 +      else if (GST_CLOCK_TIME_IS_VALID (segment->position))
 +        segment_duration = segment->position - segment->start;
 +      segment->base += segment_duration / fabs (segment->rate);
-       segment->start = lace_time;
++      segment->start = MAX (lace_time, demux->stream_start_time);
 +      segment->stop = GST_CLOCK_TIME_NONE;
-       segment->position = lace_time - demux->stream_start_time;
++      segment->position = segment->start - demux->stream_start_time;
        /* now convey our segment notion downstream */
 -      gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE,
 -              demux->common.segment.rate, demux->common.segment.format,
 -              demux->common.segment.start, demux->common.segment.stop,
 -              demux->common.segment.start));
 -      demux->need_newsegment = FALSE;
 +      gst_matroska_demux_send_event (demux, gst_event_new_segment (segment));
 +      demux->need_segment = FALSE;
      }
  
      if (block_duration != -1) {
  
          GST_OBJECT_LOCK (demux);
          if (demux->common.segment.duration == -1 ||
-             demux->common.segment.duration <
-             lace_time - demux->stream_start_time) {
+             demux->stream_start_time + demux->common.segment.duration <
+             last_stop_end) {
 -          gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME,
 -              last_stop_end - demux->stream_start_time);
 +          demux->common.segment.duration =
 +              last_stop_end - demux->stream_start_time;
            GST_OBJECT_UNLOCK (demux);
            gst_element_post_message (GST_ELEMENT_CAST (demux),
                gst_message_new_duration (GST_OBJECT_CAST (demux),
@@@ -4475,12 -4458,17 +4499,14 @@@ pause
        /* Close the segment, i.e. update segment stop with the duration
         * if no stop was set */
        if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
-           !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) {
+           !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) &&
+           GST_CLOCK_TIME_IS_VALID (demux->common.segment.start) &&
+           demux->last_stop_end > demux->common.segment.start) {
 -        /* arrange to accumulate duration downstream, but avoid sending
 -         * newsegment with decreasing start (w.r.t. sync newsegment events) */
 -        GstEvent *event =
 -            gst_event_new_new_segment_full (TRUE, demux->common.segment.rate,
 -            demux->common.segment.applied_rate, demux->common.segment.format,
 -            demux->last_stop_end, demux->last_stop_end,
 -            demux->common.segment.time + (demux->last_stop_end -
 -                demux->common.segment.start));
 +        GstSegment segment = demux->common.segment;
 +        GstEvent *event;
 +
-         segment.stop = MAX (demux->last_stop_end, segment.start);
++        segment.stop = demux->last_stop_end;
 +        event = gst_event_new_segment (&segment);
          gst_matroska_demux_send_event (demux, event);
        }
  
Simple merge
@@@ -662,9 -699,47 +665,47 @@@ gst_matroska_mux_handle_src_event (GstP
        break;
    }
  
 -  return gst_pad_event_default (pad, event);
 +  return gst_pad_event_default (pad, parent, event);
  }
  
+ static void
+ gst_matroska_mux_build_vobsub_private (GstMatroskaTrackContext * context,
+     const guint * clut)
+ {
+   gchar *clutv[17];
+   gchar *sclut;
+   gint i;
+   guint32 col;
+   gdouble y, u, v;
+   guint8 r, g, b;
+   /* produce comma-separated list in hex format */
+   for (i = 0; i < 16; ++i) {
+     col = clut[i];
+     /* replicate vobsub's slightly off RGB conversion calculation */
+     y = (((col >> 16) & 0xff) - 16) * 255 / 219;
+     u = ((col >> 8) & 0xff) - 128;
+     v = (col & 0xff) - 128;
+     r = CLAMP (1.0 * y + 1.4022 * u, 0, 255);
+     g = CLAMP (1.0 * y - 0.3456 * u - 0.7145 * v, 0, 255);
+     b = CLAMP (1.0 * y + 1.7710 * v, 0, 255);
+     clutv[i] = g_strdup_printf ("%02x%02x%02x", r, g, b);
+   }
+   clutv[i] = NULL;
+   sclut = g_strjoinv (",", clutv);
+   /* build codec private; only palette for now */
+   g_free (context->codec_priv);
+   context->codec_priv = (guint8 *) g_strdup_printf ("palette: %s", sclut);
+   /* include terminating 0 */
+   context->codec_priv_size = strlen ((gchar *) context->codec_priv) + 1;
+   g_free (sclut);
+   for (i = 0; i < 16; ++i) {
+     g_free (clutv[i]);
+   }
+ }
  /**
   * gst_matroska_mux_handle_sink_event:
   * @pad: Pad which received the event.
   * Returns: #TRUE on success.
   */
  static gboolean
- gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
-     GstEvent * event)
+ gst_matroska_mux_handle_sink_event (GstCollectPads2 * pads,
+     GstCollectData2 * data, GstEvent * event, gpointer user_data)
  {
--  GstMatroskaTrackContext *context;
    GstMatroskaPad *collect_pad;
-   GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
++  GstMatroskaTrackContext *context;
+   GstMatroskaMux *mux;
+   GstPad *pad;
    GstTagList *list;
-   gboolean ret = TRUE;
++  gboolean ret = FALSE;
+   mux = GST_MATROSKA_MUX (user_data);
+   collect_pad = (GstMatroskaPad *) data;
+   pad = data->pad;
+   context = collect_pad->track;
+   g_assert (context);
  
    switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_CAPS:{
 +      GstCaps *caps;
 +
 +      collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
 +      gst_event_parse_caps (event, &caps);
 +
 +      ret = collect_pad->capsfunc (pad, caps);
 +      gst_event_unref (event);
 +      event = NULL;
 +      break;
 +    }
      case GST_EVENT_TAG:{
        gchar *lang = NULL;
  
        event = NULL;
        break;
      }
 -    case GST_EVENT_NEWSEGMENT:{
 -      GstFormat format;
 +    case GST_EVENT_SEGMENT:{
 +      const GstSegment *segment;
  
 -      gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
 -          NULL);
 -      if (format != GST_FORMAT_TIME) {
 +      gst_event_parse_segment (event, &segment);
 +      if (segment->format != GST_FORMAT_TIME) {
-         ret = FALSE;
          gst_event_unref (event);
          event = NULL;
        }
        break;
    }
  
-   /* now GstCollectPads can take care of the rest, e.g. EOS */
-   if (event)
-     ret = mux->collect_event (pad, parent, event);
+   /* now GstCollectPads2 can take care of the rest, e.g. EOS */
 -  if (event)
 -    return FALSE;
 -  else
 -    return TRUE;
 +  return ret;
  }
  
+ static void
+ gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
+     const char *id)
+ {
+   g_assert (context && id);
+   if (context->codec_id)
+     g_free (context->codec_id);
+   context->codec_id = g_strdup (id);
+ }
  
  /**
   * gst_matroska_mux_video_pad_setcaps:
@@@ -867,17 -966,13 +940,18 @@@ skip_details
    /* extract codec_data, may turn out needed */
    value = gst_structure_get_value (structure, "codec_data");
    if (value)
 -    codec_buf = gst_value_get_buffer (value);
 +    codec_buf = (GstBuffer *) gst_value_get_buffer (value);
  
    /* find type */
 -  if (!strcmp (mimetype, "video/x-raw-yuv")) {
 +  if (!strcmp (mimetype, "video/x-raw")) {
 +    const gchar *fstr;
-     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
+     gst_matroska_mux_set_codec_id (context,
+         GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
 -    gst_structure_get_fourcc (structure, "format", &videocontext->fourcc);
 +    fstr = gst_structure_get_string (structure, "format");
 +    if (fstr && strlen (fstr) == 4)
 +      videocontext->fourcc = GST_STR_FOURCC (fstr);
 +  } else if (!strcmp (mimetype, "image/jpeg")) {
-     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
++    gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
    } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
        ||!strcmp (mimetype, "video/x-huffyuv")
        || !strcmp (mimetype, "video/x-divx")
  
      /* process codec private/initialization data, if any */
      if (codec_buf) {
 -      size += GST_BUFFER_SIZE (codec_buf);
 +      size += gst_buffer_get_size (codec_buf);
        bih = g_realloc (bih, size);
        GST_WRITE_UINT32_LE (&bih->size, size);
 -      memcpy ((guint8 *) bih + sizeof (gst_riff_strf_vids),
 -          GST_BUFFER_DATA (codec_buf), GST_BUFFER_SIZE (codec_buf));
 +      gst_buffer_extract (codec_buf, 0,
 +          (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
      }
  
-     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
+     gst_matroska_mux_set_codec_id (context,
+         GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
      context->codec_priv = (gpointer) bih;
      context->codec_priv_size = size;
    } else if (!strcmp (mimetype, "video/x-h264")) {
@@@ -1607,36 -1725,32 +1693,37 @@@ gst_matroska_mux_audio_pad_setcaps (Gst
        goto refuse_caps;
      }
  
 -    /* FIXME: where is this spec'ed out? (tpm) */
 -    if ((width == 8 && signedness) || (width >= 16 && !signedness)) {
 -      GST_DEBUG_OBJECT (mux, "8-bit PCM must be unsigned, 16-bit PCM signed");
 -      goto refuse_caps;
 -    }
 -
 -    audiocontext->bitdepth = depth;
 -    if (endianness == G_BIG_ENDIAN)
 -      gst_matroska_mux_set_codec_id (context,
 -          GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
 -    else
 -      gst_matroska_mux_set_codec_id (context,
 -          GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
 -
 -  } else if (!strcmp (mimetype, "audio/x-raw-float")) {
 -    gint width;
 +    switch (GST_AUDIO_INFO_FORMAT (&info)) {
 +      case GST_AUDIO_FORMAT_U8:
 +      case GST_AUDIO_FORMAT_S16BE:
 +      case GST_AUDIO_FORMAT_S16LE:
 +      case GST_AUDIO_FORMAT_S24BE:
 +      case GST_AUDIO_FORMAT_S24LE:
 +      case GST_AUDIO_FORMAT_S32BE:
 +      case GST_AUDIO_FORMAT_S32LE:
 +        if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
 +          GST_DEBUG_OBJECT (mux, "width must be same as depth!");
 +          goto refuse_caps;
 +        }
 +        if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
-           context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
++          gst_matroska_mux_set_codec_id (context,
++              GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
 +        else
-           context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
++          gst_matroska_mux_set_codec_id (context,
++              GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
 +        break;
 +      case GST_AUDIO_FORMAT_F32LE:
 +      case GST_AUDIO_FORMAT_F64LE:
-         context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
++        gst_matroska_mux_set_codec_id (context,
++            GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
 +        break;
  
 -    if (!gst_structure_get_int (structure, "width", &width)) {
 -      GST_DEBUG_OBJECT (mux, "broken caps, width field missing");
 -      goto refuse_caps;
 +      default:
 +        GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
 +        goto refuse_caps;
      }
  
 -    audiocontext->bitdepth = width;
 -    gst_matroska_mux_set_codec_id (context,
 -        GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
 -
 +    audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
    } else if (!strcmp (mimetype, "audio/x-vorbis")) {
      const GValue *streamheader;
  
  
      /* process codec private/initialization data, if any */
      if (buf) {
 -      memcpy ((guint8 *) codec_priv + WAVEFORMATEX_SIZE,
 -          GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
 +      gst_buffer_extract (buf, 0,
 +          (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
      }
  
-     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
+     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
      context->codec_priv = (gpointer) codec_priv;
      context->codec_priv_size = codec_priv_size;
    }
@@@ -1860,6 -1976,10 +1949,10 @@@ gst_matroska_mux_subtitle_pad_setcaps (
    GstMatroskaPad *collect_pad;
    const gchar *mimetype;
    GstStructure *structure;
 -  const GstBuffer *buf = NULL;
+   const GValue *value = NULL;
++  GstBuffer *buf = NULL;
+   gchar *id = NULL;
+   gboolean ret = TRUE;
  
    mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
  
      if (!kate_streamheader_to_codecdata (streamheader, context)) {
        GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
            ("kate stream headers missing or malformed"));
-       return FALSE;
-     }
-     return TRUE;
+       ret = FALSE;
+       goto exit;
+     }
+   } else if (!strcmp (mimetype, "text/plain")) {
+     gst_matroska_mux_set_codec_id (context,
+         GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
+   } else if (!strcmp (mimetype, "application/x-ssa")) {
+     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
+   } else if (!strcmp (mimetype, "application/x-ass")) {
+     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
+   } else if (!strcmp (mimetype, "application/x-usf")) {
+     gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
+   } else if (!strcmp (mimetype, "video/x-dvd-subpicture")) {
+     gst_matroska_mux_set_codec_id (context,
+         GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
+   } else {
+     id = NULL;
+     ret = FALSE;
+     goto exit;
    }
  
-   return FALSE;
+   /* maybe some private data, e.g. vobsub */
+   value = gst_structure_get_value (structure, "codec_data");
+   if (value)
+     buf = gst_value_get_buffer (value);
+   if (buf != NULL) {
 -    guint8 *priv_data = NULL;
 -    guint priv_data_size = 0;
++    guint8 *priv_data = NULL, *priv_buffer_data;
++    gsize priv_data_size = 0;
 -    priv_data_size = GST_BUFFER_SIZE (buf);
++    priv_buffer_data =
++        gst_buffer_map (buf, &priv_data_size, NULL, GST_MAP_READ);
+     if (priv_data_size > SUBTITLE_MAX_CODEC_PRIVATE) {
+       GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
+           " exceeded maximum (%d); discarding", pad,
+           SUBTITLE_MAX_CODEC_PRIVATE);
++      gst_buffer_unmap (buf, priv_data, priv_data_size);
+       return TRUE;
+     }
+     if (context->codec_priv != NULL)
+       g_free (context->codec_priv);
+     priv_data = g_malloc0 (priv_data_size);
 -    memcpy (priv_data, GST_BUFFER_DATA (buf), priv_data_size);
++    memcpy (priv_data, priv_buffer_data, priv_data_size);
+     context->codec_priv = priv_data;
+     context->codec_priv_size = priv_data_size;
++    gst_buffer_unmap (buf, priv_buffer_data, priv_data_size);
+   }
+   GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %u",
+       GST_STR_NULL (context->codec_id), context->codec_priv_size);
+ exit:
+   /* free default if modified */
+   if (id)
+     g_free (id);
+   return ret;
  }
  
  
@@@ -1925,20 -2096,22 +2072,22 @@@ gst_matroska_mux_request_new_pad (GstEl
    GstMatroskamuxPad *newpad;
    gchar *name = NULL;
    const gchar *pad_name = NULL;
 -  GstPadSetCapsFunction setcapsfunc = NULL;
 +  GstMatroskaCapsFunc capsfunc = NULL;
    GstMatroskaTrackContext *context = NULL;
    gint pad_id;
+   gboolean locked = TRUE;
+   gchar *id = NULL;
  
 -  if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
 +  if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
      /* don't mix named and unnamed pads, if the pad already exists we fail when
       * trying to add it */
 -    if (req_name != NULL && sscanf (req_name, "audio_%d", &pad_id) == 1) {
 +    if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
        pad_name = req_name;
      } else {
 -      name = g_strdup_printf ("audio_%d", mux->num_a_streams++);
 +      name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
        pad_name = name;
      }
 -    setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
 +    capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
      context = (GstMatroskaTrackContext *)
          g_new0 (GstMatroskaTrackAudioContext, 1);
      context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
  
    collect_pad->track = context;
    gst_matroska_pad_reset (collect_pad, FALSE);
-   /* FIXME: hacked way to override/extend the event function of
-    * GstCollectPads; because it sets its own event function giving the
-    * element no access to events.
-    * TODO GstCollectPads should really give its 'users' a clean chance to
-    * properly handle events that are not meant for collectpads itself.
-    * Perhaps a callback or so, though rejected (?) in #340060.
-    * This would allow (clean) transcoding of info from demuxer/streams
-    * to another muxer */
-   mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
-   gst_pad_set_event_function (GST_PAD (newpad),
-       GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event));
+   collect_pad->track->codec_id = id;
  
 -  gst_pad_set_setcaps_function (GST_PAD (newpad), setcapsfunc);
 +  collect_pad->capsfunc = capsfunc;
    gst_pad_set_active (GST_PAD (newpad), TRUE);
    if (!gst_element_add_pad (element, GST_PAD (newpad)))
      goto pad_add_failed;
@@@ -2988,53 -3133,53 +3116,53 @@@ gst_matroska_mux_handle_buffer (GstColl
      mux->state = GST_MATROSKA_MUX_STATE_DATA;
    }
  
-   do {
-     /* which stream to write from? */
-     best = gst_matroska_mux_best_pad (mux, &popped);
+   /* provided with stream to write from */
+   best = (GstMatroskaPad *) data;
  
-     /* if there is no best pad, we have reached EOS */
-     if (best == NULL) {
-       /* buffer popped, but none returned means it was clipped */
-       if (popped)
-         break;
-       GST_DEBUG_OBJECT (mux, "No best pad finishing...");
-       if (!mux->streamable) {
-         gst_matroska_mux_finish (mux);
-       } else {
-         GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
-       }
-       gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
-       ret = GST_FLOW_EOS;
-       break;
+   /* if there is no best pad, we have reached EOS */
+   if (best == NULL) {
+     GST_DEBUG_OBJECT (mux, "No best pad finishing...");
+     if (!mux->streamable) {
+       gst_matroska_mux_finish (mux);
+     } else {
+       GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
      }
-     GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
-         GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
-         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
-         GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
+     gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
 -    ret = GST_FLOW_UNEXPECTED;
++    ret = GST_FLOW_EOS;
+     goto exit;
+   }
  
-     /* make note of first and last encountered timestamps, so we can calculate
-      * the actual duration later when we send an updated header on eos */
-     if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
-       GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
-       GstClockTime end_ts = start_ts;
+   /* if we have a best stream, should also have a buffer */
+   g_assert (buf);
  
-       if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
-         end_ts += GST_BUFFER_DURATION (best->buffer);
-       else if (best->track->default_duration)
-         end_ts += best->track->default_duration;
+   GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
+       GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
+       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  
-       if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
-         best->end_ts = end_ts;
+   /* make note of first and last encountered timestamps, so we can calculate
+    * the actual duration later when we send an updated header on eos */
+   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+     GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
+     GstClockTime end_ts = start_ts;
  
-       if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
-               start_ts < best->start_ts))
-         best->start_ts = start_ts;
-     }
+     if (GST_BUFFER_DURATION_IS_VALID (buf))
+       end_ts += GST_BUFFER_DURATION (buf);
+     else if (best->track->default_duration)
+       end_ts += best->track->default_duration;
+     if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
+       best->end_ts = end_ts;
+     if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
+             start_ts < best->start_ts))
+       best->start_ts = start_ts;
+   }
  
-     /* write one buffer */
-     ret = gst_matroska_mux_write_data (mux, best);
-   } while (ret == GST_FLOW_OK && !popped);
+   /* write one buffer */
+   ret = gst_matroska_mux_write_data (mux, best, buf);
  
+ exit:
    return ret;
  }
  
@@@ -58,12 -56,9 +58,10 @@@ typedef gboolean (*GstMatroskaCapsFunc
  /* all information needed for one matroska stream */
  typedef struct
  {
-   GstCollectData collect;       /* we extend the CollectData */
+   GstCollectData2 collect;       /* we extend the CollectData */
 +  GstMatroskaCapsFunc capsfunc;
    GstMatroskaTrackContext *track;
  
-   GstBuffer *buffer;            /* the queued buffer for this pad */
    guint64 duration;
    GstClockTime start_ts;
    GstClockTime end_ts;    /* last timestamp + (if available) duration */
@@@ -999,7 -982,22 +999,22 @@@ gst_matroska_read_common_parse_index_cu
  
    DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
  
 -  if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
+   /* (e.g.) lavf typically creates entries without a block number,
+    * which is bogus and leads to contradictory information */
+   if (common->index->len) {
+     GstMatroskaIndex *last_idx;
+     last_idx = &g_array_index (common->index, GstMatroskaIndex,
+         common->index->len - 1);
+     if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
+         last_idx->track == idx.track && idx.time > last_idx->time) {
+       GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
+           "but has different time than previous entry; discarding");
+       idx.track = 0;
+     }
+   }
 +  if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
        && idx.pos != (guint64) - 1 && idx.track > 0) {
      g_array_append_val (common->index, idx);
      (*nentries)++;
@@@ -655,16 -656,20 +655,21 @@@ write_error
      return GST_FLOW_ERROR;
    }
  stdio_write_error:
-   {
-     GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
-         ("Error while writing to file."), (NULL));
-     gst_buffer_unmap (buffer, data, size);
-     return GST_FLOW_ERROR;
+   switch (errno) {
+     case ENOSPC:
+       GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT,
+           ("Error while writing to file."), ("%s", g_strerror (errno)));
+       break;
+     default:
+       GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
+           ("Error while writing to file."), ("%s", g_strerror (errno)));
    }
++  gst_buffer_unmap (buffer, data, size);
+   return GST_FLOW_ERROR;
  }
  
 -static GstBufferListItem
 -buffer_list_calc_size (GstBuffer ** buf, guint group, guint idx, gpointer data)
 +static gboolean
 +buffer_list_calc_size (GstBuffer ** buf, guint idx, gpointer data)
  {
    guint *p_size = data;
    guint buf_size;
@@@ -194,11 -226,10 +194,11 @@@ gst_multipart_mux_request_new_pad (GstE
      GstMultipartPadData *multipartpad;
  
      multipartpad = (GstMultipartPadData *)
-         gst_collect_pads_add_pad (multipart_mux->collect, newpad,
-         sizeof (GstMultipartPadData), NULL);
+         gst_collect_pads2_add_pad (multipart_mux->collect, newpad,
+         sizeof (GstMultipartPadData));
  
      /* save a pointer to our data in the pad */
 +    multipartpad->pad = newpad;
      gst_pad_set_element_private (newpad, multipartpad);
      multipart_mux->numpads++;
    }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  
  #include <gst/rtp/gstrtpbuffer.h>
  #include <gst/rtp/gstrtcpbuffer.h>
 -#include <gst/netbuffer/gstnetbuffer.h>
  
+ #include <gst/glib-compat-private.h>
  #include "gstrtpbin-marshal.h"
  #include "rtpsession.h"
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -72,21 -76,32 +77,34 @@@ static gboolean gst_wavparse_send_even
  static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
      GstStateChange transition);
  
 -static const GstQueryType *gst_wavparse_get_query_types (GstPad * pad);
 -static gboolean gst_wavparse_pad_query (GstPad * pad, GstQuery * query);
 -static gboolean gst_wavparse_pad_convert (GstPad * pad,
 -    GstFormat src_format,
 +static gboolean gst_wavparse_pad_query (GstPad * pad, GstObject * parent,
 +    GstQuery * query);
 +static gboolean gst_wavparse_pad_convert (GstPad * pad, GstFormat src_format,
      gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
  
 -static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
 -static gboolean gst_wavparse_sink_event (GstPad * pad, GstEvent * event);
 +static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstObject * parent,
 +    GstBuffer * buf);
 +static gboolean gst_wavparse_sink_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
  static void gst_wavparse_loop (GstPad * pad);
 -static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event);
 +static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstObject * parent,
 +    GstEvent * event);
  
+ static void gst_wavparse_set_property (GObject * object, guint prop_id,
+     const GValue * value, GParamSpec * pspec);
+ static void gst_wavparse_get_property (GObject * object, guint prop_id,
+     GValue * value, GParamSpec * pspec);
+ #define DEFAULT_IGNORE_LENGTH FALSE
+ enum
+ {
+   PROP_0,
+   PROP_IGNORE_LENGTH,
+ };
  static GstStaticPadTemplate sink_template_factory =
 -GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
 +GST_STATIC_PAD_TEMPLATE ("sink",
      GST_PAD_SINK,
      GST_PAD_ALWAYS,
      GST_STATIC_CAPS ("audio/x-wav")
@@@ -113,21 -147,29 +131,42 @@@ gst_wavparse_class_init (GstWavParseCla
  
    object_class->dispose = gst_wavparse_dispose;
  
+   object_class->set_property = gst_wavparse_set_property;
+   object_class->get_property = gst_wavparse_get_property;
+   /**
+    * GstWavParse:ignore-length
+    * 
+    * This selects whether the length found in a data chunk
+    * should be ignored. This may be useful for streamed audio
+    * where the length is unknown until the end of streaming,
+    * and various software/hardware just puts some random value
+    * in there and hopes it doesn't break too much.
+    *
+    * Since: 0.10.36
+    */
+   g_object_class_install_property (object_class, PROP_IGNORE_LENGTH,
+       g_param_spec_boolean ("ignore-length",
+           "Ignore length",
+           "Ignore length from the Wave header",
+           DEFAULT_IGNORE_LENGTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+       );
    gstelement_class->change_state = gst_wavparse_change_state;
    gstelement_class->send_event = gst_wavparse_send_event;
 +
 +  /* register pads */
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&sink_template_factory));
 +
 +  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
 +      GST_PAD_ALWAYS, gst_riff_create_audio_template_caps ());
 +  gst_element_class_add_pad_template (gstelement_class, src_template);
 +
 +  gst_element_class_set_details_simple (gstelement_class, "WAV audio demuxer",
 +      "Codec/Demuxer/Audio",
 +      "Parse a .wav file into raw audio",
 +      "Erik Walthinsen <omega@cse.ogi.edu>");
  }
  
  static void
@@@ -209,40 -277,10 +248,9 @@@ gst_wavparse_init (GstWavParse * wavpar
        GST_DEBUG_FUNCPTR (gst_wavparse_pad_query));
    gst_pad_set_event_function (wavparse->srcpad,
        GST_DEBUG_FUNCPTR (gst_wavparse_srcpad_event));
 -
 -  GST_DEBUG_OBJECT (wavparse, "srcpad created");
 +  gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
  }
  
- /* Compute (value * nom) % denom, avoiding overflow.  This can be used
-  * to perform ceiling or rounding division together with
-  * gst_util_uint64_scale[_int]. */
- #define uint64_scale_modulo(val, nom, denom) \
-   ((val % denom) * (nom % denom) % denom)
- /* Like gst_util_uint64_scale, but performs ceiling division. */
- static guint64
- uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
- {
-   guint64 result = gst_util_uint64_scale_int (val, num, denom);
-   if (uint64_scale_modulo (val, num, denom) == 0)
-     return result;
-   else
-     return result + 1;
- }
- /* Like gst_util_uint64_scale, but performs ceiling division. */
- static guint64
- uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
- {
-   guint64 result = gst_util_uint64_scale (val, num, denom);
-   if (uint64_scale_modulo (val, num, denom) == 0)
-     return result;
-   else
-     return result + 1;
- }
  /* FIXME: why is that not in use? */
  #if 0
  static void
@@@ -1003,12 -1059,11 +1011,12 @@@ gst_wavparse_peek_chunk_info (GstWavPar
    if (gst_adapter_available (wav->adapter) < 8)
      return FALSE;
  
 -  data = gst_adapter_peek (wav->adapter, 8);
 +  data = gst_adapter_map (wav->adapter, 8);
    *tag = GST_READ_UINT32_LE (data);
    *size = GST_READ_UINT32_LE (data + 4);
 +  gst_adapter_unmap (wav->adapter);
  
-   GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
+   GST_DEBUG ("Next chunk size is %u bytes, type %" GST_FOURCC_FORMAT, *size,
        GST_FOURCC_ARGS (*tag));
  
    return TRUE;
@@@ -1527,11 -1575,13 +1541,13 @@@ gst_wavparse_stream_headers (GstWavPars
  
    if (gst_wavparse_calculate_duration (wav)) {
      gst_segment_init (&wav->segment, GST_FORMAT_TIME);
-     wav->segment.duration = wav->duration;
+     if (!wav->ignore_length)
 -      gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, wav->duration);
++      wav->segment.duration = wav->duration;
    } else {
      /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
      gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
-     wav->segment.duration = wav->datasize;
+     if (!wav->ignore_length)
 -      gst_segment_set_duration (&wav->segment, GST_FORMAT_BYTES, wav->datasize);
++      wav->segment.duration = wav->datasize;
    }
  
    /* now we have all the info to perform a pending seek if any, if no
Simple merge
Simple merge
  #include <unistd.h>
  
  #include "gst/video/video.h"
 +#include "gst/video/gstvideometa.h"
 +#include "gst/video/gstvideopool.h"
  
  #include <gstv4l2bufferpool.h>
 +
  #include "gstv4l2src.h"
 -#ifdef HAVE_EXPERIMENTAL
  #include "gstv4l2sink.h"
 -#endif
  #include "v4l2_calls.h"
  #include "gst/gst-i18n-plugin.h"
+ #include <gst/glib-compat-private.h>
  
  /* videodev2.h is not versioned and we can't easily check for the presence
   * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
Simple merge
Simple merge
Simple merge
@@@ -296,8 -262,11 +297,11 @@@ elements_sunaudio_LDADD = 
        $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_MAJORMINOR@ \
        $(LDADD)
  
 -elements_videocrop_LDADD = $(GST_BASE_LIBS) $(LDADD)
 -elements_videocrop_CFLAGS = $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
+ elements_udpsrc_CFLAGS = $(AM_CFLAGS) $(GIO_CFLAGS)
+ elements_udpsrc_LDADD = $(LDADD) $(GIO_LIBS)
 +elements_videocrop_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(LDADD)
 +elements_videocrop_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
  
  elements_videofilter_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
  elements_videofilter_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(LDADD)
Simple merge
@@@ -79,6 -81,35 +81,37 @@@ setup_rgvolume (void
  }
  
  static void
 -  ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0);
+ send_newsegment_and_empty_buffer (void)
+ {
+   GstBuffer *buf;
+   GstEvent *ev;
++  GstSegment segment;
+   fail_unless (g_list_length (events) == 0);
++  gst_segment_init (&segment, GST_FORMAT_TIME);
++  ev = gst_event_new_segment (&segment);
+   fail_unless (gst_pad_push_event (mysrcpad, ev),
+       "Pushing newsegment event failed");
+   buf = test_buffer_new (0.0);
+   GST_BUFFER_SIZE (buf) = 0;
+   GST_BUFFER_DURATION (buf) = 0;
+   GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf);
+   fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
+   fail_unless (g_list_length (events) == 1);
+   fail_unless (events->data == ev);
+   gst_mini_object_unref ((GstMiniObject *) events->data);
+   events = g_list_remove (events, ev);
+   fail_unless (g_list_length (buffers) == 1);
+   fail_unless (buffers->data == buf);
+   gst_mini_object_unref ((GstMiniObject *) buffers->data);
+   buffers = g_list_remove (buffers, buf);
+ }
+ static void
  cleanup_rgvolume (GstElement * element)
  {
    GST_DEBUG ("cleanup_rgvolume");
@@@ -292,7 -319,9 +325,9 @@@ GST_START_TEST (test_events
  
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463,
        GST_TAG_ALBUM_GAIN, -1.54, GST_TAG_ALBUM_PEAK, 0.693415,
@@@ -340,7 -369,9 +375,9 @@@ GST_START_TEST (test_simple
        "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
        GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL);
@@@ -380,7 -411,9 +417,9 @@@ GST_START_TEST (test_fallback_gain
        "pre-amp", -6.00, "fallback-gain", -3.00, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0,
        GST_TAG_ALBUM_GAIN, -0.5, GST_TAG_ALBUM_PEAK, 1.0, NULL);
@@@ -423,7 -456,9 +462,9 @@@ GST_START_TEST (test_fallback_track
        "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL);
    fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
@@@ -448,7 -483,9 +489,9 @@@ GST_START_TEST (test_fallback_album
        "pre-amp", -6.00, "fallback-gain", +1.23, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL);
    fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
@@@ -470,7 -507,9 +513,9 @@@ GST_START_TEST (test_headroom
        "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL);
    fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL);
@@@ -512,7 -551,9 +557,9 @@@ GST_START_TEST (test_reference_level
        "headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
    set_playing_state (element);
  
 -  tag_list = gst_tag_list_new ();
+   send_newsegment_and_empty_buffer ();
 +  tag_list = gst_tag_list_new_empty ();
    gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2,
        GST_TAG_REFERENCE_LEVEL, 83., NULL);
Simple merge
Simple merge
Simple merge
Simple merge