diff mbox series

[FFmpeg-devel,2/3] mpegaudiodec_template: add ability to check CRC

Message ID M7yYqAp--3-2@lynne.ee
State Accepted
Commit e69f407b52110387800ee0531aa78e213b214150
Headers show
Series Untitled series #1283
Related show

Commit Message

Lynne May 22, 2020, 10:44 p.m. UTC
Posting this again.

A lot of files have CRC included. 
The CRC only covers 34 bytes at most from the frame but it should still be
enough for some amount of error detection.

Patch attached.
Subject: [PATCH 2/3] mpegaudiodec_template: add ability to check CRC

A lot of files have CRC included.
The CRC only covers 34 bytes at most from the frame but it should still be
enough for some amount of error detection.
---
 libavcodec/mpegaudiodec_template.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index 3f1674e827..3d7e3ba4f2 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -27,6 +27,7 @@ 
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
 #include "libavutil/channel_layout.h"
+#include "libavutil/crc.h"
 #include "libavutil/float_dsp.h"
 #include "libavutil/libm.h"
 #include "avcodec.h"
@@ -1565,9 +1566,22 @@  static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples,
 
     init_get_bits(&s->gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE) * 8);
 
-    /* skip error protection field */
-    if (s->error_protection)
-        skip_bits(&s->gb, 16);
+    if (s->error_protection) {
+        uint16_t crc = get_bits(&s->gb, 16);
+        if (s->err_recognition & AV_EF_CRCCHECK) {
+            const int sec_len = s->lsf ? ((s->nb_channels == 1) ? 9  : 17) :
+                                         ((s->nb_channels == 1) ? 17 : 32);
+            const AVCRC *crc_tab = av_crc_get_table(AV_CRC_16_ANSI);
+            uint32_t crc_cal = av_crc(crc_tab, UINT16_MAX, &buf[2], 2);
+            crc_cal = av_crc(crc_tab, crc_cal, &buf[6], sec_len);
+
+            if (av_bswap16(crc) ^ crc_cal) {
+                av_log(s->avctx, AV_LOG_ERROR, "CRC mismatch!\n");
+                if (s->err_recognition & AV_EF_EXPLODE)
+                    return AVERROR_INVALIDDATA;
+            }
+        }
+    }
 
     switch(s->layer) {
     case 1: