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