@@ -429,6 +429,8 @@ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
429429 int assetsCount ; // nuNumAssets
430430 int referenceClockCode ; // nuRefClockCode
431431 int extensionSubstreamFrameDurationCode ; // nuExSSFrameDurationCode
432+ boolean enableMixMetadata = false ; // bMixMetadataEnbl
433+ int [] mixerOutChannels = null ;
432434
433435 boolean staticFieldsPresent = headerBits .readBit (); // bStaticFieldsPresent
434436 if (staticFieldsPresent ) {
@@ -456,13 +458,16 @@ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
456458 }
457459 }
458460
459- if (headerBits .readBit ()) { // bMixMetadataEnbl
461+ enableMixMetadata = headerBits .readBit ();
462+ if (enableMixMetadata ) { // bMixMetadataEnbl
460463 headerBits .skipBits (2 ); // nuMixMetadataAdjLevel
461464 int mixerOutputMaskBits = (headerBits .readBits (2 ) + 1 ) << 2 ; // nuBits4MixOutMask
462465 int mixerOutputConfigurationCount = headerBits .readBits (2 ) + 1 ; // nuNumMixOutConfigs
466+ mixerOutChannels = new int [mixerOutputConfigurationCount ];
463467 // Output Mixing Configuration Loop
464468 for (int i = 0 ; i < mixerOutputConfigurationCount ; i ++) {
465- headerBits .skipBits (mixerOutputMaskBits ); // nuMixOutChMask
469+ int mask = headerBits .readBits (mixerOutputMaskBits ); // nuMixOutChMask
470+ mixerOutChannels [i ] = getRemapChannelCount (mask );
466471 }
467472 }
468473 } else {
@@ -476,8 +481,11 @@ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
476481 headerBits .skipBits (extensionSubstreamFrameSizeBits ); // nuAssetFsize
477482 int sampleRate = C .RATE_UNSET_INT ;
478483 int channelCount = C .LENGTH_UNSET ; // nuTotalNumChs
484+ boolean embeddedStereo = false ; // bEmbeddedStereoFlag
485+ boolean embedded6ch = false ; // bEmbeddedSixChFlag
479486
480- // Asset descriptor, see ETSI TS 102 114 V1.6.1 (2019-08) Table 7-5.
487+ // Asset descriptor: Size, Index and Per Stream Static Metadata, see ETSI TS 102 114 V1.6.1
488+ // (2019-08) Table 7-5.
481489 headerBits .skipBits (9 + 3 ); // nuAssetDescriptFsize, nuAssetIndex
482490 if (staticFieldsPresent ) {
483491 if (headerBits .readBit ()) { // bAssetTypeDescrPresent
@@ -493,9 +501,113 @@ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
493501 headerBits .skipBits (5 ); // nuBitResolution
494502 sampleRate = SAMPLE_RATE_BY_INDEX [headerBits .readBits (4 )]; // nuMaxSampleRate
495503 channelCount = headerBits .readBits (8 ) + 1 ;
496- // Done reading necessary bits, ignoring the rest.
504+ if (headerBits .readBit ()) { // bOne2OneMapChannels2Speakers
505+ if (channelCount > 2 ) {
506+ embeddedStereo = headerBits .readBit (); // bEmbeddedStereoFlag
507+ }
508+ if (channelCount > 6 ) {
509+ embedded6ch = headerBits .readBit (); // bEmbeddedSixChFlag
510+ }
511+ int speakerMaskLength = 0 ;
512+ if (headerBits .readBit ()) { // bSpkrMaskEnabled
513+ speakerMaskLength = (headerBits .readBits (2 ) + 1 ) << 2 ; // nuNumBits4SAMask
514+ headerBits .skipBits (speakerMaskLength ); // nuSpkrActivityMask
515+ }
516+ int speakerRemapSetsCount = headerBits .readBits (3 ); // nuNumSpkrRemapSets
517+ int [] speakerRemapSets = new int [speakerRemapSetsCount ];
518+ for (int i = 0 ; i < speakerRemapSetsCount ; i ++) {
519+ speakerRemapSets [i ] = headerBits .readBits (speakerMaskLength ); // nuStndrSpkrLayoutMask[ns]
520+ }
521+ for (int i = 0 ; i < speakerRemapSetsCount ; i ++) {
522+ int remapChannelCount = getRemapChannelCount (speakerRemapSets [i ]);
523+ int remapMaskLength = headerBits .readBits (5 ) + 1 ; // nuNumDecCh4Remap[ns]
524+ for (int j = 0 ; j < remapChannelCount ; j ++) {
525+ int remapMask = headerBits .readBits (remapMaskLength ); // nuRemapDecChMask[ns][nCh]
526+ int coef = Integer .bitCount (remapMask ); // nCoef
527+ headerBits .skipBits (coef * 5 ); // nuSpkrRemapCodes[ns][nCh][nc]
528+ }
529+ }
530+ }
531+ } else {
532+ headerBits .skipBits (3 ); // nuRepresentationType
497533 }
498534
535+ // Asset descriptor: Dynamic Metadata - DRC, DNC and Mixing Metadata, see ETSI TS 102 114 V1.6.1
536+ // (2019-08) Table 7-6.
537+ boolean hasDrcCoef = headerBits .readBit ();
538+ if (hasDrcCoef ) { // bDRCCoefPresent
539+ headerBits .skipBits (8 ); // nuDRCCode
540+ }
541+ if (headerBits .readBit ()) { // bDialNormPresent
542+ headerBits .skipBits (5 ); // nuDialNormCode
543+ }
544+ if (hasDrcCoef && embeddedStereo ) {
545+ headerBits .skipBits (8 ); // nuDRC2ChDmixCode
546+ }
547+ if (enableMixMetadata && headerBits .readBit ()) { // bMixMetadataPresent
548+ headerBits .skipBits (1 + 6 ); // bExternalMixFlag, nuPostMixGainAdjCode
549+ if (headerBits .readBits (2 ) < 3 ) { // nuControlMixerDRC
550+ headerBits .skipBits (3 ); // nuLimit4EmbeddedDRC
551+ } else {
552+ headerBits .skipBits (8 ); // nuCustomDRCCode
553+ }
554+ boolean audioScalePerChannel = headerBits .readBit (); // bEnblPerChMainAudioScale
555+ for (int mixerOutChannel : mixerOutChannels ) {
556+ if (audioScalePerChannel ) {
557+ headerBits .skipBits (6 * mixerOutChannel ); // nuMainAudioScaleCode[ns][nCh]
558+ } else {
559+ headerBits .skipBits (6 ); // nuMainAudioScaleCode[ns][0]
560+ }
561+ }
562+ int mixesCount = 1 ; // nEmDM
563+ int [] channelCountsForDownmixes = new int [3 ];
564+ channelCountsForDownmixes [0 ] = channelCount ; // nDecCh[0]
565+ if (embedded6ch ) {
566+ channelCountsForDownmixes [mixesCount ] = 6 ; // nDecCh[nEmDM]
567+ mixesCount ++; // nEmDM
568+ }
569+ if (embeddedStereo ) {
570+ channelCountsForDownmixes [mixesCount ] = 2 ; // nDecCh[nEmDM]
571+ mixesCount ++; // nEmDM
572+ }
573+ for (int mixerOutChannel : mixerOutChannels ) {
574+ for (int downmix = 0 ; downmix < mixesCount ; downmix ++) {
575+ int channelCountForDownmix = channelCountsForDownmixes [downmix ];
576+ for (int downmixChannel = 0 ; downmixChannel < channelCountForDownmix ; downmixChannel ++) {
577+ int mask = headerBits .readBits (mixerOutChannel ); // nuMixMapMask[ns][nE][nCh]
578+ int coefficients = Integer .bitCount (mask ); // nuNumMixCoefs[ns][nE][nCh]
579+ headerBits .skipBits (coefficients * 6 ); // nuMixCoeffs[ns][nE][nCh][nC]
580+ }
581+ }
582+ }
583+ }
584+
585+ // Asset descriptor: Decoder Navigation Data, see ETSI TS 102 114 V1.6.1 (2019-08) Table 7-7.
586+ int codingMode = headerBits .readBits (2 ); // nuCodingMode
587+ String mimeType ;
588+ switch (codingMode ) {
589+ case 0 : // DTS-HD Coding Mode that may contain multiple coding components
590+ int extensionMask = headerBits .readBits (12 );
591+ if ((extensionMask & 0x100 ) != 0 ) { // Low bit rate component
592+ mimeType = MimeTypes .AUDIO_DTS_EXPRESS ;
593+ } else {
594+ mimeType = MimeTypes .AUDIO_DTS_HD ;
595+ }
596+ break ;
597+ case 1 : // DTS-HD Loss-less coding mode without CBR component
598+ mimeType = MimeTypes .AUDIO_DTS_HD ;
599+ break ;
600+ case 2 : // DTS-HD Low bit-rate mode
601+ mimeType = MimeTypes .AUDIO_DTS_EXPRESS ;
602+ break ;
603+ case 3 : // The auxiliary coding mode is reserved for future applications.
604+ default :
605+ throw ParserException .createForMalformedContainer (
606+ /* message= */ "Unsupported coding mode in DTS HD header: " + codingMode ,
607+ /* cause= */ null );
608+ }
609+ // Done reading necessary bits, ignoring the rest.
610+
499611 long frameDurationUs = C .TIME_UNSET ;
500612 if (staticFieldsPresent ) {
501613 int referenceClockFrequency ;
@@ -521,14 +633,68 @@ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
521633 extensionSubstreamFrameDurationCode , C .MICROS_PER_SECOND , referenceClockFrequency );
522634 }
523635 return new DtsHeader (
524- MimeTypes . AUDIO_DTS_EXPRESS ,
636+ mimeType ,
525637 channelCount ,
526638 sampleRate ,
527639 extensionSubstreamFrameSize ,
528640 frameDurationUs ,
529641 /* bitrate= */ 0 );
530642 }
531643
644+ // See Table 7-10 in ETSI TS 102 114 V1.6.1
645+ private static int getRemapChannelCount (int mask ) {
646+ int remapChannelCount = 0 ;
647+ if ((mask & 0x0001 ) != 0 ) { // Centre in front of listener
648+ remapChannelCount += 1 ;
649+ }
650+ if ((mask & 0x0002 ) != 0 ) { // Left/Right in front
651+ remapChannelCount += 2 ;
652+ }
653+ if ((mask & 0x0004 ) != 0 ) { // Left/Right surround on side in rear
654+ remapChannelCount += 2 ;
655+ }
656+ if ((mask & 0x0008 ) != 0 ) { // Low frequency effects subwoofer
657+ remapChannelCount += 1 ;
658+ }
659+ if ((mask & 0x0010 ) != 0 ) { // Centre surround in rear
660+ remapChannelCount += 1 ;
661+ }
662+ if ((mask & 0x0020 ) != 0 ) { // Left/Right height in front
663+ remapChannelCount += 2 ;
664+ }
665+ if ((mask & 0x0040 ) != 0 ) { // Left/Right surround in rear
666+ remapChannelCount += 2 ;
667+ }
668+ if ((mask & 0x0080 ) != 0 ) { // Centre Height in front
669+ remapChannelCount += 1 ;
670+ }
671+ if ((mask & 0x0100 ) != 0 ) { // Over the listener's head
672+ remapChannelCount += 1 ;
673+ }
674+ if ((mask & 0x0200 ) != 0 ) { // Between left/right and centre in front
675+ remapChannelCount += 2 ;
676+ }
677+ if ((mask & 0x0400 ) != 0 ) { // Left/Right on side in front
678+ remapChannelCount += 2 ;
679+ }
680+ if ((mask & 0x0800 ) != 0 ) { // Left/Right surround on side
681+ remapChannelCount += 2 ;
682+ }
683+ if ((mask & 0x1000 ) != 0 ) { // Second low frequency effects subwoofer
684+ remapChannelCount += 1 ;
685+ }
686+ if ((mask & 0x2000 ) != 0 ) { // Left/Right height on side
687+ remapChannelCount += 2 ;
688+ }
689+ if ((mask & 0x4000 ) != 0 ) { // Centre height in rear
690+ remapChannelCount += 1 ;
691+ }
692+ if ((mask & 0x8000 ) != 0 ) { // Left/Right height in rear
693+ remapChannelCount += 2 ;
694+ }
695+ return remapChannelCount ;
696+ }
697+
532698 /**
533699 * Returns the size of the extension substream header in a DTS-HD frame according to ETSI TS 102
534700 * 114 V1.6.1 (2019-08), Section 7.5.2.
0 commit comments