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, 101 int64_t readPTS, size_t block) 102 { 103 if (!mNegotiated) { 104 return (ssize_t) NEGOTIATE; 105 } 106 static const size_t maxBlock = 32; 107 size_t frameSize = Format_frameSize(mFormat); 108 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 109 // double guarantees alignment for stack similar to what malloc() gives for heap 110 if (block == 0 || block > maxBlock) { 111 block = maxBlock; 112 } 113 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 114 size_t accumulator = 0; 115 while (accumulator < total) { 116 size_t count = total - accumulator; 117 if (count > block) { 118 count = block; 119 } 120 ssize_t ret = read(buffer, count, readPTS); 121 if (ret > 0) { 122 ALOG_ASSERT((size_t) ret <= count); 123 size_t maxRet = ret; 124 ret = via(user, buffer, maxRet, readPTS); 125 if (ret > 0) { 126 ALOG_ASSERT((size_t) ret <= maxRet); 127 accumulator += ret; 128 continue; 129 } 130 } 131 return accumulator > 0 ? accumulator : ret; 132 } 133 return accumulator; 134 } 135 136 // Default implementation that only accepts my mFormat 137 ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 138 NBAIO_Format counterOffers[], size_t& numCounterOffers) 139 { 140 ALOGV("negotiate offers=%p numOffers=%zu countersOffers=%p numCounterOffers=%zu", 141 offers, numOffers, counterOffers, numCounterOffers); 142 if (Format_isValid(mFormat)) { 143 for (size_t i = 0; i < numOffers; ++i) { 144 if (Format_isEqual(offers[i], mFormat)) { 145 mNegotiated = true; 146 return i; 147 } 148 } 149 if (numCounterOffers > 0) { 150 counterOffers[0] = mFormat; 151 } 152 numCounterOffers = 1; 153 } else { 154 numCounterOffers = 0; 155 } 156 return (ssize_t) NEGOTIATE; 157 } 158 159 bool Format_isValid(const NBAIO_Format& format) 160 { 161 return format.mSampleRate != 0 && format.mChannelCount != 0 && 162 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0; 163 } 164 165 bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 166 { 167 return format1.mSampleRate == format2.mSampleRate && 168 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat && 169 format1.mFrameSize == format2.mFrameSize; 170 } 171 172 } // namespace android 173