NBAIO.cpp revision 983f0578ccd2928af40c9689f6fe90110d02b92e
1010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten/* 2010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Copyright (C) 2012 The Android Open Source Project 3010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 4010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * you may not use this file except in compliance with the License. 6010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * You may obtain a copy of the License at 7010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 8010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 10010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * See the License for the specific language governing permissions and 14010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * limitations under the License. 15010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten */ 16010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 17010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "NBAIO" 18010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0 19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 212dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/NBAIO.h> 22010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 23010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 2572e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastensize_t Format_frameSize(const NBAIO_Format& format) 26010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 27983f0578ccd2928af40c9689f6fe90110d02b92eGlenn Kasten return format.mFrameSize; 28010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 29010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 304d7b3f876b21997680ae32a340d746ed1cae6ab1Glenn Kastenint Format_frameBitShift(const NBAIO_Format& format) 31010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 321ec712f180072a7eb2131be09862921ae62dc2b4Glenn Kasten // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT 33b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten // sizeof(short) == 2, so frame size == 1 << channels 34b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_channelCount(format); 354d7b3f876b21997680ae32a340d746ed1cae6ab1Glenn Kasten // FIXME must return -1 for non-power of 2 36010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 37010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 382b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kastenconst NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 }; 3951d53cd993043d9286e12cba884e6ee4d10b5facGlenn Kasten 40b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kastenenum { 41b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_8000, 42b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_11025, 43b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_16000, 44b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_22050, 45b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_24000, 46b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_32000, 47b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_44100, 48b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_48000, 49b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_Mask = 7 50b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten}; 51b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten 52b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kastenenum { 53b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_1 = 0x08, 54b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_2 = 0x10, 55b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_Mask = 0x18 56b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten}; 57b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten 5872e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastenunsigned Format_sampleRate(const NBAIO_Format& format) 59010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 606e0d67d7b496ce17c0970a4ffd3a6f808860949cGlenn Kasten if (!Format_isValid(format)) { 61b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 0; 62b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 632b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten return format.mSampleRate; 64010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 65010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 6672e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastenunsigned Format_channelCount(const NBAIO_Format& format) 67010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 686e0d67d7b496ce17c0970a4ffd3a6f808860949cGlenn Kasten if (!Format_isValid(format)) { 69b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 0; 70b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 712b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten return format.mChannelCount; 72010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 73010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 74f95a3c4122d67273d930c7d83c3df99f136603edGlenn KastenNBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount, 752b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten audio_format_t format) 76010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 772b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) { 78b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_Invalid; 79b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 80c4b8b32dec91a11a83d0a7ab49747606d16d39a5Glenn Kasten NBAIO_Format ret; 812b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten ret.mSampleRate = sampleRate; 822b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten ret.mChannelCount = channelCount; 832b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten ret.mFormat = format; 842b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten ret.mFrameSize = audio_is_linear_pcm(format) ? 852b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t); 86c4b8b32dec91a11a83d0a7ab49747606d16d39a5Glenn Kasten return ret; 87010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 88010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 89010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// This is a default implementation; it is expected that subclasses will optimize this. 90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 91010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (!mNegotiated) { 93010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 94010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 95010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten static const size_t maxBlock = 32; 96010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t frameSize = Format_frameSize(mFormat); 97010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 98010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // double guarantees alignment for stack similar to what malloc() gives for heap 99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (block == 0 || block > maxBlock) { 100010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten block = maxBlock; 101010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 102010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 103010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t accumulator = 0; 104010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten while (accumulator < total) { 105010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t count = total - accumulator; 106010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (count > block) { 107010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = block; 108010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 109010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t ret = via(user, buffer, count); 110010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 111010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= count); 112010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t maxRet = ret; 113010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ret = write(buffer, maxRet); 114010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 115010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= maxRet); 116010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten accumulator += ret; 117010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten continue; 118010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 119010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 120010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator > 0 ? accumulator : ret; 121010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 122010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator; 123010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 124010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 125010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// This is a default implementation; it is expected that subclasses will optimize this. 1262c3b2da3049627264b7c6b449a1622f002210f03John Grossmanssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 1272c3b2da3049627264b7c6b449a1622f002210f03John Grossman int64_t readPTS, size_t block) 128010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 129010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (!mNegotiated) { 130010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 131010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 132010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten static const size_t maxBlock = 32; 133010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t frameSize = Format_frameSize(mFormat); 134010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 135010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // double guarantees alignment for stack similar to what malloc() gives for heap 136010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (block == 0 || block > maxBlock) { 137010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten block = maxBlock; 138010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 139010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 140010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t accumulator = 0; 141010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten while (accumulator < total) { 142010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t count = total - accumulator; 143010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (count > block) { 144010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = block; 145010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 1462c3b2da3049627264b7c6b449a1622f002210f03John Grossman ssize_t ret = read(buffer, count, readPTS); 147010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 148010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= count); 149010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t maxRet = ret; 1502c3b2da3049627264b7c6b449a1622f002210f03John Grossman ret = via(user, buffer, maxRet, readPTS); 151010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 152010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= maxRet); 153010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten accumulator += ret; 154010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten continue; 155010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 156010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 157010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator > 0 ? accumulator : ret; 158010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 159010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator; 160010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 161010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 162010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// Default implementation that only accepts my mFormat 163010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 164010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Format counterOffers[], size_t& numCounterOffers) 165010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 166010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 167010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten offers, numOffers, counterOffers, numCounterOffers); 1686e0d67d7b496ce17c0970a4ffd3a6f808860949cGlenn Kasten if (Format_isValid(mFormat)) { 169010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten for (size_t i = 0; i < numOffers; ++i) { 1706e0d67d7b496ce17c0970a4ffd3a6f808860949cGlenn Kasten if (Format_isEqual(offers[i], mFormat)) { 171010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mNegotiated = true; 172010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return i; 173010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 174010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 175010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (numCounterOffers > 0) { 176010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten counterOffers[0] = mFormat; 177010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 178010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten numCounterOffers = 1; 179010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } else { 180010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten numCounterOffers = 0; 181010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 182010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 183010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 184010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 185cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kastenbool Format_isValid(const NBAIO_Format& format) 186cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten{ 1872b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten return format.mSampleRate != 0 && format.mChannelCount != 0 && 1882b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0; 189cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten} 190cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten 191cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kastenbool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2) 192cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten{ 1932b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten return format1.mSampleRate == format2.mSampleRate && 1942b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat && 1952b7b910f4b417ab3930379298f538d0dfc857e88Glenn Kasten format1.mFrameSize == format2.mFrameSize; 196cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten} 197cc1e0e807ee9a9f163a4685cbd6efd6ae55849cfGlenn Kasten 198010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 199