diff options
Diffstat (limited to 'ffmpeg1/libavcodec/shorten.c')
| -rw-r--r-- | ffmpeg1/libavcodec/shorten.c | 671 |
1 files changed, 0 insertions, 671 deletions
diff --git a/ffmpeg1/libavcodec/shorten.c b/ffmpeg1/libavcodec/shorten.c deleted file mode 100644 index 1d3b6eb..0000000 --- a/ffmpeg1/libavcodec/shorten.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Shorten decoder - * Copyright (c) 2005 Jeff Muizelaar - * - * 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 - */ - -/** - * @file - * Shorten decoder - * @author Jeff Muizelaar - * - */ - -#include <limits.h> -#include "avcodec.h" -#include "bytestream.h" -#include "get_bits.h" -#include "golomb.h" -#include "internal.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_S8 1 -#define TYPE_U8 2 -#define TYPE_S16HL 3 -#define TYPE_U16HL 4 -#define TYPE_S16LH 5 -#define TYPE_U16LH 6 - -#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 - -/** indicates if the FN_* command is audio or non-audio */ -static const uint8_t is_audio_command[10] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }; - -#define VERBATIM_CKSIZE_SIZE 5 -#define VERBATIM_BYTE_SIZE 8 -#define CANONICAL_HEADER_SIZE 44 - -typedef struct ShortenContext { - AVCodecContext *avctx; - GetBitContext gb; - - int min_framesize, max_framesize; - unsigned channels; - - int32_t *decoded[MAX_CHANNELS]; - int32_t *decoded_base[MAX_CHANNELS]; - int32_t *offset[MAX_CHANNELS]; - int *coeffs; - uint8_t *bitstream; - int bitstream_size; - int bitstream_index; - unsigned 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; - int got_header; - int got_quit_command; -} ShortenContext; - -static av_cold int shorten_decode_init(AVCodecContext *avctx) -{ - ShortenContext *s = avctx->priv_data; - s->avctx = avctx; - - return 0; -} - -static int allocate_buffers(ShortenContext *s) -{ - int i, chan; - int *coeffs; - void *tmp_ptr; - - for (chan = 0; chan < s->channels; chan++) { - if (FFMAX(1, s->nmean) >= UINT_MAX / sizeof(int32_t)) { - av_log(s->avctx, AV_LOG_ERROR, "nmean too large\n"); - return AVERROR_INVALIDDATA; - } - if (s->blocksize + s->nwrap >= UINT_MAX / sizeof(int32_t) || - s->blocksize + s->nwrap <= (unsigned)s->nwrap) { - av_log(s->avctx, AV_LOG_ERROR, - "s->blocksize + s->nwrap too large\n"); - return AVERROR_INVALIDDATA; - } - - tmp_ptr = - av_realloc(s->offset[chan], sizeof(int32_t) * FFMAX(1, s->nmean)); - if (!tmp_ptr) - return AVERROR(ENOMEM); - s->offset[chan] = tmp_ptr; - - tmp_ptr = av_realloc(s->decoded_base[chan], (s->blocksize + s->nwrap) * - sizeof(s->decoded_base[0][0])); - if (!tmp_ptr) - return AVERROR(ENOMEM); - s->decoded_base[chan] = tmp_ptr; - for (i = 0; i < s->nwrap; i++) - s->decoded_base[chan][i] = 0; - s->decoded[chan] = s->decoded_base[chan] + s->nwrap; - } - - coeffs = av_realloc(s->coeffs, s->nwrap * sizeof(*s->coeffs)); - if (!coeffs) - return AVERROR(ENOMEM); - s->coeffs = coeffs; - - return 0; -} - -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[i] <<= s->bitshift; -} - -static int 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_U8: - s->avctx->sample_fmt = AV_SAMPLE_FMT_U8P; - mean = 0x80; - break; - case TYPE_S16HL: - case TYPE_S16LH: - s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "unknown audio type\n"); - return AVERROR_PATCHWELCOME; - } - - for (chan = 0; chan < s->channels; chan++) - for (i = 0; i < nblock; i++) - s->offset[chan][i] = mean; - return 0; -} - -static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header, - int header_size) -{ - int len, bps; - short wave_format; - const uint8_t *end= header + header_size; - - if (bytestream_get_le32(&header) != MKTAG('R', 'I', 'F', 'F')) { - av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n"); - return AVERROR_INVALIDDATA; - } - - header += 4; /* chunk size */ - - if (bytestream_get_le32(&header) != MKTAG('W', 'A', 'V', 'E')) { - av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n"); - return AVERROR_INVALIDDATA; - } - - while (bytestream_get_le32(&header) != MKTAG('f', 'm', 't', ' ')) { - len = bytestream_get_le32(&header); - if (len<0 || end - header - 8 < len) - return AVERROR_INVALIDDATA; - header += len; - } - len = bytestream_get_le32(&header); - - if (len < 16) { - av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n"); - return AVERROR_INVALIDDATA; - } - - wave_format = bytestream_get_le16(&header); - - switch (wave_format) { - case WAVE_FORMAT_PCM: - break; - default: - av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n"); - return AVERROR(ENOSYS); - } - - header += 2; // skip channels (already got from shorten header) - avctx->sample_rate = bytestream_get_le32(&header); - header += 4; // skip bit rate (represents original uncompressed bit rate) - header += 2; // skip block align (not needed) - bps = bytestream_get_le16(&header); - avctx->bits_per_coded_sample = bps; - - if (bps != 16 && bps != 8) { - av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample: %d\n", bps); - return AVERROR(ENOSYS); - } - - len -= 16; - if (len > 0) - av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len); - - return 0; -} - -static const int fixed_coeffs[3][3] = { - { 1, 0, 0 }, - { 2, -1, 0 }, - { 3, -3, 1 } -}; - -static int decode_subframe_lpc(ShortenContext *s, int command, int channel, - int residual_size, int32_t coffset) -{ - int pred_order, sum, qshift, init_sum, i, j; - const int *coeffs; - - if (command == FN_QLPC) { - /* read/validate prediction order */ - pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE); - if (pred_order > s->nwrap) { - av_log(s->avctx, AV_LOG_ERROR, "invalid pred_order %d\n", - pred_order); - return AVERROR(EINVAL); - } - /* read LPC coefficients */ - for (i = 0; i < pred_order; i++) - s->coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT); - coeffs = s->coeffs; - - qshift = LPCQUANT; - } else { - /* fixed LPC coeffs */ - pred_order = command; - coeffs = fixed_coeffs[pred_order - 1]; - qshift = 0; - } - - /* subtract offset from previous samples to use in prediction */ - if (command == FN_QLPC && coffset) - for (i = -pred_order; i < 0; i++) - s->decoded[channel][i] -= coffset; - - /* decode residual and do LPC prediction */ - init_sum = pred_order ? (command == FN_QLPC ? s->lpcqoffset : 0) : coffset; - for (i = 0; i < s->blocksize; i++) { - sum = init_sum; - 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 >> qshift); - } - - /* add offset to current samples */ - if (command == FN_QLPC && coffset) - for (i = 0; i < s->blocksize; i++) - s->decoded[channel][i] += coffset; - - return 0; -} - -static int read_header(ShortenContext *s) -{ - int i, ret; - int maxnlpc = 0; - /* shorten signature */ - if (get_bits_long(&s->gb, 32) != AV_RB32("ajkg")) { - av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n"); - return AVERROR_INVALIDDATA; - } - - s->lpcqoffset = 0; - s->blocksize = DEFAULT_BLOCK_SIZE; - s->nmean = -1; - s->version = get_bits(&s->gb, 8); - s->internal_ftype = get_uint(s, TYPESIZE); - - s->channels = get_uint(s, CHANSIZE); - if (!s->channels) { - av_log(s->avctx, AV_LOG_ERROR, "No channels reported\n"); - return AVERROR_INVALIDDATA; - } - if (s->channels > MAX_CHANNELS) { - av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); - s->channels = 0; - return AVERROR_INVALIDDATA; - } - s->avctx->channels = s->channels; - - /* get blocksize if version > 0 */ - if (s->version > 0) { - int skip_bytes; - unsigned blocksize; - - blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE)); - if (!blocksize || blocksize > MAX_BLOCKSIZE) { - av_log(s->avctx, AV_LOG_ERROR, - "invalid or unsupported block size: %d\n", - blocksize); - return AVERROR(EINVAL); - } - s->blocksize = blocksize; - - maxnlpc = get_uint(s, LPCQSIZE); - s->nmean = get_uint(s, 0); - - skip_bytes = get_uint(s, NSKIPSIZE); - for (i = 0; i < skip_bytes; i++) - skip_bits(&s->gb, 8); - } - s->nwrap = FFMAX(NWRAP, maxnlpc); - - if ((ret = allocate_buffers(s)) < 0) - return ret; - - if ((ret = init_offset(s)) < 0) - return ret; - - if (s->version > 1) - s->lpcqoffset = V2LPCQOFFSET; - - if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) { - av_log(s->avctx, AV_LOG_ERROR, - "missing verbatim section at beginning of stream\n"); - return AVERROR_INVALIDDATA; - } - - s->header_size = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); - if (s->header_size >= OUT_BUFFER_SIZE || - s->header_size < CANONICAL_HEADER_SIZE) { - av_log(s->avctx, AV_LOG_ERROR, "header is wrong size: %d\n", - s->header_size); - return AVERROR_INVALIDDATA; - } - - for (i = 0; i < s->header_size; i++) - s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); - - if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0) - return ret; - - s->cur_chan = 0; - s->bitshift = 0; - - s->got_header = 1; - - return 0; -} - -static int shorten_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; - ShortenContext *s = avctx->priv_data; - int i, input_buf_size = 0; - int ret; - - /* allocate internal bitstream buffer */ - if (s->max_framesize == 0) { - void *tmp_ptr; - s->max_framesize = 8192; // should hopefully be enough for the first header - tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, - s->max_framesize); - if (!tmp_ptr) { - av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n"); - return AVERROR(ENOMEM); - } - s->bitstream = tmp_ptr; - } - - /* append current packet data to bitstream buffer */ - if (1 && s->max_framesize) { //FIXME truncated - buf_size = FFMIN(buf_size, s->max_framesize - s->bitstream_size); - input_buf_size = buf_size; - - if (s->bitstream_index + s->bitstream_size + buf_size > - s->allocated_bitstream_size) { - memmove(s->bitstream, &s->bitstream[s->bitstream_index], - s->bitstream_size); - s->bitstream_index = 0; - } - if (buf) - memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, - buf_size); - buf = &s->bitstream[s->bitstream_index]; - buf_size += s->bitstream_size; - s->bitstream_size = buf_size; - - /* do not decode until buffer has at least max_framesize bytes or - * the end of the file has been reached */ - if (buf_size < s->max_framesize && avpkt->data) { - *got_frame_ptr = 0; - return input_buf_size; - } - } - /* init and position bitstream reader */ - init_get_bits(&s->gb, buf, buf_size * 8); - skip_bits(&s->gb, s->bitindex); - - /* process header or next subblock */ - if (!s->got_header) { - if ((ret = read_header(s)) < 0) - return ret; - *got_frame_ptr = 0; - goto finish_frame; - } - - /* if quit command was read previously, don't decode anything */ - if (s->got_quit_command) { - *got_frame_ptr = 0; - return avpkt->size; - } - - s->cur_chan = 0; - while (s->cur_chan < s->channels) { - unsigned cmd; - int len; - - if (get_bits_left(&s->gb) < 3 + FNSIZE) { - *got_frame_ptr = 0; - break; - } - - cmd = get_ur_golomb_shorten(&s->gb, FNSIZE); - - if (cmd > FN_VERBATIM) { - av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd); - *got_frame_ptr = 0; - break; - } - - if (!is_audio_command[cmd]) { - /* process non-audio command */ - switch (cmd) { - case FN_VERBATIM: - len = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); - while (len--) - get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); - break; - case FN_BITSHIFT: - s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); - break; - case FN_BLOCKSIZE: { - unsigned blocksize = get_uint(s, av_log2(s->blocksize)); - if (blocksize > s->blocksize) { - av_log(avctx, AV_LOG_ERROR, - "Increasing block size is not supported\n"); - return AVERROR_PATCHWELCOME; - } - if (!blocksize || blocksize > MAX_BLOCKSIZE) { - av_log(avctx, AV_LOG_ERROR, "invalid or unsupported " - "block size: %d\n", blocksize); - return AVERROR(EINVAL); - } - s->blocksize = blocksize; - break; - } - case FN_QUIT: - s->got_quit_command = 1; - break; - } - if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) { - *got_frame_ptr = 0; - break; - } - } else { - /* process audio command */ - int residual_size = 0; - int channel = s->cur_chan; - int32_t coffset; - - /* get Rice code for residual decoding */ - if (cmd != FN_ZERO) { - residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE); - /* This is a hack as version 0 differed in the definition - * of get_sr_golomb_shorten(). */ - if (s->version == 0) - residual_size--; - } - - /* calculate sample offset using means from previous blocks */ - if (s->nmean == 0) - coffset = s->offset[channel][0]; - else { - int32_t sum = (s->version < 2) ? 0 : s->nmean / 2; - for (i = 0; i < s->nmean; i++) - sum += s->offset[channel][i]; - coffset = sum / s->nmean; - if (s->version >= 2) - coffset = s->bitshift == 0 ? coffset : coffset >> s->bitshift - 1 >> 1; - } - - /* decode samples for this channel */ - if (cmd == FN_ZERO) { - for (i = 0; i < s->blocksize; i++) - s->decoded[channel][i] = 0; - } else { - if ((ret = decode_subframe_lpc(s, cmd, channel, - residual_size, coffset)) < 0) - return ret; - } - - /* update means with info from the current block */ - if (s->nmean > 0) { - int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2; - for (i = 0; i < s->blocksize; i++) - sum += s->decoded[channel][i]; - - for (i = 1; i < s->nmean; i++) - s->offset[channel][i - 1] = s->offset[channel][i]; - - if (s->version < 2) - s->offset[channel][s->nmean - 1] = sum / s->blocksize; - else - s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift; - } - - /* copy wrap samples for use with next block */ - for (i = -s->nwrap; i < 0; i++) - s->decoded[channel][i] = s->decoded[channel][i + s->blocksize]; - - /* shift samples to add in unused zero bits which were removed - * during encoding */ - fix_bitshift(s, s->decoded[channel]); - - /* if this is the last channel in the block, output the samples */ - s->cur_chan++; - if (s->cur_chan == s->channels) { - uint8_t *samples_u8; - int16_t *samples_s16; - int chan; - - /* get output buffer */ - frame->nb_samples = s->blocksize; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - - for (chan = 0; chan < s->channels; chan++) { - samples_u8 = ((uint8_t **)frame->extended_data)[chan]; - samples_s16 = ((int16_t **)frame->extended_data)[chan]; - for (i = 0; i < s->blocksize; i++) { - switch (s->internal_ftype) { - case TYPE_U8: - *samples_u8++ = av_clip_uint8(s->decoded[chan][i]); - break; - case TYPE_S16HL: - case TYPE_S16LH: - *samples_s16++ = av_clip_int16(s->decoded[chan][i]); - break; - } - } - } - - *got_frame_ptr = 1; - } - } - } - if (s->cur_chan < s->channels) - *got_frame_ptr = 0; - -finish_frame: - s->bitindex = get_bits_count(&s->gb) - 8 * (get_bits_count(&s->gb) / 8); - i = get_bits_count(&s->gb) / 8; - if (i > buf_size) { - av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size); - s->bitstream_size = 0; - s->bitstream_index = 0; - return AVERROR_INVALIDDATA; - } - if (s->bitstream_size) { - s->bitstream_index += i; - s->bitstream_size -= i; - return input_buf_size; - } else - return i; -} - -static av_cold int shorten_decode_close(AVCodecContext *avctx) -{ - ShortenContext *s = avctx->priv_data; - int i; - - for (i = 0; i < s->channels; i++) { - s->decoded[i] = NULL; - av_freep(&s->decoded_base[i]); - av_freep(&s->offset[i]); - } - av_freep(&s->bitstream); - av_freep(&s->coeffs); - - return 0; -} - -AVCodec ff_shorten_decoder = { - .name = "shorten", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SHORTEN, - .priv_data_size = sizeof(ShortenContext), - .init = shorten_decode_init, - .close = shorten_decode_close, - .decode = shorten_decode_frame, - .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("Shorten"), - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, - AV_SAMPLE_FMT_U8P, - AV_SAMPLE_FMT_NONE }, -}; |
