mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
rtpamrpay: properly support perfect-rtptime
This commit is contained in:
parent
275e352a2e
commit
2953801a5f
2 changed files with 85 additions and 1 deletions
|
@ -90,6 +90,9 @@ static gboolean gst_rtp_amr_pay_setcaps (GstBaseRTPPayload * basepayload,
|
||||||
static GstFlowReturn gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * pad,
|
static GstFlowReturn gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * pad,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
|
|
||||||
|
static GstStateChangeReturn
|
||||||
|
gst_rtp_amr_pay_change_state (GstElement * element, GstStateChange transition);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstRtpAMRPay, gst_rtp_amr_pay, GstBaseRTPPayload,
|
GST_BOILERPLATE (GstRtpAMRPay, gst_rtp_amr_pay, GstBaseRTPPayload,
|
||||||
GST_TYPE_BASE_RTP_PAYLOAD);
|
GST_TYPE_BASE_RTP_PAYLOAD);
|
||||||
|
|
||||||
|
@ -113,6 +116,10 @@ static void
|
||||||
gst_rtp_amr_pay_class_init (GstRtpAMRPayClass * klass)
|
gst_rtp_amr_pay_class_init (GstRtpAMRPayClass * klass)
|
||||||
{
|
{
|
||||||
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
GstBaseRTPPayloadClass *gstbasertppayload_class;
|
||||||
|
GstElementClass *gstelement_class;
|
||||||
|
|
||||||
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
gstelement_class->change_state = gst_rtp_amr_pay_change_state;
|
||||||
|
|
||||||
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
|
||||||
|
|
||||||
|
@ -129,6 +136,14 @@ gst_rtp_amr_pay_init (GstRtpAMRPay * rtpamrpay, GstRtpAMRPayClass * klass)
|
||||||
/* needed because of GST_BOILERPLATE */
|
/* needed because of GST_BOILERPLATE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtp_amr_pay_reset (GstRtpAMRPay * pay)
|
||||||
|
{
|
||||||
|
pay->next_rtp_time = 0;
|
||||||
|
pay->first_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
pay->first_rtp_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_amr_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
gst_rtp_amr_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -178,6 +193,29 @@ wrong_type:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtp_amr_pay_recalc_rtp_time (GstRtpAMRPay * rtpamrpay,
|
||||||
|
GstClockTime timestamp)
|
||||||
|
{
|
||||||
|
/* re-sync rtp time */
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (rtpamrpay->first_ts) &&
|
||||||
|
GST_CLOCK_TIME_IS_VALID (timestamp) && timestamp >= rtpamrpay->first_ts) {
|
||||||
|
GstClockTime diff;
|
||||||
|
guint32 rtpdiff;
|
||||||
|
|
||||||
|
/* interpolate to reproduce gap from start, rather than intermediate
|
||||||
|
* intervals to avoid roundup accumulation errors */
|
||||||
|
diff = timestamp - rtpamrpay->first_ts;
|
||||||
|
rtpdiff = ((diff / GST_MSECOND) * 8) <<
|
||||||
|
(rtpamrpay->mode == GST_RTP_AMR_P_MODE_WB);
|
||||||
|
rtpamrpay->next_rtp_time = rtpamrpay->first_rtp_time + rtpdiff;
|
||||||
|
GST_DEBUG_OBJECT (rtpamrpay,
|
||||||
|
"elapsed time %" GST_TIME_FORMAT ", rtp %d, "
|
||||||
|
"new offset %" G_GUINT64_FORMAT, GST_TIME_ARGS (diff), rtpdiff,
|
||||||
|
rtpamrpay->next_rtp_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -1 is invalid */
|
/* -1 is invalid */
|
||||||
static gint nb_frame_size[16] = {
|
static gint nb_frame_size[16] = {
|
||||||
12, 13, 15, 17, 19, 20, 26, 31,
|
12, 13, 15, 17, 19, 20, 26, 31,
|
||||||
|
@ -203,6 +241,7 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
gint i, num_packets, num_nonempty_packets;
|
gint i, num_packets, num_nonempty_packets;
|
||||||
gint amr_len;
|
gint amr_len;
|
||||||
gint *frame_size;
|
gint *frame_size;
|
||||||
|
gboolean sid = FALSE;
|
||||||
|
|
||||||
rtpamrpay = GST_RTP_AMR_PAY (basepayload);
|
rtpamrpay = GST_RTP_AMR_PAY (basepayload);
|
||||||
mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay);
|
mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay);
|
||||||
|
@ -234,11 +273,14 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
FT = (data[i] & 0x78) >> 3;
|
FT = (data[i] & 0x78) >> 3;
|
||||||
|
|
||||||
fr_size = frame_size[FT];
|
fr_size = frame_size[FT];
|
||||||
GST_DEBUG_OBJECT (basepayload, "frame size %d", fr_size);
|
GST_DEBUG_OBJECT (basepayload, "frame type %d, frame size %d", FT, fr_size);
|
||||||
/* FIXME, we don't handle this yet.. */
|
/* FIXME, we don't handle this yet.. */
|
||||||
if (fr_size <= 0)
|
if (fr_size <= 0)
|
||||||
goto wrong_size;
|
goto wrong_size;
|
||||||
|
|
||||||
|
if (fr_size == 5)
|
||||||
|
sid = TRUE;
|
||||||
|
|
||||||
amr_len += fr_size;
|
amr_len += fr_size;
|
||||||
num_nonempty_packets++;
|
num_nonempty_packets++;
|
||||||
num_packets++;
|
num_packets++;
|
||||||
|
@ -272,8 +314,22 @@ gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
|
||||||
GST_DEBUG_OBJECT (basepayload, "discont, setting marker bit");
|
GST_DEBUG_OBJECT (basepayload, "discont, setting marker bit");
|
||||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
|
||||||
gst_rtp_buffer_set_marker (outbuf, TRUE);
|
gst_rtp_buffer_set_marker (outbuf, TRUE);
|
||||||
|
gst_rtp_amr_pay_recalc_rtp_time (rtpamrpay, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (sid)) {
|
||||||
|
gst_rtp_amr_pay_recalc_rtp_time (rtpamrpay, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perfect rtptime */
|
||||||
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (rtpamrpay->first_ts))) {
|
||||||
|
rtpamrpay->first_ts = timestamp;
|
||||||
|
rtpamrpay->first_rtp_time = rtpamrpay->next_rtp_time;
|
||||||
|
}
|
||||||
|
GST_BUFFER_OFFSET (outbuf) = rtpamrpay->next_rtp_time;
|
||||||
|
rtpamrpay->next_rtp_time +=
|
||||||
|
(num_packets * 160) << (rtpamrpay->mode == GST_RTP_AMR_P_MODE_WB);
|
||||||
|
|
||||||
/* get payload, this is now writable */
|
/* get payload, this is now writable */
|
||||||
payload = gst_rtp_buffer_get_payload (outbuf);
|
payload = gst_rtp_buffer_get_payload (outbuf);
|
||||||
|
|
||||||
|
@ -350,6 +406,31 @@ too_big:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstStateChangeReturn
|
||||||
|
gst_rtp_amr_pay_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
{
|
||||||
|
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
||||||
|
|
||||||
|
/* handle upwards state changes here */
|
||||||
|
switch (transition) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
|
|
||||||
|
/* handle downwards state changes */
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
gst_rtp_amr_pay_reset (GST_RTP_AMR_PAY (element));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_rtp_amr_pay_plugin_init (GstPlugin * plugin)
|
gst_rtp_amr_pay_plugin_init (GstPlugin * plugin)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,9 @@ struct _GstRtpAMRPay
|
||||||
GstBaseRTPPayload payload;
|
GstBaseRTPPayload payload;
|
||||||
|
|
||||||
GstRtpAMRPayMode mode;
|
GstRtpAMRPayMode mode;
|
||||||
|
GstClockTime first_ts;
|
||||||
|
guint32 first_rtp_time;
|
||||||
|
guint32 next_rtp_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRtpAMRPayClass
|
struct _GstRtpAMRPayClass
|
||||||
|
|
Loading…
Reference in a new issue