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

Commit ee3499a4 authored by Naresh Tanniru's avatar Naresh Tanniru
Browse files

hal: add timestamp mode support for offload playback streams

Add timestamp mode support for offload playback streams.
Support is added through compressed path, which is configured
internally when timestamp mode is requested.

CRs-fixed: 2016014
Change-Id: I0cc982a51f87abed40e424bc31fe9e013342bb71
parent 2a265b09
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ const struct string_to_enum s_flag_name_to_enum_table[] = {
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
#endif
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TIMESTAMP),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+14 −3
Original line number Diff line number Diff line
@@ -2579,9 +2579,12 @@ static size_t out_get_buffer_size(const struct audio_stream *stream)
{
    struct stream_out *out = (struct stream_out *)stream;

    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
            return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
        else
            return out->compr_config.fragment_size;
    else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
    } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
        return voice_extn_compress_voip_out_get_buffer_size(out);
    else if (is_offload_usecase(out->usecase) &&
             out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
@@ -4097,6 +4100,11 @@ int adev_open_output_stream(struct audio_hw_device *dev,
         */
        if (!audio_extn_passthru_is_passthrough_stream(out))
            out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;

        if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
            out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
        ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);

        /*TODO: Do we need to change it for passthrough */
        out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;

@@ -4159,6 +4167,9 @@ int adev_open_output_stream(struct audio_hw_device *dev,
            out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
        }

        if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
            out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
        }
        if (config->offload_info.format == AUDIO_FORMAT_FLAC)
            out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;

+1 −0
Original line number Diff line number Diff line
@@ -270,6 +270,7 @@ struct stream_out {
    struct audio_out_start_delay_param delay_param; /*start delay*/

    audio_offload_info_t info;
    qahwi_stream_out_t qahwi_out;
};

struct stream_in {
+115 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
/*#define LOG_NDEBUG 0*/
#define LOG_NDDEBUG 0

#include <inttypes.h>
#include <errno.h>
#include <cutils/log.h>

@@ -286,6 +287,117 @@ static int qahwi_open_input_stream(struct audio_hw_device *dev,
    return ret;
}

ssize_t qahwi_out_write_v2(struct audio_stream_out *stream, const void* buffer,
                          size_t bytes, int64_t* timestamp)
{
    struct stream_out *out = (struct stream_out *)stream;
    struct snd_codec_metadata *mdata = NULL;
    size_t mdata_size = 0, bytes_written = 0;
    char *buf = NULL;
    ssize_t ret = 0;

    if (!out->qahwi_out.is_inititalized) {
        ALOGE("%s: invalid state!", __func__);
        return -EINVAL;
    }
    if (COMPRESSED_TIMESTAMP_FLAG &&
        (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)) {

        mdata_size = sizeof(struct snd_codec_metadata);
        buf = (char *) out->qahwi_out.obuf;
        if (timestamp) {
            mdata = (struct snd_codec_metadata *) buf;
            mdata->length = bytes;
            mdata->offset = mdata_size;
            mdata->timestamp = *timestamp;
        }
        memcpy(buf + mdata_size, buffer, bytes);
        ret = out->qahwi_out.base.write(&out->stream, (void *)buf, out->qahwi_out.buf_size);
        if (ret <= 0) {
            ALOGE("%s: error! write returned %zd", __func__, ret);
        } else {
            bytes_written = bytes;
        }
        ALOGV("%s: flag 0x%x, bytes %zd, read %zd, ret %zd timestamp 0x%"PRIx64"",
              __func__, out->flags, bytes, bytes_written, ret, *timestamp);
    } else {
        bytes_written = out->qahwi_out.base.write(&out->stream, buffer, bytes);
        ALOGV("%s: flag 0x%x, bytes %zd, read %zd, ret %zd",
              __func__, out->flags, bytes, bytes_written, ret);
    }
    return bytes_written;
}

static void qahwi_close_output_stream(struct audio_hw_device *dev,
                               struct audio_stream_out *stream_out)
{
    struct audio_device *adev = (struct audio_device *) dev;
    struct stream_out *out = (struct stream_out *)stream_out;

    ALOGV("%s", __func__);
    if (!adev->qahwi_dev.is_inititalized || !out->qahwi_out.is_inititalized) {
        ALOGE("%s: invalid state!", __func__);
        return;
    }
    if (out->qahwi_out.obuf)
        free(out->qahwi_out.obuf);
    out->qahwi_out.buf_size = 0;
    adev->qahwi_dev.base.close_output_stream(dev, stream_out);
}

static int qahwi_open_output_stream(struct audio_hw_device *dev,
                             audio_io_handle_t handle,
                             audio_devices_t devices,
                             audio_output_flags_t flags,
                             struct audio_config *config,
                             struct audio_stream_out **stream_out,
                             const char *address)
{
    struct audio_device *adev = (struct audio_device *) dev;
    struct stream_out *out = NULL;
    size_t buf_size = 0, mdata_size = 0;
    int ret = 0;

    ALOGV("%s: dev_init %d, flags 0x%x", __func__,
              adev->qahwi_dev.is_inititalized, flags);
    if (!adev->qahwi_dev.is_inititalized) {
        ALOGE("%s: invalid state!", __func__);
        return -EINVAL;
    }

    ret = adev->qahwi_dev.base.open_output_stream(dev, handle, devices, flags,
                                                 config, stream_out, address);
    if (ret)
        return ret;

    out = (struct stream_out *)*stream_out;
    // keep adev fptrs before overriding
    out->qahwi_out.base = out->stream;

    out->qahwi_out.is_inititalized = true;

    if (COMPRESSED_TIMESTAMP_FLAG &&
        (flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)) {
        // set write to NULL as this is not supported in timestamp mode
        out->stream.write = NULL;

        mdata_size = sizeof(struct snd_codec_metadata);
        buf_size = out->qahwi_out.base.common.get_buffer_size(&out->stream.common);
        buf_size += mdata_size;
        out->qahwi_out.buf_size = buf_size;
        out->qahwi_out.obuf = malloc(buf_size);
        if (!out->qahwi_out.obuf) {
            ALOGE("%s: allocation failed for timestamp metadata!", __func__);
            qahwi_close_output_stream(dev, &out->stream);
            *stream_out = NULL;
            ret = -ENOMEM;
        }
        ALOGD("%s: obuf %p, buff_size %zd",
              __func__, out->qahwi_out.obuf, buf_size);
    }
    return ret;
}

void qahwi_init(hw_device_t *device)
{
    struct audio_device *adev = (struct audio_device *) device;
@@ -299,6 +411,9 @@ void qahwi_init(hw_device_t *device)
    adev->device.open_input_stream = qahwi_open_input_stream;
    adev->device.close_input_stream = qahwi_close_input_stream;

    adev->device.open_output_stream = qahwi_open_output_stream;
    adev->device.close_output_stream = qahwi_close_output_stream;

    adev->qahwi_dev.is_inititalized = true;
}
void qahwi_deinit(hw_device_t *device)
+9 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ __BEGIN_DECLS
#ifdef AUDIO_HW_EXTN_API_ENABLED
#include <hardware/audio.h>
typedef struct qahwi_stream_in qahwi_stream_in_t;
typedef struct qahwi_stream_out qahwi_stream_out_t;
typedef struct qahwi_device qahwi_device_t;

struct qahwi_stream_in {
@@ -41,6 +42,13 @@ struct qahwi_stream_in {
    void *ibuf;
};

struct qahwi_stream_out {
    struct audio_stream_out base;
    bool is_inititalized;
    size_t buf_size;
    void *obuf;
};

struct qahwi_device {
    struct audio_hw_device base;
    bool is_inititalized;
@@ -50,6 +58,7 @@ void qahwi_init(hw_device_t *device);
void qahwi_deinit(hw_device_t *device);
#else
typedef void *qahwi_stream_in_t;
typedef void *qahwi_stream_out_t;
typedef void *qahwi_device_t;

#define qahwi_init(device) (0)
Loading