From 506e080a15d366e9dc55622c5798d8022b37f1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 21 Sep 2018 19:47:44 +0100 Subject: [PATCH] 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. --- gst/rtp/gstrtpmp4gdepay.c | 22 ++++++++++++++++++++++ gst/rtp/gstrtpmp4gdepay.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/gst/rtp/gstrtpmp4gdepay.c b/gst/rtp/gstrtpmp4gdepay.c index 1709010728..5d9d2cdf2d 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, @@ -664,11 +667,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 5d5997af31..d4d9330c16 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;