blob: e0d2c21974dc2e08517f5ccd23047c306f5378ef [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
25size_t Format_frameSize(NBAIO_Format format)
26{
Glenn Kastenb64497e2012-10-01 09:47:30 -070027 return Format_channelCount(format) * sizeof(short);
Glenn Kasten01066232012-02-27 11:50:44 -080028}
29
30size_t Format_frameBitShift(NBAIO_Format format)
31{
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 Kastenb64497e2012-10-01 09:47:30 -070036enum {
37 Format_SR_8000,
38 Format_SR_11025,
39 Format_SR_16000,
40 Format_SR_22050,
41 Format_SR_24000,
42 Format_SR_32000,
43 Format_SR_44100,
44 Format_SR_48000,
45 Format_SR_Mask = 7
46};
47
48enum {
49 Format_C_1 = 0x08,
50 Format_C_2 = 0x10,
51 Format_C_Mask = 0x18
52};
53
Glenn Kasten01066232012-02-27 11:50:44 -080054unsigned Format_sampleRate(NBAIO_Format format)
55{
Glenn Kastenb64497e2012-10-01 09:47:30 -070056 if (format == Format_Invalid) {
57 return 0;
58 }
59 switch (format & Format_SR_Mask) {
60 case Format_SR_8000:
61 return 8000;
62 case Format_SR_11025:
63 return 11025;
64 case Format_SR_16000:
65 return 16000;
66 case Format_SR_22050:
67 return 22050;
68 case Format_SR_24000:
69 return 24000;
70 case Format_SR_32000:
71 return 32000;
72 case Format_SR_44100:
Glenn Kasten01066232012-02-27 11:50:44 -080073 return 44100;
Glenn Kastenb64497e2012-10-01 09:47:30 -070074 case Format_SR_48000:
Glenn Kasten01066232012-02-27 11:50:44 -080075 return 48000;
Glenn Kasten01066232012-02-27 11:50:44 -080076 default:
77 return 0;
78 }
79}
80
81unsigned Format_channelCount(NBAIO_Format format)
82{
Glenn Kastenb64497e2012-10-01 09:47:30 -070083 if (format == Format_Invalid) {
84 return 0;
85 }
86 switch (format & Format_C_Mask) {
87 case Format_C_1:
Glenn Kasten01066232012-02-27 11:50:44 -080088 return 1;
Glenn Kastenb64497e2012-10-01 09:47:30 -070089 case Format_C_2:
Glenn Kasten01066232012-02-27 11:50:44 -080090 return 2;
Glenn Kasten01066232012-02-27 11:50:44 -080091 default:
92 return 0;
93 }
94}
95
96NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
97{
Glenn Kastenb64497e2012-10-01 09:47:30 -070098 NBAIO_Format format;
99 switch (sampleRate) {
100 case 8000:
101 format = Format_SR_8000;
102 break;
103 case 11025:
104 format = Format_SR_11025;
105 break;
106 case 16000:
107 format = Format_SR_16000;
108 break;
109 case 22050:
110 format = Format_SR_22050;
111 break;
112 case 24000:
113 format = Format_SR_24000;
114 break;
115 case 32000:
116 format = Format_SR_32000;
117 break;
118 case 44100:
119 format = Format_SR_44100;
120 break;
121 case 48000:
122 format = Format_SR_48000;
123 break;
124 default:
125 return Format_Invalid;
126 }
127 switch (channelCount) {
128 case 1:
129 format |= Format_C_1;
130 break;
131 case 2:
132 format |= Format_C_2;
133 break;
134 default:
135 return Format_Invalid;
136 }
137 return format;
Glenn Kasten01066232012-02-27 11:50:44 -0800138}
139
140// This is a default implementation; it is expected that subclasses will optimize this.
141ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
142{
143 if (!mNegotiated) {
144 return (ssize_t) NEGOTIATE;
145 }
146 static const size_t maxBlock = 32;
147 size_t frameSize = Format_frameSize(mFormat);
148 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
149 // double guarantees alignment for stack similar to what malloc() gives for heap
150 if (block == 0 || block > maxBlock) {
151 block = maxBlock;
152 }
153 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
154 size_t accumulator = 0;
155 while (accumulator < total) {
156 size_t count = total - accumulator;
157 if (count > block) {
158 count = block;
159 }
160 ssize_t ret = via(user, buffer, count);
161 if (ret > 0) {
162 ALOG_ASSERT((size_t) ret <= count);
163 size_t maxRet = ret;
164 ret = write(buffer, maxRet);
165 if (ret > 0) {
166 ALOG_ASSERT((size_t) ret <= maxRet);
167 accumulator += ret;
168 continue;
169 }
170 }
171 return accumulator > 0 ? accumulator : ret;
172 }
173 return accumulator;
174}
175
176// This is a default implementation; it is expected that subclasses will optimize this.
John Grossman2c3b2da2012-08-02 17:08:54 -0700177ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
178 int64_t readPTS, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800179{
180 if (!mNegotiated) {
181 return (ssize_t) NEGOTIATE;
182 }
183 static const size_t maxBlock = 32;
184 size_t frameSize = Format_frameSize(mFormat);
185 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
186 // double guarantees alignment for stack similar to what malloc() gives for heap
187 if (block == 0 || block > maxBlock) {
188 block = maxBlock;
189 }
190 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
191 size_t accumulator = 0;
192 while (accumulator < total) {
193 size_t count = total - accumulator;
194 if (count > block) {
195 count = block;
196 }
John Grossman2c3b2da2012-08-02 17:08:54 -0700197 ssize_t ret = read(buffer, count, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800198 if (ret > 0) {
199 ALOG_ASSERT((size_t) ret <= count);
200 size_t maxRet = ret;
John Grossman2c3b2da2012-08-02 17:08:54 -0700201 ret = via(user, buffer, maxRet, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800202 if (ret > 0) {
203 ALOG_ASSERT((size_t) ret <= maxRet);
204 accumulator += ret;
205 continue;
206 }
207 }
208 return accumulator > 0 ? accumulator : ret;
209 }
210 return accumulator;
211}
212
213// Default implementation that only accepts my mFormat
214ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
215 NBAIO_Format counterOffers[], size_t& numCounterOffers)
216{
217 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
218 offers, numOffers, counterOffers, numCounterOffers);
219 if (mFormat != Format_Invalid) {
220 for (size_t i = 0; i < numOffers; ++i) {
221 if (offers[i] == mFormat) {
222 mNegotiated = true;
223 return i;
224 }
225 }
226 if (numCounterOffers > 0) {
227 counterOffers[0] = mFormat;
228 }
229 numCounterOffers = 1;
230 } else {
231 numCounterOffers = 0;
232 }
233 return (ssize_t) NEGOTIATE;
234}
235
236} // namespace android