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