From c056ecb02b0c194ec6647cd8d5fb5576b39e42be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 31 Dec 2012 19:42:03 +0000 Subject: [PATCH] mpegpsmux: port to 0.11 Naive port. Barely tested. --- configure.ac | 2 +- gst/mpegpsmux/mpegpsmux.c | 139 +++++++++++---------------------- gst/mpegpsmux/mpegpsmux_aac.c | 42 +++++----- gst/mpegpsmux/mpegpsmux_h264.c | 84 +++++++++++--------- gst/mpegpsmux/psmux.c | 45 ++++++----- gst/mpegpsmux/psmuxstream.c | 64 ++++++--------- gst/mpegpsmux/psmuxstream.h | 20 ++--- 7 files changed, 167 insertions(+), 229 deletions(-) diff --git a/configure.ac b/configure.ac index 34a9d92090..3b3a3a48c6 100644 --- a/configure.ac +++ b/configure.ac @@ -315,7 +315,7 @@ GST_PLUGINS_NONPORTED=" aiff \ freeverb \ hdvparse ivfparse jp2kdecimator \ kate librfb \ - mpegpsmux mve mythtv nsf nuvdemux \ + mve mythtv nsf nuvdemux \ patchdetect real \ sdi stereo tta videofilters \ videomeasure videosignal vmnc \ diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c index 17f6f36fcd..996550bf73 100644 --- a/gst/mpegpsmux/mpegpsmux.c +++ b/gst/mpegpsmux/mpegpsmux.c @@ -93,37 +93,20 @@ static void gst_mpegpsmux_set_property (GObject * object, guint prop_id, static void gst_mpegpsmux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void mpegpsmux_dispose (GObject * object); +static void mpegpsmux_finalize (GObject * object); static gboolean new_packet_cb (guint8 * data, guint len, void *user_data); -static void release_buffer_cb (guint8 * data, void *user_data); static gboolean mpegpsdemux_prepare_srcpad (MpegPsMux * mux); static GstFlowReturn mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux); static GstPad *mpegpsmux_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name); + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void mpegpsmux_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn mpegpsmux_change_state (GstElement * element, GstStateChange transition); -GST_BOILERPLATE (MpegPsMux, mpegpsmux, GstElement, GST_TYPE_ELEMENT); - -static void -mpegpsmux_base_init (gpointer g_class) -{ - - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&mpegpsmux_sink_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&mpegpsmux_src_factory)); - - gst_element_class_set_static_metadata (element_class, - "MPEG Program Stream Muxer", "Codec/Muxer", - "Multiplexes media streams into an MPEG Program Stream", - "Lin YANG "); -} +#define parent_class mpegpsmux_parent_class +G_DEFINE_TYPE (MpegPsMux, mpegpsmux, GST_TYPE_ELEMENT); static void mpegpsmux_class_init (MpegPsMuxClass * klass) @@ -131,9 +114,9 @@ mpegpsmux_class_init (MpegPsMuxClass * klass) GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_mpegpsmux_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_mpegpsmux_get_property); - gobject_class->dispose = mpegpsmux_dispose; + gobject_class->set_property = gst_mpegpsmux_set_property; + gobject_class->get_property = gst_mpegpsmux_get_property; + gobject_class->finalize = mpegpsmux_finalize; gstelement_class->request_new_pad = mpegpsmux_request_new_pad; gstelement_class->release_pad = mpegpsmux_release_pad; @@ -143,10 +126,20 @@ mpegpsmux_class_init (MpegPsMuxClass * klass) g_param_spec_boolean ("aggregate-gops", "Aggregate GOPs", "Whether to aggregate GOPs and push them out as buffer lists", DEFAULT_AGGREGATE_GOPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&mpegpsmux_sink_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&mpegpsmux_src_factory)); + + gst_element_class_set_static_metadata (gstelement_class, + "MPEG Program Stream Muxer", "Codec/Muxer", + "Multiplexes media streams into an MPEG Program Stream", + "Lin YANG "); } static void -mpegpsmux_init (MpegPsMux * mux, MpegPsMuxClass * g_class) +mpegpsmux_init (MpegPsMux * mux) { mux->srcpad = gst_pad_new_from_static_template (&mpegpsmux_src_factory, "src"); @@ -166,7 +159,7 @@ mpegpsmux_init (MpegPsMux * mux, MpegPsMuxClass * g_class) } static void -mpegpsmux_dispose (GObject * object) +mpegpsmux_finalize (GObject * object) { MpegPsMux *mux = GST_MPEG_PSMUX (object); @@ -184,7 +177,7 @@ mpegpsmux_dispose (GObject * object) mux->gop_list = NULL; } - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); + G_OBJECT_CLASS (mpegpsmux_parent_class)->finalize (object); } static void @@ -219,25 +212,17 @@ gst_mpegpsmux_get_property (GObject * object, guint prop_id, } } -static void -release_buffer_cb (guint8 * data, void *user_data) -{ - /* release a given buffer. callback func */ - - GstBuffer *buf = (GstBuffer *) user_data; - gst_buffer_unref (buf); -} - static GstFlowReturn mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad) { /* Create a steam. Fill in codec specific information */ GstFlowReturn ret = GST_FLOW_ERROR; - GstCaps *caps = gst_pad_get_negotiated_caps (pad); + GstCaps *caps; GstStructure *s; gboolean is_video = FALSE; + caps = gst_pad_get_current_caps (pad); if (caps == NULL) { GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing"); return GST_FLOW_NOT_NEGOTIATED; @@ -266,8 +251,8 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad) value = gst_structure_get_value (s, "codec_data"); if (value) { ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value)); - GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)", - GST_BUFFER_SIZE (ps_data->codec_data)); + GST_DEBUG_OBJECT (pad, "%" G_GSIZE_FORMAT " bytes of codec data", + gst_buffer_get_size (ps_data->codec_data)); ps_data->prepare_func = mpegpsmux_prepare_h264; } else { ps_data->codec_data = NULL; @@ -302,8 +287,8 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad) value = gst_structure_get_value (s, "codec_data"); if (value) { ps_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value)); - GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)", - GST_BUFFER_SIZE (ps_data->codec_data)); + GST_DEBUG_OBJECT (pad, "%" G_GSIZE_FORMAT " bytes of codec data", + gst_buffer_get_size (ps_data->codec_data)); ps_data->prepare_func = mpegpsmux_prepare_aac; } else { ps_data->codec_data = NULL; @@ -347,8 +332,6 @@ mpegpsmux_create_stream (MpegPsMux * mux, MpegPsPadData * ps_data, GstPad * pad) gst_structure_get_int (s, "channels", &ps_data->stream->audio_channels); gst_structure_get_int (s, "bitrate", &ps_data->stream->audio_bitrate); - psmux_stream_set_buffer_release_func (ps_data->stream, release_buffer_cb); - ret = GST_FLOW_OK; if (is_video && mux->video_stream_id == 0) { @@ -483,7 +466,7 @@ mpegpsmux_push_gop_list (MpegPsMux * mux) g_assert (mux->gop_list != NULL); GST_DEBUG_OBJECT (mux, "Sending pending GOP of %u buffers", - gst_buffer_list_n_groups (mux->gop_list)); + gst_buffer_list_length (mux->gop_list)); flow = gst_pad_push_list (mux->srcpad, mux->gop_list); mux->gop_list = NULL; return flow; @@ -549,9 +532,9 @@ mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux) goto done; } + /* FIXME: porting: add DTS */ /* give the buffer to libpsmux for processing */ - psmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf), buf, pts, -1, keyunit); + psmux_stream_add_data (best->stream, buf, pts, -1, keyunit); best->queued_buf = NULL; @@ -588,9 +571,8 @@ write_fail: static GstPad * mpegpsmux_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name) + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { - MpegPsMux *mux = GST_MPEG_PSMUX (element); GstPad *pad = NULL; MpegPsPadData *pad_data = NULL; @@ -652,26 +634,6 @@ mpegpsmux_release_pad (GstElement * element, GstPad * pad) gst_collect_pads_remove_pad (mux->collect, pad); } -static void -add_buffer_to_goplist (MpegPsMux * mux, GstBuffer * buf) -{ - GstBufferListIterator *it; - - if (mux->gop_list == NULL) - mux->gop_list = gst_buffer_list_new (); - - it = gst_buffer_list_iterate (mux->gop_list); - - /* move iterator to end */ - while (gst_buffer_list_iterator_next_group (it)) { - /* .. */ - } - - gst_buffer_list_iterator_add_group (it); - gst_buffer_list_iterator_add (it, buf); - gst_buffer_list_iterator_free (it); -} - static gboolean new_packet_cb (guint8 * data, guint len, void *user_data) { @@ -683,18 +645,17 @@ new_packet_cb (guint8 * data, guint len, void *user_data) GstFlowReturn ret; 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); + data = g_memdup (data, len); + buf = gst_buffer_new_wrapped (data, len); + GST_BUFFER_TIMESTAMP (buf) = mux->last_ts; if (mux->aggregate_gops) { - add_buffer_to_goplist (mux, buf); + if (mux->gop_list == NULL) + mux->gop_list = gst_buffer_list_new (); + + gst_buffer_list_add (mux->gop_list, buf); return TRUE; } @@ -708,22 +669,17 @@ new_packet_cb (guint8 * data, guint len, void *user_data) return TRUE; } +/* prepare the source pad for output */ static gboolean mpegpsdemux_prepare_srcpad (MpegPsMux * mux) { + GstSegment segment; GValue val = { 0, }; GList *headers, *l; + GstCaps *caps; - /* prepare the source pad for output */ - - GstEvent *new_seg = - gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0); - GstCaps *caps = gst_caps_new_simple ("video/mpeg", - "mpegversion", G_TYPE_INT, 2, - "systemstream", G_TYPE_BOOLEAN, TRUE, - NULL); - -/* gst_static_pad_template_get_caps (&mpegpsmux_src_factory); */ + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 2, "systemstream", G_TYPE_BOOLEAN, TRUE, NULL); headers = psmux_get_stream_headers (mux->psmux); g_value_init (&val, GST_TYPE_ARRAY); @@ -740,13 +696,12 @@ mpegpsdemux_prepare_srcpad (MpegPsMux * mux) 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); + /* Set caps on src pad and push new segment */ + gst_pad_push_event (mux->srcpad, gst_event_new_caps (caps)); + gst_caps_unref (caps); - if (!gst_pad_push_event (mux->srcpad, new_seg)) { - GST_WARNING_OBJECT (mux, "New segment event was not handled"); - return FALSE; - } + gst_segment_init (&segment, GST_FORMAT_BYTES); + gst_pad_push_event (mux->srcpad, gst_event_new_segment (&segment)); return TRUE; } diff --git a/gst/mpegpsmux/mpegpsmux_aac.c b/gst/mpegpsmux/mpegpsmux_aac.c index 177d3e56c5..3f7b0cbcbd 100644 --- a/gst/mpegpsmux/mpegpsmux_aac.c +++ b/gst/mpegpsmux/mpegpsmux_aac.c @@ -95,24 +95,28 @@ GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug); GstBuffer * mpegpsmux_prepare_aac (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux) { - guint8 adts_header[7] = { 0, }; - GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 7); - gsize out_offset = 0; + GstBuffer *out_buf; + GstMemory *mem; + gsize out_size; + guint8 *adts_header, codec_data[2]; guint8 rate_idx = 0, channels = 0, obj_type = 0; GST_DEBUG_OBJECT (mux, "Preparing AAC buffer for output"); - /* We want the same metadata */ - gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL); + adts_header = g_malloc0 (7); + + /* We want the same data and metadata, and then prepend some bytes */ + out_buf = gst_buffer_copy (buf); + out_size = gst_buffer_get_size (buf) + 7; + + gst_buffer_extract (data->codec_data, 0, codec_data, 2); /* Generate ADTS header */ - obj_type = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0xC) >> 2; + obj_type = (codec_data[0] & 0xC) >> 2; obj_type++; - rate_idx = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0x3) << 1; - rate_idx |= - (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x80) >> 7; - channels = - (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x78) >> 3; + rate_idx = (codec_data[0] & 0x3) << 1; + rate_idx |= (codec_data[1] & 0x80) >> 7; + channels = (codec_data[1] & 0x78) >> 3; GST_DEBUG_OBJECT (mux, "Rate index %u, channels %u, object type %u", rate_idx, channels, obj_type); /* Sync point over a full byte */ @@ -129,24 +133,20 @@ mpegpsmux_prepare_aac (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux) /* channels continued over next 2 bits + 4 bits at zero */ adts_header[3] = (channels & 0x3) << 6; /* frame size over last 2 bits */ - adts_header[3] |= (GST_BUFFER_SIZE (out_buf) & 0x1800) >> 11; + adts_header[3] |= (gst_buffer_get_size (out_buf) & 0x1800) >> 11; /* frame size continued over full byte */ - adts_header[4] = (GST_BUFFER_SIZE (out_buf) & 0x1FF8) >> 3; + adts_header[4] = (out_size & 0x1FF8) >> 3; /* frame size continued first 3 bits */ - adts_header[5] = (GST_BUFFER_SIZE (out_buf) & 0x7) << 5; + adts_header[5] = (out_size & 0x7) << 5; /* buffer fullness (0x7FF for VBR) over 5 last bits */ adts_header[5] |= 0x1F; /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for * number of raw data blocks */ adts_header[6] = 0xFC; - /* Insert ADTS header */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, adts_header, 7); - out_offset += 7; - - /* Now copy complete frame */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); + /* Prepend ADTS header */ + mem = gst_memory_new_wrapped (0, adts_header, 7, 0, 7, adts_header, g_free); + gst_buffer_prepend_memory (out_buf, mem); return out_buf; } diff --git a/gst/mpegpsmux/mpegpsmux_h264.c b/gst/mpegpsmux/mpegpsmux_h264.c index d3d5f84f2e..35189bb6af 100644 --- a/gst/mpegpsmux/mpegpsmux_h264.c +++ b/gst/mpegpsmux/mpegpsmux_h264.c @@ -87,6 +87,7 @@ #endif #include "mpegpsmux_h264.h" +#include #include GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug); @@ -95,32 +96,37 @@ GST_DEBUG_CATEGORY_EXTERN (mpegpsmux_debug); GstBuffer * mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux) { + GstByteWriter bw; + GstMapInfo codec_data, map; guint8 nal_length_size = 0; - guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 }; - GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2); - gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0; - gsize out_offset = 0, in_offset = 0; + GstBuffer *out_buf; + guint8 nb_sps = 0, nb_pps = 0; + gint offset = 4, i = 0; + gsize in_offset; GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output"); - /* We want the same metadata */ - gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL); + /* FIXME: are we prepending SPS/PPS in front of every single buffer? + * (should only be in front of keyframes really, if at all) */ + /* FIXME: create a byte-stream version of SPS/PPS once in set_caps */ + if (!gst_buffer_map (data->codec_data, &codec_data, GST_MAP_READ)) + return NULL; + + gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buf) * 2, FALSE); /* Get NAL length size */ - nal_length_size = - (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x03) + 1; + nal_length_size = (codec_data.data[offset] & 0x03) + 1; GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes", nal_length_size); offset++; /* Generate SPS */ - nb_sps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x1f; + nb_sps = codec_data.data[offset] & 0x1f; GST_DEBUG_OBJECT (mux, "we have %d Sequence Parameter Set", nb_sps); offset++; /* For each SPS */ for (i = 0; i < nb_sps; i++) { - guint16 sps_size = - GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset); + guint16 sps_size = GST_READ_UINT16_BE (codec_data.data + offset); GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size); @@ -128,24 +134,21 @@ mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux) offset += 2; /* Fake a start code */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4); - out_offset += 4; - /* Now push the SPS */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, - GST_BUFFER_DATA (data->codec_data) + offset, sps_size); + gst_byte_writer_put_uint32_be (&bw, 0x00000001); + + /* Now push the SPS */ + gst_byte_writer_put_data (&bw, codec_data.data + offset, sps_size); - out_offset += sps_size; offset += sps_size; } - nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset); + nb_pps = codec_data.data[offset]; GST_LOG_OBJECT (mux, "we have %d Picture Parameter Set", nb_sps); offset++; /* For each PPS */ for (i = 0; i < nb_pps; i++) { - gint pps_size = - GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset); + gint pps_size = GST_READ_UINT16_BE (codec_data.data + offset); GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size); @@ -153,47 +156,52 @@ mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux) offset += 2; /* Fake a start code */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4); - out_offset += 4; - /* Now push the PPS */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, - GST_BUFFER_DATA (data->codec_data) + offset, pps_size); + gst_byte_writer_put_uint32_be (&bw, 0x00000001); + + /* Now push the PPS */ + gst_byte_writer_put_data (&bw, codec_data.data + offset, pps_size); - out_offset += pps_size; offset += pps_size; } - while (in_offset < GST_BUFFER_SIZE (buf) && - out_offset < GST_BUFFER_SIZE (out_buf) - 4) { + gst_buffer_unmap (data->codec_data, &codec_data); + + if (!gst_buffer_map (buf, &map, GST_MAP_READ)) + return NULL; + + /* now process NALs and change them to byte-stream format */ + in_offset = 0; + while (in_offset < map.size) { guint32 nal_size = 0; switch (nal_length_size) { case 1: - nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset); + nal_size = GST_READ_UINT8 (map.data + in_offset); break; case 2: - nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset); + nal_size = GST_READ_UINT16_BE (map.data + in_offset); break; case 4: - nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset); + nal_size = GST_READ_UINT32_BE (map.data + in_offset); break; default: GST_WARNING_OBJECT (mux, "unsupported NAL length size %u", nal_length_size); + break; } in_offset += nal_length_size; /* Generate an Elementary stream buffer by inserting a startcode */ - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4); - out_offset += 4; - memcpy (GST_BUFFER_DATA (out_buf) + out_offset, - GST_BUFFER_DATA (buf) + in_offset, - MIN (nal_size, GST_BUFFER_SIZE (out_buf) - out_offset)); + gst_byte_writer_put_uint32_be (&bw, 0x00000001); + gst_byte_writer_put_data (&bw, map.data + in_offset, + MIN (nal_size, map.size - in_offset)); in_offset += nal_size; - out_offset += nal_size; } - GST_BUFFER_SIZE (out_buf) = out_offset; + out_buf = gst_byte_writer_reset_and_get_buffer (&bw); + + /* We want the same metadata */ + gst_buffer_copy_into (out_buf, buf, GST_BUFFER_COPY_METADATA, 0, 0); return out_buf; } diff --git a/gst/mpegpsmux/psmux.c b/gst/mpegpsmux/psmux.c index 7e757a4c30..fbe3fe595e 100644 --- a/gst/mpegpsmux/psmux.c +++ b/gst/mpegpsmux/psmux.c @@ -341,20 +341,19 @@ psmux_write_pack_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; + guint8 *data; if (mux->sys_header != NULL) return; - buf = gst_buffer_new_and_alloc (len); + data = g_malloc (len); - /* system_header_start_code */ - bits_initwrite (&bw, len, GST_BUFFER_DATA (buf)); + bits_initwrite (&bw, len, data); /* system_header start code */ bits_write (&bw, 24, PSMUX_START_CODE_PREFIX); @@ -374,8 +373,7 @@ psmux_ensure_system_header (PsMux * mux) bits_write (&bw, 1, 0); /* packet_rate_restriction_flag */ bits_write (&bw, 7, 0x7f); /* reserved_bits */ - for (cur = g_list_first (mux->streams), private_hit = FALSE; cur != NULL; - cur = g_list_next (cur)) { + for (cur = mux->streams, private_hit = FALSE; cur != NULL; cur = cur->next) { PsMuxStream *stream = (PsMuxStream *) cur->data; if (private_hit && stream->stream_id == PSMUX_EXTENDED_STREAM) @@ -390,19 +388,22 @@ psmux_ensure_system_header (PsMux * mux) private_hit = TRUE; } - GST_MEMDUMP ("System Header", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + GST_MEMDUMP ("System Header", data, len); - mux->sys_header = buf; + mux->sys_header = gst_buffer_new_wrapped (data, len); } static gboolean psmux_write_system_header (PsMux * mux) { + GstMapInfo map; + 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); + gst_buffer_map (mux->sys_header, &map, GST_MAP_READ); + memcpy (mux->packet_buf, map.data, map.size); + mux->packet_bytes_written = map.size; + gst_buffer_unmap (mux->sys_header, &map); return psmux_packet_out (mux); } @@ -410,19 +411,19 @@ psmux_write_system_header (PsMux * 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; + guint8 *data; 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)) { + for (cur = mux->streams; cur != NULL; cur = cur->next) { PsMuxStream *stream = (PsMuxStream *) cur->data; len = 0; @@ -442,9 +443,9 @@ psmux_ensure_program_stream_map (PsMux * mux) psm_size += es_map_size; - buf = gst_buffer_new_and_alloc (psm_size); + data = g_malloc (psm_size); - bits_initwrite (&bw, psm_size, GST_BUFFER_DATA (buf)); + bits_initwrite (&bw, psm_size, data); /* psm start code */ bits_write (&bw, 24, PSMUX_START_CODE_PREFIX); @@ -471,20 +472,22 @@ psmux_ensure_program_stream_map (PsMux * mux) psmux_put32 (&pos, crc); } - GST_MEMDUMP ("Program Stream Map", GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); + GST_MEMDUMP ("Program Stream Map", data, psm_size); - mux->psm = buf; + mux->psm = gst_buffer_new_wrapped (data, psm_size); } static gboolean psmux_write_program_stream_map (PsMux * mux) { + GstMapInfo map; + 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); + gst_buffer_map (mux->psm, &map, GST_MAP_READ); + memcpy (mux->packet_buf, map.data, map.size); + mux->packet_bytes_written = map.size; + gst_buffer_unmap (mux->psm, &map); return psmux_packet_out (mux); } diff --git a/gst/mpegpsmux/psmuxstream.c b/gst/mpegpsmux/psmuxstream.c index 68c39e37e3..ce66b2f71a 100644 --- a/gst/mpegpsmux/psmuxstream.c +++ b/gst/mpegpsmux/psmuxstream.c @@ -174,8 +174,6 @@ psmux_stream_new (PsMux * mux, PsMuxStreamType stream_type) stream->cur_pes_payload_size = 0; - stream->buffer_release = NULL; - stream->pts = -1; stream->dts = -1; stream->last_pts = -1; @@ -215,31 +213,13 @@ psmux_stream_free (PsMuxStream * stream) g_slice_free (PsMuxStream, stream); } -/** - * psmux_stream_set_buffer_release_func: - * @stream: a #PsMuxStream - * @func: the new #PsMuxStreamBufferReleaseFunc - * - * Set the function that will be called when a a piece of data fed to @stream - * with psmux_stream_add_data() can be freed. @func will be called with user - * data as provided with the call to psmux_stream_add_data(). - */ -void -psmux_stream_set_buffer_release_func (PsMuxStream * stream, - PsMuxStreamBufferReleaseFunc func) -{ - g_return_if_fail (stream != NULL); - - stream->buffer_release = func; -} - /* Advance the current packet stream position by len bytes. * Mustn't consume more than available in the current packet */ static void psmux_stream_consume (PsMuxStream * stream, guint len) { g_assert (stream->cur_buffer != NULL); - g_assert (len <= stream->cur_buffer->size - stream->cur_buffer_consumed); + g_assert (len <= stream->cur_buffer->map.size - stream->cur_buffer_consumed); stream->cur_buffer_consumed += len; stream->bytes_avail -= len; @@ -250,15 +230,12 @@ psmux_stream_consume (PsMuxStream * stream, guint len) if (stream->cur_buffer->pts != -1) stream->last_pts = stream->cur_buffer->pts; - if (stream->cur_buffer_consumed == stream->cur_buffer->size) { + if (stream->cur_buffer_consumed == stream->cur_buffer->map.size) { /* Current packet is completed, move along */ stream->buffers = g_list_delete_link (stream->buffers, stream->buffers); - if (stream->buffer_release) { - stream->buffer_release (stream->cur_buffer->data, - stream->cur_buffer->user_data); - } - + gst_buffer_unmap (stream->cur_buffer->buf, &stream->cur_buffer->map); + gst_buffer_unref (stream->cur_buffer->buf); g_slice_free (PsMuxStreamBuffer, stream->cur_buffer); stream->cur_buffer = NULL; } @@ -346,8 +323,8 @@ psmux_stream_get_data (PsMuxStream * stream, guint8 * buf, guint len) } /* Take as much as we can from the current buffer */ - avail = stream->cur_buffer->size - stream->cur_buffer_consumed; - cur = stream->cur_buffer->data + stream->cur_buffer_consumed; + avail = stream->cur_buffer->map.size - stream->cur_buffer_consumed; + cur = stream->cur_buffer->map.data + stream->cur_buffer_consumed; if (avail < w) { memcpy (buf, cur, avail); psmux_stream_consume (stream, avail); @@ -417,7 +394,7 @@ psmux_stream_find_pts_dts_within (PsMuxStream * stream, guint bound, /* FIXME: This isn't quite correct - if the 'bound' is within this * buffer, we don't know if the timestamp is before or after the split * so we shouldn't return it */ - if (bound <= curbuf->size) { + if (bound <= curbuf->map.size) { *pts = curbuf->pts; *dts = curbuf->dts; return; @@ -430,7 +407,7 @@ psmux_stream_find_pts_dts_within (PsMuxStream * stream, guint bound, return; } - bound -= curbuf->size; + bound -= curbuf->map.size; } } @@ -498,9 +475,7 @@ psmux_stream_write_pes_header (PsMuxStream * stream, guint8 * data) /** * psmux_stream_add_data: * @stream: a #PsMuxStream - * @data: data to add - * @len: length of @data - * @user_data: user data to pass to release func + * @buffer: (transfer full): buffer with data to add * @pts: PTS of access unit in @data * @dts: DTS of access unit in @data * @@ -508,21 +483,25 @@ psmux_stream_write_pes_header (PsMuxStream * stream, guint8 * data) * timestamp (against a 90Hz clock) of the first access unit in @data. A * timestamp of -1 for @pts or @dts means unknown. * - * @user_data will be passed to the release function as set with - * psmux_stream_set_buffer_release_func() when @data can be freed. + * This function takes ownership of @buffer. */ void -psmux_stream_add_data (PsMuxStream * stream, guint8 * data, guint len, - void *user_data, gint64 pts, gint64 dts, gboolean keyunit) +psmux_stream_add_data (PsMuxStream * stream, GstBuffer * buffer, + gint64 pts, gint64 dts, gboolean keyunit) { PsMuxStreamBuffer *packet; g_return_if_fail (stream != NULL); packet = g_slice_new (PsMuxStreamBuffer); - packet->data = data; - packet->size = len; - packet->user_data = user_data; + packet->buf = buffer; + + if (!gst_buffer_map (packet->buf, &packet->map, GST_MAP_READ)) { + GST_ERROR ("Failed to map buffer for reading"); + gst_buffer_unref (packet->buf); + g_slice_free (PsMuxStreamBuffer, packet); + return; + } packet->keyunit = keyunit; packet->pts = pts; @@ -531,7 +510,8 @@ psmux_stream_add_data (PsMuxStream * stream, guint8 * data, guint len, if (stream->bytes_avail == 0) stream->last_pts = pts; - stream->bytes_avail += len; + stream->bytes_avail += packet->map.size; + /* FIXME: perhaps use GstQueueArray instead? */ stream->buffers = g_list_append (stream->buffers, packet); } diff --git a/gst/mpegpsmux/psmuxstream.h b/gst/mpegpsmux/psmuxstream.h index 87c2aca1c7..0b3c139cda 100644 --- a/gst/mpegpsmux/psmuxstream.h +++ b/gst/mpegpsmux/psmuxstream.h @@ -45,7 +45,7 @@ #ifndef __PSMUXSTREAM_H__ #define __PSMUXSTREAM_H__ -#include +#include #include "psmuxcommon.h" @@ -83,16 +83,14 @@ enum PsMuxStreamType { /* Table 2-29 in spec */ struct PsMuxStreamBuffer { - guint8 *data; - guint32 size; - gboolean keyunit; /* PTS & DTS associated with the contents of this buffer */ GstClockTime pts; GstClockTime dts; - void *user_data; + GstBuffer *buf; + GstMapInfo map; }; /* PsMuxStream receives elementary streams for parsing. @@ -116,9 +114,6 @@ struct PsMuxStream{ guint16 cur_pes_payload_size; guint16 pes_bytes_written; /* delete*/ - /* Release function */ - PsMuxStreamBufferReleaseFunc buffer_release; - /* PTS/DTS to write if the flags in the packet info are set */ gint64 pts; /* TODO: cur_buffer->pts?*/ gint64 dts; /* TODO: cur_buffer->dts?*/ @@ -141,14 +136,11 @@ struct PsMuxStream{ PsMuxStream* psmux_stream_new (PsMux * mux, PsMuxStreamType stream_type); void psmux_stream_free (PsMuxStream *stream); -/* The callback when a buffer is released. Used to unref the buffer in GStreamer */ -void psmux_stream_set_buffer_release_func (PsMuxStream *stream, - PsMuxStreamBufferReleaseFunc func); - /* Add a new buffer to the pool of available bytes. If pts or dts are not -1, they * indicate the PTS or DTS of the first access unit within this packet */ -void psmux_stream_add_data (PsMuxStream *stream, guint8 *data, guint len, - void *user_data, gint64 pts, gint64 dts, +void psmux_stream_add_data (PsMuxStream *stream, + GstBuffer * buffer, + gint64 pts, gint64 dts, gboolean keyunit); /* total bytes in buffer */