summaryrefslogtreecommitdiff
path: root/gst/mpegpsmux
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim.muller@collabora.co.uk>2011-09-25 23:57:34 +0100
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2011-12-11 00:13:51 +0000
commitad6ea8fbe99b48463bb2cd615f2e4e2e50feb020 (patch)
tree096a2e1b59f42aa7f41c3ebc037bd4101198098c /gst/mpegpsmux
parenteaeba16a56e849ef892970facea935c25b44fc41 (diff)
downloadgstreamer-plugins-bad-ad6ea8fbe99b48463bb2cd615f2e4e2e50feb020.tar.gz
mpegpsmux: put stream headers into output caps
Basic version with only the system header and the program stream map. An advanced version could include codec-specific bits like SPS/PPS too. This is useful in connection with e.g. multifilesink to make sure new files always start with the stream headers.
Diffstat (limited to 'gst/mpegpsmux')
-rw-r--r--gst/mpegpsmux/mpegpsmux.c18
-rw-r--r--gst/mpegpsmux/psmux.c81
-rw-r--r--gst/mpegpsmux/psmux.h6
3 files changed, 95 insertions, 10 deletions
diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c
index 6d07d023c..3a86c0500 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 0a714d038..44e32faf5 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 5aacf94ce..3daa90af7 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