From 429158ad6e3ef0d465a9134c0f62b14ed1d4ddf4 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 2 Sep 2005 13:37:13 +0000 Subject: [PATCH] Changes to correctly use first_access parameter in ac3 and lpcm plugins. Original commit message from CVS: Changes to correctly use first_access parameter in ac3 and lpcm plugins. Some general cleanups in iec958 framer. --- ChangeLog | 11 ++++ gst/dvdlpcmdec/gstdvdlpcmdec.c | 61 +++++++++++++-------- gst/iec958/ac3iec.c | 96 +++++++++++++++++++++++++++++++--- 3 files changed, 140 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index e168c183e6..c8f2c69f38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-09-02 Michael Smith + + * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcmdec_chain_dvd): + * gst/iec958/ac3iec.c: (ac3iec_get_type), (ac3iec_base_init), + (ac3iec_class_init), (ac3iec_init), (ac3iec_finalize), + (ac3iec_setcaps), (ac3iec_set_property), (ac3iec_get_property), + (ac3iec_chain_dvd), (ac3iec_chain_raw), (ac3iec_change_state), + (plugin_init): + Changes to use the first_access parameter correctly in ac3 and lpcm + plugins. General cleanups in iec958 framer. + 2005-09-01 Michael Smith * configure.ac: diff --git a/gst/dvdlpcmdec/gstdvdlpcmdec.c b/gst/dvdlpcmdec/gstdvdlpcmdec.c index e6d900570b..5d5c5f4ee7 100644 --- a/gst/dvdlpcmdec/gstdvdlpcmdec.c +++ b/gst/dvdlpcmdec/gstdvdlpcmdec.c @@ -175,7 +175,7 @@ gst_dvdlpcmdec_init (GstDvdLpcmDec * dvdlpcmdec) gst_dvdlpcm_reset (dvdlpcmdec); } -static gboolean +static GstPadLinkReturn gst_dvdlpcmdec_setcaps (GstPad * pad, GstCaps * caps) { GstStructure *structure; @@ -358,37 +358,54 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf) dvdlpcmdec->header = header; } - GST_LOG_OBJECT (dvdlpcmdec, "first_access %d", first_access); + GST_LOG_OBJECT (dvdlpcmdec, "first_access %d, buffer length %d", first_access, + size); + + /* After first_access, we have an additional 3 bytes of data we've parsed and + * don't want to handle; this is included within the value of first_access. + * So a first_access value of between 1 and 3 is just broken, we treat that + * the same as zero. first_access == 4 means we only need to create a single + * sub-buffer, greater than that we need to create two. */ /* skip access unit bytes and info */ off = 5; - /* length before access unit */ - len = first_access + 1; - GST_LOG_OBJECT (dvdlpcmdec, "Creating first sub-buffer off %d, len %d", off, - len); + if (first_access > 4) { + /* length of first blength before access unit */ + len = first_access - 4; + + GST_LOG_OBJECT (dvdlpcmdec, "Creating first sub-buffer off %d, len %d", off, + len); + + /* see if we need a subbuffer without timestamp */ + if (len > 0) { + subbuf = gst_buffer_create_sub (buf, off, len); + GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; + ret = gst_dvdlpcmdec_chain_raw (pad, subbuf); + if (ret != GST_FLOW_OK) + goto done; + } + + /* then the buffer with new timestamp */ + off += len; + len = size - off; + + GST_LOG_OBJECT (dvdlpcmdec, "Creating next sub-buffer off %d, len %d", off, + len); - /* see if we need a subbuffer without timestamp */ - if (len > off) { subbuf = gst_buffer_create_sub (buf, off, len); + GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf); + + ret = gst_dvdlpcmdec_chain_raw (pad, subbuf); + } else { + GST_LOG_OBJECT (dvdlpcmdec, "Creating single sub-buffer off %d, len %d", + off, size - off); + /* We don't have a valid timestamp at all */ + subbuf = gst_buffer_create_sub (buf, off, size - off); GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; ret = gst_dvdlpcmdec_chain_raw (pad, subbuf); - if (ret != GST_FLOW_OK) - goto done; } - /* then the buffer with new timestamp */ - off = len; - len = size - len; - - GST_LOG_OBJECT (dvdlpcmdec, "Creating next sub-buffer off %d, len %d", off, - len); - - subbuf = gst_buffer_create_sub (buf, off, len); - GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf); - - ret = gst_dvdlpcmdec_chain_raw (pad, subbuf); - done: gst_buffer_unref (buf); gst_object_unref (dvdlpcmdec); diff --git a/gst/iec958/ac3iec.c b/gst/iec958/ac3iec.c index 7707f4d94e..9fd8860101 100644 --- a/gst/iec958/ac3iec.c +++ b/gst/iec958/ac3iec.c @@ -41,7 +41,7 @@ GST_DEBUG_CATEGORY_STATIC (ac3iec_debug); /* ElementFactory information. */ static GstElementDetails ac3iec_details = { "AC3 to IEC958 filter", - "audio/x-ac3", + "audio/x-private1-ac3", "Pads AC3 frames into IEC958 frames suitable for a raw SP/DIF interface", "Martin Soto " }; @@ -94,7 +94,9 @@ static void ac3iec_set_property (GObject * object, static void ac3iec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstFlowReturn ac3iec_chain (GstPad * pad, GstBuffer * buf); +static GstFlowReturn ac3iec_chain_dvd (GstPad * pad, GstBuffer * buf); +static GstFlowReturn ac3iec_chain_raw (GstPad * pad, GstBuffer * buf); +static GstPadLinkReturn ac3iec_setcaps (GstPad * pad, GstCaps * caps); static GstElementStateReturn ac3iec_change_state (GstElement * element); @@ -130,7 +132,6 @@ ac3iec_get_type (void) return ac3iec_type; } - static void ac3iec_base_init (gpointer g_class) { @@ -170,11 +171,12 @@ ac3iec_init (AC3IEC * ac3iec) gst_pad_new_from_template (gst_static_pad_template_get (&ac3iec_sink_template), "sink"); gst_element_add_pad (GST_ELEMENT (ac3iec), ac3iec->sink); - gst_pad_set_chain_function (ac3iec->sink, ac3iec_chain); + gst_pad_set_chain_function (ac3iec->sink, ac3iec_chain_dvd); ac3iec->src = gst_pad_new_from_template (gst_static_pad_template_get (&ac3iec_src_template), "src"); + gst_pad_set_setcaps_function (ac3iec->src, ac3iec_setcaps); gst_element_add_pad (GST_ELEMENT (ac3iec), ac3iec->src); ac3iec->cur_ts = GST_CLOCK_TIME_NONE; @@ -191,6 +193,24 @@ ac3iec_finalize (GObject * object) g_free (ac3iec->padder); } +static GstPadLinkReturn +ac3iec_setcaps (GstPad * pad, GstCaps * caps) +{ + AC3IEC *ac3iec = AC3IEC (gst_pad_get_parent (pad)); + gboolean res = TRUE; + GstCaps *src_caps; + + src_caps = gst_caps_new_simple ("audio/x-iec958", NULL); + + if (!gst_pad_set_caps (ac3iec->src, src_caps)) { + res = FALSE; + } + + gst_caps_unref (src_caps); + gst_object_unref (ac3iec); + + return res; +} static void ac3iec_set_property (GObject * object, guint prop_id, @@ -227,7 +247,58 @@ ac3iec_get_property (GObject * object, guint prop_id, } static GstFlowReturn -ac3iec_chain (GstPad * pad, GstBuffer * buf) +ac3iec_chain_dvd (GstPad * pad, GstBuffer * buf) +{ + guint first_access; + guint8 *data; + guint size; + gint offset; + gint len; + GstBuffer *subbuf; + GstFlowReturn ret; + + size = GST_BUFFER_SIZE (buf); + data = GST_BUFFER_DATA (buf); + + first_access = (data[0] << 8) | data[1]; + + /* Skip the first_access header */ + offset = 2; + + if (first_access > 1) { + /* Length of data before first_access */ + len = first_access - 1; + + if (len > 0) { + subbuf = gst_buffer_create_sub (buf, offset, len); + GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; + ret = ac3iec_chain_raw (pad, subbuf); + if (ret != GST_FLOW_OK) + goto done; + } + + offset += len; + len = size - offset; + + subbuf = gst_buffer_create_sub (buf, offset, len); + GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf); + + ret = ac3iec_chain_raw (pad, subbuf); + } else { + /* No first_access, so no timestamp */ + subbuf = gst_buffer_create_sub (buf, offset, size - offset); + GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; + ret = ac3iec_chain_raw (pad, subbuf); + } + +done: + gst_buffer_unref (buf); + + return ret; +} + +static GstFlowReturn +ac3iec_chain_raw (GstPad * pad, GstBuffer * buf) { GstBuffer *new; AC3IEC *ac3iec; @@ -254,9 +325,14 @@ ac3iec_chain (GstPad * pad, GstBuffer * buf) while (event != AC3P_EVENT_PUSH) { if (event == AC3P_EVENT_FRAME) { /* We have a new frame: */ + GstCaps *bufcaps = GST_PAD_CAPS (ac3iec->src); /* Create a new buffer, and copy the frame data into it. */ - new = gst_buffer_new_and_alloc (AC3P_IEC_FRAME_SIZE); + ret = gst_pad_alloc_buffer (ac3iec->src, 0, AC3P_IEC_FRAME_SIZE, + bufcaps, &new); + if (ret != GST_FLOW_OK) + goto buffer_alloc_failed; + memcpy (GST_BUFFER_DATA (new), ac3p_frame (ac3iec->padder), AC3P_IEC_FRAME_SIZE); @@ -275,7 +351,15 @@ ac3iec_chain (GstPad * pad, GstBuffer * buf) gst_buffer_unref (buf); +done: + gst_object_unref (ac3iec); + return ret; + +buffer_alloc_failed: + gst_buffer_unref (buf); + goto done; + }