📄 shorten.c
字号:
/* * Shorten decoder * Copyright (c) 2005 Jeff Muizelaar * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//** * @file shorten.c * Shorten decoder * @author Jeff Muizelaar * */#define DEBUG#include <limits.h>#include "avcodec.h"#include "bitstream.h"#include "golomb.h"#define MAX_CHANNELS 8#define MAX_BLOCKSIZE 65535#define OUT_BUFFER_SIZE 16384#define ULONGSIZE 2#define WAVE_FORMAT_PCM 0x0001#define DEFAULT_BLOCK_SIZE 256#define TYPESIZE 4#define CHANSIZE 0#define LPCQSIZE 2#define ENERGYSIZE 3#define BITSHIFTSIZE 2#define TYPE_S16HL 3#define TYPE_S16LH 5#define NWRAP 3#define NSKIPSIZE 1#define LPCQUANT 5#define V2LPCQOFFSET (1 << LPCQUANT)#define FNSIZE 2#define FN_DIFF0 0#define FN_DIFF1 1#define FN_DIFF2 2#define FN_DIFF3 3#define FN_QUIT 4#define FN_BLOCKSIZE 5#define FN_BITSHIFT 6#define FN_QLPC 7#define FN_ZERO 8#define FN_VERBATIM 9#define VERBATIM_CKSIZE_SIZE 5#define VERBATIM_BYTE_SIZE 8#define CANONICAL_HEADER_SIZE 44typedef struct ShortenContext { AVCodecContext *avctx; GetBitContext gb; int min_framesize, max_framesize; int channels; int32_t *decoded[MAX_CHANNELS]; int32_t *offset[MAX_CHANNELS]; uint8_t *bitstream; int bitstream_size; int bitstream_index; int allocated_bitstream_size; int header_size; uint8_t header[OUT_BUFFER_SIZE]; int version; int cur_chan; int bitshift; int nmean; int internal_ftype; int nwrap; int blocksize; int bitindex; int32_t lpcqoffset;} ShortenContext;static int shorten_decode_init(AVCodecContext * avctx){ ShortenContext *s = avctx->priv_data; s->avctx = avctx; return 0;}static void allocate_buffers(ShortenContext *s){ int i, chan; for (chan=0; chan<s->channels; chan++) { s->offset[chan] = av_realloc(s->offset[chan], sizeof(int32_t)*FFMAX(1, s->nmean)); s->decoded[chan] = av_realloc(s->decoded[chan], sizeof(int32_t)*(s->blocksize + s->nwrap)); for (i=0; i<s->nwrap; i++) s->decoded[chan][i] = 0; s->decoded[chan] += s->nwrap; }}static inline unsigned int get_uint(ShortenContext *s, int k){ if (s->version != 0) k = get_ur_golomb_shorten(&s->gb, ULONGSIZE); return get_ur_golomb_shorten(&s->gb, k);}static void fix_bitshift(ShortenContext *s, int32_t *buffer){ int i; if (s->bitshift != 0) for (i = 0; i < s->blocksize; i++) buffer[s->nwrap + i] <<= s->bitshift;}static void init_offset(ShortenContext *s){ int32_t mean = 0; int chan, i; int nblock = FFMAX(1, s->nmean); /* initialise offset */ switch (s->internal_ftype) { case TYPE_S16HL: case TYPE_S16LH: mean = 0; break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown audio type"); abort(); } for (chan = 0; chan < s->channels; chan++) for (i = 0; i < nblock; i++) s->offset[chan][i] = mean;}static int inline get_le32(GetBitContext *gb){ return bswap_32(get_bits_long(gb, 32));}static short inline get_le16(GetBitContext *gb){ return bswap_16(get_bits_long(gb, 16));}static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header_size){ GetBitContext hb; int len; int chunk_size; short wave_format; init_get_bits(&hb, header, header_size*8); if (get_le32(&hb) != MKTAG('R','I','F','F')) { av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n"); return -1; } chunk_size = get_le32(&hb); if (get_le32(&hb) != MKTAG('W','A','V','E')) { av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n"); return -1; } while (get_le32(&hb) != MKTAG('f','m','t',' ')) { len = get_le32(&hb); skip_bits(&hb, 8*len); } len = get_le32(&hb); if (len < 16) { av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n"); return -1; } wave_format = get_le16(&hb); switch (wave_format) { case WAVE_FORMAT_PCM: break; default: av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n"); return -1; } avctx->channels = get_le16(&hb); avctx->sample_rate = get_le32(&hb); avctx->bit_rate = get_le32(&hb) * 8; avctx->block_align = get_le16(&hb); avctx->bits_per_sample = get_le16(&hb); if (avctx->bits_per_sample != 16) { av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample\n"); return -1; } len -= 16; if (len > 0) av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len); return 0;}static int16_t * interleave_buffer(int16_t *samples, int nchan, int blocksize, int32_t **buffer) { int i, chan; for (i=0; i<blocksize; i++) for (chan=0; chan < nchan; chan++) *samples++ = FFMIN(buffer[chan][i], 32768); return samples;}static void decode_subframe_lpc(ShortenContext *s, int channel, int residual_size, int pred_order){ int sum, i, j; int coeffs[pred_order]; for (i=0; i<pred_order; i++) coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT); for (i=0; i < s->blocksize; i++) { sum = s->lpcqoffset; for (j=0; j<pred_order; j++) sum += coeffs[j] * s->decoded[channel][i-j-1]; s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + (sum >> LPCQUANT); }}static int shorten_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -