]> git.sesse.net Git - ffmpeg/commitdiff
mpegaudiodec_template: add ability to check CRC
authorLynne <dev@lynne.ee>
Wed, 6 Mar 2019 17:04:04 +0000 (17:04 +0000)
committerLynne <dev@lynne.ee>
Tue, 26 May 2020 09:23:11 +0000 (10:23 +0100)
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

index 3f1674e82799ae75acb0d548722d994bf0d41585..3d7e3ba4f2e021bdc9f596d8c2b901e8d7149eb2 100644 (file)
@@ -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: