1 /*
2 **
3 ** Copyright 2015, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #define LOG_TAG "AudioFlinger"
19 //#define LOG_NDEBUG 0
20 
21 #include <media/audiohal/DeviceHalInterface.h>
22 #include <media/audiohal/StreamHalInterface.h>
23 #include <system/audio.h>
24 #include <utils/Log.h>
25 
26 #include "AudioHwDevice.h"
27 #include "AudioStreamOut.h"
28 
29 namespace android {
30 
31 // ----------------------------------------------------------------------------
AudioStreamOut(AudioHwDevice * dev,audio_output_flags_t flags)32 AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
33         : audioHwDev(dev)
34         , stream(NULL)
35         , flags(flags)
36         , mFramesWritten(0)
37         , mFramesWrittenAtStandby(0)
38         , mRenderPosition(0)
39         , mRateMultiplier(1)
40         , mHalFormatHasProportionalFrames(false)
41         , mHalFrameSize(0)
42 {
43 }
44 
~AudioStreamOut()45 AudioStreamOut::~AudioStreamOut()
46 {
47 }
48 
hwDev() const49 sp<DeviceHalInterface> AudioStreamOut::hwDev() const
50 {
51     return audioHwDev->hwDevice();
52 }
53 
getRenderPosition(uint64_t * frames)54 status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
55 {
56     if (stream == 0) {
57         return NO_INIT;
58     }
59 
60     uint32_t halPosition = 0;
61     status_t status = stream->getRenderPosition(&halPosition);
62     if (status != NO_ERROR) {
63         return status;
64     }
65 
66     // Maintain a 64-bit render position using the 32-bit result from the HAL.
67     // This delta calculation relies on the arithmetic overflow behavior
68     // of integers. For example (100 - 0xFFFFFFF0) = 116.
69     uint32_t truncatedPosition = (uint32_t)mRenderPosition;
70     int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition);
71     if (deltaHalPosition > 0) {
72         mRenderPosition += deltaHalPosition;
73     }
74     // Scale from HAL sample rate to application rate.
75     *frames = mRenderPosition / mRateMultiplier;
76 
77     return status;
78 }
79 
80 // return bottom 32-bits of the render position
getRenderPosition(uint32_t * frames)81 status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
82 {
83     uint64_t position64 = 0;
84     status_t status = getRenderPosition(&position64);
85     if (status == NO_ERROR) {
86         *frames = (uint32_t)position64;
87     }
88     return status;
89 }
90 
getPresentationPosition(uint64_t * frames,struct timespec * timestamp)91 status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
92 {
93     if (stream == 0) {
94         return NO_INIT;
95     }
96 
97     uint64_t halPosition = 0;
98     status_t status = stream->getPresentationPosition(&halPosition, timestamp);
99     if (status != NO_ERROR) {
100         return status;
101     }
102 
103     // Adjust for standby using HAL rate frames.
104     // Only apply this correction if the HAL is getting PCM frames.
105     if (mHalFormatHasProportionalFrames) {
106         uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
107                 0 : (halPosition - mFramesWrittenAtStandby);
108         // Scale from HAL sample rate to application rate.
109         *frames = adjustedPosition / mRateMultiplier;
110     } else {
111         // For offloaded MP3 and other compressed formats.
112         *frames = halPosition;
113     }
114 
115     return status;
116 }
117 
open(audio_io_handle_t handle,audio_devices_t devices,struct audio_config * config,const char * address)118 status_t AudioStreamOut::open(
119         audio_io_handle_t handle,
120         audio_devices_t devices,
121         struct audio_config *config,
122         const char *address)
123 {
124     sp<StreamOutHalInterface> outStream;
125 
126     audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
127                 ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
128                 : flags;
129 
130     int status = hwDev()->openOutputStream(
131             handle,
132             devices,
133             customFlags,
134             config,
135             address,
136             &outStream);
137     ALOGV("AudioStreamOut::open(), HAL returned "
138             " stream %p, sampleRate %d, Format %#x, "
139             "channelMask %#x, status %d",
140             outStream.get(),
141             config->sample_rate,
142             config->format,
143             config->channel_mask,
144             status);
145 
146     // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare
147     // it as PCM then it will probably work.
148     if (status != NO_ERROR && config->format == AUDIO_FORMAT_IEC61937) {
149         struct audio_config customConfig = *config;
150         customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
151 
152         status = hwDev()->openOutputStream(
153                 handle,
154                 devices,
155                 customFlags,
156                 &customConfig,
157                 address,
158                 &outStream);
159         ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
160     }
161 
162     if (status == NO_ERROR) {
163         stream = outStream;
164         mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
165         status = stream->getFrameSize(&mHalFrameSize);
166     }
167 
168     return status;
169 }
170 
getFormat() const171 audio_format_t AudioStreamOut::getFormat() const
172 {
173     audio_format_t result;
174     return stream->getFormat(&result) == OK ? result : AUDIO_FORMAT_INVALID;
175 }
176 
getSampleRate() const177 uint32_t AudioStreamOut::getSampleRate() const
178 {
179     uint32_t result;
180     return stream->getSampleRate(&result) == OK ? result : 0;
181 }
182 
getChannelMask() const183 audio_channel_mask_t AudioStreamOut::getChannelMask() const
184 {
185     audio_channel_mask_t result;
186     return stream->getChannelMask(&result) == OK ? result : AUDIO_CHANNEL_INVALID;
187 }
188 
flush()189 int AudioStreamOut::flush()
190 {
191     mRenderPosition = 0;
192     mFramesWritten = 0;
193     mFramesWrittenAtStandby = 0;
194     status_t result = stream->flush();
195     return result != INVALID_OPERATION ? result : NO_ERROR;
196 }
197 
standby()198 int AudioStreamOut::standby()
199 {
200     mRenderPosition = 0;
201     mFramesWrittenAtStandby = mFramesWritten;
202     return stream->standby();
203 }
204 
write(const void * buffer,size_t numBytes)205 ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
206 {
207     size_t bytesWritten;
208     status_t result = stream->write(buffer, numBytes, &bytesWritten);
209     if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
210         mFramesWritten += bytesWritten / mHalFrameSize;
211     }
212     return result == OK ? bytesWritten : result;
213 }
214 
215 } // namespace android
216