diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-11-03 02:01:37 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-11-03 02:16:26 +0100 |
commit | 988f585fcb1cfb40fe4b706c32b31594b536bba0 (patch) | |
tree | 659b8d9f4daf4ce497b42c83f7adb45725fa4f65 /libavcodec/g726.c | |
parent | 0b3e9d5dc61bb705d93db1e87d78d8d5131905c6 (diff) | |
parent | 594b54b51e9f3af8aac18184d634b85a836b42b6 (diff) | |
download | ffmpeg-988f585fcb1cfb40fe4b706c32b31594b536bba0.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master: (44 commits)
replacement Indeo 3 decoder
gsm demuxer: do not allocate packet twice.
flvenc: use first packet delay as global delay.
ac3enc: doxygen update.
imc: return error codes instead of 0 for error conditions.
imc: return meaningful error codes instead of -1
imc: do not set channel layout for stereo
imc: validate channel count
imc: check for ff_fft_init() failure
imc: check output buffer size before decoding
imc: use DSPContext.bswap16_buf() to byte-swap packet data
rtsp: add allowed_media_types option
libgsm: add flush function to reset the decoder state when seeking
libgsm: simplify decoding by using a loop
gsm: log error message when packet is too small
libgsmdec: do not needlessly set *data_size to 0
gsmdec: do not needlessly set *data_size to 0
gsmdec: add flush function to reset the decoder state when seeking
libgsmdec: check output buffer size before decoding
gsmdec: log error message when output buffer is too small.
...
Conflicts:
Changelog
ffplay.c
libavcodec/indeo3.c
libavcodec/mjpeg_parser.c
libavcodec/vp3.c
libavformat/cutils.c
libavformat/id3v2.c
libavutil/parseutils.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/g726.c')
-rw-r--r-- | libavcodec/g726.c | 160 |
1 files changed, 111 insertions, 49 deletions
diff --git a/libavcodec/g726.c b/libavcodec/g726.c index 2ce113b24b..ae1b5a3001 100644 --- a/libavcodec/g726.c +++ b/libavcodec/g726.c @@ -22,7 +22,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <limits.h> +#include "libavutil/avassert.h" +#include "libavutil/opt.h" #include "avcodec.h" +#include "internal.h" #include "get_bits.h" #include "put_bits.h" @@ -71,6 +74,7 @@ typedef struct G726Tables { } G726Tables; typedef struct G726Context { + AVClass *class; G726Tables tbls; /**< static tables needed for computation */ Float11 sr[2]; /**< prev. reconstructed samples */ @@ -266,11 +270,11 @@ static int16_t g726_decode(G726Context* c, int I) return av_clip(re_signal << 2, -0xffff, 0xffff); } -static av_cold int g726_reset(G726Context* c, int index) +static av_cold int g726_reset(G726Context *c) { int i; - c->tbls = G726Tables_pool[index]; + c->tbls = G726Tables_pool[c->code_size - 2]; for (i=0; i<2; i++) { c->sr[i].mant = 1<<5; c->pk[i] = 1; @@ -295,65 +299,59 @@ static int16_t g726_encode(G726Context* c, int16_t sig) g726_decode(c, i); return i; } -#endif /* Interfacing to the libavcodec */ -static av_cold int g726_init(AVCodecContext * avctx) +static av_cold int g726_encode_init(AVCodecContext *avctx) { G726Context* c = avctx->priv_data; - unsigned int index; - if (avctx->sample_rate <= 0) { - av_log(avctx, AV_LOG_ERROR, "Samplerate is invalid\n"); - return -1; + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && + avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Sample rates other than 8kHz are not " + "allowed when the compliance level is higher than unofficial. " + "Resample or reduce the compliance level.\n"); + return AVERROR(EINVAL); } + av_assert0(avctx->sample_rate > 0); - index = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate - 2; - - if (avctx->bit_rate % avctx->sample_rate && avctx->codec->encode) { - av_log(avctx, AV_LOG_ERROR, "Bitrate - Samplerate combination is invalid\n"); - return -1; - } if(avctx->channels != 1){ av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); - return -1; - } - if(index>3){ - av_log(avctx, AV_LOG_ERROR, "Unsupported number of bits %d\n", index+2); - return -1; + return AVERROR(EINVAL); } - g726_reset(c, index); - c->code_size = index+2; + + if (avctx->bit_rate) + c->code_size = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate; + + c->code_size = av_clip(c->code_size, 2, 5); + avctx->bit_rate = c->code_size * avctx->sample_rate; + avctx->bits_per_coded_sample = c->code_size; + + g726_reset(c); avctx->coded_frame = avcodec_alloc_frame(); if (!avctx->coded_frame) return AVERROR(ENOMEM); avctx->coded_frame->key_frame = 1; - if (avctx->codec->decode) - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - /* select a frame size that will end on a byte boundary and have a size of approximately 1024 bytes */ - if (avctx->codec->encode) - avctx->frame_size = ((int[]){ 4096, 2736, 2048, 1640 })[index]; + avctx->frame_size = ((int[]){ 4096, 2736, 2048, 1640 })[c->code_size - 2]; return 0; } -static av_cold int g726_close(AVCodecContext *avctx) +static av_cold int g726_encode_close(AVCodecContext *avctx) { av_freep(&avctx->coded_frame); return 0; } -#if CONFIG_ADPCM_G726_ENCODER static int g726_encode_frame(AVCodecContext *avctx, uint8_t *dst, int buf_size, void *data) { G726Context *c = avctx->priv_data; - const short *samples = data; + const int16_t *samples = data; PutBitContext pb; int i; @@ -366,8 +364,72 @@ static int g726_encode_frame(AVCodecContext *avctx, return put_bits_count(&pb)>>3; } + +#define OFFSET(x) offsetof(G726Context, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "code_size", "Bits per code", OFFSET(code_size), AV_OPT_TYPE_INT, { 4 }, 2, 5, AE }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "g726", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { NULL }, +}; + +AVCodec ff_adpcm_g726_encoder = { + .name = "g726", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_ADPCM_G726, + .priv_data_size = sizeof(G726Context), + .init = g726_encode_init, + .encode = g726_encode_frame, + .close = g726_encode_close, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), + .priv_class = &class, + .defaults = defaults, +}; #endif +#if CONFIG_ADPCM_G726_DECODER +static av_cold int g726_decode_init(AVCodecContext *avctx) +{ + G726Context* c = avctx->priv_data; + + if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT && + avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Only 8kHz sample rate is allowed when " + "the compliance level is strict. Reduce the compliance level " + "if you wish to decode the stream anyway.\n"); + return AVERROR(EINVAL); + } + + if(avctx->channels != 1){ + av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); + return AVERROR(EINVAL); + } + + c->code_size = avctx->bits_per_coded_sample; + if (c->code_size < 2 || c->code_size > 5) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of bits %d\n", c->code_size); + return AVERROR(EINVAL); + } + g726_reset(c); + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + static int g726_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) @@ -375,43 +437,43 @@ static int g726_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; G726Context *c = avctx->priv_data; - short *samples = data; + int16_t *samples = data; GetBitContext gb; + int out_samples, out_size; + + out_samples = buf_size * 8 / c->code_size; + out_size = out_samples * av_get_bytes_per_sample(avctx->sample_fmt); + if (*data_size < out_size) { + av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); + return AVERROR(EINVAL); + } init_get_bits(&gb, buf, buf_size * 8); - while (get_bits_count(&gb) + c->code_size <= buf_size*8) + while (out_samples--) *samples++ = g726_decode(c, get_bits(&gb, c->code_size)); - if(buf_size*8 != get_bits_count(&gb)) + if (get_bits_left(&gb) > 0) av_log(avctx, AV_LOG_ERROR, "Frame invalidly split, missing parser?\n"); - *data_size = (uint8_t*)samples - (uint8_t*)data; + *data_size = out_size; return buf_size; } -#if CONFIG_ADPCM_G726_ENCODER -AVCodec ff_adpcm_g726_encoder = { - .name = "g726", - .type = AVMEDIA_TYPE_AUDIO, - .id = CODEC_ID_ADPCM_G726, - .priv_data_size = sizeof(G726Context), - .init = g726_init, - .encode = g726_encode_frame, - .close = g726_close, - .capabilities = CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), -}; -#endif +static void g726_decode_flush(AVCodecContext *avctx) +{ + G726Context *c = avctx->priv_data; + g726_reset(c); +} AVCodec ff_adpcm_g726_decoder = { .name = "g726", .type = AVMEDIA_TYPE_AUDIO, .id = CODEC_ID_ADPCM_G726, .priv_data_size = sizeof(G726Context), - .init = g726_init, - .close = g726_close, + .init = g726_decode_init, .decode = g726_decode_frame, + .flush = g726_decode_flush, .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), }; +#endif |