yading@10: /* yading@10: * Shorten decoder yading@10: * Copyright (c) 2005 Jeff Muizelaar yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: /** yading@10: * @file yading@10: * Shorten decoder yading@10: * @author Jeff Muizelaar yading@10: * yading@10: */ yading@10: yading@10: #include yading@10: #include "avcodec.h" yading@10: #include "bytestream.h" yading@10: #include "get_bits.h" yading@10: #include "golomb.h" yading@10: #include "internal.h" yading@10: yading@10: #define MAX_CHANNELS 8 yading@10: #define MAX_BLOCKSIZE 65535 yading@10: yading@10: #define OUT_BUFFER_SIZE 16384 yading@10: yading@10: #define ULONGSIZE 2 yading@10: yading@10: #define WAVE_FORMAT_PCM 0x0001 yading@10: yading@10: #define DEFAULT_BLOCK_SIZE 256 yading@10: yading@10: #define TYPESIZE 4 yading@10: #define CHANSIZE 0 yading@10: #define LPCQSIZE 2 yading@10: #define ENERGYSIZE 3 yading@10: #define BITSHIFTSIZE 2 yading@10: yading@10: #define TYPE_S8 1 yading@10: #define TYPE_U8 2 yading@10: #define TYPE_S16HL 3 yading@10: #define TYPE_U16HL 4 yading@10: #define TYPE_S16LH 5 yading@10: #define TYPE_U16LH 6 yading@10: yading@10: #define NWRAP 3 yading@10: #define NSKIPSIZE 1 yading@10: yading@10: #define LPCQUANT 5 yading@10: #define V2LPCQOFFSET (1 << LPCQUANT) yading@10: yading@10: #define FNSIZE 2 yading@10: #define FN_DIFF0 0 yading@10: #define FN_DIFF1 1 yading@10: #define FN_DIFF2 2 yading@10: #define FN_DIFF3 3 yading@10: #define FN_QUIT 4 yading@10: #define FN_BLOCKSIZE 5 yading@10: #define FN_BITSHIFT 6 yading@10: #define FN_QLPC 7 yading@10: #define FN_ZERO 8 yading@10: #define FN_VERBATIM 9 yading@10: yading@10: /** indicates if the FN_* command is audio or non-audio */ yading@10: static const uint8_t is_audio_command[10] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }; yading@10: yading@10: #define VERBATIM_CKSIZE_SIZE 5 yading@10: #define VERBATIM_BYTE_SIZE 8 yading@10: #define CANONICAL_HEADER_SIZE 44 yading@10: yading@10: typedef struct ShortenContext { yading@10: AVCodecContext *avctx; yading@10: GetBitContext gb; yading@10: yading@10: int min_framesize, max_framesize; yading@10: unsigned channels; yading@10: yading@10: int32_t *decoded[MAX_CHANNELS]; yading@10: int32_t *decoded_base[MAX_CHANNELS]; yading@10: int32_t *offset[MAX_CHANNELS]; yading@10: int *coeffs; yading@10: uint8_t *bitstream; yading@10: int bitstream_size; yading@10: int bitstream_index; yading@10: unsigned int allocated_bitstream_size; yading@10: int header_size; yading@10: uint8_t header[OUT_BUFFER_SIZE]; yading@10: int version; yading@10: int cur_chan; yading@10: int bitshift; yading@10: int nmean; yading@10: int internal_ftype; yading@10: int nwrap; yading@10: int blocksize; yading@10: int bitindex; yading@10: int32_t lpcqoffset; yading@10: int got_header; yading@10: int got_quit_command; yading@10: } ShortenContext; yading@10: yading@10: static av_cold int shorten_decode_init(AVCodecContext *avctx) yading@10: { yading@10: ShortenContext *s = avctx->priv_data; yading@10: s->avctx = avctx; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static int allocate_buffers(ShortenContext *s) yading@10: { yading@10: int i, chan; yading@10: int *coeffs; yading@10: void *tmp_ptr; yading@10: yading@10: for (chan = 0; chan < s->channels; chan++) { yading@10: if (FFMAX(1, s->nmean) >= UINT_MAX / sizeof(int32_t)) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "nmean too large\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: if (s->blocksize + s->nwrap >= UINT_MAX / sizeof(int32_t) || yading@10: s->blocksize + s->nwrap <= (unsigned)s->nwrap) { yading@10: av_log(s->avctx, AV_LOG_ERROR, yading@10: "s->blocksize + s->nwrap too large\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: tmp_ptr = yading@10: av_realloc(s->offset[chan], sizeof(int32_t) * FFMAX(1, s->nmean)); yading@10: if (!tmp_ptr) yading@10: return AVERROR(ENOMEM); yading@10: s->offset[chan] = tmp_ptr; yading@10: yading@10: tmp_ptr = av_realloc(s->decoded_base[chan], (s->blocksize + s->nwrap) * yading@10: sizeof(s->decoded_base[0][0])); yading@10: if (!tmp_ptr) yading@10: return AVERROR(ENOMEM); yading@10: s->decoded_base[chan] = tmp_ptr; yading@10: for (i = 0; i < s->nwrap; i++) yading@10: s->decoded_base[chan][i] = 0; yading@10: s->decoded[chan] = s->decoded_base[chan] + s->nwrap; yading@10: } yading@10: yading@10: coeffs = av_realloc(s->coeffs, s->nwrap * sizeof(*s->coeffs)); yading@10: if (!coeffs) yading@10: return AVERROR(ENOMEM); yading@10: s->coeffs = coeffs; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static inline unsigned int get_uint(ShortenContext *s, int k) yading@10: { yading@10: if (s->version != 0) yading@10: k = get_ur_golomb_shorten(&s->gb, ULONGSIZE); yading@10: return get_ur_golomb_shorten(&s->gb, k); yading@10: } yading@10: yading@10: static void fix_bitshift(ShortenContext *s, int32_t *buffer) yading@10: { yading@10: int i; yading@10: yading@10: if (s->bitshift != 0) yading@10: for (i = 0; i < s->blocksize; i++) yading@10: buffer[i] <<= s->bitshift; yading@10: } yading@10: yading@10: static int init_offset(ShortenContext *s) yading@10: { yading@10: int32_t mean = 0; yading@10: int chan, i; yading@10: int nblock = FFMAX(1, s->nmean); yading@10: /* initialise offset */ yading@10: switch (s->internal_ftype) { yading@10: case TYPE_U8: yading@10: s->avctx->sample_fmt = AV_SAMPLE_FMT_U8P; yading@10: mean = 0x80; yading@10: break; yading@10: case TYPE_S16HL: yading@10: case TYPE_S16LH: yading@10: s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P; yading@10: break; yading@10: default: yading@10: av_log(s->avctx, AV_LOG_ERROR, "unknown audio type\n"); yading@10: return AVERROR_PATCHWELCOME; yading@10: } yading@10: yading@10: for (chan = 0; chan < s->channels; chan++) yading@10: for (i = 0; i < nblock; i++) yading@10: s->offset[chan][i] = mean; yading@10: return 0; yading@10: } yading@10: yading@10: static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header, yading@10: int header_size) yading@10: { yading@10: int len, bps; yading@10: short wave_format; yading@10: const uint8_t *end= header + header_size; yading@10: yading@10: if (bytestream_get_le32(&header) != MKTAG('R', 'I', 'F', 'F')) { yading@10: av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: header += 4; /* chunk size */ yading@10: yading@10: if (bytestream_get_le32(&header) != MKTAG('W', 'A', 'V', 'E')) { yading@10: av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: while (bytestream_get_le32(&header) != MKTAG('f', 'm', 't', ' ')) { yading@10: len = bytestream_get_le32(&header); yading@10: if (len<0 || end - header - 8 < len) yading@10: return AVERROR_INVALIDDATA; yading@10: header += len; yading@10: } yading@10: len = bytestream_get_le32(&header); yading@10: yading@10: if (len < 16) { yading@10: av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: wave_format = bytestream_get_le16(&header); yading@10: yading@10: switch (wave_format) { yading@10: case WAVE_FORMAT_PCM: yading@10: break; yading@10: default: yading@10: av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n"); yading@10: return AVERROR(ENOSYS); yading@10: } yading@10: yading@10: header += 2; // skip channels (already got from shorten header) yading@10: avctx->sample_rate = bytestream_get_le32(&header); yading@10: header += 4; // skip bit rate (represents original uncompressed bit rate) yading@10: header += 2; // skip block align (not needed) yading@10: bps = bytestream_get_le16(&header); yading@10: avctx->bits_per_coded_sample = bps; yading@10: yading@10: if (bps != 16 && bps != 8) { yading@10: av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample: %d\n", bps); yading@10: return AVERROR(ENOSYS); yading@10: } yading@10: yading@10: len -= 16; yading@10: if (len > 0) yading@10: av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len); yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static const int fixed_coeffs[3][3] = { yading@10: { 1, 0, 0 }, yading@10: { 2, -1, 0 }, yading@10: { 3, -3, 1 } yading@10: }; yading@10: yading@10: static int decode_subframe_lpc(ShortenContext *s, int command, int channel, yading@10: int residual_size, int32_t coffset) yading@10: { yading@10: int pred_order, sum, qshift, init_sum, i, j; yading@10: const int *coeffs; yading@10: yading@10: if (command == FN_QLPC) { yading@10: /* read/validate prediction order */ yading@10: pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE); yading@10: if (pred_order > s->nwrap) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "invalid pred_order %d\n", yading@10: pred_order); yading@10: return AVERROR(EINVAL); yading@10: } yading@10: /* read LPC coefficients */ yading@10: for (i = 0; i < pred_order; i++) yading@10: s->coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT); yading@10: coeffs = s->coeffs; yading@10: yading@10: qshift = LPCQUANT; yading@10: } else { yading@10: /* fixed LPC coeffs */ yading@10: pred_order = command; yading@10: coeffs = fixed_coeffs[pred_order - 1]; yading@10: qshift = 0; yading@10: } yading@10: yading@10: /* subtract offset from previous samples to use in prediction */ yading@10: if (command == FN_QLPC && coffset) yading@10: for (i = -pred_order; i < 0; i++) yading@10: s->decoded[channel][i] -= coffset; yading@10: yading@10: /* decode residual and do LPC prediction */ yading@10: init_sum = pred_order ? (command == FN_QLPC ? s->lpcqoffset : 0) : coffset; yading@10: for (i = 0; i < s->blocksize; i++) { yading@10: sum = init_sum; yading@10: for (j = 0; j < pred_order; j++) yading@10: sum += coeffs[j] * s->decoded[channel][i - j - 1]; yading@10: s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + yading@10: (sum >> qshift); yading@10: } yading@10: yading@10: /* add offset to current samples */ yading@10: if (command == FN_QLPC && coffset) yading@10: for (i = 0; i < s->blocksize; i++) yading@10: s->decoded[channel][i] += coffset; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static int read_header(ShortenContext *s) yading@10: { yading@10: int i, ret; yading@10: int maxnlpc = 0; yading@10: /* shorten signature */ yading@10: if (get_bits_long(&s->gb, 32) != AV_RB32("ajkg")) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: s->lpcqoffset = 0; yading@10: s->blocksize = DEFAULT_BLOCK_SIZE; yading@10: s->nmean = -1; yading@10: s->version = get_bits(&s->gb, 8); yading@10: s->internal_ftype = get_uint(s, TYPESIZE); yading@10: yading@10: s->channels = get_uint(s, CHANSIZE); yading@10: if (!s->channels) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "No channels reported\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: if (s->channels > MAX_CHANNELS) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); yading@10: s->channels = 0; yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: s->avctx->channels = s->channels; yading@10: yading@10: /* get blocksize if version > 0 */ yading@10: if (s->version > 0) { yading@10: int skip_bytes; yading@10: unsigned blocksize; yading@10: yading@10: blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE)); yading@10: if (!blocksize || blocksize > MAX_BLOCKSIZE) { yading@10: av_log(s->avctx, AV_LOG_ERROR, yading@10: "invalid or unsupported block size: %d\n", yading@10: blocksize); yading@10: return AVERROR(EINVAL); yading@10: } yading@10: s->blocksize = blocksize; yading@10: yading@10: maxnlpc = get_uint(s, LPCQSIZE); yading@10: s->nmean = get_uint(s, 0); yading@10: yading@10: skip_bytes = get_uint(s, NSKIPSIZE); yading@10: for (i = 0; i < skip_bytes; i++) yading@10: skip_bits(&s->gb, 8); yading@10: } yading@10: s->nwrap = FFMAX(NWRAP, maxnlpc); yading@10: yading@10: if ((ret = allocate_buffers(s)) < 0) yading@10: return ret; yading@10: yading@10: if ((ret = init_offset(s)) < 0) yading@10: return ret; yading@10: yading@10: if (s->version > 1) yading@10: s->lpcqoffset = V2LPCQOFFSET; yading@10: yading@10: if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) { yading@10: av_log(s->avctx, AV_LOG_ERROR, yading@10: "missing verbatim section at beginning of stream\n"); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: s->header_size = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); yading@10: if (s->header_size >= OUT_BUFFER_SIZE || yading@10: s->header_size < CANONICAL_HEADER_SIZE) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "header is wrong size: %d\n", yading@10: s->header_size); yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: yading@10: for (i = 0; i < s->header_size; i++) yading@10: s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); yading@10: yading@10: if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0) yading@10: return ret; yading@10: yading@10: s->cur_chan = 0; yading@10: s->bitshift = 0; yading@10: yading@10: s->got_header = 1; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static int shorten_decode_frame(AVCodecContext *avctx, void *data, yading@10: int *got_frame_ptr, AVPacket *avpkt) yading@10: { yading@10: AVFrame *frame = data; yading@10: const uint8_t *buf = avpkt->data; yading@10: int buf_size = avpkt->size; yading@10: ShortenContext *s = avctx->priv_data; yading@10: int i, input_buf_size = 0; yading@10: int ret; yading@10: yading@10: /* allocate internal bitstream buffer */ yading@10: if (s->max_framesize == 0) { yading@10: void *tmp_ptr; yading@10: s->max_framesize = 8192; // should hopefully be enough for the first header yading@10: tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, yading@10: s->max_framesize); yading@10: if (!tmp_ptr) { yading@10: av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n"); yading@10: return AVERROR(ENOMEM); yading@10: } yading@10: s->bitstream = tmp_ptr; yading@10: } yading@10: yading@10: /* append current packet data to bitstream buffer */ yading@10: if (1 && s->max_framesize) { //FIXME truncated yading@10: buf_size = FFMIN(buf_size, s->max_framesize - s->bitstream_size); yading@10: input_buf_size = buf_size; yading@10: yading@10: if (s->bitstream_index + s->bitstream_size + buf_size > yading@10: s->allocated_bitstream_size) { yading@10: memmove(s->bitstream, &s->bitstream[s->bitstream_index], yading@10: s->bitstream_size); yading@10: s->bitstream_index = 0; yading@10: } yading@10: if (buf) yading@10: memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, yading@10: buf_size); yading@10: buf = &s->bitstream[s->bitstream_index]; yading@10: buf_size += s->bitstream_size; yading@10: s->bitstream_size = buf_size; yading@10: yading@10: /* do not decode until buffer has at least max_framesize bytes or yading@10: * the end of the file has been reached */ yading@10: if (buf_size < s->max_framesize && avpkt->data) { yading@10: *got_frame_ptr = 0; yading@10: return input_buf_size; yading@10: } yading@10: } yading@10: /* init and position bitstream reader */ yading@10: init_get_bits(&s->gb, buf, buf_size * 8); yading@10: skip_bits(&s->gb, s->bitindex); yading@10: yading@10: /* process header or next subblock */ yading@10: if (!s->got_header) { yading@10: if ((ret = read_header(s)) < 0) yading@10: return ret; yading@10: *got_frame_ptr = 0; yading@10: goto finish_frame; yading@10: } yading@10: yading@10: /* if quit command was read previously, don't decode anything */ yading@10: if (s->got_quit_command) { yading@10: *got_frame_ptr = 0; yading@10: return avpkt->size; yading@10: } yading@10: yading@10: s->cur_chan = 0; yading@10: while (s->cur_chan < s->channels) { yading@10: unsigned cmd; yading@10: int len; yading@10: yading@10: if (get_bits_left(&s->gb) < 3 + FNSIZE) { yading@10: *got_frame_ptr = 0; yading@10: break; yading@10: } yading@10: yading@10: cmd = get_ur_golomb_shorten(&s->gb, FNSIZE); yading@10: yading@10: if (cmd > FN_VERBATIM) { yading@10: av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd); yading@10: *got_frame_ptr = 0; yading@10: break; yading@10: } yading@10: yading@10: if (!is_audio_command[cmd]) { yading@10: /* process non-audio command */ yading@10: switch (cmd) { yading@10: case FN_VERBATIM: yading@10: len = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); yading@10: while (len--) yading@10: get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); yading@10: break; yading@10: case FN_BITSHIFT: yading@10: s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); yading@10: break; yading@10: case FN_BLOCKSIZE: { yading@10: unsigned blocksize = get_uint(s, av_log2(s->blocksize)); yading@10: if (blocksize > s->blocksize) { yading@10: av_log(avctx, AV_LOG_ERROR, yading@10: "Increasing block size is not supported\n"); yading@10: return AVERROR_PATCHWELCOME; yading@10: } yading@10: if (!blocksize || blocksize > MAX_BLOCKSIZE) { yading@10: av_log(avctx, AV_LOG_ERROR, "invalid or unsupported " yading@10: "block size: %d\n", blocksize); yading@10: return AVERROR(EINVAL); yading@10: } yading@10: s->blocksize = blocksize; yading@10: break; yading@10: } yading@10: case FN_QUIT: yading@10: s->got_quit_command = 1; yading@10: break; yading@10: } yading@10: if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) { yading@10: *got_frame_ptr = 0; yading@10: break; yading@10: } yading@10: } else { yading@10: /* process audio command */ yading@10: int residual_size = 0; yading@10: int channel = s->cur_chan; yading@10: int32_t coffset; yading@10: yading@10: /* get Rice code for residual decoding */ yading@10: if (cmd != FN_ZERO) { yading@10: residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE); yading@10: /* This is a hack as version 0 differed in the definition yading@10: * of get_sr_golomb_shorten(). */ yading@10: if (s->version == 0) yading@10: residual_size--; yading@10: } yading@10: yading@10: /* calculate sample offset using means from previous blocks */ yading@10: if (s->nmean == 0) yading@10: coffset = s->offset[channel][0]; yading@10: else { yading@10: int32_t sum = (s->version < 2) ? 0 : s->nmean / 2; yading@10: for (i = 0; i < s->nmean; i++) yading@10: sum += s->offset[channel][i]; yading@10: coffset = sum / s->nmean; yading@10: if (s->version >= 2) yading@10: coffset = s->bitshift == 0 ? coffset : coffset >> s->bitshift - 1 >> 1; yading@10: } yading@10: yading@10: /* decode samples for this channel */ yading@10: if (cmd == FN_ZERO) { yading@10: for (i = 0; i < s->blocksize; i++) yading@10: s->decoded[channel][i] = 0; yading@10: } else { yading@10: if ((ret = decode_subframe_lpc(s, cmd, channel, yading@10: residual_size, coffset)) < 0) yading@10: return ret; yading@10: } yading@10: yading@10: /* update means with info from the current block */ yading@10: if (s->nmean > 0) { yading@10: int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2; yading@10: for (i = 0; i < s->blocksize; i++) yading@10: sum += s->decoded[channel][i]; yading@10: yading@10: for (i = 1; i < s->nmean; i++) yading@10: s->offset[channel][i - 1] = s->offset[channel][i]; yading@10: yading@10: if (s->version < 2) yading@10: s->offset[channel][s->nmean - 1] = sum / s->blocksize; yading@10: else yading@10: s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift; yading@10: } yading@10: yading@10: /* copy wrap samples for use with next block */ yading@10: for (i = -s->nwrap; i < 0; i++) yading@10: s->decoded[channel][i] = s->decoded[channel][i + s->blocksize]; yading@10: yading@10: /* shift samples to add in unused zero bits which were removed yading@10: * during encoding */ yading@10: fix_bitshift(s, s->decoded[channel]); yading@10: yading@10: /* if this is the last channel in the block, output the samples */ yading@10: s->cur_chan++; yading@10: if (s->cur_chan == s->channels) { yading@10: uint8_t *samples_u8; yading@10: int16_t *samples_s16; yading@10: int chan; yading@10: yading@10: /* get output buffer */ yading@10: frame->nb_samples = s->blocksize; yading@10: if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) yading@10: return ret; yading@10: yading@10: for (chan = 0; chan < s->channels; chan++) { yading@10: samples_u8 = ((uint8_t **)frame->extended_data)[chan]; yading@10: samples_s16 = ((int16_t **)frame->extended_data)[chan]; yading@10: for (i = 0; i < s->blocksize; i++) { yading@10: switch (s->internal_ftype) { yading@10: case TYPE_U8: yading@10: *samples_u8++ = av_clip_uint8(s->decoded[chan][i]); yading@10: break; yading@10: case TYPE_S16HL: yading@10: case TYPE_S16LH: yading@10: *samples_s16++ = av_clip_int16(s->decoded[chan][i]); yading@10: break; yading@10: } yading@10: } yading@10: } yading@10: yading@10: *got_frame_ptr = 1; yading@10: } yading@10: } yading@10: } yading@10: if (s->cur_chan < s->channels) yading@10: *got_frame_ptr = 0; yading@10: yading@10: finish_frame: yading@10: s->bitindex = get_bits_count(&s->gb) - 8 * (get_bits_count(&s->gb) / 8); yading@10: i = get_bits_count(&s->gb) / 8; yading@10: if (i > buf_size) { yading@10: av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size); yading@10: s->bitstream_size = 0; yading@10: s->bitstream_index = 0; yading@10: return AVERROR_INVALIDDATA; yading@10: } yading@10: if (s->bitstream_size) { yading@10: s->bitstream_index += i; yading@10: s->bitstream_size -= i; yading@10: return input_buf_size; yading@10: } else yading@10: return i; yading@10: } yading@10: yading@10: static av_cold int shorten_decode_close(AVCodecContext *avctx) yading@10: { yading@10: ShortenContext *s = avctx->priv_data; yading@10: int i; yading@10: yading@10: for (i = 0; i < s->channels; i++) { yading@10: s->decoded[i] = NULL; yading@10: av_freep(&s->decoded_base[i]); yading@10: av_freep(&s->offset[i]); yading@10: } yading@10: av_freep(&s->bitstream); yading@10: av_freep(&s->coeffs); yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: AVCodec ff_shorten_decoder = { yading@10: .name = "shorten", yading@10: .type = AVMEDIA_TYPE_AUDIO, yading@10: .id = AV_CODEC_ID_SHORTEN, yading@10: .priv_data_size = sizeof(ShortenContext), yading@10: .init = shorten_decode_init, yading@10: .close = shorten_decode_close, yading@10: .decode = shorten_decode_frame, yading@10: .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, yading@10: .long_name = NULL_IF_CONFIG_SMALL("Shorten"), yading@10: .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, yading@10: AV_SAMPLE_FMT_U8P, yading@10: AV_SAMPLE_FMT_NONE }, yading@10: };