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