mirror of https://git.ffmpeg.org/ffmpeg.git
apedec: add ability to check CRC
The CRC flag is only signalled once every few minutes but CRC is still always present so the patch uses the file version instead. CRC on 24-bit files wants non-padded samples so skip such files. Some corrupt samples may have been output before the final check depending on the -max_samples setting.
This commit is contained in:
parent
731c775898
commit
1cc8eecd38
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
|
#include "libavutil/crc.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "lossless_audiodsp.h"
|
#include "lossless_audiodsp.h"
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
|
@ -147,7 +148,8 @@ typedef struct APEContext {
|
||||||
int fset; ///< which filter set to use (calculated from compression level)
|
int fset; ///< which filter set to use (calculated from compression level)
|
||||||
int flags; ///< global decoder flags
|
int flags; ///< global decoder flags
|
||||||
|
|
||||||
uint32_t CRC; ///< frame CRC
|
uint32_t CRC; ///< signalled frame CRC
|
||||||
|
uint32_t CRC_state; ///< accumulated CRC
|
||||||
int frameflags; ///< frame flags
|
int frameflags; ///< frame flags
|
||||||
APEPredictor predictor; ///< predictor used for final reconstruction
|
APEPredictor predictor; ///< predictor used for final reconstruction
|
||||||
|
|
||||||
|
@ -750,6 +752,7 @@ static int init_entropy_decoder(APEContext *ctx)
|
||||||
|
|
||||||
/* Read the frame flags if they exist */
|
/* Read the frame flags if they exist */
|
||||||
ctx->frameflags = 0;
|
ctx->frameflags = 0;
|
||||||
|
ctx->CRC_state = UINT32_MAX;
|
||||||
if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) {
|
if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) {
|
||||||
ctx->CRC &= ~0x80000000;
|
ctx->CRC &= ~0x80000000;
|
||||||
|
|
||||||
|
@ -1577,6 +1580,27 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data,
|
||||||
|
|
||||||
s->samples -= blockstodecode;
|
s->samples -= blockstodecode;
|
||||||
|
|
||||||
|
if (avctx->err_recognition & AV_EF_CRCCHECK &&
|
||||||
|
s->fileversion >= 3900 && s->bps < 24) {
|
||||||
|
uint32_t crc = s->CRC_state;
|
||||||
|
const AVCRC *crc_tab = av_crc_get_table(AV_CRC_32_IEEE_LE);
|
||||||
|
for (i = 0; i < blockstodecode; i++) {
|
||||||
|
for (ch = 0; ch < s->channels; ch++) {
|
||||||
|
uint8_t *smp = frame->data[ch] + (i*(s->bps >> 3));
|
||||||
|
crc = av_crc(crc_tab, crc, smp, s->bps >> 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->samples && (~crc >> 1) ^ s->CRC) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "CRC mismatch! Previously decoded "
|
||||||
|
"frames may have been affected as well.\n");
|
||||||
|
if (avctx->err_recognition & AV_EF_EXPLODE)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->CRC_state = crc;
|
||||||
|
}
|
||||||
|
|
||||||
*got_frame_ptr = 1;
|
*got_frame_ptr = 1;
|
||||||
|
|
||||||
return !s->samples ? avpkt->size : 0;
|
return !s->samples ? avpkt->size : 0;
|
||||||
|
|
Loading…
Reference in New Issue