NBAIO.cpp revision 2b7b910f4b417ab3930379298f538d0dfc857e88
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 31int 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 // FIXME must return -1 for non-power of 2 37} 38 39const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 }; 40 41enum { 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 59unsigned Format_sampleRate(const NBAIO_Format& format) 60{ 61 if (!Format_isValid(format)) { 62 return 0; 63 } 64 return format.mSampleRate; 65} 66 67unsigned Format_channelCount(const NBAIO_Format& format) 68{ 69 if (!Format_isValid(format)) { 70 return 0; 71 } 72 return format.mChannelCount; 73} 74 75NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount, 76 audio_format_t format) 77{ 78 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) { 79 return Format_Invalid; 80 } 81 NBAIO_Format ret; 82 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); 87 return ret; 88} 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. 127ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 128 int64_t readPTS, size_t block) 129{ 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 } 147 ssize_t ret = read(buffer, count, readPTS); 148 if (ret > 0) { 149 ALOG_ASSERT((size_t) ret <= count); 150 size_t maxRet = ret; 151 ret = via(user, buffer, maxRet, readPTS); 152 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); 169 if (Format_isValid(mFormat)) { 170 for (size_t i = 0; i < numOffers; ++i) { 171 if (Format_isEqual(offers[i], mFormat)) { 172 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 186bool Format_isValid(const NBAIO_Format& format) 187{ 188 return format.mSampleRate != 0 && format.mChannelCount != 0 && 189 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0; 190} 191 192bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 193{ 194 return format1.mSampleRate == format2.mSampleRate && 195 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat && 196 format1.mFrameSize == format2.mFrameSize; 197} 198 199} // namespace android 200