예제 #1
0
static GstFlowReturn
mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux)
{
  /* main muxing function */

  GstFlowReturn ret = GST_FLOW_OK;
  MpegPsPadData *best = NULL;

  GST_DEBUG_OBJECT (mux, "Pads collected");

  if (mux->first) {             /* process block for the first mux */
    /* iterate through the collect pads and add streams to @mux */
    ret = mpegpsmux_create_streams (mux);
    /* Assumption : all pads are already added at this time */

    if (G_UNLIKELY (ret != GST_FLOW_OK))
      return ret;

    best = mpegpsmux_choose_best_stream (mux);

    /* prepare the src pad (output), return if failed */
    if (!mpegpsdemux_prepare_srcpad (mux)) {
      GST_DEBUG_OBJECT (mux, "Failed to send new segment");
      goto new_seg_fail;
    }

    mux->first = FALSE;
  } else {
    best = mpegpsmux_choose_best_stream (mux);
  }

  if (best != NULL) {
    /* @*buf : the buffer to be processed */
    GstBuffer *buf = best->queued_buf;
    gint64 pts = -1;

    g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);

    GST_DEBUG_OBJECT (mux,
        "Chose stream from pad %" GST_PTR_FORMAT " for output (PID: 0x%04x)",
        best->collect.pad, best->stream_id);

    /* set timestamp */
    if (GST_CLOCK_TIME_IS_VALID (best->cur_ts)) {
      pts = GSTTIME_TO_MPEGTIME (best->cur_ts); /* @pts: current timestamp */
      GST_DEBUG_OBJECT (mux, "Buffer has TS %" GST_TIME_FORMAT " pts %"
          G_GINT64_FORMAT, GST_TIME_ARGS (best->cur_ts), pts);
    }

    /* give the buffer to libpsmux for processing */
    psmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf),
        GST_BUFFER_SIZE (buf), buf, pts, -1);
    best->queued_buf = NULL;

    /* write the data from libpsmux to stream */
    while (psmux_stream_bytes_in_buffer (best->stream) > 0) {
      GST_LOG_OBJECT (mux, "Before @psmux_write_stream_packet");
      if (!psmux_write_stream_packet (mux->psmux, best->stream)) {
        GST_DEBUG_OBJECT (mux, "Failed to write data packet");
        goto write_fail;
      }
    }
    mux->last_ts = best->last_ts;
  } else {
    /* FIXME: Drain all remaining streams */
    /* At EOS */
    if (psmux_write_end_code (mux->psmux)) {
      GST_WARNING_OBJECT (mux, "Writing MPEG PS Program end code failed.");
    }
    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;
}
예제 #2
0
static GstFlowReturn
mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux)
{
  /* main muxing function */

  GstFlowReturn ret = GST_FLOW_OK;
  MpegPsPadData *best = NULL;
  gboolean keyunit;

  GST_DEBUG_OBJECT (mux, "Pads collected");

  if (mux->first) {             /* process block for the first mux */
    /* iterate through the collect pads and add streams to @mux */
    ret = mpegpsmux_create_streams (mux);
    /* Assumption : all pads are already added at this time */

    if (G_UNLIKELY (ret != GST_FLOW_OK))
      return ret;

    best = mpegpsmux_choose_best_stream (mux);

    /* prepare the src pad (output), return if failed */
    if (!mpegpsdemux_prepare_srcpad (mux)) {
      GST_DEBUG_OBJECT (mux, "Failed to send new segment");
      goto new_seg_fail;
    }

    mux->first = FALSE;
  } else {
    best = mpegpsmux_choose_best_stream (mux);
  }

  if (best != NULL) {
    GstBuffer *buf = best->queued.buf;
    gint64 pts, dts;

    g_assert (buf != NULL);

    GST_LOG_OBJECT (mux,
        "Chose stream from pad %" GST_PTR_FORMAT " for output (PID: 0x%04x): "
        "adjusted pts: %" GST_TIME_FORMAT ", dts: %" GST_TIME_FORMAT,
        best->collect.pad, best->stream_id,
        GST_TIME_ARGS (best->queued.pts), GST_TIME_ARGS (best->queued.dts));

    /* and convert to mpeg time stamps */
    pts = GSTTIME_TO_MPEGTIME (best->queued.pts);
    dts = GSTTIME_TO_MPEGTIME (best->queued.dts);

    /* start of new GOP? */
    keyunit = !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);

    if (keyunit && best->stream_id == mux->video_stream_id
        && mux->gop_list != NULL) {
      ret = mpegpsmux_push_gop_list (mux);
      if (ret != GST_FLOW_OK)
        goto done;
    }

    /* give the buffer to libpsmux for processing */
    psmux_stream_add_data (best->stream, buf, pts, dts, keyunit);

    best->queued.buf = NULL;

    /* write the data from libpsmux to stream */
    while (psmux_stream_bytes_in_buffer (best->stream) > 0) {
      GST_LOG_OBJECT (mux, "Before @psmux_write_stream_packet");
      if (!psmux_write_stream_packet (mux->psmux, best->stream)) {
        GST_DEBUG_OBJECT (mux, "Failed to write data packet");
        goto write_fail;
      }
    }
    mux->last_ts = best->last_ts;
  } else {
    /* FIXME: Drain all remaining streams */
    /* At EOS */
    if (mux->gop_list != NULL)
      mpegpsmux_push_gop_list (mux);

    if (!psmux_write_end_code (mux->psmux)) {
      GST_WARNING_OBJECT (mux, "Writing MPEG PS Program end code failed.");
    }
    gst_pad_push_event (mux->srcpad, gst_event_new_eos ());

    ret = GST_FLOW_EOS;
  }

done:

  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;
}