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.
71062e67a26e0553dd142be622821f493df541f0c6Phil Burk        bool wrapperNeeded = !audio_is_linear_pcm(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