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 
     17 #include <pthread.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <cstdint>
     21 
     22 extern "C"{
     23 #include <cutils/str_parms.h>
     24 }
     25 
     26 #include "common/libs/auto_resources/auto_resources.h"
     27 #include "common/libs/threads/thunkers.h"
     28 #include "guest/hals/audio/audio_hal.h"
     29 #include "guest/hals/audio/vsoc_audio.h"
     30 #include "guest/hals/audio/vsoc_audio_input_stream.h"
     31 #include "guest/libs/platform_support/api_level_fixes.h"
     32 
     33 namespace cvd {
     34 
     35 namespace {
     36 template <typename F> struct Thunker :
     37   ThunkerBase<audio_stream, GceAudioInputStream, F>{};
     38 template <typename F> struct InThunker :
     39   ThunkerBase<audio_stream_in, GceAudioInputStream, F>{};
     40 }
     41 
     42 #if defined(AUDIO_DEVICE_API_VERSION_3_0)
     43 static inline size_t GceAudioFrameSize(const audio_stream_in* s) {
     44   return audio_stream_in_frame_size(s);
     45 }
     46 #elif defined(AUDIO_DEVICE_API_VERSION_2_0)
     47 static inline size_t GceAudioFrameSize(const audio_stream_in* s) {
     48 
     49   return audio_stream_frame_size(&s->common);
     50 }
     51 #else
     52 static inline size_t GceAudioFrameSize(audio_stream_in* s) {
     53 
     54   return audio_stream_frame_size(&s->common);
     55 }
     56 #endif
     57 
     58 GceAudioInputStream::GceAudioInputStream(
     59     cvd::GceAudio* dev, audio_devices_t devices, const audio_config& config)
     60     : audio_stream_in(),
     61       dev_(dev),
     62       config_(config),
     63       gain_(0.0),
     64       device_(devices) {
     65   common.get_sample_rate =
     66       Thunker<uint32_t()>::call<&GceAudioInputStream::GetSampleRate>;
     67   common.set_sample_rate =
     68       Thunker<int(uint32_t)>::call<&GceAudioInputStream::SetSampleRate>;
     69   common.get_buffer_size =
     70       Thunker<size_t()>::call<&GceAudioInputStream::GetBufferSize>;
     71   common.get_channels =
     72       Thunker<audio_channel_mask_t()>::call<&GceAudioInputStream::GetChannels>;
     73   common.get_device =
     74       Thunker<audio_devices_t()>::call<&GceAudioInputStream::GetDevice>;
     75   common.set_device =
     76       Thunker<int(audio_devices_t)>::call<&GceAudioInputStream::SetDevice>;
     77   common.get_format =
     78       Thunker<audio_format_t()>::call<&GceAudioInputStream::GetFormat>;
     79   common.set_format =
     80       Thunker<int(audio_format_t)>::call<&GceAudioInputStream::SetFormat>;
     81   common.standby =
     82       Thunker<int()>::call<&GceAudioInputStream::Standby>;
     83   common.dump =
     84       Thunker<int(int)>::call<&GceAudioInputStream::Dump>;
     85   common.set_parameters = GceAudio::SetStreamParameters;
     86   common.get_parameters =
     87       Thunker<char*(const char *)>::call<&GceAudioInputStream::GetParameters>;
     88   common.add_audio_effect =
     89       Thunker<int(effect_handle_t)>::call<&GceAudioInputStream::AddAudioEffect>;
     90   common.remove_audio_effect = Thunker<int(effect_handle_t)>::call<
     91     &GceAudioInputStream::RemoveAudioEffect>;
     92   set_gain = InThunker<int(float)>::call<&GceAudioInputStream::SetGain>;
     93   read = InThunker<ssize_t(void*, size_t)>::call<
     94     &GceAudioInputStream::Read>;
     95   get_input_frames_lost = InThunker<uint32_t()>::call<
     96     &GceAudioInputStream::GetInputFramesLost>;
     97   frame_size_ = GceAudioFrameSize(this);
     98   buffer_model_.reset(
     99       new SimulatedInputBuffer(config_.sample_rate, GetBufferSize() /
    100                                frame_size_));
    101   reported_lost_frames_ = 0;
    102 }
    103 
    104 gce_audio_message GceAudioInputStream::GetStreamDescriptor(
    105     uint32_t stream_number, gce_audio_message::message_t event) {
    106   gce_audio_message rval;
    107   rval.message_type = event;
    108   rval.stream_number = stream_number;
    109   rval.frame_num = buffer_model_->GetCurrentItemNum();
    110   rval.time_presented =
    111       buffer_model_->GetLastUpdatedTime().SinceEpoch().GetTS();
    112   rval.frame_rate = config_.sample_rate;
    113   rval.channel_mask = config_.channel_mask;
    114   rval.format = config_.format;
    115   rval.frame_size = frame_size_;
    116   return rval;
    117 }
    118 
    119 int GceAudioInputStream::Open(GceAudio* dev,
    120                               audio_io_handle_t /*handle*/,
    121                               audio_devices_t devices,
    122                               const audio_config& config,
    123                               GceAudioInputStream** stream_in) {
    124   D("GceAudioInputStream::%s", __FUNCTION__);
    125   *stream_in = new GceAudioInputStream(dev, devices, config);
    126   return 0;
    127 }
    128 
    129 int GceAudioInputStream::SetFormat(audio_format_t format) {
    130   config_.format = format;
    131   frame_size_ = GceAudioFrameSize(this);
    132   return 0;
    133 }
    134 
    135 int GceAudioInputStream::Dump(int fd) const {
    136   D("GceAudioInputStream::%s", __FUNCTION__);
    137   VSOC_FDPRINTF(
    138       fd,
    139       "\tInputSteam Dump:\n"
    140       "\t\tsample rate: %u\n"
    141       "\t\tbuffer size: %zu\n"
    142       "\t\tchannel mask: %08x\n"
    143       "\t\tformat: %d\n"
    144       "\t\tdevice: %08x\n"
    145       "\t\taudio dev: %p\n\n",
    146       GetSampleRate(), GetBufferSize(),
    147       GetChannels(), GetFormat(), device_, dev_);
    148   return 0;
    149 }
    150 
    151 int GceAudioInputStream::SetSampleRate(uint32_t sample_rate) {
    152   if (sample_rate != config_.sample_rate) {
    153     config_.sample_rate = sample_rate;
    154     buffer_model_.reset(
    155         new SimulatedInputBuffer(sample_rate, GetBufferSize() / frame_size_));
    156     reported_lost_frames_ = 0;
    157   }
    158   return 0;
    159 }
    160 
    161 char* GceAudioInputStream::GetParameters(const char* keys) const {
    162   D("GceAudioInputStream::%s", __FUNCTION__);
    163   if (keys) D("GceAudioInputStream::%s keys %s", __FUNCTION__, keys);
    164 
    165   str_parms* query = str_parms_create_str(keys);
    166   str_parms* reply = str_parms_create();
    167 
    168   char value[256];
    169   int ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING,
    170                               value, sizeof(value));
    171   char* str;
    172   if (ret >= 0) {
    173     str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, device_);
    174     str = strdup(str_parms_to_str(reply));
    175   } else {
    176     str = strdup(keys);
    177   }
    178   str_parms_destroy(query);
    179   str_parms_destroy(reply);
    180   return str;
    181 }
    182 
    183 
    184 ssize_t GceAudioInputStream::Read(void* buffer, size_t bytes) {
    185   int64_t available = buffer_model_->RemoveFromInputBuffer(
    186       bytes / frame_size_, false) * frame_size_;
    187   ssize_t rval = available;
    188   if ((rval != available) || (rval < 0)) {
    189     ALOGE("GceAudioInputStream:%s got bad value from "
    190           "RemoveFromInputBuffer %" PRId64, __FUNCTION__, available);
    191     return -1;
    192   }
    193   memset(buffer, 0, rval);
    194   return rval;
    195 }
    196 
    197 }
    198