blob: 00d201762873fd24ad324caccfd1e623a8845ec3 [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
25size_t Format_frameSize(NBAIO_Format format)
26{
27 switch (format) {
28 case Format_SR44_1_C2_I16:
29 case Format_SR48_C2_I16:
30 return 2 * sizeof(short);
31 case Format_SR44_1_C1_I16:
32 case Format_SR48_C1_I16:
33 return 1 * sizeof(short);
34 case Format_Invalid:
35 default:
36 return 0;
37 }
38}
39
40size_t Format_frameBitShift(NBAIO_Format format)
41{
42 switch (format) {
43 case Format_SR44_1_C2_I16:
44 case Format_SR48_C2_I16:
45 return 2; // 1 << 2 == 2 * sizeof(short)
46 case Format_SR44_1_C1_I16:
47 case Format_SR48_C1_I16:
48 return 1; // 1 << 1 == 1 * sizeof(short)
49 case Format_Invalid:
50 default:
51 return 0;
52 }
53}
54
55unsigned Format_sampleRate(NBAIO_Format format)
56{
57 switch (format) {
58 case Format_SR44_1_C1_I16:
59 case Format_SR44_1_C2_I16:
60 return 44100;
61 case Format_SR48_C1_I16:
62 case Format_SR48_C2_I16:
63 return 48000;
64 case Format_Invalid:
65 default:
66 return 0;
67 }
68}
69
70unsigned Format_channelCount(NBAIO_Format format)
71{
72 switch (format) {
73 case Format_SR44_1_C1_I16:
74 case Format_SR48_C1_I16:
75 return 1;
76 case Format_SR44_1_C2_I16:
77 case Format_SR48_C2_I16:
78 return 2;
79 case Format_Invalid:
80 default:
81 return 0;
82 }
83}
84
85NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
86{
87 if (sampleRate == 44100 && channelCount == 2) return Format_SR44_1_C2_I16;
88 if (sampleRate == 48000 && channelCount == 2) return Format_SR48_C2_I16;
89 if (sampleRate == 44100 && channelCount == 1) return Format_SR44_1_C1_I16;
90 if (sampleRate == 48000 && channelCount == 1) return Format_SR48_C1_I16;
91 return Format_Invalid;
92}
93
94// This is a default implementation; it is expected that subclasses will optimize this.
95ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
96{
97 if (!mNegotiated) {
98 return (ssize_t) NEGOTIATE;
99 }
100 static const size_t maxBlock = 32;
101 size_t frameSize = Format_frameSize(mFormat);
102 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
103 // double guarantees alignment for stack similar to what malloc() gives for heap
104 if (block == 0 || block > maxBlock) {
105 block = maxBlock;
106 }
107 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
108 size_t accumulator = 0;
109 while (accumulator < total) {
110 size_t count = total - accumulator;
111 if (count > block) {
112 count = block;
113 }
114 ssize_t ret = via(user, buffer, count);
115 if (ret > 0) {
116 ALOG_ASSERT((size_t) ret <= count);
117 size_t maxRet = ret;
118 ret = write(buffer, maxRet);
119 if (ret > 0) {
120 ALOG_ASSERT((size_t) ret <= maxRet);
121 accumulator += ret;
122 continue;
123 }
124 }
125 return accumulator > 0 ? accumulator : ret;
126 }
127 return accumulator;
128}
129
130// This is a default implementation; it is expected that subclasses will optimize this.
John Grossman2c3b2da2012-08-02 17:08:54 -0700131ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
132 int64_t readPTS, size_t block)
Glenn Kasten01066232012-02-27 11:50:44 -0800133{
134 if (!mNegotiated) {
135 return (ssize_t) NEGOTIATE;
136 }
137 static const size_t maxBlock = 32;
138 size_t frameSize = Format_frameSize(mFormat);
139 ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
140 // double guarantees alignment for stack similar to what malloc() gives for heap
141 if (block == 0 || block > maxBlock) {
142 block = maxBlock;
143 }
144 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
145 size_t accumulator = 0;
146 while (accumulator < total) {
147 size_t count = total - accumulator;
148 if (count > block) {
149 count = block;
150 }
John Grossman2c3b2da2012-08-02 17:08:54 -0700151 ssize_t ret = read(buffer, count, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800152 if (ret > 0) {
153 ALOG_ASSERT((size_t) ret <= count);
154 size_t maxRet = ret;
John Grossman2c3b2da2012-08-02 17:08:54 -0700155 ret = via(user, buffer, maxRet, readPTS);
Glenn Kasten01066232012-02-27 11:50:44 -0800156 if (ret > 0) {
157 ALOG_ASSERT((size_t) ret <= maxRet);
158 accumulator += ret;
159 continue;
160 }
161 }
162 return accumulator > 0 ? accumulator : ret;
163 }
164 return accumulator;
165}
166
167// Default implementation that only accepts my mFormat
168ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
169 NBAIO_Format counterOffers[], size_t& numCounterOffers)
170{
171 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
172 offers, numOffers, counterOffers, numCounterOffers);
173 if (mFormat != Format_Invalid) {
174 for (size_t i = 0; i < numOffers; ++i) {
175 if (offers[i] == mFormat) {
176 mNegotiated = true;
177 return i;
178 }
179 }
180 if (numCounterOffers > 0) {
181 counterOffers[0] = mFormat;
182 }
183 numCounterOffers = 1;
184 } else {
185 numCounterOffers = 0;
186 }
187 return (ssize_t) NEGOTIATE;
188}
189
190} // namespace android