You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.3 KiB
139 lines
4.3 KiB
/* |
|
* 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. |
|
(void) /* uint32_t ftype = */ parser.readBits(1); |
|
(void) /* 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); |
|
(void) /* 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", |
|
mSampleRate, mRateMultiplier, mFrameSizeBytes); |
|
mFormatDumpCount++; |
|
return true; |
|
} |
|
|
|
|
|
} // namespace android
|
|
|