blob: 4f6591d765e51e788800e8aae799185a8bec2495 [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 Kasten983f0572014-03-06 08:23:11 -080027 return format.mFrameSize;
Glenn Kasten01066232012-02-27 11:50:44 -080028}
29
Glenn Kastenc326e1c2014-03-06 08:01:38 -080030#if 0
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}
Glenn Kastenc326e1c2014-03-06 08:01:38 -080038#endif
Glenn Kasten01066232012-02-27 11:50:44 -080039
Glenn Kasten2b7b9102014-03-06 08:02:51 -080040const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
Glenn Kasten51d53cd2014-01-31 09:38:33 -080041
Glenn Kastenb64497e2012-10-01 09:47:30 -070042enum {
43 Format_SR_8000,
44 Format_SR_11025,
45 Format_SR_16000,
46 Format_SR_22050,
47 Format_SR_24000,
48 Format_SR_32000,
49 Format_SR_44100,
50 Format_SR_48000,
51 Format_SR_Mask = 7
52};
53
54enum {
55 Format_C_1 = 0x08,
56 Format_C_2 = 0x10,
57 Format_C_Mask = 0x18
58};
59
Glenn Kasten72e54af2014-01-31 09:37:35 -080060unsigned Format_sampleRate(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080061{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080062 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070063 return 0;
64 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080065 return format.mSampleRate;
Glenn Kasten01066232012-02-27 11:50:44 -080066}
67
Glenn Kasten72e54af2014-01-31 09:37:35 -080068unsigned Format_channelCount(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080069{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080070 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070071 return 0;
72 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080073 return format.mChannelCount;
Glenn Kasten01066232012-02-27 11:50:44 -080074}
75
Glenn Kastenf95a3c42014-03-06 07:59:49 -080076NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
Glenn Kasten2b7b9102014-03-06 08:02:51 -080077 audio_format_t format)
Glenn Kasten01066232012-02-27 11:50:44 -080078{
Glenn Kasten2b7b9102014-03-06 08:02:51 -080079 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070080 return Format_Invalid;
81 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -080082 NBAIO_Format ret;
Glenn Kasten2b7b9102014-03-06 08:02:51 -080083 ret.mSampleRate = sampleRate;
84 ret.mChannelCount = channelCount;
85 ret.mFormat = format;
86 ret.mFrameSize = audio_is_linear_pcm(format) ?
87 channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
Glenn Kastenc4b8b322014-01-31 09:39:01 -080088 return ret;
Glenn Kasten01066232012-02-27 11:50:44 -080089}
90
91// This is a default implementation; it is expected that subclasses will optimize this.
92ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
93{
94 if (!mNegotiated) {
95 return (ssize_t) NEGOTIATE;
96 }
97 static const size_t maxBlock = 32;
98 size_t frameSize = Format_frameSize(mFormat);
99 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
100 // double guarantees alignment for stack similar to what malloc() gives for heap
101 if (block == 0 || block > maxBlock) {
102 block = maxBlock;
103 }
104 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
105 size_t accumulator = 0;
106 while (accumulator < total) {
107 size_t count = total - accumulator;
108 if (count > block) {
109 count = block;
110 }
111 ssize_t ret = via(user, buffer, count);
112 if (ret > 0) {
113 ALOG_ASSERT((size_t) ret <= count);
114 size_t maxRet = ret;
115 ret = write(buffer, maxRet);
116 if (ret > 0) {
117 ALOG_ASSERT((size_t) ret <= maxRet);
118 accumulator += ret;
119 continue;
120 }
121 }
122 return accumulator > 0 ? accumulator : ret;
123 }
124 return accumulator;
125}
126
127// This is a default implementation; it is expected that subclasses will optimize this.
John Grossman2c3b2da2012-08-02 17:08:54 -0700128ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
129 int64_t readPTS, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800130{
131 if (!mNegotiated) {
132 return (ssize_t) NEGOTIATE;
133 }
134 static const size_t maxBlock = 32;
135 size_t frameSize = Format_frameSize(mFormat);
136 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
137 // double guarantees alignment for stack similar to what malloc() gives for heap
138 if (block == 0 || block > maxBlock) {
139 block = maxBlock;
140 }
141 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
142 size_t accumulator = 0;
143 while (accumulator < total) {
144 size_t count = total - accumulator;
145 if (count > block) {
146 count = block;
147 }
John Grossman2c3b2da2012-08-02 17:08:54 -0700148 ssize_t ret = read(buffer, count, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800149 if (ret > 0) {
150 ALOG_ASSERT((size_t) ret <= count);
151 size_t maxRet = ret;
John Grossman2c3b2da2012-08-02 17:08:54 -0700152 ret = via(user, buffer, maxRet, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800153 if (ret > 0) {
154 ALOG_ASSERT((size_t) ret <= maxRet);
155 accumulator += ret;
156 continue;
157 }
158 }
159 return accumulator > 0 ? accumulator : ret;
160 }
161 return accumulator;
162}
163
164// Default implementation that only accepts my mFormat
165ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
166 NBAIO_Format counterOffers[], size_t& numCounterOffers)
167{
168 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
169 offers, numOffers, counterOffers, numCounterOffers);
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800170 if (Format_isValid(mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800171 for (size_t i = 0; i < numOffers; ++i) {
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800172 if (Format_isEqual(offers[i], mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800173 mNegotiated = true;
174 return i;
175 }
176 }
177 if (numCounterOffers > 0) {
178 counterOffers[0] = mFormat;
179 }
180 numCounterOffers = 1;
181 } else {
182 numCounterOffers = 0;
183 }
184 return (ssize_t) NEGOTIATE;
185}
186
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800187bool Format_isValid(const NBAIO_Format& format)
188{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800189 return format.mSampleRate != 0 && format.mChannelCount != 0 &&
190 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800191}
192
193bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
194{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800195 return format1.mSampleRate == format2.mSampleRate &&
196 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
197 format1.mFrameSize == format2.mFrameSize;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800198}
199
Glenn Kasten01066232012-02-27 11:50:44 -0800200} // namespace android