diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c index 3fb539449f..e5e1261363 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.c +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.c @@ -1722,11 +1722,24 @@ gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream, gst_pad_push_event (stream->pad, stream->pending_segment); stream->pending_segment = NULL; } - if (G_UNLIKELY (stream->pending_tags)) { + if (G_UNLIKELY (stream->pending_tags || stream->bitrate_changed)) { + GstTagList *tags = stream->pending_tags; + + stream->pending_tags = NULL; + stream->bitrate_changed = 0; + + if (stream->fragment.bitrate != 0) { + if (tags) + tags = gst_tag_list_make_writable (tags); + else + tags = gst_tag_list_new_empty (); + + gst_tag_list_add (tags, GST_TAG_MERGE_KEEP, + GST_TAG_NOMINAL_BITRATE, stream->fragment.bitrate, NULL); + } GST_DEBUG_OBJECT (stream->pad, "Sending pending tags: %" GST_PTR_FORMAT, stream->pending_tags); - gst_pad_push_event (stream->pad, gst_event_new_tag (stream->pending_tags)); - stream->pending_tags = NULL; + gst_pad_push_event (stream->pad, gst_event_new_tag (tags)); } while (stream->pending_events != NULL) { GstEvent *event = stream->pending_events->data; @@ -1842,6 +1855,34 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) } else { GST_BUFFER_PTS (buffer) = GST_CLOCK_TIME_NONE; } + if (stream->downloading_first_buffer) { + gint64 chunk_size = 0; + + stream->downloading_first_buffer = FALSE; + + if (!stream->downloading_header && !stream->downloading_index) { + /* If this is the first buffer of a fragment (not the headers or index) + * and we don't have a birate from the sub-class, then see if we + * can work it out from the fragment size and duration */ + if (stream->fragment.bitrate == 0 && + stream->fragment.duration != 0 && + gst_element_query_duration (stream->uri_handler, GST_FORMAT_BYTES, + &chunk_size)) { + guint bitrate = MIN (G_MAXUINT, gst_util_uint64_scale (chunk_size, + 8 * GST_SECOND, stream->fragment.duration)); + GST_LOG_OBJECT (demux, + "Fragment has size %" G_GUINT64_FORMAT " duration %" GST_TIME_FORMAT + " = bitrate %u", chunk_size, + GST_TIME_ARGS (stream->fragment.duration), bitrate); + stream->fragment.bitrate = bitrate; + } + if (stream->fragment.bitrate) { + stream->bitrate_changed = TRUE; + } else { + GST_WARNING_OBJECT (demux, "Bitrate for fragment not available"); + } + } + } stream->download_total_time += g_get_monotonic_time () - stream->download_chunk_start_time; @@ -2276,6 +2317,7 @@ gst_adaptive_demux_stream_download_uri (GstAdaptiveDemux * demux, */ g_mutex_lock (&stream->fragment_download_lock); stream->download_finished = FALSE; + stream->downloading_first_buffer = TRUE; g_mutex_unlock (&stream->fragment_download_lock); GST_MANIFEST_UNLOCK (demux); @@ -3096,6 +3138,10 @@ gst_adaptive_demux_stream_update_fragment_info (GstAdaptiveDemux * demux, g_return_val_if_fail (klass->stream_update_fragment_info != NULL, GST_FLOW_ERROR); + /* Make sure the sub-class will update bitrate, or else + * we will later */ + stream->fragment.bitrate = 0; + return klass->stream_update_fragment_info (stream); } diff --git a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h index 566b29ab0a..b95af5985a 100644 --- a/gst-libs/gst/adaptivedemux/gstadaptivedemux.h +++ b/gst-libs/gst/adaptivedemux/gstadaptivedemux.h @@ -105,6 +105,10 @@ struct _GstAdaptiveDemuxStreamFragment gchar *index_uri; gint64 index_range_start; gint64 index_range_end; + + /* Nominal bitrate as provided by + * sub-class or calculated by base-class */ + guint bitrate; }; struct _GstAdaptiveDemuxStream @@ -132,9 +136,12 @@ struct _GstAdaptiveDemuxStream gboolean restart_download; gboolean discont; + gboolean downloading_first_buffer; gboolean downloading_header; gboolean downloading_index; + gboolean bitrate_changed; + /* download tooling */ GstElement *src; GstPad *src_srcpad;