Naive port. Barely tested.
freeverb \
hdvparse ivfparse jp2kdecimator \
kate librfb \
- mpegpsmux mve mythtv nsf nuvdemux \
+ mve mythtv nsf nuvdemux \
patchdetect real \
sdi stereo tta videofilters \
videomeasure videosignal vmnc \
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 <oxcsnicho@gmail.com>");
-}
+#define parent_class mpegpsmux_parent_class
+G_DEFINE_TYPE (MpegPsMux, mpegpsmux, GST_TYPE_ELEMENT);
static void
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;
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 <oxcsnicho@gmail.com>");
}
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");
}
static void
-mpegpsmux_dispose (GObject * object)
+mpegpsmux_finalize (GObject * object)
{
MpegPsMux *mux = GST_MPEG_PSMUX (object);
mux->gop_list = NULL;
}
- GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
+ G_OBJECT_CLASS (mpegpsmux_parent_class)->finalize (object);
}
static void
}
}
-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;
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;
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;
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) {
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;
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;
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;
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)
{
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;
}
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);
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;
}
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 */
/* 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;
}
#endif
#include "mpegpsmux_h264.h"
+#include <gst/base/gstbytewriter.h>
#include <string.h>
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);
offset += 2;
/* Fake a start code */
- memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
- out_offset += 4;
+ gst_byte_writer_put_uint32_be (&bw, 0x00000001);
+
/* 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_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);
offset += 2;
/* Fake a start code */
- memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
- out_offset += 4;
+ gst_byte_writer_put_uint32_be (&bw, 0x00000001);
+
/* 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_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;
}
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);
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)
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);
}
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;
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);
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);
}
stream->cur_pes_payload_size = 0;
- stream->buffer_release = NULL;
-
stream->pts = -1;
stream->dts = -1;
stream->last_pts = -1;
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;
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;
}
}
/* 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);
/* 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;
return;
}
- bound -= curbuf->size;
+ bound -= curbuf->map.size;
}
}
/**
* 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
*
* 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;
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);
}
#ifndef __PSMUXSTREAM_H__
#define __PSMUXSTREAM_H__
-#include <glib.h>
+#include <gst/gst.h>
#include "psmuxcommon.h"
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.
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?*/
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 */