1 /*
2 **
3 ** Copyright 2007, 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 "AudioHwDevice"
19 //#define LOG_NDEBUG 0
20 
21 #include <hardware/audio.h>
22 #include <utils/Log.h>
23 
24 #include <audio_utils/spdif/SPDIFEncoder.h>
25 
26 #include "AudioHwDevice.h"
27 #include "AudioStreamOut.h"
28 #include "SpdifStreamOut.h"
29 
30 namespace android {
31 
32 // ----------------------------------------------------------------------------
33 
openOutputStream(AudioStreamOut ** ppStreamOut,audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config * config,const char * address)34 status_t AudioHwDevice::openOutputStream(
35         AudioStreamOut **ppStreamOut,
36         audio_io_handle_t handle,
37         audio_devices_t devices,
38         audio_output_flags_t flags,
39         struct audio_config *config,
40         const char *address)
41 {
42 
43     struct audio_config originalConfig = *config;
44     AudioStreamOut *outputStream = new AudioStreamOut(this, flags);
45 
46     // Try to open the HAL first using the current format.
47     ALOGV("openOutputStream(), try "
48             " sampleRate %d, Format %#x, "
49             "channelMask %#x",
50             config->sample_rate,
51             config->format,
52             config->channel_mask);
53     status_t status = outputStream->open(handle, devices, config, address);
54 
55     if (status != NO_ERROR) {
56         delete outputStream;
57         outputStream = NULL;
58 
59         // FIXME Look at any modification to the config.
60         // The HAL might modify the config to suggest a wrapped format.
61         // Log this so we can see what the HALs are doing.
62         ALOGI("openOutputStream(), HAL returned"
63             " sampleRate %d, Format %#x, "
64             "channelMask %#x, status %d",
65             config->sample_rate,
66             config->format,
67             config->channel_mask,
68             status);
69 
70         // If the data is encoded then try again using wrapped PCM.
71         bool wrapperNeeded = !audio_is_linear_pcm(originalConfig.format)
72                 && ((flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
73                 && ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);
74 
75         if (wrapperNeeded) {
76             if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
77                 outputStream = new SpdifStreamOut(this, flags, originalConfig.format);
78                 status = outputStream->open(handle, devices, &originalConfig, address);
79                 if (status != NO_ERROR) {
80                     ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
81                         status);
82                     delete outputStream;
83                     outputStream = NULL;
84                 }
85             } else {
86                 ALOGE("ERROR - openOutputStream(), SPDIFEncoder does not support format 0x%08x",
87                     originalConfig.format);
88             }
89         }
90     }
91 
92     *ppStreamOut = outputStream;
93     return status;
94 }
95 
96 
97 }; // namespace android
98