blob: f6302360aed7604f74f807aad57c0e5d8004f88f [file] [log] [blame]
Glenn Kasten01066232012-02-27 11:50:44 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "NBAIO"
18//#define LOG_NDEBUG 0
19
20#include <utils/Log.h>
Glenn Kasten2dd4bdd2012-08-29 11:10:32 -070021#include <media/nbaio/NBAIO.h>
Glenn Kasten01066232012-02-27 11:50:44 -080022
23namespace android {
24
Glenn Kasten72e54af2014-01-31 09:37:35 -080025size_t Format_frameSize(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080026{
Glenn Kastenb64497e2012-10-01 09:47:30 -070027 return Format_channelCount(format) * sizeof(short);
Glenn Kasten01066232012-02-27 11:50:44 -080028}
29
Glenn Kasten72e54af2014-01-31 09:37:35 -080030size_t Format_frameBitShift(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080031{
Glenn Kastenb64497e2012-10-01 09:47:30 -070032 // sizeof(short) == 2, so frame size == 1 << channels
33 return Format_channelCount(format);
Glenn Kasten01066232012-02-27 11:50:44 -080034}
35
Glenn Kasten51d53cd2014-01-31 09:38:33 -080036const NBAIO_Format Format_Invalid = { 0 };
37
Glenn Kastenb64497e2012-10-01 09:47:30 -070038enum {
39 Format_SR_8000,
40 Format_SR_11025,
41 Format_SR_16000,
42 Format_SR_22050,
43 Format_SR_24000,
44 Format_SR_32000,
45 Format_SR_44100,
46 Format_SR_48000,
47 Format_SR_Mask = 7
48};
49
50enum {
51 Format_C_1 = 0x08,
52 Format_C_2 = 0x10,
53 Format_C_Mask = 0x18
54};
55
Glenn Kasten72e54af2014-01-31 09:37:35 -080056unsigned Format_sampleRate(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080057{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080058 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070059 return 0;
60 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -080061 switch (format.mPacked & Format_SR_Mask) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070062 case Format_SR_8000:
63 return 8000;
64 case Format_SR_11025:
65 return 11025;
66 case Format_SR_16000:
67 return 16000;
68 case Format_SR_22050:
69 return 22050;
70 case Format_SR_24000:
71 return 24000;
72 case Format_SR_32000:
73 return 32000;
74 case Format_SR_44100:
Glenn Kasten01066232012-02-27 11:50:44 -080075 return 44100;
Glenn Kastenb64497e2012-10-01 09:47:30 -070076 case Format_SR_48000:
Glenn Kasten01066232012-02-27 11:50:44 -080077 return 48000;
Glenn Kasten01066232012-02-27 11:50:44 -080078 default:
79 return 0;
80 }
81}
82
Glenn Kasten72e54af2014-01-31 09:37:35 -080083unsigned Format_channelCount(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080084{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080085 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070086 return 0;
87 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -080088 switch (format.mPacked & Format_C_Mask) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070089 case Format_C_1:
Glenn Kasten01066232012-02-27 11:50:44 -080090 return 1;
Glenn Kastenb64497e2012-10-01 09:47:30 -070091 case Format_C_2:
Glenn Kasten01066232012-02-27 11:50:44 -080092 return 2;
Glenn Kasten01066232012-02-27 11:50:44 -080093 default:
94 return 0;
95 }
96}
97
98NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
99{
Glenn Kastenc4b8b322014-01-31 09:39:01 -0800100 unsigned format;
Glenn Kastenb64497e2012-10-01 09:47:30 -0700101 switch (sampleRate) {
102 case 8000:
103 format = Format_SR_8000;
104 break;
105 case 11025:
106 format = Format_SR_11025;
107 break;
108 case 16000:
109 format = Format_SR_16000;
110 break;
111 case 22050:
112 format = Format_SR_22050;
113 break;
114 case 24000:
115 format = Format_SR_24000;
116 break;
117 case 32000:
118 format = Format_SR_32000;
119 break;
120 case 44100:
121 format = Format_SR_44100;
122 break;
123 case 48000:
124 format = Format_SR_48000;
125 break;
126 default:
127 return Format_Invalid;
128 }
129 switch (channelCount) {
130 case 1:
131 format |= Format_C_1;
132 break;
133 case 2:
134 format |= Format_C_2;
135 break;
136 default:
137 return Format_Invalid;
138 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -0800139 NBAIO_Format ret;
140 ret.mPacked = format;
141 return ret;
Glenn Kasten01066232012-02-27 11:50:44 -0800142}
143
144// This is a default implementation; it is expected that subclasses will optimize this.
145ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
146{
147 if (!mNegotiated) {
148 return (ssize_t) NEGOTIATE;
149 }
150 static const size_t maxBlock = 32;
151 size_t frameSize = Format_frameSize(mFormat);
152 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
153 // double guarantees alignment for stack similar to what malloc() gives for heap
154 if (block == 0 || block > maxBlock) {
155 block = maxBlock;
156 }
157 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
158 size_t accumulator = 0;
159 while (accumulator < total) {
160 size_t count = total - accumulator;
161 if (count > block) {
162 count = block;
163 }
164 ssize_t ret = via(user, buffer, count);
165 if (ret > 0) {
166 ALOG_ASSERT((size_t) ret <= count);
167 size_t maxRet = ret;
168 ret = write(buffer, maxRet);
169 if (ret > 0) {
170 ALOG_ASSERT((size_t) ret <= maxRet);
171 accumulator += ret;
172 continue;
173 }
174 }
175 return accumulator > 0 ? accumulator : ret;
176 }
177 return accumulator;
178}
179
180// This is a default implementation; it is expected that subclasses will optimize this.
John Grossman2c3b2da2012-08-02 17:08:54 -0700181ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
182 int64_t readPTS, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800183{
184 if (!mNegotiated) {
185 return (ssize_t) NEGOTIATE;
186 }
187 static const size_t maxBlock = 32;
188 size_t frameSize = Format_frameSize(mFormat);
189 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
190 // double guarantees alignment for stack similar to what malloc() gives for heap
191 if (block == 0 || block > maxBlock) {
192 block = maxBlock;
193 }
194 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
195 size_t accumulator = 0;
196 while (accumulator < total) {
197 size_t count = total - accumulator;
198 if (count > block) {
199 count = block;
200 }
John Grossman2c3b2da2012-08-02 17:08:54 -0700201 ssize_t ret = read(buffer, count, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800202 if (ret > 0) {
203 ALOG_ASSERT((size_t) ret <= count);
204 size_t maxRet = ret;
John Grossman2c3b2da2012-08-02 17:08:54 -0700205 ret = via(user, buffer, maxRet, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800206 if (ret > 0) {
207 ALOG_ASSERT((size_t) ret <= maxRet);
208 accumulator += ret;
209 continue;
210 }
211 }
212 return accumulator > 0 ? accumulator : ret;
213 }
214 return accumulator;
215}
216
217// Default implementation that only accepts my mFormat
218ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
219 NBAIO_Format counterOffers[], size_t& numCounterOffers)
220{
221 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
222 offers, numOffers, counterOffers, numCounterOffers);
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800223 if (Format_isValid(mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800224 for (size_t i = 0; i < numOffers; ++i) {
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800225 if (Format_isEqual(offers[i], mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800226 mNegotiated = true;
227 return i;
228 }
229 }
230 if (numCounterOffers > 0) {
231 counterOffers[0] = mFormat;
232 }
233 numCounterOffers = 1;
234 } else {
235 numCounterOffers = 0;
236 }
237 return (ssize_t) NEGOTIATE;
238}
239
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800240bool Format_isValid(const NBAIO_Format& format)
241{
Glenn Kastenc4b8b322014-01-31 09:39:01 -0800242 return format.mPacked != Format_Invalid.mPacked;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800243}
244
245bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
246{
Glenn Kastenc4b8b322014-01-31 09:39:01 -0800247 return format1.mPacked == format2.mPacked;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800248}
249
Glenn Kasten01066232012-02-27 11:50:44 -0800250} // namespace android