X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fshorten.c;h=1dc010f441d57de1f2f97b2ee9cca53fbd56c103;hb=0e02b381b4850bbc5b8e1ce6e17447968a2ae8b5;hp=ad274b4b04201b9fdb3afb0b1ebe8247f8d6710e;hpb=9e5e2c2d010c05c10337e9c1ec9d0d61495e0c9c;p=ffmpeg diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index ad274b4b042..1dc010f441d 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -28,8 +28,10 @@ #include #include "avcodec.h" +#include "bytestream.h" #include "get_bits.h" #include "golomb.h" +#include "internal.h" #define MAX_CHANNELS 8 #define MAX_BLOCKSIZE 65535 @@ -78,12 +80,14 @@ static const uint8_t is_audio_command[10] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }; typedef struct ShortenContext { AVCodecContext *avctx; + AVFrame frame; GetBitContext gb; int min_framesize, max_framesize; int channels; int32_t *decoded[MAX_CHANNELS]; + int32_t *decoded_base[MAX_CHANNELS]; int32_t *offset[MAX_CHANNELS]; int *coeffs; uint8_t *bitstream; @@ -101,13 +105,18 @@ typedef struct ShortenContext { 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; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; return 0; } @@ -133,13 +142,14 @@ static int allocate_buffers(ShortenContext *s) return AVERROR(ENOMEM); s->offset[chan] = tmp_ptr; - tmp_ptr = av_realloc(s->decoded[chan], sizeof(int32_t)*(s->blocksize + s->nwrap)); + 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[chan] = tmp_ptr; + s->decoded_base[chan] = tmp_ptr; for (i=0; inwrap; i++) - s->decoded[chan][i] = 0; - s->decoded[chan] += s->nwrap; + 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)); @@ -169,7 +179,7 @@ static void fix_bitshift(ShortenContext *s, int32_t *buffer) } -static void init_offset(ShortenContext *s) +static int init_offset(ShortenContext *s) { int32_t mean = 0; int chan, i; @@ -183,55 +193,46 @@ static void init_offset(ShortenContext *s) break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown audio type"); - abort(); + return AVERROR_INVALIDDATA; } for (chan = 0; chan < s->channels; chan++) for (i = 0; i < nblock; i++) s->offset[chan][i] = mean; + return 0; } -static inline int get_le32(GetBitContext *gb) -{ - return av_bswap32(get_bits_long(gb, 32)); -} - -static inline short get_le16(GetBitContext *gb) -{ - return av_bswap16(get_bits_long(gb, 16)); -} - -static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header_size) +static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header, + int header_size) { - GetBitContext hb; int len; short wave_format; - init_get_bits(&hb, header, header_size*8); - if (get_le32(&hb) != MKTAG('R','I','F','F')) { + + if (bytestream_get_le32(&header) != MKTAG('R','I','F','F')) { av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n"); return -1; } - skip_bits_long(&hb, 32); /* chunk_size */ + header += 4; /* chunk size */; - if (get_le32(&hb) != MKTAG('W','A','V','E')) { + if (bytestream_get_le32(&header) != 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); + while (bytestream_get_le32(&header) != MKTAG('f','m','t',' ')) { + len = bytestream_get_le32(&header); + header += len; } - len = get_le32(&hb); + len = bytestream_get_le32(&header); if (len < 16) { av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n"); return -1; } - wave_format = get_le16(&hb); + wave_format = bytestream_get_le16(&header); switch (wave_format) { case WAVE_FORMAT_PCM: @@ -241,11 +242,11 @@ static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header return -1; } - skip_bits(&hb, 16); // skip channels (already got from shorten header) - avctx->sample_rate = get_le32(&hb); - skip_bits(&hb, 32); // skip bit rate (represents original uncompressed bit rate) - skip_bits(&hb, 16); // skip block align (not needed) - avctx->bits_per_coded_sample = get_le16(&hb); + 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) + avctx->bits_per_coded_sample = bytestream_get_le16(&header); if (avctx->bits_per_coded_sample != 16) { av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample\n"); @@ -259,45 +260,66 @@ static int decode_wave_header(AVCodecContext *avctx, uint8_t *header, int header return 0; } -static int16_t * interleave_buffer(int16_t *samples, int nchan, int blocksize, int32_t **buffer) { - int i, chan; - for (i=0; icoeffs; - - /* 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); + 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; icoeffs[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; } - /* read LPC coefficients */ - for (i=0; igb, LPCQUANT); /* subtract offset from previous samples to use in prediction */ - if (coffset) + 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 = s->lpcqoffset; + sum = init_sum; for (j=0; jdecoded[channel][i-j-1]; - s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + (sum >> LPCQUANT); + s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + (sum >> qshift); } /* add offset to current samples */ - if (coffset != 0) + if (command == FN_QLPC && coffset) for (i = 0; i < s->blocksize; i++) s->decoded[channel][i] += coffset; @@ -306,7 +328,7 @@ static int decode_subframe_lpc(ShortenContext *s, int channel, static int read_header(ShortenContext *s) { - int i; + int i, ret; int maxnlpc = 0; /* shorten signature */ if (get_bits_long(&s->gb, 32) != AV_RB32("ajkg")) { @@ -316,13 +338,12 @@ static int read_header(ShortenContext *s) s->lpcqoffset = 0; s->blocksize = DEFAULT_BLOCK_SIZE; - s->channels = 1; 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 > MAX_CHANNELS) { + if (s->channels <= 0 || s->channels > MAX_CHANNELS) { av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); return -1; } @@ -330,8 +351,16 @@ static int read_header(ShortenContext *s) /* get blocksize if version > 0 */ if (s->version > 0) { - int skip_bytes; - s->blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE)); + int skip_bytes, 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); @@ -342,10 +371,11 @@ static int read_header(ShortenContext *s) } s->nwrap = FFMAX(NWRAP, maxnlpc); - if (allocate_buffers(s)) - return -1; + if ((ret = allocate_buffers(s)) < 0) + return ret; - init_offset(s); + if ((ret = init_offset(s)) < 0) + return ret; if (s->version > 1) s->lpcqoffset = V2LPCQOFFSET; @@ -370,18 +400,21 @@ static int read_header(ShortenContext *s) s->cur_chan = 0; s->bitshift = 0; + s->got_header = 1; + return 0; } -static int shorten_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +static int shorten_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ShortenContext *s = avctx->priv_data; int i, input_buf_size = 0; - int16_t *samples = data; + int ret; + + /* allocate internal bitstream buffer */ if(s->max_framesize == 0){ void *tmp_ptr; s->max_framesize= 1024; // should hopefully be enough for the first header @@ -394,47 +427,62 @@ static int shorten_decode_frame(AVCodecContext *avctx, 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){ - // printf("memmove\n"); memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size); s->bitstream_index=0; } - memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size); + 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; - if(buf_size < s->max_framesize){ - *data_size = 0; + /* 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); - if (!s->blocksize) - { - int ret; + + /* process header or next subblock */ + if (!s->got_header) { if ((ret = read_header(s)) < 0) return ret; - *data_size = 0; + *got_frame_ptr = 0; + goto finish_frame; } - else - { + + /* 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) { int 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); - if (s->bitstream_size > 0) { - s->bitstream_index++; - s->bitstream_size--; - } - return -1; + *got_frame_ptr = 0; + break; } if (!is_audio_command[cmd]) { @@ -455,26 +503,38 @@ static int shorten_decode_frame(AVCodecContext *avctx, 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; } - *data_size = 0; + if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) { + *got_frame_ptr = 0; + break; + } } else { /* process audio command */ - int ret; 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 defintion of get_sr_golomb_shorten */ + /* 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 { @@ -485,35 +545,17 @@ static int shorten_decode_frame(AVCodecContext *avctx, if (s->version >= 2) coffset >>= FFMIN(1, s->bitshift); } - switch (cmd) { - case FN_ZERO: - for (i=0; iblocksize; i++) - s->decoded[channel][i] = 0; - break; - case FN_DIFF0: - for (i=0; iblocksize; i++) - s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + coffset; - break; - case FN_DIFF1: - for (i=0; iblocksize; i++) - s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + s->decoded[channel][i - 1]; - break; - case FN_DIFF2: - for (i=0; iblocksize; i++) - s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 2*s->decoded[channel][i-1] - - s->decoded[channel][i-2]; - break; - case FN_DIFF3: - for (i=0; iblocksize; i++) - s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 3*s->decoded[channel][i-1] - - 3*s->decoded[channel][i-2] - + s->decoded[channel][i-3]; - break; - case FN_QLPC: - if ((ret = decode_subframe_lpc(s, channel, residual_size, coffset)) < 0) - return ret; - break; + + /* decode samples for this channel */ + if (cmd == FN_ZERO) { + for (i=0; iblocksize; 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; iblocksize; i++) @@ -527,23 +569,37 @@ static int shorten_decode_frame(AVCodecContext *avctx, 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) { - samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded); - s->cur_chan = 0; - *data_size = (int8_t *)samples - (int8_t *)data; - } else { - *data_size = 0; + /* get output buffer */ + s->frame.nb_samples = s->blocksize; + if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + /* interleave output */ + output_buffer((int16_t **)s->frame.extended_data, s->channels, + s->blocksize, s->decoded); + + *got_frame_ptr = 1; + *(AVFrame *)data = s->frame; } } } + if (s->cur_chan < s->channels) + *got_frame_ptr = 0; - // s->last_blocksize = s->blocksize; +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) { @@ -566,22 +622,26 @@ static av_cold int shorten_decode_close(AVCodecContext *avctx) int i; for (i = 0; i < s->channels; i++) { - s->decoded[i] -= s->nwrap; - av_freep(&s->decoded[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 = CODEC_ID_SHORTEN, + .id = AV_CODEC_ID_SHORTEN, .priv_data_size = sizeof(ShortenContext), .init = shorten_decode_init, .close = shorten_decode_close, .decode = shorten_decode_frame, - .long_name= NULL_IF_CONFIG_SMALL("Shorten"), + .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_NONE }, };