diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-06 15:32:44 -0500 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-07 13:38:23 -0500 |
commit | 77c5b66cbec5a04c846b0dd3997c898146334b60 (patch) | |
tree | 9a1986e4dca17d8dc6fea73bb7de49bdf91fe1e9 | |
parent | 34093ba0819c8f00f024a49cc2cebe0400f020d4 (diff) | |
download | ffmpeg-77c5b66cbec5a04c846b0dd3997c898146334b60.tar.gz |
g722enc: set frame_size, and also handle an odd number of input samples
The fate reference is updated because the previous test skipped a sample in
each encode() call due each input frame having an odd number of samples.
-rw-r--r-- | libavcodec/g722enc.c | 38 | ||||
-rw-r--r-- | tests/ref/acodec/g722 | 8 |
2 files changed, 40 insertions, 6 deletions
diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c index 470770c413..ceb18b46db 100644 --- a/libavcodec/g722enc.c +++ b/libavcodec/g722enc.c @@ -32,6 +32,10 @@ #define FREEZE_INTERVAL 128 +/* This is an arbitrary value. Allowing insanely large values leads to strange + problems, so we limit it to a reasonable value */ +#define MAX_FRAME_SIZE 32768 + static av_cold int g722_encode_init(AVCodecContext * avctx) { G722Context *c = avctx->priv_data; @@ -56,6 +60,29 @@ static av_cold int g722_encode_init(AVCodecContext * avctx) } } + if (avctx->frame_size) { + /* validate frame size */ + if (avctx->frame_size & 1 || avctx->frame_size > MAX_FRAME_SIZE) { + int new_frame_size; + + if (avctx->frame_size == 1) + new_frame_size = 2; + else if (avctx->frame_size > MAX_FRAME_SIZE) + new_frame_size = MAX_FRAME_SIZE; + else + new_frame_size = avctx->frame_size - 1; + + av_log(avctx, AV_LOG_WARNING, "Requested frame size is not " + "allowed. Using %d instead of %d\n", new_frame_size, + avctx->frame_size); + avctx->frame_size = new_frame_size; + } + } else { + /* This is arbitrary. We use 320 because it's 20ms @ 16kHz, which is + a common packet size for VoIP applications */ + avctx->frame_size = 320; + } + return 0; } @@ -301,14 +328,20 @@ static int g722_encode_frame(AVCodecContext *avctx, const int16_t *samples = data; int nb_samples; - nb_samples = buf_size * 2; + nb_samples = avctx->frame_size - (avctx->frame_size & 1); if (avctx->trellis) g722_encode_trellis(c, avctx->trellis, dst, nb_samples, samples); else g722_encode_no_trellis(c, dst, nb_samples, samples); - return buf_size; + /* handle last frame with odd frame_size */ + if (nb_samples < avctx->frame_size) { + int16_t last_samples[2] = { samples[nb_samples], samples[nb_samples] }; + encode_byte(c, &dst[nb_samples >> 1], last_samples); + } + + return (avctx->frame_size + 1) >> 1; } AVCodec ff_adpcm_g722_encoder = { @@ -319,6 +352,7 @@ AVCodec ff_adpcm_g722_encoder = { .init = g722_encode_init, .close = g722_encode_close, .encode = g722_encode_frame, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME, .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, }; diff --git a/tests/ref/acodec/g722 b/tests/ref/acodec/g722 index a1fc72a3bb..6ea492ae45 100644 --- a/tests/ref/acodec/g722 +++ b/tests/ref/acodec/g722 @@ -1,4 +1,4 @@ -b380355e0360b4e50ee78f33fd60a0f5 *./tests/data/acodec/g722.wav -47991 ./tests/data/acodec/g722.wav -82fdd5bb059336e0550de7ba5947c5bb *./tests/data/g722.acodec.out.wav -stddev: 8860.44 PSNR: 17.38 MAXDIFF:33814 bytes: 191732/ 1058400 +1975cc4a3521e374b33ae042e182f6b6 *./tests/data/acodec/g722.wav +48053 ./tests/data/acodec/g722.wav +ade04cdcf249e6946395f109b077dd62 *./tests/data/g722.acodec.out.wav +stddev: 8841.24 PSNR: 17.40 MAXDIFF:36225 bytes: 191980/ 1058400 |