diff options
| author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-02-27 20:28:27 +0100 | 
|---|---|---|
| committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-02-27 20:28:27 +0100 | 
| commit | d189fe7f265ae6c606c1fb803c8349b36016bc87 (patch) | |
| tree | 3a74c6f9a9309872ce2dde05796219132bbffdf2 | |
| parent | 5d9c947f923dc2f06020c2aaa0898855692dc2a1 (diff) | |
| parent | b50452fc37a74cab50a44948efa944edd077af92 (diff) | |
Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-good
| -rw-r--r-- | gst/avi/gstavidemux.c | 13 | ||||
| -rw-r--r-- | gst/matroska/matroska-demux.c | 4 | ||||
| -rw-r--r-- | gst/replaygain/gstrgvolume.c | 2 | ||||
| -rw-r--r-- | gst/rtp/gstrtpvrawdepay.c | 10 | ||||
| -rw-r--r-- | gst/rtp/gstrtpvrawpay.c | 39 | ||||
| -rw-r--r-- | gst/rtsp/gstrtspsrc.c | 29 | ||||
| -rw-r--r-- | gst/rtsp/gstrtspsrc.h | 1 | ||||
| -rw-r--r-- | gst/udp/gstudpnetutils.c | 12 | ||||
| -rw-r--r-- | gst/wavparse/gstwavparse.c | 286 | 
9 files changed, 350 insertions, 46 deletions
| diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 017a7f58..adea05fd 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -619,9 +619,13 @@ gst_avi_demux_handle_src_event (GstPad * pad, GstEvent * event)    switch (GST_EVENT_TYPE (event)) {      case GST_EVENT_SEEK: -      /* handle seeking */ -      res = gst_avi_demux_handle_seek (avi, pad, event); -      gst_event_unref (event); +      /* handle seeking only in pull mode */ +      if (!avi->streaming) { +        res = gst_avi_demux_handle_seek (avi, pad, event); +        gst_event_unref (event); +      } else { +        res = gst_pad_event_default (pad, event); +      }        break;      case GST_EVENT_QOS:      case GST_EVENT_NAVIGATION: @@ -4246,6 +4250,7 @@ gst_avi_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)    if (active) {      avi->segment_running = TRUE; +    avi->streaming = FALSE;      return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_avi_demux_loop,          sinkpad);    } else { @@ -4257,9 +4262,11 @@ gst_avi_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)  static gboolean  gst_avi_demux_activate_push (GstPad * pad, gboolean active)  { +  GstAviDemux *avi = GST_AVI_DEMUX (GST_OBJECT_PARENT (pad));    if (active) {      GST_DEBUG ("avi: activating push/chain function"); +    avi->streaming = TRUE;    } else {      GST_DEBUG ("avi: deactivating push/chain function");    } diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 118886fc..50011cff 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -5135,9 +5135,6 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *        guint rformat;        guint subformat; -      gst_util_dump_mem (data, size); -      gst_util_dump_mem (data + 0x1a, size - 0x1a); -        subformat = GST_READ_UINT32_BE (data + 0x1a);        rformat = GST_READ_UINT32_BE (data + 0x1e); @@ -5503,7 +5500,6 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *        guint extra_data_size;        GST_ERROR ("real audio raversion:%d", raversion); -      gst_util_dump_mem (data, size);        if (raversion == 8) {          /* COOK */          flavor = GST_READ_UINT16_BE (data + 22); diff --git a/gst/replaygain/gstrgvolume.c b/gst/replaygain/gstrgvolume.c index 41fe441d..d569b4bb 100644 --- a/gst/replaygain/gstrgvolume.c +++ b/gst/replaygain/gstrgvolume.c @@ -92,7 +92,7 @@ enum  #define PEAK_FORMAT ".06f"  #define VALID_GAIN(x) ((x) > -60.00 && (x) < 60.00) -#define VALID_PEAK(x) ((x) > 0.) +#define VALID_PEAK(x) ((x) > 0. && (x) < 1.)  /* Same template caps as GstVolume, for I don't like having just ANY caps. */ diff --git a/gst/rtp/gstrtpvrawdepay.c b/gst/rtp/gstrtpvrawdepay.c index 35e68a3e..3f599f5d 100644 --- a/gst/rtp/gstrtpvrawdepay.c +++ b/gst/rtp/gstrtpvrawdepay.c @@ -139,6 +139,11 @@ gst_rtp_vraw_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)      goto no_height;    height = atoi (str); +  /* optional interlace value but we don't handle interlaced +   * formats yet */ +  if ((str = gst_structure_get_string (structure, "interlace"))) +    goto interlaced; +    if (!(str = gst_structure_get_string (structure, "sampling")))      goto no_sampling; @@ -248,6 +253,11 @@ no_height:      GST_ERROR_OBJECT (depayload, "no height specified");      return FALSE;    } +interlaced: +  { +    GST_ERROR_OBJECT (depayload, "interlaced formats not supported yet"); +    return FALSE; +  }  no_sampling:    {      GST_ERROR_OBJECT (depayload, "no sampling specified"); diff --git a/gst/rtp/gstrtpvrawpay.c b/gst/rtp/gstrtpvrawpay.c index 19c14c2b..0f0ef7e8 100644 --- a/gst/rtp/gstrtpvrawpay.c +++ b/gst/rtp/gstrtpvrawpay.c @@ -211,6 +211,7 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)    GstVideoFormat sampling;    const gchar *depthstr, *samplingstr, *colorimetrystr;    gchar *wstr, *hstr; +  gboolean interlaced;    rtpvrawpay = GST_RTP_VRAW_PAY (payload); @@ -229,6 +230,13 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)    if (!res)      goto missing_dimension; +  /* fail on interlaced video for now */ +  if (!gst_structure_get_boolean (s, "interlaced", &interlaced)) +    interlaced = FALSE; + +  if (interlaced) +    goto interlaced; +    yp = up = vp = 0;    xinc = yinc = 1; @@ -358,6 +366,11 @@ unknown_fourcc:      GST_ERROR_OBJECT (payload, "invalid or missing fourcc");      return FALSE;    } +interlaced: +  { +    GST_ERROR_OBJECT (payload, "interlaced video not supported yet"); +    return FALSE; +  }  missing_dimension:    {      GST_ERROR_OBJECT (payload, "missing width or height property"); @@ -409,7 +422,7 @@ gst_rtp_vraw_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer)      GstBuffer *out;      guint8 *outdata, *headers;      gboolean next_line; -    guint length, cont, pixels; +    guint length, cont, pixels, fieldid;      /* get the max allowed payload length size, we try to fill the complete MTU */      left = gst_rtp_buffer_calc_payload_len (mtu, 0, 0); @@ -422,6 +435,24 @@ gst_rtp_vraw_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer)      GST_LOG_OBJECT (rtpvrawpay, "created buffer of size %u for MTU %u", left,          mtu); +    /* +     *   0                   1                   2                   3 +     *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +     *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +     *  |   Extended Sequence Number    |            Length             | +     *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +     *  |F|          Line No            |C|           Offset            | +     *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +     *  |            Length             |F|          Line No            | +     *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +     *  |C|           Offset            |                               . +     *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               . +     *  .                                                               . +     *  .                 Two (partial) lines of video data             . +     *  .                                                               . +     *  +---------------------------------------------------------------+ +     */ +      /* need 2 bytes for the extended sequence number */      *outdata++ = 0;      *outdata++ = 0; @@ -456,8 +487,12 @@ gst_rtp_vraw_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer)        /* write length */        *outdata++ = (length >> 8) & 0xff;        *outdata++ = length & 0xff; + +      /* always 0 for now */ +      fieldid = 0x00; +        /* write line no */ -      *outdata++ = (line >> 8) & 0x7f; +      *outdata++ = ((line >> 8) & 0x7f) | fieldid;        *outdata++ = line & 0xff;        if (next_line) { diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index b3e1df47..7c5ef8a6 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -146,6 +146,7 @@ enum  #define DEFAULT_LATENCY_MS       3000  #define DEFAULT_CONNECTION_SPEED 0  #define DEFAULT_NAT_METHOD       GST_RTSP_NAT_DUMMY +#define DEFAULT_DO_RTCP          TRUE  enum  { @@ -159,6 +160,7 @@ enum    PROP_LATENCY,    PROP_CONNECTION_SPEED,    PROP_NAT_METHOD, +  PROP_DO_RTCP,    PROP_LAST  }; @@ -335,6 +337,19 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)            GST_TYPE_RTSP_NAT_METHOD, DEFAULT_NAT_METHOD,            G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +  /** +   * GstRTSPSrc::do-rtcp +   * +   * Enable RTCP support. Some old server don't like RTCP and then this property +   * needs to be set to FALSE. +   * +   * Since: 0.10.15 +   */ +  g_object_class_install_property (gobject_class, PROP_DO_RTCP, +      g_param_spec_boolean ("do-rtcp", "Do RTCP", +          "Don't send RTCP packets", +          DEFAULT_DO_RTCP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +    gstelement_class->change_state = gst_rtspsrc_change_state;    gstbin_class->handle_message = gst_rtspsrc_handle_message; @@ -454,6 +469,9 @@ gst_rtspsrc_set_property (GObject * object, guint prop_id, const GValue * value,      case PROP_NAT_METHOD:        rtspsrc->nat_method = g_value_get_enum (value);        break; +    case PROP_DO_RTCP: +      rtspsrc->do_rtcp = g_value_get_boolean (value); +      break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);        break; @@ -502,6 +520,9 @@ gst_rtspsrc_get_property (GObject * object, guint prop_id, GValue * value,      case PROP_NAT_METHOD:        g_value_set_enum (value, rtspsrc->nat_method);        break; +    case PROP_DO_RTCP: +      g_value_set_boolean (value, rtspsrc->do_rtcp); +      break;      default:        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);        break; @@ -1942,8 +1963,8 @@ gst_rtspsrc_stream_configure_tcp (GstRTSPSrc * src, GstRTSPStream * stream,      }      gst_object_unref (template);    } -  /* setup RTCP transport back to the server */ -  if (src->session) { +  /* setup RTCP transport back to the server if we have to. */ +  if (src->session && src->do_rtcp) {      GstPad *pad;      template = gst_static_pad_template_get (&anysinktemplate); @@ -2162,7 +2183,7 @@ gst_rtspsrc_stream_configure_udp_sinks (GstRTSPSrc * src,    }    /* it's possible that the server does not want us to send RTCP in which case     * the port is -1 */ -  if (rtcp_port != -1 && src->session != NULL) { +  if (rtcp_port != -1 && src->session != NULL && src->do_rtcp) {      GST_DEBUG_OBJECT (src, "configure RTCP UDP sink for %s:%d", destination,          rtcp_port); @@ -3944,7 +3965,7 @@ gst_rtspsrc_setup_streams (GstRTSPSrc * src)      GST_DEBUG_OBJECT (src, "doing setup of stream %p with %s", stream,          stream->setup_url); -retry: +  retry:      /* create a string with all the transports */      res = gst_rtspsrc_create_transports_string (src, protocols, &transports);      if (res < 0) diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 95dd9869..40a368c6 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -186,6 +186,7 @@ struct _GstRTSPSrc {    guint             latency;    guint             connection_speed;    GstRTSPNatMethod  nat_method; +  gboolean          do_rtcp;    /* state */    GstRTSPState       state; diff --git a/gst/udp/gstudpnetutils.c b/gst/udp/gstudpnetutils.c index 07268509..5fa7593a 100644 --- a/gst/udp/gstudpnetutils.c +++ b/gst/udp/gstudpnetutils.c @@ -115,12 +115,17 @@ beach:  int  gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)  { +  socklen_t socklen; +  struct sockaddr_storage addr;    int ret = -1; - -#if 0    int l = (loop == FALSE) ? 0 : 1; -  switch (addr->ss_family) { +  socklen = sizeof (addr); +  if ((ret = getsockname (sockfd, (struct sockaddr *) &addr, &socklen)) < 0) { +    return ret; +  } + +  switch (addr.ss_family) {      case AF_INET:      {        if ((ret = @@ -155,7 +160,6 @@ gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)        errno = EAFNOSUPPORT;  #endif    } -#endif    return ret;  } diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c index 266c430f..c8e7c756 100644 --- a/gst/wavparse/gstwavparse.c +++ b/gst/wavparse/gstwavparse.c @@ -77,6 +77,7 @@ static gboolean gst_wavparse_pad_convert (GstPad * pad,      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 void gst_wavparse_loop (GstPad * pad);  static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event); @@ -193,6 +194,8 @@ gst_wavparse_init (GstWavParse * wavparse, GstWavParseClass * g_class)        GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_pull));    gst_pad_set_chain_function (wavparse->sinkpad,        GST_DEBUG_FUNCPTR (gst_wavparse_chain)); +  gst_pad_set_event_function (wavparse->sinkpad, +      GST_DEBUG_FUNCPTR (gst_wavparse_sink_event));    gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->sinkpad);    /* src, will be created later */ @@ -725,8 +728,35 @@ gst_wavparse_stream_init (GstWavParse * wav)    return GST_FLOW_OK;  } -/* This function is used to perform seeks on the element in - * pull mode. +static gboolean +gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos) +{ +  /* -1 always maps to -1 */ +  if (ts == -1) { +    *bytepos = -1; +    return TRUE; +  } + +  /* 0 always maps to 0 */ +  if (ts == 0) { +    *bytepos = 0; +    return TRUE; +  } + +  if (wav->bps > 0) { +    *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND); +    return TRUE; +  } else if (wav->fact) { +    guint64 bps = +        gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact); +    *bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND); +    return TRUE; +  } + +  return FALSE; +} + +/* This function is used to perform seeks on the element.   *   * It also works when event is NULL, in which case it will just   * start from the last configured segment. This technique is @@ -783,6 +813,48 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)      stop_type = GST_SEEK_TYPE_SET;    } +  /* in push mode, we must delegate to upstream */ +  if (wav->streaming) { +    gboolean res = FALSE; + +    /* if streaming not yet started; only prepare initial newsegment */ +    if (!event || wav->state != GST_WAVPARSE_DATA) { +      if (wav->start_segment) +        gst_event_unref (wav->start_segment); +      wav->start_segment = +          gst_event_new_new_segment (FALSE, wav->segment.rate, +          wav->segment.format, wav->segment.last_stop, wav->segment.duration, +          wav->segment.last_stop); +      res = TRUE; +    } else { +      /* convert seek positions to byte positions in data sections */ +      if (format == GST_FORMAT_TIME) { +        /* should not fail */ +        if (!gst_wavparse_time_to_bytepos (wav, cur, &cur)) +          goto no_position; +        if (!gst_wavparse_time_to_bytepos (wav, stop, &stop)) +          goto no_position; +      } +      /* mind sample boundary and header */ +      if (cur >= 0) { +        cur -= (cur % wav->bytes_per_sample); +        cur += wav->datastart; +      } +      if (stop >= 0) { +        stop -= (stop % wav->bytes_per_sample); +        stop += wav->datastart; +      } +      GST_DEBUG_OBJECT (wav, "Pushing BYTE seek rate %g, " +          "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, +          stop); +      /* BYTE seek event */ +      event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur, +          stop_type, stop); +      res = gst_pad_push_event (wav->sinkpad, event); +    } +    return res; +  } +    /* get flush flag */    flush = flags & GST_SEEK_FLAG_FLUSH; @@ -832,16 +904,8 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)      /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and       * we can just copy the last_stop. If not, we use the bps to convert TIME to       * bytes. */ -    if (wav->bps > 0) -      wav->offset = -          uint64_ceiling_scale (seeksegment.last_stop, (guint64) wav->bps, -          GST_SECOND); -    else if (wav->fact) { -      guint64 bps = -          gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact); -      wav->offset = -          uint64_ceiling_scale (seeksegment.last_stop, bps, GST_SECOND); -    } else +    if (!gst_wavparse_time_to_bytepos (wav, seeksegment.last_stop, +            (gint64 *) & wav->offset))        wav->offset = seeksegment.last_stop;      GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);      wav->offset -= (wav->offset % wav->bytes_per_sample); @@ -854,14 +918,7 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)    }    if (stop_type != GST_SEEK_TYPE_NONE) { -    if (wav->bps > 0) -      wav->end_offset = -          uint64_ceiling_scale (stop, (guint64) wav->bps, GST_SECOND); -    else if (wav->fact) { -      guint64 bps = -          gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact); -      wav->end_offset = uint64_ceiling_scale (stop, bps, GST_SECOND); -    } else +    if (!gst_wavparse_time_to_bytepos (wav, stop, (gint64 *) & wav->end_offset))        wav->end_offset = stop;      GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);      wav->end_offset -= (wav->end_offset % wav->bytes_per_sample); @@ -962,6 +1019,12 @@ no_format:      GST_DEBUG_OBJECT (wav, "unsupported format given, seek aborted.");      return FALSE;    } +no_position: +  { +    GST_DEBUG_OBJECT (wav, +        "Could not determine byte position for desired time"); +    return FALSE; +  }  }  /* @@ -1678,6 +1741,32 @@ iterate_adapter:    if (wav->streaming) {      guint avail = gst_adapter_available (wav->adapter); +    guint extra; + +    /* flush some bytes if evil upstream sends segment that starts +     * before data or does is not send sample aligned segment */ +    if (G_LIKELY (wav->offset >= wav->datastart)) { +      extra = (wav->offset - wav->datastart) % wav->bytes_per_sample; +    } else { +      extra = wav->datastart - wav->offset; +    } + +    if (G_UNLIKELY (extra)) { +      extra = wav->bytes_per_sample - extra; +      if (extra <= avail) { +        GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra); +        gst_adapter_flush (wav->adapter, extra); +        wav->offset += extra; +        wav->dataleft -= extra; +        goto iterate_adapter; +      } else { +        GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail); +        gst_adapter_clear (wav->adapter); +        wav->offset += avail; +        wav->dataleft -= avail; +        return GST_FLOW_OK; +      } +    }      if (avail < desired) {        GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail); @@ -1927,6 +2016,8 @@ gst_wavparse_chain (GstPad * pad, GstBuffer * buf)        /* fall-through */      case GST_WAVPARSE_DATA: +      if (buf && GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) +        wav->discont = TRUE;        if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)          goto done;        break; @@ -1937,6 +2028,132 @@ done:    return ret;  } +static GstFlowReturn +gst_wavparse_flush_data (GstWavParse * wav) +{ +  GstFlowReturn ret = GST_FLOW_OK; +  guint av; + +  if ((av = gst_adapter_available (wav->adapter)) > 0) { +    wav->dataleft = av; +    wav->end_offset = wav->offset + av; +    ret = gst_wavparse_stream_data (wav); +  } + +  return ret; +} + +static gboolean +gst_wavparse_sink_event (GstPad * pad, GstEvent * event) +{ +  GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad)); +  gboolean ret = TRUE; + +  GST_LOG_OBJECT (wav, "handling %s event", GST_EVENT_TYPE_NAME (event)); + +  switch (GST_EVENT_TYPE (event)) { +    case GST_EVENT_NEWSEGMENT: +    { +      GstFormat format; +      gdouble rate, arate; +      gint64 start, stop, time, offset = 0, end_offset = -1; +      gboolean update; +      GstSegment segment; + +      /* some debug output */ +      gst_segment_init (&segment, GST_FORMAT_UNDEFINED); +      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, +          &start, &stop, &time); +      gst_segment_set_newsegment_full (&segment, update, rate, arate, format, +          start, stop, time); +      GST_DEBUG_OBJECT (wav, +          "received format %d newsegment %" GST_SEGMENT_FORMAT, format, +          &segment); + +      if (wav->state != GST_WAVPARSE_DATA) { +        GST_DEBUG_OBJECT (wav, "still starting, eating event"); +        goto exit; +      } + +      /* now we are either committed to TIME or BYTE format, +       * and we only expect a BYTE segment, e.g. following a seek */ +      if (format == GST_FORMAT_BYTES) { +        if (start > 0) { +          offset = start; +          start -= wav->datastart; +          start = MAX (start, 0); +        } +        if (stop > 0) { +          end_offset = stop; +          stop -= wav->datastart; +          stop = MAX (stop, 0); +        } +        if (wav->segment.format == GST_FORMAT_TIME) { +          guint64 bps = wav->bps; + +          /* operating in format TIME, so we can convert */ +          if (!bps && wav->fact) +            bps = +                gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact); +          if (bps) { +            if (start >= 0) +              start = +                  uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps); +            if (stop >= 0) +              stop = +                  uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps); +          } +        } +      } else { +        GST_DEBUG_OBJECT (wav, "unsupported segment format, ignoring"); +        goto exit; +      } + +      /* accept upstream's notion of segment and distribute along */ +      gst_segment_set_newsegment_full (&wav->segment, update, rate, arate, +          wav->segment.format, start, stop, start); +      /* also store the newsegment event for the streaming thread */ +      if (wav->start_segment) +        gst_event_unref (wav->start_segment); +      wav->start_segment = +          gst_event_new_new_segment_full (update, rate, arate, +          wav->segment.format, start, stop, start); +      GST_DEBUG_OBJECT (wav, "Pushing newseg update %d, rate %g, " +          "applied rate %g, format %d, start %" G_GINT64_FORMAT ", " +          "stop %" G_GINT64_FORMAT, update, rate, arate, wav->segment.format, +          start, stop); + +      /* stream leftover data in current segment */ +      gst_wavparse_flush_data (wav); +      /* and set up streaming thread for next one */ +      wav->offset = offset; +      wav->end_offset = end_offset; +      if (wav->end_offset > 0) { +        wav->dataleft = wav->end_offset - wav->offset; +      } else { +        /* infinity; upstream will EOS when done */ +        wav->dataleft = G_MAXUINT64; +      } +    exit: +      gst_event_unref (event); +      break; +    } +    case GST_EVENT_EOS: +      /* stream leftover data in current segment */ +      gst_wavparse_flush_data (wav); +      /* fall-through */ +    case GST_EVENT_FLUSH_STOP: +      gst_adapter_clear (wav->adapter); +      wav->discont = TRUE; +      /* fall-through */ +    default: +      ret = gst_pad_event_default (wav->sinkpad, event); +      break; +  } + +  return ret; +} +  #if 0  /* convert and query stuff */  static const GstFormat * @@ -2089,6 +2306,8 @@ gst_wavparse_pad_query (GstPad * pad, GstQuery * query)      return FALSE;    } +  GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query)); +    switch (GST_QUERY_TYPE (query)) {      case GST_QUERY_POSITION:      { @@ -2152,20 +2371,31 @@ gst_wavparse_pad_query (GstPad * pad, GstQuery * query)      }      case GST_QUERY_SEEKING:{        GstFormat fmt; +      gboolean seekable = FALSE;        gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); -      if (fmt == GST_FORMAT_TIME) { -        gboolean seekable = TRUE; +      if (fmt == wav->segment.format) { +        res = TRUE; +        if (wav->streaming) { +          GstQuery *q; -        if ((wav->bps == 0) && !wav->fact) { -          seekable = FALSE; -        } else if (!gst_wavparse_calculate_duration (wav)) { -          seekable = FALSE; +          q = gst_query_new_seeking (GST_FORMAT_BYTES); +          if ((res = gst_pad_peer_query (wav->sinkpad, q))) { +            gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL); +            GST_LOG_OBJECT (wav, "upstream BYTE seekable %d", seekable); +          } +          gst_query_unref (q); +        } else { +          GST_LOG_OBJECT (wav, "looping => seekable"); +          seekable = TRUE; +          res = TRUE;          } -        gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, -            0, wav->duration); +      } else if (fmt == GST_FORMAT_TIME) {          res = TRUE;        } +      if (res) { +        gst_query_set_seeking (query, fmt, seekable, 0, wav->segment.duration); +      }        break;      }      default: | 
