blob: 70ced6e729344bdf78d7949e3a0209488bd98778 [file] [log] [blame]
Cody Schuffelen134ff032019-11-22 00:25:32 -08001/*
2 * Copyright (C) 2016 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#pragma once
17
18#include <memory>
19
20#include "common/libs/utils/simulated_buffer.h"
21#include "common/vsoc/lib/vsoc_audio_message.h"
22#include "guest/hals/audio/legacy/audio_hal.h"
23
24namespace cvd {
25
26// Defines static callback functions for the audio_stream and audio_stream_out
27// interfaces in libhardware/include/hardware/audio.h
28//
29// Where the is a conflict the comments there apply.
30// By default these methods return 0 on success -<errno> for failure.
31class GceAudioOutputStream : public audio_stream_out {
32 public:
33 // Factory method for a new output stream.
34 static int Open(GceAudio* dev, audio_io_handle_t handle,
35 audio_devices_t devices, audio_output_flags_t flags,
36 audio_config* config, uint32_t stream_number,
37 GceAudioOutputStream** stream_out);
38
39 gce_audio_message GetStreamDescriptor(
40 gce_audio_message::message_t message_type) const {
41 gce_audio_message rval = message_header_;
42 rval.total_size = sizeof(rval);
43 rval.header_size = sizeof(rval);
44 rval.message_type = message_type;
45 rval.num_frames_presented = 0;
46 rval.num_frames_accepted = 0;
47 return rval;
48 }
49
50 // Method from audio_stream, listed in order of appearance.
51 // TODO(ghartman): Consider moving these if they could be shared with
52 // gce_audio_input_stream.
53
54
55 // Returns the sampling rate in Hz - eg. 44100.
56 uint32_t GetSampleRate() const {
57 return message_header_.frame_rate;
58 }
59
60 // Sets the sample rate
61 // AUDIO_PARAMETER_STREAM_SAMPLING_RATE
62 int SetSampleRate(uint32_t sample_rate) {
63 if (sample_rate != message_header_.frame_rate) {
64 message_header_.frame_rate = sample_rate;
65 // TODO(ghartman): The output buffer should be quantized at about 192
66 // bytes for better fidelity. Do this by passing
67 // frame_rate * frame_size / 192 and then rescaling the outputs.
68 // Or we could always create a quantized wrapper of the buffer...
69 buffer_.reset(
70 new SimulatedOutputBuffer(
71 sample_rate, GetBufferSize() / frame_size_));
72 }
73 return 0;
74 }
75
76 // Returns the size of input/output buffer in bytes for this stream.
77 // eg. 4800.
78 // It should be a multiple of the frame size. See also GetInputBufferSize.
79 size_t GetBufferSize() const {
80 return kOutBufferSize;
81 }
82
83 // Returns the channel mask -
84 // e.g. AUDIO_CHANNEL_OUT_STEREO or AUDIO_CHANNEL_IN_STEREO
85 audio_channel_mask_t GetChannels() const {
86 return message_header_.channel_mask;
87 }
88
89 // Returns the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT
90 audio_format_t GetFormat() const {
91 return message_header_.format;
92 }
93
94 // Sets the audio format.
95 // Unused as of JB - use set_parameters with key
96 // AUDIO_PARAMETER_STREAM_FORMAT
97 int SetFormat(audio_format_t format) {
98 message_header_.format = format;
99 return 0;
100 }
101
102 // Puts the audio hardware input/output into standby mode.
103 // Driver should exit from standby mode at the next I/O operation.
104 // Returns 0 on success and <0 on failure.
105 // TODO(ghartman): This should reset some of the frame counts.
106 int Standby() {
107 return 0;
108 }
109
110 // dumps the state of the audio hardware to the given fd.
111 // This information can be retrieved using the dumpsys utility.
112 int Dump(int fd) const;
113
114 // Returns the set of device(s) which this stream is connected to.
115 // TODO(ghartman): Implement this.
116 audio_devices_t GetDevice() const { return device_; }
117
118 // Not directly called from JB forward.
119 // Called indirectly from SetParameters with the key
120 // AUDIO_PARAMETER_STREAM_ROUTING
121 int SetDevice(audio_devices_t device) { device_ = device; return 0; }
122
123 // Sets audio stream parameters. The function accepts a list of
124 // parameter key value pairs in the form: key1=value1;key2=value2;...
125 //
126 // Some keys are reserved for standard parameters (See AudioParameter class)
127 //
128 // If the implementation does not accept a parameter change while
129 // the output is active but the parameter is acceptable otherwise, it must
130 // return -ENOSYS.
131 //
132 // The audio flinger will put the stream in standby and then change the
133 // parameter value.
134 int SetParameters(const char* kv_pairs);
135
136 // Gets audio stream parameters. The function accepts a list of
137 // keys in the form: key1=value1;key2=value2;...
138 //
139 // Returns a pointer to a heap allocated string. The caller is responsible
140 // for freeing the memory for it using free().
141 // TODO(ghartman): Implement this.
142 char* GetParameters(const char* keys) const;
143
144 // TODO(ghartman): Implement this.
145 int AddAudioEffect(effect_handle_t /*effect*/) const {
146 static unsigned int printed = 0; // printed every 2^32-th call.
147 ALOGE_IF(!printed++, "%s: not implemented", __FUNCTION__);
148 return 0;
149 }
150
151 // TODO(ghartman): Implement this.
152 int RemoveAudioEffect(effect_handle_t /*effect*/) const {
153 static unsigned int printed = 0; // printed every 2^32-th call.
154 ALOGE_IF(!printed++, "%s: not implemented", __FUNCTION__);
155 return 0;
156 }
157
158 // Methods defined in audio_stream_out
159
160 // Returns the audio hardware driver estimated latency in milliseconds.
161 // TODO(ghartman): Calculate this based on the format and the quantum.
162 uint32_t GetLatency() const {
163 return kOutLatency;
164 }
165
166 // Use this method in situations where audio mixing is done in the
167 // hardware. This method serves as a direct interface with hardware,
168 // allowing you to directly set the volume as apposed to via the framework.
169 // This method might produce multiple PCM outputs or hardware accelerated
170 // codecs, such as MP3 or AAC.
171 //
172 // Note that GCE simulates hardware mixing.
173 int SetVolume(float left_volume, float right_volume) {
174 left_volume_ = left_volume;
175 right_volume_ = right_volume;
176 return 0;
177 }
178
179 // Write audio buffer to driver. Returns number of bytes written, or a
180 // negative android::status_t. If at least one frame was written successfully prior
181 // to the error the driver will return that successful (short) byte count
182 // and then return an error in the subsequent call.
183 //
184 // If SetCallback() has previously been called to enable non-blocking mode
185 // the Write() is not allowed to block. It must write only the number of
186 // bytes that currently fit in the driver/hardware buffer and then return
187 // this byte count. If this is less than the requested write size the
188 // callback function must be called when more space is available in the
189 // driver/hardware buffer.
190 ssize_t Write(const void* buffer, size_t bytes);
191
192 // Returns the number of audio frames written by the audio dsp to DAC since
193 // the output has exited standby
194 // TODO(ghartman): Implement zeroing this in Standby().
195 int GetRenderPosition(uint32_t* dsp_frames) const;
196
197 // Gets the local time at which the next write to the audio driver will be
198 // presented. The units are microseconds, where the epoch is decided by the
199 // local audio HAL.
200 //
201 // The GCE implementation uses CLOCK_MONOTONIC, which also happens to line
202 // up with LocalTime.
203 int GetNextWriteTimestamp(int64_t*) const;
204
205 // Turns on non-blocking mode and sets the callback function for notifying
206 // completion of non-blocking write and drain.
207 // Calling this function implies that all future Write() and Drain()
208 // must be non-blocking and use the callback to signal completion.
209 //
210 // TODO(ghartman): Implement this URGENTLY.
211 //
212 // int SetCallback(stream_callback_t callback, void *cookie);
213
214 // Notifies to the audio driver to stop playback however the queued buffers
215 // are retained by the hardware. Useful for implementing pause/resume. Empty
216 // implementation if not supported however should be implemented for hardware
217 // with non-trivial latency. In the pause state audio hardware could still be
218 // using power. User may consider calling suspend after a timeout.
219 //
220 // Implementation of this function is mandatory for offloaded playback.
221 //
222 // TODO(ghartman): Implement this URGENTLY. There is already support in
223 // SimulatedBuffer.
224 // int Pause();
225
226 // Notifies to the audio driver to resume playback following a pause.
227 // Returns error if called without matching pause.
228 //
229 // Implementation of this function is mandatory for offloaded playback.
230 //
231 // TODO(ghartman): Implement this URGENTLY.
232 //
233 // int Resume();
234
235 // Requests notification when data buffered by the driver/hardware has
236 // been played. If set_callback() has previously been called to enable
237 // non-blocking mode, the drain() must not block, instead it should return
238 // quickly and completion of the drain is notified through the callback.
239 // If set_callback() has not been called, the drain() must block until
240 // completion.
241 //
242 // If type==AUDIO_DRAIN_ALL, the drain completes when all previously written
243 // data has been played.
244 //
245 // If type==AUDIO_DRAIN_EARLY_NOTIFY, the drain completes shortly before all
246 // data for the current track has played to allow time for the framework
247 // to perform a gapless track switch.
248 //
249 // Drain must return immediately on stop() and flush() call
250 //
251 // Implementation of this function is mandatory for offloaded playback.
252 //
253 // TODO(ghartman): Implement this URGENTLY.
254 //
255 // int Drain(audio_drain_type_t type);
256
257 // Notifies to the audio driver to flush the queued data. Stream must already
258 // be paused before calling Flush().
259 //
260 // Implementation of this function is mandatory for offloaded playback.
261 //
262 // TODO(ghartman): Implement this URGENTLY.
263 //
264 // int Flush();
265
266 // Returns a recent count of the number of audio frames presented to an
267 // external observer. This excludes frames which have been written but are
268 // still in the pipeline.
269 //
270 // The count is not reset to zero when output enters standby.
271 // Also returns the value of CLOCK_MONOTONIC as of this presentation count.
272 // The returned count is expected to be 'recent',
273 // but does not need to be the most recent possible value.
274 // However, the associated time should correspond to whatever count is
275 // returned.
276 //
277 // Example: assume that N+M frames have been presented, where M is a
278 // 'small' number.
279 // Then it is permissible to return N instead of N+M,
280 // and the timestamp should correspond to N rather than N+M.
281 // The terms 'recent' and 'small' are not defined.
282 // They reflect the quality of the implementation.
283 //
284 // 3.0 and higher only.
285 //
286 // TODO(ghartman): Implement this URGENTLY.
287 //
288 // int GetPresentationPosition(uint64_t *frames, struct timespec *timestamp);
289
290 private:
291 // If key is present in query, add key=value; to reply.
292 // query should be pointer to const, but the str_parms functions aren't
293 // const-correct, so neither is this.
294 static void AddIntIfKeyPresent(
295 /*const*/ str_parms* query, str_parms* reply, const char* key, int value);
296
297
298 explicit GceAudioOutputStream(cvd::GceAudio*);
299
300 static const size_t kOutBufferSize = 3840;
301 static const size_t kOutLatency = 2;
302
303 gce_audio_message message_header_;
304 std::unique_ptr<SimulatedOutputBuffer> buffer_;
305 cvd::GceAudio *dev_;
306 audio_devices_t device_;
307 size_t frame_size_;
308 size_t frame_count_;
309 float left_volume_;
310 float right_volume_;
311};
312
313}