diff options
author | Thilo Borgmann <thilo.borgmann@googlemail.com> | 2010-06-29 20:56:28 +0400 |
---|---|---|
committer | Thilo Borgmann <thilo.borgmann@googlemail.com> | 2010-06-29 20:56:28 +0400 |
commit | cbb39648c1699820f92d36b577caeaac44fa3250 (patch) | |
tree | 047ed6461b23d39fb012a5cfa2a0af8c0e996e42 | |
parent | a4edc5a9df99bdbe1b56fa4f6656ce37dfb48f37 (diff) |
Add CRC check to the ALS decoder.
Originally committed as revision 23889 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/alsdec.c | 95 |
1 files changed, 89 insertions, 6 deletions
diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index f75398fe9e..3bfe9e0cff 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -35,6 +35,8 @@ #include "mpeg4audio.h" #include "bytestream.h" #include "bgmc.h" +#include "dsputil.h" +#include "libavutil/crc.h" #include <stdint.h> @@ -154,6 +156,7 @@ typedef struct { uint32_t samples; ///< number of samples, 0xFFFFFFFF if unknown int resolution; ///< 000 = 8-bit; 001 = 16-bit; 010 = 24-bit; 011 = 32-bit int floating; ///< 1 = IEEE 32-bit floating-point, 0 = integer + int msb_first; ///< 1 = original CRC calculated on big-endian system, 0 = little-endian int frame_length; ///< frame length for each frame (last frame may differ) int ra_distance; ///< distance between RA frames (in frames, 0...255) enum RA_Flag ra_flag; ///< indicates where the size of ra units is stored @@ -171,6 +174,7 @@ typedef struct { int rlslms; ///< use "Recursive Least Square-Least Mean Square" predictor: 1 = on, 0 = off int chan_config_info; ///< mapping of channels to loudspeaker locations. Unused until setting channel configuration is implemented. int *chan_pos; ///< original channel positions + int crc_enabled; ///< enable Cyclic Redundancy Checksum } ALSSpecificConfig; @@ -188,6 +192,10 @@ typedef struct { AVCodecContext *avctx; ALSSpecificConfig sconf; GetBitContext gb; + DSPContext dsp; + const AVCRC *crc_table; + uint32_t crc_org; ///< CRC value of the original input data + uint32_t crc; ///< CRC value calculated from decoded data unsigned int cur_frame_length; ///< length of the current frame to decode unsigned int frame_id; ///< the frame ID / number of the current frame unsigned int js_switch; ///< if true, joint-stereo decoding is enforced @@ -211,6 +219,7 @@ typedef struct { int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block int32_t **raw_samples; ///< decoded raw samples for each channel int32_t *raw_buffer; ///< contains all decoded raw samples including carryover samples + uint8_t *crc_buffer; ///< buffer of byte order corrected samples used for CRC check } ALSDecContext; @@ -268,7 +277,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) { GetBitContext gb; uint64_t ht_size; - int i, config_offset, crc_enabled; + int i, config_offset; MPEG4AudioConfig m4ac; ALSSpecificConfig *sconf = &ctx->sconf; AVCodecContext *avctx = ctx->avctx; @@ -297,7 +306,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) skip_bits(&gb, 3); // skip file_type sconf->resolution = get_bits(&gb, 3); sconf->floating = get_bits1(&gb); - skip_bits1(&gb); // skip msb_first + sconf->msb_first = get_bits1(&gb); sconf->frame_length = get_bits(&gb, 16) + 1; sconf->ra_distance = get_bits(&gb, 8); sconf->ra_flag = get_bits(&gb, 2); @@ -312,7 +321,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) sconf->mc_coding = get_bits1(&gb); sconf->chan_config = get_bits1(&gb); sconf->chan_sort = get_bits1(&gb); - crc_enabled = get_bits1(&gb); + sconf->crc_enabled = get_bits1(&gb); sconf->rlslms = get_bits1(&gb); skip_bits(&gb, 5); // skip 5 reserved bits skip_bits1(&gb); // skip aux_data_enabled @@ -375,12 +384,17 @@ static av_cold int read_specific_config(ALSDecContext *ctx) skip_bits_long(&gb, ht_size); - // skip the crc data - if (crc_enabled) { + // initialize CRC calculation + if (sconf->crc_enabled) { if (get_bits_left(&gb) < 32) return -1; - skip_bits_long(&gb, 32); + if (avctx->error_recognition >= FF_ER_CAREFUL) { + ctx->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); + ctx->crc = 0xFFFFFFFF; + ctx->crc_org = ~get_bits_long(&gb, 32); + } else + skip_bits_long(&gb, 32); } @@ -1437,6 +1451,59 @@ static int decode_frame(AVCodecContext *avctx, INTERLEAVE_OUTPUT(32) } + // update CRC + if (sconf->crc_enabled && avctx->error_recognition >= FF_ER_CAREFUL) { + int swap = HAVE_BIGENDIAN != sconf->msb_first; + + if (ctx->avctx->bits_per_raw_sample == 24) { + int32_t *src = data; + + for (sample = 0; + sample < ctx->cur_frame_length * avctx->channels; + sample++) { + int32_t v; + + if (swap) + v = bswap_32(src[sample]); + else + v = src[sample]; + if (!HAVE_BIGENDIAN) + v >>= 8; + + ctx->crc = av_crc(ctx->crc_table, ctx->crc, (uint8_t*)(&v), 3); + } + } else { + uint8_t *crc_source; + + if (swap) { + if (ctx->avctx->bits_per_raw_sample <= 16) { + int16_t *src = (int16_t*) data; + int16_t *dest = (int16_t*) ctx->crc_buffer; + for (sample = 0; + sample < ctx->cur_frame_length * avctx->channels; + sample++) + *dest++ = bswap_16(src[sample]); + } else { + ctx->dsp.bswap_buf((uint32_t*)ctx->crc_buffer, data, + ctx->cur_frame_length * avctx->channels); + } + crc_source = ctx->crc_buffer; + } else { + crc_source = data; + } + + ctx->crc = av_crc(ctx->crc_table, ctx->crc, crc_source, size); + } + + + // check CRC sums if this is the last frame + if (ctx->cur_frame_length != sconf->frame_length && + ctx->crc_org != ctx->crc) { + av_log(avctx, AV_LOG_ERROR, "CRC error.\n"); + } + } + + bytes_read = invalid_frame ? buffer_size : (get_bits_count(&ctx->gb) + 7) >> 3; @@ -1606,6 +1673,22 @@ static av_cold int decode_init(AVCodecContext *avctx) for (c = 1; c < avctx->channels; c++) ctx->raw_samples[c] = ctx->raw_samples[c - 1] + channel_size; + // allocate crc buffer + if (HAVE_BIGENDIAN != sconf->msb_first && sconf->crc_enabled && + avctx->error_recognition >= FF_ER_CAREFUL) { + ctx->crc_buffer = av_malloc(sizeof(*ctx->crc_buffer) * + ctx->cur_frame_length * + avctx->channels * + (av_get_bits_per_sample_format(avctx->sample_fmt) >> 3)); + if (!ctx->crc_buffer) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + decode_end(avctx); + return AVERROR(ENOMEM); + } + } + + dsputil_init(&ctx->dsp, avctx); + return 0; } |