1 /* 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 24 namespace 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. 31 class 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 GetStreamDescriptor(gce_audio_message::message_t message_type)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. GetSampleRate()56 uint32_t GetSampleRate() const { 57 return message_header_.frame_rate; 58 } 59 60 // Sets the sample rate 61 // AUDIO_PARAMETER_STREAM_SAMPLING_RATE SetSampleRate(uint32_t sample_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. GetBufferSize()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 GetChannels()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 GetFormat()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 SetFormat(audio_format_t 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. Standby()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. GetDevice()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 SetDevice(audio_devices_t device)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. AddAudioEffect(effect_handle_t)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. RemoveAudioEffect(effect_handle_t)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. GetLatency()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. SetVolume(float left_volume,float right_volume)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 } 314