blob: cfcd8b445db0d2f0c3c085091efc5188f894fec6 [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 Kasten1ec712f2014-01-31 09:47:15 -080027 // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
Glenn Kastenb64497e2012-10-01 09:47:30 -070028 return Format_channelCount(format) * sizeof(short);
Glenn Kasten01066232012-02-27 11:50:44 -080029}
30
Glenn Kasten4d7b3f82014-01-31 10:38:16 -080031int Format_frameBitShift(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080032{
Glenn Kasten1ec712f2014-01-31 09:47:15 -080033 // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
Glenn Kastenb64497e2012-10-01 09:47:30 -070034 // sizeof(short) == 2, so frame size == 1 << channels
35 return Format_channelCount(format);
Glenn Kasten4d7b3f82014-01-31 10:38:16 -080036 // FIXME must return -1 for non-power of 2
Glenn Kasten01066232012-02-27 11:50:44 -080037}
38
Glenn Kasten2b7b9102014-03-06 08:02:51 -080039const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
Glenn Kasten51d53cd2014-01-31 09:38:33 -080040
Glenn Kastenb64497e2012-10-01 09:47:30 -070041enum {
42 Format_SR_8000,
43 Format_SR_11025,
44 Format_SR_16000,
45 Format_SR_22050,
46 Format_SR_24000,
47 Format_SR_32000,
48 Format_SR_44100,
49 Format_SR_48000,
50 Format_SR_Mask = 7
51};
52
53enum {
54 Format_C_1 = 0x08,
55 Format_C_2 = 0x10,
56 Format_C_Mask = 0x18
57};
58
Glenn Kasten72e54af2014-01-31 09:37:35 -080059unsigned Format_sampleRate(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080060{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080061 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070062 return 0;
63 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080064 return format.mSampleRate;
Glenn Kasten01066232012-02-27 11:50:44 -080065}
66
Glenn Kasten72e54af2014-01-31 09:37:35 -080067unsigned Format_channelCount(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080068{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080069 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070070 return 0;
71 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080072 return format.mChannelCount;
Glenn Kasten01066232012-02-27 11:50:44 -080073}
74
Glenn Kastenf95a3c42014-03-06 07:59:49 -080075NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
Glenn Kasten2b7b9102014-03-06 08:02:51 -080076 audio_format_t format)
Glenn Kasten01066232012-02-27 11:50:44 -080077{
Glenn Kasten2b7b9102014-03-06 08:02:51 -080078 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070079 return Format_Invalid;
80 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -080081 NBAIO_Format ret;
Glenn Kasten2b7b9102014-03-06 08:02:51 -080082 ret.mSampleRate = sampleRate;
83 ret.mChannelCount = channelCount;
84 ret.mFormat = format;
85 ret.mFrameSize = audio_is_linear_pcm(format) ?
86 channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
Glenn Kastenc4b8b322014-01-31 09:39:01 -080087 return ret;
Glenn Kasten01066232012-02-27 11:50:44 -080088}
89
90// This is a default implementation; it is expected that subclasses will optimize this.
91ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
92{
93 if (!mNegotiated) {
94 return (ssize_t) NEGOTIATE;
95 }
96 static const size_t maxBlock = 32;
97 size_t frameSize = Format_frameSize(mFormat);
98 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
99 // double guarantees alignment for stack similar to what malloc() gives for heap
100 if (block == 0 || block > maxBlock) {
101 block = maxBlock;
102 }
103 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
104 size_t accumulator = 0;
105 while (accumulator < total) {
106 size_t count = total - accumulator;
107 if (count > block) {
108 count = block;
109 }
110 ssize_t ret = via(user, buffer, count);
111 if (ret > 0) {
112 ALOG_ASSERT((size_t) ret <= count);
113 size_t maxRet = ret;
114 ret = write(buffer, maxRet);
115 if (ret > 0) {
116 ALOG_ASSERT((size_t) ret <= maxRet);
117 accumulator += ret;
118 continue;
119 }
120 }
121 return accumulator > 0 ? accumulator : ret;
122 }
123 return accumulator;
124}
125
126// This is a default implementation; it is expected that subclasses will optimize this.
John Grossman2c3b2da2012-08-02 17:08:54 -0700127ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
128 int64_t readPTS, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800129{
130 if (!mNegotiated) {
131 return (ssize_t) NEGOTIATE;
132 }
133 static const size_t maxBlock = 32;
134 size_t frameSize = Format_frameSize(mFormat);
135 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
136 // double guarantees alignment for stack similar to what malloc() gives for heap
137 if (block == 0 || block > maxBlock) {
138 block = maxBlock;
139 }
140 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
141 size_t accumulator = 0;
142 while (accumulator < total) {
143 size_t count = total - accumulator;
144 if (count > block) {
145 count = block;
146 }
John Grossman2c3b2da2012-08-02 17:08:54 -0700147 ssize_t ret = read(buffer, count, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800148 if (ret > 0) {
149 ALOG_ASSERT((size_t) ret <= count);
150 size_t maxRet = ret;
John Grossman2c3b2da2012-08-02 17:08:54 -0700151 ret = via(user, buffer, maxRet, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800152 if (ret > 0) {
153 ALOG_ASSERT((size_t) ret <= maxRet);
154 accumulator += ret;
155 continue;
156 }
157 }
158 return accumulator > 0 ? accumulator : ret;
159 }
160 return accumulator;
161}
162
163// Default implementation that only accepts my mFormat
164ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
165 NBAIO_Format counterOffers[], size_t& numCounterOffers)
166{
167 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
168 offers, numOffers, counterOffers, numCounterOffers);
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800169 if (Format_isValid(mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800170 for (size_t i = 0; i < numOffers; ++i) {
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800171 if (Format_isEqual(offers[i], mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800172 mNegotiated = true;
173 return i;
174 }
175 }
176 if (numCounterOffers > 0) {
177 counterOffers[0] = mFormat;
178 }
179 numCounterOffers = 1;
180 } else {
181 numCounterOffers = 0;
182 }
183 return (ssize_t) NEGOTIATE;
184}
185
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800186bool Format_isValid(const NBAIO_Format& format)
187{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800188 return format.mSampleRate != 0 && format.mChannelCount != 0 &&
189 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800190}
191
192bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
193{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800194 return format1.mSampleRate == format2.mSampleRate &&
195 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
196 format1.mFrameSize == format2.mFrameSize;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800197}
198
Glenn Kasten01066232012-02-27 11:50:44 -0800199} // namespace android