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