aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2014-09-21 02:29:27 +0200
committerMichael Niedermayer <michaelni@gmx.at>2014-09-21 13:32:56 +0200
commitff34b2d6d35b212523428b9b932cce4914f7ac03 (patch)
tree1a33096e77d6a766d9e83c0af3b1491999ee2ed4
parent6821a5a4adcb40c458356e8bb90416dd8f5dd6b2 (diff)
downloadffmpeg-ff34b2d6d35b212523428b9b932cce4914f7ac03.tar.gz
mlpdec: support major sync headers with optional extension blocks
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/mlp_parser.c29
-rw-r--r--libavcodec/mlp_parser.h1
-rw-r--r--libavcodec/mlpdec.c7
3 files changed, 31 insertions, 6 deletions
diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c
index 4bb82eebbf..deaa844fc0 100644
--- a/libavcodec/mlp_parser.c
+++ b/libavcodec/mlp_parser.c
@@ -119,6 +119,23 @@ uint64_t ff_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,19 @@ uint64_t ff_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;
av_assert1(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 +165,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)];
@@ -199,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 5d1d2e7845..0c0109efcc 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 ed6a7fb58c..fddeb14ad7 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;
@@ -349,6 +352,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;
@@ -1142,7 +1147,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) {