[FFmpeg-cvslog] g726: use bits_per_coded_sample instead of bitrate to determine mode

Justin Ruggles git at videolan.org
Thu Nov 3 02:23:05 CET 2011


ffmpeg | branch: master | Justin Ruggles <justin.ruggles at gmail.com> | Thu Oct 27 20:16:45 2011 -0400| [6ac34eed54f8e0298acb16636d0104c297e3d09f] | committer: Justin Ruggles

g726: use bits_per_coded_sample instead of bitrate to determine mode

This requires some workarounds in the WAV muxer and demuxer. We need to write
the correct bits_per_coded_sample and block_align in the muxer. In the
demuxer, we cannot rely on the bits_per_coded_sample value, so we use the bit
rate and sample rate to determine the value.

This avoids having the decoder rely on AVCodecContext.bit_rate, which is not
required to be set by the user for decoding according to our API.

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

 libavcodec/g726.c  |   40 +++++++++++++++++++---------------------
 libavformat/riff.c |   17 ++++++++++-------
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index b150f58..3392811 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -301,29 +301,29 @@ static int16_t g726_encode(G726Context* c, int16_t sig)
 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;
     }
 
-    index = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate - 2;
-
-    if (avctx->bit_rate % avctx->sample_rate) {
-        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;
+
+    if (avctx->bit_rate % avctx->sample_rate) {
+        av_log(avctx, AV_LOG_ERROR, "Bitrate - Samplerate combination is invalid\n");
+        return AVERROR(EINVAL);
+    }
+    c->code_size = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate;
+    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, index);
-    c->code_size = index+2;
+    avctx->bits_per_coded_sample = c->code_size;
+
+    g726_reset(c, c->code_size - 2);
 
     avctx->coded_frame = avcodec_alloc_frame();
     if (!avctx->coded_frame)
@@ -332,7 +332,7 @@ static av_cold int g726_encode_init(AVCodecContext *avctx)
 
     /* select a frame size that will end on a byte boundary and have a size of
        approximately 1024 bytes */
-    avctx->frame_size = ((int[]){ 4096, 2736, 2048, 1640 })[index];
+    avctx->frame_size = ((int[]){ 4096, 2736, 2048, 1640 })[c->code_size - 2];
 
     return 0;
 }
@@ -365,25 +365,23 @@ static int g726_encode_frame(AVCodecContext *avctx,
 static av_cold int g726_decode_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;
     }
 
-    index = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate - 2;
-
     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;
+
+    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, index);
-    c->code_size = index+2;
+    g726_reset(c, c->code_size - 2);
 
     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
 
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 0f4c079..8eed7ce 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -385,11 +385,13 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
     avio_wl32(pb, enc->sample_rate);
     if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) {
         bps = 0;
-    } else if (enc->codec_id == CODEC_ID_ADPCM_G726) {
-        bps = 4;
     } else {
-        if (!(bps = av_get_bits_per_sample(enc->codec_id)))
-            bps = 16; // default to 16
+        if (!(bps = av_get_bits_per_sample(enc->codec_id))) {
+            if (enc->bits_per_coded_sample)
+                bps = enc->bits_per_coded_sample;
+            else
+                bps = 16; // default to 16
+        }
     }
     if(bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample){
         av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps);
@@ -400,12 +402,10 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
         //blkalign = 144 * enc->bit_rate/enc->sample_rate;
     } else if (enc->codec_id == CODEC_ID_AC3) {
             blkalign = 3840; //maximum bytes per frame
-    } else if (enc->codec_id == CODEC_ID_ADPCM_G726) { //
-        blkalign = 1;
     } else if (enc->block_align != 0) { /* specified by the codec */
         blkalign = enc->block_align;
     } else
-        blkalign = enc->channels*bps >> 3;
+        blkalign = bps * enc->channels / av_gcd(8, bps);
     if (enc->codec_id == CODEC_ID_PCM_U8 ||
         enc->codec_id == CODEC_ID_PCM_S24LE ||
         enc->codec_id == CODEC_ID_PCM_S32LE ||
@@ -545,6 +545,9 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size)
         codec->channels    = 0;
         codec->sample_rate = 0;
     }
+    /* override bits_per_coded_sample for G.726 */
+    if (codec->codec_id == CODEC_ID_ADPCM_G726)
+        codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate;
 
     return 0;
 }



More information about the ffmpeg-cvslog mailing list