예제 #1
0
static void
new_packet_common_init (MpegTsMux * mux, GstBuffer * buf, guint8 * data,
    guint len)
{
  /* Packets should be at least 188 bytes, but check anyway */
  g_return_if_fail (len >= 2);

  if (!mux->streamheader_sent) {
    guint pid = ((data[1] & 0x1f) << 8) | data[2];
    /* if it's a PAT or a PMT */
    if (pid == 0x00 || (pid >= TSMUX_START_PMT_PID && pid < TSMUX_START_ES_PID)) {
      mux->streamheader =
          g_list_append (mux->streamheader, gst_buffer_copy (buf));
    } else if (mux->streamheader) {
      mpegtsdemux_set_header_on_caps (mux);
      mux->streamheader_sent = TRUE;
    }
  }

  /* Set the caps on the buffer only after possibly setting the stream headers
   * into the pad caps above */
  gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));

  if (mux->is_delta) {
    GST_LOG_OBJECT (mux, "marking as delta unit");
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
  } else {
    GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
    mux->is_delta = TRUE;
  }
}
예제 #2
0
static gboolean
new_packet_cb (guint8 * data, guint len, void *user_data, gint64 new_pcr)
{
  /* Called when the TsMux has prepared a packet for output. Return FALSE
   * on error */
  MpegTsMux *mux = (MpegTsMux *) user_data;
  GstBuffer *buf, *out_buf;
  GstFlowReturn ret;
  gfloat current_ts;
  gint64 m2ts_pcr, pcr_bytes, chunk_bytes;
  gint8 *temp_ptr;
  gint64 ts_rate;

  if (mux->m2ts_mode == TRUE) {
    /* Enters when the m2ts-mode is set true */
    buf = gst_buffer_new_and_alloc (M2TS_PACKET_LENGTH);
    if (mux->is_delta) {
      GST_LOG_OBJECT (mux, "marking as delta unit");
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
    } else {
      GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
      mux->is_delta = TRUE;
    }
    if (G_UNLIKELY (buf == NULL)) {
      mux->last_flow_ret = GST_FLOW_ERROR;
      return FALSE;
    }
    gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));

    /* copies the ts data of 188 bytes to the m2ts buffer at an offset 
       of 4 bytes of timestamp  */
    memcpy (GST_BUFFER_DATA (buf) + 4, data, len);

    if (new_pcr >= 0) {
      /*when there is a pcr value in ts data */
      pcr_bytes = 0;
      if (mux->first_pcr) {
        /*Incase of first pcr */
        /*writing the 4  byte timestamp value */
        GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), new_pcr);

        GST_LOG_OBJECT (mux, "Outputting a packet of length %d",
            M2TS_PACKET_LENGTH);
        ret = gst_pad_push (mux->srcpad, buf);
        if (G_UNLIKELY (ret != GST_FLOW_OK)) {
          mux->last_flow_ret = ret;
          return FALSE;
        }
        mux->first_pcr = FALSE;
        mux->previous_pcr = new_pcr;
        pcr_bytes = M2TS_PACKET_LENGTH;
      }
      chunk_bytes = gst_adapter_available (mux->adapter);

      if (G_UNLIKELY (chunk_bytes)) {
        /* calculate rate based on latest and previous pcr values */
        ts_rate = ((chunk_bytes * STANDARD_TIME_CLOCK) / (new_pcr -
                mux->previous_pcr));
        while (1) {
          /*loop till all the accumulated ts packets are transformed to 
             m2ts packets and pushed */
          current_ts = ((gfloat) mux->previous_pcr / STANDARD_TIME_CLOCK) +
              ((gfloat) pcr_bytes / ts_rate);
          m2ts_pcr = (((gint64) (STANDARD_TIME_CLOCK * current_ts / 300) &
                  TWO_POW_33_MINUS1) * 300) + ((gint64) (STANDARD_TIME_CLOCK *
                  current_ts) % 300);
          temp_ptr = (gint8 *) & m2ts_pcr;

          out_buf = gst_adapter_take_buffer (mux->adapter, M2TS_PACKET_LENGTH);
          if (G_UNLIKELY (!out_buf))
            break;
          gst_buffer_set_caps (out_buf, GST_PAD_CAPS (mux->srcpad));

          /*writing the 4  byte timestamp value */
          GST_WRITE_UINT32_BE (GST_BUFFER_DATA (out_buf), m2ts_pcr);

          GST_LOG_OBJECT (mux, "Outputting a packet of length %d",
              M2TS_PACKET_LENGTH);
          ret = gst_pad_push (mux->srcpad, out_buf);
          if (G_UNLIKELY (ret != GST_FLOW_OK)) {
            mux->last_flow_ret = ret;
            return FALSE;
          }
          pcr_bytes += M2TS_PACKET_LENGTH;
        }
        mux->previous_pcr = m2ts_pcr;
      }
    } else
      /* If theres no pcr in current ts packet then push the packet 
         to an adapter, which is used to create m2ts packets */
      gst_adapter_push (mux->adapter, buf);
  } else {
    /* In case of Normal Ts packets */
    GST_LOG_OBJECT (mux, "Outputting a packet of length %d", len);
    buf = gst_buffer_new_and_alloc (len);
    if (G_UNLIKELY (buf == NULL)) {
      mux->last_flow_ret = GST_FLOW_ERROR;
      return FALSE;
    }
    gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));

    memcpy (GST_BUFFER_DATA (buf), data, len);
    GST_BUFFER_TIMESTAMP (buf) = mux->last_ts;

    if (!mux->streamheader_sent) {
      guint pid = ((data[1] & 0x1f) << 8) | data[2];
      /* if it's a PAT or a PMT */
      if (pid == 0x00 ||
          (pid >= TSMUX_START_PMT_PID && pid < TSMUX_START_ES_PID)) {
        mux->streamheader =
            g_list_append (mux->streamheader, gst_buffer_copy (buf));
      } else if (mux->streamheader) {
        mpegtsdemux_set_header_on_caps (mux);
        mux->streamheader_sent = TRUE;
        /* don't unset the streamheaders by pushing old caps */
        gst_buffer_set_caps (buf, GST_PAD_CAPS (mux->srcpad));
      }
    }

    if (mux->is_delta) {
      GST_LOG_OBJECT (mux, "marking as delta unit");
      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
    } else {
      GST_DEBUG_OBJECT (mux, "marking as non-delta unit");
      mux->is_delta = TRUE;
    }

    ret = gst_pad_push (mux->srcpad, buf);
    if (G_UNLIKELY (ret != GST_FLOW_OK)) {
      mux->last_flow_ret = ret;
      return FALSE;
    }
  }

  return TRUE;
}