1/* 2** 3** Copyright 2015, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#define LOG_TAG "AudioFlinger" 19//#define LOG_NDEBUG 0 20#include <hardware/audio.h> 21#include <utils/Log.h> 22 23#include <audio_utils/spdif/SPDIFEncoder.h> 24 25#include "AudioHwDevice.h" 26#include "AudioStreamOut.h" 27#include "SpdifStreamOut.h" 28 29namespace android { 30 31/** 32 * If the AudioFlinger is processing encoded data and the HAL expects 33 * PCM then we need to wrap the data in an SPDIF wrapper. 34 */ 35SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev, 36 audio_output_flags_t flags, 37 audio_format_t format) 38 // Tell the HAL that the data will be compressed audio wrapped in a data burst. 39 : AudioStreamOut(dev, (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)) 40 , mSpdifEncoder(this, format) 41 , mApplicationFormat(AUDIO_FORMAT_DEFAULT) 42 , mApplicationSampleRate(0) 43 , mApplicationChannelMask(0) 44{ 45} 46 47status_t SpdifStreamOut::open( 48 audio_io_handle_t handle, 49 audio_devices_t devices, 50 struct audio_config *config, 51 const char *address) 52{ 53 struct audio_config customConfig = *config; 54 55 mApplicationFormat = config->format; 56 mApplicationSampleRate = config->sample_rate; 57 mApplicationChannelMask = config->channel_mask; 58 59 // Some data bursts run at a higher sample rate. 60 // TODO Move this into the audio_utils as a static method. 61 switch(config->format) { 62 case AUDIO_FORMAT_E_AC3: 63 mRateMultiplier = 4; 64 break; 65 case AUDIO_FORMAT_AC3: 66 case AUDIO_FORMAT_DTS: 67 case AUDIO_FORMAT_DTS_HD: 68 mRateMultiplier = 1; 69 break; 70 default: 71 ALOGE("ERROR SpdifStreamOut::open() unrecognized format 0x%08X\n", 72 config->format); 73 return BAD_VALUE; 74 } 75 customConfig.sample_rate = config->sample_rate * mRateMultiplier; 76 77 customConfig.format = AUDIO_FORMAT_PCM_16_BIT; 78 customConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; 79 80 // Always print this because otherwise it could be very confusing if the 81 // HAL and AudioFlinger are using different formats. 82 // Print before open() because HAL may modify customConfig. 83 ALOGI("SpdifStreamOut::open() AudioFlinger requested" 84 " sampleRate %d, format %#x, channelMask %#x", 85 config->sample_rate, 86 config->format, 87 config->channel_mask); 88 ALOGI("SpdifStreamOut::open() HAL configured for" 89 " sampleRate %d, format %#x, channelMask %#x", 90 customConfig.sample_rate, 91 customConfig.format, 92 customConfig.channel_mask); 93 94 status_t status = AudioStreamOut::open( 95 handle, 96 devices, 97 &customConfig, 98 address); 99 100 ALOGI("SpdifStreamOut::open() status = %d", status); 101 102 return status; 103} 104 105int SpdifStreamOut::flush() 106{ 107 mSpdifEncoder.reset(); 108 return AudioStreamOut::flush(); 109} 110 111int SpdifStreamOut::standby() 112{ 113 mSpdifEncoder.reset(); 114 return AudioStreamOut::standby(); 115} 116 117ssize_t SpdifStreamOut::writeDataBurst(const void* buffer, size_t bytes) 118{ 119 return AudioStreamOut::write(buffer, bytes); 120} 121 122ssize_t SpdifStreamOut::write(const void* buffer, size_t numBytes) 123{ 124 // Write to SPDIF wrapper. It will call back to writeDataBurst(). 125 return mSpdifEncoder.write(buffer, numBytes); 126} 127 128} // namespace android 129