Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 062e67a2 authored by Phil Burk's avatar Phil Burk
Browse files

AudioFlinger: call SPDIF wrapper from AudioFlinger



Create an interface layer between the AudioFlinger and the HAL
that manages the wrapping and format conversion.

Removed unnecessary includes.
Handle rate conversion in getRenderPosition().
Try to open HAL with encoded format before wrapping with SPDIF.

Bug: 17566660
Change-Id: I00ad888ca15ff0f85b85efb8167c7f5ea761a244
Signed-off-by: default avatarPhil Burk <philburk@google.com>
parent 21b51b61
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@ LOCAL_SRC_FILES:= \
    AudioFlinger.cpp            \
    Threads.cpp                 \
    Tracks.cpp                  \
    AudioHwDevice.cpp           \
    AudioStreamOut.cpp          \
    SpdifStreamOut.cpp          \
    Effects.cpp                 \
    AudioMixer.cpp.arm          \
    PatchPanel.cpp
@@ -52,6 +55,7 @@ LOCAL_C_INCLUDES := \

LOCAL_SHARED_LIBRARIES := \
    libaudioresampler \
    libaudiospdif \
    libaudioutils \
    libcommon_time_client \
    libcutils \
+11 −20
Original line number Diff line number Diff line
@@ -272,7 +272,7 @@ static const char * const audio_interfaces[] = {
};
#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))

AudioFlinger::AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
        audio_module_handle_t module,
        audio_devices_t devices)
{
@@ -1716,8 +1716,6 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_

    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;

    audio_stream_out_t *outStream = NULL;

    // FOR TESTING ONLY:
    // This if statement allows overriding the audio policy settings
    // and forcing a specific format or channel mask to the HAL/Sink device for testing.
@@ -1739,25 +1737,18 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_
        }
    }

    status_t status = hwDevHal->open_output_stream(hwDevHal,
    AudioStreamOut *outputStream = NULL;
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            devices,
            flags,
            config,
                                                   &outStream,
            address.string());

    mHardwareStatus = AUDIO_HW_IDLE;
    ALOGV("openOutput_l() openOutputStream returned output %p, sampleRate %d, Format %#x, "
            "channelMask %#x, status %d",
            outStream,
            config->sample_rate,
            config->format,
            config->channel_mask,
            status);

    if (status == NO_ERROR && outStream != NULL) {
        AudioStreamOut *outputStream = new AudioStreamOut(outHwDev, outStream, flags);
    if (status == NO_ERROR) {

        PlaybackThread *thread;
        if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
@@ -1787,7 +1778,7 @@ status_t AudioFlinger::openOutput(audio_module_handle_t module,
                                  uint32_t *latencyMs,
                                  audio_output_flags_t flags)
{
    ALOGV("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x",
    ALOGI("openOutput(), module %d Device %x, SamplingRate %d, Format %#08x, Channels %x, flags %x",
              module,
              (devices != NULL) ? *devices : 0,
              config->sample_rate,
+5 −49
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@
#include <media/nbaio/NBAIO.h>
#include "AudioWatchdog.h"
#include "AudioMixer.h"
#include "AudioStreamOut.h"
#include "SpdifStreamOut.h"
#include "AudioHwDevice.h"

#include <powermanager/IPowerManager.h>

@@ -311,7 +314,6 @@ public:
                                        wp<RefBase> cookie);

private:
    class AudioHwDevice;    // fwd declaration for findSuitableHwDev_l

               audio_mode_t getMode() const { return mMode; }

@@ -449,7 +451,7 @@ private:
    class EffectModule;
    class EffectHandle;
    class EffectChain;
    struct AudioStreamOut;

    struct AudioStreamIn;

    struct  stream_type_t {
@@ -586,57 +588,11 @@ private:
                // Return true if the effect was found in mOrphanEffectChains, false otherwise.
                bool            updateOrphanEffectChains(const sp<EffectModule>& effect);

    class AudioHwDevice {
    public:
        enum Flags {
            AHWD_CAN_SET_MASTER_VOLUME  = 0x1,
            AHWD_CAN_SET_MASTER_MUTE    = 0x2,
        };

        AudioHwDevice(audio_module_handle_t handle,
                      const char *moduleName,
                      audio_hw_device_t *hwDevice,
                      Flags flags)
            : mHandle(handle), mModuleName(strdup(moduleName))
            , mHwDevice(hwDevice)
            , mFlags(flags) { }
        /*virtual*/ ~AudioHwDevice() { free((void *)mModuleName); }

        bool canSetMasterVolume() const {
            return (0 != (mFlags & AHWD_CAN_SET_MASTER_VOLUME));
        }

        bool canSetMasterMute() const {
            return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE));
        }

        audio_module_handle_t handle() const { return mHandle; }
        const char *moduleName() const { return mModuleName; }
        audio_hw_device_t *hwDevice() const { return mHwDevice; }
        uint32_t version() const { return mHwDevice->common.version; }

    private:
        const audio_module_handle_t mHandle;
        const char * const mModuleName;
        audio_hw_device_t * const mHwDevice;
        const Flags mFlags;
    };

    // AudioStreamOut and AudioStreamIn are immutable, so their fields are const.
    // AudioStreamIn is immutable, so their fields are const.
    // For emphasis, we could also make all pointers to them be "const *",
    // but that would clutter the code unnecessarily.

    struct AudioStreamOut {
        AudioHwDevice* const audioHwDev;
        audio_stream_out_t* const stream;
        const audio_output_flags_t flags;

        audio_hw_device_t* hwDev() const { return audioHwDev->hwDevice(); }

        AudioStreamOut(AudioHwDevice *dev, audio_stream_out_t *out, audio_output_flags_t flags) :
            audioHwDev(dev), stream(out), flags(flags) {}
    };

    struct AudioStreamIn {
        AudioHwDevice* const audioHwDev;
        audio_stream_in_t* const stream;
+94 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#define LOG_TAG "AudioHwDevice"
//#define LOG_NDEBUG 0

#include <hardware/audio.h>
#include <utils/Log.h>

#include <audio_utils/spdif/SPDIFEncoder.h>

#include "AudioHwDevice.h"
#include "AudioStreamOut.h"
#include "SpdifStreamOut.h"

namespace android {

// ----------------------------------------------------------------------------

status_t AudioHwDevice::openOutputStream(
        AudioStreamOut **ppStreamOut,
        audio_io_handle_t handle,
        audio_devices_t devices,
        audio_output_flags_t flags,
        struct audio_config *config,
        const char *address)
{

    struct audio_config originalConfig = *config;
    AudioStreamOut *outputStream = new AudioStreamOut(this, flags);

    // Try to open the HAL first using the current format.
    ALOGV("AudioHwDevice::openOutputStream(), try "
            " sampleRate %d, Format %#x, "
            "channelMask %#x",
            config->sample_rate,
            config->format,
            config->channel_mask);
    status_t status = outputStream->open(handle, devices, config, address);

    if (status != NO_ERROR) {
        delete outputStream;
        outputStream = NULL;

        // FIXME Look at any modification to the config.
        // The HAL might modify the config to suggest a wrapped format.
        // Log this so we can see what the HALs are doing.
        ALOGI("AudioHwDevice::openOutputStream(), HAL returned"
            " sampleRate %d, Format %#x, "
            "channelMask %#x, status %d",
            config->sample_rate,
            config->format,
            config->channel_mask,
            status);

        // If the data is encoded then try again using wrapped PCM.
        bool wrapperNeeded = !audio_is_linear_pcm(originalConfig.format)
                && ((flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
                && ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);

        // FIXME - Add isEncodingSupported() query to SPDIF wrapper then
        // call it from here.
        if (wrapperNeeded) {
            outputStream = new SpdifStreamOut(this, flags);
            status = outputStream->open(handle, devices, &originalConfig, address);
            if (status != NO_ERROR) {
                ALOGE("ERROR - AudioHwDevice::openOutputStream(), SPDIF open returned %d",
                    status);
                delete outputStream;
                outputStream = NULL;
            }
        }
    }

    *ppStreamOut = outputStream;
    return status;
}


}; // namespace android
+88 −0
Original line number Diff line number Diff line
/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef ANDROID_AUDIO_HW_DEVICE_H
#define ANDROID_AUDIO_HW_DEVICE_H

#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>

#include <hardware/audio.h>
#include <utils/Errors.h>
#include <system/audio.h>


namespace android {

class AudioStreamOut;

class AudioHwDevice {
public:
    enum Flags {
        AHWD_CAN_SET_MASTER_VOLUME  = 0x1,
        AHWD_CAN_SET_MASTER_MUTE    = 0x2,
    };

    AudioHwDevice(audio_module_handle_t handle,
                  const char *moduleName,
                  audio_hw_device_t *hwDevice,
                  Flags flags)
        : mHandle(handle)
        , mModuleName(strdup(moduleName))
        , mHwDevice(hwDevice)
        , mFlags(flags) { }
    virtual ~AudioHwDevice() { free((void *)mModuleName); }

    bool canSetMasterVolume() const {
        return (0 != (mFlags & AHWD_CAN_SET_MASTER_VOLUME));
    }

    bool canSetMasterMute() const {
        return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE));
    }

    audio_module_handle_t handle() const { return mHandle; }
    const char *moduleName() const { return mModuleName; }
    audio_hw_device_t *hwDevice() const { return mHwDevice; }
    uint32_t version() const { return mHwDevice->common.version; }

    /** This method creates and opens the audio hardware output stream.
     * The "address" parameter qualifies the "devices" audio device type if needed.
     * The format format depends on the device type:
     * - Bluetooth devices use the MAC address of the device in the form "00:11:22:AA:BB:CC"
     * - USB devices use the ALSA card and device numbers in the form  "card=X;device=Y"
     * - Other devices may use a number or any other string.
     */
    status_t openOutputStream(
            AudioStreamOut **ppStreamOut,
            audio_io_handle_t handle,
            audio_devices_t devices,
            audio_output_flags_t flags,
            struct audio_config *config,
            const char *address);

private:
    const audio_module_handle_t mHandle;
    const char * const          mModuleName;
    audio_hw_device_t * const   mHwDevice;
    const Flags                 mFlags;
};

} // namespace android

#endif // ANDROID_AUDIO_HW_DEVICE_H
Loading