static void gst_hls_demux_clear_pending_data (GstHLSDemux * hlsdemux) { gst_hls_demux_decrypt_end (hlsdemux); gst_adapter_clear (hlsdemux->pending_encrypted_data); gst_buffer_replace (&hlsdemux->pending_decrypted_buffer, NULL); gst_buffer_replace (&hlsdemux->pending_typefind_buffer, NULL); hlsdemux->current_offset = -1; }
static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream) { GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); GstFlowReturn ret = GST_FLOW_OK; if (hlsdemux->current_key) gst_hls_demux_decrypt_end (hlsdemux); /* ideally this should be empty, but this eos might have been * caused by an error on the source element */ GST_DEBUG_OBJECT (demux, "Data still on the adapter when EOS was received" ": %" G_GSIZE_FORMAT, gst_adapter_available (stream->adapter)); gst_adapter_clear (stream->adapter); if (stream->last_ret == GST_FLOW_OK) { if (hlsdemux->pending_buffer) { if (hlsdemux->current_key) { GstMapInfo info; gssize unpadded_size; /* Handle pkcs7 unpadding here */ gst_buffer_map (hlsdemux->pending_buffer, &info, GST_MAP_READ); unpadded_size = info.size - info.data[info.size - 1]; gst_buffer_unmap (hlsdemux->pending_buffer, &info); gst_buffer_resize (hlsdemux->pending_buffer, 0, unpadded_size); } ret = gst_hls_demux_handle_buffer (demux, stream, hlsdemux->pending_buffer, TRUE); hlsdemux->pending_buffer = NULL; } } else { if (hlsdemux->pending_buffer) gst_buffer_unref (hlsdemux->pending_buffer); hlsdemux->pending_buffer = NULL; } if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) return gst_adaptive_demux_stream_advance_fragment (demux, stream, stream->fragment.duration); return ret; }
static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream) { GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); GstFlowReturn ret = GST_FLOW_OK; if (hlsdemux->current_key) gst_hls_demux_decrypt_end (hlsdemux); if (stream->last_ret == GST_FLOW_OK) { if (hlsdemux->pending_decrypted_buffer) { if (hlsdemux->current_key) { GstMapInfo info; gssize unpadded_size; /* Handle pkcs7 unpadding here */ gst_buffer_map (hlsdemux->pending_decrypted_buffer, &info, GST_MAP_READ); unpadded_size = info.size - info.data[info.size - 1]; gst_buffer_unmap (hlsdemux->pending_decrypted_buffer, &info); gst_buffer_resize (hlsdemux->pending_decrypted_buffer, 0, unpadded_size); } ret = gst_hls_demux_handle_buffer (demux, stream, hlsdemux->pending_decrypted_buffer, TRUE); hlsdemux->pending_decrypted_buffer = NULL; } } gst_hls_demux_clear_pending_data (hlsdemux); if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED) return gst_adaptive_demux_stream_advance_fragment (demux, stream, stream->fragment.duration); return ret; }
static void gst_hls_demux_reset (GstAdaptiveDemux * ademux) { GstHLSDemux *demux = GST_HLS_DEMUX_CAST (ademux); demux->do_typefind = TRUE; demux->reset_pts = TRUE; g_free (demux->key_url); demux->key_url = NULL; if (demux->key_fragment) g_object_unref (demux->key_fragment); demux->key_fragment = NULL; if (demux->client) { gst_m3u8_client_free (demux->client); demux->client = NULL; } /* TODO recreated on hls only if reset was not for disposing */ demux->client = gst_m3u8_client_new ("", NULL); demux->srcpad_counter = 0; if (demux->pending_buffer) gst_buffer_unref (demux->pending_buffer); demux->pending_buffer = NULL; if (demux->current_key) { g_free (demux->current_key); demux->current_key = NULL; } if (demux->current_iv) { g_free (demux->current_iv); demux->current_iv = NULL; } gst_hls_demux_decrypt_end (demux); }
static gboolean gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek) { GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); GstFormat format; GstSeekFlags flags; GstSeekType start_type, stop_type; gint64 start, stop; gdouble rate; GList *walk, *current_file = NULL; GstClockTime current_pos, target_pos; gint64 current_sequence; GstM3U8MediaFile *file; guint64 bitrate; gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start, &stop_type, &stop); bitrate = gst_hls_demux_get_bitrate (hlsdemux); /* properly cleanup pending decryption status */ if (flags & GST_SEEK_FLAG_FLUSH) { gst_hls_demux_decrypt_end (hlsdemux); } /* Use I-frame variants for trick modes */ if (hlsdemux->client->main->iframe_lists && rate < -1.0 && demux->segment.rate >= -1.0 && demux->segment.rate <= 1.0) { GError *err = NULL; GST_M3U8_CLIENT_LOCK (hlsdemux->client); /* Switch to I-frame variant */ hlsdemux->client->main->current_variant = hlsdemux->client->main->iframe_lists; GST_M3U8_CLIENT_UNLOCK (hlsdemux->client); gst_m3u8_client_set_current (hlsdemux->client, hlsdemux->client->main->iframe_lists->data); gst_uri_downloader_reset (demux->downloader); if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) { GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err); return FALSE; } //hlsdemux->discont = TRUE; hlsdemux->do_typefind = TRUE; gst_hls_demux_change_playlist (hlsdemux, bitrate / ABS (rate), NULL); } else if (rate > -1.0 && rate <= 1.0 && (demux->segment.rate < -1.0 || demux->segment.rate > 1.0)) { GError *err = NULL; GST_M3U8_CLIENT_LOCK (hlsdemux->client); /* Switch to normal variant */ hlsdemux->client->main->current_variant = hlsdemux->client->main->lists; GST_M3U8_CLIENT_UNLOCK (hlsdemux->client); gst_m3u8_client_set_current (hlsdemux->client, hlsdemux->client->main->lists->data); gst_uri_downloader_reset (demux->downloader); if (!gst_hls_demux_update_playlist (hlsdemux, FALSE, &err)) { GST_ELEMENT_ERROR_FROM_ERROR (hlsdemux, "Could not switch playlist", err); return FALSE; } //hlsdemux->discont = TRUE; hlsdemux->do_typefind = TRUE; /* TODO why not continue using the same? that was being used up to now? */ gst_hls_demux_change_playlist (hlsdemux, bitrate, NULL); } GST_M3U8_CLIENT_LOCK (hlsdemux->client); file = GST_M3U8_MEDIA_FILE (hlsdemux->client->current->files->data); current_sequence = file->sequence; current_pos = 0; target_pos = rate > 0 ? start : stop; /* FIXME: Here we need proper discont handling */ for (walk = hlsdemux->client->current->files; walk; walk = walk->next) { file = walk->data; current_sequence = file->sequence; current_file = walk; if (current_pos <= target_pos && target_pos < current_pos + file->duration) { break; } current_pos += file->duration; } if (walk == NULL) { GST_DEBUG_OBJECT (demux, "seeking further than track duration"); current_sequence++; } GST_DEBUG_OBJECT (demux, "seeking to sequence %u", (guint) current_sequence); hlsdemux->reset_pts = TRUE; hlsdemux->client->sequence = current_sequence; hlsdemux->client->current_file = current_file ? current_file : hlsdemux->client->current->files; hlsdemux->client->sequence_position = current_pos; GST_M3U8_CLIENT_UNLOCK (hlsdemux->client); return TRUE; }