mirror of https://git.videolan.org/git/ffmpeg.git
mlpdec: support major sync headers with optional extension blocks
Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
parent
448c8cfe4c
commit
f36f6a608b
|
@ -119,6 +119,23 @@ static uint64_t truehd_layout(int chanmap)
|
||||||
return layout;
|
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
|
/** Read a major sync info header - contains high level information about
|
||||||
* the stream - sample rate, channel arrangement etc. Most of this
|
* the stream - sample rate, channel arrangement etc. Most of this
|
||||||
* information is not actually necessary for decoding, only for playback.
|
* information is not actually necessary for decoding, only for playback.
|
||||||
|
@ -127,18 +144,19 @@ static uint64_t truehd_layout(int chanmap)
|
||||||
|
|
||||||
int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
|
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;
|
uint16_t checksum;
|
||||||
|
|
||||||
assert(get_bits_count(gb) == 0);
|
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");
|
av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
checksum = ff_mlp_checksum16(gb->buffer, 26);
|
checksum = ff_mlp_checksum16(gb->buffer, header_size - 2);
|
||||||
if (checksum != AV_RL16(gb->buffer+26)) {
|
if (checksum != AV_RL16(gb->buffer+header_size-2)) {
|
||||||
av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
|
av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +165,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
mh->stream_type = get_bits(gb, 8);
|
mh->stream_type = get_bits(gb, 8);
|
||||||
|
mh->header_size = header_size;
|
||||||
|
|
||||||
if (mh->stream_type == 0xbb) {
|
if (mh->stream_type == 0xbb) {
|
||||||
mh->group1_bits = mlp_quants[get_bits(gb, 4)];
|
mh->group1_bits = mlp_quants[get_bits(gb, 4)];
|
||||||
|
@ -197,7 +216,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
|
||||||
|
|
||||||
mh->num_substreams = get_bits(gb, 4);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
typedef struct MLPHeaderInfo
|
typedef struct MLPHeaderInfo
|
||||||
{
|
{
|
||||||
int stream_type; ///< 0xBB for MLP, 0xBA for TrueHD
|
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 group1_bits; ///< The bit depth of the first substream
|
||||||
int group2_bits; ///< Bit depth of the second substream (MLP only)
|
int group2_bits; ///< Bit depth of the second substream (MLP only)
|
||||||
|
|
|
@ -132,6 +132,9 @@ typedef struct MLPDecodeContext {
|
||||||
/// Current access unit being read has a major sync.
|
/// Current access unit being read has a major sync.
|
||||||
int is_major_sync_unit;
|
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.
|
/// Set if a valid major sync block has been read. Otherwise no decoding is possible.
|
||||||
uint8_t params_valid;
|
uint8_t params_valid;
|
||||||
|
|
||||||
|
@ -346,6 +349,8 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb)
|
||||||
return AVERROR_PATCHWELCOME;
|
return AVERROR_PATCHWELCOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m->major_sync_header_size = mh.header_size;
|
||||||
|
|
||||||
m->access_unit_size = mh.access_unit_size;
|
m->access_unit_size = mh.access_unit_size;
|
||||||
m->access_unit_size_pow2 = mh.access_unit_size_pow2;
|
m->access_unit_size_pow2 = mh.access_unit_size_pow2;
|
||||||
|
|
||||||
|
@ -1105,7 +1110,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data,
|
||||||
if (read_major_sync(m, &gb) < 0)
|
if (read_major_sync(m, &gb) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
m->is_major_sync_unit = 1;
|
m->is_major_sync_unit = 1;
|
||||||
header_size += 28;
|
header_size += m->major_sync_header_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m->params_valid) {
|
if (!m->params_valid) {
|
||||||
|
|
Loading…
Reference in New Issue