1062e67a26e0553dd142be622821f493df541f0c6Phil Burk/* 2062e67a26e0553dd142be622821f493df541f0c6Phil Burk** 3062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Copyright 2007, The Android Open Source Project 4062e67a26e0553dd142be622821f493df541f0c6Phil Burk** 5062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Licensed under the Apache License, Version 2.0 (the "License"); 6062e67a26e0553dd142be622821f493df541f0c6Phil Burk** you may not use this file except in compliance with the License. 7062e67a26e0553dd142be622821f493df541f0c6Phil Burk** You may obtain a copy of the License at 8062e67a26e0553dd142be622821f493df541f0c6Phil Burk** 9062e67a26e0553dd142be622821f493df541f0c6Phil Burk** http://www.apache.org/licenses/LICENSE-2.0 10062e67a26e0553dd142be622821f493df541f0c6Phil Burk** 11062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Unless required by applicable law or agreed to in writing, software 12062e67a26e0553dd142be622821f493df541f0c6Phil Burk** distributed under the License is distributed on an "AS IS" BASIS, 13062e67a26e0553dd142be622821f493df541f0c6Phil Burk** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14062e67a26e0553dd142be622821f493df541f0c6Phil Burk** See the License for the specific language governing permissions and 15062e67a26e0553dd142be622821f493df541f0c6Phil Burk** limitations under the License. 16062e67a26e0553dd142be622821f493df541f0c6Phil Burk*/ 17062e67a26e0553dd142be622821f493df541f0c6Phil Burk 18062e67a26e0553dd142be622821f493df541f0c6Phil Burk#define LOG_TAG "AudioHwDevice" 19062e67a26e0553dd142be622821f493df541f0c6Phil Burk//#define LOG_NDEBUG 0 20062e67a26e0553dd142be622821f493df541f0c6Phil Burk 21062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <hardware/audio.h> 22062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <utils/Log.h> 23062e67a26e0553dd142be622821f493df541f0c6Phil Burk 24062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <audio_utils/spdif/SPDIFEncoder.h> 25062e67a26e0553dd142be622821f493df541f0c6Phil Burk 26062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioHwDevice.h" 27062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioStreamOut.h" 28062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "SpdifStreamOut.h" 29062e67a26e0553dd142be622821f493df541f0c6Phil Burk 30062e67a26e0553dd142be622821f493df541f0c6Phil Burknamespace android { 31062e67a26e0553dd142be622821f493df541f0c6Phil Burk 32062e67a26e0553dd142be622821f493df541f0c6Phil Burk// ---------------------------------------------------------------------------- 33062e67a26e0553dd142be622821f493df541f0c6Phil Burk 34062e67a26e0553dd142be622821f493df541f0c6Phil Burkstatus_t AudioHwDevice::openOutputStream( 35062e67a26e0553dd142be622821f493df541f0c6Phil Burk AudioStreamOut **ppStreamOut, 36062e67a26e0553dd142be622821f493df541f0c6Phil Burk audio_io_handle_t handle, 37062e67a26e0553dd142be622821f493df541f0c6Phil Burk audio_devices_t devices, 38062e67a26e0553dd142be622821f493df541f0c6Phil Burk audio_output_flags_t flags, 39062e67a26e0553dd142be622821f493df541f0c6Phil Burk struct audio_config *config, 40062e67a26e0553dd142be622821f493df541f0c6Phil Burk const char *address) 41062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 42062e67a26e0553dd142be622821f493df541f0c6Phil Burk 43062e67a26e0553dd142be622821f493df541f0c6Phil Burk struct audio_config originalConfig = *config; 44062e67a26e0553dd142be622821f493df541f0c6Phil Burk AudioStreamOut *outputStream = new AudioStreamOut(this, flags); 45062e67a26e0553dd142be622821f493df541f0c6Phil Burk 46062e67a26e0553dd142be622821f493df541f0c6Phil Burk // Try to open the HAL first using the current format. 4723d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk ALOGV("openOutputStream(), try " 48062e67a26e0553dd142be622821f493df541f0c6Phil Burk " sampleRate %d, Format %#x, " 49062e67a26e0553dd142be622821f493df541f0c6Phil Burk "channelMask %#x", 50062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->sample_rate, 51062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->format, 52062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->channel_mask); 53062e67a26e0553dd142be622821f493df541f0c6Phil Burk status_t status = outputStream->open(handle, devices, config, address); 54062e67a26e0553dd142be622821f493df541f0c6Phil Burk 55062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (status != NO_ERROR) { 56062e67a26e0553dd142be622821f493df541f0c6Phil Burk delete outputStream; 57062e67a26e0553dd142be622821f493df541f0c6Phil Burk outputStream = NULL; 58062e67a26e0553dd142be622821f493df541f0c6Phil Burk 59062e67a26e0553dd142be622821f493df541f0c6Phil Burk // FIXME Look at any modification to the config. 60062e67a26e0553dd142be622821f493df541f0c6Phil Burk // The HAL might modify the config to suggest a wrapped format. 61062e67a26e0553dd142be622821f493df541f0c6Phil Burk // Log this so we can see what the HALs are doing. 6223d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk ALOGI("openOutputStream(), HAL returned" 63062e67a26e0553dd142be622821f493df541f0c6Phil Burk " sampleRate %d, Format %#x, " 64062e67a26e0553dd142be622821f493df541f0c6Phil Burk "channelMask %#x, status %d", 65062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->sample_rate, 66062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->format, 67062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->channel_mask, 68062e67a26e0553dd142be622821f493df541f0c6Phil Burk status); 69062e67a26e0553dd142be622821f493df541f0c6Phil Burk 70062e67a26e0553dd142be622821f493df541f0c6Phil Burk // If the data is encoded then try again using wrapped PCM. 71fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format) 72062e67a26e0553dd142be622821f493df541f0c6Phil Burk && ((flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) 73062e67a26e0553dd142be622821f493df541f0c6Phil Burk && ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0); 74062e67a26e0553dd142be622821f493df541f0c6Phil Burk 75062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (wrapperNeeded) { 7623d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk if (SPDIFEncoder::isFormatSupported(originalConfig.format)) { 7723d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk outputStream = new SpdifStreamOut(this, flags, originalConfig.format); 7823d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk status = outputStream->open(handle, devices, &originalConfig, address); 7923d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk if (status != NO_ERROR) { 8023d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk ALOGE("ERROR - openOutputStream(), SPDIF open returned %d", 8123d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk status); 8223d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk delete outputStream; 8323d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk outputStream = NULL; 8423d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk } 8523d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk } else { 8623d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk ALOGE("ERROR - openOutputStream(), SPDIFEncoder does not support format 0x%08x", 8723d8997f58bb9c59fa3a1b9a6b2edbf1b2b0f4c6Phil Burk originalConfig.format); 88062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 89062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 90062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 91062e67a26e0553dd142be622821f493df541f0c6Phil Burk 92062e67a26e0553dd142be622821f493df541f0c6Phil Burk *ppStreamOut = outputStream; 93062e67a26e0553dd142be622821f493df541f0c6Phil Burk return status; 94062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 95062e67a26e0553dd142be622821f493df541f0c6Phil Burk 96062e67a26e0553dd142be622821f493df541f0c6Phil Burk 97062e67a26e0553dd142be622821f493df541f0c6Phil Burk}; // namespace android 98