xref: /aosp_15_r20/system/media/audio_utils/spdif/DTSFrameScanner.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker  * Copyright 2015, The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker  *
4*b9df5ad1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker  *
8*b9df5ad1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker  *
10*b9df5ad1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker  * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker  */
16*b9df5ad1SAndroid Build Coastguard Worker 
17*b9df5ad1SAndroid Build Coastguard Worker #define LOG_TAG "AudioSPDIF"
18*b9df5ad1SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*b9df5ad1SAndroid Build Coastguard Worker 
20*b9df5ad1SAndroid Build Coastguard Worker #include <assert.h>
21*b9df5ad1SAndroid Build Coastguard Worker #include <string.h>
22*b9df5ad1SAndroid Build Coastguard Worker 
23*b9df5ad1SAndroid Build Coastguard Worker #include <log/log.h>
24*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/spdif/FrameScanner.h>
25*b9df5ad1SAndroid Build Coastguard Worker 
26*b9df5ad1SAndroid Build Coastguard Worker #include "BitFieldParser.h"
27*b9df5ad1SAndroid Build Coastguard Worker #include "DTSFrameScanner.h"
28*b9df5ad1SAndroid Build Coastguard Worker 
29*b9df5ad1SAndroid Build Coastguard Worker namespace android {
30*b9df5ad1SAndroid Build Coastguard Worker 
31*b9df5ad1SAndroid Build Coastguard Worker // TODO Handle termination frames.
32*b9df5ad1SAndroid Build Coastguard Worker // TODO assert if parse past end of header buffer
33*b9df5ad1SAndroid Build Coastguard Worker // TODO Handle DTS_HD
34*b9df5ad1SAndroid Build Coastguard Worker 
35*b9df5ad1SAndroid Build Coastguard Worker const uint8_t DTSFrameScanner::kSyncBytes[] =
36*b9df5ad1SAndroid Build Coastguard Worker         { 0x7F, 0xFE, 0x80, 0x01 };
37*b9df5ad1SAndroid Build Coastguard Worker 
38*b9df5ad1SAndroid Build Coastguard Worker const int32_t DTSFrameScanner::kDTSSampleRateTable[DTS_NUM_SAMPLE_RATE_TABLE_ENTRIES]
39*b9df5ad1SAndroid Build Coastguard Worker         = { -1, 8000, 16000, 32000, -1, -1,
40*b9df5ad1SAndroid Build Coastguard Worker         11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1 };
41*b9df5ad1SAndroid Build Coastguard Worker 
42*b9df5ad1SAndroid Build Coastguard Worker // Defined in IEC61937-2
43*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_DATA_TYPE_DTS_I        11
44*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_DATA_TYPE_DTS_II       12
45*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_DATA_TYPE_DTS_III      13
46*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_DATA_TYPE_DTS_IV       17
47*b9df5ad1SAndroid Build Coastguard Worker 
48*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_MAX_SAMPLES_TYPE_I    512
49*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_MAX_SAMPLES_TYPE_II  1024
50*b9df5ad1SAndroid Build Coastguard Worker #define IEC61937_MAX_SAMPLES_TYPE_III 2048
51*b9df5ad1SAndroid Build Coastguard Worker 
52*b9df5ad1SAndroid Build Coastguard Worker // Limits defined in DTS spec paragraph 5.3.1
53*b9df5ad1SAndroid Build Coastguard Worker #define DTS_MINIMUM_NBLKS                5
54*b9df5ad1SAndroid Build Coastguard Worker #define DTS_MINIMUM_FSIZE               95
55*b9df5ad1SAndroid Build Coastguard Worker 
56*b9df5ad1SAndroid Build Coastguard Worker #define DTS_HEADER_BYTES_NEEDED         12
57*b9df5ad1SAndroid Build Coastguard Worker 
58*b9df5ad1SAndroid Build Coastguard Worker // Scanner for DTS byte streams.
DTSFrameScanner()59*b9df5ad1SAndroid Build Coastguard Worker DTSFrameScanner::DTSFrameScanner()
60*b9df5ad1SAndroid Build Coastguard Worker  : FrameScanner(IEC61937_DATA_TYPE_DTS_I,
61*b9df5ad1SAndroid Build Coastguard Worker     DTSFrameScanner::kSyncBytes,
62*b9df5ad1SAndroid Build Coastguard Worker     sizeof(DTSFrameScanner::kSyncBytes),
63*b9df5ad1SAndroid Build Coastguard Worker     DTS_HEADER_BYTES_NEEDED)
64*b9df5ad1SAndroid Build Coastguard Worker  , mSampleFramesPerSyncFrame(0)
65*b9df5ad1SAndroid Build Coastguard Worker {
66*b9df5ad1SAndroid Build Coastguard Worker }
67*b9df5ad1SAndroid Build Coastguard Worker 
~DTSFrameScanner()68*b9df5ad1SAndroid Build Coastguard Worker DTSFrameScanner::~DTSFrameScanner()
69*b9df5ad1SAndroid Build Coastguard Worker {
70*b9df5ad1SAndroid Build Coastguard Worker }
71*b9df5ad1SAndroid Build Coastguard Worker 
72*b9df5ad1SAndroid Build Coastguard Worker // Parse DTS header.
73*b9df5ad1SAndroid Build Coastguard Worker // Detect whether the stream is DTS or DTS_HD. Extract data depending on type.
74*b9df5ad1SAndroid Build Coastguard Worker // Sets mDataType, mFrameSizeBytes,
75*b9df5ad1SAndroid Build Coastguard Worker //      mSampleRate, mRateMultiplier, mLengthCode.
76*b9df5ad1SAndroid Build Coastguard Worker //
77*b9df5ad1SAndroid Build Coastguard Worker // @return true if valid
parseHeader()78*b9df5ad1SAndroid Build Coastguard Worker bool DTSFrameScanner::parseHeader()
79*b9df5ad1SAndroid Build Coastguard Worker {
80*b9df5ad1SAndroid Build Coastguard Worker     BitFieldParser parser(&mHeaderBuffer[mSyncLength]);
81*b9df5ad1SAndroid Build Coastguard Worker 
82*b9df5ad1SAndroid Build Coastguard Worker     // These variables are named after the fields in the DTS spec 5.3.1
83*b9df5ad1SAndroid Build Coastguard Worker     // Extract field in order.
84*b9df5ad1SAndroid Build Coastguard Worker     (void) /* uint32_t ftype = */ parser.readBits(1);
85*b9df5ad1SAndroid Build Coastguard Worker     (void) /* uint32_t deficit = */ parser.readBits(5); // "short"
86*b9df5ad1SAndroid Build Coastguard Worker     uint32_t cpf = parser.readBits(1);
87*b9df5ad1SAndroid Build Coastguard Worker     uint32_t nblks = parser.readBits(7);
88*b9df5ad1SAndroid Build Coastguard Worker     uint32_t fsize = parser.readBits(14);
89*b9df5ad1SAndroid Build Coastguard Worker     (void) /* uint32_t amode = */ parser.readBits(6);
90*b9df5ad1SAndroid Build Coastguard Worker     uint32_t sfreq = parser.readBits(4);
91*b9df5ad1SAndroid Build Coastguard Worker     // make sure we did not read past collected data
92*b9df5ad1SAndroid Build Coastguard Worker     ALOG_ASSERT((mSyncLength + ((parser.getBitCursor() + 7) >> 3))
93*b9df5ad1SAndroid Build Coastguard Worker             <= mHeaderLength);
94*b9df5ad1SAndroid Build Coastguard Worker 
95*b9df5ad1SAndroid Build Coastguard Worker     // Validate fields.
96*b9df5ad1SAndroid Build Coastguard Worker     if (cpf != 0) {
97*b9df5ad1SAndroid Build Coastguard Worker         ALOGE("DTSFrameScanner: ERROR - CPF not zero!");
98*b9df5ad1SAndroid Build Coastguard Worker         return false;
99*b9df5ad1SAndroid Build Coastguard Worker     }
100*b9df5ad1SAndroid Build Coastguard Worker     if (nblks < DTS_MINIMUM_NBLKS) {
101*b9df5ad1SAndroid Build Coastguard Worker         ALOGE("DTSFrameScanner: ERROR - nblks = %u", nblks);
102*b9df5ad1SAndroid Build Coastguard Worker         return false;
103*b9df5ad1SAndroid Build Coastguard Worker     }
104*b9df5ad1SAndroid Build Coastguard Worker     if (fsize < DTS_MINIMUM_FSIZE) {
105*b9df5ad1SAndroid Build Coastguard Worker         ALOGE("DTSFrameScanner: ERROR - fsize = %u", fsize);
106*b9df5ad1SAndroid Build Coastguard Worker         return false;
107*b9df5ad1SAndroid Build Coastguard Worker     }
108*b9df5ad1SAndroid Build Coastguard Worker 
109*b9df5ad1SAndroid Build Coastguard Worker     int32_t sampleRate = kDTSSampleRateTable[sfreq];
110*b9df5ad1SAndroid Build Coastguard Worker     if (sampleRate < 0) {
111*b9df5ad1SAndroid Build Coastguard Worker         ALOGE("DTSFrameScanner: ERROR - invalid sampleRate[%u] = %d", sfreq, sampleRate);
112*b9df5ad1SAndroid Build Coastguard Worker         return false;
113*b9df5ad1SAndroid Build Coastguard Worker     }
114*b9df5ad1SAndroid Build Coastguard Worker     mSampleRate = (uint32_t) sampleRate;
115*b9df5ad1SAndroid Build Coastguard Worker 
116*b9df5ad1SAndroid Build Coastguard Worker     mSampleFramesPerSyncFrame = (nblks + 1) * DTS_PCM_FRAMES_PER_BLOCK;
117*b9df5ad1SAndroid Build Coastguard Worker     if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_I) {
118*b9df5ad1SAndroid Build Coastguard Worker         mDataType = IEC61937_DATA_TYPE_DTS_I;
119*b9df5ad1SAndroid Build Coastguard Worker     } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_II) {
120*b9df5ad1SAndroid Build Coastguard Worker         mDataType = IEC61937_DATA_TYPE_DTS_II;
121*b9df5ad1SAndroid Build Coastguard Worker     } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_III) {
122*b9df5ad1SAndroid Build Coastguard Worker         mDataType = IEC61937_DATA_TYPE_DTS_III;
123*b9df5ad1SAndroid Build Coastguard Worker     } else {
124*b9df5ad1SAndroid Build Coastguard Worker         mDataType = IEC61937_DATA_TYPE_DTS_IV;
125*b9df5ad1SAndroid Build Coastguard Worker         // TODO set bits 8,10
126*b9df5ad1SAndroid Build Coastguard Worker     }
127*b9df5ad1SAndroid Build Coastguard Worker 
128*b9df5ad1SAndroid Build Coastguard Worker     mFrameSizeBytes = fsize + 1;
129*b9df5ad1SAndroid Build Coastguard Worker 
130*b9df5ad1SAndroid Build Coastguard Worker     mRateMultiplier = 1; // TODO what about "frequency extension"?
131*b9df5ad1SAndroid Build Coastguard Worker     ALOGI_IF((mFormatDumpCount == 0),
132*b9df5ad1SAndroid Build Coastguard Worker             "DTS frame rate = %d * %d, size = %zu",
133*b9df5ad1SAndroid Build Coastguard Worker             mSampleRate, mRateMultiplier, mFrameSizeBytes);
134*b9df5ad1SAndroid Build Coastguard Worker     mFormatDumpCount++;
135*b9df5ad1SAndroid Build Coastguard Worker     return true;
136*b9df5ad1SAndroid Build Coastguard Worker }
137*b9df5ad1SAndroid Build Coastguard Worker 
138*b9df5ad1SAndroid Build Coastguard Worker 
139*b9df5ad1SAndroid Build Coastguard Worker }  // namespace android
140