Home | History | Annotate | Download | only in audio
      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/vsoc/lib/vsoc_audio_message.h"
     21 #include "guest/hals/audio/audio_hal.h"
     22 #include "guest/hals/audio/simulated_buffer.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 
     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 }
    314