NBAIO.cpp revision 983f0578ccd2928af40c9689f6fe90110d02b92e
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 return format.mFrameSize; 28} 29 30int Format_frameBitShift(const NBAIO_Format& format) 31{ 32 // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT 33 // sizeof(short) == 2, so frame size == 1 << channels 34 return Format_channelCount(format); 35 // FIXME must return -1 for non-power of 2 36} 37 38const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_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 return format.mSampleRate; 64} 65 66unsigned Format_channelCount(const NBAIO_Format& format) 67{ 68 if (!Format_isValid(format)) { 69 return 0; 70 } 71 return format.mChannelCount; 72} 73 74NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount, 75 audio_format_t format) 76{ 77 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) { 78 return Format_Invalid; 79 } 80 NBAIO_Format ret; 81 ret.mSampleRate = sampleRate; 82 ret.mChannelCount = channelCount; 83 ret.mFormat = format; 84 ret.mFrameSize = audio_is_linear_pcm(format) ? 85 channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t); 86 return ret; 87} 88 89// This is a default implementation; it is expected that subclasses will optimize this. 90ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 91{ 92 if (!mNegotiated) { 93 return (ssize_t) NEGOTIATE; 94 } 95 static const size_t maxBlock = 32; 96 size_t frameSize = Format_frameSize(mFormat); 97 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 98 // double guarantees alignment for stack similar to what malloc() gives for heap 99 if (block == 0 || block > maxBlock) { 100 block = maxBlock; 101 } 102 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 103 size_t accumulator = 0; 104 while (accumulator < total) { 105 size_t count = total - accumulator; 106 if (count > block) { 107 count = block; 108 } 109 ssize_t ret = via(user, buffer, count); 110 if (ret > 0) { 111 ALOG_ASSERT((size_t) ret <= count); 112 size_t maxRet = ret; 113 ret = write(buffer, maxRet); 114 if (ret > 0) { 115 ALOG_ASSERT((size_t) ret <= maxRet); 116 accumulator += ret; 117 continue; 118 } 119 } 120 return accumulator > 0 ? accumulator : ret; 121 } 122 return accumulator; 123} 124 125// This is a default implementation; it is expected that subclasses will optimize this. 126ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 127 int64_t readPTS, size_t block) 128{ 129 if (!mNegotiated) { 130 return (ssize_t) NEGOTIATE; 131 } 132 static const size_t maxBlock = 32; 133 size_t frameSize = Format_frameSize(mFormat); 134 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 135 // double guarantees alignment for stack similar to what malloc() gives for heap 136 if (block == 0 || block > maxBlock) { 137 block = maxBlock; 138 } 139 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 140 size_t accumulator = 0; 141 while (accumulator < total) { 142 size_t count = total - accumulator; 143 if (count > block) { 144 count = block; 145 } 146 ssize_t ret = read(buffer, count, readPTS); 147 if (ret > 0) { 148 ALOG_ASSERT((size_t) ret <= count); 149 size_t maxRet = ret; 150 ret = via(user, buffer, maxRet, readPTS); 151 if (ret > 0) { 152 ALOG_ASSERT((size_t) ret <= maxRet); 153 accumulator += ret; 154 continue; 155 } 156 } 157 return accumulator > 0 ? accumulator : ret; 158 } 159 return accumulator; 160} 161 162// Default implementation that only accepts my mFormat 163ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 164 NBAIO_Format counterOffers[], size_t& numCounterOffers) 165{ 166 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 167 offers, numOffers, counterOffers, numCounterOffers); 168 if (Format_isValid(mFormat)) { 169 for (size_t i = 0; i < numOffers; ++i) { 170 if (Format_isEqual(offers[i], mFormat)) { 171 mNegotiated = true; 172 return i; 173 } 174 } 175 if (numCounterOffers > 0) { 176 counterOffers[0] = mFormat; 177 } 178 numCounterOffers = 1; 179 } else { 180 numCounterOffers = 0; 181 } 182 return (ssize_t) NEGOTIATE; 183} 184 185bool Format_isValid(const NBAIO_Format& format) 186{ 187 return format.mSampleRate != 0 && format.mChannelCount != 0 && 188 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0; 189} 190 191bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 192{ 193 return format1.mSampleRate == format2.mSampleRate && 194 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat && 195 format1.mFrameSize == format2.mFrameSize; 196} 197 198} // namespace android 199