aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2018-01-17 20:46:06 +0600
committerVadim Yanitskiy <axilirator@gmail.com>2018-01-17 20:54:03 +0600
commit7a79fc11692779a1f9377b416b6208f1245e7612 (patch)
tree96998b59cbc1f4dceabd54c7a6980d7e63b3fa89 /src
parent30493c78b3579b562b4d71224857d11fbf1b56b6 (diff)
parent6f34c8f3017629ea4865543e901b61ac893e0356 (diff)
Merge branch 'fixeria/lib' into master
The previous GAPK implementation was represented by a single executable. So, all audio transcoding operations were available only via calling the 'gapk' binary. This approach didn't allow external applications to benefit from using GAPK API directly. The following set of changes separates the common code into a shared library called 'libosmogapk', linking the 'gapk' binary against it: - 95e6664 Introduce a shared 'libosmogapk' library - 30209ce Install GAPK headers to '${includedir}/osmocom/gapk/' - a8d4657 Add an 'osmo_gapk' prefix to the exposed symbols - 40d59f1 Add a pkg-config manifest for libosmogapk - 4f0a47d Add the symbol export map for libosmogapk All memory management operations are now based on talloc library: - 3c20dac libosmogapk: use talloc for memory management - 5cabe1e osmo-gapk: use talloc for memory management Integrated Osmocom logging framework: - c35ba8a libosmogapk: use Osmocom logging framework - 4b7cd2c osmo-gapk: drop useless printf calls - 0fe18af osmo-gapk: use Osmocom logging framework - 11943bf osmo-gapk: adjust application verbosity Integrated GNU Autotest environment and basic test coverage: - f069eb3 Init automake test environment - 1fe6a9b tests: add procqueue test - 3e9e57f tests: add pq_file test - 9d2b15d tests: add pq_rtp test - f59f3f1 tests: add format / codec transcoding tests For more details, see commits history. Change-Id: I3c6d4a9d326ee49153e4ad83823d094831c112da
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am105
-rw-r--r--src/app_osmo_gapk.c (renamed from src/main.c)353
-rw-r--r--src/benchmark.c92
-rw-r--r--src/codec_amr.c17
-rw-r--r--src/codec_efr.c15
-rw-r--r--src/codec_fr.c7
-rw-r--r--src/codec_hr.c7
-rw-r--r--src/codec_pcm.c4
-rw-r--r--src/codecs.c16
-rw-r--r--src/common.c38
-rw-r--r--src/fmt_amr.c8
-rw-r--r--src/fmt_amr_opencore.c8
-rw-r--r--src/fmt_gsm.c6
-rw-r--r--src/fmt_hr_ref.c10
-rw-r--r--src/fmt_racal.c12
-rw-r--r--src/fmt_rawpcm.c6
-rw-r--r--src/fmt_rtp_amr.c8
-rw-r--r--src/fmt_rtp_efr.c8
-rw-r--r--src/fmt_rtp_hr_etsi.c8
-rw-r--r--src/fmt_rtp_hr_ietf.c8
-rw-r--r--src/fmt_ti.c12
-rw-r--r--src/formats.c46
-rw-r--r--src/libosmogapk.map4
-rw-r--r--src/pq_alsa.c50
-rw-r--r--src/pq_codec.c34
-rw-r--r--src/pq_file.c42
-rw-r--r--src/pq_format.c35
-rw-r--r--src/pq_rtp.c45
-rw-r--r--src/procqueue.c230
29 files changed, 852 insertions, 382 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e0b622c..8efd165 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,20 +1,97 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOCORE_CFLAGS) \
- ${OPENCORE_AMRNB_CFLAGS} $(LIBALSA_CFLAGS)
-AM_LDFLAGS=$(LIBOSMOCODEC_LIBS) $(LIBOSMOCORE_LIBS) \
- ${OPENCORE_AMRNB_LIBS} ${LIBGSM_LIBS} $(LIBALSA_LIBS)
+# This is _NOT_ the library release version, it's an API version.
+# Please read Chapter 6 "Library interface versions" of the libtool
+# documentation before making any modification
+LIBVERSION = 0:0:0
-COM_SOURCES = procqueue.c pq_file.c pq_format.c pq_codec.c pq_rtp.c pq_alsa.c \
- formats.c fmt_amr.c fmt_gsm.c fmt_hr_ref.c fmt_racal.c \
- fmt_amr_opencore.c \
- fmt_rtp_amr.c fmt_rtp_efr.c fmt_rtp_hr_etsi.c fmt_rtp_hr_ietf.c \
- fmt_rawpcm.c fmt_ti.c benchmark.c \
- codecs.c codec_pcm.c codec_hr.c codec_fr.c codec_efr.c codec_amr.c
+AM_CPPFLAGS = \
+ $(all_includes) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/include \
+ $(NULL)
-bin_PROGRAMS = gapk
+AM_CFLAGS = \
+ -Wall \
+ $(LIBOSMOCORE_CFLAGS) \
+ $(LIBOSMOCODEC_CFLAGS) \
+ ${OPENCORE_AMRNB_CFLAGS} \
+ $(LIBALSA_CFLAGS) \
+ $(NULL)
-gapk_SOURCES = main.c $(COM_SOURCES)
+lib_LTLIBRARIES = libosmogapk.la
+EXTRA_DIST = libosmogapk.map
+
+libosmogapk_la_LDFLAGS = \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOCODEC_LIBS) \
+ ${OPENCORE_AMRNB_LIBS} \
+ ${LIBGSM_LIBS} \
+ $(LIBALSA_LIBS) \
+ $(LTLDFLAGS_OSMOGAPK) \
+ -version-info $(LIBVERSION) \
+ -no-undefined \
+ $(NULL)
if ENABLE_GSMHR
-gapk_LDADD = $(top_builddir)/libgsmhr/libgsmhr.la
+libosmogapk_la_LIBADD = $(top_builddir)/libgsmhr/libgsmhr.la
endif
+
+# Processing queue implementation
+libosmogapk_la_SOURCES = \
+ procqueue.c \
+ pq_format.c \
+ pq_codec.c \
+ pq_file.c \
+ pq_alsa.c \
+ pq_rtp.c \
+ $(NULL)
+
+# Formats implementation
+libosmogapk_la_SOURCES += \
+ formats.c \
+ fmt_ti.c \
+ fmt_amr.c \
+ fmt_gsm.c \
+ fmt_hr_ref.c \
+ fmt_racal.c \
+ fmt_rawpcm.c \
+ fmt_rtp_amr.c \
+ fmt_rtp_efr.c \
+ fmt_rtp_hr_etsi.c \
+ fmt_rtp_hr_ietf.c \
+ fmt_amr_opencore.c \
+ $(NULL)
+
+# Codecs implementation
+libosmogapk_la_SOURCES += \
+ codecs.c \
+ codec_pcm.c \
+ codec_hr.c \
+ codec_fr.c \
+ codec_efr.c \
+ codec_amr.c \
+ $(NULL)
+
+# Codec benchmarking
+libosmogapk_la_SOURCES += \
+ benchmark.c \
+ $(NULL)
+
+# Common routines
+libosmogapk_la_SOURCES += \
+ common.c \
+ $(NULL)
+
+# libosmogapk representative application
+bin_PROGRAMS = osmo-gapk
+
+osmo_gapk_SOURCES = \
+ app_osmo_gapk.c \
+ $(NULL)
+
+osmo_gapk_LDFLAGS = \
+ $(LIBOSMOCORE_LIBS) \
+ $(NULL)
+
+osmo_gapk_LDADD = \
+ $(top_builddir)/src/libosmogapk.la \
+ $(NULL)
diff --git a/src/main.c b/src/app_osmo_gapk.c
index 58e23c1..729ea25 100644
--- a/src/main.c
+++ b/src/app_osmo_gapk.c
@@ -26,18 +26,25 @@
#include <string.h>
#include <unistd.h>
#include <getopt.h>
+#include <talloc.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
#include <osmocom/core/socket.h>
+#include <osmocom/core/utils.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/common.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
+#include <osmocom/gapk/benchmark.h>
+/* The root talloc context of application */
+TALLOC_CTX *app_root_ctx;
struct gapk_options
{
@@ -47,7 +54,7 @@ struct gapk_options
uint16_t port;
} rtp_in;
const char *alsa_in;
- const struct format_desc *fmt_in;
+ const struct osmo_gapk_format_desc *fmt_in;
const char *fname_out;
struct {
@@ -55,14 +62,17 @@ struct gapk_options
uint16_t port;
} rtp_out;
const char *alsa_out;
- const struct format_desc *fmt_out;
+ const struct osmo_gapk_format_desc *fmt_out;
+
+ int benchmark;
+ int verbose;
};
struct gapk_state
{
struct gapk_options opts;
-
- struct pq *pq;
+ struct osmo_gapk_pq *pq;
+ int exit;
struct {
struct {
@@ -83,10 +93,30 @@ struct gapk_state
} out;
};
+/* Logging related routines */
+enum {
+ DAPP,
+};
+
+static struct log_info_cat gapk_log_info_cat[] = {
+ [DAPP] = {
+ .name = "DAPP",
+ .description = "Application",
+ .color = "\033[0;36m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+};
+
+static const struct log_info gapk_log_info = {
+ .cat = gapk_log_info_cat,
+ .num_cat = ARRAY_SIZE(gapk_log_info_cat),
+};
+
static void
print_help(char *progname)
{
+ const struct osmo_gapk_codec_desc *codec;
int i;
/* Header */
@@ -103,6 +133,8 @@ print_help(char *progname)
#endif
fprintf(stdout, " -f, --input-format=FMT\tInput format (see below)\n");
fprintf(stdout, " -g, --output-format=FMT\tOutput format (see below)\n");
+ fprintf(stdout, " -b, --enable-benchmark\tEnable codec benchmarking\n");
+ fprintf(stdout, " -v, --verbose\t\t\tEnable debug messages\n");
fprintf(stdout, "\n");
/* Print all codecs */
@@ -110,7 +142,7 @@ print_help(char *progname)
fprintf(stdout, " name\tfmt enc dec\tdescription\n");
for (i=CODEC_INVALID+1; i<_CODEC_MAX; i++) {
- const struct codec_desc *codec = codec_get_from_type(i);
+ codec = osmo_gapk_codec_get_from_type(i);
fprintf(stdout, " %4s %c %c %c \t%s\n",
codec->name,
'*',
@@ -126,7 +158,7 @@ print_help(char *progname)
fprintf(stdout, "Supported formats:\n");
for (i=FMT_INVALID+1; i<_FMT_MAX; i++) {
- const struct format_desc *fmt = fmt_get_from_type(i);
+ const struct osmo_gapk_format_desc *fmt = osmo_gapk_fmt_get_from_type(i);
fprintf(stdout, " %-19s %s\n",
fmt->name,
fmt->description
@@ -171,9 +203,11 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
#endif
{"input-format", 1, 0, 'f'},
{"output-format", 1, 0, 'g'},
+ {"enable-benchmark", 0, 0, 'b'},
+ {"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
};
- const char *short_options = "i:o:I:O:f:g:h"
+ const char *short_options = "i:o:I:O:f:g:bvh"
#ifdef HAVE_ALSA
"a:A:"
#endif
@@ -206,7 +240,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
case 'I':
rv = parse_host_port(optarg, &opt->rtp_in.hostname);
if (rv < 0 || rv > 0xffff) {
- fprintf(stderr, "[!] Invalid port: %d\n", rv);
+ LOGP(DAPP, LOGL_ERROR, "Invalid port: %d\n", rv);
return -EINVAL;
}
opt->rtp_in.port = rv;
@@ -223,33 +257,42 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
case 'O':
rv = parse_host_port(optarg, &opt->rtp_out.hostname);
if (rv < 0 || rv > 0xffff) {
- fprintf(stderr, "[!] Invalid port: %d\n", rv);
+ LOGP(DAPP, LOGL_ERROR, "Invalid port: %d\n", rv);
return -EINVAL;
}
opt->rtp_out.port = rv;
break;
case 'f':
- opt->fmt_in = fmt_get_from_name(optarg);
+ opt->fmt_in = osmo_gapk_fmt_get_from_name(optarg);
if (!opt->fmt_in) {
- fprintf(stderr, "[!] Unsupported format: %s\n", optarg);
+ LOGP(DAPP, LOGL_ERROR, "Unsupported format: %s\n", optarg);
return -EINVAL;
}
break;
case 'g':
- opt->fmt_out = fmt_get_from_name(optarg);
+ opt->fmt_out = osmo_gapk_fmt_get_from_name(optarg);
if (!opt->fmt_out) {
- fprintf(stderr, "[!] Unsupported format: %s\n", optarg);
+ LOGP(DAPP, LOGL_ERROR, "Unsupported format: %s\n", optarg);
return -EINVAL;
}
break;
+ case 'b':
+ opt->benchmark = 1;
+ break;
+
+ case 'v':
+ log_parse_category_mask(osmo_stderr_target, "DAPP");
+ opt->verbose = 1;
+ break;
+
case 'h':
return 1;
default:
- fprintf(stderr, "[+] Unknown option\n");
+ LOGP(DAPP, LOGL_ERROR, "Unknown option\n");
return -EINVAL;
}
@@ -263,98 +306,157 @@ check_options(struct gapk_state *gs)
{
/* Required formats */
if (!gs->opts.fmt_in || !gs->opts.fmt_out) {
- fprintf(stderr, "[!] Input and output formats are required arguments !\n");
+ LOGP(DAPP, LOGL_ERROR, "Input and output formats are required arguments\n");
return -EINVAL;
}
/* Transcoding */
if (gs->opts.fmt_in->codec_type != gs->opts.fmt_out->codec_type) {
- const struct codec_desc *codec;
+ const struct osmo_gapk_codec_desc *codec;
/* Check source codec */
- codec = codec_get_from_type(gs->opts.fmt_in->codec_type);
+ codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_in->codec_type);
if (!codec) {
- fprintf(stderr, "[!] Internal error: bad codec reference\n");
+ LOGP(DAPP, LOGL_ERROR, "Internal error: bad codec reference\n");
return -EINVAL;
}
if ((codec->type != CODEC_PCM) && !codec->codec_decode) {
- fprintf(stderr, "[!] Decoding from '%s' codec is unsupported\n", codec->name);
+ LOGP(DAPP, LOGL_ERROR, "Decoding from '%s' codec is unsupported\n", codec->name);
return -ENOTSUP;
}
/* Check destination codec */
- codec = codec_get_from_type(gs->opts.fmt_out->codec_type);
+ codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_out->codec_type);
if (!codec) {
- fprintf(stderr, "[!] Internal error: bad codec reference\n");
+ LOGP(DAPP, LOGL_ERROR, "Internal error: bad codec reference\n");
return -EINVAL;
}
if ((codec->type != CODEC_PCM) && !codec->codec_encode) {
- fprintf(stderr, "[!] Encoding to '%s' codec is unsupported\n", codec->name);
+ LOGP(DAPP, LOGL_ERROR, "Encoding to '%s' codec is unsupported\n", codec->name);
return -ENOTSUP;
}
}
- /* Input combinations */
- if (gs->opts.fname_in && gs->opts.rtp_in.port) {
- fprintf(stderr, "[!] You have to decide on either file or RTP input\n");
- return -EINVAL;
- }
-
- /* Output combinations */
- if (gs->opts.fname_out && gs->opts.rtp_out.port) {
- fprintf(stderr, "[!] You have to decide on either file or RTP output\n");
+ /* Check I/O combinations */
+ int src_count = 0;
+ int sink_count = 0;
+
+ if (gs->opts.fname_in)
+ src_count++;
+ if (gs->opts.rtp_in.port)
+ src_count++;
+ if (gs->opts.alsa_in)
+ src_count++;
+
+ if (gs->opts.fname_out)
+ sink_count++;
+ if (gs->opts.rtp_out.port)
+ sink_count++;
+ if (gs->opts.alsa_out)
+ sink_count++;
+
+ if (src_count > 1 || sink_count > 1) {
+ LOGP(DAPP, LOGL_ERROR, "You have to decide on "
+ "a single input and a single output\n");
return -EINVAL;
}
return 0;
}
+static void
+benchmark_dump(void)
+{
+ int i;
+
+ for (i = 0; i < _CODEC_MAX; i++) {
+ struct osmo_gapk_bench_cycles *bc;
+ unsigned long long cycles;
+ unsigned int frames;
+
+ /* Check if there are benchmark data */
+ bc = osmo_gapk_bench_codec[i];
+ if (!bc)
+ continue;
+
+ if (bc->enc_used) {
+ cycles = osmo_gapk_bench_get_cycles(i, 1);
+ frames = osmo_gapk_bench_get_frames(i, 1);
+
+ LOGP(DAPP, LOGL_NOTICE, "Codec %u (ENC): %llu cycles for %u frames"
+ " => %llu cycles/frame\n", i, cycles,
+ frames, cycles / frames);
+ }
+
+ if (bc->dec_used) {
+ cycles = osmo_gapk_bench_get_cycles(i, 0);
+ frames = osmo_gapk_bench_get_frames(i, 0);
+
+ LOGP(DAPP, LOGL_NOTICE, "Codec %u (DEC): %llu cycles for %u frames"
+ " => %llu cycles/frame\n", i, cycles,
+ frames, cycles / frames);
+ }
+ }
+}
+
static int
files_open(struct gapk_state *gs)
{
+ LOGP(DAPP, LOGL_NOTICE, "Opening I/O streams\n");
+
if (gs->opts.fname_in) {
+ LOGP(DAPP, LOGL_NOTICE, "Using a file as source\n");
gs->in.file.fh = fopen(gs->opts.fname_in, "rb");
if (!gs->in.file.fh) {
- fprintf(stderr, "[!] Error while opening input file for reading\n");
+ LOGP(DAPP, LOGL_ERROR, "Error while opening input file for reading\n");
perror("fopen");
return -errno;
}
} else if (gs->opts.rtp_in.port) {
+ LOGP(DAPP, LOGL_NOTICE, "Using RTP as source\n");
gs->in.rtp.fd = osmo_sock_init(AF_UNSPEC, SOCK_DGRAM,
IPPROTO_UDP,
gs->opts.rtp_in.hostname,
gs->opts.rtp_in.port,
OSMO_SOCK_F_BIND);
if (gs->in.rtp.fd < 0) {
- fprintf(stderr, "[!] Error while opening input socket\n");
+ LOGP(DAPP, LOGL_ERROR, "Error while opening input socket\n");
return gs->in.rtp.fd;
}
} else if (gs->opts.alsa_in) {
- printf("alsa_in, not stdin\n");
- } else
+ /* Do nothing, ALSA source does the initialization itself */
+ LOGP(DAPP, LOGL_NOTICE, "Using ALSA as source\n");
+ } else {
+ LOGP(DAPP, LOGL_NOTICE, "Using stdin as source\n");
gs->in.file.fh = stdin;
+ }
if (gs->opts.fname_out) {
+ LOGP(DAPP, LOGL_NOTICE, "Using a file as sink\n");
gs->out.file.fh = fopen(gs->opts.fname_out, "wb");
if (!gs->out.file.fh) {
- fprintf(stderr, "[!] Error while opening output file for writing\n");
+ LOGP(DAPP, LOGL_ERROR, "Error while opening output file for writing\n");
perror("fopen");
return -errno;
}
} else if (gs->opts.rtp_out.port) {
+ LOGP(DAPP, LOGL_NOTICE, "Using RTP as sink\n");
gs->out.rtp.fd = osmo_sock_init(AF_UNSPEC, SOCK_DGRAM,
IPPROTO_UDP,
gs->opts.rtp_out.hostname,
gs->opts.rtp_out.port,
OSMO_SOCK_F_CONNECT);
if (gs->out.rtp.fd < 0) {
- fprintf(stderr, "[!] Error while opening output socket\n");
+ LOGP(DAPP, LOGL_ERROR, "Error while opening output socket\n");
return gs->out.rtp.fd;
}
} else if (gs->opts.alsa_out) {
- printf("alsa_out, not stdout\n");
- } else
+ /* Do nothing, ALSA sink does the initialization itself */
+ LOGP(DAPP, LOGL_NOTICE, "Using ALSA as sink\n");
+ } else {
+ LOGP(DAPP, LOGL_NOTICE, "Using stdout as sink\n");
gs->out.file.fh = stdout;
+ }
return 0;
}
@@ -362,6 +464,8 @@ files_open(struct gapk_state *gs)
static void
files_close(struct gapk_state *gs)
{
+ LOGP(DAPP, LOGL_NOTICE, "Closing I/O streams\n");
+
if (gs->in.file.fh && gs->in.file.fh != stdin)
fclose(gs->in.file.fh);
if (gs->in.rtp.fd >= 0)
@@ -383,7 +487,7 @@ handle_headers(struct gapk_state *gs)
if (len && gs->in.file.fh) {
uint8_t *buf;
- buf = malloc(len);
+ buf = talloc_size(app_root_ctx, len);
if (!buf)
return -ENOMEM;
@@ -391,12 +495,12 @@ handle_headers(struct gapk_state *gs)
if ((rv != 1) ||
memcmp(buf, gs->opts.fmt_in->header, len))
{
- free(buf);
- fprintf(stderr, "[!] Invalid header in input file");
+ LOGP(DAPP, LOGL_ERROR, "Invalid header in input file");
+ talloc_free(buf);
return -EINVAL;
}
- free(buf);
+ talloc_free(buf);
}
/* Output file header (write it) */
@@ -413,16 +517,19 @@ handle_headers(struct gapk_state *gs)
static int
make_processing_chain(struct gapk_state *gs)
{
- const struct format_desc *fmt_in, *fmt_out;
- const struct codec_desc *codec_in, *codec_out;
+ const struct osmo_gapk_format_desc *fmt_in, *fmt_out;
+ const struct osmo_gapk_codec_desc *codec_in, *codec_out;
int need_dec, need_enc;
+ int rc;
+
+ LOGP(DAPP, LOGL_NOTICE, "Creating a processing queue\n");
fmt_in = gs->opts.fmt_in;
fmt_out = gs->opts.fmt_out;
- codec_in = codec_get_from_type(fmt_in->codec_type);
- codec_out = codec_get_from_type(fmt_out->codec_type);
+ codec_in = osmo_gapk_codec_get_from_type(fmt_in->codec_type);
+ codec_out = osmo_gapk_codec_get_from_type(fmt_out->codec_type);
need_dec = (fmt_in->codec_type != CODEC_PCM) &&
(fmt_in->codec_type != fmt_out->codec_type);
@@ -431,15 +538,15 @@ make_processing_chain(struct gapk_state *gs)
/* File read */
if (gs->in.file.fh)
- pq_queue_file_input(gs->pq, gs->in.file.fh, fmt_in->frame_len);
+ osmo_gapk_pq_queue_file_input(gs->pq, gs->in.file.fh, fmt_in->frame_len);
else if (gs->in.rtp.fd != -1)
- pq_queue_rtp_input(gs->pq, gs->in.rtp.fd, fmt_in->frame_len);
+ osmo_gapk_pq_queue_rtp_input(gs->pq, gs->in.rtp.fd, fmt_in->frame_len);
#ifdef HAVE_ALSA
else if (gs->opts.alsa_in)
- pq_queue_alsa_input(gs->pq, gs->opts.alsa_in, fmt_in->frame_len);
+ osmo_gapk_pq_queue_alsa_input(gs->pq, gs->opts.alsa_in, fmt_in->frame_len);
#endif
else {
- fprintf(stderr, "Unknown/invalid input\n");
+ LOGP(DAPP, LOGL_ERROR, "Unknown/invalid input\n");
return -1;
}
@@ -449,85 +556,111 @@ make_processing_chain(struct gapk_state *gs)
/* Convert input to decoder input fmt */
if (fmt_in->type != codec_in->codec_dec_format_type)
{
- const struct format_desc *fmt_dec;
+ const struct osmo_gapk_format_desc *fmt_dec;
- fmt_dec = fmt_get_from_type(codec_in->codec_dec_format_type);
+ fmt_dec = osmo_gapk_fmt_get_from_type(codec_in->codec_dec_format_type);
if (!fmt_dec) {
- fprintf(stderr, "Cannot determine decoder input format for codec %s\n",
- codec_in->name);
+ LOGP(DAPP, LOGL_ERROR, "Cannot determine decoder input format "
+ "for codec %s\n", codec_in->name);
return -EINVAL;
}
- pq_queue_fmt_convert(gs->pq, fmt_in, 0);
- pq_queue_fmt_convert(gs->pq, fmt_dec, 1);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_dec, 1);
}
/* Do decoding */
- pq_queue_codec(gs->pq, codec_in, 0);
+ osmo_gapk_pq_queue_codec(gs->pq, codec_in, 0);
+
+ /* Allocate memory for benchmarking */
+ if (gs->opts.benchmark)
+ osmo_gapk_bench_enable(fmt_in->codec_type);
}
else if (fmt_in->type != fmt_out->type)
{
/* Convert input to canonical fmt */
- pq_queue_fmt_convert(gs->pq, fmt_in, 0);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0);
}
/* Encoding from PCM ? */
if (need_enc)
{
/* Do encoding */
- pq_queue_codec(gs->pq, codec_out, 1);
+ osmo_gapk_pq_queue_codec(gs->pq, codec_out, 1);
+
+ /* Allocate memory for benchmarking */
+ if (gs->opts.benchmark)
+ osmo_gapk_bench_enable(fmt_out->codec_type);
/* Convert encoder output to output fmt */
if (fmt_out->type != codec_out->codec_enc_format_type)
{
- const struct format_desc *fmt_enc;
+ const struct osmo_gapk_format_desc *fmt_enc;
- fmt_enc = fmt_get_from_type(codec_out->codec_enc_format_type);
+ fmt_enc = osmo_gapk_fmt_get_from_type(codec_out->codec_enc_format_type);
if (!fmt_enc) {
- fprintf(stderr, "Cannot determine encoder output format for codec %s\n",
- codec_out->name);
+ LOGP(DAPP, LOGL_ERROR, "Cannot determine encoder output format "
+ "for codec %s\n", codec_out->name);
return -EINVAL;
}
- pq_queue_fmt_convert(gs->pq, fmt_enc, 0);
- pq_queue_fmt_convert(gs->pq, fmt_out, 1);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_enc, 0);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_out, 1);
}
}
else if (fmt_in->type != fmt_out->type)
{
/* Convert canonical to output fmt */
- pq_queue_fmt_convert(gs->pq, fmt_out, 1);
+ osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_out, 1);
}
/* File write */
if (gs->out.file.fh)
- pq_queue_file_output(gs->pq, gs->out.file.fh, fmt_out->frame_len);
+ osmo_gapk_pq_queue_file_output(gs->pq, gs->out.file.fh, fmt_out->frame_len);
else if (gs->out.rtp.fd != -1)
- pq_queue_rtp_output(gs->pq, gs->out.rtp.fd, fmt_out->frame_len);
+ osmo_gapk_pq_queue_rtp_output(gs->pq, gs->out.rtp.fd, fmt_out->frame_len);
#ifdef HAVE_ALSA
else if (gs->opts.alsa_out)
- pq_queue_alsa_output(gs->pq, gs->opts.alsa_out, fmt_out->frame_len);
+ osmo_gapk_pq_queue_alsa_output(gs->pq, gs->opts.alsa_out, fmt_out->frame_len);
#endif
else {
- fprintf(stderr, "Unknown/invalid output\n");
+ LOGP(DAPP, LOGL_ERROR, "Unknown/invalid output\n");
return -1;
}
+ /* Check the processing queue in strict mode */
+ rc = osmo_gapk_pq_check(gs->pq, 1);
+ if (rc)
+ return rc;
+
return 0;
}
static int
run(struct gapk_state *gs)
{
+ struct osmo_gapk_pq_item *item;
int rv, frames;
- rv = pq_prepare(gs->pq);
+ rv = osmo_gapk_pq_prepare(gs->pq);
if (rv)
return rv;
- for (frames=0; !(rv = pq_execute(gs->pq)); frames++);
+ for (frames = 0; !gs->exit; frames++) {
+ rv = osmo_gapk_pq_execute(gs->pq);
+ if (rv)
+ break;
+ }
+
+ LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", frames);
- fprintf(stderr, "[+] Processed %d frames\n", frames);
+ /* Wait for sink to process buffers */
+ item = llist_last_entry(&gs->pq->items, struct osmo_gapk_pq_item, list);
+ if (item->wait && !gs->exit) {
+ LOGP(DAPP, LOGL_NOTICE, "Waiting for sink to finish...\n");
+ while (item->wait(item->state))
+ continue;
+ }
return frames > 0 ? 0 : rv;
}
@@ -535,15 +668,39 @@ run(struct gapk_state *gs)
static struct gapk_state _gs, *gs = &_gs;
+static void app_shutdown(void)
+{
+ /* Close source / destination files */
+ files_close(gs);
+
+ /* Release processing queue */
+ osmo_gapk_pq_destroy(gs->pq);
+
+ /* Print benchmarking results, if enabled */
+ benchmark_dump();
+
+ /* Free memory taken by benchmark data */
+ osmo_gapk_bench_free();
+
+ if (gs->opts.verbose)
+ talloc_report_full(app_root_ctx, stderr);
+}
+
static void signal_handler(int signal)
{
+ fprintf(stderr, "signal %u received\n", signal);
+
switch (signal) {
case SIGINT:
- fprintf(stderr, "catching sigint, closing files\n");
- files_close(gs);
- pq_destroy(gs->pq);
- exit(0);
+ if (gs->exit++) {
+ app_shutdown();
+ exit(0);
+ }
break;
+ case SIGABRT:
+ case SIGUSR1:
+ case SIGUSR2:
+ talloc_report_full(app_root_ctx, stderr);
default:
break;
}
@@ -554,6 +711,15 @@ int main(int argc, char *argv[])
{
int rv;
+ /* Init talloc memory management system */
+ app_root_ctx = talloc_init("osmo-gapk root context");
+ osmo_gapk_set_talloc_ctx(app_root_ctx);
+
+ /* Init Osmocom logging framework */
+ osmo_init_logging(&gapk_log_info);
+ /* and GAPK logging wrapper */
+ osmo_gapk_log_init(DAPP);
+
/* Clear state */
memset(gs, 0x00, sizeof(struct gapk_state));
gs->in.rtp.fd = -1;
@@ -574,47 +740,44 @@ int main(int argc, char *argv[])
return rv;
/* Create processing queue */
- gs->pq = pq_create();
+ gs->pq = osmo_gapk_pq_create("main");
if (!gs->pq) {
rv = -ENOMEM;
- fprintf(stderr, "Error creating processing queue\n");
+ LOGP(DAPP, LOGL_ERROR, "Error creating processing queue\n");
goto error;
}
/* Open source / destination files */
rv = files_open(gs);
if (rv) {
- fprintf(stderr, "Error opening file(s)\n");
+ LOGP(DAPP, LOGL_ERROR, "Error opening file(s)\n");
goto error;
}
/* Handle input/output headers */
rv = handle_headers(gs);
if (rv) {
- fprintf(stderr, "Error handling header(s)\n");
+ LOGP(DAPP, LOGL_ERROR, "Error handling header(s)\n");
goto error;
}
/* Make processing chain */
rv = make_processing_chain(gs);
if (rv) {
- fprintf(stderr, "Error making processing chain\n");
+ LOGP(DAPP, LOGL_ERROR, "Error making processing chain\n");
goto error;
}
signal(SIGINT, &signal_handler);
+ signal(SIGABRT, &signal_handler);
+ signal(SIGUSR1, &signal_handler);
+ signal(SIGUSR2, &signal_handler);
/* Run the processing queue */
+ LOGP(DAPP, LOGL_NOTICE, "Init complete, starting processing queue...\n");
rv = run(gs);
error:
- /* Close source / destination files */
- files_close(gs);
-
- /* Release processing queue */
- pq_destroy(gs->pq);
-
- benchmark_dump();
-
+ app_shutdown();
return rv;
}
diff --git a/src/benchmark.c b/src/benchmark.c
index 91e2ce5..b3bb60b 100644
--- a/src/benchmark.c
+++ b/src/benchmark.c
@@ -17,41 +17,73 @@
* (C) 2014 Harald Welte <laforge@gnumonks.org>
*/
-#include <stdio.h>
+#include <talloc.h>
+#include <errno.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/benchmark.h>
+#include <osmocom/gapk/codecs.h>
-struct benchmark_cycles codec_cycles[_CODEC_MAX];
+/* Internal root talloc context */
+extern TALLOC_CTX *gapk_root_ctx;
-void benchmark_dump(void)
+struct osmo_gapk_bench_cycles *
+ osmo_gapk_bench_codec[_CODEC_MAX] = { NULL };
+
+int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec)
+{
+ struct osmo_gapk_bench_cycles *bench;
+
+ /* Allocate zero-initialized memory */
+ bench = talloc_zero(gapk_root_ctx, struct osmo_gapk_bench_cycles);
+ if (!bench)
+ return -ENOMEM;
+
+ /* Set up pointer */
+ osmo_gapk_bench_codec[codec] = bench;
+
+ return 0;
+}
+
+unsigned long long
+osmo_gapk_bench_get_cycles(enum osmo_gapk_codec_type codec, int enc)
{
+ struct osmo_gapk_bench_cycles *bench;
+ unsigned long long cycles = 0;
int i;
- for (i = 0; i < _CODEC_MAX; i++) {
- struct benchmark_cycles *bc = &codec_cycles[i];
- unsigned long long total;
- int j;
-
- if (bc->enc_used) {
- total = 0;
- for (j = 0; j < bc->enc_used; j++)
- total += bc->enc[j];
-
- fprintf(stderr,
- "Codec %u (ENC): %llu cycles for %u frames => "
- "%llu cycles/frame\n", i, total, bc->enc_used,
- total / bc->enc_used);
- }
-
- if (bc->dec_used) {
- total = 0;
- for (j = 0; j < bc->dec_used; j++)
- total += bc->dec[j];
-
- fprintf(stderr,
- "Codec %u (DEC): %llu cycles for %u frames => "
- "%llu cycles/frame\n", i, total, bc->dec_used,
- total / bc->dec_used);
- }
+ /* Check if there are benchmark data */
+ bench = osmo_gapk_bench_codec[codec];
+ if (!bench)
+ return -EAGAIN;
+
+ if (enc) {
+ for (i = 0; i < bench->enc_used; i++)
+ cycles += bench->enc[i];
+ } else {
+ for (i = 0; i < bench->dec_used; i++)
+ cycles += bench->dec[i];
}
+
+ return cycles;
+}
+
+unsigned int
+osmo_gapk_bench_get_frames(enum osmo_gapk_codec_type codec, int enc)
+{
+ struct osmo_gapk_bench_cycles *bench;
+
+ /* Check if there are benchmark data */
+ bench = osmo_gapk_bench_codec[codec];
+ if (!bench)
+ return -EAGAIN;
+
+ return enc ? bench->enc_used : bench->dec_used;
+}
+
+void osmo_gapk_bench_free(void)
+{
+ int i;
+
+ for (i = 0; i < _CODEC_MAX; i++)
+ talloc_free(osmo_gapk_bench_codec[i]);
}
diff --git a/src/codec_amr.c b/src/codec_amr.c
index ca614ed..614b744 100644
--- a/src/codec_amr.c
+++ b/src/codec_amr.c
@@ -18,20 +18,23 @@
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gapk/codecs.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/benchmark.h>
+#include <osmocom/gapk/bench.h>
#include "config.h"
#ifdef HAVE_OPENCORE_AMRNB
-#include <stdlib.h>
-#include <stdio.h>
+#include <talloc.h>
#include <opencore-amrnb/interf_dec.h>
#include <opencore-amrnb/interf_enc.h>
+/* Internal root talloc context */
+extern TALLOC_CTX *gapk_root_ctx;
+
struct codec_amr_state {
void *encoder;
void *decoder;
@@ -43,7 +46,7 @@ codec_amr_init(void)
{
struct codec_amr_state *st;
- st = calloc(1, sizeof(*st));
+ st = talloc_zero(gapk_root_ctx, struct codec_amr_state);
if (!st)
return NULL;
@@ -61,6 +64,8 @@ codec_amr_exit(void *state)
Decoder_Interface_exit(st->decoder);
Encoder_Interface_exit(st->encoder);
+ talloc_free(st);
+
return;
}
@@ -103,7 +108,7 @@ codec_amr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod
#endif /* HAVE_OPENCORE_AMRNB */
-const struct codec_desc codec_amr_desc = {
+const struct osmo_gapk_codec_desc codec_amr_desc = {
.type = CODEC_AMR,
.name = "amr",
.description = "GSM 26.071 Adaptive Multi Rate codec",
diff --git a/src/codec_efr.c b/src/codec_efr.c
index 339172a..9804bd9 100644
--- a/src/codec_efr.c
+++ b/src/codec_efr.c
@@ -17,20 +17,23 @@
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gapk/codecs.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/benchmark.h>
+#include <osmocom/gapk/bench.h>
#include "config.h"
#ifdef HAVE_OPENCORE_AMRNB
-#include <stdlib.h>
+#include <talloc.h>
#include <assert.h>
#include <opencore-amrnb/interf_dec.h>
#include <opencore-amrnb/interf_enc.h>
+/* Internal root talloc context */
+extern TALLOC_CTX *gapk_root_ctx;
struct codec_efr_state {
void *encoder;
@@ -43,7 +46,7 @@ codec_efr_init(void)
{
struct codec_efr_state *st;
- st = calloc(1, sizeof(*st));
+ st = talloc_zero(gapk_root_ctx, struct codec_efr_state);
if (!st)
return NULL;
@@ -61,6 +64,8 @@ codec_efr_exit(void *state)
Decoder_Interface_exit(st->decoder);
Encoder_Interface_exit(st->encoder);
+ talloc_free(st);
+
return;
}
@@ -108,7 +113,7 @@ codec_efr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod
#endif /* HAVE_OPENCORE_AMRNB */
-const struct codec_desc codec_efr_desc = {
+const struct osmo_gapk_codec_desc codec_efr_desc = {
.type = CODEC_EFR,
.name = "efr",
.description = "GSM 06.60 Enhanced Full Rate codec",
diff --git a/src/codec_fr.c b/src/codec_fr.c
index 917f34b..eddbee6 100644
--- a/src/codec_fr.c
+++ b/src/codec_fr.c
@@ -19,8 +19,9 @@
#include <assert.h>
-#include <gapk/codecs.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/benchmark.h>
+#include <osmocom/gapk/bench.h>
#include "config.h"
@@ -83,7 +84,7 @@ codec_fr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod_
#endif /* HAVE_LIBGSM */
-const struct codec_desc codec_fr_desc = {
+const struct osmo_gapk_codec_desc codec_fr_desc = {
.type = CODEC_FR,
.name = "fr",
.description = "GSM 06.10 Full Rate codec (classic gsm codec)",
diff --git a/src/codec_hr.c b/src/codec_hr.c
index b3247e0..ef66f57 100644
--- a/src/codec_hr.c
+++ b/src/codec_hr.c
@@ -19,8 +19,9 @@
#include <assert.h>
-#include <gapk/codecs.h>
-#include <gapk/benchmark.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/benchmark.h>
+#include <osmocom/gapk/bench.h>
#include "config.h"
@@ -73,7 +74,7 @@ codec_hr_decode(void *_state, uint8_t *pcm, const uint8_t *cod, unsigned int cod
#endif /* HAVE_LIBGSMHR */
-const struct codec_desc codec_hr_desc = {
+const struct osmo_gapk_codec_desc codec_hr_desc = {
.type = CODEC_HR,
.name = "hr",
.description = "GSM 06.20 Half Rate codec",
diff --git a/src/codec_pcm.c b/src/codec_pcm.c
index 9fa8c1b..76cab34 100644
--- a/src/codec_pcm.c
+++ b/src/codec_pcm.c
@@ -17,9 +17,9 @@
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gapk/codecs.h>
+#include <osmocom/gapk/codecs.h>
-const struct codec_desc codec_pcm_desc = {
+const struct osmo_gapk_codec_desc codec_pcm_desc = {
.type = CODEC_PCM,
.name = "pcm",
.description = "Raw PCM signed 16 bits samples",
diff --git a/src/codecs.c b/src/codecs.c
index 623e80c..be5a112 100644
--- a/src/codecs.c
+++ b/src/codecs.c
@@ -19,18 +19,18 @@
#include <stdio.h> /* for NULL */
-#include <gapk/codecs.h>
+#include <osmocom/gapk/codecs.h>
/* Extern codec descriptors */
-extern const struct codec_desc codec_pcm_desc;
-extern const struct codec_desc codec_hr_desc;
-extern const struct codec_desc codec_fr_desc;
-extern const struct codec_desc codec_efr_desc;
-extern const struct codec_desc codec_amr_desc;
+extern const struct osmo_gapk_codec_desc codec_pcm_desc;
+extern const struct osmo_gapk_codec_desc codec_hr_desc;
+extern const struct osmo_gapk_codec_desc codec_fr_desc;
+extern const struct osmo_gapk_codec_desc codec_efr_desc;
+extern const struct osmo_gapk_codec_desc codec_amr_desc;
-const struct codec_desc *
-codec_get_from_type(enum codec_type type)
+const struct osmo_gapk_codec_desc *
+osmo_gapk_codec_get_from_type(enum osmo_gapk_codec_type type)
{
switch (type) {
case CODEC_PCM: return &codec_pcm_desc;
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..c7c5c32
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of gapk (GSM Audio Pocket Knife).
+ *
+ * (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com>
+ *
+ * gapk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gapk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gapk. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <talloc.h>
+
+/* Internal root talloc context */
+TALLOC_CTX *gapk_root_ctx = NULL;
+
+void osmo_gapk_set_talloc_ctx(void *ctx)
+{
+ gapk_root_ctx = ctx;
+}
+
+/* Internal GAPK logging */
+int gapk_log_init_complete = 0;
+int gapk_log_subsys;
+
+void osmo_gapk_log_init(int subsys)
+{
+ gapk_log_subsys = subsys;
+ gapk_log_init_complete = 1;
+}
diff --git a/src/fmt_amr.c b/src/fmt_amr.c
index e28024c..3694f8a 100644
--- a/src/fmt_amr.c
+++ b/src/fmt_amr.c
@@ -22,9 +22,9 @@
#include <osmocom/codec/codec.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
#define EFR_LEN 32
@@ -70,7 +70,7 @@ amr_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return EFR_CANON_LEN;
}
-const struct format_desc fmt_amr_efr = {
+const struct osmo_gapk_format_desc fmt_amr_efr = {
.type = FMT_AMR_EFR,
.codec_type = CODEC_EFR,
.name = "amr-efr",
diff --git a/src/fmt_amr_opencore.c b/src/fmt_amr_opencore.c
index 3fa547b..640595e 100644
--- a/src/fmt_amr_opencore.c
+++ b/src/fmt_amr_opencore.c
@@ -21,9 +21,9 @@
#include <stdint.h>
#include <string.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
static int
amr_opencore_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
@@ -39,7 +39,7 @@ amr_opencore_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return src_len;
}
-const struct format_desc fmt_amr_opencore = {
+const struct osmo_gapk_format_desc fmt_amr_opencore = {
.type = FMT_AMR_OPENCORE,
.codec_type = CODEC_AMR,
.name = "amr-opencore",
diff --git a/src/fmt_gsm.c b/src/fmt_gsm.c
index 27701f0..e97ac9b 100644
--- a/src/fmt_gsm.c
+++ b/src/fmt_gsm.c
@@ -18,8 +18,8 @@
*/
#include <assert.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
#define GSM_LEN 33
#define GSM_MAGIC 0xd
@@ -54,7 +54,7 @@ gsm_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return FR_CANON_LEN;
}
-const struct format_desc fmt_gsm = {
+const struct osmo_gapk_format_desc fmt_gsm = {
.type = FMT_GSM,
.codec_type = CODEC_FR,
.name = "gsm",
diff --git a/src/fmt_hr_ref.c b/src/fmt_hr_ref.c
index d64918b..0394b76 100644
--- a/src/fmt_hr_ref.c
+++ b/src/fmt_hr_ref.c
@@ -22,9 +22,9 @@
#include <assert.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
static const int params_unvoiced[] = {
5, /* R0 */
@@ -191,7 +191,7 @@ hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
}
-const struct format_desc fmt_hr_ref_dec = {
+const struct osmo_gapk_format_desc fmt_hr_ref_dec = {
.type = FMT_HR_REF_DEC,
.codec_type = CODEC_HR,
.name = "hr-ref-dec",
@@ -202,7 +202,7 @@ const struct format_desc fmt_hr_ref_dec = {
.conv_to_canon = hr_ref_dec_to_canon,
};
-const struct format_desc fmt_hr_ref_enc = {
+const struct osmo_gapk_format_desc fmt_hr_ref_enc = {
.type = FMT_HR_REF_ENC,
.codec_type = CODEC_HR,
.name = "hr-ref-enc",
diff --git a/src/fmt_racal.c b/src/fmt_racal.c
index 1dbc61d..7bb53dd 100644
--- a/src/fmt_racal.c
+++ b/src/fmt_racal.c
@@ -22,9 +22,9 @@
#include <osmocom/codec/codec.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
#define RACAL_HR_LEN 14
#define RACAL_FR_LEN 33
@@ -76,7 +76,7 @@ racal_hr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return RACAL_HR_LEN;
}
-const struct format_desc fmt_racal_hr = {
+const struct osmo_gapk_format_desc fmt_racal_hr = {
.type = FMT_RACAL_HR,
.codec_type = CODEC_HR,
.name = "racal-hr",
@@ -124,7 +124,7 @@ racal_fr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return FR_CANON_LEN;
}
-const struct format_desc fmt_racal_fr = {
+const struct osmo_gapk_format_desc fmt_racal_fr = {
.type = FMT_RACAL_FR,
.codec_type = CODEC_FR,
.name = "racal-fr",
@@ -166,7 +166,7 @@ racal_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return EFR_CANON_LEN;
}
-const struct format_desc fmt_racal_efr = {
+const struct osmo_gapk_format_desc fmt_racal_efr = {
.type = FMT_RACAL_EFR,
.codec_type = CODEC_EFR,
.name = "racal-efr",
diff --git a/src/fmt_rawpcm.c b/src/fmt_rawpcm.c
index 207708c..7b45060 100644
--- a/src/fmt_rawpcm.c
+++ b/src/fmt_rawpcm.c
@@ -19,8 +19,8 @@
#include <assert.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
static int
rawpcm_s16le_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
@@ -53,7 +53,7 @@ rawpcm_s16le_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return PCM_CANON_LEN;
}
-const struct format_desc fmt_rawpcm_s16le = {
+const struct osmo_gapk_format_desc fmt_rawpcm_s16le = {
.type = FMT_RAWPCM_S16LE,
.codec_type = CODEC_PCM,
.name = "rawpcm-s16le",
diff --git a/src/fmt_rtp_amr.c b/src/fmt_rtp_amr.c
index 1d5357d..a6a3c9f 100644
--- a/src/fmt_rtp_amr.c
+++ b/src/fmt_rtp_amr.c
@@ -23,9 +23,9 @@
#include <osmocom/codec/codec.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
/* conversion function: RTP payload -> canonical format */
static int
@@ -48,7 +48,7 @@ rtp_amr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return src_len-1;
}
-const struct format_desc fmt_rtp_amr = {
+const struct osmo_gapk_format_desc fmt_rtp_amr = {
.type = FMT_RTP_AMR,
.codec_type = CODEC_AMR,
.name = "rtp-amr",
diff --git a/src/fmt_rtp_efr.c b/src/fmt_rtp_efr.c
index 0132e32..accfd4f 100644
--- a/src/fmt_rtp_efr.c
+++ b/src/fmt_rtp_efr.c
@@ -23,9 +23,9 @@
#include <osmocom/codec/codec.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
#define EFR_LEN 31
#define EFR_MAGIC 0xc
@@ -61,7 +61,7 @@ rtp_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return EFR_CANON_LEN;
}
-const struct format_desc fmt_rtp_efr = {
+const struct osmo_gapk_format_desc fmt_rtp_efr = {
.type = FMT_RTP_EFR,
.codec_type = CODEC_EFR,
.name = "rtp-efr",
diff --git a/src/fmt_rtp_hr_etsi.c b/src/fmt_rtp_hr_etsi.c
index fe6728a..9ed9b22 100644
--- a/src/fmt_rtp_hr_etsi.c
+++ b/src/fmt_rtp_hr_etsi.c
@@ -22,9 +22,9 @@
#include <assert.h>
#include <string.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
/* conversion function: RTP payload -> canonical format */
static int
@@ -48,7 +48,7 @@ rtp_hr_etsi_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return HR_CANON_LEN;
}
-const struct format_desc fmt_rtp_hr_etsi = {
+const struct osmo_gapk_format_desc fmt_rtp_hr_etsi = {
.type = FMT_RTP_HR_ETSI,
.codec_type = CODEC_HR,
.name = "rtp-hr-etsi",
diff --git a/src/fmt_rtp_hr_ietf.c b/src/fmt_rtp_hr_ietf.c
index 3e8e6a3..4ee548f 100644
--- a/src/fmt_rtp_hr_ietf.c
+++ b/src/fmt_rtp_hr_ietf.c
@@ -22,9 +22,9 @@
#include <assert.h>
#include <string.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
#define HR_LEN (HR_CANON_LEN+1)
@@ -68,7 +68,7 @@ rtp_hr_ietf_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return HR_CANON_LEN;
}
-const struct format_desc fmt_rtp_hr_ietf = {
+const struct osmo_gapk_format_desc fmt_rtp_hr_ietf = {
.type = FMT_RTP_HR_IETF,
.codec_type = CODEC_HR,
.name = "rtp-hr-ietf",
diff --git a/src/fmt_ti.c b/src/fmt_ti.c
index 582bff4..d7a1ec7 100644
--- a/src/fmt_ti.c
+++ b/src/fmt_ti.c
@@ -30,9 +30,9 @@
#include <osmocom/codec/codec.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/utils.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/utils.h>
#define TI_LEN 33
@@ -84,7 +84,7 @@ ti_hr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return HR_CANON_LEN;
}
-const struct format_desc fmt_ti_hr = {
+const struct osmo_gapk_format_desc fmt_ti_hr = {
.type = FMT_TI_HR,
.codec_type = CODEC_HR,
.name = "ti-hr",
@@ -132,7 +132,7 @@ ti_fr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return FR_CANON_LEN;
}
-const struct format_desc fmt_ti_fr = {
+const struct osmo_gapk_format_desc fmt_ti_fr = {
.type = FMT_TI_FR,
.codec_type = CODEC_FR,
.name = "ti-fr",
@@ -224,7 +224,7 @@ ti_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
return EFR_CANON_LEN;
}
-const struct format_desc fmt_ti_efr = {
+const struct osmo_gapk_format_desc fmt_ti_efr = {
.type = FMT_TI_EFR,
.codec_type = CODEC_EFR,
.name = "ti-efr",
diff --git a/src/formats.c b/src/formats.c
index 60182fe..835af6b 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -20,27 +20,27 @@
#include <stdio.h> /* for NULL */
#include <string.h>
-#include <gapk/formats.h>
+#include <osmocom/gapk/formats.h>
/* Extern format descriptors */
-extern const struct format_desc fmt_amr_efr;
-extern const struct format_desc fmt_gsm;
-extern const struct format_desc fmt_hr_ref_dec;
-extern const struct format_desc fmt_hr_ref_enc;
-extern const struct format_desc fmt_racal_hr;
-extern const struct format_desc fmt_racal_fr;
-extern const struct format_desc fmt_racal_efr;
-extern const struct format_desc fmt_rawpcm_s16le;
-extern const struct format_desc fmt_ti_hr;
-extern const struct format_desc fmt_ti_fr;
-extern const struct format_desc fmt_ti_efr;
-extern const struct format_desc fmt_amr_opencore;
-extern const struct format_desc fmt_rtp_amr;
-extern const struct format_desc fmt_rtp_efr;
-extern const struct format_desc fmt_rtp_hr_etsi;
-extern const struct format_desc fmt_rtp_hr_ietf;
+extern const struct osmo_gapk_format_desc fmt_amr_efr;
+extern const struct osmo_gapk_format_desc fmt_gsm;
+extern const struct osmo_gapk_format_desc fmt_hr_ref_dec;
+extern const struct osmo_gapk_format_desc fmt_hr_ref_enc;
+extern const struct osmo_gapk_format_desc fmt_racal_hr;
+extern const struct osmo_gapk_format_desc fmt_racal_fr;
+extern const struct osmo_gapk_format_desc fmt_racal_efr;
+extern const struct osmo_gapk_format_desc fmt_rawpcm_s16le;
+extern const struct osmo_gapk_format_desc fmt_ti_hr;
+extern const struct osmo_gapk_format_desc fmt_ti_fr;
+extern const struct osmo_gapk_format_desc fmt_ti_efr;
+extern const struct osmo_gapk_format_desc fmt_amr_opencore;
+extern const struct osmo_gapk_format_desc fmt_rtp_amr;
+extern const struct osmo_gapk_format_desc fmt_rtp_efr;
+extern const struct osmo_gapk_format_desc fmt_rtp_hr_etsi;
+extern const struct osmo_gapk_format_desc fmt_rtp_hr_ietf;
-static const struct format_desc *supported_formats[_FMT_MAX] = {
+static const struct osmo_gapk_format_desc *supported_formats[_FMT_MAX] = {
[FMT_INVALID] = NULL,
[FMT_AMR_EFR] = &fmt_amr_efr,
[FMT_GSM] = &fmt_gsm,
@@ -61,20 +61,20 @@ static const struct format_desc *supported_formats[_FMT_MAX] = {
};
-const struct format_desc *
-fmt_get_from_type(enum format_type type)
+const struct osmo_gapk_format_desc *
+osmo_gapk_fmt_get_from_type(enum osmo_gapk_format_type type)
{
if (type <= FMT_INVALID || type >= _FMT_MAX)
return NULL;
return supported_formats[type];
}
-const struct format_desc *
-fmt_get_from_name(const char *name)
+const struct osmo_gapk_format_desc *
+osmo_gapk_fmt_get_from_name(const char *name)
{
int i;
for (i=FMT_INVALID+1; i<_FMT_MAX; i++) {
- const struct format_desc *fmt = supported_formats[i];
+ const struct osmo_gapk_format_desc *fmt = supported_formats[i];
if (!fmt)
continue;
if (!strcmp(fmt->name, name))
diff --git a/src/libosmogapk.map b/src/libosmogapk.map
new file mode 100644
index 0000000..6cd817e
--- /dev/null
+++ b/src/libosmogapk.map
@@ -0,0 +1,4 @@
+LIBOSMOGAPK_1.0 {
+global: osmo_gapk_*;
+local: *;
+};
diff --git a/src/pq_alsa.c b/src/pq_alsa.c
index cad76ca..3550221 100644
--- a/src/pq_alsa.c
+++ b/src/pq_alsa.c
@@ -20,12 +20,12 @@
#include <errno.h>
#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <talloc.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
#include "config.h"
@@ -69,22 +69,30 @@ pq_cb_alsa_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in
return rv == num_samples ? 0 : -1;
}
+static int
+pq_cb_alsa_wait(void *_state)
+{
+ struct pq_state_alsa *state = _state;
+ return snd_pcm_avail_update(state->pcm_handle) > 0;
+}
+
static void
pq_cb_alsa_exit(void *_state)
{
struct pq_state_alsa *state = _state;
snd_pcm_close(state->pcm_handle);
+ talloc_free(state);
}
static int
-pq_queue_alsa_op(struct pq *pq, const char *alsa_dev, unsigned int blk_len, int in_out_n)
+pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk_len, int in_out_n)
{
- struct pq_item *item;
+ struct osmo_gapk_pq_item *item;
struct pq_state_alsa *state;
snd_pcm_hw_params_t *hw_params;
int rc = -1;
- state = calloc(1, sizeof(struct pq_state_alsa));
+ state = talloc_zero(pq, struct pq_state_alsa);
if (!state) {
rc = -ENOMEM;
goto out_print;
@@ -127,27 +135,37 @@ pq_queue_alsa_op(struct pq *pq, const char *alsa_dev, unsigned int blk_len, int
snd_pcm_hw_params_free(hw_params);
- item = pq_add_item(pq);
+ item = osmo_gapk_pq_add_item(pq);
if (!item) {
rc = -ENOMEM;
goto out_close;
}
+ item->type = in_out_n ?
+ OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK;
+ item->cat_name = in_out_n ?
+ OSMO_GAPK_CAT_NAME_SOURCE : OSMO_GAPK_CAT_NAME_SINK;
+ item->sub_name = "alsa";
+
item->len_in = in_out_n ? 0 : blk_len;
item->len_out = in_out_n ? blk_len : 0;
item->state = state;
item->proc = in_out_n ? pq_cb_alsa_input : pq_cb_alsa_output;
+ item->wait = pq_cb_alsa_wait;
item->exit = pq_cb_alsa_exit;
+ /* Change state's talloc context from pq to item */
+ talloc_steal(item, state);
+
return 0;
out_free_par:
snd_pcm_hw_params_free(hw_params);
out_close:
snd_pcm_close(state->pcm_handle);
- free(state);
+ talloc_free(state);
out_print:
- fprintf(stderr, "[!] Couldn't init ALSA device '%s': %s\n",
+ LOGPGAPK(LOGL_ERROR, "Couldn't init ALSA device '%s': %s\n",
alsa_dev, snd_strerror(rc));
return rc;
}
@@ -160,9 +178,10 @@ out_print:
* \param[in] blk_len block length to be read from device
* \returns 0 on sucess; negative on error */
int
-pq_queue_alsa_input(struct pq *pq, const char *hwdev, unsigned int blk_len)
+osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding ALSA input (dev='%s', blk_len=%u)\n", hwdev, blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding ALSA input "
+ "(dev='%s', blk_len=%u)\n", pq->name, hwdev, blk_len);
return pq_queue_alsa_op(pq, hwdev, blk_len, 1);
}
@@ -173,9 +192,10 @@ pq_queue_alsa_input(struct pq *pq, const char *hwdev, unsigned int blk_len)
* \param[in] blk_len block length to be written to device
* \returns 0 on sucess; negative on error */
int
-pq_queue_alsa_output(struct pq *pq, const char *hwdev, unsigned int blk_len)
+osmo_gapk_pq_queue_alsa_output(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding ALSA output (dev='%s', blk_len=%u)\n", hwdev, blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding ALSA output "
+ "(dev='%s', blk_len=%u)\n", pq->name, hwdev, blk_len);
return pq_queue_alsa_op(pq, hwdev, blk_len, 0);
}
diff --git a/src/pq_codec.c b/src/pq_codec.c
index f1884fb..87afd82 100644
--- a/src/pq_codec.c
+++ b/src/pq_codec.c
@@ -20,9 +20,10 @@
#include <errno.h>
#include <stdint.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
/*! Add a codecl to the processing queue
@@ -31,14 +32,14 @@
* \param[in] encode (1) or decode (0)
* \returns 0 on success; negative on error */
int
-pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int enc_dec_n)
+osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_desc *codec, int enc_dec_n)
{
- const struct codec_desc *codec_pcm = codec_get_from_type(CODEC_PCM);
- const struct format_desc *fmt;
- struct pq_item *item;
+ const struct osmo_gapk_codec_desc *codec_pcm;
+ const struct osmo_gapk_format_desc *fmt;
+ struct osmo_gapk_pq_item *item;
/* allocate a new item to the processing queue */
- item = pq_add_item(pq);
+ item = osmo_gapk_pq_add_item(pq);
if (!item)
return -ENOMEM;
@@ -50,7 +51,8 @@ pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int enc_dec_n)
}
if (enc_dec_n) {
- fmt = fmt_get_from_type(codec->codec_enc_format_type);
+ codec_pcm = osmo_gapk_codec_get_from_type(CODEC_PCM);
+ fmt = osmo_gapk_fmt_get_from_type(codec->codec_enc_format_type);
if (!fmt)
return -EINVAL;
@@ -58,7 +60,8 @@ pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int enc_dec_n)
item->len_out = fmt->frame_len;
item->proc = codec->codec_encode;
} else {
- fmt = fmt_get_from_type(codec->codec_dec_format_type);
+ codec_pcm = osmo_gapk_codec_get_from_type(CODEC_PCM);
+ fmt = osmo_gapk_fmt_get_from_type(codec->codec_dec_format_type);
if (!fmt)
return -EINVAL;
@@ -67,10 +70,17 @@ pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int enc_dec_n)
item->proc = codec->codec_decode;
}
+ item->type = OSMO_GAPK_ITEM_TYPE_PROC;
item->exit = codec->codec_exit;
+ item->wait = NULL;
- fprintf(stderr, "[+] PQ: Adding Codec %s, %s format %s\n", codec->name,
- enc_dec_n ? "encoding to" : "decoding from", fmt->name);
+ /* Meta information */
+ item->cat_name = "codec";
+ item->sub_name = codec->name;
+
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding codec %s, %s format %s\n",
+ pq->name, codec->name, enc_dec_n ?
+ "encoding to" : "decoding from", fmt->name);
if (!item->proc)
return -ENOTSUP;
diff --git a/src/pq_file.c b/src/pq_file.c
index 96f7b3f..22dc9cd 100644
--- a/src/pq_file.c
+++ b/src/pq_file.c
@@ -19,12 +19,12 @@
#include <errno.h>
#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <talloc.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
struct pq_state_file {
@@ -56,34 +56,44 @@ pq_cb_file_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in
static void
pq_cb_file_exit(void *_state)
{
- free(_state);
+ talloc_free(_state);
}
static int
-pq_queue_file_op(struct pq *pq, FILE *fh, unsigned int blk_len, int in_out_n)
+pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in_out_n)
{
- struct pq_item *item;
+ struct osmo_gapk_pq_item *item;
struct pq_state_file *state;
- state = calloc(1, sizeof(struct pq_state_file));
+ state = talloc_zero(pq, struct pq_state_file);
if (!state)
return -ENOMEM;
state->fh = fh;
state->blk_len = blk_len;
- item = pq_add_item(pq);
+ item = osmo_gapk_pq_add_item(pq);
if (!item) {
- free(state);
+ talloc_free(state);
return -ENOMEM;
}
+ item->type = in_out_n ?
+ OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK;
+ item->cat_name = in_out_n ?
+ OSMO_GAPK_CAT_NAME_SOURCE : OSMO_GAPK_CAT_NAME_SINK;
+ item->sub_name = "file";
+
item->len_in = in_out_n ? 0 : blk_len;
item->len_out = in_out_n ? blk_len : 0;
item->state = state;
item->proc = in_out_n ? pq_cb_file_input : pq_cb_file_output;
+ item->wait = NULL;
item->exit = pq_cb_file_exit;
+ /* Change state's talloc context from pq to item */
+ talloc_steal(item, state);
+
return 0;
}
@@ -95,9 +105,10 @@ pq_queue_file_op(struct pq *pq, FILE *fh, unsigned int blk_len, int in_out_n)
* \param[in] blk_len block length to be read from file
* \returns 0 on sucess; negative on error */
int
-pq_queue_file_input(struct pq *pq, FILE *src, unsigned int blk_len)
+osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding file input (blk_len=%u)\n", blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding file input (blk_len=%u)\n",
+ pq->name, blk_len);
return pq_queue_file_op(pq, src, blk_len, 1);
}
@@ -108,8 +119,9 @@ pq_queue_file_input(struct pq *pq, FILE *src, unsigned int blk_len)
* \param[in] blk_len block length to be written to file
* \returns 0 on sucess; negative on error */
int
-pq_queue_file_output(struct pq *pq, FILE *dst, unsigned int blk_len)
+osmo_gapk_pq_queue_file_output(struct osmo_gapk_pq *pq, FILE *dst, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding file output (blk_len=%u)\n", blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding file output (blk_len=%u)\n",
+ pq->name, blk_len);
return pq_queue_file_op(pq, dst, blk_len, 0);
}
diff --git a/src/pq_format.c b/src/pq_format.c
index d6bc8af..2c4a2fd 100644
--- a/src/pq_format.c
+++ b/src/pq_format.c
@@ -20,15 +20,16 @@
#include <errno.h>
#include <stdint.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
static int
pq_cb_fmt_convert(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
{
- fmt_conv_cb_t f = _state;
+ osmo_gapk_fmt_conv_cb_t f = _state;
return f(out, in, in_len);
}
@@ -37,36 +38,44 @@ pq_cb_fmt_convert(void *_state, uint8_t *out, const uint8_t *in, unsigned int in
* \param[in] fmt Format description for conversion
* \param[in] to_from_n convert to (0) or from (1) specified format */
int
-pq_queue_fmt_convert(struct pq *pq, const struct format_desc *fmt, int to_from_n)
+osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_format_desc *fmt, int to_from_n)
{
- struct pq_item *item;
- const struct codec_desc *codec = codec_get_from_type(fmt->codec_type);
+ const struct osmo_gapk_codec_desc *codec;
+ struct osmo_gapk_pq_item *item;
+ codec = osmo_gapk_codec_get_from_type(fmt->codec_type);
if (!codec) {
- fprintf(stderr, "[!] Cannot determine codec from format %s\n", fmt->name);
+ LOGPGAPK(LOGL_ERROR, "Cannot determine codec from "
+ "format %s\n", fmt->name);
return -EINVAL;
}
- item = pq_add_item(pq);
+ item = osmo_gapk_pq_add_item(pq);
if (!item)
return -ENOMEM;
if (to_from_n) {
- fprintf(stderr, "[+] PQ: Adding conversion from canon to %s (for codec %s)\n",
- fmt->name, codec->name);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding conversion from canon "
+ "to %s (for codec %s)\n", pq->name, fmt->name, codec->name);
item->len_in = codec->canon_frame_len;
item->len_out = fmt->frame_len;
item->state = fmt->conv_from_canon;
} else {
- fprintf(stderr, "[+] PQ: Adding conversion from %s to canon (for codec %s)\n",
- fmt->name, codec->name);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding conversion from %s "
+ "to canon (for codec %s)\n", pq->name, fmt->name, codec->name);
item->len_in = fmt->frame_len;
item->len_out = codec->canon_frame_len;
item->state = fmt->conv_to_canon;
}
+ item->type = OSMO_GAPK_ITEM_TYPE_PROC;
item->proc = pq_cb_fmt_convert;
+ item->wait = NULL;
+
+ /* Meta information */
+ item->cat_name = "format";
+ item->sub_name = fmt->name;
return 0;
}
diff --git a/src/pq_rtp.c b/src/pq_rtp.c
index f5603de..a50013a 100644
--- a/src/pq_rtp.c
+++ b/src/pq_rtp.c
@@ -20,16 +20,16 @@
#include <errno.h>
#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <talloc.h>
#include <arpa/inet.h>
-#include <gapk/codecs.h>
-#include <gapk/formats.h>
-#include <gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+#include <osmocom/gapk/codecs.h>
+#include <osmocom/gapk/formats.h>
+#include <osmocom/gapk/procqueue.h>
#ifndef __BYTE_ORDER
# ifdef __APPLE__
@@ -86,7 +86,8 @@ struct pq_state_rtp {
uint32_t ssrc;
};
-#define rtp_err(x, args...) fprintf(stderr, "[!] %s():" x, __func__, ## args)
+#define rtp_err(err_msg, args...) \
+ LOGPGAPK(LOGL_ERROR, "%s():" err_msg, __func__, ## args)
static int
pq_cb_rtp_input(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
@@ -188,16 +189,16 @@ pq_cb_rtp_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_
static void
pq_cb_rtp_exit(void *_state)
{
- free(_state);
+ talloc_free(_state);
}
static int
-pq_queue_rtp_op(struct pq *pq, int udp_fd, unsigned int blk_len, int in_out_n)
+pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int in_out_n)
{
- struct pq_item *item;
+ struct osmo_gapk_pq_item *item;
struct pq_state_rtp *state;
- state = calloc(1, sizeof(struct pq_state_rtp));
+ state = talloc_zero(pq, struct pq_state_rtp);
if (!state)
return -ENOMEM;
@@ -217,18 +218,28 @@ pq_queue_rtp_op(struct pq *pq, int udp_fd, unsigned int blk_len, int in_out_n)
state->payload_type = RTP_PT_GSM_FULL;
}
- item = pq_add_item(pq);
+ item = osmo_gapk_pq_add_item(pq);
if (!item) {
- free(state);
+ talloc_free(state);
return -ENOMEM;
}
+ item->type = in_out_n ?
+ OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK;
+ item->cat_name = in_out_n ?
+ OSMO_GAPK_CAT_NAME_SOURCE : OSMO_GAPK_CAT_NAME_SINK;
+ item->sub_name = "rtp";
+
item->len_in = in_out_n ? 0 : blk_len;
item->len_out = in_out_n ? blk_len : 0;
item->state = state;
item->proc = in_out_n ? pq_cb_rtp_input : pq_cb_rtp_output;
+ item->wait = NULL;
item->exit = pq_cb_rtp_exit;
+ /* Change state's talloc context from pq to item */
+ talloc_steal(item, state);
+
return 0;
}
@@ -239,9 +250,10 @@ pq_queue_rtp_op(struct pq *pq, int udp_fd, unsigned int blk_len, int in_out_n)
* \param[in] udp_fd UDP file descriptor for the RTP input
* \param[in] blk_len Block Length to read from RTP */
int
-pq_queue_rtp_input(struct pq *pq, int udp_fd, unsigned int blk_len)
+osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding RTP input (blk_len=%u)\n", blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding RTP input (blk_len=%u)\n",
+ pq->name, blk_len);
return pq_queue_rtp_op(pq, udp_fd, blk_len, 1);
}
@@ -251,8 +263,9 @@ pq_queue_rtp_input(struct pq *pq, int udp_fd, unsigned int blk_len)
* \param[in] udp_fd UDP file descriptor for the RTP output
* \param[in] blk_len Block Length to read from RTP */
int
-pq_queue_rtp_output(struct pq *pq, int udp_fd, unsigned int blk_len)
+osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len)
{
- fprintf(stderr, "[+] PQ: Adding RTP output (blk_len=%u)\n", blk_len);
+ LOGPGAPK(LOGL_DEBUG, "PQ '%s': Adding RTP output (blk_len=%u)\n",
+ pq->name, blk_len);
return pq_queue_rtp_op(pq, udp_fd, blk_len, 0);
}
diff --git a/src/procqueue.c b/src/procqueue.c
index 01ad581..78dee4d 100644
--- a/src/procqueue.c
+++ b/src/procqueue.c
@@ -20,108 +20,164 @@
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
+#include <talloc.h>
-#include <gapk/procqueue.h>
+#include <osmocom/core/linuxlist.h>
-#define VAR_BUF_SIZE 320
-#define MAX_PQ_ITEMS 8
-
-struct pq {
- int n_items;
- struct pq_item* items[MAX_PQ_ITEMS];
- void * buffers[MAX_PQ_ITEMS+1];
-};
+#include <osmocom/gapk/procqueue.h>
+#include <osmocom/gapk/logging.h>
+/* Internal root talloc context */
+extern TALLOC_CTX *gapk_root_ctx;
/* crate a new (empty) processing queue */
-struct pq *
-pq_create(void)
+struct osmo_gapk_pq *
+osmo_gapk_pq_create(const char *name)
{
- return (struct pq *) calloc(1, sizeof(struct pq));
+ struct osmo_gapk_pq *pq;
+
+ /* Allocate memory for a new processing queue */
+ pq = talloc_zero(gapk_root_ctx, struct osmo_gapk_pq);
+ if (!pq)
+ return NULL;
+
+ if (name != NULL) {
+ /* Rename talloc context */
+ talloc_set_name(pq, "struct osmo_gapk_pq '%s'", name);
+ /* Set queue name */
+ pq->name = name;
+ }
+
+ /* Init its list of items */
+ INIT_LLIST_HEAD(&pq->items);
+
+ return pq;
}
/*! destroy a processing queue, calls exit() callback of each item
* \param[in] pq Processing Queue to be destroyed */
void
-pq_destroy(struct pq *pq)
+osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq)
{
- int i;
+ struct osmo_gapk_pq_item *item, *item_next;
if (!pq)
return;
- for (i=0; i<pq->n_items; i++) {
- if (!pq->items[i])
- continue;
- if (pq->items[i]->exit)
- pq->items[i]->exit(pq->items[i]->state);
- free(pq->items[i]);
- }
+ /* Iterate over all items in queue */
+ llist_for_each_entry_safe(item, item_next, &pq->items, list) {
+ /* Free output buffer memory */
+ talloc_free(item->buf);
- for (i=0; i<pq->n_items-1; i++)
- free(pq->buffers[i]); /* free is NULL safe */
+ /* Call exit handler if preset */
+ if (item->exit)
+ item->exit(item->state);
- free(pq);
+ /* Delete an item from list */
+ llist_del(&item->list);
+ talloc_free(item);
+ }
+
+ talloc_free(pq);
}
/*! allocate + add an item to a processing queue; return new item
* \param[in] pq Processing Queue to which item is added
* \returns new PQ item; NULL on error */
-struct pq_item *
-pq_add_item(struct pq *pq)
+struct osmo_gapk_pq_item *
+osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq)
{
- struct pq_item *item;
-
- if (pq->n_items == MAX_PQ_ITEMS) {
- fprintf(stderr, "[!] Processing Queue cannot handle more than %u items\n",
- MAX_PQ_ITEMS);
- return NULL;
- }
+ struct osmo_gapk_pq_item *item;
- item = calloc(1, sizeof(struct pq_item));
+ /* Allocate memory for a new item */
+ item = talloc_zero(pq, struct osmo_gapk_pq_item);
if (!item)
return NULL;
- pq->items[pq->n_items++] = item;
+ /* Add one to the end of a queue */
+ llist_add_tail(&item->list, &pq->items);
+
+ /* Increase the items count */
+ pq->n_items++;
return item;
}
-/*! prepare a processing queue; allocates buffers; checks lengths
- * \param[in] pq Processing Queue to be prepared
+/*! check a processing queue; make sure I/O data lengths are equal
+ * \param[in] pq Make sure both source and sink are preset
+ * \param[in] strict Processing Queue to be checked
* \returns 0 on succcess; negative on error */
int
-pq_prepare(struct pq *pq)
+osmo_gapk_pq_check(struct osmo_gapk_pq *pq, int strict)
{
- int i;
- unsigned int len_prev;
+ struct osmo_gapk_pq_item *item_prev = NULL;
+ struct osmo_gapk_pq_item *item;
+
+ /* Make sure I/O data lengths are equal */
+ llist_for_each_entry(item, &pq->items, list) {
+ if (item_prev && item->len_in) {
+ if (item->len_in != item_prev->len_out) {
+ LOGPGAPK(LOGL_ERROR, "PQ '%s': item '%s/%s' requires "
+ "input size %u, but previous '%s/%s' has %u\n",
+ pq->name, item->cat_name, item->sub_name,
+ item->len_in, item_prev->cat_name,
+ item_prev->sub_name, item_prev->len_out);
+ return -EINVAL;
+ }
+ }
- len_prev = 0;
+ /* Save pointer to the previous item */
+ item_prev = item;
+ }
- for (i=0; i<pq->n_items; i++) {
- struct pq_item *item = pq->items[i];
+ if (strict) {
+ /* Make sure the first item is a source */
+ item = llist_first_entry(&pq->items,
+ struct osmo_gapk_pq_item, list);
+ if (item->type != OSMO_GAPK_ITEM_TYPE_SOURCE)
+ goto src_sink_err;
+
+ /* Make sure the last item is a sink */
+ item = llist_last_entry(&pq->items,
+ struct osmo_gapk_pq_item, list);
+ if (item->type != OSMO_GAPK_ITEM_TYPE_SINK)
+ goto src_sink_err;
+ }
- if (item->len_in && item->len_in != len_prev) {
- fprintf(stderr, "[!] PQ item requires input size %u, but previous output is %u\n",
- item->len_in, len_prev);
- return -EINVAL;
- }
+ return 0;
+
+src_sink_err:
+ LOGPGAPK(LOGL_ERROR, "PQ '%s': the first item should be a source, "
+ "and the last one should be a sink\n", pq->name);
+ return -EINVAL;
+}
- if (i < (pq->n_items-1)) {
+/*! prepare a processing queue; allocates buffers
+ * \param[in] pq Processing Queue to be prepared
+ * \returns 0 on succcess; negative on error */
+int
+osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq)
+{
+ struct osmo_gapk_pq_item *item;
+
+ /* Iterate over all items in queue */
+ llist_for_each_entry(item, &pq->items, list) {
+ /* The sink item doesn't require an output buffer */
+ if (item->list.next != &pq->items) {
unsigned int buf_size = item->len_out;
- /* variable-length codec output, use maximum
- * known buffer size */
+
+ /**
+ * Use maximum known buffer size
+ * for variable-length codec output
+ */
if (!buf_size)
buf_size = VAR_BUF_SIZE;
- pq->buffers[i] = malloc(buf_size);
- if (!pq->buffers[i])
+
+ /* Allocate memory for an output buffer */
+ item->buf = talloc_named_const(item, buf_size, ".buffer");
+ if (!item->buf)
return -ENOMEM;
- } else{
- if (item->len_out)
- return -EINVAL;
}
-
- len_prev = item->len_out;
}
return 0;
@@ -131,30 +187,54 @@ pq_prepare(struct pq *pq)
* \param[in] pq Processing Queue to be executed
* \returns 0 on success; negative on error (if any item returns negative) */
int
-pq_execute(struct pq *pq)
+osmo_gapk_pq_execute(struct osmo_gapk_pq *pq)
{
- int i;
- void *buf_prev, *buf;
- unsigned int len_prev;
-
- buf_prev = NULL;
- len_prev = 0;
-
- for (i=0; i<pq->n_items; i++) {
- int rv;
- struct pq_item *item = pq->items[i];
-
- buf = i < (pq->n_items-1) ? pq->buffers[i] : NULL;
-
- rv = item->proc(item->state, buf, buf_prev, len_prev);
+ struct osmo_gapk_pq_item *item;
+ unsigned int len_prev = 0;
+ uint8_t *buf_prev = NULL;
+ int rv;
+
+ /* Iterate over all items in queue */
+ llist_for_each_entry(item, &pq->items, list) {
+ /* Call item's processing handler */
+ rv = item->proc(item->state, item->buf, buf_prev, len_prev);
if (rv < 0) {
- fprintf(stderr, "[!] pq_execute(): abort, item returned %d\n", rv);
+ LOGPGAPK(LOGL_ERROR, "PQ '%s': execution aborted: "
+ "item '%s/%s' returned %d\n", pq->name,
+ item->cat_name, item->sub_name, rv);
return rv;
}
- buf_prev = buf;
+ buf_prev = item->buf;
len_prev = rv;
}
return 0;
}
+
+char *
+osmo_gapk_pq_describe(struct osmo_gapk_pq *pq)
+{
+ struct osmo_gapk_pq_item *item;
+ char *result = NULL;
+ int i = 0;
+
+ /* Nothing to describe */
+ if (!pq->n_items)
+ return NULL;
+
+ /* Iterate over all items in queue */
+ llist_for_each_entry(item, &pq->items, list) {
+ result = talloc_asprintf_append(result, "%s/%s%s",
+ item->cat_name, item->sub_name,
+ ++i < pq->n_items ? " -> " : "");
+ }
+
+ /* Change talloc context name */
+ talloc_set_name_const(result, ".description");
+
+ /* Change parent talloc context to pq */
+ talloc_steal(pq, result);
+
+ return result;
+}