summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.com>2018-09-21 19:47:44 +0100
committerTim-Philipp Müller <tim@centricular.com>2019-05-01 19:28:33 +0100
commit6d03fee9171ab1392d57d210c199812f754b80c1 (patch)
tree8e71a7d864641535f8e0fc1e938952343b5c16cd
parenta1a165a68980766f86cf34f3598a58fb9c3ac864 (diff)
downloadgstreamer-plugins-good-6d03fee9171ab1392d57d210c199812f754b80c1.tar.gz
rtpmp4gdepay: detect broken senders who send AAC with ADTS frames
Strip ADTS headers if we detect any, apparently some Sony cameras send AAC with ADTS headers. We could also change the stream-format in the output caps, but that would be unexpected to pipeline builders and would not exactly be backwards compatible.
-rw-r--r--gst/rtp/gstrtpmp4gdepay.c22
-rw-r--r--gst/rtp/gstrtpmp4gdepay.h2
2 files changed, 24 insertions, 0 deletions
diff --git a/gst/rtp/gstrtpmp4gdepay.c b/gst/rtp/gstrtpmp4gdepay.c
index d7d91c4ed..858651a78 100644
--- a/gst/rtp/gstrtpmp4gdepay.c
+++ b/gst/rtp/gstrtpmp4gdepay.c
@@ -233,11 +233,14 @@ gst_rtp_mp4g_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
clock_rate = 90000; /* default */
depayload->clock_rate = clock_rate;
+ rtpmp4gdepay->check_adts = FALSE;
+
if ((str = gst_structure_get_string (structure, "media"))) {
if (strcmp (str, "audio") == 0) {
srccaps = gst_caps_new_simple ("audio/mpeg",
"mpegversion", G_TYPE_INT, 4, "stream-format", G_TYPE_STRING, "raw",
NULL);
+ rtpmp4gdepay->check_adts = TRUE;
} else if (strcmp (str, "video") == 0) {
srccaps = gst_caps_new_simple ("video/mpeg",
"mpegversion", G_TYPE_INT, 4,
@@ -665,11 +668,30 @@ gst_rtp_mp4g_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
gst_adapter_push (rtpmp4gdepay->adapter, outbuf);
if (M) {
+ guint32 v = 0;
guint avail;
/* packet is complete, flush */
avail = gst_adapter_available (rtpmp4gdepay->adapter);
+ /* Some broken senders send ADTS headers (e.g. some Sony cameras).
+ * Try to detect those and skip them (still needs config set), but
+ * don't check every frame, only the first (unless we detect ADTS) */
+ if (rtpmp4gdepay->check_adts && avail >= 7) {
+ if (gst_adapter_masked_scan_uint32_peek (rtpmp4gdepay->adapter,
+ 0xfffe0000, 0xfff00000, 0, 4, &v) == 0) {
+ guint adts_hdr_len = (((v >> 16) & 0x1) == 0) ? 9 : 7;
+ if (avail > adts_hdr_len) {
+ GST_WARNING_OBJECT (rtpmp4gdepay, "Detected ADTS header of "
+ "%u bytes, skipping", adts_hdr_len);
+ gst_adapter_flush (rtpmp4gdepay->adapter, adts_hdr_len);
+ avail -= adts_hdr_len;
+ }
+ } else {
+ rtpmp4gdepay->check_adts = FALSE;
+ }
+ }
+
outbuf = gst_adapter_take_buffer (rtpmp4gdepay->adapter, avail);
/* copy some of the fields we calculated above on the buffer. We also
diff --git a/gst/rtp/gstrtpmp4gdepay.h b/gst/rtp/gstrtpmp4gdepay.h
index 5d5997af3..d4d9330c1 100644
--- a/gst/rtp/gstrtpmp4gdepay.h
+++ b/gst/rtp/gstrtpmp4gdepay.h
@@ -67,6 +67,8 @@ struct _GstRtpMP4GDepay
guint32 prev_rtptime;
guint prev_AU_num;
+ gboolean check_adts; /* check for ADTS headers */
+
GQueue *packets;
GstAdapter *adapter;