summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-10-29 17:19:50 +0000
committerWim Taymans <wim.taymans@collabora.co.uk>2012-10-29 17:19:50 +0000
commit1936d84771c0b4baf50fca8efc250eeb953425d5 (patch)
tree2279739c11238634446972ff23bb796b6d6d970a
parentaceb0a95962ddaa21f1e428f553b11ed39e35c4d (diff)
sbcdec: handle DISCONT and timestamps
Reset state on discont. Interpollate timestamps.
-rw-r--r--audio/gstsbcdec.c58
-rw-r--r--audio/gstsbcdec.h1
2 files changed, 50 insertions, 9 deletions
diff --git a/audio/gstsbcdec.c b/audio/gstsbcdec.c
index ebcc0e43..420d7e45 100644
--- a/audio/gstsbcdec.c
+++ b/audio/gstsbcdec.c
@@ -62,9 +62,18 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
GstFlowReturn res = GST_FLOW_OK;
guint size, codesize, offset = 0;
guint8 *data;
+ GstClockTime timestamp;
codesize = sbc_get_codesize(&dec->sbc);
+ if (GST_BUFFER_IS_DISCONT (buffer)) {
+ /* reset previous buffer */
+ gst_buffer_unref(dec->buffer);
+ dec->buffer = NULL;
+ /* we need a new timestamp to lock onto */
+ dec->next_sample = -1;
+ }
+
if (dec->buffer) {
GstBuffer *temp = buffer;
buffer = gst_buffer_span(dec->buffer, 0, buffer,
@@ -77,11 +86,16 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
data = GST_BUFFER_DATA(buffer);
size = GST_BUFFER_SIZE(buffer);
+ timestamp = GST_BUFFER_TIMESTAMP (buffer);
+
+
while (offset < size) {
GstBuffer *output;
GstPadTemplate *template;
GstCaps *caps;
int consumed;
+ GstClockTime duration;
+ gint rate, channels;
res = gst_pad_alloc_buffer_and_set_caps(dec->srcpad,
GST_BUFFER_OFFSET_NONE,
@@ -93,18 +107,46 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
consumed = sbc_decode(&dec->sbc, data + offset, size - offset,
GST_BUFFER_DATA(output), codesize,
NULL);
+ GST_INFO_OBJECT (dec, "consumed %d bytes", consumed);
+
if (consumed <= 0)
break;
+ rate = gst_sbc_parse_rate_from_sbc (dec->sbc.frequency);
+ channels = gst_sbc_get_channel_number (dec->sbc.mode);
+
+ if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ /* lock onto timestamp when we have one */
+ dec->next_sample = gst_util_uint64_scale_int (timestamp,
+ rate, GST_SECOND);
+ } if (dec->next_sample != (guint64) -1) {
+ /* reconstruct timestamp from our sample counter otherwise */
+ timestamp = gst_util_uint64_scale_int (dec->next_sample,
+ GST_SECOND, rate);
+ }
+ GST_BUFFER_TIMESTAMP (output) = timestamp;
+
+ /* calculate the next sample */
+ if (dec->next_sample != (guint64) -1) {
+ /* we ave a valid sample, counter, increment it. */
+ dec->next_sample += codesize / (2 * channels);
+ duration = gst_util_uint64_scale_int (dec->next_sample,
+ GST_SECOND, rate) - timestamp;
+ } else {
+ /* otherwise calculate duration based on output size */
+ duration = gst_util_uint64_scale_int (codesize / (2 * channels),
+ GST_SECOND, rate) - timestamp;
+ }
+ GST_BUFFER_DURATION (output) = duration;
+
+ /* reset timestamp for next round */
+ timestamp = GST_CLOCK_TIME_NONE;
+
/* we will reuse the same caps object */
if (dec->outcaps == NULL) {
caps = gst_caps_new_simple("audio/x-raw-int",
- "rate", G_TYPE_INT,
- gst_sbc_parse_rate_from_sbc(
- dec->sbc.frequency),
- "channels", G_TYPE_INT,
- gst_sbc_get_channel_number(
- dec->sbc.mode),
+ "rate", G_TYPE_INT, rate,
+ "channels", G_TYPE_INT, channels,
NULL);
template = gst_static_pad_template_get(&sbc_dec_src_factory);
@@ -118,9 +160,6 @@ static GstFlowReturn sbc_dec_chain(GstPad *pad, GstBuffer *buffer)
gst_buffer_set_caps(output, dec->outcaps);
- gst_buffer_copy_metadata(output, buffer,
- GST_BUFFER_COPY_TIMESTAMPS);
-
res = gst_pad_push(dec->srcpad, output);
if (res != GST_FLOW_OK)
goto done;
@@ -154,6 +193,7 @@ static GstStateChangeReturn sbc_dec_change_state(GstElement *element,
}
sbc_init(&dec->sbc, 0);
dec->outcaps = NULL;
+ dec->next_sample = -1;
break;
default:
break;
diff --git a/audio/gstsbcdec.h b/audio/gstsbcdec.h
index c77feaed..a62e61b2 100644
--- a/audio/gstsbcdec.h
+++ b/audio/gstsbcdec.h
@@ -53,6 +53,7 @@ struct _GstSbcDec {
GstCaps *outcaps;
sbc_t sbc;
+ guint64 next_sample;
};
struct _GstSbcDecClass {