NBAIO.cpp revision c4b8b32dec91a11a83d0a7ab49747606d16d39a5
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.mPacked & 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.mPacked & 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 unsigned 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 NBAIO_Format ret; 140 ret.mPacked = format; 141 return ret; 142} 143 144// This is a default implementation; it is expected that subclasses will optimize this. 145ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 146{ 147 if (!mNegotiated) { 148 return (ssize_t) NEGOTIATE; 149 } 150 static const size_t maxBlock = 32; 151 size_t frameSize = Format_frameSize(mFormat); 152 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 153 // double guarantees alignment for stack similar to what malloc() gives for heap 154 if (block == 0 || block > maxBlock) { 155 block = maxBlock; 156 } 157 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 158 size_t accumulator = 0; 159 while (accumulator < total) { 160 size_t count = total - accumulator; 161 if (count > block) { 162 count = block; 163 } 164 ssize_t ret = via(user, buffer, count); 165 if (ret > 0) { 166 ALOG_ASSERT((size_t) ret <= count); 167 size_t maxRet = ret; 168 ret = write(buffer, maxRet); 169 if (ret > 0) { 170 ALOG_ASSERT((size_t) ret <= maxRet); 171 accumulator += ret; 172 continue; 173 } 174 } 175 return accumulator > 0 ? accumulator : ret; 176 } 177 return accumulator; 178} 179 180// This is a default implementation; it is expected that subclasses will optimize this. 181ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 182 int64_t readPTS, size_t block) 183{ 184 if (!mNegotiated) { 185 return (ssize_t) NEGOTIATE; 186 } 187 static const size_t maxBlock = 32; 188 size_t frameSize = Format_frameSize(mFormat); 189 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 190 // double guarantees alignment for stack similar to what malloc() gives for heap 191 if (block == 0 || block > maxBlock) { 192 block = maxBlock; 193 } 194 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 195 size_t accumulator = 0; 196 while (accumulator < total) { 197 size_t count = total - accumulator; 198 if (count > block) { 199 count = block; 200 } 201 ssize_t ret = read(buffer, count, readPTS); 202 if (ret > 0) { 203 ALOG_ASSERT((size_t) ret <= count); 204 size_t maxRet = ret; 205 ret = via(user, buffer, maxRet, readPTS); 206 if (ret > 0) { 207 ALOG_ASSERT((size_t) ret <= maxRet); 208 accumulator += ret; 209 continue; 210 } 211 } 212 return accumulator > 0 ? accumulator : ret; 213 } 214 return accumulator; 215} 216 217// Default implementation that only accepts my mFormat 218ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 219 NBAIO_Format counterOffers[], size_t& numCounterOffers) 220{ 221 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 222 offers, numOffers, counterOffers, numCounterOffers); 223 if (Format_isValid(mFormat)) { 224 for (size_t i = 0; i < numOffers; ++i) { 225 if (Format_isEqual(offers[i], mFormat)) { 226 mNegotiated = true; 227 return i; 228 } 229 } 230 if (numCounterOffers > 0) { 231 counterOffers[0] = mFormat; 232 } 233 numCounterOffers = 1; 234 } else { 235 numCounterOffers = 0; 236 } 237 return (ssize_t) NEGOTIATE; 238} 239 240bool Format_isValid(const NBAIO_Format& format) 241{ 242 return format.mPacked != Format_Invalid.mPacked; 243} 244 245bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 246{ 247 return format1.mPacked == format2.mPacked; 248} 249 250} // namespace android 251