mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
g726depay: implement RFC3551 packing
We implemented the AAL2 packing, add the encoding-name for those to the caps and a property to force AAL2 decoding (always TRUE for now). Implement RFC3551 unpacking for regular G726. See #567140.
This commit is contained in:
parent
c34d5aa016
commit
0802ba8730
2 changed files with 154 additions and 20 deletions
|
@ -49,9 +49,13 @@ enum
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_FORCE_AAL2 TRUE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0
|
PROP_0,
|
||||||
|
PROP_FORCE_AAL2,
|
||||||
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_rtp_g726_depay_sink_template =
|
static GstStaticPadTemplate gst_rtp_g726_depay_sink_template =
|
||||||
|
@ -61,7 +65,8 @@ static GstStaticPadTemplate gst_rtp_g726_depay_sink_template =
|
||||||
GST_STATIC_CAPS ("application/x-rtp, "
|
GST_STATIC_CAPS ("application/x-rtp, "
|
||||||
"media = (string) \"audio\", "
|
"media = (string) \"audio\", "
|
||||||
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
"payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
|
||||||
"encoding-name = (string) { \"G726\", \"G726-16\", \"G726-24\", \"G726-32\", \"G726-40\"}, "
|
"encoding-name = (string) { \"G726\", \"G726-16\", \"G726-24\", \"G726-32\", \"G726-40\", "
|
||||||
|
"\"AAL2-G726-16\", \"AAL2-G726-24\", \"AAL2-G726-32\", \"AAL2-G726-40\" }, "
|
||||||
"clock-rate = (int) 8000;")
|
"clock-rate = (int) 8000;")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -122,6 +127,8 @@ gst_rtp_g726_depay_init (GstRtpG726Depay * rtpG726depay,
|
||||||
depayload = GST_BASE_RTP_DEPAYLOAD (rtpG726depay);
|
depayload = GST_BASE_RTP_DEPAYLOAD (rtpG726depay);
|
||||||
|
|
||||||
gst_pad_use_fixed_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload));
|
gst_pad_use_fixed_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload));
|
||||||
|
|
||||||
|
rtpG726depay->force_aal2 = DEFAULT_FORCE_AAL2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -132,7 +139,9 @@ gst_rtp_g726_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
gint clock_rate;
|
gint clock_rate;
|
||||||
const gchar *encoding_name;
|
const gchar *encoding_name;
|
||||||
gint bitrate;
|
GstRtpG726Depay *depay;
|
||||||
|
|
||||||
|
depay = GST_RTP_G726_DEPAY (depayload);
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
@ -140,52 +149,173 @@ gst_rtp_g726_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
|
||||||
clock_rate = 8000; /* default */
|
clock_rate = 8000; /* default */
|
||||||
depayload->clock_rate = clock_rate;
|
depayload->clock_rate = clock_rate;
|
||||||
|
|
||||||
|
depay->aal2 = FALSE;
|
||||||
encoding_name = gst_structure_get_string (structure, "encoding-name");
|
encoding_name = gst_structure_get_string (structure, "encoding-name");
|
||||||
if (encoding_name == NULL || g_ascii_strcasecmp (encoding_name, "G726") == 0) {
|
if (encoding_name == NULL || g_ascii_strcasecmp (encoding_name, "G726") == 0) {
|
||||||
bitrate = DEFAULT_BIT_RATE;
|
depay->bitrate = DEFAULT_BIT_RATE;
|
||||||
} else if (g_ascii_strcasecmp (encoding_name, "G726-16") == 0) {
|
|
||||||
bitrate = 16000;
|
|
||||||
} else if (g_ascii_strcasecmp (encoding_name, "G726-24") == 0) {
|
|
||||||
bitrate = 24000;
|
|
||||||
} else if (g_ascii_strcasecmp (encoding_name, "G726-32") == 0) {
|
|
||||||
bitrate = 32000;
|
|
||||||
} else if (g_ascii_strcasecmp (encoding_name, "G726-40") == 0) {
|
|
||||||
bitrate = 40000;
|
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("Could not determine bitrate from encoding-name (%s)",
|
if (g_str_has_prefix (encoding_name, "AAL2-")) {
|
||||||
encoding_name);
|
depay->aal2 = TRUE;
|
||||||
ret = FALSE;
|
encoding_name += 5;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
GST_DEBUG ("RTP G.726 depayloader, bitrate set to %d\n", bitrate);
|
if (g_ascii_strcasecmp (encoding_name, "G726-16") == 0) {
|
||||||
|
depay->bitrate = 16000;
|
||||||
|
} else if (g_ascii_strcasecmp (encoding_name, "G726-24") == 0) {
|
||||||
|
depay->bitrate = 24000;
|
||||||
|
} else if (g_ascii_strcasecmp (encoding_name, "G726-32") == 0) {
|
||||||
|
depay->bitrate = 32000;
|
||||||
|
} else if (g_ascii_strcasecmp (encoding_name, "G726-40") == 0) {
|
||||||
|
depay->bitrate = 40000;
|
||||||
|
} else
|
||||||
|
goto unknown_encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG ("RTP G.726 depayloader, bitrate set to %d\n", depay->bitrate);
|
||||||
|
|
||||||
srccaps = gst_caps_new_simple ("audio/x-adpcm",
|
srccaps = gst_caps_new_simple ("audio/x-adpcm",
|
||||||
"channels", G_TYPE_INT, 1,
|
"channels", G_TYPE_INT, 1,
|
||||||
"rate", G_TYPE_INT, clock_rate,
|
"rate", G_TYPE_INT, clock_rate,
|
||||||
"bitrate", G_TYPE_INT, bitrate,
|
"bitrate", G_TYPE_INT, depay->bitrate,
|
||||||
"layout", G_TYPE_STRING, LAYOUT_G726, NULL);
|
"layout", G_TYPE_STRING, LAYOUT_G726, NULL);
|
||||||
|
|
||||||
ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps);
|
ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps);
|
||||||
gst_caps_unref (srccaps);
|
gst_caps_unref (srccaps);
|
||||||
|
|
||||||
done:
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
unknown_encoding:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Could not determine bitrate from encoding-name (%s)",
|
||||||
|
encoding_name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static GstBuffer *
|
static GstBuffer *
|
||||||
gst_rtp_g726_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
gst_rtp_g726_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
|
GstRtpG726Depay *depay;
|
||||||
GstBuffer *outbuf = NULL;
|
GstBuffer *outbuf = NULL;
|
||||||
gboolean marker;
|
gboolean marker;
|
||||||
|
|
||||||
|
depay = GST_RTP_G726_DEPAY (depayload);
|
||||||
|
|
||||||
marker = gst_rtp_buffer_get_marker (buf);
|
marker = gst_rtp_buffer_get_marker (buf);
|
||||||
|
|
||||||
GST_DEBUG ("process : got %d bytes, mark %d ts %u seqn %d",
|
GST_DEBUG ("process : got %d bytes, mark %d ts %u seqn %d",
|
||||||
GST_BUFFER_SIZE (buf), marker,
|
GST_BUFFER_SIZE (buf), marker,
|
||||||
gst_rtp_buffer_get_timestamp (buf), gst_rtp_buffer_get_seq (buf));
|
gst_rtp_buffer_get_timestamp (buf), gst_rtp_buffer_get_seq (buf));
|
||||||
|
|
||||||
|
if (depay->aal2 || depay->force_aal2) {
|
||||||
|
/* AAL2, we can just copy the bytes */
|
||||||
outbuf = gst_rtp_buffer_get_payload_buffer (buf);
|
outbuf = gst_rtp_buffer_get_payload_buffer (buf);
|
||||||
|
} else {
|
||||||
|
guint8 *in, *out, tmp;
|
||||||
|
guint len;
|
||||||
|
|
||||||
|
in = gst_rtp_buffer_get_payload (buf);
|
||||||
|
len = gst_rtp_buffer_get_payload_len (buf);
|
||||||
|
|
||||||
|
if (gst_buffer_is_writable (buf)) {
|
||||||
|
outbuf = gst_rtp_buffer_get_payload_buffer (buf);
|
||||||
|
} else {
|
||||||
|
GstBuffer *copy;
|
||||||
|
|
||||||
|
/* copy buffer */
|
||||||
|
copy = gst_buffer_copy (buf);
|
||||||
|
outbuf = gst_rtp_buffer_get_payload_buffer (copy);
|
||||||
|
gst_buffer_unref (copy);
|
||||||
|
}
|
||||||
|
out = GST_BUFFER_DATA (outbuf);
|
||||||
|
|
||||||
|
/* we need to reshuffle the bytes */
|
||||||
|
switch (depay->bitrate) {
|
||||||
|
case 16000:
|
||||||
|
{
|
||||||
|
/* 0
|
||||||
|
* 0 1 2 3 4 5 6 7
|
||||||
|
* +-+-+-+-+-+-+-+-+-
|
||||||
|
* |D D|C C|B B|A A| ...
|
||||||
|
* |0 1|0 1|0 1|0 1|
|
||||||
|
* +-+-+-+-+-+-+-+-+-
|
||||||
|
*/
|
||||||
|
while (len > 0) {
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xc0) >> 6) |
|
||||||
|
((tmp & 0x30) >> 2) | ((tmp & 0x0c) << 2) | ((tmp & 0x03) << 6);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 24000:
|
||||||
|
{
|
||||||
|
/* 0 1 2
|
||||||
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
* |C C|B B B|A A A|F|E E E|D D D|C|H H H|G G G|F F| ...
|
||||||
|
* |1 2|0 1 2|0 1 2|2|0 1 2|0 1 2|0|0 1 2|0 1 2|0 1|
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
*/
|
||||||
|
while (len > 2) {
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xe0) >> 5) |
|
||||||
|
((tmp & 0x1c) << 1) | ((tmp & 0x03) << 6);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0x80) >> 7) |
|
||||||
|
((tmp & 0x70) >> 3) | ((tmp & 0x0e) << 4) | ((tmp & 0x01) << 7);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xc0) >> 6) |
|
||||||
|
((tmp & 0x38) >> 1) | ((tmp & 0x07) << 5);
|
||||||
|
len -= 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 32000:
|
||||||
|
{
|
||||||
|
/* 0 1
|
||||||
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
* |B B B B|A A A A|D D D D|C C C C| ...
|
||||||
|
* |0 1 2 3|0 1 2 3|0 1 2 3|0 1 2 3|
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
*/
|
||||||
|
while (len > 0) {
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xf0) >> 4) | ((tmp & 0x0f) << 4);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 40000:
|
||||||
|
{
|
||||||
|
/* 0 1 2 3 4
|
||||||
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
* |B B B|A A A A A|D|C C C C C|B B|E E E E|D D D D|G G|F F F F F|E|H H H H H|G G G|
|
||||||
|
* |2 3 4|0 1 2 3 4|4|0 1 2 3 4|0 1|1 2 3 4|0 1 2 3|3 4|0 1 2 3 4|0|0 1 2 3 4|0 1 2|
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||||
|
*/
|
||||||
|
while (len > 4) {
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xf8) >> 3) | ((tmp & 0x07) << 5);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xc0) >> 6) |
|
||||||
|
((tmp & 0x3e) << 1) | ((tmp & 0x01) << 7);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xf0) >> 4) | ((tmp & 0x0f) << 4);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0x80) >> 7) |
|
||||||
|
((tmp & 0x7c) >> 1) | ((tmp & 0x03) << 6);
|
||||||
|
tmp = *in++;
|
||||||
|
*out++ = ((tmp & 0xe0) >> 5) | ((tmp & 0x1f) << 3);
|
||||||
|
len -= 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (marker) {
|
if (marker) {
|
||||||
/* mark start of talkspurt with discont */
|
/* mark start of talkspurt with discont */
|
||||||
|
|
|
@ -38,6 +38,10 @@ typedef struct _GstRtpG726DepayClass GstRtpG726DepayClass;
|
||||||
struct _GstRtpG726Depay
|
struct _GstRtpG726Depay
|
||||||
{
|
{
|
||||||
GstBaseRTPDepayload depayload;
|
GstBaseRTPDepayload depayload;
|
||||||
|
|
||||||
|
gboolean aal2;
|
||||||
|
gboolean force_aal2;
|
||||||
|
gint bitrate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRtpG726DepayClass
|
struct _GstRtpG726DepayClass
|
||||||
|
|
Loading…
Reference in a new issue