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

Commit c1d4afe7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add offload support for aaudio." into main

parents 7d652bd3 0996f2b4
Loading
Loading
Loading
Loading
+158 −3
Original line number Diff line number Diff line
@@ -119,8 +119,42 @@ enum {
     *
     * Available since API level 34.
     */
    AAUDIO_FORMAT_IEC61937
    AAUDIO_FORMAT_IEC61937,

    /**
     * This format is used for audio compressed in MP3 format.
     */
    AAUDIO_FORMAT_MP3,

    /**
     * This format is used for audio compressed in AAC LC format.
     */
    AAUDIO_FORMAT_AAC_LC,

    /**
     * This format is used for audio compressed in AAC HE V1 format.
     */
    AAUDIO_FORMAT_AAC_HE_V1,

    /**
     * This format is used for audio compressed in AAC HE V2 format.
     */
    AAUDIO_FORMAT_AAC_HE_V2,

    /**
     * This format is used for audio compressed in AAC ELD format.
     */
    AAUDIO_FORMAT_AAC_ELD,

    /**
     * This format is used for audio compressed in AAC XHE format.
     */
    AAUDIO_FORMAT_AAC_XHE,

    /**
     * This format is used for audio compressed in OPUS.
     */
    AAUDIO_FORMAT_OPUS
};
typedef int32_t aaudio_format_t;

@@ -335,7 +369,23 @@ enum {
    /**
     * Reducing latency is more important than battery life.
     */
    AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
    AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,

    /**
     * Extending battery life is more important than low latency.
     *
     * This mode is not supported in input streams.
     * This mode will play through the offloaded audio path to save battery life.
     *
     * Comparing to mode {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING}, the stream at
     * this mode will be able to write a large amount(several seconds) of data within a
     * short time. The written data will be queued in a hardware buffer. After that, the
     * app can suspend its thread/process that playing audio, the audio framework's data
     * pipe will be suspended automatically and the CPU will be allowed to sleep for
     * power saving. When all queued data are played, the apps will be able to get callback
     * to feed more data.
     */
    AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED
};
typedef int32_t aaudio_performance_mode_t;

@@ -1090,7 +1140,8 @@ AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(
 * Set the requested performance mode.
 *
 * Supported modes are {@link #AAUDIO_PERFORMANCE_MODE_NONE},
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING} * and {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}.
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING}, {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY} and
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED}.
 *
 * The default, if you do not call this function, is {@link #AAUDIO_PERFORMANCE_MODE_NONE}.
 *
@@ -1474,6 +1525,44 @@ AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* _Nonnu
        AAudioStream_errorCallback _Nullable callback, void* _Nullable userData)
        __INTRODUCED_IN(26);

/**
 * Prototype for the callback function that is passed to
 * AAudioStreamBuilder_setPresentationEndCallback().
 *
 * This will be called when all the buffers of an offloaded stream that were queued in the audio
 * system (e.g. the combination of the Android audio framework and the device's audio hardware)
 * have been played after AudioStream_requestStop() has been called.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream(), which must be an
 *               output stream as the offloaded mode is only supported for output stream
 * @param userData the same address that was passed to
 *                 AAudioStreamBuilder_setPresentationEndCallback().
 */
typedef void (*AAudioStream_presentationEndCallback)(AAudioStream* _Nonnull stream,
                                                     void* _Null_unspecified userData);

/**
 * Request that AAudio call this function when all the buffers of an offloaded stream that were
 * queued in the audio system (e.g. the combination of the Android audio framework and the device's
 * audio hardware) have been played.
 *
 * The presentation end callback must be used together with the data callback.
 * The presentation edn callback won't be called if the stream is closed before all the data
 * is played.
 *
 * Available since API level 36.
 *
 * @param builder reference provided by AAudio_createStreamBuilder()
 * @param callback pointer to a function that will be called when all the buffers of an offloaded
 *                 stream that were queued have been played.
 * @param userData pointer to an application data structure that will be passed
 *                 to the callback functions.
 */
AAUDIO_API void AAudioStreamBuilder_setPresentationEndCallback(
        AAudioStreamBuilder* _Nonnull builder,
        AAudioStream_presentationEndCallback _Nonnull callback,
        void* _Nullable userData) __INTRODUCED_IN(36);

/**
 * Open a stream based on the options in the StreamBuilder.
 *
@@ -2188,6 +2277,72 @@ AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* _Nonnull stream)
AAUDIO_API aaudio_channel_mask_t AAudioStream_getChannelMask(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(32);

/**
 * Configures the delay and padding values for the current stream playing in offload mode.
 * This should only be used on a stream whose performance mode is
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED} and the format is compressed format.
 * The unit is frames, where a frame includes samples for all audio channels, e.g. 100 frames
 * for a stereo stream corresponds to 200 interleaved PCM samples.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @param delayInFrames number of frames to be ignored at the beginning of the stream. A value
 *                      of 0 indicates no delay is to be applied.
 * @param paddingInFrames number of frames to be ignored at the end of the stream. A value of 0
 *                        of 0 indicates no padding is to be applied.
 * @return {@link #AAUDIO_OK} if the delay and padding values are set successfully,
 *         or {@link #AAUDIO_ERROR_ILLEGAL_ARGUMENT} if delayInFrames or paddingInFrames
 *         is less than 0,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API aaudio_result_t AAudioStream_setOffloadDelayPadding(
        AAudioStream* _Nonnull stream, int32_t delayInFrames, int32_t paddingInFrames)
        __INTRODUCED_IN(36);

/**
 * Return the decoder delay of an offloaded stream in frames.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return the offload delay in frames that previously set with
 *         {@link #AAudioStream_setOffloadDelayPadding},
 *         or 0 if it was never modified,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API int32_t AAudioStream_getOffloadDelay(AAudioStream* _Nonnull stream) __INTRODUCED_IN(36);

/**
 * Return the decoder padding of an offloaded stream in frames.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return the offload padding in frames that previously set with
 *         {@link #AAudioStream_setOffloadDelayPadding},
 *         or 0 if it was never modified,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API int32_t AAudioStream_getOffloadPadding(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(36);

/**
 * Declares that the last data writing operation on this stream provided the last buffer of this
 * stream.
 * After the end of stream, previously set padding and delay values are ignored. That indicates
 * all written data will be played.
 * Use this method in the same thread as any data writing operation.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return {@link #AAUDIO_OK} on success,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API aaudio_result_t AAudioStream_setOffloadEndOfStream(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(36);

#ifdef __cplusplus
}
#endif
+34 −0
Original line number Diff line number Diff line
@@ -255,6 +255,16 @@ AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builde
    streamBuilder->setErrorCallbackUserData(userData);
}

AAUDIO_API void AAudioStreamBuilder_setPresentationEndCallback(AAudioStreamBuilder* builder,
        AAudioStream_presentationEndCallback callback, void* userData) {
    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    if (streamBuilder == nullptr) {
        return;
    }
    streamBuilder->setPresentationEndCallbackProc(callback)
                 ->setPresentationEndCallbackUserData(userData);
}

AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
                                                int32_t frames)
{
@@ -693,3 +703,27 @@ AAUDIO_API aaudio_channel_mask_t AAudioStream_getChannelMask(AAudioStream* strea
    // Do not return channel index masks as they are not public.
    return AAudio_isChannelIndexMask(channelMask) ? AAUDIO_UNSPECIFIED : channelMask;
}

AAUDIO_API aaudio_result_t AAudioStream_setOffloadDelayPadding(
        AAudioStream* stream, int32_t delayInFrames, int32_t paddingInFrames) {
    if (delayInFrames < 0 || paddingInFrames < 0) {
        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    }
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->setOffloadDelayPadding(delayInFrames, paddingInFrames);
}

AAUDIO_API int32_t AAudioStream_getOffloadDelay(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->getOffloadDelay();
}

AAUDIO_API int32_t AAudioStream_getOffloadPadding(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->getOffloadPadding();
}

AAUDIO_API aaudio_result_t AAudioStream_setOffloadEndOfStream(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->setOffloadEndOfStream();
}
+7 −0
Original line number Diff line number Diff line
@@ -58,6 +58,13 @@ static aaudio_result_t isFormatValid(audio_format_t format) {
        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
        case AUDIO_FORMAT_PCM_8_24_BIT:
        case AUDIO_FORMAT_IEC61937:
        case AUDIO_FORMAT_MP3:
        case AUDIO_FORMAT_AAC_LC:
        case AUDIO_FORMAT_AAC_HE_V1:
        case AUDIO_FORMAT_AAC_HE_V2:
        case AUDIO_FORMAT_AAC_ELD:
        case AUDIO_FORMAT_AAC_XHE:
        case AUDIO_FORMAT_OPUS:
            break; // valid
        default:
            ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
+6 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
    mErrorCallbackProc = builder.getErrorCallbackProc();
    mDataCallbackUserData = builder.getDataCallbackUserData();
    mErrorCallbackUserData = builder.getErrorCallbackUserData();
    setPresentationEndCallbackUserData(builder.getPresentationEndCallbackUserData());
    setPresentationEndCallbackProc(builder.getPresentationEndCallbackProc());

    return AAUDIO_OK;
}
@@ -285,6 +287,10 @@ aaudio_result_t AudioStream::safeFlush() {

aaudio_result_t AudioStream::systemStopInternal() {
    std::lock_guard<std::mutex> lock(mStreamLock);
    return systemStopInternal_l();
}

aaudio_result_t AudioStream::systemStopInternal_l() {
    aaudio_result_t result = safeStop_l();
    if (result == AAUDIO_OK) {
        // We only call this for logging in "dumpsys audio". So ignore return code.
+25 −5
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ public:
     * have been called.
     */
    int32_t getBytesPerFrame() const {
        return mSamplesPerFrame * getBytesPerSample();
        return audio_bytes_per_frame(mSamplesPerFrame, mFormat);
    }

    /**
@@ -346,7 +346,7 @@ public:
     * This is only valid after setDeviceSamplesPerFrame() and setDeviceFormat() have been called.
     */
    int32_t getBytesPerDeviceFrame() const {
        return getDeviceSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat());
        return audio_bytes_per_frame(getDeviceSamplesPerFrame(), getDeviceFormat());
    }

    virtual int64_t getFramesWritten() = 0;
@@ -390,6 +390,24 @@ public:
        mDeviceSamplesPerFrame = deviceSamplesPerFrame;
    }

    virtual aaudio_result_t setOffloadDelayPadding(int32_t delayInFrames, int32_t paddingInFrames) {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual int32_t getOffloadDelay() {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual int32_t getOffloadPadding() {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual aaudio_result_t setOffloadEndOfStream() EXCLUDES(mStreamLock) {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual void setPresentationEndCallbackProc(AAudioStream_presentationEndCallback proc) { }
    virtual void setPresentationEndCallbackUserData(void* userData) { }

    /**
     * @return true if data callback has been specified
@@ -408,7 +426,7 @@ public:
    /**
     * @return true if called from the same thread as the callback
     */
    bool collidesWithCallback() const;
    virtual bool collidesWithCallback() const;

    // Implement AudioDeviceCallback
    void onAudioDeviceUpdate(audio_io_handle_t audioIo,
@@ -649,6 +667,8 @@ protected:

    aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock);

    virtual aaudio_result_t systemStopInternal_l() REQUIRES(mStreamLock);

    std::atomic<bool>    mCallbackEnabled{false};

    float                mDuckAndMuteVolume = 1.0f;
@@ -742,6 +762,8 @@ protected:
        mAudioBalance = audioBalance;
    }

    aaudio_result_t safeStop_l() REQUIRES(mStreamLock);

    std::string mMetricsId; // set once during open()

    std::mutex                 mStreamLock;
@@ -750,8 +772,6 @@ protected:

private:

    aaudio_result_t safeStop_l() REQUIRES(mStreamLock);

    /**
     * Release then close the stream.
     */
Loading