NBAIO.cpp revision 1ec712f180072a7eb2131be09862921ae62dc2b4
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 23namespace android { 24 25size_t Format_frameSize(const NBAIO_Format& format) 26{ 27 // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT 28 return Format_channelCount(format) * sizeof(short); 29} 30 31size_t Format_frameBitShift(const NBAIO_Format& format) 32{ 33 // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT 34 // sizeof(short) == 2, so frame size == 1 << channels 35 return Format_channelCount(format); 36} 37 38const NBAIO_Format Format_Invalid = { 0 }; 39 40enum { 41 Format_SR_8000, 42 Format_SR_11025, 43 Format_SR_16000, 44 Format_SR_22050, 45 Format_SR_24000, 46 Format_SR_32000, 47 Format_SR_44100, 48 Format_SR_48000, 49 Format_SR_Mask = 7 50}; 51 52enum { 53 Format_C_1 = 0x08, 54 Format_C_2 = 0x10, 55 Format_C_Mask = 0x18 56}; 57 58unsigned Format_sampleRate(const NBAIO_Format& format) 59{ 60 if (!Format_isValid(format)) { 61 return 0; 62 } 63 switch (format.mPacked & Format_SR_Mask) { 64 case Format_SR_8000: 65 return 8000; 66 case Format_SR_11025: 67 return 11025; 68 case Format_SR_16000: 69 return 16000; 70 case Format_SR_22050: 71 return 22050; 72 case Format_SR_24000: 73 return 24000; 74 case Format_SR_32000: 75 return 32000; 76 case Format_SR_44100: 77 return 44100; 78 case Format_SR_48000: 79 return 48000; 80 default: 81 return 0; 82 } 83} 84 85unsigned Format_channelCount(const NBAIO_Format& format) 86{ 87 if (!Format_isValid(format)) { 88 return 0; 89 } 90 switch (format.mPacked & Format_C_Mask) { 91 case Format_C_1: 92 return 1; 93 case Format_C_2: 94 return 2; 95 default: 96 return 0; 97 } 98} 99 100NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount) 101{ 102 unsigned format; 103 switch (sampleRate) { 104 case 8000: 105 format = Format_SR_8000; 106 break; 107 case 11025: 108 format = Format_SR_11025; 109 break; 110 case 16000: 111 format = Format_SR_16000; 112 break; 113 case 22050: 114 format = Format_SR_22050; 115 break; 116 case 24000: 117 format = Format_SR_24000; 118 break; 119 case 32000: 120 format = Format_SR_32000; 121 break; 122 case 44100: 123 format = Format_SR_44100; 124 break; 125 case 48000: 126 format = Format_SR_48000; 127 break; 128 default: 129 return Format_Invalid; 130 } 131 switch (channelCount) { 132 case 1: 133 format |= Format_C_1; 134 break; 135 case 2: 136 format |= Format_C_2; 137 break; 138 default: 139 return Format_Invalid; 140 } 141 NBAIO_Format ret; 142 ret.mPacked = format; 143 return ret; 144} 145 146// This is a default implementation; it is expected that subclasses will optimize this. 147ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 148{ 149 if (!mNegotiated) { 150 return (ssize_t) NEGOTIATE; 151 } 152 static const size_t maxBlock = 32; 153 size_t frameSize = Format_frameSize(mFormat); 154 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 155 // double guarantees alignment for stack similar to what malloc() gives for heap 156 if (block == 0 || block > maxBlock) { 157 block = maxBlock; 158 } 159 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 160 size_t accumulator = 0; 161 while (accumulator < total) { 162 size_t count = total - accumulator; 163 if (count > block) { 164 count = block; 165 } 166 ssize_t ret = via(user, buffer, count); 167 if (ret > 0) { 168 ALOG_ASSERT((size_t) ret <= count); 169 size_t maxRet = ret; 170 ret = write(buffer, maxRet); 171 if (ret > 0) { 172 ALOG_ASSERT((size_t) ret <= maxRet); 173 accumulator += ret; 174 continue; 175 } 176 } 177 return accumulator > 0 ? accumulator : ret; 178 } 179 return accumulator; 180} 181 182// This is a default implementation; it is expected that subclasses will optimize this. 183ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 184 int64_t readPTS, size_t block) 185{ 186 if (!mNegotiated) { 187 return (ssize_t) NEGOTIATE; 188 } 189 static const size_t maxBlock = 32; 190 size_t frameSize = Format_frameSize(mFormat); 191 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 192 // double guarantees alignment for stack similar to what malloc() gives for heap 193 if (block == 0 || block > maxBlock) { 194 block = maxBlock; 195 } 196 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 197 size_t accumulator = 0; 198 while (accumulator < total) { 199 size_t count = total - accumulator; 200 if (count > block) { 201 count = block; 202 } 203 ssize_t ret = read(buffer, count, readPTS); 204 if (ret > 0) { 205 ALOG_ASSERT((size_t) ret <= count); 206 size_t maxRet = ret; 207 ret = via(user, buffer, maxRet, readPTS); 208 if (ret > 0) { 209 ALOG_ASSERT((size_t) ret <= maxRet); 210 accumulator += ret; 211 continue; 212 } 213 } 214 return accumulator > 0 ? accumulator : ret; 215 } 216 return accumulator; 217} 218 219// Default implementation that only accepts my mFormat 220ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 221 NBAIO_Format counterOffers[], size_t& numCounterOffers) 222{ 223 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 224 offers, numOffers, counterOffers, numCounterOffers); 225 if (Format_isValid(mFormat)) { 226 for (size_t i = 0; i < numOffers; ++i) { 227 if (Format_isEqual(offers[i], mFormat)) { 228 mNegotiated = true; 229 return i; 230 } 231 } 232 if (numCounterOffers > 0) { 233 counterOffers[0] = mFormat; 234 } 235 numCounterOffers = 1; 236 } else { 237 numCounterOffers = 0; 238 } 239 return (ssize_t) NEGOTIATE; 240} 241 242bool Format_isValid(const NBAIO_Format& format) 243{ 244 return format.mPacked != Format_Invalid.mPacked; 245} 246 247bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 248{ 249 return format1.mPacked == format2.mPacked; 250} 251 252} // namespace android 253