Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions include/sound/compress_offload.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <linux/types.h>
#include <sound/asound.h>
#include <sound/compress_params.h>
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 2, 0)
#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heh! GH doesnt let comment on patchlog...
I guess it would make sense to say, move the header to version 0.3.0...


struct snd_compressed_buffer {
__u32 fragment_size;
Expand Down Expand Up @@ -49,7 +49,8 @@ struct snd_compr_avail {

enum snd_compr_direction {
SND_COMPRESS_PLAYBACK = 0,
SND_COMPRESS_CAPTURE
SND_COMPRESS_CAPTURE,
SND_COMPRESS_ACCEL
};

struct snd_compr_caps {
Expand Down Expand Up @@ -79,6 +80,58 @@ struct snd_compr_metadata {
__u32 value[8];
}__attribute__((packed, aligned(4)));


/* flags for struct snd_compr_task */
#define SND_COMPRESS_TFLG_NEW_STREAM (1<<0) /* mark for the new stream data */

/**
* struct snd_compr_task - task primitive for non-realtime operation
* @seqno: sequence number (task identifier)
* @origin_seqno: previous sequence number (task identifier) - for reuse
* @input_fd: data input file descriptor (dma-buf)
* @output_fd: data output file descriptor (dma-buf)
* @input_size: filled data in bytes (from caller, must not exceed fragment size)
* @flags: see SND_COMPRESS_TFLG_* defines
*/
struct snd_compr_task {
__u64 seqno;
__u64 origin_seqno;
int input_fd;
int output_fd;
__u64 input_size;
__u32 flags;
__u8 reserved[16];
} __attribute__((packed, aligned(4)));

/**
* enum snd_compr_state - task state
* @SND_COMPRESS_TASK_STATE_IDLE: task is not queued
* @SND_COMPRESS_TASK_STATE_ACTIVE: task is in the queue
* @SND_COMPRESS_TASK_STATE_FINISHED: task was processed, output is available
*/
enum snd_compr_state {
SND_COMPRESS_TASK_STATE_IDLE = 0,
SND_COMPRESS_TASK_STATE_ACTIVE,
SND_COMPRESS_TASK_STATE_FINISHED
};

/**
* struct snd_compr_task_status - task status
* @seqno: sequence number (task identifier)
* @input_size: filled data in bytes (from user space)
* @output_size: filled data in bytes (from driver)
* @output_flags: reserved for future (all zeros - from driver)
* @state: actual task state (SND_COMPRESS_TASK_STATE_*)
*/
struct snd_compr_task_status {
__u64 seqno;
__u64 input_size;
__u64 output_size;
__u32 output_flags;
__u8 state;
__u8 reserved[15];
} __attribute__((packed, aligned(4)));

#define SNDRV_COMPRESS_IOCTL_VERSION _IOR('C', 0x00, int)
#define SNDRV_COMPRESS_GET_CAPS _IOWR('C', 0x10, struct snd_compr_caps)
#define SNDRV_COMPRESS_GET_CODEC_CAPS _IOWR('C', 0x11, struct snd_compr_codec_caps)
Expand All @@ -98,4 +151,11 @@ struct snd_compr_metadata {
#define SND_COMPR_TRIGGER_DRAIN 7
#define SND_COMPR_TRIGGER_NEXT_TRACK 8
#define SND_COMPR_TRIGGER_PARTIAL_DRAIN 9

#define SNDRV_COMPRESS_TASK_CREATE _IOWR('C', 0x60, struct snd_compr_task)
#define SNDRV_COMPRESS_TASK_FREE _IOW('C', 0x61, __u64)
#define SNDRV_COMPRESS_TASK_START _IOWR('C', 0x62, struct snd_compr_task)
#define SNDRV_COMPRESS_TASK_STOP _IOW('C', 0x63, __u64)
#define SNDRV_COMPRESS_TASK_STATUS _IOWR('C', 0x68, struct snd_compr_task_status)

#endif
18 changes: 16 additions & 2 deletions include/sound/compress_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,16 @@ union snd_codec_options {
struct snd_dec_wma wma_d;
struct snd_dec_alac alac_d;
struct snd_dec_ape ape_d;
struct {
__u32 out_sample_rate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be folded into previos patch as both are coming from kernel header

} src_d;
}__attribute__((packed, aligned(4)));

struct snd_codec_desc_src {
__u32 out_sample_rate_min;
__u32 out_sample_rate_max;
} __attribute__((packed, aligned(4)));

struct snd_codec_desc {
__u32 max_ch;
__u32 sample_rates[MAX_NUM_SAMPLE_RATES];
Expand All @@ -266,7 +274,12 @@ struct snd_codec_desc {
__u32 modes;
__u32 formats;
__u32 min_buffer;
__u32 reserved[15];
__u32 pcm_formats;
union {
__u32 u_space[6];
struct snd_codec_desc_src src;
} __attribute__((packed, aligned(4)));
__u32 reserved[8];
}__attribute__((packed, aligned(4)));

struct snd_codec {
Expand All @@ -282,7 +295,8 @@ struct snd_codec {
__u32 format;
__u32 align;
union snd_codec_options options;
__u32 reserved[3];
__u32 pcm_format;
__u32 reserved[2];
}__attribute__((packed, aligned(4)));

#endif
5 changes: 5 additions & 0 deletions include/tinycompress/compress_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ struct compress_ops {
int (*is_compress_ready)(void *compress_data);
const char *(*get_error)(void *compress_data);
int (*set_codec_params)(void *compress_data, struct snd_codec *codec);
int (*task_create)(void *compress_data, struct compr_task *task);
int (*task_start)(void *compress_data, struct compr_task *task);
int (*task_stop)(void *compress_data, struct compr_task *task);
int (*task_free)(void *compress_data, struct compr_task *task);
int (*task_status)(void *compress_data, struct compr_task_status *status);
};

#endif /* end of __COMPRESS_OPS_H__ */
28 changes: 28 additions & 0 deletions include/tinycompress/tinycompress.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ struct compr_gapless_mdata {
__u32 encoder_padding;
};

/* Same as struct snd_compr_task */
struct compr_task {
__u64 seqno;
__u64 origin_seqno;
int input_fd;
int output_fd;
__u64 input_size;
__u32 flags;
__u8 reserved[16];
};

/* Same as struct snd_compr_task_status */
struct compr_task_status {
__u64 seqno;
__u64 input_size;
__u64 output_size;
__u32 output_flags;
__u8 state;
__u8 reserved[15];
};

#define COMPRESS_ACCEL 0x40000000
#define COMPRESS_OUT 0x20000000
#define COMPRESS_IN 0x10000000

Expand Down Expand Up @@ -318,6 +340,12 @@ const char *compress_get_error(struct compress *compress);
*/
int compress_set_codec_params(struct compress *compress, struct snd_codec *codec);

int compress_task_create(struct compress *compress, struct compr_task *task);
int compress_task_start(struct compress *compress, struct compr_task *task);
int compress_task_stop(struct compress *compress, struct compr_task *task);
int compress_task_free(struct compress *compress, struct compr_task *task);
int compress_task_status(struct compress *compress, struct compr_task_status *status);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
25 changes: 25 additions & 0 deletions src/lib/compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,28 @@ int compress_set_codec_params(struct compress *compress, struct snd_codec *codec
{
return compress->ops->set_codec_params(compress->data, codec);
}

int compress_task_create(struct compress *compress, struct compr_task *task)
{
return compress->ops->task_create(compress->data, task);
}

int compress_task_start(struct compress *compress, struct compr_task *task)
{
return compress->ops->task_start(compress->data, task);
}

int compress_task_stop(struct compress *compress, struct compr_task *task)
{
return compress->ops->task_stop(compress->data, task);
}

int compress_task_free(struct compress *compress, struct compr_task *task)
{
return compress->ops->task_free(compress->data, task);
}

int compress_task_status(struct compress *compress, struct compr_task_status *status)
{
return compress->ops->task_status(compress->data, status);
}
96 changes: 94 additions & 2 deletions src/lib/compress_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,19 @@ static void *compress_hw_open_by_name(const char *name,
compress->max_poll_wait_ms = DEFAULT_MAX_POLL_WAIT_MS;

compress->flags = flags;
if (!((flags & COMPRESS_OUT) || (flags & COMPRESS_IN))) {
if (!((flags & COMPRESS_OUT) || (flags & COMPRESS_IN) || (flags & COMPRESS_ACCEL))) {
oops(&bad_compress, EINVAL, "can't deduce device direction from given flags");
goto config_fail;
}

if (flags & COMPRESS_OUT) {
compress->fd = open(fn, O_RDONLY);
} else {
} else if (flags & COMPRESS_IN) {
compress->fd = open(fn, O_WRONLY);
} else {
compress->fd = open(fn, O_RDWR);
}

if (compress->fd < 0) {
oops(&bad_compress, errno, "cannot open device '%s'", fn);
goto config_fail;
Expand Down Expand Up @@ -598,6 +601,90 @@ static int compress_hw_set_codec_params(void *data, struct snd_codec *codec)
return 0;
}

static int compress_hw_task_create(void *data, struct compr_task *ctask)
{
struct compress_hw_data *compress = (struct compress_hw_data *)data;
struct snd_compr_task task;

if (!is_compress_hw_ready(compress))
return oops(compress, ENODEV, "device not ready\n");

memcpy(&task, ctask, sizeof(task));

if (ioctl(compress->fd, SNDRV_COMPRESS_TASK_CREATE, &task))
return oops(compress, errno, "cannot create task\n");

memcpy(ctask, &task, sizeof(task));

return 0;
}

static int compress_hw_task_start(void *data, struct compr_task *ctask)
{
struct compress_hw_data *compress = (struct compress_hw_data *)data;
struct snd_compr_task task;

if (!is_compress_hw_ready(compress))
return oops(compress, ENODEV, "device not ready\n");

memcpy(&task, ctask, sizeof(task));

if (ioctl(compress->fd, SNDRV_COMPRESS_TASK_START, &task))
return oops(compress, errno, "cannot create task\n");

return 0;
}

static int compress_hw_task_stop(void *data, struct compr_task *ctask)
{
struct compress_hw_data *compress = (struct compress_hw_data *)data;
struct snd_compr_task task;

if (!is_compress_hw_ready(compress))
return oops(compress, ENODEV, "device not ready\n");

memcpy(&task, ctask, sizeof(task));

if (ioctl(compress->fd, SNDRV_COMPRESS_TASK_STOP, &task.seqno))
return oops(compress, errno, "cannot create task\n");

return 0;
}

static int compress_hw_task_free(void *data, struct compr_task *ctask)
{
struct compress_hw_data *compress = (struct compress_hw_data *)data;
struct snd_compr_task task;

if (!is_compress_hw_ready(compress))
return oops(compress, ENODEV, "device not ready\n");

memcpy(&task, ctask, sizeof(task));

if (ioctl(compress->fd, SNDRV_COMPRESS_TASK_FREE, &task.seqno))
return oops(compress, errno, "cannot create task\n");

return 0;
}

static int compress_hw_task_status(void *data, struct compr_task_status *cstatus)
{
struct compress_hw_data *compress = (struct compress_hw_data *)data;
struct snd_compr_task_status status;

if (!is_compress_hw_ready(compress))
return oops(compress, ENODEV, "device not ready\n");

memcpy(&status, cstatus, sizeof(status));

if (ioctl(compress->fd, SNDRV_COMPRESS_TASK_STATUS, &status))
return oops(compress, errno, "cannot create task\n");

memcpy(cstatus, &status, sizeof(status));

return 0;
}

struct compress_ops compress_hw_ops = {
.open_by_name = compress_hw_open_by_name,
.close = compress_hw_close,
Expand All @@ -621,5 +708,10 @@ struct compress_ops compress_hw_ops = {
.is_compress_ready = is_compress_hw_ready,
.get_error = compress_hw_get_error,
.set_codec_params = compress_hw_set_codec_params,
.task_create = compress_hw_task_create,
.task_start = compress_hw_task_start,
.task_stop = compress_hw_task_stop,
.task_status = compress_hw_task_status,
.task_free = compress_hw_task_free,
};

5 changes: 4 additions & 1 deletion src/utils/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
bin_PROGRAMS = cplay crecord
bin_PROGRAMS = cplay crecord caccel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we always build caccel?


cplay_SOURCES = cplay.c wave.c
crecord_SOURCES = crecord.c wave.c
caccel_SOURCES = caccel.c wave.c alsa_wrap.c

cplay_CFLAGS = -I$(top_srcdir)/include
crecord_CFLAGS = -I$(top_srcdir)/include
caccel_CFLAGS = -I$(top_srcdir)/include


cplay_LDADD = $(top_builddir)/src/lib/libtinycompress.la
crecord_LDADD = $(top_builddir)/src/lib/libtinycompress.la
caccel_LDADD = $(top_builddir)/src/lib/libtinycompress.la -lasound
28 changes: 28 additions & 0 deletions src/utils/alsa_wrap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: (LGPL-2.1-only OR BSD-3-Clause)

#include <alsa/asoundlib.h>

snd_pcm_format_t alsa_snd_pcm_format_value(const char *name)
{
return snd_pcm_format_value(name);
}

int alsa_snd_pcm_format_physical_width(snd_pcm_format_t format)
{
return snd_pcm_format_physical_width(format);
}

int alsa_snd_pcm_format_width(snd_pcm_format_t format)
{
return snd_pcm_format_width(format);
}

int alsa_snd_pcm_format_linear(snd_pcm_format_t format)
{
return snd_pcm_format_linear(format);
}

int alsa_snd_pcm_format_signed(snd_pcm_format_t format)
{
return snd_pcm_format_signed(format);
}
12 changes: 12 additions & 0 deletions src/utils/alsa_wrap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: (LGPL-2.1-only OR BSD-3-Clause) */

#ifndef __ALSA_WRAP_API_H
#define __ALSA_WRAP_API_H

snd_pcm_format_t alsa_snd_pcm_format_value(const char *name);
int alsa_snd_pcm_format_physical_width(snd_pcm_format_t format);
int alsa_snd_pcm_format_width(snd_pcm_format_t format);
int alsa_snd_pcm_format_linear(snd_pcm_format_t format);
int alsa_snd_pcm_format_signed(snd_pcm_format_t format);
#endif

Loading