static gboolean gst_hls_demux_fetch_location (GstHLSDemux * demux, const gchar * uri) { GstStateChangeReturn ret; gboolean bret = FALSE; g_mutex_lock (demux->fetcher_lock); while (demux->fetcher) g_cond_wait (demux->fetcher_cond, demux->fetcher_lock); if (demux->cancelled) goto quit; if (!gst_hls_demux_make_fetcher (demux, uri)) { goto uri_error; } ret = gst_element_set_state (demux->fetcher, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) goto state_change_error; /* wait until we have fetched the uri */ GST_DEBUG_OBJECT (demux, "Waiting to fetch the URI"); g_cond_wait (demux->fetcher_cond, demux->fetcher_lock); gst_hls_demux_stop_fetcher (demux, FALSE); if (gst_adapter_available (demux->download)) { GST_INFO_OBJECT (demux, "URI fetched successfully"); bret = TRUE; } goto quit; uri_error: { GST_ELEMENT_ERROR (demux, RESOURCE, OPEN_READ, ("Could not create an element to fetch the given URI."), ("URI: \"%s\"", uri)); bret = FALSE; goto quit; } state_change_error: { GST_ELEMENT_ERROR (demux, CORE, STATE_CHANGE, ("Error changing state of the fetcher element."), (NULL)); bret = FALSE; goto quit; } quit: { g_mutex_unlock (demux->fetcher_lock); /* Unlock any other fetcher that might be waiting */ g_cond_broadcast (demux->fetcher_cond); return bret; } }
static void gst_hls_demux_stop (GstHLSDemux * demux) { gst_hls_demux_stop_fetcher (demux, TRUE); if (GST_TASK_STATE (demux->task) != GST_TASK_STOPPED) gst_task_stop (demux->task); g_cond_signal (demux->thread_cond); }
static gboolean gst_hls_demux_src_event (GstPad * pad, GstEvent * event) { GstHLSDemux *demux; demux = GST_HLS_DEMUX (gst_pad_get_element_private (pad)); switch (event->type) { case GST_EVENT_SEEK: { gdouble rate; GstFormat format; GstSeekFlags flags; GstSeekType start_type, stop_type; gint64 start, stop; GList *walk; gint current_pos; gint current_sequence; gint target_second; GstM3U8MediaFile *file; GST_INFO_OBJECT (demux, "Received GST_EVENT_SEEK"); if (gst_m3u8_client_is_live (demux->client)) { GST_WARNING_OBJECT (demux, "Received seek event for live stream"); return FALSE; } gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, &stop_type, &stop); if (format != GST_FORMAT_TIME) return FALSE; GST_DEBUG_OBJECT (demux, "seek event, rate: %f start: %" GST_TIME_FORMAT " stop: %" GST_TIME_FORMAT, rate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); file = GST_M3U8_MEDIA_FILE (demux->client->current->files->data); current_sequence = file->sequence; current_pos = 0; target_second = start / GST_SECOND; GST_DEBUG_OBJECT (demux, "Target seek to %d", target_second); for (walk = demux->client->current->files; walk; walk = walk->next) { file = walk->data; current_sequence = file->sequence; if (current_pos <= target_second && target_second < current_pos + file->duration) { break; } current_pos += file->duration; } if (walk == NULL) { GST_WARNING_OBJECT (demux, "Could not find seeked fragment"); return FALSE; } if (flags & GST_SEEK_FLAG_FLUSH) { GST_DEBUG_OBJECT (demux, "sending flush start"); gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ()); } demux->cancelled = TRUE; gst_task_pause (demux->task); g_mutex_lock (demux->fetcher_lock); gst_hls_demux_stop_fetcher (demux, TRUE); g_mutex_unlock (demux->fetcher_lock); g_mutex_lock (demux->thread_lock); g_cond_signal (demux->thread_cond); g_mutex_unlock (demux->thread_lock); gst_task_pause (demux->task); /* wait for streaming to finish */ g_static_rec_mutex_lock (&demux->task_lock); demux->need_cache = TRUE; while (!g_queue_is_empty (demux->queue)) { GstBuffer *buf = g_queue_pop_head (demux->queue); gst_buffer_unref (buf); } GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence); demux->client->sequence = current_sequence; demux->position = start; demux->need_segment = TRUE; if (flags & GST_SEEK_FLAG_FLUSH) { GST_DEBUG_OBJECT (demux, "sending flush stop"); gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop ()); } demux->cancelled = FALSE; gst_task_start (demux->task); g_static_rec_mutex_unlock (&demux->task_lock); return TRUE; } default: break; } return gst_pad_event_default (pad, event); }