/** * hls_progress_buffer_loop() * * Primary function for push-mode. Pulls data from progressbuffer's cache queue. */ static void hls_progress_buffer_loop(void *data) { HLSProgressBuffer* element = HLS_PROGRESS_BUFFER(data); GstFlowReturn result = GST_FLOW_OK; g_mutex_lock(element->lock); while (element->srcresult == GST_FLOW_OK && !cache_has_enough_data(element->cache[element->cache_read_index])) { if (element->is_eos) { gst_pad_push_event(element->srcpad, gst_event_new_eos()); element->srcresult = GST_FLOW_WRONG_STATE; break; } if (!element->is_eos) { g_cond_wait(element->add_cond, element->lock); } } result = element->srcresult; if (result == GST_FLOW_OK) { GstBuffer *buffer = NULL; guint64 read_position = cache_read_buffer(element->cache[element->cache_read_index], &buffer); if (read_position == element->cache_size[element->cache_read_index]) { element->cache_write_ready[element->cache_read_index] = TRUE; element->cache_read_index = (element->cache_read_index + 1) % NUM_OF_CACHED_SEGMENTS; send_hls_not_full_message(element); g_cond_signal(element->del_cond); } g_mutex_unlock(element->lock); gst_buffer_set_caps(buffer, GST_PAD_CAPS(element->sinkpad)); // Send the data to the hls progressbuffer source pad result = gst_pad_push(element->srcpad, buffer); g_mutex_lock(element->lock); if (GST_FLOW_OK == element->srcresult || GST_FLOW_OK != result) element->srcresult = result; else result = element->srcresult; g_mutex_unlock(element->lock); } else { g_mutex_unlock(element->lock); } if (result != GST_FLOW_OK && !element->is_flushing) gst_pad_pause_task(element->srcpad); }
/** * progress_buffer_loop() * * Primary function for push-mode. Pulls data from progressbuffer's cache queue. */ static void progress_buffer_loop(void *data) { ProgressBuffer *element = PROGRESS_BUFFER(data); GstFlowReturn result; gboolean skip = FALSE; g_mutex_lock(&element->lock); next_item: while (element->srcresult == GST_FLOW_OK && element->pending_src_event == NULL && (!cache_has_enough_data(element->cache) || !element->instant_seek)) { if (element->instant_seek) send_underrun_message(element); g_cond_wait(&element->add_cond, &element->lock); } result = element->srcresult; if (result == GST_FLOW_OK) { if (element->pending_src_event) { GstEvent *event = gst_event_ref(element->pending_src_event); progress_buffer_set_pending_event(element, NULL); switch(GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: result = GST_FLOW_EOS; break; case GST_EVENT_SEGMENT: skip = FALSE; break; default: if (skip) { gst_event_unref (event); // INLINE - gst_event_unref() goto next_item; } break; } element->srcresult = result; g_mutex_unlock(&element->lock); gst_pad_push_event (element->srcpad, event); } else // create a buffer { GstBuffer *buffer = NULL; guint64 read_position = cache_read_buffer(element->cache, &buffer); read_position += element->cache_read_offset; GST_BUFFER_OFFSET(buffer) = read_position - gst_buffer_get_size(buffer); if (read_position == element->sink_segment.stop) progress_buffer_set_pending_event(element, gst_event_new_eos()); if (skip) { gst_buffer_unref(buffer); // INLINE - gst_buffer_unref() goto next_item; } else { g_mutex_unlock(&element->lock); // Send the data to the progressbuffer source pad result = gst_pad_push(element->srcpad, buffer); // Switch to skip mode. No we can only pass EOS and NEWSEGMENT events. if (result == GST_FLOW_EOS) { g_mutex_lock(&element->lock); skip = TRUE; goto next_item; } g_mutex_lock(&element->lock); element->srcresult = result; g_mutex_unlock(&element->lock); } } } else { if (skip) // Run out of items in skip mode. Expecting only EOS or NEWSEGMENT in _chain() { element->unexpected = TRUE; result = GST_FLOW_OK; } g_mutex_unlock(&element->lock); } if (result != GST_FLOW_OK) gst_pad_pause_task(element->srcpad); }