• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace android {
24 
Format_frameSize(const NBAIO_Format & format)25 size_t Format_frameSize(const NBAIO_Format& format)
26 {
27     return format.mFrameSize;
28 }
29 
30 const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
31 
Format_sampleRate(const NBAIO_Format & format)32 unsigned Format_sampleRate(const NBAIO_Format& format)
33 {
34     if (!Format_isValid(format)) {
35         return 0;
36     }
37     return format.mSampleRate;
38 }
39 
Format_channelCount(const NBAIO_Format & format)40 unsigned Format_channelCount(const NBAIO_Format& format)
41 {
42     if (!Format_isValid(format)) {
43         return 0;
44     }
45     return format.mChannelCount;
46 }
47 
Format_from_SR_C(unsigned sampleRate,unsigned channelCount,audio_format_t format)48 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
49         audio_format_t format)
50 {
51     if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
52         return Format_Invalid;
53     }
54     NBAIO_Format ret;
55     ret.mSampleRate = sampleRate;
56     ret.mChannelCount = channelCount;
57     ret.mFormat = format;
58     ret.mFrameSize = audio_bytes_per_frame(channelCount, format);
59     return ret;
60 }
61 
62 // This is a default implementation; it is expected that subclasses will optimize this.
writeVia(writeVia_t via,size_t total,void * user,size_t block)63 ssize_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.
readVia(readVia_t via,size_t total,void * user,size_t block)99 ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, size_t block)
100 {
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         }
118         ssize_t ret = read(buffer, count);
119         if (ret > 0) {
120             ALOG_ASSERT((size_t) ret <= count);
121             size_t maxRet = ret;
122             ret = via(user, buffer, maxRet);
123             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
negotiate(const NBAIO_Format offers[],size_t numOffers,NBAIO_Format counterOffers[],size_t & numCounterOffers)135 ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
136                                   NBAIO_Format counterOffers[], size_t& numCounterOffers)
137 {
138     ALOGV("negotiate offers=%p numOffers=%zu countersOffers=%p numCounterOffers=%zu",
139             offers, numOffers, counterOffers, numCounterOffers);
140     if (Format_isValid(mFormat)) {
141         for (size_t i = 0; i < numOffers; ++i) {
142             if (Format_isEqual(offers[i], mFormat)) {
143                 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 
Format_isValid(const NBAIO_Format & format)157 bool Format_isValid(const NBAIO_Format& format)
158 {
159     return format.mSampleRate != 0 && format.mChannelCount != 0 &&
160             format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
161 }
162 
Format_isEqual(const NBAIO_Format & format1,const NBAIO_Format & format2)163 bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
164 {
165     return format1.mSampleRate == format2.mSampleRate &&
166             format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
167             format1.mFrameSize == format2.mFrameSize;
168 }
169 
170 }   // namespace android
171