From: Hendrik Leppkes <h.lepp...@gmail.com>

Signed-off-by: Luca Barbato <lu_z...@gentoo.org>
---

Again, asked by Felix, not really tested.

 libavcodec/mlp_parser.c | 31 ++++++++++++++++++++++++++-----
 libavcodec/mlp_parser.h |  1 +
 libavcodec/mlpdec.c     |  7 ++++++-
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c
index 075227f..1523000 100644
--- a/libavcodec/mlp_parser.c
+++ b/libavcodec/mlp_parser.c
@@ -119,6 +119,23 @@ static uint64_t truehd_layout(int chanmap)
     return layout;
 }

+static int ff_mlp_get_major_sync_size(const uint8_t * buf, int bufsize)
+{
+    int has_extension, extensions = 0;
+    int size = 28;
+    if (bufsize < 28)
+        return -1;
+
+    if (AV_RB32(buf) == 0xf8726fba) {
+        has_extension = buf[25] & 1;
+        if (has_extension) {
+            extensions = buf[26] >> 4;
+            size += 2 + extensions * 2;
+        }
+    }
+    return size;
+}
+
 /** Read a major sync info header - contains high level information about
  *  the stream - sample rate, channel arrangement etc. Most of this
  *  information is not actually necessary for decoding, only for playback.
@@ -127,18 +144,21 @@ static uint64_t truehd_layout(int chanmap)

 int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
 {
-    int ratebits, channel_arrangement;
+    int ratebits, channel_arrangement, header_size;
     uint16_t checksum;

     assert(get_bits_count(gb) == 0);

-    if (gb->size_in_bits < 28 << 3) {
+    header_size = ff_mlp_get_major_sync_size(gb->buffer,
+                                             gb->size_in_bits >> 3);
+
+    if (header_size < 0 || gb->size_in_bits < header_size << 3) {
         av_log(log, AV_LOG_ERROR, "packet too short, unable to read major 
sync\n");
         return -1;
     }

-    checksum = ff_mlp_checksum16(gb->buffer, 26);
-    if (checksum != AV_RL16(gb->buffer+26)) {
+    checksum = ff_mlp_checksum16(gb->buffer, header_size - 2);
+    if (checksum != AV_RL16(gb->buffer + header_size - 2)) {
         av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
         return AVERROR_INVALIDDATA;
     }
@@ -147,6 +167,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, 
GetBitContext *gb)
         return AVERROR_INVALIDDATA;

     mh->stream_type = get_bits(gb, 8);
+    mh->header_size = header_size;

     if (mh->stream_type == 0xbb) {
         mh->group1_bits = mlp_quants[get_bits(gb, 4)];
@@ -197,7 +218,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, 
GetBitContext *gb)

     mh->num_substreams = get_bits(gb, 4);

-    skip_bits_long(gb, 4 + 11 * 8);
+    skip_bits_long(gb, 4 + (header_size - 17) * 8);

     return 0;
 }
diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h
index 7530fac..06ab421 100644
--- a/libavcodec/mlp_parser.h
+++ b/libavcodec/mlp_parser.h
@@ -32,6 +32,7 @@
 typedef struct MLPHeaderInfo
 {
     int stream_type;                        ///< 0xBB for MLP, 0xBA for TrueHD
+    int header_size;                        ///< Size of the major sync 
header, in bytes

     int group1_bits;                        ///< The bit depth of the first 
substream
     int group2_bits;                        ///< Bit depth of the second 
substream (MLP only)
diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
index 17f188f..2c279fe 100644
--- a/libavcodec/mlpdec.c
+++ b/libavcodec/mlpdec.c
@@ -132,6 +132,9 @@ typedef struct MLPDecodeContext {
     /// Current access unit being read has a major sync.
     int         is_major_sync_unit;

+    /// Size of the major sync unit, in bytes
+    int         major_sync_header_size;
+
     /// Set if a valid major sync block has been read. Otherwise no decoding 
is possible.
     uint8_t     params_valid;

@@ -346,6 +349,8 @@ static int read_major_sync(MLPDecodeContext *m, 
GetBitContext *gb)
         return AVERROR_PATCHWELCOME;
     }

+    m->major_sync_header_size = mh.header_size;
+
     m->access_unit_size      = mh.access_unit_size;
     m->access_unit_size_pow2 = mh.access_unit_size_pow2;

@@ -1107,7 +1112,7 @@ static int read_access_unit(AVCodecContext *avctx, void* 
data,
         if (read_major_sync(m, &gb) < 0)
             goto error;
         m->is_major_sync_unit = 1;
-        header_size += 28;
+        header_size += m->major_sync_header_size;
     }

     if (!m->params_valid) {
--
2.1.0

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to