mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
sbcdepay: Add property to ignore input timestamps
This then just counts samples and calculates the output timestamps based on that and the very first observed timestamp. The timestamps on the buffers are continued to be used to detect discontinuities that are too big and reset the counter at that point. When receiving data via Bluetooth, many devices put completely wrong values into the RTP timestamp field. For example iOS seems to put a timestamp in milliseconds in there, instead of something based on the current sample offset (RTP clock-rate == sample rate). https://bugzilla.gnome.org/show_bug.cgi?id=787297
This commit is contained in:
parent
c0622addf6
commit
58f0eabd61
2 changed files with 115 additions and 3 deletions
|
@ -53,9 +53,22 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
|||
"encoding-name = (string) SBC")
|
||||
);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_IGNORE_TIMESTAMPS,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
#define DEFAULT_IGNORE_TIMESTAMPS FALSE
|
||||
|
||||
#define gst_rtp_sbc_depay_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstRtpSbcDepay, gst_rtp_sbc_depay, GST_TYPE_RTP_BASE_DEPAYLOAD);
|
||||
|
||||
static void gst_rtp_sbc_depay_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_rtp_sbc_depay_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
static void gst_rtp_sbc_depay_finalize (GObject * object);
|
||||
|
||||
static gboolean gst_rtp_sbc_depay_setcaps (GstRTPBaseDepayload * base,
|
||||
|
@ -72,6 +85,13 @@ gst_rtp_sbc_depay_class_init (GstRtpSbcDepayClass * klass)
|
|||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gst_rtp_sbc_depay_finalize;
|
||||
gobject_class->set_property = gst_rtp_sbc_depay_set_property;
|
||||
gobject_class->get_property = gst_rtp_sbc_depay_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_IGNORE_TIMESTAMPS,
|
||||
g_param_spec_boolean ("ignore-timestamps", "Ignore Timestamps",
|
||||
"Various statistics", DEFAULT_IGNORE_TIMESTAMPS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstbasertpdepayload_class->set_caps = gst_rtp_sbc_depay_setcaps;
|
||||
gstbasertpdepayload_class->process_rtp_packet = gst_rtp_sbc_depay_process;
|
||||
|
@ -95,6 +115,9 @@ static void
|
|||
gst_rtp_sbc_depay_init (GstRtpSbcDepay * rtpsbcdepay)
|
||||
{
|
||||
rtpsbcdepay->adapter = gst_adapter_new ();
|
||||
rtpsbcdepay->stream_align =
|
||||
gst_audio_stream_align_new (48000, 40 * GST_MSECOND, 1 * GST_SECOND);
|
||||
rtpsbcdepay->ignore_timestamps = DEFAULT_IGNORE_TIMESTAMPS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -102,11 +125,44 @@ gst_rtp_sbc_depay_finalize (GObject * object)
|
|||
{
|
||||
GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (object);
|
||||
|
||||
gst_audio_stream_align_free (depay->stream_align);
|
||||
gst_object_unref (depay->adapter);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_sbc_depay_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_IGNORE_TIMESTAMPS:
|
||||
depay->ignore_timestamps = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_sbc_depay_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_IGNORE_TIMESTAMPS:
|
||||
g_value_set_boolean (value, depay->ignore_timestamps);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: This duplicates similar functionality rtpsbcpay, but there isn't a
|
||||
* simple way to consolidate the two. This is best done by moving the function
|
||||
* to the codec-utils library in gst-plugins-base when these elements move to
|
||||
|
@ -184,6 +240,9 @@ gst_rtp_sbc_depay_setcaps (GstRTPBaseDepayload * base, GstCaps * caps)
|
|||
if (oldcaps)
|
||||
gst_caps_unref (oldcaps);
|
||||
|
||||
/* Reset when the caps are changing */
|
||||
gst_audio_stream_align_set_rate (depay->stream_align, depay->rate);
|
||||
|
||||
return TRUE;
|
||||
|
||||
bad_caps:
|
||||
|
@ -202,6 +261,9 @@ gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
|
|||
guint8 nframes;
|
||||
guint8 *payload;
|
||||
guint payload_len;
|
||||
gint samples = 0;
|
||||
|
||||
GstClockTime timestamp;
|
||||
|
||||
GST_LOG_OBJECT (depay, "Got %" G_GSIZE_FORMAT " bytes",
|
||||
gst_buffer_get_size (rtp->buffer));
|
||||
|
@ -212,6 +274,27 @@ gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
|
|||
goto bad_packet;
|
||||
}
|
||||
|
||||
timestamp = GST_BUFFER_DTS_OR_PTS (rtp->buffer);
|
||||
if (depay->ignore_timestamps && timestamp == GST_CLOCK_TIME_NONE) {
|
||||
GstClockTime initial_timestamp;
|
||||
guint64 n_samples;
|
||||
|
||||
initial_timestamp =
|
||||
gst_audio_stream_align_get_timestamp_at_discont (depay->stream_align);
|
||||
n_samples =
|
||||
gst_audio_stream_align_get_samples_since_discont (depay->stream_align);
|
||||
|
||||
if (initial_timestamp == GST_CLOCK_TIME_NONE) {
|
||||
GST_ERROR_OBJECT (depay,
|
||||
"Can only ignore timestamps on streams without valid initial timestamp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
timestamp =
|
||||
initial_timestamp + gst_util_uint64_scale (n_samples, GST_SECOND,
|
||||
depay->rate);
|
||||
}
|
||||
|
||||
payload = gst_rtp_buffer_get_payload (rtp);
|
||||
payload_len = gst_rtp_buffer_get_payload_len (rtp);
|
||||
|
||||
|
@ -243,15 +326,25 @@ gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
|
|||
gst_adapter_push (depay->adapter, data);
|
||||
|
||||
if (last) {
|
||||
gint framelen, samples;
|
||||
guint8 header[4];
|
||||
|
||||
data = gst_adapter_take_buffer (depay->adapter,
|
||||
gst_adapter_available (depay->adapter));
|
||||
gst_rtp_drop_non_audio_meta (depay, data);
|
||||
} else
|
||||
data = NULL;
|
||||
|
||||
if (gst_buffer_extract (data, 0, &header, 4) != 4 ||
|
||||
gst_rtp_sbc_depay_get_params (depay, header,
|
||||
payload_len, &framelen, &samples) < 0) {
|
||||
gst_buffer_unref (data);
|
||||
goto bad_packet;
|
||||
}
|
||||
} else {
|
||||
data = NULL;
|
||||
}
|
||||
} else {
|
||||
/* !fragment */
|
||||
gint framelen, samples;
|
||||
gint framelen;
|
||||
|
||||
GST_LOG_OBJECT (depay, "Got %d frames", nframes);
|
||||
|
||||
|
@ -261,6 +354,8 @@ gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
|
|||
goto bad_packet;
|
||||
}
|
||||
|
||||
samples *= nframes;
|
||||
|
||||
GST_LOG_OBJECT (depay, "Got payload of %d", payload_len);
|
||||
|
||||
if (nframes * framelen > (gint) payload_len) {
|
||||
|
@ -271,6 +366,18 @@ gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
|
|||
}
|
||||
}
|
||||
|
||||
if (depay->ignore_timestamps) {
|
||||
GstClockTime duration;
|
||||
|
||||
gst_audio_stream_align_process (depay->stream_align,
|
||||
GST_BUFFER_IS_DISCONT (rtp->buffer), timestamp, samples, ×tamp,
|
||||
&duration, NULL);
|
||||
|
||||
GST_BUFFER_PTS (data) = timestamp;
|
||||
GST_BUFFER_DTS (data) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (data) = duration;
|
||||
}
|
||||
|
||||
out:
|
||||
return data;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
#include <gst/rtp/gstrtpbasedepayload.h>
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GST_TYPE_RTP_SBC_DEPAY \
|
||||
|
@ -50,6 +51,10 @@ struct _GstRtpSbcDepay
|
|||
|
||||
int rate;
|
||||
GstAdapter *adapter;
|
||||
gboolean ignore_timestamps;
|
||||
|
||||
/* Timestamp tracking when ignoring input timestamps */
|
||||
GstAudioStreamAlign *stream_align;
|
||||
};
|
||||
|
||||
struct _GstRtpSbcDepayClass
|
||||
|
|
Loading…
Reference in a new issue