xref: /aosp_15_r20/system/media/audio_utils/spdif/AC3FrameScanner.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker  * Copyright 2014, 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 
19*b9df5ad1SAndroid Build Coastguard Worker #include <string.h>
20*b9df5ad1SAndroid Build Coastguard Worker 
21*b9df5ad1SAndroid Build Coastguard Worker #include <log/log.h>
22*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/spdif/FrameScanner.h>
23*b9df5ad1SAndroid Build Coastguard Worker 
24*b9df5ad1SAndroid Build Coastguard Worker #include "AC3FrameScanner.h"
25*b9df5ad1SAndroid Build Coastguard Worker 
26*b9df5ad1SAndroid Build Coastguard Worker namespace android {
27*b9df5ad1SAndroid Build Coastguard Worker 
28*b9df5ad1SAndroid Build Coastguard Worker // These values are from the AC3 spec. Do not change them.
29*b9df5ad1SAndroid Build Coastguard Worker 
30*b9df5ad1SAndroid Build Coastguard Worker const uint8_t AC3FrameScanner::kSyncBytes[] = { 0x0B, 0x77 };
31*b9df5ad1SAndroid Build Coastguard Worker 
32*b9df5ad1SAndroid Build Coastguard Worker const uint16_t AC3FrameScanner::kAC3SampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
33*b9df5ad1SAndroid Build Coastguard Worker     = { 48000, 44100, 32000 };
34*b9df5ad1SAndroid Build Coastguard Worker 
35*b9df5ad1SAndroid Build Coastguard Worker // Table contains number of 16-bit words in an AC3 frame.
36*b9df5ad1SAndroid Build Coastguard Worker // From AC3 spec table 5.13
37*b9df5ad1SAndroid Build Coastguard Worker const uint16_t AC3FrameScanner::kAC3FrameSizeTable[AC3_NUM_FRAME_SIZE_TABLE_ENTRIES]
38*b9df5ad1SAndroid Build Coastguard Worker         [AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES] = {
39*b9df5ad1SAndroid Build Coastguard Worker     { 64, 69, 96 },
40*b9df5ad1SAndroid Build Coastguard Worker     { 64, 70, 96 },
41*b9df5ad1SAndroid Build Coastguard Worker     { 80, 87, 120 },
42*b9df5ad1SAndroid Build Coastguard Worker     { 80, 88, 120 },
43*b9df5ad1SAndroid Build Coastguard Worker     { 96, 104, 144 },
44*b9df5ad1SAndroid Build Coastguard Worker     { 96, 105, 144 },
45*b9df5ad1SAndroid Build Coastguard Worker     { 112, 121, 168 },
46*b9df5ad1SAndroid Build Coastguard Worker     { 112, 122, 168 },
47*b9df5ad1SAndroid Build Coastguard Worker     { 128, 139, 192 },
48*b9df5ad1SAndroid Build Coastguard Worker     { 128, 140, 192 },
49*b9df5ad1SAndroid Build Coastguard Worker     { 160, 174, 240 },
50*b9df5ad1SAndroid Build Coastguard Worker     { 160, 175, 240 },
51*b9df5ad1SAndroid Build Coastguard Worker     { 192, 208, 288 },
52*b9df5ad1SAndroid Build Coastguard Worker     { 192, 209, 288 },
53*b9df5ad1SAndroid Build Coastguard Worker     { 224, 243, 336 },
54*b9df5ad1SAndroid Build Coastguard Worker     { 224, 244, 336 },
55*b9df5ad1SAndroid Build Coastguard Worker     { 256, 278, 384 },
56*b9df5ad1SAndroid Build Coastguard Worker     { 256, 279, 384 },
57*b9df5ad1SAndroid Build Coastguard Worker     { 320, 348, 480 },
58*b9df5ad1SAndroid Build Coastguard Worker     { 320, 349, 480 },
59*b9df5ad1SAndroid Build Coastguard Worker     { 384, 417, 576 },
60*b9df5ad1SAndroid Build Coastguard Worker     { 384, 418, 576 },
61*b9df5ad1SAndroid Build Coastguard Worker     { 448, 487, 672 },
62*b9df5ad1SAndroid Build Coastguard Worker     { 448, 488, 672 },
63*b9df5ad1SAndroid Build Coastguard Worker     { 512, 557, 768 },
64*b9df5ad1SAndroid Build Coastguard Worker     { 512, 558, 768 },
65*b9df5ad1SAndroid Build Coastguard Worker     { 640, 696, 960 },
66*b9df5ad1SAndroid Build Coastguard Worker     { 640, 697, 960 },
67*b9df5ad1SAndroid Build Coastguard Worker     { 768, 835, 1152 },
68*b9df5ad1SAndroid Build Coastguard Worker     { 768, 836, 1152 },
69*b9df5ad1SAndroid Build Coastguard Worker     { 896, 975, 1344 },
70*b9df5ad1SAndroid Build Coastguard Worker     { 896, 976, 1344 },
71*b9df5ad1SAndroid Build Coastguard Worker     { 1024, 1114, 1536 },
72*b9df5ad1SAndroid Build Coastguard Worker     { 1024, 1115, 1536 },
73*b9df5ad1SAndroid Build Coastguard Worker     { 1152, 1253, 1728 },
74*b9df5ad1SAndroid Build Coastguard Worker     { 1152, 1254, 1728 },
75*b9df5ad1SAndroid Build Coastguard Worker     { 1280, 1393, 1920 },
76*b9df5ad1SAndroid Build Coastguard Worker     { 1280, 1394, 1920 }
77*b9df5ad1SAndroid Build Coastguard Worker };
78*b9df5ad1SAndroid Build Coastguard Worker 
79*b9df5ad1SAndroid Build Coastguard Worker const uint16_t AC3FrameScanner::kEAC3ReducedSampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
80*b9df5ad1SAndroid Build Coastguard Worker         = { 24000, 22050, 16000 };
81*b9df5ad1SAndroid Build Coastguard Worker 
82*b9df5ad1SAndroid Build Coastguard Worker const uint16_t
83*b9df5ad1SAndroid Build Coastguard Worker         AC3FrameScanner::kEAC3BlocksPerFrameTable[EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES]
84*b9df5ad1SAndroid Build Coastguard Worker         = { 1, 2, 3, 6 };
85*b9df5ad1SAndroid Build Coastguard Worker 
86*b9df5ad1SAndroid Build Coastguard Worker // Defined in IEC61937-2
87*b9df5ad1SAndroid Build Coastguard Worker #define AC3_STREAM_TYPE_0       0
88*b9df5ad1SAndroid Build Coastguard Worker #define AC3_STREAM_TYPE_1       1
89*b9df5ad1SAndroid Build Coastguard Worker #define AC3_STREAM_TYPE_2       2
90*b9df5ad1SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
91*b9df5ad1SAndroid Build Coastguard Worker 
92*b9df5ad1SAndroid Build Coastguard Worker // Scanner for AC3 byte streams.
AC3FrameScanner(audio_format_t format)93*b9df5ad1SAndroid Build Coastguard Worker AC3FrameScanner::AC3FrameScanner(audio_format_t format)
94*b9df5ad1SAndroid Build Coastguard Worker  : FrameScanner(kSpdifDataTypeAc3,
95*b9df5ad1SAndroid Build Coastguard Worker         AC3FrameScanner::kSyncBytes,
96*b9df5ad1SAndroid Build Coastguard Worker         sizeof(AC3FrameScanner::kSyncBytes), 6)
97*b9df5ad1SAndroid Build Coastguard Worker  , mStreamType(0)
98*b9df5ad1SAndroid Build Coastguard Worker  , mSubstreamID(0)
99*b9df5ad1SAndroid Build Coastguard Worker  , mFormat(format)
100*b9df5ad1SAndroid Build Coastguard Worker {
101*b9df5ad1SAndroid Build Coastguard Worker     mAudioBlocksPerSyncFrame = 6;
102*b9df5ad1SAndroid Build Coastguard Worker     memset(mSubstreamBlockCounts, 0, sizeof(mSubstreamBlockCounts));
103*b9df5ad1SAndroid Build Coastguard Worker }
104*b9df5ad1SAndroid Build Coastguard Worker 
~AC3FrameScanner()105*b9df5ad1SAndroid Build Coastguard Worker AC3FrameScanner::~AC3FrameScanner()
106*b9df5ad1SAndroid Build Coastguard Worker {
107*b9df5ad1SAndroid Build Coastguard Worker }
108*b9df5ad1SAndroid Build Coastguard Worker 
getSampleFramesPerSyncFrame() const109*b9df5ad1SAndroid Build Coastguard Worker int AC3FrameScanner::getSampleFramesPerSyncFrame() const
110*b9df5ad1SAndroid Build Coastguard Worker {
111*b9df5ad1SAndroid Build Coastguard Worker     return mRateMultiplier
112*b9df5ad1SAndroid Build Coastguard Worker             * AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * AC3_PCM_FRAMES_PER_BLOCK;
113*b9df5ad1SAndroid Build Coastguard Worker }
114*b9df5ad1SAndroid Build Coastguard Worker 
resetBurst()115*b9df5ad1SAndroid Build Coastguard Worker void AC3FrameScanner::resetBurst()
116*b9df5ad1SAndroid Build Coastguard Worker {
117*b9df5ad1SAndroid Build Coastguard Worker     for (int i = 0; i < EAC3_MAX_SUBSTREAMS; i++) {
118*b9df5ad1SAndroid Build Coastguard Worker         if (mSubstreamBlockCounts[i] >= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK) {
119*b9df5ad1SAndroid Build Coastguard Worker             mSubstreamBlockCounts[i] -= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK;
120*b9df5ad1SAndroid Build Coastguard Worker         } else if (mSubstreamBlockCounts[i] > 0) {
121*b9df5ad1SAndroid Build Coastguard Worker             ALOGW("EAC3 substream[%d] has only %d audio blocks!",
122*b9df5ad1SAndroid Build Coastguard Worker                 i, mSubstreamBlockCounts[i]);
123*b9df5ad1SAndroid Build Coastguard Worker             mSubstreamBlockCounts[i] = 0;
124*b9df5ad1SAndroid Build Coastguard Worker         }
125*b9df5ad1SAndroid Build Coastguard Worker     }
126*b9df5ad1SAndroid Build Coastguard Worker }
127*b9df5ad1SAndroid Build Coastguard Worker 
128*b9df5ad1SAndroid Build Coastguard Worker // Per IEC 61973-3:5.3.3, for E-AC3 burst-length shall be in bytes.
convertBytesToLengthCode(uint16_t numBytes) const129*b9df5ad1SAndroid Build Coastguard Worker uint16_t AC3FrameScanner::convertBytesToLengthCode(uint16_t numBytes) const
130*b9df5ad1SAndroid Build Coastguard Worker {
131*b9df5ad1SAndroid Build Coastguard Worker     return (mDataType == kSpdifDataTypeEac3) ? numBytes : numBytes * 8;
132*b9df5ad1SAndroid Build Coastguard Worker }
133*b9df5ad1SAndroid Build Coastguard Worker 
134*b9df5ad1SAndroid Build Coastguard Worker // per IEC 61973-3 Paragraph 5.3.3
135*b9df5ad1SAndroid Build Coastguard Worker // We have to send 6 audio blocks on all active substreams.
136*b9df5ad1SAndroid Build Coastguard Worker // Substream zero must be the first.
137*b9df5ad1SAndroid Build Coastguard Worker // We don't know if we have all the blocks we need until we see
138*b9df5ad1SAndroid Build Coastguard Worker // the 7th block of substream#0.
isFirstInBurst()139*b9df5ad1SAndroid Build Coastguard Worker bool AC3FrameScanner::isFirstInBurst()
140*b9df5ad1SAndroid Build Coastguard Worker {
141*b9df5ad1SAndroid Build Coastguard Worker     if (mDataType == kSpdifDataTypeEac3) {
142*b9df5ad1SAndroid Build Coastguard Worker         if (((mStreamType == AC3_STREAM_TYPE_0)
143*b9df5ad1SAndroid Build Coastguard Worker                 || (mStreamType == AC3_STREAM_TYPE_2))
144*b9df5ad1SAndroid Build Coastguard Worker                 && (mSubstreamID == 0)
145*b9df5ad1SAndroid Build Coastguard Worker                 // The ">" is intentional. We have to see the beginning
146*b9df5ad1SAndroid Build Coastguard Worker                 // of the block in the next burst before we can send
147*b9df5ad1SAndroid Build Coastguard Worker                 // the current burst.
148*b9df5ad1SAndroid Build Coastguard Worker                 && (mSubstreamBlockCounts[0] > AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK)) {
149*b9df5ad1SAndroid Build Coastguard Worker             return true;
150*b9df5ad1SAndroid Build Coastguard Worker         }
151*b9df5ad1SAndroid Build Coastguard Worker     }
152*b9df5ad1SAndroid Build Coastguard Worker     return false;
153*b9df5ad1SAndroid Build Coastguard Worker }
154*b9df5ad1SAndroid Build Coastguard Worker 
isLastInBurst()155*b9df5ad1SAndroid Build Coastguard Worker bool AC3FrameScanner::isLastInBurst()
156*b9df5ad1SAndroid Build Coastguard Worker {
157*b9df5ad1SAndroid Build Coastguard Worker     // For EAC3 we don't know if we are the end until we see a
158*b9df5ad1SAndroid Build Coastguard Worker     // frame that must be at the beginning. See isFirstInBurst().
159*b9df5ad1SAndroid Build Coastguard Worker     return (mDataType != kSpdifDataTypeEac3); // Just one AC3 frame per burst.
160*b9df5ad1SAndroid Build Coastguard Worker }
161*b9df5ad1SAndroid Build Coastguard Worker 
162*b9df5ad1SAndroid Build Coastguard Worker // TODO Use BitFieldParser
163*b9df5ad1SAndroid Build Coastguard Worker 
164*b9df5ad1SAndroid Build Coastguard Worker // Parse AC3 header.
165*b9df5ad1SAndroid Build Coastguard Worker // Detect whether the stream is AC3 or EAC3. Extract data depending on type.
166*b9df5ad1SAndroid Build Coastguard Worker //
167*b9df5ad1SAndroid Build Coastguard Worker // @return true if valid
parseHeader()168*b9df5ad1SAndroid Build Coastguard Worker bool AC3FrameScanner::parseHeader()
169*b9df5ad1SAndroid Build Coastguard Worker {
170*b9df5ad1SAndroid Build Coastguard Worker     // Interpret bsid based on paragraph E2.3.1.6 of EAC3 spec.
171*b9df5ad1SAndroid Build Coastguard Worker     uint32_t bsid = mHeaderBuffer[5] >> 3; // bitstream ID
172*b9df5ad1SAndroid Build Coastguard Worker     // Check BSID to see if this is EAC3 or regular AC3.
173*b9df5ad1SAndroid Build Coastguard Worker     // These arbitrary BSID numbers do not have any names in the spec.
174*b9df5ad1SAndroid Build Coastguard Worker     if ((bsid > 10) && (bsid <= 16)) {
175*b9df5ad1SAndroid Build Coastguard Worker         mDataType = kSpdifDataTypeEac3;
176*b9df5ad1SAndroid Build Coastguard Worker     } else if (bsid <= 8) {
177*b9df5ad1SAndroid Build Coastguard Worker         mDataType = kSpdifDataTypeAc3;
178*b9df5ad1SAndroid Build Coastguard Worker     } else {
179*b9df5ad1SAndroid Build Coastguard Worker         ALOGW("AC3 bsid = %d not supported", bsid);
180*b9df5ad1SAndroid Build Coastguard Worker         return false;
181*b9df5ad1SAndroid Build Coastguard Worker     }
182*b9df5ad1SAndroid Build Coastguard Worker 
183*b9df5ad1SAndroid Build Coastguard Worker     // bitstream mode, main, commentary, etc.
184*b9df5ad1SAndroid Build Coastguard Worker     uint32_t bsmod = mHeaderBuffer[5] & 7;
185*b9df5ad1SAndroid Build Coastguard Worker 
186*b9df5ad1SAndroid Build Coastguard Worker     mDataTypeInfo = 0;
187*b9df5ad1SAndroid Build Coastguard Worker 
188*b9df5ad1SAndroid Build Coastguard Worker     // The names fscod, frmsiz are from the AC3 spec.
189*b9df5ad1SAndroid Build Coastguard Worker     uint32_t fscod = mHeaderBuffer[4] >> 6;
190*b9df5ad1SAndroid Build Coastguard Worker     if (mDataType == kSpdifDataTypeEac3) {
191*b9df5ad1SAndroid Build Coastguard Worker         mStreamType = mHeaderBuffer[2] >> 6; // strmtyp in spec
192*b9df5ad1SAndroid Build Coastguard Worker         mSubstreamID = (mHeaderBuffer[2] >> 3) & 0x07;
193*b9df5ad1SAndroid Build Coastguard Worker         // For EAC3 stream, only set data-type-dependent information as the value of
194*b9df5ad1SAndroid Build Coastguard Worker         // bsmod in independent substream 0 of EAC3 elementary stream.
195*b9df5ad1SAndroid Build Coastguard Worker         if (mStreamType != 1 && mSubstreamID == 0) {
196*b9df5ad1SAndroid Build Coastguard Worker             const int infomdate = (mHeaderBuffer[5] >> 3) & 1;
197*b9df5ad1SAndroid Build Coastguard Worker             if (infomdate == 1) {
198*b9df5ad1SAndroid Build Coastguard Worker                 mDataTypeInfo = bsmod;
199*b9df5ad1SAndroid Build Coastguard Worker             }
200*b9df5ad1SAndroid Build Coastguard Worker         }
201*b9df5ad1SAndroid Build Coastguard Worker 
202*b9df5ad1SAndroid Build Coastguard Worker 
203*b9df5ad1SAndroid Build Coastguard Worker         // Frame size is explicit in EAC3. Paragraph E2.3.1.3
204*b9df5ad1SAndroid Build Coastguard Worker         uint32_t frmsiz = ((mHeaderBuffer[2] & 0x07) << 8) + mHeaderBuffer[3];
205*b9df5ad1SAndroid Build Coastguard Worker         uint32_t frameSizeBytes = (frmsiz + 1) * sizeof(int16_t);
206*b9df5ad1SAndroid Build Coastguard Worker         if (frameSizeBytes < mHeaderLength) {
207*b9df5ad1SAndroid Build Coastguard Worker             ALOGW("AC3 frame size = %d, less than header size = %d", frameSizeBytes, mHeaderLength);
208*b9df5ad1SAndroid Build Coastguard Worker             android_errorWriteLog(0x534e4554, "145262423");
209*b9df5ad1SAndroid Build Coastguard Worker             return false;
210*b9df5ad1SAndroid Build Coastguard Worker         }
211*b9df5ad1SAndroid Build Coastguard Worker         mFrameSizeBytes = frameSizeBytes;
212*b9df5ad1SAndroid Build Coastguard Worker 
213*b9df5ad1SAndroid Build Coastguard Worker         uint32_t numblkscod = 3; // 6 blocks default
214*b9df5ad1SAndroid Build Coastguard Worker         if (fscod == 3) {
215*b9df5ad1SAndroid Build Coastguard Worker             uint32_t fscod2 = (mHeaderBuffer[4] >> 4) & 0x03;
216*b9df5ad1SAndroid Build Coastguard Worker             if (fscod2 >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
217*b9df5ad1SAndroid Build Coastguard Worker                 ALOGW("Invalid EAC3 fscod2 = %d", fscod2);
218*b9df5ad1SAndroid Build Coastguard Worker                 return false;
219*b9df5ad1SAndroid Build Coastguard Worker             } else {
220*b9df5ad1SAndroid Build Coastguard Worker                 mSampleRate = kEAC3ReducedSampleRateTable[fscod2];
221*b9df5ad1SAndroid Build Coastguard Worker             }
222*b9df5ad1SAndroid Build Coastguard Worker         } else {
223*b9df5ad1SAndroid Build Coastguard Worker             mSampleRate = kAC3SampleRateTable[fscod];
224*b9df5ad1SAndroid Build Coastguard Worker             numblkscod = (mHeaderBuffer[4] >> 4) & 0x03;
225*b9df5ad1SAndroid Build Coastguard Worker         }
226*b9df5ad1SAndroid Build Coastguard Worker         mRateMultiplier = kSpdifRateMultiplierEac3;  // per IEC 61973-3 Paragraph 5.3.3
227*b9df5ad1SAndroid Build Coastguard Worker         // Don't send data burst until we have 6 blocks per substream.
228*b9df5ad1SAndroid Build Coastguard Worker         mAudioBlocksPerSyncFrame = kEAC3BlocksPerFrameTable[numblkscod];
229*b9df5ad1SAndroid Build Coastguard Worker         // Keep track of how many audio blocks we have for each substream.
230*b9df5ad1SAndroid Build Coastguard Worker         // This should be safe because mSubstreamID is ANDed with 0x07 above.
231*b9df5ad1SAndroid Build Coastguard Worker         // And the array is allocated as [8].
232*b9df5ad1SAndroid Build Coastguard Worker         if ((mStreamType == AC3_STREAM_TYPE_0)
233*b9df5ad1SAndroid Build Coastguard Worker                 || (mStreamType == AC3_STREAM_TYPE_2)) {
234*b9df5ad1SAndroid Build Coastguard Worker             mSubstreamBlockCounts[mSubstreamID] += mAudioBlocksPerSyncFrame;
235*b9df5ad1SAndroid Build Coastguard Worker         }
236*b9df5ad1SAndroid Build Coastguard Worker 
237*b9df5ad1SAndroid Build Coastguard Worker         // Print enough so we can see all the substreams.
238*b9df5ad1SAndroid Build Coastguard Worker         ALOGD_IF((mFormatDumpCount < 3*8 ),
239*b9df5ad1SAndroid Build Coastguard Worker                 "EAC3 mStreamType = %d, mSubstreamID = %d",
240*b9df5ad1SAndroid Build Coastguard Worker                 mStreamType, mSubstreamID);
241*b9df5ad1SAndroid Build Coastguard Worker     } else { // regular AC3
242*b9df5ad1SAndroid Build Coastguard Worker         mDataTypeInfo = bsmod; // as per IEC61937-3, table 3.
243*b9df5ad1SAndroid Build Coastguard Worker         // Extract sample rate and frame size from codes.
244*b9df5ad1SAndroid Build Coastguard Worker         uint32_t frmsizcod = mHeaderBuffer[4] & 0x3F; // frame size code
245*b9df5ad1SAndroid Build Coastguard Worker 
246*b9df5ad1SAndroid Build Coastguard Worker         if (fscod >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
247*b9df5ad1SAndroid Build Coastguard Worker             ALOGW("Invalid AC3 sampleRateCode = %d", fscod);
248*b9df5ad1SAndroid Build Coastguard Worker             return false;
249*b9df5ad1SAndroid Build Coastguard Worker         } else if (frmsizcod >= AC3_NUM_FRAME_SIZE_TABLE_ENTRIES) {
250*b9df5ad1SAndroid Build Coastguard Worker             ALOGW("Invalid AC3 frameSizeCode = %d", frmsizcod);
251*b9df5ad1SAndroid Build Coastguard Worker             return false;
252*b9df5ad1SAndroid Build Coastguard Worker         } else {
253*b9df5ad1SAndroid Build Coastguard Worker             mSampleRate = kAC3SampleRateTable[fscod];
254*b9df5ad1SAndroid Build Coastguard Worker             mRateMultiplier = 1;
255*b9df5ad1SAndroid Build Coastguard Worker             mFrameSizeBytes = sizeof(uint16_t)
256*b9df5ad1SAndroid Build Coastguard Worker                     * kAC3FrameSizeTable[frmsizcod][fscod];
257*b9df5ad1SAndroid Build Coastguard Worker         }
258*b9df5ad1SAndroid Build Coastguard Worker         mAudioBlocksPerSyncFrame = 6;
259*b9df5ad1SAndroid Build Coastguard Worker         if (mFormat == AUDIO_FORMAT_E_AC3 || mFormat == AUDIO_FORMAT_E_AC3_JOC) {
260*b9df5ad1SAndroid Build Coastguard Worker             ALOGV("Its a Ac3 substream in EAC3 stream");
261*b9df5ad1SAndroid Build Coastguard Worker             mStreamType = 2;
262*b9df5ad1SAndroid Build Coastguard Worker             mSubstreamID = 0;
263*b9df5ad1SAndroid Build Coastguard Worker             mSubstreamBlockCounts[0] += mAudioBlocksPerSyncFrame;
264*b9df5ad1SAndroid Build Coastguard Worker             mDataType = kSpdifDataTypeEac3;
265*b9df5ad1SAndroid Build Coastguard Worker             mRateMultiplier = kSpdifRateMultiplierEac3;
266*b9df5ad1SAndroid Build Coastguard Worker         }
267*b9df5ad1SAndroid Build Coastguard Worker     }
268*b9df5ad1SAndroid Build Coastguard Worker     ALOGI_IF((mFormatDumpCount == 0),
269*b9df5ad1SAndroid Build Coastguard Worker             "AC3 frame rate = %d * %d, size = %zu, audioBlocksPerSyncFrame = %d",
270*b9df5ad1SAndroid Build Coastguard Worker             mSampleRate, mRateMultiplier, mFrameSizeBytes, mAudioBlocksPerSyncFrame);
271*b9df5ad1SAndroid Build Coastguard Worker     mFormatDumpCount++;
272*b9df5ad1SAndroid Build Coastguard Worker     return true;
273*b9df5ad1SAndroid Build Coastguard Worker }
274*b9df5ad1SAndroid Build Coastguard Worker 
275*b9df5ad1SAndroid Build Coastguard Worker }  // namespace android
276