mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
hlsdemux: add hlsdemux-specific AdaptiveDemuxStream subclass
Prepare hlsdemux for more than one single stream. Currently hlsdemux assumes there'll only ever be one stream and most of the stream-specific state is actually in the hlsdemux structure. Add a stream subclass instead and move some stream-specific members there instead.
This commit is contained in:
parent
585e60c4ab
commit
463f48c148
2 changed files with 103 additions and 58 deletions
|
@ -93,6 +93,7 @@ static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream);
|
GstAdaptiveDemuxStream * stream);
|
||||||
static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
|
static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
|
GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
|
||||||
|
static void gst_hls_demux_stream_free (GstAdaptiveDemuxStream * stream);
|
||||||
static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream *
|
static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream *
|
||||||
stream);
|
stream);
|
||||||
static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream *
|
static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream *
|
||||||
|
@ -114,7 +115,6 @@ gst_hls_demux_finalize (GObject * obj)
|
||||||
GstHLSDemux *demux = GST_HLS_DEMUX (obj);
|
GstHLSDemux *demux = GST_HLS_DEMUX (obj);
|
||||||
|
|
||||||
gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
|
gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
|
||||||
g_object_unref (demux->pending_encrypted_data);
|
|
||||||
gst_m3u8_client_free (demux->client);
|
gst_m3u8_client_free (demux->client);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||||
|
@ -160,6 +160,7 @@ gst_hls_demux_class_init (GstHLSDemuxClass * klass)
|
||||||
adaptivedemux_class->stream_update_fragment_info =
|
adaptivedemux_class->stream_update_fragment_info =
|
||||||
gst_hls_demux_update_fragment_info;
|
gst_hls_demux_update_fragment_info;
|
||||||
adaptivedemux_class->stream_select_bitrate = gst_hls_demux_select_bitrate;
|
adaptivedemux_class->stream_select_bitrate = gst_hls_demux_select_bitrate;
|
||||||
|
adaptivedemux_class->stream_free = gst_hls_demux_stream_free;
|
||||||
|
|
||||||
adaptivedemux_class->start_fragment = gst_hls_demux_start_fragment;
|
adaptivedemux_class->start_fragment = gst_hls_demux_start_fragment;
|
||||||
adaptivedemux_class->finish_fragment = gst_hls_demux_finish_fragment;
|
adaptivedemux_class->finish_fragment = gst_hls_demux_finish_fragment;
|
||||||
|
@ -172,8 +173,8 @@ gst_hls_demux_class_init (GstHLSDemuxClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_hls_demux_init (GstHLSDemux * demux)
|
gst_hls_demux_init (GstHLSDemux * demux)
|
||||||
{
|
{
|
||||||
demux->do_typefind = TRUE;
|
gst_adaptive_demux_set_stream_struct_size (GST_ADAPTIVE_DEMUX_CAST (demux),
|
||||||
demux->pending_encrypted_data = gst_adapter_new ();
|
sizeof (GstHLSDemuxStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -232,11 +233,18 @@ gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
|
||||||
static void
|
static void
|
||||||
gst_hls_demux_clear_pending_data (GstHLSDemux * hlsdemux)
|
gst_hls_demux_clear_pending_data (GstHLSDemux * hlsdemux)
|
||||||
{
|
{
|
||||||
|
GstAdaptiveDemux *demux = (GstAdaptiveDemux *) hlsdemux;
|
||||||
|
GList *walk;
|
||||||
|
|
||||||
gst_hls_demux_decrypt_end (hlsdemux);
|
gst_hls_demux_decrypt_end (hlsdemux);
|
||||||
gst_adapter_clear (hlsdemux->pending_encrypted_data);
|
for (walk = demux->streams; walk != NULL; walk = walk->next) {
|
||||||
gst_buffer_replace (&hlsdemux->pending_decrypted_buffer, NULL);
|
GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (walk->data);
|
||||||
gst_buffer_replace (&hlsdemux->pending_typefind_buffer, NULL);
|
if (hls_stream->pending_encrypted_data)
|
||||||
hlsdemux->current_offset = -1;
|
gst_adapter_clear (hls_stream->pending_encrypted_data);
|
||||||
|
gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
|
||||||
|
gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
|
||||||
|
hls_stream->current_offset = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -284,7 +292,6 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
//hlsdemux->discont = TRUE;
|
//hlsdemux->discont = TRUE;
|
||||||
hlsdemux->do_typefind = TRUE;
|
|
||||||
|
|
||||||
gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL);
|
gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL);
|
||||||
} else if (rate > -1.0 && rate <= 1.0 && (demux->segment.rate < -1.0
|
} else if (rate > -1.0 && rate <= 1.0 && (demux->segment.rate < -1.0
|
||||||
|
@ -302,7 +309,6 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
//hlsdemux->discont = TRUE;
|
//hlsdemux->discont = TRUE;
|
||||||
hlsdemux->do_typefind = TRUE;
|
|
||||||
/* TODO why not continue using the same? that was being used up to now? */
|
/* TODO why not continue using the same? that was being used up to now? */
|
||||||
gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL);
|
gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL);
|
||||||
}
|
}
|
||||||
|
@ -353,7 +359,8 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "seeking to sequence %u", (guint) current_sequence);
|
GST_DEBUG_OBJECT (demux, "seeking to sequence %u", (guint) current_sequence);
|
||||||
hlsdemux->reset_pts = TRUE;
|
for (walk = demux->streams; walk != NULL; walk = walk->next)
|
||||||
|
GST_HLS_DEMUX_STREAM_CAST (walk->data)->reset_pts = TRUE;
|
||||||
hlsdemux->client->sequence = current_sequence;
|
hlsdemux->client->sequence = current_sequence;
|
||||||
hlsdemux->client->current_file =
|
hlsdemux->client->current_file =
|
||||||
current_file ? current_file : hlsdemux->client->current->files;
|
current_file ? current_file : hlsdemux->client->current->files;
|
||||||
|
@ -390,12 +397,18 @@ static gboolean
|
||||||
gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
|
gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
|
||||||
{
|
{
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
||||||
|
GstAdaptiveDemuxStream *stream;
|
||||||
|
GstHLSDemuxStream *hlsdemux_stream;
|
||||||
|
|
||||||
/* only 1 output supported */
|
/* only 1 output supported */
|
||||||
gst_hls_demux_clear_pending_data (hlsdemux);
|
gst_hls_demux_clear_pending_data (hlsdemux);
|
||||||
gst_adaptive_demux_stream_new (demux, gst_hls_demux_create_pad (hlsdemux));
|
stream = gst_adaptive_demux_stream_new (demux,
|
||||||
|
gst_hls_demux_create_pad (hlsdemux));
|
||||||
|
|
||||||
hlsdemux->reset_pts = TRUE;
|
hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
|
||||||
|
|
||||||
|
hlsdemux_stream->do_typefind = TRUE;
|
||||||
|
hlsdemux_stream->reset_pts = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +433,9 @@ gst_hls_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
|
||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
GST_WARNING_OBJECT (demux, "Error validating first playlist.");
|
GST_WARNING_OBJECT (demux, "Error validating first playlist.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else if (!gst_m3u8_client_update (hlsdemux->client, playlist)) {
|
}
|
||||||
|
|
||||||
|
if (!gst_m3u8_client_update (hlsdemux->client, playlist)) {
|
||||||
/* In most cases, this will happen if we set a wrong url in the
|
/* In most cases, this will happen if we set a wrong url in the
|
||||||
* source element and we have received the 404 HTML response instead of
|
* source element and we have received the 404 HTML response instead of
|
||||||
* the playlist */
|
* the playlist */
|
||||||
|
@ -535,22 +550,25 @@ key_failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles decrypted buffers only */
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
|
gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force)
|
GstAdaptiveDemuxStream * stream, GstBuffer * buffer, gboolean force)
|
||||||
{
|
{
|
||||||
|
GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream); // FIXME: pass HlsStream into function
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
||||||
|
|
||||||
if (G_UNLIKELY (hlsdemux->do_typefind && buffer != NULL)) {
|
if (buffer == NULL)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (hls_stream->do_typefind)) {
|
||||||
GstCaps *caps = NULL;
|
GstCaps *caps = NULL;
|
||||||
GstMapInfo info;
|
GstMapInfo info;
|
||||||
guint buffer_size;
|
guint buffer_size;
|
||||||
GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
|
GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
|
||||||
|
|
||||||
if (hlsdemux->pending_typefind_buffer)
|
if (hls_stream->pending_typefind_buffer)
|
||||||
buffer = gst_buffer_append (hlsdemux->pending_typefind_buffer, buffer);
|
buffer = gst_buffer_append (hls_stream->pending_typefind_buffer, buffer);
|
||||||
hlsdemux->pending_typefind_buffer = NULL;
|
hls_stream->pending_typefind_buffer = NULL;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &info, GST_MAP_READ);
|
gst_buffer_map (buffer, &info, GST_MAP_READ);
|
||||||
buffer_size = info.size;
|
buffer_size = info.size;
|
||||||
|
@ -572,26 +590,26 @@ gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
|
||||||
("Could not determine type of stream"), (NULL));
|
("Could not determine type of stream"), (NULL));
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
} else {
|
|
||||||
hlsdemux->pending_typefind_buffer = buffer;
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hls_stream->pending_typefind_buffer = buffer;
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
|
GST_DEBUG_OBJECT (hlsdemux, "Typefind result: %" GST_PTR_FORMAT " prob:%d",
|
||||||
caps, prob);
|
caps, prob);
|
||||||
|
|
||||||
gst_adaptive_demux_stream_set_caps (stream, caps);
|
gst_adaptive_demux_stream_set_caps (stream, caps);
|
||||||
hlsdemux->do_typefind = FALSE;
|
hls_stream->do_typefind = FALSE;
|
||||||
}
|
}
|
||||||
|
g_assert (hls_stream->pending_typefind_buffer == NULL);
|
||||||
g_assert (hlsdemux->pending_typefind_buffer == NULL);
|
|
||||||
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
buffer = gst_buffer_make_writable (buffer);
|
buffer = gst_buffer_make_writable (buffer);
|
||||||
GST_BUFFER_OFFSET (buffer) = hlsdemux->current_offset;
|
GST_BUFFER_OFFSET (buffer) = hls_stream->current_offset;
|
||||||
hlsdemux->current_offset += gst_buffer_get_size (buffer);
|
hls_stream->current_offset += gst_buffer_get_size (buffer);
|
||||||
GST_BUFFER_OFFSET_END (buffer) = hlsdemux->current_offset;
|
GST_BUFFER_OFFSET_END (buffer) = hls_stream->current_offset;
|
||||||
return gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
return gst_adaptive_demux_stream_push_buffer (stream, buffer);
|
||||||
}
|
}
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -602,31 +620,32 @@ gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream)
|
GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
||||||
|
GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream); // FIXME: pass HlsStream into function
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
if (hlsdemux->current_key)
|
if (hlsdemux->current_key)
|
||||||
gst_hls_demux_decrypt_end (hlsdemux);
|
gst_hls_demux_decrypt_end (hlsdemux);
|
||||||
|
|
||||||
if (stream->last_ret == GST_FLOW_OK) {
|
if (stream->last_ret == GST_FLOW_OK) {
|
||||||
if (hlsdemux->pending_decrypted_buffer) {
|
if (hls_stream->pending_decrypted_buffer) {
|
||||||
if (hlsdemux->current_key) {
|
if (hlsdemux->current_key) {
|
||||||
GstMapInfo info;
|
GstMapInfo info;
|
||||||
gssize unpadded_size;
|
gssize unpadded_size;
|
||||||
|
|
||||||
/* Handle pkcs7 unpadding here */
|
/* Handle pkcs7 unpadding here */
|
||||||
gst_buffer_map (hlsdemux->pending_decrypted_buffer, &info,
|
gst_buffer_map (hls_stream->pending_decrypted_buffer, &info,
|
||||||
GST_MAP_READ);
|
GST_MAP_READ);
|
||||||
unpadded_size = info.size - info.data[info.size - 1];
|
unpadded_size = info.size - info.data[info.size - 1];
|
||||||
gst_buffer_unmap (hlsdemux->pending_decrypted_buffer, &info);
|
gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info);
|
||||||
|
|
||||||
gst_buffer_resize (hlsdemux->pending_decrypted_buffer, 0,
|
gst_buffer_resize (hls_stream->pending_decrypted_buffer, 0,
|
||||||
unpadded_size);
|
unpadded_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gst_hls_demux_handle_buffer (demux, stream,
|
gst_hls_demux_handle_buffer (demux, stream,
|
||||||
hlsdemux->pending_decrypted_buffer, TRUE);
|
hls_stream->pending_decrypted_buffer, TRUE);
|
||||||
hlsdemux->pending_decrypted_buffer = NULL;
|
hls_stream->pending_decrypted_buffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gst_hls_demux_clear_pending_data (hlsdemux);
|
gst_hls_demux_clear_pending_data (hlsdemux);
|
||||||
|
@ -642,9 +661,10 @@ gst_hls_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
|
GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
|
||||||
|
GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
|
||||||
|
|
||||||
if (hlsdemux->current_offset == -1)
|
if (hls_stream->current_offset == -1)
|
||||||
hlsdemux->current_offset =
|
hls_stream->current_offset =
|
||||||
GST_BUFFER_OFFSET_IS_VALID (buffer) ? GST_BUFFER_OFFSET (buffer) : 0;
|
GST_BUFFER_OFFSET_IS_VALID (buffer) ? GST_BUFFER_OFFSET (buffer) : 0;
|
||||||
|
|
||||||
/* Is it encrypted? */
|
/* Is it encrypted? */
|
||||||
|
@ -653,17 +673,20 @@ gst_hls_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
gsize size;
|
gsize size;
|
||||||
GstBuffer *tmp_buffer;
|
GstBuffer *tmp_buffer;
|
||||||
|
|
||||||
gst_adapter_push (hlsdemux->pending_encrypted_data, buffer);
|
if (hls_stream->pending_encrypted_data == NULL)
|
||||||
size = gst_adapter_available (hlsdemux->pending_encrypted_data);
|
hls_stream->pending_encrypted_data = gst_adapter_new ();
|
||||||
|
|
||||||
|
gst_adapter_push (hls_stream->pending_encrypted_data, buffer);
|
||||||
|
size = gst_adapter_available (hls_stream->pending_encrypted_data);
|
||||||
|
|
||||||
/* must be a multiple of 16 */
|
/* must be a multiple of 16 */
|
||||||
size = size & (~0xF);
|
size &= (~0xF);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = gst_adapter_take_buffer (hlsdemux->pending_encrypted_data, size);
|
buffer = gst_adapter_take_buffer (hls_stream->pending_encrypted_data, size);
|
||||||
buffer = gst_hls_demux_decrypt_fragment (hlsdemux, buffer, &err);
|
buffer = gst_hls_demux_decrypt_fragment (hlsdemux, buffer, &err);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
|
GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
|
||||||
|
@ -672,14 +695,26 @@ gst_hls_demux_data_received (GstAdaptiveDemux * demux,
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_buffer = hlsdemux->pending_decrypted_buffer;
|
tmp_buffer = hls_stream->pending_decrypted_buffer;
|
||||||
hlsdemux->pending_decrypted_buffer = buffer;
|
hls_stream->pending_decrypted_buffer = buffer;
|
||||||
buffer = tmp_buffer;
|
buffer = tmp_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
|
return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_hls_demux_stream_free (GstAdaptiveDemuxStream * stream)
|
||||||
|
{
|
||||||
|
GstHLSDemuxStream *hls_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
|
||||||
|
|
||||||
|
if (hls_stream->pending_encrypted_data)
|
||||||
|
g_object_unref (hls_stream->pending_encrypted_data);
|
||||||
|
|
||||||
|
gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL);
|
||||||
|
gst_buffer_replace (&hls_stream->pending_typefind_buffer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
|
gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
|
@ -692,17 +727,19 @@ gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream * stream)
|
gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
|
GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
|
||||||
|
|
||||||
gst_m3u8_client_advance_fragment (hlsdemux->client,
|
gst_m3u8_client_advance_fragment (hlsdemux->client,
|
||||||
stream->demux->segment.rate > 0);
|
stream->demux->segment.rate > 0);
|
||||||
hlsdemux->reset_pts = FALSE;
|
hlsdemux_stream->reset_pts = FALSE;
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream)
|
gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream)
|
||||||
{
|
{
|
||||||
|
GstHLSDemuxStream *hlsdemux_stream = GST_HLS_DEMUX_STREAM_CAST (stream);
|
||||||
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
|
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (stream->demux);
|
||||||
gchar *next_fragment_uri;
|
gchar *next_fragment_uri;
|
||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
|
@ -723,7 +760,8 @@ gst_hls_demux_update_fragment_info (GstAdaptiveDemuxStream * stream)
|
||||||
discont = TRUE;
|
discont = TRUE;
|
||||||
|
|
||||||
/* set up our source for download */
|
/* set up our source for download */
|
||||||
if (hlsdemux->reset_pts || discont || stream->demux->segment.rate < 0.0) {
|
if (hlsdemux_stream->reset_pts || discont
|
||||||
|
|| stream->demux->segment.rate < 0.0) {
|
||||||
stream->fragment.timestamp = timestamp;
|
stream->fragment.timestamp = timestamp;
|
||||||
} else {
|
} else {
|
||||||
stream->fragment.timestamp = GST_CLOCK_TIME_NONE;
|
stream->fragment.timestamp = GST_CLOCK_TIME_NONE;
|
||||||
|
@ -775,9 +813,6 @@ gst_hls_demux_reset (GstAdaptiveDemux * ademux)
|
||||||
{
|
{
|
||||||
GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
|
GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux);
|
||||||
|
|
||||||
demux->do_typefind = TRUE;
|
|
||||||
demux->reset_pts = TRUE;
|
|
||||||
|
|
||||||
g_free (demux->key_url);
|
g_free (demux->key_url);
|
||||||
demux->key_url = NULL;
|
demux->key_url = NULL;
|
||||||
|
|
||||||
|
@ -793,8 +828,9 @@ gst_hls_demux_reset (GstAdaptiveDemux * ademux)
|
||||||
demux->client = gst_m3u8_client_new ("", NULL);
|
demux->client = gst_m3u8_client_new ("", NULL);
|
||||||
|
|
||||||
demux->srcpad_counter = 0;
|
demux->srcpad_counter = 0;
|
||||||
|
|
||||||
gst_hls_demux_clear_pending_data (demux);
|
gst_hls_demux_clear_pending_data (demux);
|
||||||
gst_buffer_replace (&demux->pending_typefind_buffer, NULL);
|
|
||||||
if (demux->current_key) {
|
if (demux->current_key) {
|
||||||
g_free (demux->current_key);
|
g_free (demux->current_key);
|
||||||
demux->current_key = NULL;
|
demux->current_key = NULL;
|
||||||
|
@ -1099,9 +1135,6 @@ retry_failover_protection:
|
||||||
return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
|
return gst_hls_demux_change_playlist (demux, new_bandwidth - 1, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Force typefinding since we might have changed media type */
|
|
||||||
demux->do_typefind = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1137,7 +1170,7 @@ decrypt_fragment (GstHLSDemux * demux, gsize length,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_hls_demux_decrypt_end (GstHLSDemux * demux)
|
gst_hls_stream_decrypt_end (GstHLSDemuxStream * stream)
|
||||||
{
|
{
|
||||||
EVP_CIPHER_CTX_cleanup (&demux->aes_ctx);
|
EVP_CIPHER_CTX_cleanup (&demux->aes_ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_HLS_DEMUX \
|
#define GST_TYPE_HLS_DEMUX \
|
||||||
(gst_hls_demux_get_type())
|
(gst_hls_demux_get_type())
|
||||||
#define GST_HLS_DEMUX(obj) \
|
#define GST_HLS_DEMUX(obj) \
|
||||||
|
@ -52,8 +53,26 @@ G_BEGIN_DECLS
|
||||||
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_HLS_DEMUX,GstHLSDemuxClass))
|
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_HLS_DEMUX,GstHLSDemuxClass))
|
||||||
#define GST_HLS_DEMUX_CAST(obj) \
|
#define GST_HLS_DEMUX_CAST(obj) \
|
||||||
((GstHLSDemux *)obj)
|
((GstHLSDemux *)obj)
|
||||||
|
|
||||||
typedef struct _GstHLSDemux GstHLSDemux;
|
typedef struct _GstHLSDemux GstHLSDemux;
|
||||||
typedef struct _GstHLSDemuxClass GstHLSDemuxClass;
|
typedef struct _GstHLSDemuxClass GstHLSDemuxClass;
|
||||||
|
typedef struct _GstHLSDemuxStream GstHLSDemuxStream;
|
||||||
|
|
||||||
|
#define GST_HLS_DEMUX_STREAM_CAST(stream) ((GstHLSDemuxStream *)(stream))
|
||||||
|
|
||||||
|
struct _GstHLSDemuxStream
|
||||||
|
{
|
||||||
|
GstAdaptiveDemux adaptive_demux_stream;
|
||||||
|
|
||||||
|
gboolean do_typefind; /* Whether we need to typefind the next buffer */
|
||||||
|
GstBuffer *pending_typefind_buffer; /* for collecting data until typefind succeeds */
|
||||||
|
|
||||||
|
GstAdapter *pending_encrypted_data; /* for chunking data into 16 byte multiples for decryption */
|
||||||
|
GstBuffer *pending_decrypted_buffer; /* last decrypted buffer for pkcs7 unpadding.
|
||||||
|
We only know that it is the last at EOS */
|
||||||
|
guint64 current_offset; /* offset we're currently at */
|
||||||
|
gboolean reset_pts;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstHLSDemux:
|
* GstHLSDemux:
|
||||||
|
@ -68,7 +87,6 @@ struct _GstHLSDemux
|
||||||
|
|
||||||
gchar *uri; /* Original playlist URI */
|
gchar *uri; /* Original playlist URI */
|
||||||
GstM3U8Client *client; /* M3U8 client */
|
GstM3U8Client *client; /* M3U8 client */
|
||||||
gboolean do_typefind; /* Whether we need to typefind the next buffer */
|
|
||||||
|
|
||||||
/* Cache for the last key */
|
/* Cache for the last key */
|
||||||
gchar *key_url;
|
gchar *key_url;
|
||||||
|
@ -84,12 +102,6 @@ struct _GstHLSDemux
|
||||||
#endif
|
#endif
|
||||||
gchar *current_key;
|
gchar *current_key;
|
||||||
guint8 *current_iv;
|
guint8 *current_iv;
|
||||||
GstAdapter *pending_encrypted_data; /* for chunking data into 16 byte multiples for decryption */
|
|
||||||
GstBuffer *pending_decrypted_buffer; /* last decrypted buffer for pkcs7 unpadding.
|
|
||||||
We only know that it is the last at EOS */
|
|
||||||
GstBuffer *pending_typefind_buffer; /* for collecting data until typefind succeeds */
|
|
||||||
guint64 current_offset; /* offset we're currently at */
|
|
||||||
gboolean reset_pts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstHLSDemuxClass
|
struct _GstHLSDemuxClass
|
||||||
|
|
Loading…
Reference in a new issue