[SCM] libav/experimental: put_bits can only reliably write up to 31 bit bits, above it relies on undefined shift behaviour. Document this, fix the assert and add a put_bits32 to handle writing 32 bits and use that where necessary.

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jun 30 16:52:20 UTC 2013


The following commit has been merged in the experimental branch:
commit 43d7c6118d64a8b2772e2d9e0c13413968e776f1
Author: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
Date:   Thu Oct 1 15:40:29 2009 +0000

    put_bits can only reliably write up to 31 bit bits, above it relies on
    undefined shift behaviour.
    Document this, fix the assert and add a put_bits32 to handle writing 32
    bits and use that where necessary.
    
    Originally committed as revision 20124 to svn://svn.ffmpeg.org/ffmpeg/trunk

diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c
index 5e8defb..691e6df 100644
--- a/libavcodec/alacenc.c
+++ b/libavcodec/alacenc.c
@@ -123,7 +123,7 @@ static void write_frame_header(AlacEncodeContext *s, int is_verbatim)
     put_bits(&s->pbctx, 1,  1);                             // Sample count is in the header
     put_bits(&s->pbctx, 2,  0);                             // FIXME: Wasted bytes field
     put_bits(&s->pbctx, 1,  is_verbatim);                   // Audio block is verbatim
-    put_bits(&s->pbctx, 32, s->avctx->frame_size);          // No. of samples in the frame
+    put_bits32(&s->pbctx, s->avctx->frame_size);            // No. of samples in the frame
 }
 
 static void calc_predictor_params(AlacEncodeContext *s, int ch)
diff --git a/libavcodec/put_bits.h b/libavcodec/put_bits.h
index 4b4b3a8..b081c26 100644
--- a/libavcodec/put_bits.h
+++ b/libavcodec/put_bits.h
@@ -136,6 +136,10 @@ void ff_put_string(PutBitContext * pbc, const char *s, int terminate_string);
  */
 void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
 
+/**
+ * Write up to 31 bits into a bitstream.
+ * Use put_bits32 to write 32 bits.
+ */
 static inline void put_bits(PutBitContext *s, int n, unsigned int value)
 #ifndef ALT_BITSTREAM_WRITER
 {
@@ -143,7 +147,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value)
     int bit_left;
 
     //    printf("put_bits=%d %x\n", n, value);
-    assert(n == 32 || value < (1U << n));
+    assert(n <= 31 && value < (1U << n));
 
     bit_buf = s->bit_buf;
     bit_left = s->bit_left;
@@ -260,6 +264,22 @@ static inline void put_sbits(PutBitContext *pb, int bits, int32_t val)
 }
 
 /**
+ * Write exactly 32 bits into a bitstream
+ */
+static void av_unused put_bits32(PutBitContext *s, uint32_t value)
+{
+    int lo = value & 0xffff;
+    int hi = value >> 16;
+#ifdef ALT_BITSTREAM_WRITER_LE
+    put_bits(s, 16, lo);
+    put_bits(s, 16, hi);
+#else
+    put_bits(s, 16, hi);
+    put_bits(s, 16, lo);
+#endif
+}
+
+/**
  * Returns the pointer to the byte where the bitstream writer will put
  * the next bit.
  */
diff --git a/libavcodec/vorbis_enc.c b/libavcodec/vorbis_enc.c
index 508a4f3..61f78b5 100644
--- a/libavcodec/vorbis_enc.c
+++ b/libavcodec/vorbis_enc.c
@@ -386,7 +386,7 @@ static void put_float(PutBitContext *pb, float f)
         mant = -mant;
     }
     res |= mant | (exp << 21);
-    put_bits(pb, 32, res);
+    put_bits32(pb, res);
 }
 
 static void put_codebook_header(PutBitContext *pb, vorbis_enc_codebook *cb)
@@ -531,12 +531,12 @@ static int put_main_header(vorbis_enc_context *venc, uint8_t **out)
     init_put_bits(&pb, p, buffer_len);
     put_bits(&pb, 8, 1); //magic
     ff_put_string(&pb, "vorbis", 0);
-    put_bits(&pb, 32, 0); // version
+    put_bits32(&pb, 0); // version
     put_bits(&pb,  8, venc->channels);
-    put_bits(&pb, 32, venc->sample_rate);
-    put_bits(&pb, 32, 0); // bitrate
-    put_bits(&pb, 32, 0); // bitrate
-    put_bits(&pb, 32, 0); // bitrate
+    put_bits32(&pb, venc->sample_rate);
+    put_bits32(&pb, 0); // bitrate
+    put_bits32(&pb, 0); // bitrate
+    put_bits32(&pb, 0); // bitrate
     put_bits(&pb,  4, venc->log2_blocksize[0]);
     put_bits(&pb,  4, venc->log2_blocksize[1]);
     put_bits(&pb,  1, 1); // framing
@@ -550,8 +550,8 @@ static int put_main_header(vorbis_enc_context *venc, uint8_t **out)
     init_put_bits(&pb, p, buffer_len);
     put_bits(&pb, 8, 3); //magic
     ff_put_string(&pb, "vorbis", 0);
-    put_bits(&pb, 32, 0); // vendor length TODO
-    put_bits(&pb, 32, 0); // amount of comments
+    put_bits32(&pb, 0); // vendor length TODO
+    put_bits32(&pb, 0); // amount of comments
     put_bits(&pb,  1, 1); // framing
 
     flush_put_bits(&pb);
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index df4c991..a471b38 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -89,7 +89,7 @@ static int put_pack_header(AVFormatContext *ctx,
 
     init_put_bits(&pb, buf, 128);
 
-    put_bits(&pb, 32, PACK_START_CODE);
+    put_bits32(&pb, PACK_START_CODE);
     if (s->is_mpeg2) {
         put_bits(&pb, 2, 0x1);
     } else {
@@ -125,7 +125,7 @@ static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_str
 
     init_put_bits(&pb, buf, 128);
 
-    put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
+    put_bits32(&pb, SYSTEM_HEADER_START_CODE);
     put_bits(&pb, 16, 0);
     put_bits(&pb, 1, 1);
 

-- 
Libav/FFmpeg packaging



More information about the pkg-multimedia-commits mailing list