[FFmpeg-cvslog] g722enc: set frame_size, and also handle an odd number of input samples

Justin Ruggles git at videolan.org
Sun Jan 8 04:21:41 CET 2012


ffmpeg | branch: master | Justin Ruggles <justin.ruggles at gmail.com> | Fri Jan  6 15:32:44 2012 -0500| [77c5b66cbec5a04c846b0dd3997c898146334b60] | committer: Justin Ruggles

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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=77c5b66cbec5a04c846b0dd3997c898146334b60
---

 libavcodec/g722enc.c  |   38 ++++++++++++++++++++++++++++++++++++--
 tests/ref/acodec/g722 |    8 ++++----
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c
index 470770c..ceb18b4 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 a1fc72a..6ea492a 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



More information about the ffmpeg-cvslog mailing list