diff options
author | Ramiro Polla <ramiro.polla@gmail.com> | 2008-08-13 18:47:03 +0000 |
---|---|---|
committer | Ramiro Polla <ramiro.polla@gmail.com> | 2008-08-13 18:47:03 +0000 |
commit | ce15710f554ef3520f968c8b4284a0f576611c95 (patch) | |
tree | aaaba49c251115e36e7921f2e534b170b3ff42cd | |
parent | e7327dbba70a1dff3bc4c2f353adff174753edff (diff) | |
download | ffmpeg-ce15710f554ef3520f968c8b4284a0f576611c95.tar.gz |
mlp: Split common code from parser and decoder to be used by encoder.
Originally committed as revision 14733 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/Makefile | 4 | ||||
-rw-r--r-- | libavcodec/mlp.c | 120 | ||||
-rw-r--r-- | libavcodec/mlp.h | 109 | ||||
-rw-r--r-- | libavcodec/mlp_parser.c | 33 | ||||
-rw-r--r-- | libavcodec/mlpdec.c | 161 |
5 files changed, 247 insertions, 180 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d08a8d5d47..df08e02605 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -109,7 +109,7 @@ OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpeg.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o mpegvideo_enc.o motion_est.o ratecontrol.o mpeg12data.o mpegvideo.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o -OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o +OBJS-$(CONFIG_MLP_DECODER) += mlp.o mlpdec.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o @@ -348,7 +348,7 @@ OBJS-$(CONFIG_H261_PARSER) += h261_parser.o OBJS-$(CONFIG_H263_PARSER) += h263_parser.o OBJS-$(CONFIG_H264_PARSER) += h264_parser.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o -OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o +OBJS-$(CONFIG_MLP_PARSER) += mlp.o mlp_parser.o OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o mpeg12data.o mpegvideo.o error_resilience.o OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o mpegaudiodecheader.o mpegaudiodata.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o diff --git a/libavcodec/mlp.c b/libavcodec/mlp.c new file mode 100644 index 0000000000..f2a0276574 --- /dev/null +++ b/libavcodec/mlp.c @@ -0,0 +1,120 @@ +/* + * MLP codec common code + * Copyright (c) 2007-2008 Ian Caulfield + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> + +#include "libavutil/crc.h" +#include "mlp.h" + +const uint8_t ff_mlp_huffman_tables[3][18][2] = { + { /* Huffman table 0, -7 - +10 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x04, 3}, {0x05, 3}, {0x06, 3}, {0x07, 3}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + }, { /* Huffman table 1, -7 - +8 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x02, 2}, {0x03, 2}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + }, { /* Huffman table 2, -7 - +7 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x01, 1}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + } +}; + +static int crc_init = 0; +static AVCRC crc_63[1024]; +static AVCRC crc_1D[1024]; + + +static int crc_init_2D = 0; +static AVCRC crc_2D[1024]; + +int av_cold ff_mlp_init_crc2D(AVCodecParserContext *s) +{ + if (!crc_init_2D) { + av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D)); + crc_init_2D = 1; + } + + return 0; +} + +void av_cold ff_mlp_init_crc() +{ + if (!crc_init) { + av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63)); + av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D)); + crc_init = 1; + } +} + +uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size) +{ + uint16_t crc; + + crc = av_crc(crc_2D, 0, buf, buf_size - 2); + crc ^= AV_RL16(buf + buf_size - 2); + return crc; +} + +uint8_t ff_mlp_checksum8(const uint8_t *buf, unsigned int buf_size) +{ + uint8_t checksum = av_crc(crc_63, 0x3c, buf, buf_size - 1); // crc_63[0xa2] == 0x3c + checksum ^= buf[buf_size-1]; + return checksum; +} + +uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size) +{ + int i; + int num_bytes = (bit_size + 2) / 8; + + int crc = crc_1D[buf[0] & 0x3f]; + crc = av_crc(crc_1D, crc, buf + 1, num_bytes - 2); + crc ^= buf[num_bytes - 1]; + + for (i = 0; i < ((bit_size + 2) & 7); i++) { + crc <<= 1; + if (crc & 0x100) + crc ^= 0x11D; + crc ^= (buf[num_bytes] >> (7 - i)) & 1; + } + + return crc; +} + +uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size) +{ + uint32_t scratch = 0; + const uint8_t *buf_end = buf + buf_size; + + for (; buf < buf_end - 3; buf += 4) + scratch ^= *((const uint32_t*)buf); + + scratch ^= scratch >> 16; + scratch ^= scratch >> 8; + + for (; buf < buf_end; buf++) + scratch ^= *buf; + + return scratch; +} diff --git a/libavcodec/mlp.h b/libavcodec/mlp.h new file mode 100644 index 0000000000..43c3b272a5 --- /dev/null +++ b/libavcodec/mlp.h @@ -0,0 +1,109 @@ +/* + * MLP codec common header file + * Copyright (c) 2007-2008 Ian Caulfield + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFMPEG_MLP_H +#define FFMPEG_MLP_H + +#include <stdint.h> + +#include "avcodec.h" + +/** Maximum number of channels that can be decoded. */ +#define MAX_CHANNELS 16 + +/** Maximum number of matrices used in decoding; most streams have one matrix + * per output channel, but some rematrix a channel (usually 0) more than once. + */ + +#define MAX_MATRICES 15 + +/** Maximum number of substreams that can be decoded. This could also be set + * higher, but I haven't seen any examples with more than two. */ +#define MAX_SUBSTREAMS 2 + +/** maximum sample frequency seen in files */ +#define MAX_SAMPLERATE 192000 + +/** maximum number of audio samples within one access unit */ +#define MAX_BLOCKSIZE (40 * (MAX_SAMPLERATE / 48000)) +/** next power of two greater than MAX_BLOCKSIZE */ +#define MAX_BLOCKSIZE_POW2 (64 * (MAX_SAMPLERATE / 48000)) + +/** number of allowed filters */ +#define NUM_FILTERS 2 + +/** The maximum number of taps in either the IIR or FIR filter; + * I believe MLP actually specifies the maximum order for IIR filters as four, + * and that the sum of the orders of both filters must be <= 8. */ +#define MAX_FILTER_ORDER 8 + +#define FIR 0 +#define IIR 1 + +/** filter data */ +typedef struct { + uint8_t order; ///< number of taps in filter + uint8_t shift; ///< Right shift to apply to output of filter. + + int32_t coeff[MAX_FILTER_ORDER]; + int32_t state[MAX_FILTER_ORDER]; +} FilterParams; + +/** sample data coding information */ +typedef struct { + FilterParams filter_params[NUM_FILTERS]; + + int16_t huff_offset; ///< Offset to apply to residual values. + int32_t sign_huff_offset; ///< sign/rounding-corrected version of huff_offset + uint8_t codebook; ///< Which VLC codebook to use to read residuals. + uint8_t huff_lsbs; ///< Size of residual suffix not encoded using VLC. +} ChannelParams; + +/** Tables defining the Huffman codes. + * There are three entropy coding methods used in MLP (four if you count + * "none" as a method). These use the same sequences for codes starting with + * 00 or 01, but have different codes starting with 1. */ + +extern const uint8_t ff_mlp_huffman_tables[3][18][2]; + +/** MLP uses checksums that seem to be based on the standard CRC algorithm, but + * are not (in implementation terms, the table lookup and XOR are reversed). + * We can implement this behavior using a standard av_crc on all but the + * last element, then XOR that with the last element. */ + +uint8_t ff_mlp_checksum8 (const uint8_t *buf, unsigned int buf_size); +uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size); + +/** Calculate an 8-bit checksum over a restart header -- a non-multiple-of-8 + * number of bits, starting two bits into the first byte of buf. */ + +uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size); + +/** XOR together all the bytes of a buffer. + * Does this belong in dspcontext? */ + +uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size); + +int ff_mlp_init_crc2D(AVCodecParserContext *s); + +void ff_mlp_init_crc(); + +#endif /* FFMPEG_MLP_H */ diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 7668857d70..4400d71fc4 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -30,6 +30,7 @@ #include "bitstream.h" #include "parser.h" #include "mlp_parser.h" +#include "mlp.h" static const uint8_t mlp_quants[16] = { 16, 20, 24, 0, 0, 0, 0, 0, @@ -64,34 +65,6 @@ static int truehd_channels(int chanmap) return channels; } -static int crc_init = 0; -static AVCRC crc_2D[1024]; - -/** MLP uses checksums that seem to be based on the standard CRC algorithm, but - * are not (in implementation terms, the table lookup and XOR are reversed). - * We can implement this behavior using a standard av_crc on all but the - * last element, then XOR that with the last element. - */ - -static uint16_t mlp_checksum16(const uint8_t *buf, unsigned int buf_size) -{ - uint16_t crc; - - crc = av_crc(crc_2D, 0, buf, buf_size - 2); - crc ^= AV_RL16(buf + buf_size - 2); - return crc; -} - -static int av_cold mlp_parse_init(AVCodecParserContext *s) -{ - if (!crc_init) { - av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D)); - crc_init = 1; - } - - return 0; -} - /** Read a major sync info header - contains high level information about * the stream - sample rate, channel arrangement etc. Most of this * information is not actually necessary for decoding, only for playback. @@ -110,7 +83,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) return -1; } - checksum = mlp_checksum16(gb->buffer, 26); + checksum = ff_mlp_checksum16(gb->buffer, 26); if (checksum != AV_RL16(gb->buffer+26)) { av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); return -1; @@ -310,7 +283,7 @@ lost_sync: AVCodecParser mlp_parser = { { CODEC_ID_MLP }, sizeof(MLPParseContext), - mlp_parse_init, + ff_mlp_init_crc2D, mlp_parse, NULL, }; diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 37111be835..d44c9b0b29 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -32,35 +32,7 @@ #include "libavutil/crc.h" #include "parser.h" #include "mlp_parser.h" - -/** Maximum number of channels that can be decoded. */ -#define MAX_CHANNELS 16 - -/** Maximum number of matrices used in decoding; most streams have one matrix - * per output channel, but some rematrix a channel (usually 0) more than once. - */ - -#define MAX_MATRICES 15 - -/** Maximum number of substreams that can be decoded. This could also be set - * higher, but I haven't seen any examples with more than two. */ -#define MAX_SUBSTREAMS 2 - -/** maximum sample frequency seen in files */ -#define MAX_SAMPLERATE 192000 - -/** maximum number of audio samples within one access unit */ -#define MAX_BLOCKSIZE (40 * (MAX_SAMPLERATE / 48000)) -/** next power of two greater than MAX_BLOCKSIZE */ -#define MAX_BLOCKSIZE_POW2 (64 * (MAX_SAMPLERATE / 48000)) - -/** number of allowed filters */ -#define NUM_FILTERS 2 - -/** The maximum number of taps in either the IIR or FIR filter; - * I believe MLP actually specifies the maximum order for IIR filters as four, - * and that the sum of the orders of both filters must be <= 8. */ -#define MAX_FILTER_ORDER 8 +#include "mlp.h" /** number of bits used for VLC lookup - longest Huffman code is 9 */ #define VLC_BITS 9 @@ -139,28 +111,6 @@ typedef struct SubStream { } SubStream; -#define FIR 0 -#define IIR 1 - -/** filter data */ -typedef struct { - uint8_t order; ///< number of taps in filter - uint8_t shift; ///< Right shift to apply to output of filter. - - int32_t coeff[MAX_FILTER_ORDER]; - int32_t state[MAX_FILTER_ORDER]; -} FilterParams; - -/** sample data coding information */ -typedef struct { - FilterParams filter_params[NUM_FILTERS]; - - int16_t huff_offset; ///< Offset to apply to residual values. - int32_t sign_huff_offset; ///< sign/rounding-corrected version of huff_offset - uint8_t codebook; ///< Which VLC codebook to use to read residuals. - uint8_t huff_lsbs; ///< Size of residual suffix not encoded using VLC. -} ChannelParams; - typedef struct MLPDecodeContext { AVCodecContext *avctx; @@ -187,88 +137,23 @@ typedef struct MLPDecodeContext { int32_t sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS+2]; } MLPDecodeContext; -/** Tables defining the Huffman codes. - * There are three entropy coding methods used in MLP (four if you count - * "none" as a method). These use the same sequences for codes starting with - * 00 or 01, but have different codes starting with 1. */ - -static const uint8_t huffman_tables[3][18][2] = { - { /* Huffman table 0, -7 - +10 */ - {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, - {0x04, 3}, {0x05, 3}, {0x06, 3}, {0x07, 3}, - {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, - }, { /* Huffman table 1, -7 - +8 */ - {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, - {0x02, 2}, {0x03, 2}, - {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, - }, { /* Huffman table 2, -7 - +7 */ - {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, - {0x01, 1}, - {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, - } -}; - static VLC huff_vlc[3]; -static int crc_init = 0; -static AVCRC crc_63[1024]; -static AVCRC crc_1D[1024]; - - /** Initialize static data, constant between all invocations of the codec. */ static av_cold void init_static() { INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, - &huffman_tables[0][0][1], 2, 1, - &huffman_tables[0][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[0][0][1], 2, 1, + &ff_mlp_huffman_tables[0][0][0], 2, 1, 512); INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, - &huffman_tables[1][0][1], 2, 1, - &huffman_tables[1][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[1][0][1], 2, 1, + &ff_mlp_huffman_tables[1][0][0], 2, 1, 512); INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, - &huffman_tables[2][0][1], 2, 1, - &huffman_tables[2][0][0], 2, 1, 512); + &ff_mlp_huffman_tables[2][0][1], 2, 1, + &ff_mlp_huffman_tables[2][0][0], 2, 1, 512); - if (!crc_init) { - av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63)); - av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D)); - crc_init = 1; - } -} - - -/** MLP uses checksums that seem to be based on the standard CRC algorithm, but - * are not (in implementation terms, the table lookup and XOR are reversed). - * We can implement this behavior using a standard av_crc on all but the - * last element, then XOR that with the last element. */ - -static uint8_t mlp_checksum8(const uint8_t *buf, unsigned int buf_size) -{ - uint8_t checksum = av_crc(crc_63, 0x3c, buf, buf_size - 1); // crc_63[0xa2] == 0x3c - checksum ^= buf[buf_size-1]; - return checksum; -} - -/** Calculate an 8-bit checksum over a restart header -- a non-multiple-of-8 - * number of bits, starting two bits into the first byte of buf. */ - -static uint8_t mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size) -{ - int i; - int num_bytes = (bit_size + 2) / 8; - - int crc = crc_1D[buf[0] & 0x3f]; - crc = av_crc(crc_1D, crc, buf + 1, num_bytes - 2); - crc ^= buf[num_bytes - 1]; - - for (i = 0; i < ((bit_size + 2) & 7); i++) { - crc <<= 1; - if (crc & 0x100) - crc ^= 0x11D; - crc ^= (buf[num_bytes] >> (7 - i)) & 1; - } - - return crc; + ff_mlp_init_crc(); } static inline int32_t calculate_sign_huff(MLPDecodeContext *m, @@ -506,7 +391,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, } } - checksum = mlp_restart_checksum(buf, get_bits_count(gbp) - start_count); + checksum = ff_mlp_restart_checksum(buf, get_bits_count(gbp) - start_count); if (checksum != get_bits(gbp, 8)) av_log(m->avctx, AV_LOG_ERROR, "restart header checksum error\n"); @@ -975,26 +860,6 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, } -/** XOR together all the bytes of a buffer. - * Does this belong in dspcontext? */ - -static uint8_t calculate_parity(const uint8_t *buf, unsigned int buf_size) -{ - uint32_t scratch = 0; - const uint8_t *buf_end = buf + buf_size; - - for (; buf < buf_end - 3; buf += 4) - scratch ^= *((const uint32_t*)buf); - - scratch ^= scratch >> 16; - scratch ^= scratch >> 8; - - for (; buf < buf_end; buf++) - scratch ^= *buf; - - return scratch; -} - /** Read an access unit from the stream. * Returns < 0 on error, 0 if not enough data is present in the input stream * otherwise returns the number of bytes consumed. */ @@ -1078,8 +943,8 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, substream_start = end; } - parity_bits = calculate_parity(buf, 4); - parity_bits ^= calculate_parity(buf + header_size, substr_header_size); + parity_bits = ff_mlp_calculate_parity(buf, 4); + parity_bits ^= ff_mlp_calculate_parity(buf + header_size, substr_header_size); if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { av_log(avctx, AV_LOG_ERROR, "Parity check failed.\n"); @@ -1145,12 +1010,12 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, substream_parity_present[substr]) { uint8_t parity, checksum; - parity = calculate_parity(buf, substream_data_len[substr] - 2); + parity = ff_mlp_calculate_parity(buf, substream_data_len[substr] - 2); if ((parity ^ get_bits(&gb, 8)) != 0xa9) av_log(m->avctx, AV_LOG_ERROR, "Substream %d parity check failed.\n", substr); - checksum = mlp_checksum8(buf, substream_data_len[substr] - 2); + checksum = ff_mlp_checksum8(buf, substream_data_len[substr] - 2); if (checksum != get_bits(&gb, 8)) av_log(m->avctx, AV_LOG_ERROR, "Substream %d checksum failed.\n", substr); |