• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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