static GstPadProbeReturn encoder_appsink_event_probe (GstPad *pad, GstPadProbeInfo *info, gpointer data) { GstEvent *event = gst_pad_probe_info_get_event (info); Encoder *encoder = data; GstClockTime timestamp, running_time, stream_time; gboolean all_headers; guint count; if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { GST_ERROR ("End of Stream of encoder %s", encoder->name); *(encoder->output->eos) = TRUE; return GST_PAD_PROBE_OK; } if (!gst_video_event_is_force_key_unit (event)) { return GST_PAD_PROBE_OK; } /* force key unit event */ gst_video_event_parse_downstream_force_key_unit (event, ×tamp, &stream_time, &running_time, &all_headers, &count); if (encoder->last_segment_duration != 0) { encoder->last_running_time = timestamp; } return GST_PAD_PROBE_OK; }
static gboolean mpegtsmux_sink_event (GstPad * pad, GstEvent * event) { MpegTsMux *mux = GST_MPEG_TSMUX (gst_pad_get_parent (pad)); MpegTsPadData *ts_data; gboolean res = TRUE; gboolean forward = TRUE; ts_data = (MpegTsPadData *) gst_pad_get_element_private (pad); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CUSTOM_DOWNSTREAM: { GstClockTime timestamp, stream_time, running_time; gboolean all_headers; guint count; if (!gst_video_event_is_force_key_unit (event)) goto out; forward = FALSE; gst_video_event_parse_downstream_force_key_unit (event, ×tamp, &stream_time, &running_time, &all_headers, &count); GST_INFO_OBJECT (mux, "have downstream force-key-unit event on pad %s, " "seqnum %d, running-time %" GST_TIME_FORMAT " count %d", gst_pad_get_name (pad), gst_event_get_seqnum (event), GST_TIME_ARGS (running_time), count); if (mux->force_key_unit_event != NULL) { GST_INFO_OBJECT (mux, "skipping downstream force key unit event " "as an upstream force key unit is already queued"); goto out; } if (!all_headers) goto out; mux->pending_key_unit_ts = running_time; gst_event_replace (&mux->force_key_unit_event, event); break; } default: break; } out: if (forward) res = ts_data->eventfunc (pad, event); gst_object_unref (mux); return res; }
static GstPadProbeReturn gst_hls_sink_ghost_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) { GstHlsSink *sink = GST_HLS_SINK_CAST (data); GstEvent *event = gst_pad_probe_info_get_event (info); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: { gst_event_copy_segment (event, &sink->segment); break; } case GST_EVENT_FLUSH_STOP: gst_segment_init (&sink->segment, GST_FORMAT_UNDEFINED); break; case GST_EVENT_CUSTOM_DOWNSTREAM: { GstClockTime timestamp; GstClockTime running_time, stream_time; gboolean all_headers; guint count; if (!gst_video_event_is_force_key_unit (event)) break; gst_event_replace (&sink->force_key_unit_event, event); gst_video_event_parse_downstream_force_key_unit (event, ×tamp, &stream_time, &running_time, &all_headers, &count); GST_INFO_OBJECT (sink, "setting index %d", count); sink->index = count; break; } default: break; } return GST_PAD_PROBE_OK; }
static gboolean gst_multi_file_sink_event (GstBaseSink * sink, GstEvent * event) { GstMultiFileSink *multifilesink; gchar *filename; multifilesink = GST_MULTI_FILE_SINK (sink); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CUSTOM_DOWNSTREAM: { GstClockTime timestamp, duration; GstClockTime running_time, stream_time; guint64 offset, offset_end; gboolean all_headers; guint count; if (multifilesink->next_file != GST_MULTI_FILE_SINK_NEXT_KEY_UNIT_EVENT || !gst_video_event_is_force_key_unit (event)) goto out; gst_video_event_parse_downstream_force_key_unit (event, ×tamp, &stream_time, &running_time, &all_headers, &count); if (multifilesink->force_key_unit_count != -1 && multifilesink->force_key_unit_count == count) goto out; multifilesink->force_key_unit_count = count; if (multifilesink->file) { duration = GST_CLOCK_TIME_NONE; offset = offset_end = -1; filename = g_strdup_printf (multifilesink->filename, multifilesink->index); gst_multi_file_sink_close_file (multifilesink, NULL); gst_multi_file_sink_post_message_full (multifilesink, timestamp, duration, offset, offset_end, running_time, stream_time, filename); g_free (filename); } if (multifilesink->file == NULL) { if (!gst_multi_file_sink_open_next_file (multifilesink)) goto stdio_write_error; } break; } case GST_EVENT_EOS: if (multifilesink->aggregate_gops) { GstBuffer *buf = gst_buffer_new (); /* push key unit buffer to force writing out the pending GOP data */ GST_INFO_OBJECT (sink, "EOS, write pending GOP data"); GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT); gst_multi_file_sink_render (sink, buf); gst_buffer_unref (buf); } if (multifilesink->file) { gchar *filename; filename = g_strdup_printf (multifilesink->filename, multifilesink->index); gst_multi_file_sink_close_file (multifilesink, NULL); gst_multi_file_sink_post_message_from_time (multifilesink, GST_BASE_SINK (multifilesink)->segment.position, -1, filename); g_free (filename); } break; default: break; } out: return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); /* ERRORS */ stdio_write_error: { GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE, ("Error while writing to file."), (NULL)); gst_event_unref (event); return FALSE; } }
static GstFlowReturn mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux) { GstFlowReturn ret = GST_FLOW_OK; MpegTsPadData *best = NULL; GST_DEBUG_OBJECT (mux, "Pads collected"); if (G_UNLIKELY (mux->first)) { ret = mpegtsmux_create_streams (mux); if (G_UNLIKELY (ret != GST_FLOW_OK)) return ret; mpegtsdemux_prepare_srcpad (mux); mux->first = FALSE; } best = mpegtsmux_choose_best_stream (mux); if (best != NULL) { TsMuxProgram *prog = best->prog; GstBuffer *buf = best->queued_buf; gint64 pts = -1; gboolean delta = TRUE; if (prog == NULL) { GST_ELEMENT_ERROR (mux, STREAM, MUX, ("Stream on pad %" GST_PTR_FORMAT " is not associated with any program", COLLECT_DATA_PAD (best)), (NULL)); return GST_FLOW_ERROR; } if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) { GstEvent *event; event = check_pending_key_unit_event (mux->force_key_unit_event, &best->collect.segment, GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_FLAGS (buf), mux->pending_key_unit_ts); if (event) { GstClockTime running_time; guint count; GList *cur; mux->pending_key_unit_ts = GST_CLOCK_TIME_NONE; gst_event_replace (&mux->force_key_unit_event, NULL); gst_video_event_parse_downstream_force_key_unit (event, NULL, NULL, &running_time, NULL, &count); GST_INFO_OBJECT (mux, "pushing downstream force-key-unit event %d " "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event), GST_TIME_ARGS (running_time), count); gst_pad_push_event (mux->srcpad, event); /* output PAT */ mux->tsmux->last_pat_ts = -1; /* output PMT for each program */ for (cur = g_list_first (mux->tsmux->programs); cur != NULL; cur = g_list_next (cur)) { TsMuxProgram *program = (TsMuxProgram *) cur->data; program->last_pmt_ts = -1; } tsmux_program_set_pcr_stream (prog, NULL); } } if (G_UNLIKELY (prog->pcr_stream == NULL)) { /* Take the first data stream for the PCR */ GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best), "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)", MPEG_TS_PAD_DATA (best)->pid, MPEG_TS_PAD_DATA (best)->prog_id); /* Set the chosen PCR stream */ tsmux_program_set_pcr_stream (prog, best->stream); } g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); if (best->stream->is_video_stream) delta = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); GST_DEBUG_OBJECT (mux, "delta: %d", delta); GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best), "Chose stream for output (PID: 0x%04x)", best->pid); if (GST_CLOCK_TIME_IS_VALID (best->cur_ts)) { pts = GSTTIME_TO_MPEGTIME (best->cur_ts); GST_DEBUG_OBJECT (mux, "Buffer has TS %" GST_TIME_FORMAT " pts %" G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_ts), pts); } tsmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), buf, pts, -1, !delta); best->queued_buf = NULL; mux->is_delta = delta; while (tsmux_stream_bytes_in_buffer (best->stream) > 0) { if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) { /* Failed writing data for some reason. Set appropriate error */ GST_DEBUG_OBJECT (mux, "Failed to write data packet"); GST_ELEMENT_ERROR (mux, STREAM, MUX, ("Failed writing output data to stream %04x", best->stream->id), (NULL)); goto write_fail; } } if (prog->pcr_stream == best->stream) { mux->last_ts = best->last_ts; } } else { /* FIXME: Drain all remaining streams */ /* At EOS */ gst_pad_push_event (mux->srcpad, gst_event_new_eos ()); } return ret; write_fail: return mux->last_flow_ret; }