| /* |
| * Copyright 2015, 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" |
| //#define LOG_NDEBUG 0 |
| |
| #include <assert.h> |
| #include <string.h> |
| |
| #include <utils/Log.h> |
| #include <audio_utils/spdif/FrameScanner.h> |
| |
| #include "BitFieldParser.h" |
| #include "DTSFrameScanner.h" |
| |
| namespace android { |
| |
| // TODO Handle termination frames. |
| // TODO assert if parse past end of header buffer |
| // TODO Handle DTS_HD |
| |
| const uint8_t DTSFrameScanner::kSyncBytes[] = |
| { 0x7F, 0xFE, 0x80, 0x01 }; |
| |
| const int32_t DTSFrameScanner::kDTSSampleRateTable[DTS_NUM_SAMPLE_RATE_TABLE_ENTRIES] |
| = { -1, 8000, 16000, 32000, -1, -1, |
| 11025, 22050, 44100, -1, -1, 12000, 24000, 48000, -1, -1 }; |
| |
| // Defined in IEC61937-2 |
| #define IEC61937_DATA_TYPE_DTS_I 11 |
| #define IEC61937_DATA_TYPE_DTS_II 12 |
| #define IEC61937_DATA_TYPE_DTS_III 13 |
| #define IEC61937_DATA_TYPE_DTS_IV 17 |
| |
| #define IEC61937_MAX_SAMPLES_TYPE_I 512 |
| #define IEC61937_MAX_SAMPLES_TYPE_II 1024 |
| #define IEC61937_MAX_SAMPLES_TYPE_III 2048 |
| |
| // Limits defined in DTS spec paragraph 5.3.1 |
| #define DTS_MINIMUM_NBLKS 5 |
| #define DTS_MINIMUM_FSIZE 95 |
| |
| #define DTS_HEADER_BYTES_NEEDED 12 |
| |
| // Scanner for DTS byte streams. |
| DTSFrameScanner::DTSFrameScanner() |
| : FrameScanner(IEC61937_DATA_TYPE_DTS_I, |
| DTSFrameScanner::kSyncBytes, |
| sizeof(DTSFrameScanner::kSyncBytes), |
| DTS_HEADER_BYTES_NEEDED) |
| , mSampleFramesPerSyncFrame(0) |
| { |
| } |
| |
| DTSFrameScanner::~DTSFrameScanner() |
| { |
| } |
| |
| // Parse DTS header. |
| // Detect whether the stream is DTS or DTS_HD. Extract data depending on type. |
| // Sets mDataType, mFrameSizeBytes, |
| // mSampleRate, mRateMultiplier, mLengthCode. |
| // |
| // @return true if valid |
| bool DTSFrameScanner::parseHeader() |
| { |
| BitFieldParser parser(&mHeaderBuffer[mSyncLength]); |
| |
| // These variables are named after the fields in the DTS spec 5.3.1 |
| // Extract field in order. |
| uint32_t ftype = parser.readBits(1); |
| uint32_t deficit = parser.readBits(5); // "short" |
| uint32_t cpf = parser.readBits(1); |
| uint32_t nblks = parser.readBits(7); |
| uint32_t fsize = parser.readBits(14); |
| uint32_t amode = parser.readBits(6); |
| uint32_t sfreq = parser.readBits(4); |
| // make sure we did not read past collected data |
| ALOG_ASSERT((mSyncLength + ((parser.getBitCursor() + 7) >> 3)) |
| <= mHeaderLength); |
| |
| // Validate fields. |
| if (cpf != 0) { |
| ALOGE("DTSFrameScanner: ERROR - CPF not zero!"); |
| return false; |
| } |
| if (nblks < DTS_MINIMUM_NBLKS) { |
| ALOGE("DTSFrameScanner: ERROR - nblks = %u", nblks); |
| return false; |
| } |
| if (fsize < DTS_MINIMUM_FSIZE) { |
| ALOGE("DTSFrameScanner: ERROR - fsize = %u", fsize); |
| return false; |
| } |
| |
| int32_t sampleRate = kDTSSampleRateTable[sfreq]; |
| if (sampleRate < 0) { |
| ALOGE("DTSFrameScanner: ERROR - invalid sampleRate[%u] = %d", sfreq, sampleRate); |
| return false; |
| } |
| mSampleRate = (uint32_t) sampleRate; |
| |
| mSampleFramesPerSyncFrame = (nblks + 1) * DTS_PCM_FRAMES_PER_BLOCK; |
| if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_I) { |
| mDataType = IEC61937_DATA_TYPE_DTS_I; |
| } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_II) { |
| mDataType = IEC61937_DATA_TYPE_DTS_II; |
| } else if (mSampleFramesPerSyncFrame <= IEC61937_MAX_SAMPLES_TYPE_III) { |
| mDataType = IEC61937_DATA_TYPE_DTS_III; |
| } else { |
| mDataType = IEC61937_DATA_TYPE_DTS_IV; |
| // TODO set bits 8,10 |
| } |
| |
| mFrameSizeBytes = fsize + 1; |
| |
| mRateMultiplier = 1; // TODO what about "frequency extension"? |
| ALOGI_IF((mFormatDumpCount == 0), |
| "DTS frame rate = %d * %d, size = %zu\n", |
| mSampleRate, mRateMultiplier, mFrameSizeBytes); |
| mFormatDumpCount++; |
| return true; |
| } |
| |
| |
| } // namespace android |