From 2f68d625c10971acd7e0326bcc1f64447d7e72a6 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 11 May 2006 16:17:44 +0000 Subject: [PATCH] ext/a52dec/gsta52dec.c: Add more debug Original commit message from CVS: * ext/a52dec/gsta52dec.c: (gst_a52dec_chain): Add more debug * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcm_reset), (gst_dvdlpcmdec_init), (update_timestamps), (gst_dvdlpcmdec_chain_dvd), (gst_dvdlpcmdec_chain_raw), (dvdlpcmdec_sink_event): * gst/dvdlpcmdec/gstdvdlpcmdec.h: If we have a first_access offset but no current timestamp (might happen after a seek), then calculate a start time for the first portion so that it will align with the timestamp given for the first_access portion. If a new-segment arrives with format time, store the start time as a failsafe timestamp in case we never get any further timestamp info (unlikely) Mask out the 'frame number' section of the incoming header so that we don't consider it to be changing on every buffer and reset the caps constantly. Use gst_util_uint64_scale for duration calculation --- ChangeLog | 25 ++++++++ ext/a52dec/gsta52dec.c | 3 +- gst/dvdlpcmdec/gstdvdlpcmdec.c | 101 +++++++++++++++++++++++++++++---- gst/dvdlpcmdec/gstdvdlpcmdec.h | 1 + 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 07bbd54206..4454a6de70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2006-05-11 Jan Schmidt + + * ext/a52dec/gsta52dec.c: (gst_a52dec_chain): + Add more debug + + * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcm_reset), + (gst_dvdlpcmdec_init), (update_timestamps), + (gst_dvdlpcmdec_chain_dvd), (gst_dvdlpcmdec_chain_raw), + (dvdlpcmdec_sink_event): + * gst/dvdlpcmdec/gstdvdlpcmdec.h: + If we have a first_access offset but no current timestamp (might + happen after a seek), then calculate a start time for the first + portion so that it will align with the timestamp given for the + first_access portion. + + If a new-segment arrives with format time, store the start + time as a failsafe timestamp in case we never get any further + timestamp info (unlikely) + + Mask out the 'frame number' section of the incoming header so + that we don't consider it to be changing on every buffer and + reset the caps constantly. + + Use gst_util_uint64_scale for duration calculation + 2006-05-11 Michael Smith * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcmdec_chain_dvd): diff --git a/ext/a52dec/gsta52dec.c b/ext/a52dec/gsta52dec.c index 76b286e27b..7bd449b782 100644 --- a/ext/a52dec/gsta52dec.c +++ b/ext/a52dec/gsta52dec.c @@ -535,7 +535,8 @@ gst_a52dec_chain (GstPad * pad, GstBuffer * buf) len = first_access - 1; if (len <= 0 || offset + len > size) { - GST_ERROR_OBJECT (pad, "Bad first_access parameter in buffer"); + GST_ERROR_OBJECT (pad, "Bad first_access parameter (%d) in buffer", + first_access); ret = GST_FLOW_ERROR; goto done; } diff --git a/gst/dvdlpcmdec/gstdvdlpcmdec.c b/gst/dvdlpcmdec/gstdvdlpcmdec.c index 6b476f456f..15a05965c9 100644 --- a/gst/dvdlpcmdec/gstdvdlpcmdec.c +++ b/gst/dvdlpcmdec/gstdvdlpcmdec.c @@ -85,6 +85,7 @@ static GstFlowReturn gst_dvdlpcmdec_chain_raw (GstPad * pad, static GstFlowReturn gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buffer); static gboolean gst_dvdlpcmdec_setcaps (GstPad * pad, GstCaps * caps); +static gboolean dvdlpcmdec_sink_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_dvdlpcmdec_change_state (GstElement * element, GstStateChange transition); @@ -150,7 +151,7 @@ gst_dvdlpcm_reset (GstDvdLpcmDec * dvdlpcmdec) dvdlpcmdec->dynamic_range = 0; dvdlpcmdec->emphasis = FALSE; dvdlpcmdec->mute = FALSE; - dvdlpcmdec->timestamp = 0; + dvdlpcmdec->timestamp = GST_CLOCK_TIME_NONE; dvdlpcmdec->header = 0; @@ -165,6 +166,7 @@ gst_dvdlpcmdec_init (GstDvdLpcmDec * dvdlpcmdec) gst_pad_new_from_template (gst_static_pad_template_get (&gst_dvdlpcmdec_sink_template), "sink"); gst_pad_set_setcaps_function (dvdlpcmdec->sinkpad, gst_dvdlpcmdec_setcaps); + gst_pad_set_event_function (dvdlpcmdec->sinkpad, dvdlpcmdec_sink_event); gst_element_add_pad (GST_ELEMENT (dvdlpcmdec), dvdlpcmdec->sinkpad); dvdlpcmdec->srcpad = @@ -257,15 +259,21 @@ caps_parse_error: static void update_timestamps (GstDvdLpcmDec * dvdlpcmdec, GstBuffer * buf, int samples) { - GST_BUFFER_DURATION (buf) = samples * GST_SECOND / dvdlpcmdec->rate; + GST_BUFFER_DURATION (buf) = + gst_util_uint64_scale (samples, GST_SECOND, dvdlpcmdec->rate); + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { /* Then leave it as-is, and save this timestamp */ dvdlpcmdec->timestamp = GST_BUFFER_TIMESTAMP (buf); } else { - dvdlpcmdec->timestamp += GST_BUFFER_DURATION (buf); + if (!GST_CLOCK_TIME_IS_VALID (dvdlpcmdec->timestamp)) + dvdlpcmdec->timestamp = dvdlpcmdec->segment_start; + GST_BUFFER_TIMESTAMP (buf) = dvdlpcmdec->timestamp; } + dvdlpcmdec->timestamp += GST_BUFFER_DURATION (buf); + GST_LOG_OBJECT (dvdlpcmdec, "Updated timestamp to %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); } @@ -315,7 +323,7 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf) guint first_access; guint32 header; GstBuffer *subbuf; - GstFlowReturn ret; + GstFlowReturn ret = GST_FLOW_OK; gint off, len; dvdlpcmdec = GST_DVDLPCMDEC (gst_pad_get_parent (pad)); @@ -348,7 +356,8 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf) goto done; } - header = (data[2] << 16) | (data[3] << 8) | data[4]; + /* Don't keep the 'frame number' low 5 bits of the first byte */ + header = ((data[2] & 0xC0) << 16) | (data[3] << 8) | data[4]; /* see if we have a new header */ if (header != dvdlpcmdec->header) { @@ -389,11 +398,14 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf) off = 5; if (first_access > 4) { + guint samples = 0; + GstClockTime ts; + /* length of first buffer */ len = first_access - 4; - GST_LOG_OBJECT (dvdlpcmdec, "Creating first sub-buffer off %d, len %d", off, - len); + GST_LOG_OBJECT (dvdlpcmdec, "Creating first sub-buffer off %d, len %d", + off, len); /* see if we need a subbuffer without timestamp */ if (off + len > size) { @@ -406,7 +418,35 @@ gst_dvdlpcmdec_chain_dvd (GstPad * pad, GstBuffer * buf) } subbuf = gst_buffer_create_sub (buf, off, len); - GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; + + /* If we don't have a stored timestamp from the last packet, + * (it's straight after a new-segment, but we have one on the + * first access buffer, then calculate the timestamp to align + * this buffer to just before the first_access buffer */ + if (!GST_CLOCK_TIME_IS_VALID (dvdlpcmdec->timestamp) && + GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + switch (dvdlpcmdec->width) { + case 16: + samples = len / dvdlpcmdec->channels / 2; + break; + case 20: + samples = (len / dvdlpcmdec->channels) * 2 / 5; + break; + case 24: + samples = len / dvdlpcmdec->channels / 3; + break; + } + } + if (samples != 0) { + ts = gst_util_uint64_scale (samples, GST_SECOND, dvdlpcmdec->rate); + if (ts < GST_BUFFER_TIMESTAMP (buf)) + GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf) - ts; + else + GST_BUFFER_TIMESTAMP (subbuf) = 0; + } else { + GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE; + } + ret = gst_dvdlpcmdec_chain_raw (pad, subbuf); if (ret != GST_FLOW_OK) goto done; @@ -462,7 +502,9 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf) size = GST_BUFFER_SIZE (buf); data = GST_BUFFER_DATA (buf); - GST_LOG_OBJECT (dvdlpcmdec, "got buffer %p of size %d", buf, size); + GST_LOG_OBJECT (dvdlpcmdec, + "got buffer %p of size %d with ts %" GST_TIME_FORMAT, + buf, size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); if (dvdlpcmdec->rate == 0) goto not_negotiated; @@ -475,7 +517,7 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf) /* We can just pass 16-bits straight through intact, once we set * appropriate things on the buffer */ samples = size / dvdlpcmdec->channels / 2; - buf = gst_buffer_make_writable (buf); + buf = gst_buffer_make_metadata_writable (buf); break; } case 20: @@ -600,6 +642,45 @@ invalid_width: } } +static gboolean +dvdlpcmdec_sink_event (GstPad * pad, GstEvent * event) +{ + GstDvdLpcmDec *dvdlpcmdec = GST_DVDLPCMDEC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + gdouble rate, arate; + GstFormat format; + gboolean update; + gint64 start, end, base; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, + &format, &start, &end, &base); + + GST_DEBUG_OBJECT (dvdlpcmdec, + "new segment, format=%d, start = %" G_GINT64_FORMAT + ", end = %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT, + format, start, end, base); + + dvdlpcmdec->timestamp = GST_CLOCK_TIME_NONE; + if (format == GST_FORMAT_TIME) + dvdlpcmdec->segment_start = start; + else + dvdlpcmdec->segment_start = 0; + + GST_DEBUG_OBJECT (dvdlpcmdec, + "Have new segment. Resetting timestamp. segment_start = % " + G_GINT64_FORMAT, dvdlpcmdec->segment_start); + break; + } + default: + break; + } + + return gst_pad_event_default (pad, event); +} + static GstStateChangeReturn gst_dvdlpcmdec_change_state (GstElement * element, GstStateChange transition) { diff --git a/gst/dvdlpcmdec/gstdvdlpcmdec.h b/gst/dvdlpcmdec/gstdvdlpcmdec.h index 9c5962345c..36c44e3885 100644 --- a/gst/dvdlpcmdec/gstdvdlpcmdec.h +++ b/gst/dvdlpcmdec/gstdvdlpcmdec.h @@ -55,6 +55,7 @@ struct _GstDvdLpcmDec { gint mute; GstClockTime timestamp; + GstClockTime segment_start; }; struct _GstDvdLpcmDecClass {