]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/cbs_mpeg2.c
avcodec/clearvideo: display warning if decoder overreads input
[ffmpeg] / libavcodec / cbs_mpeg2.c
index 5956f393355a0f9fb94347081a042558744d6363..bfb64a0851192d555768cba9dfcafe3f6c3cdd0d 100644 (file)
@@ -1,18 +1,18 @@
 /*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -41,7 +41,7 @@
 
 #define READ
 #define READWRITE read
-#define RWContext BitstreamContext
+#define RWContext GetBitContext
 
 #define xui(width, name, var) do { \
         uint32_t value = 0; \
@@ -59,8 +59,8 @@
     } while (0)
 
 #define nextbits(width, compare, var) \
-    (bitstream_bits_left(rw) >= width && \
-     (var = bitstream_peek(rw, width)) == (compare))
+    (get_bits_left(rw) >= width && \
+     (var = show_bits(rw, width)) == (compare))
 
 #include "cbs_mpeg2_syntax_template.c"
 
 #undef nextbits
 
 
+static void cbs_mpeg2_free_user_data(void *unit, uint8_t *content)
+{
+    MPEG2RawUserData *user = (MPEG2RawUserData*)content;
+    av_buffer_unref(&user->user_data_ref);
+    av_freep(&content);
+}
+
+static void cbs_mpeg2_free_slice(void *unit, uint8_t *content)
+{
+    MPEG2RawSlice *slice = (MPEG2RawSlice*)content;
+    av_buffer_unref(&slice->header.extra_information_ref);
+    av_buffer_unref(&slice->data_ref);
+    av_freep(&content);
+}
+
 static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
                                     CodedBitstreamFragment *frag,
                                     int header)
@@ -138,7 +153,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
         memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 
         err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type,
-                                      unit_data, unit_size);
+                                      unit_data, unit_size, NULL);
         if (err < 0) {
             av_freep(&unit_data);
             return err;
@@ -157,10 +172,10 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
 static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
                                CodedBitstreamUnit *unit)
 {
-    BitstreamContext bc;
+    GetBitContext gbc;
     int err;
 
-    err = bitstream_init(&bc, unit->data, 8 * unit->data_size);
+    err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
     if (err < 0)
         return err;
 
@@ -168,25 +183,25 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
         MPEG2RawSlice *slice;
         int pos, len;
 
-        slice = av_mallocz(sizeof(*slice));
-        if (!slice)
-            return AVERROR(ENOMEM);
-        err = cbs_mpeg2_read_slice_header(ctx, &bc, &slice->header);
-        if (err < 0) {
-            av_free(slice);
+        err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice),
+                                        &cbs_mpeg2_free_slice);
+        if (err < 0)
+            return err;
+        slice = unit->content;
+
+        err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
+        if (err < 0)
             return err;
-        }
 
-        pos = bitstream_tell(&bc);
+        pos = get_bits_count(&gbc);
         len = unit->data_size;
 
         slice->data_size = len - pos / 8;
-        slice->data = av_malloc(slice->data_size +
-                                AV_INPUT_BUFFER_PADDING_SIZE);
-        if (!slice->data) {
-            av_free(slice);
+        slice->data_ref  = av_buffer_alloc(slice->data_size +
+                                           AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!slice->data_ref)
             return AVERROR(ENOMEM);
-        }
+        slice->data = slice->data_ref->data;
 
         memcpy(slice->data,
                unit->data + pos / 8, slice->data_size);
@@ -194,30 +209,29 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
                AV_INPUT_BUFFER_PADDING_SIZE);
         slice->data_bit_start = pos % 8;
 
-        unit->content = slice;
-
     } else {
         switch (unit->type) {
-#define START(start_code, type, func) \
+#define START(start_code, type, read_func, free_func) \
         case start_code: \
             { \
                 type *header; \
-                header = av_mallocz(sizeof(*header)); \
-                if (!header) \
-                    return AVERROR(ENOMEM); \
-                err = cbs_mpeg2_read_ ## func(ctx, &bc, header); \
-                if (err < 0) { \
-                    av_free(header); \
+                err = ff_cbs_alloc_unit_content(ctx, unit, \
+                                                sizeof(*header), free_func); \
+                if (err < 0) \
+                    return err; \
+                header = unit->content; \
+                err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \
+                if (err < 0) \
                     return err; \
-                } \
-                unit->content = header; \
             } \
             break;
-            START(0x00, MPEG2RawPictureHeader,  picture_header);
-            START(0xb2, MPEG2RawUserData,       user_data);
-            START(0xb3, MPEG2RawSequenceHeader, sequence_header);
-            START(0xb5, MPEG2RawExtensionData,  extension_data);
-            START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header);
+            START(0x00, MPEG2RawPictureHeader,  picture_header,  NULL);
+            START(0xb2, MPEG2RawUserData,       user_data,
+                                            &cbs_mpeg2_free_user_data);
+            START(0xb3, MPEG2RawSequenceHeader, sequence_header, NULL);
+            START(0xb5, MPEG2RawExtensionData,  extension_data,  NULL);
+            START(0xb8, MPEG2RawGroupOfPicturesHeader,
+                                       group_of_pictures_header, NULL);
 #undef START
         default:
             av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n",
@@ -260,7 +274,7 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
                                  PutBitContext *pbc)
 {
     MPEG2RawSlice *slice = unit->content;
-    BitstreamContext bc;
+    GetBitContext gbc;
     size_t bits_left;
     int err;
 
@@ -272,14 +286,14 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
         if (slice->data_size * 8 + 8 > put_bits_left(pbc))
             return AVERROR(ENOSPC);
 
-        bitstream_init(&bc, slice->data, slice->data_size * 8);
-        bitstream_skip(&bc, slice->data_bit_start);
+        init_get_bits(&gbc, slice->data, slice->data_size * 8);
+        skip_bits_long(&gbc, slice->data_bit_start);
 
-        while (bitstream_bits_left(&bc) > 15)
-            put_bits(pbc, 16, bitstream_read(&bc, 16));
+        while (get_bits_left(&gbc) > 15)
+            put_bits(pbc, 16, get_bits(&gbc, 16));
 
-        bits_left = bitstream_bits_left(&bc);
-        put_bits(pbc, bits_left, bitstream_read(&bc, bits_left));
+        bits_left = get_bits_left(&gbc);
+        put_bits(pbc, bits_left, get_bits(&gbc, bits_left));
 
         // Align with zeroes.
         while (put_bits_count(pbc) % 8 != 0)
@@ -305,7 +319,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
         if (err < 0) {
             av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
                    "sufficiently large write buffer (last attempt "
-                   "%zu bytes).\n", priv->write_buffer_size);
+                   "%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size);
             return err;
         }
     }
@@ -335,7 +349,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
     unit->data_size = (put_bits_count(&pbc) + 7) / 8;
     flush_put_bits(&pbc);
 
-    err = av_reallocp(&unit->data, unit->data_size);
+    err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
     if (err < 0)
         return err;
 
@@ -355,9 +369,10 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
     for (i = 0; i < frag->nb_units; i++)
         size += 3 + frag->units[i].data_size;
 
-    data = av_malloc(size);
-    if (!data)
+    frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!frag->data_ref)
         return AVERROR(ENOMEM);
+    data = frag->data_ref->data;
 
     dp = 0;
     for (i = 0; i < frag->nb_units; i++) {
@@ -373,25 +388,13 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
 
     av_assert0(dp == size);
 
+    memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     frag->data      = data;
     frag->data_size = size;
 
     return 0;
 }
 
-static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit)
-{
-    if (MPEG2_START_IS_SLICE(unit->type)) {
-        MPEG2RawSlice *slice = unit->content;
-        av_freep(&slice->data);
-        av_freep(&slice->header.extra_information);
-    } else if (unit->type == MPEG2_START_USER_DATA) {
-        MPEG2RawUserData *user = unit->content;
-        av_freep(&user->user_data);
-    }
-    av_freep(&unit->content);
-}
-
 static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
 {
     CodedBitstreamMPEG2Context *priv = ctx->priv_data;
@@ -409,6 +412,5 @@ const CodedBitstreamType ff_cbs_type_mpeg2 = {
     .write_unit        = &cbs_mpeg2_write_unit,
     .assemble_fragment = &cbs_mpeg2_assemble_fragment,
 
-    .free_unit         = &cbs_mpeg2_free_unit,
     .close             = &cbs_mpeg2_close,
 };