mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 23:48:53 +00:00
dashdemux: change bitrates based on the stream bitrate
Do not use a global bitrate as the sizes of the fragments matter when calculating the download rate as the connection setup time is also being taken into the download duration, a smaller fragment will have a lower bitrate than a larger one. This avoids switching the bitrates for streams frequently because of bitrate mismatches
This commit is contained in:
parent
770df6277a
commit
94dcb60127
2 changed files with 28 additions and 17 deletions
|
@ -231,8 +231,7 @@ static void gst_dash_demux_pause_stream_task (GstDashDemux * demux);
|
||||||
static void gst_dash_demux_resume_stream_task (GstDashDemux * demux);
|
static void gst_dash_demux_resume_stream_task (GstDashDemux * demux);
|
||||||
static void gst_dash_demux_resume_download_task (GstDashDemux * demux);
|
static void gst_dash_demux_resume_download_task (GstDashDemux * demux);
|
||||||
static gboolean gst_dash_demux_setup_all_streams (GstDashDemux * demux);
|
static gboolean gst_dash_demux_setup_all_streams (GstDashDemux * demux);
|
||||||
static gboolean gst_dash_demux_select_representations (GstDashDemux * demux,
|
static gboolean gst_dash_demux_select_representations (GstDashDemux * demux);
|
||||||
guint64 current_bitrate);
|
|
||||||
static gboolean gst_dash_demux_get_next_fragment (GstDashDemux * demux);
|
static gboolean gst_dash_demux_get_next_fragment (GstDashDemux * demux);
|
||||||
|
|
||||||
static void gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose);
|
static void gst_dash_demux_reset (GstDashDemux * demux, gboolean dispose);
|
||||||
|
@ -1414,8 +1413,7 @@ gst_dash_demux_download_loop (GstDashDemux * demux)
|
||||||
|
|
||||||
/* try to switch to another set of representations if needed */
|
/* try to switch to another set of representations if needed */
|
||||||
if (gst_dash_demux_all_streams_have_data (demux)) {
|
if (gst_dash_demux_all_streams_have_data (demux)) {
|
||||||
gst_dash_demux_select_representations (demux,
|
gst_dash_demux_select_representations (demux);
|
||||||
demux->bandwidth_usage * demux->dnl_rate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fetch the next fragment */
|
/* fetch the next fragment */
|
||||||
|
@ -1526,7 +1524,7 @@ gst_dash_demux_prepare_pad_switch (GstDashDemux * demux)
|
||||||
|
|
||||||
/* gst_dash_demux_select_representations:
|
/* gst_dash_demux_select_representations:
|
||||||
*
|
*
|
||||||
* Select the most appropriate media representations based on a target
|
* Select the most appropriate media representations based on current target
|
||||||
* bitrate.
|
* bitrate.
|
||||||
*
|
*
|
||||||
* FIXME: all representations are selected against the same bitrate, but
|
* FIXME: all representations are selected against the same bitrate, but
|
||||||
|
@ -1537,7 +1535,7 @@ gst_dash_demux_prepare_pad_switch (GstDashDemux * demux)
|
||||||
* Returns TRUE if a new set of representations has been selected
|
* Returns TRUE if a new set of representations has been selected
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
|
gst_dash_demux_select_representations (GstDashDemux * demux)
|
||||||
{
|
{
|
||||||
GstActiveStream *active_stream = NULL;
|
GstActiveStream *active_stream = NULL;
|
||||||
GList *rep_list = NULL;
|
GList *rep_list = NULL;
|
||||||
|
@ -1548,8 +1546,10 @@ gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
|
||||||
|
|
||||||
guint i = 0;
|
guint i = 0;
|
||||||
|
|
||||||
|
|
||||||
GST_MPD_CLIENT_LOCK (demux->client);
|
GST_MPD_CLIENT_LOCK (demux->client);
|
||||||
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
for (iter = demux->streams; iter; iter = g_slist_next (iter)) {
|
||||||
|
guint64 bitrate;
|
||||||
stream = iter->data;
|
stream = iter->data;
|
||||||
active_stream =
|
active_stream =
|
||||||
gst_mpdparser_get_active_stream_by_index (demux->client, stream->index);
|
gst_mpdparser_get_active_stream_by_index (demux->client, stream->index);
|
||||||
|
@ -1562,6 +1562,9 @@ gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
|
||||||
if (!rep_list)
|
if (!rep_list)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
bitrate = stream->dnl_rate * demux->bandwidth_usage;
|
||||||
|
GST_DEBUG_OBJECT (demux, "Trying to change to bitrate: %llu", bitrate);
|
||||||
|
|
||||||
/* get representation index with current max_bandwidth */
|
/* get representation index with current max_bandwidth */
|
||||||
new_index =
|
new_index =
|
||||||
gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate);
|
gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate);
|
||||||
|
@ -1571,9 +1574,11 @@ gst_dash_demux_select_representations (GstDashDemux * demux, guint64 bitrate)
|
||||||
new_index = gst_mpdparser_get_rep_idx_with_min_bandwidth (rep_list);
|
new_index = gst_mpdparser_get_rep_idx_with_min_bandwidth (rep_list);
|
||||||
|
|
||||||
if (new_index != active_stream->representation_idx) {
|
if (new_index != active_stream->representation_idx) {
|
||||||
GST_INFO_OBJECT (demux, "Changing representation idx: %d", new_index);
|
GstRepresentationNode *rep = g_list_nth_data (rep_list, new_index);
|
||||||
|
GST_INFO_OBJECT (demux, "Changing representation idx: %d %d %u",
|
||||||
|
stream->index, new_index, rep->bandwidth);
|
||||||
if (gst_mpd_client_setup_representation (demux->client, active_stream,
|
if (gst_mpd_client_setup_representation (demux->client, active_stream,
|
||||||
g_list_nth_data (rep_list, new_index))) {
|
rep)) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
GST_INFO_OBJECT (demux, "Switching bitrate to %d",
|
GST_INFO_OBJECT (demux, "Switching bitrate to %d",
|
||||||
active_stream->cur_representation->bandwidth);
|
active_stream->cur_representation->bandwidth);
|
||||||
|
@ -1767,7 +1772,6 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_get_current_time (&start);
|
|
||||||
/* Get the fragment corresponding to each stream index */
|
/* Get the fragment corresponding to each stream index */
|
||||||
if (selected_stream) {
|
if (selected_stream) {
|
||||||
guint stream_idx = selected_stream->index;
|
guint stream_idx = selected_stream->index;
|
||||||
|
@ -1776,6 +1780,7 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
if (gst_mpd_client_get_next_fragment (demux->client,
|
if (gst_mpd_client_get_next_fragment (demux->client,
|
||||||
stream_idx, &discont, &next_fragment_uri, &duration, ×tamp)) {
|
stream_idx, &discont, &next_fragment_uri, &duration, ×tamp)) {
|
||||||
|
|
||||||
|
g_get_current_time (&start);
|
||||||
GST_INFO_OBJECT (demux, "Next fragment for stream #%i", stream_idx);
|
GST_INFO_OBJECT (demux, "Next fragment for stream #%i", stream_idx);
|
||||||
GST_INFO_OBJECT (demux,
|
GST_INFO_OBJECT (demux,
|
||||||
"Fetching next fragment %s ts:%" GST_TIME_FORMAT " dur:%"
|
"Fetching next fragment %s ts:%" GST_TIME_FORMAT " dur:%"
|
||||||
|
@ -1813,6 +1818,7 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
}
|
}
|
||||||
selected_stream->need_header = FALSE;
|
selected_stream->need_header = FALSE;
|
||||||
}
|
}
|
||||||
|
g_get_current_time (&now);
|
||||||
|
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
buffer = gst_buffer_make_metadata_writable (buffer);
|
||||||
|
|
||||||
|
@ -1837,11 +1843,15 @@ gst_dash_demux_get_next_fragment (GstDashDemux * demux)
|
||||||
|
|
||||||
/* Wake the download task up */
|
/* Wake the download task up */
|
||||||
GST_TASK_SIGNAL (demux->download_task);
|
GST_TASK_SIGNAL (demux->download_task);
|
||||||
g_get_current_time (&now);
|
if (selected_stream) {
|
||||||
diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (start));
|
diff = (GST_TIMEVAL_TO_TIME (now) - GST_TIMEVAL_TO_TIME (start));
|
||||||
demux->dnl_rate = (size_buffer * 8) / ((double) diff / GST_SECOND);
|
selected_stream->dnl_rate =
|
||||||
GST_INFO_OBJECT (demux,
|
(size_buffer * 8) / ((double) diff / GST_SECOND);
|
||||||
"Download rate = %" PRIu64 " Kbits/s (%" PRIu64 " Ko in %.2f s)",
|
GST_INFO_OBJECT (demux,
|
||||||
demux->dnl_rate / 1000, size_buffer / 1024, ((double) diff / GST_SECOND));
|
"Stream: %d Download rate = %" PRIu64 " Kbits/s (%" PRIu64
|
||||||
|
" Ko in %.2f s)", selected_stream->index,
|
||||||
|
selected_stream->dnl_rate / 1000, size_buffer / 1024,
|
||||||
|
((double) diff / GST_SECOND));
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,9 @@ struct _GstDashDemuxStream
|
||||||
gboolean has_data_queued;
|
gboolean has_data_queued;
|
||||||
|
|
||||||
GstDataQueue *queue;
|
GstDataQueue *queue;
|
||||||
|
|
||||||
|
/* Download rate */
|
||||||
|
guint64 dnl_rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,8 +140,6 @@ struct _GstDashDemux
|
||||||
GstClockTime position;
|
GstClockTime position;
|
||||||
GstClockTime position_shift;
|
GstClockTime position_shift;
|
||||||
GstClockTime last_position_shift;
|
GstClockTime last_position_shift;
|
||||||
/* Download rate */
|
|
||||||
guint64 dnl_rate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstDashDemuxClass
|
struct _GstDashDemuxClass
|
||||||
|
|
Loading…
Reference in a new issue