blob: 3abc35e89a83a0dbedece6e72a50cc84de9465e3 [file] [log] [blame]
Glenn Kasten01066232012-02-27 11:50:44 -08001/*
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>
Glenn Kasten2dd4bdd2012-08-29 11:10:32 -070021#include <media/nbaio/NBAIO.h>
Glenn Kasten01066232012-02-27 11:50:44 -080022
23namespace android {
24
Glenn Kasten72e54af2014-01-31 09:37:35 -080025size_t Format_frameSize(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080026{
Glenn Kasten983f0572014-03-06 08:23:11 -080027 return format.mFrameSize;
Glenn Kasten01066232012-02-27 11:50:44 -080028}
29
Glenn Kasten2b7b9102014-03-06 08:02:51 -080030const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
Glenn Kasten51d53cd2014-01-31 09:38:33 -080031
Glenn Kasten72e54af2014-01-31 09:37:35 -080032unsigned Format_sampleRate(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080033{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080034 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070035 return 0;
36 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080037 return format.mSampleRate;
Glenn Kasten01066232012-02-27 11:50:44 -080038}
39
Glenn Kasten72e54af2014-01-31 09:37:35 -080040unsigned Format_channelCount(const NBAIO_Format& format)
Glenn Kasten01066232012-02-27 11:50:44 -080041{
Glenn Kasten6e0d67d2014-01-31 09:41:08 -080042 if (!Format_isValid(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070043 return 0;
44 }
Glenn Kasten2b7b9102014-03-06 08:02:51 -080045 return format.mChannelCount;
Glenn Kasten01066232012-02-27 11:50:44 -080046}
47
Glenn Kastenf95a3c42014-03-06 07:59:49 -080048NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
Glenn Kasten2b7b9102014-03-06 08:02:51 -080049 audio_format_t format)
Glenn Kasten01066232012-02-27 11:50:44 -080050{
Glenn Kasten2b7b9102014-03-06 08:02:51 -080051 if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
Glenn Kastenb64497e2012-10-01 09:47:30 -070052 return Format_Invalid;
53 }
Glenn Kastenc4b8b322014-01-31 09:39:01 -080054 NBAIO_Format ret;
Glenn Kasten2b7b9102014-03-06 08:02:51 -080055 ret.mSampleRate = sampleRate;
56 ret.mChannelCount = channelCount;
57 ret.mFormat = format;
Dean Wheatleyd883e302023-10-20 06:11:43 +110058 ret.mFrameSize = audio_bytes_per_frame(channelCount, format);
Glenn Kastenc4b8b322014-01-31 09:39:01 -080059 return ret;
Glenn Kasten01066232012-02-27 11:50:44 -080060}
61
62// This is a default implementation; it is expected that subclasses will optimize this.
63ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
64{
65 if (!mNegotiated) {
66 return (ssize_t) NEGOTIATE;
67 }
68 static const size_t maxBlock = 32;
69 size_t frameSize = Format_frameSize(mFormat);
70 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
71 // double guarantees alignment for stack similar to what malloc() gives for heap
72 if (block == 0 || block > maxBlock) {
73 block = maxBlock;
74 }
75 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
76 size_t accumulator = 0;
77 while (accumulator < total) {
78 size_t count = total - accumulator;
79 if (count > block) {
80 count = block;
81 }
82 ssize_t ret = via(user, buffer, count);
83 if (ret > 0) {
84 ALOG_ASSERT((size_t) ret <= count);
85 size_t maxRet = ret;
86 ret = write(buffer, maxRet);
87 if (ret > 0) {
88 ALOG_ASSERT((size_t) ret <= maxRet);
89 accumulator += ret;
90 continue;
91 }
92 }
93 return accumulator > 0 ? accumulator : ret;
94 }
95 return accumulator;
96}
97
98// This is a default implementation; it is expected that subclasses will optimize this.
Glenn Kastend79072e2016-01-06 08:41:20 -080099ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800100{
101 if (!mNegotiated) {
102 return (ssize_t) NEGOTIATE;
103 }
104 static const size_t maxBlock = 32;
105 size_t frameSize = Format_frameSize(mFormat);
106 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
107 // double guarantees alignment for stack similar to what malloc() gives for heap
108 if (block == 0 || block > maxBlock) {
109 block = maxBlock;
110 }
111 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
112 size_t accumulator = 0;
113 while (accumulator < total) {
114 size_t count = total - accumulator;
115 if (count > block) {
116 count = block;
117 }
Glenn Kastend79072e2016-01-06 08:41:20 -0800118 ssize_t ret = read(buffer, count);
Glenn Kasten01066232012-02-27 11:50:44 -0800119 if (ret > 0) {
120 ALOG_ASSERT((size_t) ret <= count);
121 size_t maxRet = ret;
Glenn Kastend79072e2016-01-06 08:41:20 -0800122 ret = via(user, buffer, maxRet);
Glenn Kasten01066232012-02-27 11:50:44 -0800123 if (ret > 0) {
124 ALOG_ASSERT((size_t) ret <= maxRet);
125 accumulator += ret;
126 continue;
127 }
128 }
129 return accumulator > 0 ? accumulator : ret;
130 }
131 return accumulator;
132}
133
134// Default implementation that only accepts my mFormat
135ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
136 NBAIO_Format counterOffers[], size_t& numCounterOffers)
137{
Mark Salyzyn0f6a0432014-06-18 16:32:00 -0700138 ALOGV("negotiate offers=%p numOffers=%zu countersOffers=%p numCounterOffers=%zu",
Glenn Kasten01066232012-02-27 11:50:44 -0800139 offers, numOffers, counterOffers, numCounterOffers);
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800140 if (Format_isValid(mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800141 for (size_t i = 0; i < numOffers; ++i) {
Glenn Kasten6e0d67d2014-01-31 09:41:08 -0800142 if (Format_isEqual(offers[i], mFormat)) {
Glenn Kasten01066232012-02-27 11:50:44 -0800143 mNegotiated = true;
144 return i;
145 }
146 }
147 if (numCounterOffers > 0) {
148 counterOffers[0] = mFormat;
149 }
150 numCounterOffers = 1;
151 } else {
152 numCounterOffers = 0;
153 }
154 return (ssize_t) NEGOTIATE;
155}
156
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800157bool Format_isValid(const NBAIO_Format& format)
158{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800159 return format.mSampleRate != 0 && format.mChannelCount != 0 &&
160 format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800161}
162
163bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
164{
Glenn Kasten2b7b9102014-03-06 08:02:51 -0800165 return format1.mSampleRate == format2.mSampleRate &&
166 format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
167 format1.mFrameSize == format2.mFrameSize;
Glenn Kastencc1e0e82014-01-31 09:48:42 -0800168}
169
Glenn Kasten01066232012-02-27 11:50:44 -0800170} // namespace android