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

Commit 03f2fb3c authored by John Grossman's avatar John Grossman
Browse files

AAH_RX: Add the ability to control volume and stream type.



DO NOT MERGE

Change the AAH_RX player so that it implements MediaPlayerHWInterface
(instead of just MediaPlayerInterface) so the app level can control
the rendering volume of individual RX player instances as well as the
stream type of the audio tracks created by the RX player.

Change-Id: Ieff1ea774f7981227546744883ee4b4e87a2cd2a
Signed-off-by: default avatarJohn Grossman <johngro@google.com>
parent 9d98a089
Loading
Loading
Loading
Loading
+34 −13
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 * Copyright (C) 2012 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.
@@ -47,7 +47,9 @@ AAH_DecoderPump::AAH_DecoderPump(OMXClient& omx)
    , last_queued_pts_valid_(false)
    , last_queued_pts_(0)
    , last_ts_transform_valid_(false)
    , last_volume_(0xFF) {
    , last_left_volume_(1.0f)
    , last_right_volume_(1.0f)
    , last_stream_type_(AUDIO_STREAM_DEFAULT) {
    thread_ = new ThreadWrapper(this);
}

@@ -102,13 +104,13 @@ void AAH_DecoderPump::queueToRenderer(MediaBuffer* decoded_sample) {
            if (NULL != renderer_) {
                int frameCount;
                AudioTrack::getMinFrameCount(&frameCount,
                        AUDIO_STREAM_DEFAULT,
                        last_stream_type_,
                        static_cast<int>(format_sample_rate_));
                int ch_format = (format_channels_ == 1)
                    ? AUDIO_CHANNEL_OUT_MONO
                    : AUDIO_CHANNEL_OUT_STEREO;

                res = renderer_->set(AUDIO_STREAM_DEFAULT,
                res = renderer_->set(last_stream_type_,
                        format_sample_rate_,
                        AUDIO_FORMAT_PCM_16_BIT,
                        ch_format,
@@ -128,9 +130,8 @@ void AAH_DecoderPump::queueToRenderer(MediaBuffer* decoded_sample) {
                        delete renderer_;
                        renderer_ = NULL;
                    } else {
                        float volume = static_cast<float>(last_volume_)
                                     / 255.0f;
                        if (renderer_->setVolume(volume, volume) != OK) {
                        if (renderer_->setVolume(last_left_volume_,
                                                 last_right_volume_) != OK) {
                            LOGW("%s: setVolume failed", __FUNCTION__);
                        }

@@ -204,22 +205,41 @@ void AAH_DecoderPump::setRenderTSTransform(const LinearTransform& trans) {
    }
}

void AAH_DecoderPump::setRenderVolume(uint8_t volume) {
void AAH_DecoderPump::setRenderVolume(float left, float right) {
    Mutex::Autolock lock(&render_lock_);

    if (volume == last_volume_) {
    if ((left == last_left_volume_) && (right == last_right_volume_)) {
        return;
    }

    last_volume_ = volume;
    last_left_volume_  = left;
    last_right_volume_ = right;

    if (renderer_ != NULL) {
        float volume = static_cast<float>(last_volume_) / 255.0f;
        if (renderer_->setVolume(volume, volume) != OK) {
        if (renderer_->setVolume(left, right) != OK) {
            LOGW("%s: setVolume failed", __FUNCTION__);
        }
    }
}

void AAH_DecoderPump::setRenderStreamType(int stream_type) {
    Mutex::Autolock lock(&render_lock_);

    if (last_stream_type_ == stream_type) {
        return;
    }

    // TODO: figure out if changing stream type dynamically will ever be a
    // requirement.  If it is not, we probably want to refactor this such that
    // stream type is only passed during construction.
    if (renderer_ != NULL) {
        LOGW("Attempting to change stream type (%d -> %d) after rendering has"
             " started", last_stream_type_, stream_type);
    }

    last_stream_type_ = stream_type;
}

// isAboutToUnderflow is something of a hack used to figure out when it might be
// time to give up on trying to fill in a gap in the RTP sequence and simply
// move on with a discontinuity.  If we had perfect knowledge of when we were
@@ -509,7 +529,8 @@ status_t AAH_DecoderPump::shutdown_l() {

    last_queued_pts_valid_   = false;
    last_ts_transform_valid_ = false;
    last_volume_             = 0xFF;
    last_left_volume_        = 1.0f;
    last_right_volume_       = 1.0f;
    thread_status_           = OK;

    decoder_ = NULL;
+5 −2
Original line number Diff line number Diff line
@@ -42,7 +42,8 @@ class AAH_DecoderPump : public MediaSource {
    status_t shutdown();

    void setRenderTSTransform(const LinearTransform& trans);
    void setRenderVolume(uint8_t volume);
    void setRenderVolume(float left, float right);
    void setRenderStreamType(int stream_type);
    bool isAboutToUnderflow(int64_t threshold);
    bool getStatus() const { return thread_status_; }

@@ -93,7 +94,9 @@ class AAH_DecoderPump : public MediaSource {
    int64_t             last_queued_pts_;
    bool                last_ts_transform_valid_;
    LinearTransform     last_ts_transform_;
    uint8_t             last_volume_;
    float               last_left_volume_;
    float               last_right_volume_;
    int                 last_stream_type_;
    CCHelper            cc_helper_;

    // protected by the thread_lock_
+38 −0
Original line number Diff line number Diff line
@@ -46,6 +46,10 @@ AAH_RXPlayer::AAH_RXPlayer()
    current_epoch_known_ = false;
    data_source_set_     = false;
    sock_fd_             = -1;
    audio_volume_left_   = 1.0;
    audio_volume_right_  = 1.0;
    audio_stream_type_   = AUDIO_STREAM_DEFAULT;
    audio_params_dirty_  = false;

    substreams_.setCapacity(4);

@@ -298,4 +302,38 @@ void AAH_RXPlayer::fetchAudioFlinger() {
    }
}

status_t AAH_RXPlayer::setVolume(float leftVolume, float rightVolume) {
    AutoMutex api_lock(&api_lock_);

    {  // explicit scope for autolock pattern
        AutoMutex api_lock(&audio_param_lock_);
        if ((leftVolume  == audio_volume_left_) &&
            (rightVolume == audio_volume_right_)) {
            return OK;
        }

        audio_volume_left_  = leftVolume;
        audio_volume_right_ = rightVolume;
        audio_params_dirty_ = true;
    }

    signalEventFD(wakeup_work_thread_evt_fd_);

    return OK;
}

status_t AAH_RXPlayer::setAudioStreamType(int streamType) {
    AutoMutex api_lock(&api_lock_);

    {  // explicit scope for autolock pattern
        AutoMutex api_lock(&audio_param_lock_);
        audio_stream_type_  = streamType;
        audio_params_dirty_ = true;
    }

    signalEventFD(wakeup_work_thread_evt_fd_);

    return OK;
}

}  // namespace android
+19 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@

namespace android {

class AAH_RXPlayer : public MediaPlayerInterface {
class AAH_RXPlayer : public MediaPlayerHWInterface {
  public:
    AAH_RXPlayer();

@@ -62,6 +62,9 @@ class AAH_RXPlayer : public MediaPlayerInterface {
    virtual status_t    getParameter(int key, Parcel *reply);
    virtual status_t    invoke(const Parcel& request, Parcel *reply);

    virtual status_t    setVolume(float leftVolume, float rightVolume);
    virtual status_t    setAudioStreamType(int streamType);

  protected:
    virtual ~AAH_RXPlayer();

@@ -196,6 +199,9 @@ class AAH_RXPlayer : public MediaPlayerInterface {
        uint32_t getSSRC()      const { return ssrc_; }
        uint8_t  getProgramID() const { return (ssrc_ >> 5) & 0x1F; }
        status_t getStatus() const { return status_; }
        void     setAudioSpecificParams(float left_vol,
                                        float right_vol,
                                        int stream_type);

        void clearInactivityTimeout() {
            inactivity_timeout_.setTimeout(-1);
@@ -226,6 +232,7 @@ class AAH_RXPlayer : public MediaPlayerInterface {
        bool                    setupAACSubstreamMeta();
        bool                    setupSubstreamType(uint8_t substream_type,
                                                   uint8_t codec_type);
        void                    applyVolume();

        uint32_t                ssrc_;
        bool                    waiting_for_rap_;
@@ -248,6 +255,11 @@ class AAH_RXPlayer : public MediaPlayerInterface {
        Timeout                 inactivity_timeout_;
        bool                    eos_reached_;

        float                   audio_volume_local_left_;
        float                   audio_volume_local_right_;
        uint8_t                 audio_volume_remote_;
        int                     audio_stream_type_;

        static const int64_t    kAboutToUnderflowThreshold;
        static const int        kInactivityTimeoutMsec;

@@ -303,6 +315,12 @@ class AAH_RXPlayer : public MediaPlayerInterface {
    OMXClient           omx_;
    CCHelper            cc_helper_;

    Mutex               audio_param_lock_;
    float               audio_volume_left_;
    float               audio_volume_right_;
    int                 audio_stream_type_;
    bool                audio_params_dirty_;

    // Connection to audio flinger used to hack a path to setMasterVolume.
    sp<IAudioFlinger>   audio_flinger_;

+27 −4
Original line number Diff line number Diff line
@@ -316,7 +316,30 @@ bool AAH_RXPlayer::threadLoop() {
        clearEventFD(wakeup_work_thread_evt_fd_);
        process_more_right_now = false;

        // Step 2: Do we have data waiting in the socket?  If so, drain the
        // Step 2: Do we have a change of audio parameters (volume/stream_type)
        // to apply to our current substreams?  If so, go ahead and take care of
        // it.
        if (audio_params_dirty_) {
            float latched_left_volume, latched_right_volume;
            int latched_stream_type;
            {  // explicit scope for autolock pattern
                AutoMutex api_lock(&audio_param_lock_);
                latched_left_volume  = audio_volume_left_;
                latched_right_volume = audio_volume_right_;
                latched_stream_type  = audio_stream_type_;
                audio_params_dirty_  = false;
            }

            for (size_t i = 0; i < substreams_.size(); ++i) {
                CHECK(substreams_.valueAt(i) != NULL);
                substreams_.valueAt(i)->setAudioSpecificParams(
                        latched_left_volume,
                        latched_right_volume,
                        latched_stream_type);
            }
        }

        // Step 3: Do we have data waiting in the socket?  If so, drain the
        // socket moving valid RTP information into the ring buffer to be
        // processed.
        if (poll_fds[1].revents) {
@@ -403,13 +426,13 @@ bool AAH_RXPlayer::threadLoop() {
            }
        }

        // Step 3: Process any data we mave have accumulated in the ring buffer
        // Step 4: Process any data we mave have accumulated in the ring buffer
        // so far.
        if (!thread_wrapper_->exitPending()) {
            processRingBuffer();
        }

        // Step 4: At this point in time, the ring buffer should either be
        // Step 5: At this point in time, the ring buffer should either be
        // empty, or stalled in front of a gap caused by some dropped packets.
        // Check on the current gap situation and deal with it in an appropriate
        // fashion.  If processGaps returns true, it means that it has given up
@@ -419,7 +442,7 @@ bool AAH_RXPlayer::threadLoop() {
            process_more_right_now = processGaps();
        }

        // Step 5: Check for fatal errors.  If any of our substreams has
        // Step 6: Check for fatal errors.  If any of our substreams has
        // encountered a fatal, unrecoverable, error, then propagate the error
        // up to user level and shut down.
        for (size_t i = 0; i < substreams_.size(); ++i) {
Loading