diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 50a132f3f9..2889b89f49 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -637,6 +637,31 @@ packet_duration_flac (GstOggStream * pad, ogg_packet * packet) if (block_size_index >= 8) { return 256 << (block_size_index - 8); } + if (block_size_index == 6 || block_size_index == 7) { + guint len, bytes = (block_size_index - 6) + 1; + guint8 tmp; + + if (packet->bytes < 4 + 1 + bytes) + return -1; + tmp = packet->packet[4]; + /* utf-8 prefix */ + len = 0; + while (tmp & 0x80) { + len++; + tmp <<= 1; + } + if (len == 2) + return -1; + if (len == 0) + len++; + if (packet->bytes < 4 + len + bytes) + return -1; + if (bytes == 1) { + return packet->packet[4 + len] + 1; + } else { + return GST_READ_UINT16_BE (packet->packet + 4 + len) + 1; + } + } return -1; } @@ -1156,7 +1181,7 @@ static const GstOggMap mappers[] = { NULL }, { - "\177FLAC", 4, 36, + "\177FLAC", 5, 36, "audio/x-flac", setup_flac_mapper, granulepos_to_granule_default, diff --git a/ext/pango/gsttextoverlay.c b/ext/pango/gsttextoverlay.c index cb5f55946c..3e4a0ee7f1 100644 --- a/ext/pango/gsttextoverlay.c +++ b/ext/pango/gsttextoverlay.c @@ -2035,7 +2035,8 @@ gst_text_overlay_video_chain (GstPad * pad, GstBuffer * buffer) gint fps_num, fps_denom; s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0); - if (gst_structure_get_fraction (s, "framerate", &fps_num, &fps_denom)) { + if (gst_structure_get_fraction (s, "framerate", &fps_num, &fps_denom) && + fps_num && fps_denom) { GST_DEBUG_OBJECT (overlay, "estimating duration based on framerate"); stop = start + gst_util_uint64_scale_int (GST_SECOND, fps_denom, fps_num); } else { diff --git a/gst-libs/gst/rtp/gstbasertpaudiopayload.c b/gst-libs/gst/rtp/gstbasertpaudiopayload.c index 966d93d74b..1daa783d66 100644 --- a/gst-libs/gst/rtp/gstbasertpaudiopayload.c +++ b/gst-libs/gst/rtp/gstbasertpaudiopayload.c @@ -98,6 +98,7 @@ struct _GstBaseRTPAudioPayloadPrivate guint cached_mtu; guint cached_min_ptime; guint cached_max_ptime; + guint cached_ptime; guint cached_min_length; guint cached_max_length; }; @@ -516,6 +517,7 @@ gst_base_rtp_audio_payload_get_lengths (GstBaseRTPPayload * /* check cached values */ if (G_LIKELY (priv->cached_mtu == mtu + && priv->cached_ptime == basepayload->abidata.ABI.ptime && priv->cached_max_ptime == basepayload->max_ptime && priv->cached_min_ptime == basepayload->min_ptime)) { /* if nothing changed, return cached values */ @@ -546,8 +548,21 @@ gst_base_rtp_audio_payload_get_lengths (GstBaseRTPPayload * if (*min_payload_len > *max_payload_len) *min_payload_len = *max_payload_len; + /* If the ptime is specified in the caps, tried to adhere to it exactly */ + if (basepayload->abidata.ABI.ptime) { + guint ptime_in_bytes = priv->time_to_bytes (payload, + basepayload->abidata.ABI.ptime); + + /* clip to computed min and max lengths */ + ptime_in_bytes = MAX (*min_payload_len, ptime_in_bytes); + ptime_in_bytes = MIN (*max_payload_len, ptime_in_bytes); + + *min_payload_len = *max_payload_len = ptime_in_bytes; + } + /* cache values */ priv->cached_mtu = mtu; + priv->cached_ptime = basepayload->abidata.ABI.ptime; priv->cached_min_ptime = basepayload->min_ptime; priv->cached_max_ptime = basepayload->max_ptime; priv->cached_min_length = *min_payload_len; diff --git a/gst-libs/gst/rtp/gstbasertppayload.c b/gst-libs/gst/rtp/gstbasertppayload.c index e3b4d7f8ab..a6d8eb3ce4 100644 --- a/gst-libs/gst/rtp/gstbasertppayload.c +++ b/gst-libs/gst/rtp/gstbasertppayload.c @@ -46,6 +46,9 @@ struct _GstBaseRTPPayloadPrivate gboolean ssrc_random; guint16 next_seqnum; gboolean perfect_rtptime; + + gint64 prop_max_ptime; + gint64 caps_max_ptime; }; /* BaseRTPPayload signals and args */ @@ -281,6 +284,9 @@ gst_basertppayload_init (GstBaseRTPPayload * basertppayload, gpointer g_class) basertppayload->encoding_name = NULL; basertppayload->clock_rate = 0; + + basertppayload->priv->caps_max_ptime = DEFAULT_MAX_PTIME; + basertppayload->priv->prop_max_ptime = DEFAULT_MAX_PTIME; } static void @@ -469,6 +475,21 @@ copy_fixed (GQuark field_id, const GValue * value, GstStructure * dest) return TRUE; } +static void +update_max_ptime (GstBaseRTPPayload * basertppayload) +{ + if (basertppayload->priv->caps_max_ptime != -1 && + basertppayload->priv->prop_max_ptime != -1) + basertppayload->max_ptime = MIN (basertppayload->priv->caps_max_ptime, + basertppayload->priv->prop_max_ptime); + else if (basertppayload->priv->caps_max_ptime != -1) + basertppayload->max_ptime = basertppayload->priv->caps_max_ptime; + else if (basertppayload->priv->prop_max_ptime != -1) + basertppayload->max_ptime = basertppayload->priv->prop_max_ptime; + else + basertppayload->max_ptime = DEFAULT_MAX_PTIME; +} + /** * gst_basertppayload_set_outcaps: * @payload: a #GstBaseRTPPayload @@ -508,6 +529,9 @@ gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, gchar * fieldname, GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps); } + payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME; + payload->abidata.ABI.ptime = 0; + /* the peer caps can override some of the defaults */ peercaps = gst_pad_peer_get_caps (payload->srcpad); if (peercaps == NULL) { @@ -524,6 +548,7 @@ gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, gchar * fieldname, GstStructure *s, *d; const GValue *value; gint pt; + gint max_ptime, ptime; /* peer provides caps we can use to fixate, intersect. This always returns a * writable caps. */ @@ -537,6 +562,12 @@ gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, gchar * fieldname, /* get first structure */ s = gst_caps_get_structure (temp, 0); + if (gst_structure_get_int (s, "maxptime", &max_ptime) && max_ptime > 0) + payload->priv->caps_max_ptime = max_ptime * GST_MSECOND; + + if (gst_structure_get_int (s, "ptime", &ptime) && ptime > 0) + payload->abidata.ABI.ptime = ptime; + if (gst_structure_get_int (s, "payload", &pt)) { /* use peer pt */ GST_BASE_RTP_PAYLOAD_PT (payload) = pt; @@ -602,6 +633,8 @@ gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, gchar * fieldname, GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps); } + update_max_ptime (payload); + res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps); gst_caps_unref (srccaps); @@ -858,7 +891,8 @@ gst_basertppayload_set_property (GObject * object, guint prop_id, basertppayload->seqnum_offset, priv->seqnum_offset_random); break; case PROP_MAX_PTIME: - basertppayload->max_ptime = g_value_get_int64 (value); + basertppayload->priv->prop_max_ptime = g_value_get_int64 (value); + update_max_ptime (basertppayload); break; case PROP_MIN_PTIME: basertppayload->min_ptime = g_value_get_int64 (value); diff --git a/gst-libs/gst/rtp/gstbasertppayload.h b/gst-libs/gst/rtp/gstbasertppayload.h index e57f74ea97..1591c104e1 100644 --- a/gst-libs/gst/rtp/gstbasertppayload.h +++ b/gst-libs/gst/rtp/gstbasertppayload.h @@ -111,7 +111,12 @@ struct _GstBaseRTPPayload /*< private >*/ GstBaseRTPPayloadPrivate *priv; - gpointer _gst_reserved[GST_PADDING - (sizeof(guint64)/sizeof(gpointer)) - 1]; + union { + struct { + guint ptime; /* in ms */ + } ABI; + gpointer _gst_reserved[GST_PADDING - (sizeof(guint64)/sizeof(gpointer)) - 1]; + } abidata; }; struct _GstBaseRTPPayloadClass