vlc | branch: master | Francois Cartegnie <[email protected]> | Mon Mar 11 18:28:54 2019 +0100| [ddf8716a0d749e9af01b6d1a32f6f99ab7aed340] | committer: Francois Cartegnie
packetizer: dts: handle LBR (fix #21973) > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ddf8716a0d749e9af01b6d1a32f6f99ab7aed340 --- modules/packetizer/dts.c | 75 ++++++++++++++++++++++++++++++++--------- modules/packetizer/dts_header.c | 55 ++++++++++++++++++++++++++++-- modules/packetizer/dts_header.h | 3 ++ 3 files changed, 114 insertions(+), 19 deletions(-) diff --git a/modules/packetizer/dts.c b/modules/packetizer/dts.c index b5bb4f09ce..0500009d57 100644 --- a/modules/packetizer/dts.c +++ b/modules/packetizer/dts.c @@ -222,14 +222,47 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block ) break; case STATE_SYNC_SUBSTREAM_EXTENSIONS: + /* Peek into the substream extension (sync + header size < frame_size) */ + if( block_PeekOffsetBytes( &p_sys->bytestream, + p_sys->first.i_substream_header_size, + p_header, + VLC_DTS_HEADER_SIZE ) != VLC_SUCCESS ) { - msg_Warn( p_dec, "substream without the paired core stream, " - "skip it" ); + /* Need more data */ + return NULL; + } + + vlc_dts_header_t xssheader; + if( vlc_dts_header_Parse( &xssheader, p_header, + VLC_DTS_HEADER_SIZE ) != VLC_SUCCESS ) + { + msg_Dbg( p_dec, "emulated substream sync word, can't find extension" ); + block_SkipByte( &p_sys->bytestream ); p_sys->i_state = STATE_NOSYNC; - if( block_SkipBytes( &p_sys->bytestream, - p_sys->first.i_frame_size ) != VLC_SUCCESS ) - return NULL; + break; + } + + if( xssheader.syncword == DTS_SYNC_SUBSTREAM_LBR ) + { + /* + * LBR exists as independant SUBSTREAM. It is seen valid + * only when SUBSTREAM[LBR]..SUBTREAM. + * CORE...SUBSTREAM is regular extension. + * SUBSTREAM...CORE is sync issue. + */ + p_dec->fmt_out.i_profile = PROFILE_DTS_EXPRESS; + p_sys->first.i_rate = xssheader.i_rate; + p_sys->first.i_frame_length = xssheader.i_frame_length; + p_sys->i_state = STATE_NEXT_SYNC; + break; } + + msg_Warn( p_dec, "substream without the paired core stream, skip it" ); + p_sys->i_state = STATE_NOSYNC; + p_dec->fmt_out.i_profile = PROFILE_DTS; + if( block_SkipBytes( &p_sys->bytestream, + p_sys->first.i_frame_size ) != VLC_SUCCESS ) + return NULL; break; case STATE_NEXT_SYNC: @@ -279,24 +312,34 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block ) /* Check if a DTS substream packet is located just after * the core packet */ - if( p_sys->i_next_offset == p_sys->first.i_frame_size ) + if( p_sys->i_next_offset == p_sys->first.i_frame_size && + vlc_dts_header_Parse( &p_sys->second, + p_header, VLC_DTS_HEADER_SIZE ) == VLC_SUCCESS && + p_sys->second.syncword == DTS_SYNC_SUBSTREAM ) { - if( vlc_dts_header_Parse( &p_sys->second, p_header, - VLC_DTS_HEADER_SIZE ) - == VLC_SUCCESS && p_sys->second.syncword == DTS_SYNC_SUBSTREAM ) - { - p_sys->i_state = STATE_NEXT_SYNC_SUBSTREAM_EXTENSIONS; - break; - } + p_sys->i_state = STATE_NEXT_SYNC_SUBSTREAM_EXTENSIONS; + } + else + { + p_dec->fmt_out.i_profile = PROFILE_DTS; + p_sys->i_state = STATE_GET_DATA; } - p_sys->i_state = STATE_GET_DATA; } break; case STATE_NEXT_SYNC_SUBSTREAM_EXTENSIONS: - p_dec->fmt_out.i_profile = PROFILE_DTS_HD; + assert(p_sys->second.syncword == DTS_SYNC_SUBSTREAM); + if( p_sys->first.syncword == DTS_SYNC_SUBSTREAM ) + { + /* First substream must have been LBR */ + p_dec->fmt_out.i_profile = PROFILE_DTS_EXPRESS; + } + else /* Otherwise that's core + extensions, we need to output both */ + { + p_dec->fmt_out.i_profile = PROFILE_DTS_HD; + p_sys->i_input_size += p_sys->second.i_frame_size; + } p_sys->i_state = STATE_GET_DATA; - p_sys->i_input_size += p_sys->second.i_frame_size; break; case STATE_GET_DATA: diff --git a/modules/packetizer/dts_header.c b/modules/packetizer/dts_header.c index 1d4ebd98a1..0eb64dfcfa 100644 --- a/modules/packetizer/dts_header.c +++ b/modules/packetizer/dts_header.c @@ -113,6 +113,9 @@ static enum vlc_dts_syncword_e dts_header_getSyncword( const uint8_t *p_buf ) && (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 ) return DTS_SYNC_CORE_14BITS_LE; else + if( memcmp( p_buf, "\x0A\x80\x19\x21", 4 ) == 0 ) + return DTS_SYNC_SUBSTREAM_LBR; + else return DTS_SYNC_NONE; } @@ -233,6 +236,49 @@ static uint16_t dca_get_channels( uint8_t i_amode, bool b_lfe, return i_physical_channels; } +static uint8_t dca_get_LBR_channels( uint16_t nuSpkrActivityMask, + uint16_t *pi_chans ) +{ + uint16_t i_physical_channels = 0; + uint8_t i_channels = 0; + + static const struct + { + int phy; + uint8_t nb; + } bitmask[16] = { + /* table 7-10 */ + { AOUT_CHAN_CENTER, 1 }, + { AOUT_CHANS_FRONT, 2 }, + { AOUT_CHANS_MIDDLE, 2 }, + { AOUT_CHAN_LFE, 1 }, + { AOUT_CHAN_REARCENTER, 1 }, + { 0, 2 }, + { AOUT_CHANS_REAR, 2 }, + { 0, 1 }, + { 0, 1 }, + { 0, 2 }, + { AOUT_CHANS_FRONT, 2 }, + { AOUT_CHANS_MIDDLE, 2 }, + { 0, 1 }, + { 0, 2 }, + { 0, 1 }, + { 0, 2 }, + }; + + for( int i=0 ; nuSpkrActivityMask; nuSpkrActivityMask >>= 1 ) + { + if( nuSpkrActivityMask & 1 ) + { + i_physical_channels |= bitmask[i].phy; + i_channels += bitmask[i].nb; + } + ++i; + } + *pi_chans = i_physical_channels; + return i_channels; +} + static int dts_header_ParseSubstream( vlc_dts_header_t *p_header, const void *p_buffer ) { @@ -288,12 +334,13 @@ static int dts_header_ParseLBRExtSubstream( vlc_dts_header_t *p_header, p_header->i_frame_length = 4096; uint16_t i_spkrmask = bs_read( &s, 16 ); + dca_get_LBR_channels( i_spkrmask, &p_header->i_physical_channels ); bs_skip( &s, 16 ); bs_skip( &s, 8 ); - bs_skip( &s, 8 ); - bs_skip( &s, 16 ); + uint16_t nLBRBitRateMSnybbles = bs_read( &s, 8 ); bs_skip( &s, 16 ); - + uint16_t nLBRScaledBitRate_LSW = bs_read( &s, 16 ); + p_header->i_bitrate = nLBRScaledBitRate_LSW | ((nLBRBitRateMSnybbles & 0xF0) << 12); return VLC_SUCCESS; } @@ -388,6 +435,8 @@ int vlc_dts_header_Parse( vlc_dts_header_t *p_header, } case DTS_SYNC_SUBSTREAM: return dts_header_ParseSubstream( p_header, p_buffer ); + case DTS_SYNC_SUBSTREAM_LBR: + return dts_header_ParseLBRExtSubstream( p_header, p_buffer ); default: vlc_assert_unreachable(); } diff --git a/modules/packetizer/dts_header.h b/modules/packetizer/dts_header.h index 2ec623d934..255f0be770 100644 --- a/modules/packetizer/dts_header.h +++ b/modules/packetizer/dts_header.h @@ -26,6 +26,7 @@ #define PROFILE_DTS_INVALID -1 #define PROFILE_DTS 0 #define PROFILE_DTS_HD 1 +#define PROFILE_DTS_EXPRESS 2 enum vlc_dts_syncword_e { @@ -35,6 +36,8 @@ enum vlc_dts_syncword_e DTS_SYNC_CORE_14BITS_BE, DTS_SYNC_CORE_14BITS_LE, DTS_SYNC_SUBSTREAM, + /* Substreams internal syncs */ + DTS_SYNC_SUBSTREAM_LBR, }; typedef struct _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
