static GstFlowReturn mpegtsmux_collected (GstCollectPads * pads, MpegTsMux * mux) { GstFlowReturn ret = GST_FLOW_OK; MpegTsPadData *best = NULL; GST_DEBUG_OBJECT (mux, "Pads collected"); if (mux->first) { ret = mpegtsmux_create_streams (mux); if (G_UNLIKELY (ret != GST_FLOW_OK)) return ret; best = mpegtsmux_choose_best_stream (mux); if (mux->pcr_stream == NULL) { if (best) { /* Take the first data stream for the PCR */ GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best), "Use stream as PCR"); mux->pcr_stream = best->stream; } } /* Set the chosen PCR stream */ g_return_val_if_fail (mux->pcr_stream != NULL, GST_FLOW_ERROR); tsmux_program_set_pcr_stream (mux->program, mux->pcr_stream); if (!mpegtsdemux_prepare_srcpad (mux)) { GST_DEBUG_OBJECT (mux, "Failed to send new segment"); goto new_seg_fail; } mux->first = FALSE; } else { best = mpegtsmux_choose_best_stream (mux); } if (best != NULL) { GstBuffer *buf = best->queued_buf; gint64 pts = -1; g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); 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); best->queued_buf = NULL; while (tsmux_stream_bytes_in_buffer (best->stream) > 0) { if (!tsmux_write_stream_packet (mux->tsmux, best->stream)) { GST_DEBUG_OBJECT (mux, "Failed to write data packet"); goto write_fail; } } if (mux->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; new_seg_fail: return GST_FLOW_ERROR; write_fail: /* FIXME: Failed writing data for some reason. Should set appropriate error */ return mux->last_flow_ret; }
static GstFlowReturn mpegtsmux_collected (GstCollectPads * pads, MpegTsMux * mux) { GstFlowReturn ret = GST_FLOW_OK; MpegTsPadData *best = NULL; GST_DEBUG_OBJECT (mux, "Pads collected"); if (mux->first) { ret = mpegtsmux_create_streams (mux); if (G_UNLIKELY (ret != GST_FLOW_OK)) return ret; best = mpegtsmux_choose_best_stream (mux); if (!mpegtsdemux_prepare_srcpad (mux)) { GST_DEBUG_OBJECT (mux, "Failed to send new segment"); goto new_seg_fail; } mux->first = FALSE; } else { 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 is not associated with " "any program"), (NULL)); return GST_FLOW_ERROR; } if (G_UNLIKELY (prog->pcr_stream == NULL)) { if (best) { /* 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)) { GST_DEBUG_OBJECT (mux, "Failed to write data packet"); 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; new_seg_fail: return GST_FLOW_ERROR; write_fail: /* FIXME: Failed writing data for some reason. Should set appropriate error */ return mux->last_flow_ret; }
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; }