diff options
author | Tim-Philipp Müller <tim@centricular.com> | 2018-09-21 19:47:44 +0100 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2019-05-01 19:28:33 +0100 |
commit | 6d03fee9171ab1392d57d210c199812f754b80c1 (patch) | |
tree | 8e71a7d864641535f8e0fc1e938952343b5c16cd | |
parent | a1a165a68980766f86cf34f3598a58fb9c3ac864 (diff) | |
download | gstreamer-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.c | 22 | ||||
-rw-r--r-- | gst/rtp/gstrtpmp4gdepay.h | 2 |
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; |