[FFmpeg-devel] [PATCH] libavformat/rtpdec_mpeg: handle bare ADTS packets with explicit decoder config

Jeff Mahoney jeffm at jeffm.io
Sat Oct 2 01:53:23 EEST 2021


When SDP specifies a decoder config, there may not be any AU headers
provided by the sender.  This can result in rtp_parse_mp4_au failing
and aac_parse_packet reporting "Error parsing AU headers." and no audio
is recovered from the stream.

This commit modifies aac_parse_header to check for an explicit decoder config
set by the sdp parser (e.g. a:fmtp # config=hexvalue). If it has and there
is an ADTS header present, it skips the header and copies the RTP
payload directly as an AAC packet.

This resolves an issue observed with some inexpensive IP cameras.

Signed-off-by: Jeff Mahoney <jeffm at jeffm.io>
---
 libavformat/rtpdec_mpeg4.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c
index 34c7950bcc..dd0ced790e 100644
--- a/libavformat/rtpdec_mpeg4.c
+++ b/libavformat/rtpdec_mpeg4.c
@@ -176,7 +176,7 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data,
                             int flags)
 {
     int ret;
-
+    AVCodecParameters *par = st->codecpar;
 
     if (!buf) {
         if (data->cur_au_index > data->nb_au_headers) {
@@ -204,6 +204,38 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data,
         return 1;
     }
 
+    /* Check for an explicit decoder config (e.g. SDP a:fmtp... config=) */
+    if (par->extradata && len > 7) {
+        /*
+         * Start of ADTS header - syncword
+         * If present skip the header and copy the entire payload as AAC data
+         */
+        if (buf[0] == 0xff && (buf[1] & 0xf0) == 0xf0) {
+            /*
+             * The ADTS header is 7 or 9 bytes depending on whether
+             * the protection absent bit is set.  If it is unset, a 16-bit CRC
+             * is appended to the header.
+             */
+            size_t header_size = 7 + ((buf[1] & 0x01) ? 0 : 2);
+            if (len < header_size) {
+                ac_log(ctx, AV_LOG_ERROR, "Error parsing ADTS header\n");
+                return -1;
+            }
+
+            buf += header_size;
+            len -= header_size;
+
+            if ((ret = av_new_packet(pkt, len)) < 0) {
+                av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
+                return ret;
+            }
+            memcpy(pkt->data, buf, len);
+            pkt->stream_index = st->index;
+
+            return 0;
+        }
+    }
+
     if (rtp_parse_mp4_au(data, buf, len)) {
         av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n");
         return -1;
-- 
2.33.0



More information about the ffmpeg-devel mailing list