SPDIF: add DTS support to SPDIF wrapper

Refactor AC3 out of FrameScanner.cpp.
Simplify scanning state machine and move up into FrameScanner.cpp.

Bug: 18292317
Change-Id: Iaefdce9c960abbea5dcdc2390a5da00181da0f8c
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/audio_utils/spdif/FrameScanner.cpp b/audio_utils/spdif/FrameScanner.cpp
index 72edd20..80c1d94 100644
--- a/audio_utils/spdif/FrameScanner.cpp
+++ b/audio_utils/spdif/FrameScanner.cpp
@@ -1,36 +1,40 @@
 /*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #define LOG_TAG "AudioSPDIF"
 
 #include <string.h>
+#include <assert.h>
 
 #include <utils/Log.h>
 #include <audio_utils/spdif/FrameScanner.h>
 
 namespace android {
 
-#define SPDIF_DATA_TYPE_AC3     1
-#define SPDIF_DATA_TYPE_E_AC3  21
-
-#define AC3_SYNCWORD_SIZE  2
-
-FrameScanner::FrameScanner(int dataType)
- : mSampleRate(0)
+FrameScanner::FrameScanner(int dataType,
+            const uint8_t *syncBytes,
+            uint32_t syncLength,
+            uint32_t headerLength)
+ : mBytesSkipped(0)
+ , mSyncBytes(syncBytes)
+ , mSyncLength(syncLength)
+ , mHeaderLength(headerLength)
+ , mCursor(0)
+ , mFormatDumpCount(0)
+ , mSampleRate(0)
  , mRateMultiplier(1)
  , mFrameSizeBytes(0)
  , mDataType(dataType)
@@ -42,256 +46,34 @@
 {
 }
 
-// ------------------- AC3 -----------------------------------------------------
-// These values are from the AC3 spec. Do not change them.
-const uint8_t AC3FrameScanner::kAC3SyncByte1 = 0x0B;
-const uint8_t AC3FrameScanner::kAC3SyncByte2 = 0x77;
-
-const uint16_t AC3FrameScanner::kAC3SampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
-    = { 48000, 44100, 32000 };
-
-// Table contains number of 16-bit words in an AC3 frame.
-const uint16_t AC3FrameScanner::kAC3FrameSizeTable[AC3_NUM_FRAME_SIZE_TABLE_ENTRIES]
-        [AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES] = {
-    { 64, 69, 96 },
-    { 64, 70, 96 },
-    { 80, 87, 120 },
-    { 80, 88, 120 },
-    { 96, 104, 144 },
-    { 96, 105, 144 },
-    { 112, 121, 168 },
-    { 112, 122, 168 },
-    { 128, 139, 192 },
-    { 128, 140, 192 },
-    { 160, 174, 240 },
-    { 160, 175, 240 },
-    { 192, 208, 288 },
-    { 192, 209, 288 },
-    { 224, 243, 336 },
-    { 224, 244, 336 },
-    { 256, 278, 384 },
-    { 256, 279, 384 },
-    { 320, 348, 480 },
-    { 320, 349, 480 },
-    { 384, 417, 576 },
-    { 384, 418, 576 },
-    { 448, 487, 672 },
-    { 448, 488, 672 },
-    { 512, 557, 768 },
-    { 512, 558, 768 },
-    { 640, 696, 960 },
-    { 640, 697, 960 },
-    { 768, 835, 1152 },
-    { 768, 836, 1152 },
-    { 896, 975, 1344 },
-    { 896, 976, 1344 },
-    { 1024, 1114, 1536 },
-    { 1024, 1115, 1536 },
-    { 1152, 1253, 1728 },
-    { 1152, 1254, 1728 },
-    { 1280, 1393, 1920 },
-    { 1280, 1394, 1920 }
-};
-
-const uint16_t AC3FrameScanner::kEAC3ReducedSampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES]
-        = { 24000, 22050, 16000 };
-
-const uint16_t
-        AC3FrameScanner::kEAC3BlocksPerFrameTable[EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES]
-        = { 1, 2, 3, 6 };
-// -----------------------------------------------------------------------------
-
-// Scanner for AC3 byte streams.
-AC3FrameScanner::AC3FrameScanner()
- : FrameScanner(SPDIF_DATA_TYPE_AC3)
- , mState(STATE_EXPECTING_SYNC_1)
- , mBytesSkipped(0)
- , mAudioBlocksPerSyncFrame(6)
- , mCursor(AC3_SYNCWORD_SIZE) // past sync word
- , mStreamType(0)
- , mSubstreamID(0)
- , mFormatDumpCount(0)
-{
-    memset(mSubstreamBlockCounts, 0, sizeof(mSubstreamBlockCounts));
-    // Define beginning of syncinfo for getSyncAddress()
-    mHeaderBuffer[0] = kAC3SyncByte1;
-    mHeaderBuffer[1] = kAC3SyncByte2;
-}
-
-AC3FrameScanner::~AC3FrameScanner()
-{
-}
-
-int AC3FrameScanner::getSampleFramesPerSyncFrame() const
-{
-    return mRateMultiplier * AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * AC3_PCM_FRAMES_PER_BLOCK;
-}
-
-void AC3FrameScanner::resetBurst()
-{
-    for (int i = 0; i < EAC3_MAX_SUBSTREAMS; i++) {
-        if (mSubstreamBlockCounts[i] >= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK) {
-            mSubstreamBlockCounts[i] -= AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK;
-        } else if (mSubstreamBlockCounts[i] > 0) {
-            ALOGW("EAC3 substream[%d] has only %d audio blocks!",
-                i, mSubstreamBlockCounts[i]);
-            mSubstreamBlockCounts[i] = 0;
-        }
-    }
-}
-
-// per IEC 61973-3 Paragraph 5.3.3
-// We have to send 6 audio blocks on all active substreams.
-// Substream zero must be the first.
-// We don't know if we have all the blocks we need until we see
-// the 7th block of substream#0.
-bool AC3FrameScanner::isFirstInBurst()
-{
-    if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
-        if (((mStreamType == 0) || (mStreamType == 2))
-            && (mSubstreamID == 0)
-            // The ">" is intentional. We have to see the beginning of the block
-            // in the next burst before we can send the current burst.
-            && (mSubstreamBlockCounts[0] > AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AC3FrameScanner::isLastInBurst()
-{
-    // For EAC3 we don't know if we are the end until we see a
-    // frame that must be at the beginning. See isFirstInBurst().
-    return (mDataType != SPDIF_DATA_TYPE_E_AC3); // Just one AC3 frame per burst.
-}
-
-// Parse AC3 header.
-// Detect whether the stream is AC3 or EAC3. Extract data depending on type.
-// Sets mDataType, mFrameSizeBytes, mAudioBlocksPerSyncFrame,
-//      mSampleRate, mRateMultiplier, mLengthCode.
-//
-// @return next state for scanner
-AC3FrameScanner::State AC3FrameScanner::parseHeader()
-{
-    // Interpret bsid based on paragraph E2.3.1.6 of EAC3 spec.
-    int bsid = mHeaderBuffer[5] >> 3; // bitstream ID
-    // Check BSID to see if this is EAC3 or regular AC3
-    if ((bsid >= 10) && (bsid <= 16)) {
-        mDataType = SPDIF_DATA_TYPE_E_AC3;
-    } else if ((bsid >= 0) && (bsid <= 8)) {
-        mDataType = SPDIF_DATA_TYPE_AC3;
-    } else {
-        ALOGW("AC3 bsid = %d not supported", bsid);
-        return STATE_EXPECTING_SYNC_1;
-    }
-
-    // The names fscod, frmsiz are from the AC3 spec.
-    int fscod = mHeaderBuffer[4] >> 6;
-    if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
-        mStreamType = mHeaderBuffer[2] >> 6; // strmtyp in spec
-        mSubstreamID = (mHeaderBuffer[2] >> 3) & 0x07;
-
-        // Frame size is explicit in EAC3. Paragraph E2.3.1.3
-        int frmsiz = ((mHeaderBuffer[2] & 0x07) << 8) + mHeaderBuffer[3];
-        mFrameSizeBytes = (frmsiz + 1) * sizeof(int16_t);
-
-        int numblkscod = 3; // 6 blocks default
-        if (fscod == 3) {
-            int fscod2 = (mHeaderBuffer[4] >> 4) & 0x03;
-            if (fscod2 >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
-                ALOGW("Invalid EAC3 fscod2 = %d\n", fscod2);
-                return STATE_EXPECTING_SYNC_1;
-            } else {
-                mSampleRate = kEAC3ReducedSampleRateTable[fscod2];
-            }
-        } else {
-            mSampleRate = kAC3SampleRateTable[fscod];
-            numblkscod = (mHeaderBuffer[4] >> 4) & 0x03;
-        }
-        mRateMultiplier = EAC3_RATE_MULTIPLIER; // per IEC 61973-3 Paragraph 5.3.3
-        // Don't send data burst until we have 6 blocks per substream.
-        mAudioBlocksPerSyncFrame = kEAC3BlocksPerFrameTable[numblkscod];
-        // Keep track of how many audio blocks we have for each substream.
-        // This should be safe because mSubstreamID is ANDed with 0x07 above.
-        // And the array is allocated as [8].
-        mSubstreamBlockCounts[mSubstreamID] += mAudioBlocksPerSyncFrame;
-
-        // Print enough so we can see all the substreams.
-        ALOGD_IF((mFormatDumpCount < 3*8 ),
-                "EAC3 mStreamType = %d, mSubstreamID = %d",
-                mStreamType, mSubstreamID);
-    } else { // regular AC3
-        // Extract sample rate and frame size from codes.
-        unsigned int frmsizcod = mHeaderBuffer[4] & 0x3F; // frame size code
-
-        if (fscod >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
-            ALOGW("Invalid AC3 sampleRateCode = %d\n", fscod);
-            return STATE_EXPECTING_SYNC_1;
-        } else if (frmsizcod >= AC3_NUM_FRAME_SIZE_TABLE_ENTRIES) {
-            ALOGW("Invalid AC3 frameSizeCode = %d\n", frmsizcod);
-            return STATE_EXPECTING_SYNC_1;
-        } else {
-            mSampleRate = kAC3SampleRateTable[fscod];
-            mRateMultiplier = 1;
-            mFrameSizeBytes = sizeof(uint16_t)
-                    * kAC3FrameSizeTable[frmsizcod][fscod];
-        }
-        mAudioBlocksPerSyncFrame = 6;
-    }
-    ALOGI_IF((mFormatDumpCount == 0),
-            "AC3 frame rate = %d * %d, size = %d, audioBlocksPerSyncFrame = %d\n",
-            mSampleRate, mRateMultiplier, mFrameSizeBytes, mAudioBlocksPerSyncFrame);
-    mFormatDumpCount++;
-    return STATE_GOT_HEADER;
-}
-
-// State machine that scans for AC3 headers in a byte stream.
+// State machine that scans for headers in a byte stream.
 // @return true if we have detected a complete and valid header.
-bool AC3FrameScanner::scan(uint8_t byte)
+bool FrameScanner::scan(uint8_t byte)
 {
-    State nextState = mState;
-    switch (mState) {
-    case STATE_GOT_HEADER:
-        nextState = STATE_EXPECTING_SYNC_1;
-        // deliberately fall through
-    case STATE_EXPECTING_SYNC_1:
-        if (byte == kAC3SyncByte1) {
-            nextState = STATE_EXPECTING_SYNC_2; // advance
+    bool result = false;
+    ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d\n", byte, mCursor);
+    assert(mCursor < sizeof(mHeaderBuffer));
+    if (mCursor < mSyncLength) {
+        // match sync word
+        if (byte == mSyncBytes[mCursor]) {
+            mHeaderBuffer[mCursor++] = byte;
         } else {
             mBytesSkipped += 1; // skip unsynchronized data
+            mCursor = 0;
         }
-        break;
-
-    case STATE_EXPECTING_SYNC_2:
-        if (byte == kAC3SyncByte2) {
-            if (mBytesSkipped > 0) {
-                ALOGI("WARNING AC3 skipped %u bytes looking for a valid header.\n", mBytesSkipped);
-                mBytesSkipped = 0;
+    } else if (mCursor < mHeaderLength) {
+        // gather header for parsing
+        mHeaderBuffer[mCursor++] = byte;
+        if (mCursor >= mHeaderLength) {
+            if (parseHeader()) {
+                result = true;
+            } else {
+                ALOGE("FrameScanner: ERROR - parseHeader() failed.");
             }
-            mCursor = AC3_SYNCWORD_SIZE;
-            nextState = STATE_GATHERING; // advance
-        } else if (byte == kAC3SyncByte1) {
-            nextState = STATE_EXPECTING_SYNC_2; // resync
-        } else {
-            nextState = STATE_EXPECTING_SYNC_1; // restart
+            mCursor = 0;
         }
-        break;
-
-    case STATE_GATHERING:
-        mHeaderBuffer[mCursor++] = byte; // save for getSyncAddress()
-        if (mCursor >= sizeof(mHeaderBuffer)) {
-            nextState = parseHeader();
-        }
-        break;
-
-    default:
-        ALOGE("AC3FrameScanner: invalid state = %d\n", mState);
-        nextState = STATE_EXPECTING_SYNC_1; // restart
-        break;
     }
-    mState = nextState;
-    return mState == STATE_GOT_HEADER;
+    return result;
 }
 
 }  // namespace android