1 /*
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>
21 #include <media/nbaio/NBAIO.h>
22
23 namespace android {
24
Format_frameSize(const NBAIO_Format & format)25 size_t Format_frameSize(const NBAIO_Format& format)
26 {
27 return format.mFrameSize;
28 }
29
30 const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
31
Format_sampleRate(const NBAIO_Format & format)32 unsigned Format_sampleRate(const NBAIO_Format& format)
33 {
34 if (!Format_isValid(format)) {
35 return 0;
36 }
37 return format.mSampleRate;
38 }
39
Format_channelCount(const NBAIO_Format & format)40 unsigned Format_channelCount(const NBAIO_Format& format)
41 {
42 if (!Format_isValid(format)) {
43 return 0;
44 }
45 return format.mChannelCount;
46 }
47
Format_from_SR_C(unsigned sampleRate,unsigned channelCount,audio_format_t format)48 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
49 audio_format_t format)
50 {
51 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
52 return Format_Invalid;
53 }
54 NBAIO_Format ret;
55 ret.mSampleRate = sampleRate;
56 ret.mChannelCount = channelCount;
57 ret.mFormat = format;
58 ret.mFrameSize = audio_bytes_per_frame(channelCount, format);
59 return ret;
60 }
61
62 // This is a default implementation; it is expected that subclasses will optimize this.
writeVia(writeVia_t via,size_t total,void * user,size_t block)63 ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
64 {
65 if (!mNegotiated) {
66 return (ssize_t) NEGOTIATE;
67 }
68 static const size_t maxBlock = 32;
69 size_t frameSize = Format_frameSize(mFormat);
70 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
71 // double guarantees alignment for stack similar to what malloc() gives for heap
72 if (block == 0 || block > maxBlock) {
73 block = maxBlock;
74 }
75 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
76 size_t accumulator = 0;
77 while (accumulator < total) {
78 size_t count = total - accumulator;
79 if (count > block) {
80 count = block;
81 }
82 ssize_t ret = via(user, buffer, count);
83 if (ret > 0) {
84 ALOG_ASSERT((size_t) ret <= count);
85 size_t maxRet = ret;
86 ret = write(buffer, maxRet);
87 if (ret > 0) {
88 ALOG_ASSERT((size_t) ret <= maxRet);
89 accumulator += ret;
90 continue;
91 }
92 }
93 return accumulator > 0 ? accumulator : ret;
94 }
95 return accumulator;
96 }
97
98 // This is a default implementation; it is expected that subclasses will optimize this.
readVia(readVia_t via,size_t total,void * user,size_t block)99 ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, size_t block)
100 {
101 if (!mNegotiated) {
102 return (ssize_t) NEGOTIATE;
103 }
104 static const size_t maxBlock = 32;
105 size_t frameSize = Format_frameSize(mFormat);
106 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
107 // double guarantees alignment for stack similar to what malloc() gives for heap
108 if (block == 0 || block > maxBlock) {
109 block = maxBlock;
110 }
111 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
112 size_t accumulator = 0;
113 while (accumulator < total) {
114 size_t count = total - accumulator;
115 if (count > block) {
116 count = block;
117 }
118 ssize_t ret = read(buffer, count);
119 if (ret > 0) {
120 ALOG_ASSERT((size_t) ret <= count);
121 size_t maxRet = ret;
122 ret = via(user, buffer, maxRet);
123 if (ret > 0) {
124 ALOG_ASSERT((size_t) ret <= maxRet);
125 accumulator += ret;
126 continue;
127 }
128 }
129 return accumulator > 0 ? accumulator : ret;
130 }
131 return accumulator;
132 }
133
134 // Default implementation that only accepts my mFormat
negotiate(const NBAIO_Format offers[],size_t numOffers,NBAIO_Format counterOffers[],size_t & numCounterOffers)135 ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
136 NBAIO_Format counterOffers[], size_t& numCounterOffers)
137 {
138 ALOGV("negotiate offers=%p numOffers=%zu countersOffers=%p numCounterOffers=%zu",
139 offers, numOffers, counterOffers, numCounterOffers);
140 if (Format_isValid(mFormat)) {
141 for (size_t i = 0; i < numOffers; ++i) {
142 if (Format_isEqual(offers[i], mFormat)) {
143 mNegotiated = true;
144 return i;
145 }
146 }
147 if (numCounterOffers > 0) {
148 counterOffers[0] = mFormat;
149 }
150 numCounterOffers = 1;
151 } else {
152 numCounterOffers = 0;
153 }
154 return (ssize_t) NEGOTIATE;
155 }
156
Format_isValid(const NBAIO_Format & format)157 bool Format_isValid(const NBAIO_Format& format)
158 {
159 return format.mSampleRate != 0 && format.mChannelCount != 0 &&
160 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
161 }
162
Format_isEqual(const NBAIO_Format & format1,const NBAIO_Format & format2)163 bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
164 {
165 return format1.mSampleRate == format2.mSampleRate &&
166 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
167 format1.mFrameSize == format2.mFrameSize;
168 }
169
170 } // namespace android
171