diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c index 6d07d023c0..3a86c0500e 100644 --- a/gst/mpegpsmux/mpegpsmux.c +++ b/gst/mpegpsmux/mpegpsmux.c @@ -709,6 +709,9 @@ new_packet_cb (guint8 * data, guint len, void *user_data) static gboolean mpegpsdemux_prepare_srcpad (MpegPsMux * mux) { + GValue val = { 0, }; + GList *headers, *l; + /* prepare the source pad for output */ GstEvent *new_seg = @@ -720,6 +723,21 @@ mpegpsdemux_prepare_srcpad (MpegPsMux * mux) /* gst_static_pad_template_get_caps (&mpegpsmux_src_factory); */ + headers = psmux_get_stream_headers (mux->psmux); + g_value_init (&val, GST_TYPE_ARRAY); + for (l = headers; l != NULL; l = l->next) { + GValue buf_val = { 0, }; + + g_value_init (&buf_val, GST_TYPE_BUFFER); + gst_value_take_buffer (&buf_val, GST_BUFFER (l->data)); + l->data = NULL; + gst_value_array_append_value (&val, &buf_val); + g_value_unset (&buf_val); + } + gst_caps_set_value (caps, "streamheader", &val); + g_value_unset (&val); + g_list_free (headers); + /* Set caps on src pad from our template and push new segment */ gst_pad_set_caps (mux->srcpad, caps); diff --git a/gst/mpegpsmux/psmux.c b/gst/mpegpsmux/psmux.c index 0a714d038a..44e32faf5b 100644 --- a/gst/mpegpsmux/psmux.c +++ b/gst/mpegpsmux/psmux.c @@ -141,6 +141,12 @@ psmux_free (PsMux * mux) } g_list_free (mux->streams); + if (mux->sys_header != NULL) + gst_buffer_unref (mux->sys_header); + + if (mux->psm != NULL) + gst_buffer_unref (mux->psm); + g_slice_free (PsMux, mux); } @@ -332,17 +338,23 @@ psmux_write_pack_header (PsMux * mux) return psmux_packet_out (mux); } -static gboolean -psmux_write_system_header (PsMux * mux) +static void +psmux_ensure_system_header (PsMux * mux) { + GstBuffer *buf; bits_buffer_t bw; guint len = 12 + (mux->nb_streams + (mux->nb_private_streams > 1 ? mux->nb_private_streams - 1 : 0)) * 3; GList *cur; gboolean private_hit = FALSE; + if (mux->sys_header != NULL) + return; + + buf = gst_buffer_new_and_alloc (len); + /* system_header_start_code */ - bits_initwrite (&bw, len, mux->packet_buf); + bits_initwrite (&bw, len, GST_BUFFER_DATA (buf)); /* system_header start code */ bits_write (&bw, 24, PSMUX_START_CODE_PREFIX); @@ -378,19 +390,36 @@ psmux_write_system_header (PsMux * mux) private_hit = TRUE; } - mux->packet_bytes_written = len; - return psmux_packet_out (mux); + GST_MEMDUMP ("System Header", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + + mux->sys_header = buf; } static gboolean -psmux_write_program_stream_map (PsMux * mux) +psmux_write_system_header (PsMux * mux) { + psmux_ensure_system_header (mux); + + memcpy (mux->packet_buf, GST_BUFFER_DATA (mux->sys_header), + GST_BUFFER_SIZE (mux->sys_header)); + mux->packet_bytes_written = GST_BUFFER_SIZE (mux->sys_header); + + return psmux_packet_out (mux); +} + +static void +psmux_ensure_program_stream_map (PsMux * mux) +{ + GstBuffer *buf; gint psm_size = 16, es_map_size = 0; bits_buffer_t bw; GList *cur; guint16 len; guint8 *pos; + if (mux->psm != NULL) + return; + /* pre-write the descriptor loop */ pos = mux->es_info_buf; for (cur = g_list_first (mux->streams); cur != NULL; cur = g_list_next (cur)) { @@ -412,7 +441,10 @@ psmux_write_program_stream_map (PsMux * mux) } psm_size += es_map_size; - bits_initwrite (&bw, psm_size, mux->packet_buf); + + buf = gst_buffer_new_and_alloc (psm_size); + + bits_initwrite (&bw, psm_size, GST_BUFFER_DATA (buf)); /* psm start code */ bits_write (&bw, 24, PSMUX_START_CODE_PREFIX); @@ -429,15 +461,44 @@ psmux_write_program_stream_map (PsMux * mux) /* program_stream_info empty */ bits_write (&bw, 16, es_map_size); /* elementary_stream_map_length */ + memcpy (bw.p_data + bw.i_data, mux->es_info_buf, es_map_size); /* CRC32 */ { - guint32 crc = calc_crc32 (mux->packet_buf, psm_size - 4); - guint8 *pos = mux->packet_buf + psm_size - 4; + guint32 crc = calc_crc32 (bw.p_data, psm_size - 4); + guint8 *pos = bw.p_data + psm_size - 4; psmux_put32 (&pos, crc); } - mux->packet_bytes_written = psm_size; + GST_MEMDUMP ("Program Stream Map", GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf)); + + mux->psm = buf; +} + +static gboolean +psmux_write_program_stream_map (PsMux * mux) +{ + psmux_ensure_program_stream_map (mux); + + memcpy (mux->packet_buf, GST_BUFFER_DATA (mux->psm), + GST_BUFFER_SIZE (mux->psm)); + mux->packet_bytes_written = GST_BUFFER_SIZE (mux->psm); + return psmux_packet_out (mux); } + +GList * +psmux_get_stream_headers (PsMux * mux) +{ + GList *list; + + psmux_ensure_system_header (mux); + psmux_ensure_program_stream_map (mux); + + list = g_list_append (NULL, gst_buffer_ref (mux->sys_header)); + list = g_list_append (list, gst_buffer_ref (mux->psm)); + + return list; +} diff --git a/gst/mpegpsmux/psmux.h b/gst/mpegpsmux/psmux.h index 5aacf94cec..3daa90af7e 100644 --- a/gst/mpegpsmux/psmux.h +++ b/gst/mpegpsmux/psmux.h @@ -93,6 +93,10 @@ struct PsMux { guint8 audio_bound; guint8 video_bound; guint32 rate_bound; + + /* stream headers */ + GstBuffer *sys_header; + GstBuffer *psm; }; /* create/free new muxer session */ @@ -109,6 +113,8 @@ PsMuxStream * psmux_create_stream (PsMux *mux, PsMuxStreamType stream_type); gboolean psmux_write_stream_packet (PsMux *mux, PsMuxStream *stream); gboolean psmux_write_end_code (PsMux *mux); +GList * psmux_get_stream_headers (PsMux *mux); + G_END_DECLS #endif