Unified · Split
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | +#include "libavutil/intreadwrite.h" | |
| 21 | 22 | #include "libavutil/mathematics.h" |
| 22 | 23 | #include "adx.h" |
| 23 | 24 | |
| @@ -32,3 +33,49 @@ void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff) · 8 unmodified lines | ||
| 32 | 33 | coeff[0] = lrintf(c * 2.0 * (1 << bits)); |
| 33 | 34 | coeff[1] = lrintf(-(c * c) * (1 << bits)); |
| 34 | 35 | } |
| 36 | + | |
| 37 | +int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, int bufsize, | |
| 38 | + int *header_size, int *coeff) | |
| 39 | +{ | |
| 40 | + int offset, cutoff; | |
| 41 | + | |
| 42 | + if (bufsize < 24) | |
| 43 | + return AVERROR_INVALIDDATA; | |
| 44 | + | |
| 45 | + if (AV_RB16(buf) != 0x8000) | |
| 46 | + return AVERROR_INVALIDDATA; | |
| 47 | + offset = AV_RB16(buf + 2) + 4; | |
| 48 | + | |
| 49 | + /* if copyright string is within the provided data, validate it */ | |
| 50 | + if (bufsize >= offset && memcmp(buf + offset - 6, "(c)CRI", 6)) | |
| 51 | + return AVERROR_INVALIDDATA; | |
| 52 | + | |
| 53 | + /* check for encoding=3 block_size=18, sample_size=4 */ | |
| 54 | + if (buf[4] != 3 || buf[5] != 18 || buf[6] != 4) { | |
| 55 | + av_log_ask_for_sample(avctx, "unsupported ADX format\n"); | |
| 56 | + return AVERROR_PATCHWELCOME; | |
| 57 | + } | |
| 58 | + | |
| 59 | + /* channels */ | |
| 60 | + avctx->channels = buf[7]; | |
| 61 | + if (avctx->channels > 2) | |
| 62 | + return AVERROR_INVALIDDATA; | |
| 63 | + | |
| 64 | + /* sample rate */ | |
| 65 | + avctx->sample_rate = AV_RB32(buf + 8); | |
| 66 | + if (avctx->sample_rate < 1 || | |
| 67 | + avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8)) | |
| 68 | + return AVERROR_INVALIDDATA; | |
| 69 | + | |
| 70 | + /* bit rate */ | |
| 71 | + avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES; | |
| 72 | + | |
| 73 | + /* LPC coefficients */ | |
| 74 | + if (coeff) { | |
| 75 | + cutoff = AV_RB16(buf + 16); | |
| 76 | + ff_adx_calculate_coeffs(cutoff, avctx->sample_rate, COEFF_BITS, coeff); | |
| 77 | + } | |
| 78 | + | |
| 79 | + *header_size = offset; | |
| 80 | + return 0; | |
| 81 | +} | |
| @@ -31,6 +31,10 @@ · 30 unmodified lines | ||
| 31 | 31 | #ifndef AVCODEC_ADX_H |
| 32 | 32 | #define AVCODEC_ADX_H |
| 33 | 33 | |
| 34 | +#include <stdint.h> | |
| 35 | + | |
| 36 | +#include "avcodec.h" | |
| 37 | + | |
| 34 | 38 | typedef struct { |
| 35 | 39 | int s1,s2; |
| 36 | 40 | } ADXChannelState; |
| @@ -47,6 +51,9 @@ typedef struct { · 10 unmodified lines | ||
| 47 | 51 | |
| 48 | 52 | #define COEFF_BITS 12 |
| 49 | 53 | |
| 54 | +#define BLOCK_SIZE 18 | |
| 55 | +#define BLOCK_SAMPLES 32 | |
| 56 | + | |
| 50 | 57 | /** |
| 51 | 58 | * Calculate LPC coefficients based on cutoff frequency and sample rate. |
| 52 | 59 | * |
| @@ -57,4 +64,18 @@ typedef struct { · 4 unmodified lines | ||
| 57 | 64 | */ |
| 58 | 65 | void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff); |
| 59 | 66 | |
| 67 | +/** | |
| 68 | + * Decode ADX stream header. | |
| 69 | + * Sets avctx->channels and avctx->sample_rate. | |
| 70 | + * | |
| 71 | + * @param avctx codec context | |
| 72 | + * @param buf header data | |
| 73 | + * @param bufsize data size, should be at least 24 bytes | |
| 74 | + * @param[out] header_size size of ADX header | |
| 75 | + * @param[out] coeff 2 LPC coefficients, can be NULL | |
| 76 | + * @return data offset or negative error code if header is invalid | |
| 77 | + */ | |
| 78 | +int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, int bufsize, | |
| 79 | + int *header_size, int *coeff); | |
| 80 | + | |
| 60 | 81 | #endif /* AVCODEC_ADX_H */ |
| @@ -33,9 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ |
| 34 | 34 | */ |
| 35 | 35 | |
| 36 | −#define BLOCK_SIZE 18 | |
| 37 | −#define BLOCK_SAMPLES 32 | |
| 38 | − | |
| 39 | 36 | static av_cold int adx_decode_init(AVCodecContext *avctx) |
| 40 | 37 | { |
| 41 | 38 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
| @@ -72,45 +69,18 @@ static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) · 30 unmodified lines | ||
| 72 | 69 | prev->s2 = s2; |
| 73 | 70 | } |
| 74 | 71 | |
| 75 | −/** | |
| 76 | − * Decode stream header. | |
| 77 | − * | |
| 78 | − * @param avctx codec context | |
| 79 | − * @param buf packet data | |
| 80 | − * @param bufsize packet size | |
| 81 | − * @return data offset or negative error code if header is invalid | |
| 82 | − */ | |
| 83 | 72 | static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, |
| 84 | 73 | int bufsize) |
| 85 | 74 | { |
| 86 | 75 | ADXContext *c = avctx->priv_data; |
| 87 | − int offset, cutoff; | |
| 88 | − | |
| 89 | − if (AV_RB16(buf) != 0x8000) | |
| 90 | − return AVERROR_INVALIDDATA; | |
| 91 | − offset = AV_RB16(buf + 2) + 4; | |
| 92 | − if (bufsize < offset || memcmp(buf + offset - 6, "(c)CRI", 6)) | |
| 93 | − return AVERROR_INVALIDDATA; | |
| 94 | − | |
| 95 | − /* check for encoding=3 block_size=18, sample_size=4 */ | |
| 96 | − if (buf[4] != 3 || buf[5] != 18 || buf[6] != 4) { | |
| 97 | − av_log_ask_for_sample(avctx, "unsupported ADX format\n"); | |
| 98 | − return AVERROR_PATCHWELCOME; | |
| 99 | − } | |
| 100 | − | |
| 101 | − c->channels = avctx->channels = buf[7]; | |
| 102 | − if (avctx->channels > 2) | |
| 103 | − return AVERROR_INVALIDDATA; | |
| 104 | − avctx->sample_rate = AV_RB32(buf + 8); | |
| 105 | − if (avctx->sample_rate < 1 || | |
| 106 | − avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8)) | |
| 107 | − return AVERROR_INVALIDDATA; | |
| 108 | − avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES; | |
| 76 | + int ret, header_size; | |
| 109 | 77 | |
| 110 | − cutoff = AV_RB16(buf + 16); | |
| 111 | − ff_adx_calculate_coeffs(cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); | |
| 78 | + if ((ret = ff_adx_decode_header(avctx, buf, bufsize, &header_size, | |
| 79 | + c->coeff)) < 0) | |
| 80 | + return ret; | |
| 112 | 81 | |
| 113 | − return offset; | |
| 82 | + c->channels = avctx->channels; | |
| 83 | + return header_size; | |
| 114 | 84 | } |
| 115 | 85 | |
| 116 | 86 | static int adx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |