From 95e666404e1e31dfb95d7dc8b00c1b0be88659b3 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 30 Aug 2017 19:03:49 +0700 Subject: Introduce a shared 'libosmogapk' library The previous GAPK implementation was represented as a single executable. So, all audio transcoding operations were available only by calling the 'gapk' binary. This approach didn't allow external applications to benefit from using GAPK API directly. Since there are some projects (such as GR-GSM and OsmocomBB), which are potential users of GAPK code base, it would be better to have all transcoding functions within a shared library. So, this change separates the common code into a shared library, named 'libosmogapk', and links the 'gapk' binary against one. Currently there are no shared headers, pkg-config manifest and the export map, but they will be done latter. --- src/Makefile.am | 100 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e0b622c..93bdfa1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,20 +1,90 @@ -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) - -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 +# 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 -bin_PROGRAMS = gapk +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCODEC_CFLAGS) \ + ${OPENCORE_AMRNB_CFLAGS} \ + $(LIBALSA_CFLAGS) \ + $(NULL) + +lib_LTLIBRARIES = libosmogapk.la -gapk_SOURCES = main.c $(COM_SOURCES) +libosmogapk_la_LDFLAGS = \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCODEC_LIBS) \ + ${OPENCORE_AMRNB_LIBS} \ + ${LIBGSM_LIBS} \ + $(LIBALSA_LIBS) \ + -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) + +# libosmogapk representative application +bin_PROGRAMS = gapk + +gapk_SOURCES = \ + main.c \ + $(NULL) + +gapk_LDFLAGS = \ + $(LIBOSMOCORE_LIBS) \ + $(NULL) + +gapk_LDADD = \ + $(top_builddir)/src/libosmogapk.la \ + $(NULL) -- cgit v1.2.3 From 48206ad2e07216e01c9870b606aee442b3d7ec0e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 30 Aug 2017 19:35:51 +0700 Subject: Add an 'osmo' prefix to the 'gapk' binary This is a common practice of all Osmocom executables to have an 'osmo' prefix. Let's follow this here too. --- .gitignore | 2 +- contrib/benchmark.sh | 2 +- src/Makefile.am | 8 ++++---- test/common.sh | 10 +++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 93316ad..6288340 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ stamp-h1 libgsmhr/refsrc # final executables -src/gapk +src/osmo-gapk # temporary/backup files *.*~ diff --git a/contrib/benchmark.sh b/contrib/benchmark.sh index 0148667..0e86876 100755 --- a/contrib/benchmark.sh +++ b/contrib/benchmark.sh @@ -1,6 +1,6 @@ #!/bin/sh -GAPK=./src/gapk +GAPK=./src/osmo-gapk PCMFILE=$1 BASE=`basename $PCMFILE` diff --git a/src/Makefile.am b/src/Makefile.am index 93bdfa1..c38f2fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,16 +75,16 @@ libosmogapk_la_SOURCES += \ $(NULL) # libosmogapk representative application -bin_PROGRAMS = gapk +bin_PROGRAMS = osmo-gapk -gapk_SOURCES = \ +osmo_gapk_SOURCES = \ main.c \ $(NULL) -gapk_LDFLAGS = \ +osmo_gapk_LDFLAGS = \ $(LIBOSMOCORE_LIBS) \ $(NULL) -gapk_LDADD = \ +osmo_gapk_LDADD = \ $(top_builddir)/src/libosmogapk.la \ $(NULL) diff --git a/test/common.sh b/test/common.sh index 591be3a..5fded94 100644 --- a/test/common.sh +++ b/test/common.sh @@ -1,13 +1,13 @@ # directory containing the reference files for comparing against REFDIR=./ref-files -if [ -f ../src/gapk ]; then - GAPK=../src/gapk -elif [ -f `which gapk` ]; then - GAPK=`which gapk` +if [ -f ../src/osmo-gapk ]; then + GAPK=../src/osmo-gapk +elif [ -f `which osmo-gapk` ]; then + GAPK=`which osmo-gapk` else exit 1 fi -echo Using gapk found at $GAPK +echo Using osmo-gapk found at $GAPK FORMATS="amr-efr gsm racal-hr racal-fr racal-efr ti-hr ti-fr ti-efr rtp-efr rtp-hr-etsi rtp-hr-ietf" -- cgit v1.2.3 From 30209cedddb3b6ece5614b40f65f6a04e84388b4 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 30 Aug 2017 20:26:02 +0700 Subject: Install GAPK headers to '${includedir}/osmocom/gapk/' To be able to use the library, external applications need to know, which symbols are exposed. This information is provided by header files, which are being installed to a system's ${includedir} since this change. --- configure.ac | 1 - include/Makefile.am | 14 +++- include/gapk/Makefile.am | 6 -- include/gapk/benchmark.h | 60 ----------------- include/gapk/codecs.h | 71 -------------------- include/gapk/formats.h | 94 -------------------------- include/gapk/get_cycles.h | 138 -------------------------------------- include/gapk/procqueue.h | 72 -------------------- include/gapk/utils.h | 104 ---------------------------- include/osmocom/gapk/benchmark.h | 60 +++++++++++++++++ include/osmocom/gapk/codecs.h | 71 ++++++++++++++++++++ include/osmocom/gapk/formats.h | 94 ++++++++++++++++++++++++++ include/osmocom/gapk/get_cycles.h | 138 ++++++++++++++++++++++++++++++++++++++ include/osmocom/gapk/procqueue.h | 72 ++++++++++++++++++++ include/osmocom/gapk/utils.h | 104 ++++++++++++++++++++++++++++ src/benchmark.c | 2 +- src/codec_amr.c | 4 +- src/codec_efr.c | 4 +- src/codec_fr.c | 4 +- src/codec_hr.c | 4 +- src/codec_pcm.c | 2 +- src/codecs.c | 2 +- src/fmt_amr.c | 6 +- src/fmt_amr_opencore.c | 6 +- src/fmt_gsm.c | 4 +- src/fmt_hr_ref.c | 6 +- src/fmt_racal.c | 6 +- src/fmt_rawpcm.c | 4 +- src/fmt_rtp_amr.c | 6 +- src/fmt_rtp_efr.c | 6 +- src/fmt_rtp_hr_etsi.c | 6 +- src/fmt_rtp_hr_ietf.c | 6 +- src/fmt_ti.c | 6 +- src/formats.c | 2 +- src/main.c | 8 +-- src/pq_alsa.c | 6 +- src/pq_codec.c | 6 +- src/pq_file.c | 6 +- src/pq_format.c | 6 +- src/pq_rtp.c | 6 +- src/procqueue.c | 2 +- 41 files changed, 614 insertions(+), 611 deletions(-) delete mode 100644 include/gapk/Makefile.am delete mode 100644 include/gapk/benchmark.h delete mode 100644 include/gapk/codecs.h delete mode 100644 include/gapk/formats.h delete mode 100644 include/gapk/get_cycles.h delete mode 100644 include/gapk/procqueue.h delete mode 100644 include/gapk/utils.h create mode 100644 include/osmocom/gapk/benchmark.h create mode 100644 include/osmocom/gapk/codecs.h create mode 100644 include/osmocom/gapk/formats.h create mode 100644 include/osmocom/gapk/get_cycles.h create mode 100644 include/osmocom/gapk/procqueue.h create mode 100644 include/osmocom/gapk/utils.h diff --git a/configure.ac b/configure.ac index c24e8f0..85d722d 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,6 @@ AC_CONFIG_FILES([ src/Makefile libgsmhr/Makefile include/Makefile - include/gapk/Makefile include/gsmhr/Makefile ]) diff --git a/include/Makefile.am b/include/Makefile.am index ddb25df..f64faeb 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,15 @@ -SUBDIRS = gapk +noinst_HEADERS = \ + osmocom/gapk/utils.h \ + $(NULL) + +nobase_include_HEADERS = \ + osmocom/gapk/get_cycles.h \ + osmocom/gapk/benchmark.h \ + osmocom/gapk/procqueue.h \ + osmocom/gapk/formats.h \ + osmocom/gapk/codecs.h \ + $(NULL) if ENABLE_GSMHR -SUBDIRS += gsmhr +SUBDIRS = gsmhr endif diff --git a/include/gapk/Makefile.am b/include/gapk/Makefile.am deleted file mode 100644 index 5fcc3b9..0000000 --- a/include/gapk/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -noinst_HEADERS = benchmark.h \ - codecs.h \ - formats.h \ - get_cycles.h \ - procqueue.h \ - utils.h diff --git a/include/gapk/benchmark.h b/include/gapk/benchmark.h deleted file mode 100644 index 49c2c36..0000000 --- a/include/gapk/benchmark.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _BENCHMARK_H -#define _BENCHMARK_H - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - * - * (C) 2014 Harald Welte - */ - -#include -#include - -#define NUM_AVG 102400 - -struct benchmark_cycles { - cycles_t enc[NUM_AVG]; - unsigned int enc_used; - cycles_t dec[NUM_AVG]; - unsigned int dec_used; -}; - -extern struct benchmark_cycles codec_cycles[_CODEC_MAX]; - -static inline void benchmark_stop(enum codec_type codec, int encode, unsigned long cycles) -{ - struct benchmark_cycles *bc = &codec_cycles[codec]; - - if (encode) { - bc->enc_used = (bc->enc_used + 1) % NUM_AVG; - bc->enc[bc->enc_used] = cycles; - } else { - bc->dec_used = (bc->dec_used + 1) % NUM_AVG; - bc->dec[bc->dec_used] = cycles; - } -} - -#define BENCHMARK_START do { \ - cycles_t _cycles_start, _cycles_stop; \ - _cycles_start = get_cycles() - -#define BENCHMARK_STOP(x,y) _cycles_stop = get_cycles(); \ - benchmark_stop(x, y, _cycles_stop - _cycles_start); \ - } while (0) - -void benchmark_dump(void); - -#endif diff --git a/include/gapk/codecs.h b/include/gapk/codecs.h deleted file mode 100644 index aa1c829..0000000 --- a/include/gapk/codecs.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Codecs handling */ - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - */ - -#ifndef __GAPK_CODECS_H__ -#define __GAPK_CODECS_H__ - -#include - -#define FR_CANON_LEN 33 -#define HR_CANON_LEN 14 -#define EFR_CANON_LEN 31 -#define PCM_CANON_LEN (160*sizeof(uint16_t)) -#define HR_REF_ENC_LEN (20 * sizeof(uint16_t)) -#define HR_REF_DEC_LEN (22 * sizeof(uint16_t)) - -enum codec_type { - CODEC_INVALID = 0, - CODEC_PCM, /* 16 bits PCM samples */ - CODEC_HR, /* GSM Half Rate codec GSM 06.20 */ - CODEC_FR, /* GSM Full Rate codec GSM 06.10 */ - CODEC_EFR, /* GSM Enhanced Full Rate codec GSM 06.60 */ - CODEC_AMR, /* GSM Adaptive Multi Rate codec GSM 26.071 */ - _CODEC_MAX, -}; - -#include /* need to import here because or enum interdep */ - -/*! call-back for actual codec conversion function - * \param[in] state opaque state pointer (returned by codec->init) - * \param[out] dst caller-allocated buffer for output data - * \param[in] src input data - * \param[in] src_len length of input data \a src - * \returns number of output bytes written to \a dst; negative on error */ -typedef int (*codec_conv_cb_t)(void *state, uint8_t *dst, const uint8_t *src, unsigned int src_len); - -struct codec_desc { - enum codec_type type; - const char * name; - const char * description; - /*! canonical frame size (in bytes); 0 in case of variable length */ - unsigned int canon_frame_len; - - enum format_type codec_enc_format_type; /* what the encoder provides */ - enum format_type codec_dec_format_type; /* what to give the decoder */ - /*! codec initialization function pointer, returns opaque state */ - void * (*codec_init)(void); - /*! codec exit function pointer, gets passed opaque state */ - void (*codec_exit)(void *state); - codec_conv_cb_t codec_encode; - codec_conv_cb_t codec_decode; -}; - -const struct codec_desc *codec_get_from_type(enum codec_type type); - -#endif /* __GAPK_CODECS_H__ */ diff --git a/include/gapk/formats.h b/include/gapk/formats.h deleted file mode 100644 index 81670b8..0000000 --- a/include/gapk/formats.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Formats handling */ - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - */ - -#ifndef __GAPK_FORMATS_H__ -#define __GAPK_FORMATS_H__ - -#include - -enum format_type { - FMT_INVALID = 0, - - /* Classic .amr container */ - FMT_AMR_EFR, - - /* Classic .gsm file for FR */ - FMT_GSM, - - /* 3GPP Reference HR vocodec files */ - FMT_HR_REF_DEC, - FMT_HR_REF_ENC, - - /* Racal 6103E TCH recordings */ - FMT_RACAL_HR, - FMT_RACAL_FR, - FMT_RACAL_EFR, - - /* Raw PCM */ - FMT_RAWPCM_S16LE, - - /* Texas Instrument calypso/locosto buffer format */ - FMT_TI_HR, - FMT_TI_FR, - FMT_TI_EFR, - - /* AMR encoded data, variable length */ - FMT_AMR_OPENCORE, - FMT_RTP_AMR, - - FMT_RTP_EFR, - - /* HR in RTP according to ETSI TS 101 318 */ - FMT_RTP_HR_ETSI, - /* HR in RTP according to IETF RFC5993 */ - FMT_RTP_HR_IETF, - - _FMT_MAX, -}; - -#include /* need to import here because or enum interdep */ - -/*! call-back for actual format conversion function - * \param[out] dst caller-allocated buffer for output data - * \param[in] src input data - * \param[in] src_len length of input data \a src - * \returns number of output bytes written to \a dst; negative on error */ -typedef int (*fmt_conv_cb_t)(uint8_t *dst, const uint8_t *src, unsigned int src_len); - -struct format_desc { - enum format_type type; - enum codec_type codec_type; - const char * name; - const char * description; - - /*! length of frames in this format (as opposed to canonical) */ - unsigned int frame_len; - fmt_conv_cb_t conv_from_canon; - fmt_conv_cb_t conv_to_canon; - - /*! length of a (global) header at start of file */ - unsigned int header_len; - /*! exact match for (global) header at start of file */ - const uint8_t * header; -}; - -const struct format_desc *fmt_get_from_type(enum format_type type); -const struct format_desc *fmt_get_from_name(const char *name); - -#endif /* __GAPK_FORMATS_H__ */ diff --git a/include/gapk/get_cycles.h b/include/gapk/get_cycles.h deleted file mode 100644 index 9eb7bc3..0000000 --- a/include/gapk/get_cycles.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies Ltd., - * (c) 2005 Harald Welte , All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * $Id$ - */ - -#ifndef GET_CLOCK_H -#define GET_CLOCK_H - -#if 0 - -#define _POSIX_C_SOURCE 199506L -#include -#include - -/* Ideally we would be using clock_getres() and clock_gettime(). - * glibc manpage says CLOCK_PROCESS_CPUTIME_ID is only defined if it is - * actually present. however, on ppc64 it is defined but not implemented. */ -#ifdef CLOCK_PROCESS_CPUTIME_ID -typedef long cycles_t; -static inline cycles_t get_cycles() -{ - struct timespec ts; - -#if defined (__x86_64__) || defined(__i386__) - asm volatile ("cpuid" : : : "eax", "ebx", "ecx", "edx" ); /* flush pipeline */ -#endif - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); - return ts.tv_nsec; -} -#endif - -#endif - -#if defined (__x86_64__) || defined(__i386__) -/* Note: only x86 CPUs which have rdtsc instruction are supported. */ -typedef unsigned long long cycles_t; -static inline cycles_t get_cycles() -{ - unsigned low, high; - unsigned long long val; - asm volatile ("cpuid" : : : "eax", "ebx", "ecx", "edx" ); /* flush pipeline */ - asm volatile ("rdtsc" : "=a" (low), "=d" (high)); - val = high; - val = (val << 32) | low; - return val; -} -#elif defined(__PPC64__) -/* Note: only PPC CPUs which have mftb instruction are supported. */ -typedef unsigned long long cycles_t; -static inline cycles_t get_cycles() -{ - cycles_t ret; - - asm volatile ("mftb %0" : "=r" (ret) : ); - return ret; -} -#elif defined(__sparc__) -/* Note: only sparc64 supports this register */ -typedef unsigned long long cycles_t; -#define TICK_PRIV_BIT (1ULL << 63) -static inline cycles_t get_cycles() -{ - cycles_t ret; - -#if defined(__sparcv9) || defined(__arch64__) - asm volatile ("rd %%tick, %0" : "=r" (ret)); -#else - asm volatile ("rd %%tick, %%g1\n\t" - "srlx %%g1, 32, %H0\n\t" - "srl %%g1, 0, %L0" - : "=r" (ret) - : /* no inputs */ - : "g1"); -#endif - return ret & ~TICK_PRIV_BIT; -} -#elif defined(__PPC__) -#define CPU_FTR_601 0x00000100 -typedef unsigned long cycles_t; -static inline cycles_t get_cycles() -{ - cycles_t ret; - - asm volatile ( - "98: mftb %0\n" - "99:\n" - ".section __ftr_fixup,\"a\"\n" - " .long %1\n" - " .long 0\n" - " .long 98b\n" - " .long 99b\n" - ".previous" - : "=r" (ret) : "i" (CPU_FTR_601)); - return ret; -} -#elif defined(__ia64__) || defined(__mips__) || \ - defined(__s390__) -/* Itanium2 and up has ar.itc (Itanium1 has errata) */ -/* PPC64 has mftb */ -#include -#else -#warning get_cycles not implemented for this architecture: attempt asm/timex.h -#include -#endif - -extern double get_cpu_mhz(void); - -#endif /* GET_CLOCK_H */ diff --git a/include/gapk/procqueue.h b/include/gapk/procqueue.h deleted file mode 100644 index d9a5546..0000000 --- a/include/gapk/procqueue.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Processing Queue Management */ - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - */ - -#ifndef __GAPK_PROCQUEUE_H__ -#define __GAPK_PROCQUEUE_H__ - -#include -#include /* for FILE */ - -struct pq; - -struct pq_item { - /*! input frame size (in bytes). '0' in case of variable frames */ - int len_in; - /*! output frame size (in bytes). '0' in case of variable frames */ - int len_out; - /*! opaque state */ - void *state; - /*! call-back for actual format conversion function - * \param[in] state opaque state pointer - * \param[out] out caller-allocated buffer for output data - * \param[in] in input data - * \param[in] in_len length of input data \a in - * \returns number of output bytes written to \a out; negative on error */ - int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len); - void (*exit)(void *state); -}; - -/* Management */ -struct pq * pq_create(void); -void pq_destroy(struct pq *pq); -struct pq_item * pq_add_item(struct pq *pq); -int pq_prepare(struct pq *pq); -int pq_execute(struct pq *pq); - -/* File */ -int pq_queue_file_input(struct pq *pq, FILE *src, unsigned int block_len); -int pq_queue_file_output(struct pq *pq, FILE *dst, unsigned int block_len); - -/* RTP */ -int pq_queue_rtp_input(struct pq *pq, int rtp_fd, unsigned int block_len); -int pq_queue_rtp_output(struct pq *pq, int rtp_fd, unsigned int block_len); - -/* ALSA */ -int pq_queue_alsa_input(struct pq *pq, const char *hwdev, unsigned int blk_len); -int pq_queue_alsa_output(struct pq *pq, const char *hwdev, unsigned int blk_len); - -/* Format */ -struct format_desc; -int pq_queue_fmt_convert(struct pq *pq, const struct format_desc *fmt, int to_from_n); - -/* Codec */ -struct codec_desc; -int pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int encode); - -#endif /* __GAPK_PROCQUEUE_H__ */ diff --git a/include/gapk/utils.h b/include/gapk/utils.h deleted file mode 100644 index 3b02049..0000000 --- a/include/gapk/utils.h +++ /dev/null @@ -1,104 +0,0 @@ -/* Various helpers */ - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - */ - -#ifndef __GAPK_UTILS_H__ -#define __GAPK_UTILS_H__ - -#include - -static inline int -msb_get_bit(const uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = 7 - (bn & 7); - - return (buf[pos_byte] >> pos_bit) & 1; -} - -static inline void -msb_put_bit(uint8_t *buf, int bn, int bit) -{ - int pos_byte = bn >> 3; - int pos_bit = 7 - (bn & 7); - - if (bit) - buf[pos_byte] |= (1 << pos_bit); - else - buf[pos_byte] &= ~(1 << pos_bit); -} - -static inline void -msb_set_bit(uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = 7 - (bn & 7); - - buf[pos_byte] |= (1 << pos_bit); -} - -static inline void -msb_clr_bit(uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = 7 - (bn & 7); - - buf[pos_byte] &= ~(1 << pos_bit); -} - - -static inline int -lsb_get_bit(const uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = bn & 7; - - return (buf[pos_byte] >> pos_bit) & 1; -} - -static inline void -lsb_put_bit(uint8_t *buf, int bn, int bit) -{ - int pos_byte = bn >> 3; - int pos_bit = bn & 7; - - if (bit) - buf[pos_byte] |= (1 << pos_bit); - else - buf[pos_byte] &= ~(1 << pos_bit); -} - -static inline void -lsb_set_bit(uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = bn & 7; - - buf[pos_byte] |= (1 << pos_bit); -} - -static inline void -lsb_clr_bit(uint8_t *buf, int bn) -{ - int pos_byte = bn >> 3; - int pos_bit = bn & 7; - - buf[pos_byte] &= ~(1 << pos_bit); -} - -#endif /* __GAPK_UTILS_H__ */ diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h new file mode 100644 index 0000000..b67af6f --- /dev/null +++ b/include/osmocom/gapk/benchmark.h @@ -0,0 +1,60 @@ +#ifndef _BENCHMARK_H +#define _BENCHMARK_H + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + * + * (C) 2014 Harald Welte + */ + +#include +#include + +#define NUM_AVG 102400 + +struct benchmark_cycles { + cycles_t enc[NUM_AVG]; + unsigned int enc_used; + cycles_t dec[NUM_AVG]; + unsigned int dec_used; +}; + +extern struct benchmark_cycles codec_cycles[_CODEC_MAX]; + +static inline void benchmark_stop(enum codec_type codec, int encode, unsigned long cycles) +{ + struct benchmark_cycles *bc = &codec_cycles[codec]; + + if (encode) { + bc->enc_used = (bc->enc_used + 1) % NUM_AVG; + bc->enc[bc->enc_used] = cycles; + } else { + bc->dec_used = (bc->dec_used + 1) % NUM_AVG; + bc->dec[bc->dec_used] = cycles; + } +} + +#define BENCHMARK_START do { \ + cycles_t _cycles_start, _cycles_stop; \ + _cycles_start = get_cycles() + +#define BENCHMARK_STOP(x,y) _cycles_stop = get_cycles(); \ + benchmark_stop(x, y, _cycles_stop - _cycles_start); \ + } while (0) + +void benchmark_dump(void); + +#endif diff --git a/include/osmocom/gapk/codecs.h b/include/osmocom/gapk/codecs.h new file mode 100644 index 0000000..1ad4e73 --- /dev/null +++ b/include/osmocom/gapk/codecs.h @@ -0,0 +1,71 @@ +/* Codecs handling */ + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + */ + +#ifndef __GAPK_CODECS_H__ +#define __GAPK_CODECS_H__ + +#include + +#define FR_CANON_LEN 33 +#define HR_CANON_LEN 14 +#define EFR_CANON_LEN 31 +#define PCM_CANON_LEN (160*sizeof(uint16_t)) +#define HR_REF_ENC_LEN (20 * sizeof(uint16_t)) +#define HR_REF_DEC_LEN (22 * sizeof(uint16_t)) + +enum codec_type { + CODEC_INVALID = 0, + CODEC_PCM, /* 16 bits PCM samples */ + CODEC_HR, /* GSM Half Rate codec GSM 06.20 */ + CODEC_FR, /* GSM Full Rate codec GSM 06.10 */ + CODEC_EFR, /* GSM Enhanced Full Rate codec GSM 06.60 */ + CODEC_AMR, /* GSM Adaptive Multi Rate codec GSM 26.071 */ + _CODEC_MAX, +}; + +#include /* need to import here because or enum interdep */ + +/*! call-back for actual codec conversion function + * \param[in] state opaque state pointer (returned by codec->init) + * \param[out] dst caller-allocated buffer for output data + * \param[in] src input data + * \param[in] src_len length of input data \a src + * \returns number of output bytes written to \a dst; negative on error */ +typedef int (*codec_conv_cb_t)(void *state, uint8_t *dst, const uint8_t *src, unsigned int src_len); + +struct codec_desc { + enum codec_type type; + const char * name; + const char * description; + /*! canonical frame size (in bytes); 0 in case of variable length */ + unsigned int canon_frame_len; + + enum format_type codec_enc_format_type; /* what the encoder provides */ + enum format_type codec_dec_format_type; /* what to give the decoder */ + /*! codec initialization function pointer, returns opaque state */ + void * (*codec_init)(void); + /*! codec exit function pointer, gets passed opaque state */ + void (*codec_exit)(void *state); + codec_conv_cb_t codec_encode; + codec_conv_cb_t codec_decode; +}; + +const struct codec_desc *codec_get_from_type(enum codec_type type); + +#endif /* __GAPK_CODECS_H__ */ diff --git a/include/osmocom/gapk/formats.h b/include/osmocom/gapk/formats.h new file mode 100644 index 0000000..7847782 --- /dev/null +++ b/include/osmocom/gapk/formats.h @@ -0,0 +1,94 @@ +/* Formats handling */ + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + */ + +#ifndef __GAPK_FORMATS_H__ +#define __GAPK_FORMATS_H__ + +#include + +enum format_type { + FMT_INVALID = 0, + + /* Classic .amr container */ + FMT_AMR_EFR, + + /* Classic .gsm file for FR */ + FMT_GSM, + + /* 3GPP Reference HR vocodec files */ + FMT_HR_REF_DEC, + FMT_HR_REF_ENC, + + /* Racal 6103E TCH recordings */ + FMT_RACAL_HR, + FMT_RACAL_FR, + FMT_RACAL_EFR, + + /* Raw PCM */ + FMT_RAWPCM_S16LE, + + /* Texas Instrument calypso/locosto buffer format */ + FMT_TI_HR, + FMT_TI_FR, + FMT_TI_EFR, + + /* AMR encoded data, variable length */ + FMT_AMR_OPENCORE, + FMT_RTP_AMR, + + FMT_RTP_EFR, + + /* HR in RTP according to ETSI TS 101 318 */ + FMT_RTP_HR_ETSI, + /* HR in RTP according to IETF RFC5993 */ + FMT_RTP_HR_IETF, + + _FMT_MAX, +}; + +#include /* need to import here because or enum interdep */ + +/*! call-back for actual format conversion function + * \param[out] dst caller-allocated buffer for output data + * \param[in] src input data + * \param[in] src_len length of input data \a src + * \returns number of output bytes written to \a dst; negative on error */ +typedef int (*fmt_conv_cb_t)(uint8_t *dst, const uint8_t *src, unsigned int src_len); + +struct format_desc { + enum format_type type; + enum codec_type codec_type; + const char * name; + const char * description; + + /*! length of frames in this format (as opposed to canonical) */ + unsigned int frame_len; + fmt_conv_cb_t conv_from_canon; + fmt_conv_cb_t conv_to_canon; + + /*! length of a (global) header at start of file */ + unsigned int header_len; + /*! exact match for (global) header at start of file */ + const uint8_t * header; +}; + +const struct format_desc *fmt_get_from_type(enum format_type type); +const struct format_desc *fmt_get_from_name(const char *name); + +#endif /* __GAPK_FORMATS_H__ */ diff --git a/include/osmocom/gapk/get_cycles.h b/include/osmocom/gapk/get_cycles.h new file mode 100644 index 0000000..9eb7bc3 --- /dev/null +++ b/include/osmocom/gapk/get_cycles.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005 Mellanox Technologies Ltd., + * (c) 2005 Harald Welte , All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id$ + */ + +#ifndef GET_CLOCK_H +#define GET_CLOCK_H + +#if 0 + +#define _POSIX_C_SOURCE 199506L +#include +#include + +/* Ideally we would be using clock_getres() and clock_gettime(). + * glibc manpage says CLOCK_PROCESS_CPUTIME_ID is only defined if it is + * actually present. however, on ppc64 it is defined but not implemented. */ +#ifdef CLOCK_PROCESS_CPUTIME_ID +typedef long cycles_t; +static inline cycles_t get_cycles() +{ + struct timespec ts; + +#if defined (__x86_64__) || defined(__i386__) + asm volatile ("cpuid" : : : "eax", "ebx", "ecx", "edx" ); /* flush pipeline */ +#endif + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + return ts.tv_nsec; +} +#endif + +#endif + +#if defined (__x86_64__) || defined(__i386__) +/* Note: only x86 CPUs which have rdtsc instruction are supported. */ +typedef unsigned long long cycles_t; +static inline cycles_t get_cycles() +{ + unsigned low, high; + unsigned long long val; + asm volatile ("cpuid" : : : "eax", "ebx", "ecx", "edx" ); /* flush pipeline */ + asm volatile ("rdtsc" : "=a" (low), "=d" (high)); + val = high; + val = (val << 32) | low; + return val; +} +#elif defined(__PPC64__) +/* Note: only PPC CPUs which have mftb instruction are supported. */ +typedef unsigned long long cycles_t; +static inline cycles_t get_cycles() +{ + cycles_t ret; + + asm volatile ("mftb %0" : "=r" (ret) : ); + return ret; +} +#elif defined(__sparc__) +/* Note: only sparc64 supports this register */ +typedef unsigned long long cycles_t; +#define TICK_PRIV_BIT (1ULL << 63) +static inline cycles_t get_cycles() +{ + cycles_t ret; + +#if defined(__sparcv9) || defined(__arch64__) + asm volatile ("rd %%tick, %0" : "=r" (ret)); +#else + asm volatile ("rd %%tick, %%g1\n\t" + "srlx %%g1, 32, %H0\n\t" + "srl %%g1, 0, %L0" + : "=r" (ret) + : /* no inputs */ + : "g1"); +#endif + return ret & ~TICK_PRIV_BIT; +} +#elif defined(__PPC__) +#define CPU_FTR_601 0x00000100 +typedef unsigned long cycles_t; +static inline cycles_t get_cycles() +{ + cycles_t ret; + + asm volatile ( + "98: mftb %0\n" + "99:\n" + ".section __ftr_fixup,\"a\"\n" + " .long %1\n" + " .long 0\n" + " .long 98b\n" + " .long 99b\n" + ".previous" + : "=r" (ret) : "i" (CPU_FTR_601)); + return ret; +} +#elif defined(__ia64__) || defined(__mips__) || \ + defined(__s390__) +/* Itanium2 and up has ar.itc (Itanium1 has errata) */ +/* PPC64 has mftb */ +#include +#else +#warning get_cycles not implemented for this architecture: attempt asm/timex.h +#include +#endif + +extern double get_cpu_mhz(void); + +#endif /* GET_CLOCK_H */ diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h new file mode 100644 index 0000000..d9a5546 --- /dev/null +++ b/include/osmocom/gapk/procqueue.h @@ -0,0 +1,72 @@ +/* Processing Queue Management */ + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + */ + +#ifndef __GAPK_PROCQUEUE_H__ +#define __GAPK_PROCQUEUE_H__ + +#include +#include /* for FILE */ + +struct pq; + +struct pq_item { + /*! input frame size (in bytes). '0' in case of variable frames */ + int len_in; + /*! output frame size (in bytes). '0' in case of variable frames */ + int len_out; + /*! opaque state */ + void *state; + /*! call-back for actual format conversion function + * \param[in] state opaque state pointer + * \param[out] out caller-allocated buffer for output data + * \param[in] in input data + * \param[in] in_len length of input data \a in + * \returns number of output bytes written to \a out; negative on error */ + int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len); + void (*exit)(void *state); +}; + +/* Management */ +struct pq * pq_create(void); +void pq_destroy(struct pq *pq); +struct pq_item * pq_add_item(struct pq *pq); +int pq_prepare(struct pq *pq); +int pq_execute(struct pq *pq); + +/* File */ +int pq_queue_file_input(struct pq *pq, FILE *src, unsigned int block_len); +int pq_queue_file_output(struct pq *pq, FILE *dst, unsigned int block_len); + +/* RTP */ +int pq_queue_rtp_input(struct pq *pq, int rtp_fd, unsigned int block_len); +int pq_queue_rtp_output(struct pq *pq, int rtp_fd, unsigned int block_len); + +/* ALSA */ +int pq_queue_alsa_input(struct pq *pq, const char *hwdev, unsigned int blk_len); +int pq_queue_alsa_output(struct pq *pq, const char *hwdev, unsigned int blk_len); + +/* Format */ +struct format_desc; +int pq_queue_fmt_convert(struct pq *pq, const struct format_desc *fmt, int to_from_n); + +/* Codec */ +struct codec_desc; +int pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int encode); + +#endif /* __GAPK_PROCQUEUE_H__ */ diff --git a/include/osmocom/gapk/utils.h b/include/osmocom/gapk/utils.h new file mode 100644 index 0000000..3b02049 --- /dev/null +++ b/include/osmocom/gapk/utils.h @@ -0,0 +1,104 @@ +/* Various helpers */ + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + */ + +#ifndef __GAPK_UTILS_H__ +#define __GAPK_UTILS_H__ + +#include + +static inline int +msb_get_bit(const uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + return (buf[pos_byte] >> pos_bit) & 1; +} + +static inline void +msb_put_bit(uint8_t *buf, int bn, int bit) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + if (bit) + buf[pos_byte] |= (1 << pos_bit); + else + buf[pos_byte] &= ~(1 << pos_bit); +} + +static inline void +msb_set_bit(uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + buf[pos_byte] |= (1 << pos_bit); +} + +static inline void +msb_clr_bit(uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + buf[pos_byte] &= ~(1 << pos_bit); +} + + +static inline int +lsb_get_bit(const uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = bn & 7; + + return (buf[pos_byte] >> pos_bit) & 1; +} + +static inline void +lsb_put_bit(uint8_t *buf, int bn, int bit) +{ + int pos_byte = bn >> 3; + int pos_bit = bn & 7; + + if (bit) + buf[pos_byte] |= (1 << pos_bit); + else + buf[pos_byte] &= ~(1 << pos_bit); +} + +static inline void +lsb_set_bit(uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = bn & 7; + + buf[pos_byte] |= (1 << pos_bit); +} + +static inline void +lsb_clr_bit(uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = bn & 7; + + buf[pos_byte] &= ~(1 << pos_bit); +} + +#endif /* __GAPK_UTILS_H__ */ diff --git a/src/benchmark.c b/src/benchmark.c index 91e2ce5..6dfc33b 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -19,7 +19,7 @@ #include -#include +#include struct benchmark_cycles codec_cycles[_CODEC_MAX]; diff --git a/src/codec_amr.c b/src/codec_amr.c index 4aae733..4c4b3e6 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -18,8 +18,8 @@ * along with gapk. If not, see . */ -#include -#include +#include +#include #include "config.h" diff --git a/src/codec_efr.c b/src/codec_efr.c index 339172a..84e5fc5 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -17,8 +17,8 @@ * along with gapk. If not, see . */ -#include -#include +#include +#include #include "config.h" diff --git a/src/codec_fr.c b/src/codec_fr.c index 2ce44b4..0cda1f4 100644 --- a/src/codec_fr.c +++ b/src/codec_fr.c @@ -19,8 +19,8 @@ #include -#include -#include +#include +#include #include "config.h" diff --git a/src/codec_hr.c b/src/codec_hr.c index b3247e0..6e5948a 100644 --- a/src/codec_hr.c +++ b/src/codec_hr.c @@ -19,8 +19,8 @@ #include -#include -#include +#include +#include #include "config.h" diff --git a/src/codec_pcm.c b/src/codec_pcm.c index 9fa8c1b..95e83ca 100644 --- a/src/codec_pcm.c +++ b/src/codec_pcm.c @@ -17,7 +17,7 @@ * along with gapk. If not, see . */ -#include +#include const struct codec_desc codec_pcm_desc = { .type = CODEC_PCM, diff --git a/src/codecs.c b/src/codecs.c index 623e80c..f7f86bd 100644 --- a/src/codecs.c +++ b/src/codecs.c @@ -19,7 +19,7 @@ #include /* for NULL */ -#include +#include /* Extern codec descriptors */ extern const struct codec_desc codec_pcm_desc; diff --git a/src/fmt_amr.c b/src/fmt_amr.c index e28024c..06f4158 100644 --- a/src/fmt_amr.c +++ b/src/fmt_amr.c @@ -22,9 +22,9 @@ #include -#include -#include -#include +#include +#include +#include #define EFR_LEN 32 diff --git a/src/fmt_amr_opencore.c b/src/fmt_amr_opencore.c index 3fa547b..07281fd 100644 --- a/src/fmt_amr_opencore.c +++ b/src/fmt_amr_opencore.c @@ -21,9 +21,9 @@ #include #include -#include -#include -#include +#include +#include +#include static int amr_opencore_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len) diff --git a/src/fmt_gsm.c b/src/fmt_gsm.c index 27701f0..1963692 100644 --- a/src/fmt_gsm.c +++ b/src/fmt_gsm.c @@ -18,8 +18,8 @@ */ #include -#include -#include +#include +#include #define GSM_LEN 33 #define GSM_MAGIC 0xd diff --git a/src/fmt_hr_ref.c b/src/fmt_hr_ref.c index d64918b..fb5b008 100644 --- a/src/fmt_hr_ref.c +++ b/src/fmt_hr_ref.c @@ -22,9 +22,9 @@ #include -#include -#include -#include +#include +#include +#include static const int params_unvoiced[] = { 5, /* R0 */ diff --git a/src/fmt_racal.c b/src/fmt_racal.c index 1dbc61d..add202b 100644 --- a/src/fmt_racal.c +++ b/src/fmt_racal.c @@ -22,9 +22,9 @@ #include -#include -#include -#include +#include +#include +#include #define RACAL_HR_LEN 14 #define RACAL_FR_LEN 33 diff --git a/src/fmt_rawpcm.c b/src/fmt_rawpcm.c index 207708c..c0c83c1 100644 --- a/src/fmt_rawpcm.c +++ b/src/fmt_rawpcm.c @@ -19,8 +19,8 @@ #include -#include -#include +#include +#include static int rawpcm_s16le_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len) diff --git a/src/fmt_rtp_amr.c b/src/fmt_rtp_amr.c index 1d5357d..79dd37c 100644 --- a/src/fmt_rtp_amr.c +++ b/src/fmt_rtp_amr.c @@ -23,9 +23,9 @@ #include -#include -#include -#include +#include +#include +#include /* conversion function: RTP payload -> canonical format */ static int diff --git a/src/fmt_rtp_efr.c b/src/fmt_rtp_efr.c index 0132e32..f900f75 100644 --- a/src/fmt_rtp_efr.c +++ b/src/fmt_rtp_efr.c @@ -23,9 +23,9 @@ #include -#include -#include -#include +#include +#include +#include #define EFR_LEN 31 #define EFR_MAGIC 0xc diff --git a/src/fmt_rtp_hr_etsi.c b/src/fmt_rtp_hr_etsi.c index fe6728a..475f156 100644 --- a/src/fmt_rtp_hr_etsi.c +++ b/src/fmt_rtp_hr_etsi.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include /* conversion function: RTP payload -> canonical format */ static int diff --git a/src/fmt_rtp_hr_ietf.c b/src/fmt_rtp_hr_ietf.c index 3e8e6a3..cedf461 100644 --- a/src/fmt_rtp_hr_ietf.c +++ b/src/fmt_rtp_hr_ietf.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include #define HR_LEN (HR_CANON_LEN+1) diff --git a/src/fmt_ti.c b/src/fmt_ti.c index 582bff4..5f2da9f 100644 --- a/src/fmt_ti.c +++ b/src/fmt_ti.c @@ -30,9 +30,9 @@ #include -#include -#include -#include +#include +#include +#include #define TI_LEN 33 diff --git a/src/formats.c b/src/formats.c index 60182fe..8544186 100644 --- a/src/formats.c +++ b/src/formats.c @@ -20,7 +20,7 @@ #include /* for NULL */ #include -#include +#include /* Extern format descriptors */ extern const struct format_desc fmt_amr_efr; diff --git a/src/main.c b/src/main.c index 58e23c1..9b56e58 100644 --- a/src/main.c +++ b/src/main.c @@ -33,10 +33,10 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include struct gapk_options diff --git a/src/pq_alsa.c b/src/pq_alsa.c index cad76ca..1902d7b 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -23,9 +23,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include "config.h" diff --git a/src/pq_codec.c b/src/pq_codec.c index f1884fb..4b41e1d 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -20,9 +20,9 @@ #include #include -#include -#include -#include +#include +#include +#include /*! Add a codecl to the processing queue diff --git a/src/pq_file.c b/src/pq_file.c index 96f7b3f..e20b52b 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include struct pq_state_file { diff --git a/src/pq_format.c b/src/pq_format.c index d6bc8af..ae98483 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -20,9 +20,9 @@ #include #include -#include -#include -#include +#include +#include +#include static int diff --git a/src/pq_rtp.c b/src/pq_rtp.c index f5603de..d7d924e 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -27,9 +27,9 @@ #include -#include -#include -#include +#include +#include +#include #ifndef __BYTE_ORDER # ifdef __APPLE__ diff --git a/src/procqueue.c b/src/procqueue.c index 01ad581..f54da40 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -21,7 +21,7 @@ #include #include -#include +#include #define VAR_BUF_SIZE 320 #define MAX_PQ_ITEMS 8 -- cgit v1.2.3 From 5f941573b0040c1b27014b4756155c86fe896b9f Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 31 Aug 2017 01:20:18 +0700 Subject: Use '#pragma once' instead of include guard The most compilers today do support the '#pragma once', which is designed to cause the current source file to be included only once in a single compilation. One has several advantages, including: less code, avoidance of name clashes, and sometimes improvement in compilation speed. See: https://en.wikipedia.org/wiki/Pragma_once for details. --- include/gsmhr/gsmhr.h | 5 +---- include/osmocom/gapk/benchmark.h | 7 ++----- include/osmocom/gapk/codecs.h | 5 +---- include/osmocom/gapk/formats.h | 5 +---- include/osmocom/gapk/get_cycles.h | 5 +---- include/osmocom/gapk/procqueue.h | 5 +---- include/osmocom/gapk/utils.h | 5 +---- 7 files changed, 8 insertions(+), 29 deletions(-) diff --git a/include/gsmhr/gsmhr.h b/include/gsmhr/gsmhr.h index 17d42cb..b2fa0da 100644 --- a/include/gsmhr/gsmhr.h +++ b/include/gsmhr/gsmhr.h @@ -17,8 +17,7 @@ * along with gapk. If not, see . */ -#ifndef __GSM_HR_H__ -#define __GSM_HR_H__ +#pragma once #include @@ -36,5 +35,3 @@ int gsmhr_decode(struct gsmhr *state, int16_t *pcm, const int16_t *hr_ #ifdef __cplusplus } #endif - -#endif /* __GSM_HR_H__ */ diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index b67af6f..c18d85e 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -1,6 +1,3 @@ -#ifndef _BENCHMARK_H -#define _BENCHMARK_H - /* * This file is part of gapk (GSM Audio Pocket Knife). * @@ -20,6 +17,8 @@ * (C) 2014 Harald Welte */ +#pragma once + #include #include @@ -56,5 +55,3 @@ static inline void benchmark_stop(enum codec_type codec, int encode, unsigned lo } while (0) void benchmark_dump(void); - -#endif diff --git a/include/osmocom/gapk/codecs.h b/include/osmocom/gapk/codecs.h index 1ad4e73..f680460 100644 --- a/include/osmocom/gapk/codecs.h +++ b/include/osmocom/gapk/codecs.h @@ -17,8 +17,7 @@ * along with gapk. If not, see . */ -#ifndef __GAPK_CODECS_H__ -#define __GAPK_CODECS_H__ +#pragma once #include @@ -67,5 +66,3 @@ struct codec_desc { }; const struct codec_desc *codec_get_from_type(enum codec_type type); - -#endif /* __GAPK_CODECS_H__ */ diff --git a/include/osmocom/gapk/formats.h b/include/osmocom/gapk/formats.h index 7847782..4a3cb67 100644 --- a/include/osmocom/gapk/formats.h +++ b/include/osmocom/gapk/formats.h @@ -17,8 +17,7 @@ * along with gapk. If not, see . */ -#ifndef __GAPK_FORMATS_H__ -#define __GAPK_FORMATS_H__ +#pragma once #include @@ -90,5 +89,3 @@ struct format_desc { const struct format_desc *fmt_get_from_type(enum format_type type); const struct format_desc *fmt_get_from_name(const char *name); - -#endif /* __GAPK_FORMATS_H__ */ diff --git a/include/osmocom/gapk/get_cycles.h b/include/osmocom/gapk/get_cycles.h index 9eb7bc3..40ac570 100644 --- a/include/osmocom/gapk/get_cycles.h +++ b/include/osmocom/gapk/get_cycles.h @@ -33,8 +33,7 @@ * $Id$ */ -#ifndef GET_CLOCK_H -#define GET_CLOCK_H +#pragma once #if 0 @@ -134,5 +133,3 @@ static inline cycles_t get_cycles() #endif extern double get_cpu_mhz(void); - -#endif /* GET_CLOCK_H */ diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index d9a5546..708f767 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -17,8 +17,7 @@ * along with gapk. If not, see . */ -#ifndef __GAPK_PROCQUEUE_H__ -#define __GAPK_PROCQUEUE_H__ +#pragma once #include #include /* for FILE */ @@ -68,5 +67,3 @@ int pq_queue_fmt_convert(struct pq *pq, const struct format_desc *fmt, int to_fr /* Codec */ struct codec_desc; int pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int encode); - -#endif /* __GAPK_PROCQUEUE_H__ */ diff --git a/include/osmocom/gapk/utils.h b/include/osmocom/gapk/utils.h index 3b02049..0b8b75b 100644 --- a/include/osmocom/gapk/utils.h +++ b/include/osmocom/gapk/utils.h @@ -17,8 +17,7 @@ * along with gapk. If not, see . */ -#ifndef __GAPK_UTILS_H__ -#define __GAPK_UTILS_H__ +#pragma once #include @@ -100,5 +99,3 @@ lsb_clr_bit(uint8_t *buf, int bn) buf[pos_byte] &= ~(1 << pos_bit); } - -#endif /* __GAPK_UTILS_H__ */ -- cgit v1.2.3 From 40d59f14a240e943205fafe7d2449b286d3b4913 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 31 Aug 2017 01:41:26 +0700 Subject: Add a pkg-config manifest for libosmogapk In order to make pkg-config 'see' the libosmogapk, a corresponding package description is required. For more details, see: https://autotools.io/pkgconfig/file-format.html --- .gitignore | 3 ++- Makefile.am | 3 +++ configure.ac | 1 + libosmogapk.pc.in | 11 +++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 libosmogapk.pc.in diff --git a/.gitignore b/.gitignore index 6288340..456b782 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ autoscan-2.*.log configure.scan # autoreconf by-products -*.in +Makefile.in aclocal.m4 autom4te.cache/ @@ -18,6 +18,7 @@ m4/ missing # configure by-products +*.pc .deps Makefile diff --git a/Makefile.am b/Makefile.am index d1638ec..4242427 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,9 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 ACLOCAL_AMFLAGS = -I m4 +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libosmogapk.pc + AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include SUBDIRS = include diff --git a/configure.ac b/configure.ac index 85d722d..901a3d6 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,7 @@ AC_CONFIG_FILES([ libgsmhr/Makefile include/Makefile include/gsmhr/Makefile + libosmogapk.pc ]) # Options diff --git a/libosmogapk.pc.in b/libosmogapk.pc.in new file mode 100644 index 0000000..df27402 --- /dev/null +++ b/libosmogapk.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Osmocom GSM Audio Transcoding Library +Description: C Utility Library +Requires: libosmocore, libosmocodec +Version: @VERSION@ +Libs: -L${libdir} -losmogapk +Cflags: -I${includedir}/ -- cgit v1.2.3 From 9cba760ba2ca5fd73e34f91bf388fc255dbcd335 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 31 Aug 2017 02:31:18 +0700 Subject: procqueue: expose the processing queue struct definition To be able to use processing queues from outside, the pq struct should be shared in the corresponding header file. --- include/osmocom/gapk/procqueue.h | 11 +++++++++-- src/procqueue.c | 10 ---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index 708f767..b07970d 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -22,8 +22,6 @@ #include #include /* for FILE */ -struct pq; - struct pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ int len_in; @@ -41,6 +39,15 @@ struct pq_item { void (*exit)(void *state); }; +#define VAR_BUF_SIZE 320 +#define MAX_PQ_ITEMS 8 + +struct pq { + unsigned n_items; + struct pq_item *items[MAX_PQ_ITEMS]; + void *buffers[MAX_PQ_ITEMS + 1]; +}; + /* Management */ struct pq * pq_create(void); void pq_destroy(struct pq *pq); diff --git a/src/procqueue.c b/src/procqueue.c index f54da40..cba6dbb 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -23,16 +23,6 @@ #include -#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]; -}; - - /* crate a new (empty) processing queue */ struct pq * pq_create(void) -- cgit v1.2.3 From a8d46571cebb7f14501fa7bcf3c2eb86c473d8b2 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 31 Aug 2017 17:22:56 +0700 Subject: Add an 'osmo_gapk' prefix to the exposed symbols To avoid a naming conflict between libosmogapk and other projects during linkage, all the exposed symbols should have an unique prefix. Let's use 'osmo_gapk' for that. --- include/osmocom/gapk/benchmark.h | 9 ++--- include/osmocom/gapk/codecs.h | 47 +++++++++++++++---------- include/osmocom/gapk/formats.h | 48 ++++++++++++++----------- include/osmocom/gapk/procqueue.h | 40 +++++++++++---------- src/benchmark.c | 4 +-- src/codec_amr.c | 2 +- src/codec_efr.c | 2 +- src/codec_fr.c | 2 +- src/codec_hr.c | 2 +- src/codec_pcm.c | 2 +- src/codecs.c | 14 ++++---- src/fmt_amr.c | 2 +- src/fmt_amr_opencore.c | 2 +- src/fmt_gsm.c | 2 +- src/fmt_hr_ref.c | 4 +-- src/fmt_racal.c | 6 ++-- src/fmt_rawpcm.c | 2 +- src/fmt_rtp_amr.c | 2 +- src/fmt_rtp_efr.c | 2 +- src/fmt_rtp_hr_etsi.c | 2 +- src/fmt_rtp_hr_ietf.c | 2 +- src/fmt_ti.c | 6 ++-- src/formats.c | 44 +++++++++++------------ src/main.c | 75 ++++++++++++++++++++-------------------- src/pq_alsa.c | 10 +++--- src/pq_codec.c | 16 +++++---- src/pq_file.c | 10 +++--- src/pq_format.c | 11 +++--- src/pq_rtp.c | 10 +++--- src/procqueue.c | 26 +++++++------- 30 files changed, 215 insertions(+), 191 deletions(-) diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index c18d85e..a404168 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -24,18 +24,19 @@ #define NUM_AVG 102400 -struct benchmark_cycles { +struct osmo_gapk_bench_cycles { cycles_t enc[NUM_AVG]; unsigned int enc_used; cycles_t dec[NUM_AVG]; unsigned int dec_used; }; -extern struct benchmark_cycles codec_cycles[_CODEC_MAX]; +extern struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; -static inline void benchmark_stop(enum codec_type codec, int encode, unsigned long cycles) +static inline void benchmark_stop(enum osmo_gapk_codec_type codec, + int encode, unsigned long cycles) { - struct benchmark_cycles *bc = &codec_cycles[codec]; + struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[codec]; if (encode) { bc->enc_used = (bc->enc_used + 1) % NUM_AVG; diff --git a/include/osmocom/gapk/codecs.h b/include/osmocom/gapk/codecs.h index f680460..253fb14 100644 --- a/include/osmocom/gapk/codecs.h +++ b/include/osmocom/gapk/codecs.h @@ -28,7 +28,7 @@ #define HR_REF_ENC_LEN (20 * sizeof(uint16_t)) #define HR_REF_DEC_LEN (22 * sizeof(uint16_t)) -enum codec_type { +enum osmo_gapk_codec_type { CODEC_INVALID = 0, CODEC_PCM, /* 16 bits PCM samples */ CODEC_HR, /* GSM Half Rate codec GSM 06.20 */ @@ -38,7 +38,8 @@ enum codec_type { _CODEC_MAX, }; -#include /* need to import here because or enum interdep */ +/* Need to import here because of enum interdep */ +#include /*! call-back for actual codec conversion function * \param[in] state opaque state pointer (returned by codec->init) @@ -46,23 +47,33 @@ enum codec_type { * \param[in] src input data * \param[in] src_len length of input data \a src * \returns number of output bytes written to \a dst; negative on error */ -typedef int (*codec_conv_cb_t)(void *state, uint8_t *dst, const uint8_t *src, unsigned int src_len); +typedef int (*osmo_gapk_codec_conv_cb_t)(void *state, uint8_t *dst, + const uint8_t *src, unsigned int src_len); -struct codec_desc { - enum codec_type type; - const char * name; - const char * description; - /*! canonical frame size (in bytes); 0 in case of variable length */ - unsigned int canon_frame_len; +struct osmo_gapk_codec_desc { + enum osmo_gapk_codec_type type; + const char *description; + const char *name; - enum format_type codec_enc_format_type; /* what the encoder provides */ - enum format_type codec_dec_format_type; /* what to give the decoder */ - /*! codec initialization function pointer, returns opaque state */ - void * (*codec_init)(void); - /*! codec exit function pointer, gets passed opaque state */ - void (*codec_exit)(void *state); - codec_conv_cb_t codec_encode; - codec_conv_cb_t codec_decode; + /*! + * Canonical frame size (in bytes); + * 0 in case of variable length + */ + unsigned int canon_frame_len; + + /*! What the encoder provides */ + enum osmo_gapk_format_type codec_enc_format_type; + /*! What to give the decoder */ + enum osmo_gapk_format_type codec_dec_format_type; + + /* (De)initialization function pointers */ + void *(*codec_init)(void); + void (*codec_exit)(void *state); + + /* Encoding / decoding function pointers */ + osmo_gapk_codec_conv_cb_t codec_encode; + osmo_gapk_codec_conv_cb_t codec_decode; }; -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); diff --git a/include/osmocom/gapk/formats.h b/include/osmocom/gapk/formats.h index 4a3cb67..d1521d0 100644 --- a/include/osmocom/gapk/formats.h +++ b/include/osmocom/gapk/formats.h @@ -21,7 +21,7 @@ #include -enum format_type { +enum osmo_gapk_format_type { FMT_INVALID = 0, /* Classic .amr container */ @@ -61,31 +61,37 @@ enum format_type { _FMT_MAX, }; -#include /* need to import here because or enum interdep */ +/* Need to import here because of enum interdep */ +#include /*! call-back for actual format conversion function * \param[out] dst caller-allocated buffer for output data * \param[in] src input data * \param[in] src_len length of input data \a src * \returns number of output bytes written to \a dst; negative on error */ -typedef int (*fmt_conv_cb_t)(uint8_t *dst, const uint8_t *src, unsigned int src_len); - -struct format_desc { - enum format_type type; - enum codec_type codec_type; - const char * name; - const char * description; - - /*! length of frames in this format (as opposed to canonical) */ - unsigned int frame_len; - fmt_conv_cb_t conv_from_canon; - fmt_conv_cb_t conv_to_canon; - - /*! length of a (global) header at start of file */ - unsigned int header_len; - /*! exact match for (global) header at start of file */ - const uint8_t * header; +typedef int (*osmo_gapk_fmt_conv_cb_t)(uint8_t *dst, + const uint8_t *src, unsigned int src_len); + +struct osmo_gapk_format_desc { + enum osmo_gapk_format_type type; + enum osmo_gapk_codec_type codec_type; + const char *description; + const char *name; + + /*! Length of frames in this format (as opposed to canonical) */ + unsigned int frame_len; + + /* Format conversation function pointers */ + osmo_gapk_fmt_conv_cb_t conv_from_canon; + osmo_gapk_fmt_conv_cb_t conv_to_canon; + + /*! Length of a (global) header at start of file */ + unsigned int header_len; + /*! Exact match for (global) header at start of file */ + const uint8_t *header; }; -const struct format_desc *fmt_get_from_type(enum format_type type); -const struct format_desc *fmt_get_from_name(const char *name); +const struct osmo_gapk_format_desc * +osmo_gapk_fmt_get_from_type(enum osmo_gapk_format_type type); +const struct osmo_gapk_format_desc * +osmo_gapk_fmt_get_from_name(const char *name); diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index b07970d..50e6eb6 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -22,7 +22,7 @@ #include #include /* for FILE */ -struct pq_item { +struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ int len_in; /*! output frame size (in bytes). '0' in case of variable frames */ @@ -42,35 +42,37 @@ struct pq_item { #define VAR_BUF_SIZE 320 #define MAX_PQ_ITEMS 8 -struct pq { +struct osmo_gapk_pq { unsigned n_items; - struct pq_item *items[MAX_PQ_ITEMS]; + struct osmo_gapk_pq_item *items[MAX_PQ_ITEMS]; void *buffers[MAX_PQ_ITEMS + 1]; }; -/* Management */ -struct pq * pq_create(void); -void pq_destroy(struct pq *pq); -struct pq_item * pq_add_item(struct pq *pq); -int pq_prepare(struct pq *pq); -int pq_execute(struct pq *pq); +/* Processing queue management */ +struct osmo_gapk_pq *osmo_gapk_pq_create(void); +int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq); +int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq); +void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq); + +/* Processing queue item management */ +struct osmo_gapk_pq_item *osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq); /* File */ -int pq_queue_file_input(struct pq *pq, FILE *src, unsigned int block_len); -int pq_queue_file_output(struct pq *pq, FILE *dst, unsigned int block_len); +int osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int block_len); +int osmo_gapk_pq_queue_file_output(struct osmo_gapk_pq *pq, FILE *dst, unsigned int block_len); /* RTP */ -int pq_queue_rtp_input(struct pq *pq, int rtp_fd, unsigned int block_len); -int pq_queue_rtp_output(struct pq *pq, int rtp_fd, unsigned int block_len); +int osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int rtp_fd, unsigned int block_len); +int osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int rtp_fd, unsigned int block_len); /* ALSA */ -int pq_queue_alsa_input(struct pq *pq, const char *hwdev, unsigned int blk_len); -int pq_queue_alsa_output(struct pq *pq, const char *hwdev, unsigned int blk_len); +int osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len); +int osmo_gapk_pq_queue_alsa_output(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len); /* Format */ -struct format_desc; -int pq_queue_fmt_convert(struct pq *pq, const struct format_desc *fmt, int to_from_n); +struct osmo_gapk_format_desc; +int osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_format_desc *fmt, int to_from_n); /* Codec */ -struct codec_desc; -int pq_queue_codec(struct pq *pq, const struct codec_desc *codec, int encode); +struct osmo_gapk_codec_desc; +int osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_desc *codec, int encode); diff --git a/src/benchmark.c b/src/benchmark.c index 6dfc33b..59f5965 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -21,14 +21,14 @@ #include -struct benchmark_cycles codec_cycles[_CODEC_MAX]; +struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; void benchmark_dump(void) { int i; for (i = 0; i < _CODEC_MAX; i++) { - struct benchmark_cycles *bc = &codec_cycles[i]; + struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[i]; unsigned long long total; int j; diff --git a/src/codec_amr.c b/src/codec_amr.c index 4c4b3e6..9cbeba6 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -103,7 +103,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 84e5fc5..ba39f61 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -108,7 +108,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 0cda1f4..6fc0af1 100644 --- a/src/codec_fr.c +++ b/src/codec_fr.c @@ -83,7 +83,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 6e5948a..7c1484e 100644 --- a/src/codec_hr.c +++ b/src/codec_hr.c @@ -73,7 +73,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 95e83ca..76cab34 100644 --- a/src/codec_pcm.c +++ b/src/codec_pcm.c @@ -19,7 +19,7 @@ #include -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 f7f86bd..be5a112 100644 --- a/src/codecs.c +++ b/src/codecs.c @@ -22,15 +22,15 @@ #include /* 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/fmt_amr.c b/src/fmt_amr.c index 06f4158..3694f8a 100644 --- a/src/fmt_amr.c +++ b/src/fmt_amr.c @@ -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 07281fd..640595e 100644 --- a/src/fmt_amr_opencore.c +++ b/src/fmt_amr_opencore.c @@ -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 1963692..e97ac9b 100644 --- a/src/fmt_gsm.c +++ b/src/fmt_gsm.c @@ -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 fb5b008..0394b76 100644 --- a/src/fmt_hr_ref.c +++ b/src/fmt_hr_ref.c @@ -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 add202b..7bb53dd 100644 --- a/src/fmt_racal.c +++ b/src/fmt_racal.c @@ -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 c0c83c1..7b45060 100644 --- a/src/fmt_rawpcm.c +++ b/src/fmt_rawpcm.c @@ -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 79dd37c..a6a3c9f 100644 --- a/src/fmt_rtp_amr.c +++ b/src/fmt_rtp_amr.c @@ -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 f900f75..accfd4f 100644 --- a/src/fmt_rtp_efr.c +++ b/src/fmt_rtp_efr.c @@ -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 475f156..9ed9b22 100644 --- a/src/fmt_rtp_hr_etsi.c +++ b/src/fmt_rtp_hr_etsi.c @@ -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 cedf461..4ee548f 100644 --- a/src/fmt_rtp_hr_ietf.c +++ b/src/fmt_rtp_hr_ietf.c @@ -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 5f2da9f..d7a1ec7 100644 --- a/src/fmt_ti.c +++ b/src/fmt_ti.c @@ -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 8544186..835af6b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -23,24 +23,24 @@ #include /* 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/main.c b/src/main.c index 9b56e58..b9faeb2 100644 --- a/src/main.c +++ b/src/main.c @@ -47,7 +47,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 +55,14 @@ 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; }; struct gapk_state { struct gapk_options opts; - struct pq *pq; + struct osmo_gapk_pq *pq; struct { struct { @@ -87,6 +87,7 @@ struct gapk_state static void print_help(char *progname) { + const struct osmo_gapk_codec_desc *codec; int i; /* Header */ @@ -110,7 +111,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 +127,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 @@ -230,7 +231,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) 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); return -EINVAL; @@ -238,7 +239,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) 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); return -EINVAL; @@ -269,10 +270,10 @@ check_options(struct gapk_state *gs) /* 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"); return -EINVAL; @@ -283,7 +284,7 @@ check_options(struct gapk_state *gs) } /* 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"); return -EINVAL; @@ -413,16 +414,16 @@ 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; 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,12 +432,12 @@ 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"); @@ -449,64 +450,64 @@ 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); 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); } 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); /* 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); 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"); @@ -521,11 +522,11 @@ run(struct gapk_state *gs) { 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; !(rv = osmo_gapk_pq_execute(gs->pq)); frames++); fprintf(stderr, "[+] Processed %d frames\n", frames); @@ -541,7 +542,7 @@ static void signal_handler(int signal) case SIGINT: fprintf(stderr, "catching sigint, closing files\n"); files_close(gs); - pq_destroy(gs->pq); + osmo_gapk_pq_destroy(gs->pq); exit(0); break; default: @@ -574,7 +575,7 @@ int main(int argc, char *argv[]) return rv; /* Create processing queue */ - gs->pq = pq_create(); + gs->pq = osmo_gapk_pq_create(); if (!gs->pq) { rv = -ENOMEM; fprintf(stderr, "Error creating processing queue\n"); @@ -612,7 +613,7 @@ error: files_close(gs); /* Release processing queue */ - pq_destroy(gs->pq); + osmo_gapk_pq_destroy(gs->pq); benchmark_dump(); diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 1902d7b..d280de6 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -77,9 +77,9 @@ pq_cb_alsa_exit(void *_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; @@ -127,7 +127,7 @@ 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; @@ -160,7 +160,7 @@ 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); return pq_queue_alsa_op(pq, hwdev, blk_len, 1); @@ -173,7 +173,7 @@ 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); return pq_queue_alsa_op(pq, hwdev, blk_len, 0); diff --git a/src/pq_codec.c b/src/pq_codec.c index 4b41e1d..37fa1c9 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -31,14 +31,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 +50,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 +59,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; diff --git a/src/pq_file.c b/src/pq_file.c index e20b52b..2d0a6b0 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -60,9 +60,9 @@ pq_cb_file_exit(void *_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)); @@ -72,7 +72,7 @@ pq_queue_file_op(struct pq *pq, FILE *fh, unsigned int blk_len, int in_out_n) state->fh = fh; state->blk_len = blk_len; - item = pq_add_item(pq); + item = osmo_gapk_pq_add_item(pq); if (!item) { free(state); return -ENOMEM; @@ -95,7 +95,7 @@ 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); return pq_queue_file_op(pq, src, blk_len, 1); @@ -108,7 +108,7 @@ 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); return pq_queue_file_op(pq, dst, blk_len, 0); diff --git a/src/pq_format.c b/src/pq_format.c index ae98483..08860a3 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -28,7 +28,7 @@ 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,18 +37,19 @@ 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); return -EINVAL; } - item = pq_add_item(pq); + item = osmo_gapk_pq_add_item(pq); if (!item) return -ENOMEM; diff --git a/src/pq_rtp.c b/src/pq_rtp.c index d7d924e..b68e84a 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -192,9 +192,9 @@ pq_cb_rtp_exit(void *_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)); @@ -217,7 +217,7 @@ 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); return -ENOMEM; @@ -239,7 +239,7 @@ 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); return pq_queue_rtp_op(pq, udp_fd, blk_len, 1); @@ -251,7 +251,7 @@ 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); return pq_queue_rtp_op(pq, udp_fd, blk_len, 0); diff --git a/src/procqueue.c b/src/procqueue.c index cba6dbb..f377db1 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -24,16 +24,16 @@ #include /* crate a new (empty) processing queue */ -struct pq * -pq_create(void) +struct osmo_gapk_pq * +osmo_gapk_pq_create(void) { - return (struct pq *) calloc(1, sizeof(struct pq)); + return (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_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; @@ -57,10 +57,10 @@ pq_destroy(struct pq *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; + struct osmo_gapk_pq_item *item; if (pq->n_items == MAX_PQ_ITEMS) { fprintf(stderr, "[!] Processing Queue cannot handle more than %u items\n", @@ -68,7 +68,7 @@ pq_add_item(struct pq *pq) return NULL; } - item = calloc(1, sizeof(struct pq_item)); + item = calloc(1, sizeof(struct osmo_gapk_pq_item)); if (!item) return NULL; @@ -81,7 +81,7 @@ pq_add_item(struct pq *pq) * \param[in] pq Processing Queue to be prepared * \returns 0 on succcess; negative on error */ int -pq_prepare(struct pq *pq) +osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) { int i; unsigned int len_prev; @@ -89,7 +89,7 @@ pq_prepare(struct pq *pq) len_prev = 0; for (i=0; in_items; i++) { - struct pq_item *item = pq->items[i]; + struct osmo_gapk_pq_item *item = pq->items[i]; if (item->len_in && item->len_in != len_prev) { fprintf(stderr, "[!] PQ item requires input size %u, but previous output is %u\n", @@ -121,7 +121,7 @@ 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; @@ -132,13 +132,13 @@ pq_execute(struct pq *pq) for (i=0; in_items; i++) { int rv; - struct pq_item *item = pq->items[i]; + struct osmo_gapk_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); if (rv < 0) { - fprintf(stderr, "[!] pq_execute(): abort, item returned %d\n", rv); + fprintf(stderr, "[!] osmo_gapk_pq_execute(): abort, item returned %d\n", rv); return rv; } -- cgit v1.2.3 From 349219c14875705b8142d599f6af153d22a9a00e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Sep 2017 00:42:38 +0700 Subject: benchmark: move benchmark_dump() outside the library The benchmark_dump() is only used by the osmo-gapk binary, and is intended to prepare and print benchmarking results to stderr, what is most likely unusable for the library users. --- include/osmocom/gapk/benchmark.h | 2 -- src/benchmark.c | 33 --------------------------------- src/main.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index a404168..6cfc074 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -54,5 +54,3 @@ static inline void benchmark_stop(enum osmo_gapk_codec_type codec, #define BENCHMARK_STOP(x,y) _cycles_stop = get_cycles(); \ benchmark_stop(x, y, _cycles_stop - _cycles_start); \ } while (0) - -void benchmark_dump(void); diff --git a/src/benchmark.c b/src/benchmark.c index 59f5965..3dead5a 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -22,36 +22,3 @@ #include struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; - -void benchmark_dump(void) -{ - int i; - - for (i = 0; i < _CODEC_MAX; i++) { - struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[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); - } - } -} diff --git a/src/main.c b/src/main.c index b9faeb2..b893f34 100644 --- a/src/main.c +++ b/src/main.c @@ -310,6 +310,39 @@ check_options(struct gapk_state *gs) return 0; } +static void +benchmark_dump(void) +{ + int i, j; + + for (i = 0; i < _CODEC_MAX; i++) { + struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[i]; + unsigned long long total; + + 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); + } + } +} + static int files_open(struct gapk_state *gs) { -- cgit v1.2.3 From ba46856bb403a507977e4c699c90714c962463f9 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Sep 2017 02:23:18 +0700 Subject: benchmark: move benchmark impl to a private header There is no need to expose the implementation details of both BENCHMARK_START and BENCHMARK_STOP macros via public header. This change moves them to a separate private header 'bench.h'. --- include/Makefile.am | 1 + include/osmocom/gapk/bench.h | 50 ++++++++++++++++++++++++++++++++++++++++ include/osmocom/gapk/benchmark.h | 28 +++------------------- src/codec_amr.c | 1 + src/codec_efr.c | 1 + src/codec_fr.c | 1 + src/codec_hr.c | 1 + 7 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 include/osmocom/gapk/bench.h diff --git a/include/Makefile.am b/include/Makefile.am index f64faeb..81419f7 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,6 @@ noinst_HEADERS = \ osmocom/gapk/utils.h \ + osmocom/gapk/bench.h \ $(NULL) nobase_include_HEADERS = \ diff --git a/include/osmocom/gapk/bench.h b/include/osmocom/gapk/bench.h new file mode 100644 index 0000000..02c28db --- /dev/null +++ b/include/osmocom/gapk/bench.h @@ -0,0 +1,50 @@ +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * (C) 2014 Harald Welte + * + * 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 . + * + */ + +#pragma once + +#include +#include +#include + +static inline void benchmark_store(enum osmo_gapk_codec_type codec, + int encode, unsigned long cycles) +{ + struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[codec]; + + if (encode) { + bc->enc_used = (bc->enc_used + 1) % OSMO_GAPK_CYCLES_NUM_AVG; + bc->enc[bc->enc_used] = cycles; + } else { + bc->dec_used = (bc->dec_used + 1) % OSMO_GAPK_CYCLES_NUM_AVG; + bc->dec[bc->dec_used] = cycles; + } +} + +#define BENCHMARK_START \ + do { \ + cycles_t _cycles_start, _cycles_stop; \ + _cycles_start = get_cycles() + +#define BENCHMARK_STOP(codec, enc) \ + _cycles_stop = get_cycles(); \ + benchmark_store(codec, enc, \ + _cycles_stop - _cycles_start); \ + } while (0) diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index 6cfc074..b64a3b5 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -22,35 +22,13 @@ #include #include -#define NUM_AVG 102400 +#define OSMO_GAPK_CYCLES_NUM_AVG 102400 struct osmo_gapk_bench_cycles { - cycles_t enc[NUM_AVG]; + cycles_t enc[OSMO_GAPK_CYCLES_NUM_AVG]; unsigned int enc_used; - cycles_t dec[NUM_AVG]; + cycles_t dec[OSMO_GAPK_CYCLES_NUM_AVG]; unsigned int dec_used; }; extern struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; - -static inline void benchmark_stop(enum osmo_gapk_codec_type codec, - int encode, unsigned long cycles) -{ - struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[codec]; - - if (encode) { - bc->enc_used = (bc->enc_used + 1) % NUM_AVG; - bc->enc[bc->enc_used] = cycles; - } else { - bc->dec_used = (bc->dec_used + 1) % NUM_AVG; - bc->dec[bc->dec_used] = cycles; - } -} - -#define BENCHMARK_START do { \ - cycles_t _cycles_start, _cycles_stop; \ - _cycles_start = get_cycles() - -#define BENCHMARK_STOP(x,y) _cycles_stop = get_cycles(); \ - benchmark_stop(x, y, _cycles_stop - _cycles_start); \ - } while (0) diff --git a/src/codec_amr.c b/src/codec_amr.c index 9cbeba6..2fa7a2f 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -20,6 +20,7 @@ #include #include +#include #include "config.h" diff --git a/src/codec_efr.c b/src/codec_efr.c index ba39f61..f5b7f83 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -19,6 +19,7 @@ #include #include +#include #include "config.h" diff --git a/src/codec_fr.c b/src/codec_fr.c index 6fc0af1..2a4936d 100644 --- a/src/codec_fr.c +++ b/src/codec_fr.c @@ -21,6 +21,7 @@ #include #include +#include #include "config.h" diff --git a/src/codec_hr.c b/src/codec_hr.c index 7c1484e..ef66f57 100644 --- a/src/codec_hr.c +++ b/src/codec_hr.c @@ -21,6 +21,7 @@ #include #include +#include #include "config.h" -- cgit v1.2.3 From c9a75e59c67d62bc9d64c8c110ef47feb60e7ebf Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Sep 2017 03:03:32 +0700 Subject: benchmark: get rid of 'static inline' definition The usage of a 'static inline' function definition in the 'bench.h' is resulting in separate independent function definitions in each translation unit from which the header is included. This is increasing the size of compiled code unnecessarily. --- include/osmocom/gapk/bench.h | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/include/osmocom/gapk/bench.h b/include/osmocom/gapk/bench.h index 02c28db..1cfbeb3 100644 --- a/include/osmocom/gapk/bench.h +++ b/include/osmocom/gapk/bench.h @@ -24,27 +24,25 @@ #include #include -static inline void benchmark_store(enum osmo_gapk_codec_type codec, - int encode, unsigned long cycles) -{ - struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[codec]; - - if (encode) { - bc->enc_used = (bc->enc_used + 1) % OSMO_GAPK_CYCLES_NUM_AVG; - bc->enc[bc->enc_used] = cycles; - } else { - bc->dec_used = (bc->dec_used + 1) % OSMO_GAPK_CYCLES_NUM_AVG; - bc->dec[bc->dec_used] = cycles; - } -} - #define BENCHMARK_START \ do { \ cycles_t _cycles_start, _cycles_stop; \ + struct osmo_gapk_bench_cycles *_bc; \ _cycles_start = get_cycles() -#define BENCHMARK_STOP(codec, enc) \ - _cycles_stop = get_cycles(); \ - benchmark_store(codec, enc, \ - _cycles_stop - _cycles_start); \ +#define BENCHMARK_STOP(codec, encode) \ + _cycles_stop = get_cycles(); \ + _bc = &osmo_gapk_bench_codec[codec]; \ + \ + if (encode) { \ + _bc->enc_used = (_bc->enc_used + 1) \ + % OSMO_GAPK_CYCLES_NUM_AVG; \ + _bc->enc[_bc->enc_used] = \ + _cycles_stop - _cycles_start; \ + } else { \ + _bc->dec_used = (_bc->dec_used + 1) \ + % OSMO_GAPK_CYCLES_NUM_AVG; \ + _bc->dec[_bc->dec_used] = \ + _cycles_stop - _cycles_start; \ + } \ } while (0) -- cgit v1.2.3 From 72218e7da04783222f04492d939268ac40585027 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Sep 2017 03:33:48 +0700 Subject: benchmark: allocate memory dynamically Having statically allocated memory for benchmark data of every codec causes high memory usage, especially if actual benchmarking is not required for a particular use case. Instead of that, let's provide an optional opportunity to enable benchmarking for a particular codec by calling the osmo_gapk_bench_enable(). The required amount of memory would be allocated, and then can be freed by calling the osmo_gapk_bench_free() or manually. --- include/osmocom/gapk/bench.h | 3 ++- include/osmocom/gapk/benchmark.h | 5 ++++- src/benchmark.c | 30 +++++++++++++++++++++++++++++- src/main.c | 11 ++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/osmocom/gapk/bench.h b/include/osmocom/gapk/bench.h index 1cfbeb3..404760e 100644 --- a/include/osmocom/gapk/bench.h +++ b/include/osmocom/gapk/bench.h @@ -32,7 +32,8 @@ #define BENCHMARK_STOP(codec, encode) \ _cycles_stop = get_cycles(); \ - _bc = &osmo_gapk_bench_codec[codec]; \ + _bc = osmo_gapk_bench_codec[codec]; \ + if (!_bc) break; \ \ if (encode) { \ _bc->enc_used = (_bc->enc_used + 1) \ diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index b64a3b5..cce7076 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -31,4 +31,7 @@ struct osmo_gapk_bench_cycles { unsigned int dec_used; }; -extern struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; +extern struct osmo_gapk_bench_cycles *osmo_gapk_bench_codec[_CODEC_MAX]; + +int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec); +void osmo_gapk_bench_free(void); diff --git a/src/benchmark.c b/src/benchmark.c index 3dead5a..8896a3b 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -18,7 +18,35 @@ */ #include +#include +#include #include +#include -struct osmo_gapk_bench_cycles osmo_gapk_bench_codec[_CODEC_MAX]; +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 = (struct osmo_gapk_bench_cycles *) + calloc(1, sizeof(struct osmo_gapk_bench_cycles)); + if (!bench) + return -ENOMEM; + + /* Set up pointer */ + osmo_gapk_bench_codec[codec] = bench; + + return 0; +} + +void osmo_gapk_bench_free(void) +{ + int i; + + for (i = 0; i < _CODEC_MAX; i++) + free(osmo_gapk_bench_codec[i]); +} diff --git a/src/main.c b/src/main.c index b893f34..623926f 100644 --- a/src/main.c +++ b/src/main.c @@ -316,7 +316,7 @@ benchmark_dump(void) int i, j; for (i = 0; i < _CODEC_MAX; i++) { - struct osmo_gapk_bench_cycles *bc = &osmo_gapk_bench_codec[i]; + struct osmo_gapk_bench_cycles *bc = osmo_gapk_bench_codec[i]; unsigned long long total; if (bc->enc_used) { @@ -498,6 +498,9 @@ make_processing_chain(struct gapk_state *gs) /* Do decoding */ osmo_gapk_pq_queue_codec(gs->pq, codec_in, 0); + + /* Allocate memory for benchmarking */ + osmo_gapk_bench_enable(fmt_in->codec_type); } else if (fmt_in->type != fmt_out->type) { @@ -511,6 +514,9 @@ make_processing_chain(struct gapk_state *gs) /* Do encoding */ osmo_gapk_pq_queue_codec(gs->pq, codec_out, 1); + /* Allocate memory for benchmarking */ + osmo_gapk_bench_enable(fmt_out->codec_type); + /* Convert encoder output to output fmt */ if (fmt_out->type != codec_out->codec_enc_format_type) { @@ -649,6 +655,9 @@ error: osmo_gapk_pq_destroy(gs->pq); benchmark_dump(); + + /* Free memory taken by benchmark data */ + osmo_gapk_bench_free(); return rv; } -- cgit v1.2.3 From cda8995ac8a17cc1d579f73519fd5b0f2429675a Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Sep 2017 04:18:06 +0700 Subject: benchmark: add functions to get cycle and frame count To simplify the benchrarking process via the library API, this change introduces two new functions, which are intended to provide total cycle and frame count. --- include/osmocom/gapk/benchmark.h | 5 +++++ src/benchmark.c | 36 ++++++++++++++++++++++++++++++++++++ src/main.c | 40 +++++++++++++++++++++------------------- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/include/osmocom/gapk/benchmark.h b/include/osmocom/gapk/benchmark.h index cce7076..f87899d 100644 --- a/include/osmocom/gapk/benchmark.h +++ b/include/osmocom/gapk/benchmark.h @@ -35,3 +35,8 @@ extern struct osmo_gapk_bench_cycles *osmo_gapk_bench_codec[_CODEC_MAX]; int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec); void osmo_gapk_bench_free(void); + +unsigned long long +osmo_gapk_bench_get_cycles(enum osmo_gapk_codec_type codec, int enc); +unsigned int +osmo_gapk_bench_get_frames(enum osmo_gapk_codec_type codec, int enc); diff --git a/src/benchmark.c b/src/benchmark.c index 8896a3b..e9637b1 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -43,6 +43,42 @@ int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec) 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; + + /* 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; diff --git a/src/main.c b/src/main.c index 623926f..3596ec1 100644 --- a/src/main.c +++ b/src/main.c @@ -313,32 +313,34 @@ check_options(struct gapk_state *gs) static void benchmark_dump(void) { - int i, j; + int i; for (i = 0; i < _CODEC_MAX; i++) { - struct osmo_gapk_bench_cycles *bc = osmo_gapk_bench_codec[i]; - unsigned long long total; + 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) { - 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); + cycles = osmo_gapk_bench_get_cycles(i, 1); + frames = osmo_gapk_bench_get_frames(i, 1); + + fprintf(stderr, "Codec %u (ENC): %llu cycles for %u frames" + " => %llu cycles/frame\n", i, cycles, + frames, cycles / frames); } 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); + cycles = osmo_gapk_bench_get_cycles(i, 0); + frames = osmo_gapk_bench_get_frames(i, 0); + + fprintf(stderr, "Codec %u (DEC): %llu cycles for %u frames" + " => %llu cycles/frame\n", i, cycles, + frames, cycles / frames); } } } -- cgit v1.2.3 From 4f0a47d0e35ece9ca46bb62294357d89920d06aa Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 31 Aug 2017 17:49:36 +0700 Subject: Add the symbol export map for libosmogapk --- configure.ac | 10 ++++++++++ src/Makefile.am | 2 ++ src/libosmogapk.map | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/libosmogapk.map diff --git a/configure.ac b/configure.ac index 901a3d6..35b08f1 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,16 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])], CFLAGS="$saved_CFLAGS" AC_SUBST(SYMBOL_VISIBILITY) +dnl check os: some linker flags not available on osx +case $host in +*-darwin*) + ;; +*) + LTLDFLAGS_OSMOGAPK='-Wl,--version-script=$(srcdir)/libosmogapk.map' + ;; +esac +AC_SUBST(LTLDFLAGS_OSMOGAPK) + # Checks for programs. AC_PROG_CC diff --git a/src/Makefile.am b/src/Makefile.am index c38f2fe..5dd75ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,7 @@ AM_CFLAGS = \ $(NULL) lib_LTLIBRARIES = libosmogapk.la +EXTRA_DIST = libosmogapk.map libosmogapk_la_LDFLAGS = \ $(LIBOSMOCORE_LIBS) \ @@ -25,6 +26,7 @@ libosmogapk_la_LDFLAGS = \ ${OPENCORE_AMRNB_LIBS} \ ${LIBGSM_LIBS} \ $(LIBALSA_LIBS) \ + $(LTLDFLAGS_OSMOGAPK) \ -version-info $(LIBVERSION) \ -no-undefined \ $(NULL) diff --git a/src/libosmogapk.map b/src/libosmogapk.map new file mode 100644 index 0000000..0ab0669 --- /dev/null +++ b/src/libosmogapk.map @@ -0,0 +1,44 @@ +LIBOSMOGAPK_1.0 { +global: + +osmo_gapk_pq; +osmo_gapk_pq_item; + +osmo_gapk_pq_create; +osmo_gapk_pq_prepare; +osmo_gapk_pq_execute; +osmo_gapk_pq_destroy; + +osmo_gapk_pq_add_item; + +osmo_gapk_pq_queue_file_input; +osmo_gapk_pq_queue_file_output; +osmo_gapk_pq_queue_rtp_input; +osmo_gapk_pq_queue_rtp_output; +osmo_gapk_pq_queue_alsa_input; +osmo_gapk_pq_queue_alsa_output; +osmo_gapk_pq_queue_fmt_convert; +osmo_gapk_pq_queue_codec; + +osmo_gapk_format_desc; +osmo_gapk_format_type; +osmo_gapk_fmt_conv_cb_t; + +osmo_gapk_fmt_get_from_type; +osmo_gapk_fmt_get_from_name; + +osmo_gapk_codec_desc; +osmo_gapk_codec_type; +osmo_gapk_codec_conv_cb_t; + +osmo_gapk_codec_get_from_type; + +osmo_gapk_bench_codec; +osmo_gapk_bench_enable; +osmo_gapk_bench_free; + +osmo_gapk_bench_get_cycles; +osmo_gapk_bench_get_frames; + +local: *; +}; -- cgit v1.2.3 From 3be9c7ae3c22f3e91c4e54b57a07b722dd4fb73f Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Sep 2017 14:33:19 +0700 Subject: procqueue: use unsigned int for I/O frame size fields A frame size cannot be negative, so 'unsigned' is more suitable for frame size fields. --- include/osmocom/gapk/procqueue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index 50e6eb6..b4aa857 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -24,9 +24,9 @@ struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ - int len_in; + unsigned int len_in; /*! output frame size (in bytes). '0' in case of variable frames */ - int len_out; + unsigned int len_out; /*! opaque state */ void *state; /*! call-back for actual format conversion function -- cgit v1.2.3 From 304fa73421a7c6ca5dcf36145f40c77af7df1de7 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Sep 2017 15:15:45 +0700 Subject: procqueue: store output buffers inside queue items An output buffer belongs to its queue item, so it will be more correctly to store its pointer inside the osmo_gapk_pq_item. --- include/osmocom/gapk/procqueue.h | 3 ++- src/procqueue.c | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index b4aa857..6921b51 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -29,6 +29,8 @@ struct osmo_gapk_pq_item { unsigned int len_out; /*! opaque state */ void *state; + /*! buffer for output data */ + uint8_t *buf; /*! call-back for actual format conversion function * \param[in] state opaque state pointer * \param[out] out caller-allocated buffer for output data @@ -45,7 +47,6 @@ struct osmo_gapk_pq_item { struct osmo_gapk_pq { unsigned n_items; struct osmo_gapk_pq_item *items[MAX_PQ_ITEMS]; - void *buffers[MAX_PQ_ITEMS + 1]; }; /* Processing queue management */ diff --git a/src/procqueue.c b/src/procqueue.c index f377db1..0176317 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -45,12 +45,11 @@ osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq) continue; if (pq->items[i]->exit) pq->items[i]->exit(pq->items[i]->state); + + free(pq->items[i]->buf); free(pq->items[i]); } - for (i=0; in_items-1; i++) - free(pq->buffers[i]); /* free is NULL safe */ - free(pq); } @@ -103,8 +102,9 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) * known buffer size */ if (!buf_size) buf_size = VAR_BUF_SIZE; - pq->buffers[i] = malloc(buf_size); - if (!pq->buffers[i]) + + item->buf = malloc(buf_size); + if (!item->buf) return -ENOMEM; } else{ if (item->len_out) @@ -134,7 +134,7 @@ osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) int rv; struct osmo_gapk_pq_item *item = pq->items[i]; - buf = i < (pq->n_items-1) ? pq->buffers[i] : NULL; + buf = i < (pq->n_items-1) ? item->buf : NULL; rv = item->proc(item->state, buf, buf_prev, len_prev); if (rv < 0) { -- cgit v1.2.3 From 1cf7f34444b3d8b44122a57d2bed7542b8c3b7f2 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Sep 2017 15:22:32 +0700 Subject: procqueue: use uint8_t as output buffer type --- src/procqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/procqueue.c b/src/procqueue.c index 0176317..1586f97 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -124,7 +124,7 @@ int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) { int i; - void *buf_prev, *buf; + uint8_t *buf_prev, *buf; unsigned int len_prev; buf_prev = NULL; -- cgit v1.2.3 From 539af39e29726fc196e874b5d9cd6ec619dc5f3c Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Sep 2017 16:19:40 +0700 Subject: procqueue: use linuxlist to store queue items The usage of linuxlist is more flexible than having a limited array of pointers. This approach allows to have as much items in a processing queue as required. --- include/osmocom/gapk/procqueue.h | 8 ++- src/procqueue.c | 104 ++++++++++++++++++++++----------------- 2 files changed, 65 insertions(+), 47 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index 6921b51..a72fd61 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -22,6 +22,8 @@ #include #include /* for FILE */ +#include + struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ unsigned int len_in; @@ -39,14 +41,16 @@ struct osmo_gapk_pq_item { * \returns number of output bytes written to \a out; negative on error */ int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len); void (*exit)(void *state); + + /*! \brief link to a processing queue */ + struct llist_head list; }; #define VAR_BUF_SIZE 320 -#define MAX_PQ_ITEMS 8 struct osmo_gapk_pq { + struct llist_head items; unsigned n_items; - struct osmo_gapk_pq_item *items[MAX_PQ_ITEMS]; }; /* Processing queue management */ diff --git a/src/procqueue.c b/src/procqueue.c index 1586f97..00472d3 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -21,13 +21,23 @@ #include #include +#include + #include /* crate a new (empty) processing queue */ struct osmo_gapk_pq * osmo_gapk_pq_create(void) { - return (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_pq)); + struct osmo_gapk_pq *pq; + + /* Allocate memory for a new processing queue */ + pq = (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_pq)); + + /* Init its list of items */ + INIT_LLIST_HEAD(&pq->items); + + return pq; } /*! destroy a processing queue, calls exit() callback of each item @@ -35,19 +45,23 @@ osmo_gapk_pq_create(void) void 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; in_items; i++) { - if (!pq->items[i]) - continue; - if (pq->items[i]->exit) - pq->items[i]->exit(pq->items[i]->state); + /* Iterate over all items in queue */ + llist_for_each_entry_safe(item, item_next, &pq->items, list) { + /* Free output buffer memory */ + free(item->buf); + + /* Call exit handler if preset */ + if (item->exit) + item->exit(item->state); - free(pq->items[i]->buf); - free(pq->items[i]); + /* Delete an item from list */ + llist_del(&item->list); + free(item); } free(pq); @@ -61,17 +75,16 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) { struct osmo_gapk_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; - } - + /* Allocate memory for a new item */ item = calloc(1, sizeof(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; } @@ -82,35 +95,40 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) { - int i; - unsigned int len_prev; - - len_prev = 0; - - for (i=0; in_items; i++) { - struct osmo_gapk_pq_item *item = pq->items[i]; + struct osmo_gapk_pq_item *item; + unsigned int len_prev = 0; + /* Iterate over all items in queue */ + llist_for_each_entry(item, &pq->items, list) { + /* Make sure I/O data lengths are equal */ 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); + fprintf(stderr, "[!] PQ item requires input size %u, " + "but previous output is %u\n", item->len_in, len_prev); return -EINVAL; } - if (i < (pq->n_items-1)) { + /* 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; + /* Allocate memory for an output buffer */ item->buf = malloc(buf_size); if (!item->buf) return -ENOMEM; - } else{ + } else { + /* Make sure the last item is a sink */ if (item->len_out) return -EINVAL; } + /* Store output length for further comparation */ len_prev = item->len_out; } @@ -123,26 +141,22 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) { - int i; - uint8_t *buf_prev, *buf; - unsigned int len_prev; - - buf_prev = NULL; - len_prev = 0; - - for (i=0; in_items; i++) { - int rv; - struct osmo_gapk_pq_item *item = pq->items[i]; - - buf = i < (pq->n_items-1) ? item->buf : 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, "[!] osmo_gapk_pq_execute(): abort, item returned %d\n", rv); + fprintf(stderr, "[!] osmo_gapk_pq_execute(): " + "abort, item returned %d\n", rv); return rv; } - buf_prev = buf; + buf_prev = item->buf; len_prev = rv; } -- cgit v1.2.3 From 5716ca636d8638060e525f428a497ddee18b4072 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 6 Sep 2017 23:42:19 +0300 Subject: osmo-gapk: add an option to enable / disable benchmark If the codec benchmarking is required in particular case, it could be activated by a special command line option introduced by this change. --- src/main.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 3596ec1..661f246 100644 --- a/src/main.c +++ b/src/main.c @@ -56,6 +56,8 @@ struct gapk_options } rtp_out; const char *alsa_out; const struct osmo_gapk_format_desc *fmt_out; + + int benchmark; }; struct gapk_state @@ -104,6 +106,7 @@ 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, "\n"); /* Print all codecs */ @@ -172,9 +175,10 @@ 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'}, {"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:bh" #ifdef HAVE_ALSA "a:A:" #endif @@ -246,6 +250,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) } break; + case 'b': + opt->benchmark = 1; + break; + case 'h': return 1; @@ -502,7 +510,8 @@ make_processing_chain(struct gapk_state *gs) osmo_gapk_pq_queue_codec(gs->pq, codec_in, 0); /* Allocate memory for benchmarking */ - osmo_gapk_bench_enable(fmt_in->codec_type); + if (gs->opts.benchmark) + osmo_gapk_bench_enable(fmt_in->codec_type); } else if (fmt_in->type != fmt_out->type) { @@ -517,7 +526,8 @@ make_processing_chain(struct gapk_state *gs) osmo_gapk_pq_queue_codec(gs->pq, codec_out, 1); /* Allocate memory for benchmarking */ - osmo_gapk_bench_enable(fmt_out->codec_type); + 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) -- cgit v1.2.3 From 4ffd6f20a9b7604308506d9e04ef1bb2e41cd282 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 6 Sep 2017 23:53:30 +0300 Subject: osmo-gapk: create a common shutdown function Previously the code intended to shutdown the osmo-gapk application was repeated two times. It's better to have a single function. --- src/main.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main.c b/src/main.c index 661f246..90779af 100644 --- a/src/main.c +++ b/src/main.c @@ -587,13 +587,27 @@ 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(); +} + static void signal_handler(int signal) { switch (signal) { case SIGINT: - fprintf(stderr, "catching sigint, closing files\n"); - files_close(gs); - osmo_gapk_pq_destroy(gs->pq); + fprintf(stderr, "catching sigint, shutting down...\n"); + app_shutdown(); exit(0); break; default: @@ -660,16 +674,6 @@ int main(int argc, char *argv[]) rv = run(gs); error: - /* Close source / destination files */ - files_close(gs); - - /* Release processing queue */ - osmo_gapk_pq_destroy(gs->pq); - - benchmark_dump(); - - /* Free memory taken by benchmark data */ - osmo_gapk_bench_free(); - + app_shutdown(); return rv; } -- cgit v1.2.3 From f8d91a07b45a618fd25c9d6edcf28218642044c9 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 00:04:01 +0300 Subject: osmo-gapk: use more convenient name for the source file Since GAPK package contains a library and the representative osmo-gapk application, the 'main.c' looks a bit confusing. Let's use the common naming scheme. --- configure.ac | 2 +- src/Makefile.am | 2 +- src/app_osmo_gapk.c | 679 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 679 ---------------------------------------------------- 4 files changed, 681 insertions(+), 681 deletions(-) create mode 100644 src/app_osmo_gapk.c delete mode 100644 src/main.c diff --git a/configure.ac b/configure.ac index 35b08f1..fdbc787 100644 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ LT_INIT([disable-static]) # kernel style compile messages m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -AC_CONFIG_SRCDIR([src/main.c]) +AC_CONFIG_SRCDIR([src/app_osmo_gapk.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_FILES([ diff --git a/src/Makefile.am b/src/Makefile.am index 5dd75ff..2c52ec1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,7 +80,7 @@ libosmogapk_la_SOURCES += \ bin_PROGRAMS = osmo-gapk osmo_gapk_SOURCES = \ - main.c \ + app_osmo_gapk.c \ $(NULL) osmo_gapk_LDFLAGS = \ diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c new file mode 100644 index 0000000..90779af --- /dev/null +++ b/src/app_osmo_gapk.c @@ -0,0 +1,679 @@ +/* Main */ + +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + + +struct gapk_options +{ + const char *fname_in; + struct { + const char *hostname; + uint16_t port; + } rtp_in; + const char *alsa_in; + const struct osmo_gapk_format_desc *fmt_in; + + const char *fname_out; + struct { + const char *hostname; + uint16_t port; + } rtp_out; + const char *alsa_out; + const struct osmo_gapk_format_desc *fmt_out; + + int benchmark; +}; + +struct gapk_state +{ + struct gapk_options opts; + + struct osmo_gapk_pq *pq; + + struct { + struct { + FILE *fh; + } file; + struct { + int fd; + } rtp; + } in; + + struct { + struct { + FILE *fh; + } file; + struct { + int fd; + } rtp; + } out; +}; + + +static void +print_help(char *progname) +{ + const struct osmo_gapk_codec_desc *codec; + int i; + + /* Header */ + fprintf(stdout, "Usage: %s [options]\n", progname); + fprintf(stdout, "\n"); + fprintf(stdout, "Options:\n"); + fprintf(stdout, " -i, --input-file=FILE\t\tInput file\n"); + fprintf(stdout, " -I, --input-rtp=HOST/PORT\tInput RTP stream\n"); + fprintf(stdout, " -o, --output-file=FILE\tOutput file\n"); + fprintf(stdout, " -O, --output-rtp=HOST/PORT\tOutput RTP stream\n"); +#ifdef HAVE_ALSA + fprintf(stdout, " -a, --input-alsa=dev\t\tInput ALSA stream\n"); + fprintf(stdout, " -A, --output-alsa=dev\t\tOutput ALSA stream\n"); +#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, "\n"); + + /* Print all codecs */ + fprintf(stdout, "Supported codecs:\n"); + fprintf(stdout, " name\tfmt enc dec\tdescription\n"); + + for (i=CODEC_INVALID+1; i<_CODEC_MAX; i++) { + codec = osmo_gapk_codec_get_from_type(i); + fprintf(stdout, " %4s %c %c %c \t%s\n", + codec->name, + '*', + codec->codec_encode ? '*' : ' ', + codec->codec_decode ? '*' : ' ', + codec->description + ); + } + + fprintf(stdout, "\n"); + + /* Print all formats */ + fprintf(stdout, "Supported formats:\n"); + + for (i=FMT_INVALID+1; i<_FMT_MAX; i++) { + const struct osmo_gapk_format_desc *fmt = osmo_gapk_fmt_get_from_type(i); + fprintf(stdout, " %-19s %s\n", + fmt->name, + fmt->description + ); + } + + fprintf(stdout, "\n"); +} + +static int +parse_host_port(const char *host_port, const char **host) +{ + char *dup = strdup(host_port); + char *tok; + + if (!dup) + return -ENOMEM; + + tok = strtok(dup, "/"); + if (!tok) + return -EINVAL; + *host = tok; + + tok = strtok(NULL, "/"); + if (!tok) + return -EINVAL; + + return atoi(tok); +} + +static int +parse_options(struct gapk_state *state, int argc, char *argv[]) +{ + const struct option long_options[] = { + {"input-file", 1, 0, 'i'}, + {"output-file", 1, 0, 'o'}, + {"input-rtp", 1, 0, 'I'}, + {"output-rtp", 1, 0, 'O'}, +#ifdef HAVE_ALSA + {"input-alsa", 1, 0, 'a'}, + {"output-alsa", 1, 0, 'A'}, +#endif + {"input-format", 1, 0, 'f'}, + {"output-format", 1, 0, 'g'}, + {"enable-benchmark", 0, 0, 'b'}, + {"help", 0, 0, 'h'}, + }; + const char *short_options = "i:o:I:O:f:g:bh" +#ifdef HAVE_ALSA + "a:A:" +#endif + ; + + struct gapk_options *opt = &state->opts; + + /* Set some defaults */ + memset(opt, 0x00, sizeof(*opt)); + + /* Parse */ + while (1) { + int c, rv; + int opt_idx; + + c = getopt_long( + argc, argv, short_options, long_options, &opt_idx); + if (c == -1) + break; + + switch (c) { + case 'i': + opt->fname_in = optarg; + break; + + case 'o': + opt->fname_out = optarg; + break; + + case 'I': + rv = parse_host_port(optarg, &opt->rtp_in.hostname); + if (rv < 0 || rv > 0xffff) { + fprintf(stderr, "[!] Invalid port: %d\n", rv); + return -EINVAL; + } + opt->rtp_in.port = rv; + break; +#ifdef HAVE_ALSA + case 'a': + opt->alsa_in = optarg; + break; + + case 'A': + opt->alsa_out = optarg; + break; +#endif + case 'O': + rv = parse_host_port(optarg, &opt->rtp_out.hostname); + if (rv < 0 || rv > 0xffff) { + fprintf(stderr, "[!] Invalid port: %d\n", rv); + return -EINVAL; + } + opt->rtp_out.port = rv; + break; + + case 'f': + opt->fmt_in = osmo_gapk_fmt_get_from_name(optarg); + if (!opt->fmt_in) { + fprintf(stderr, "[!] Unsupported format: %s\n", optarg); + return -EINVAL; + } + break; + + case 'g': + opt->fmt_out = osmo_gapk_fmt_get_from_name(optarg); + if (!opt->fmt_out) { + fprintf(stderr, "[!] Unsupported format: %s\n", optarg); + return -EINVAL; + } + break; + + case 'b': + opt->benchmark = 1; + break; + + case 'h': + return 1; + + default: + fprintf(stderr, "[+] Unknown option\n"); + return -EINVAL; + + } + } + + return 0; +} + +static int +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"); + return -EINVAL; + } + + /* Transcoding */ + if (gs->opts.fmt_in->codec_type != gs->opts.fmt_out->codec_type) { + const struct osmo_gapk_codec_desc *codec; + + /* Check source codec */ + codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_in->codec_type); + if (!codec) { + fprintf(stderr, "[!] 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); + return -ENOTSUP; + } + + /* Check destination codec */ + codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_out->codec_type); + if (!codec) { + fprintf(stderr, "[!] 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); + 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"); + 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); + + fprintf(stderr, "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); + + fprintf(stderr, "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) +{ + if (gs->opts.fname_in) { + 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"); + perror("fopen"); + return -errno; + } + } else if (gs->opts.rtp_in.port) { + 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"); + return gs->in.rtp.fd; + } + } else if (gs->opts.alsa_in) { + printf("alsa_in, not stdin\n"); + } else + gs->in.file.fh = stdin; + + if (gs->opts.fname_out) { + 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"); + perror("fopen"); + return -errno; + } + } else if (gs->opts.rtp_out.port) { + 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"); + return gs->out.rtp.fd; + } + } else if (gs->opts.alsa_out) { + printf("alsa_out, not stdout\n"); + } else + gs->out.file.fh = stdout; + + return 0; +} + +static void +files_close(struct gapk_state *gs) +{ + if (gs->in.file.fh && gs->in.file.fh != stdin) + fclose(gs->in.file.fh); + if (gs->in.rtp.fd >= 0) + close(gs->in.rtp.fd); + if (gs->out.file.fh && gs->out.file.fh != stdout) + fclose(gs->out.file.fh); + if (gs->out.rtp.fd >= 0) + close(gs->out.rtp.fd); +} + +static int +handle_headers(struct gapk_state *gs) +{ + int rv; + unsigned int len; + + /* Input file header (remove & check it) */ + len = gs->opts.fmt_in->header_len; + if (len && gs->in.file.fh) { + uint8_t *buf; + + buf = malloc(len); + if (!buf) + return -ENOMEM; + + rv = fread(buf, len, 1, gs->in.file.fh); + if ((rv != 1) || + memcmp(buf, gs->opts.fmt_in->header, len)) + { + free(buf); + fprintf(stderr, "[!] Invalid header in input file"); + return -EINVAL; + } + + free(buf); + } + + /* Output file header (write it) */ + len = gs->opts.fmt_out->header_len; + if (len && gs->out.file.fh) { + rv = fwrite(gs->opts.fmt_out->header, len, 1, gs->out.file.fh); + if (rv != 1) + return -ENOSPC; + } + + return 0; +} + +static int +make_processing_chain(struct gapk_state *gs) +{ + 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; + + fmt_in = gs->opts.fmt_in; + fmt_out = gs->opts.fmt_out; + + 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); + need_enc = (fmt_out->codec_type != CODEC_PCM) && + (fmt_out->codec_type != fmt_in->codec_type); + + /* File read */ + if (gs->in.file.fh) + osmo_gapk_pq_queue_file_input(gs->pq, gs->in.file.fh, fmt_in->frame_len); + else if (gs->in.rtp.fd != -1) + 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) + osmo_gapk_pq_queue_alsa_input(gs->pq, gs->opts.alsa_in, fmt_in->frame_len); +#endif + else { + fprintf(stderr, "Unknown/invalid input\n"); + return -1; + } + + /* Decoding to PCM ? */ + if (need_dec) + { + /* Convert input to decoder input fmt */ + if (fmt_in->type != codec_in->codec_dec_format_type) + { + const struct osmo_gapk_format_desc *fmt_dec; + + 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); + return -EINVAL; + } + + osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0); + osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_dec, 1); + } + + /* Do decoding */ + 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 */ + osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0); + } + + /* Encoding from PCM ? */ + if (need_enc) + { + /* Do encoding */ + 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 osmo_gapk_format_desc *fmt_enc; + + 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); + return -EINVAL; + } + + 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 */ + osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_out, 1); + } + + /* File write */ + if (gs->out.file.fh) + osmo_gapk_pq_queue_file_output(gs->pq, gs->out.file.fh, fmt_out->frame_len); + else if (gs->out.rtp.fd != -1) + 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) + osmo_gapk_pq_queue_alsa_output(gs->pq, gs->opts.alsa_out, fmt_out->frame_len); +#endif + else { + fprintf(stderr, "Unknown/invalid output\n"); + return -1; + } + + return 0; +} + +static int +run(struct gapk_state *gs) +{ + int rv, frames; + + rv = osmo_gapk_pq_prepare(gs->pq); + if (rv) + return rv; + + for (frames=0; !(rv = osmo_gapk_pq_execute(gs->pq)); frames++); + + fprintf(stderr, "[+] Processed %d frames\n", frames); + + return frames > 0 ? 0 : rv; +} + + +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(); +} + +static void signal_handler(int signal) +{ + switch (signal) { + case SIGINT: + fprintf(stderr, "catching sigint, shutting down...\n"); + app_shutdown(); + exit(0); + break; + default: + break; + } +} + + +int main(int argc, char *argv[]) +{ + int rv; + + /* Clear state */ + memset(gs, 0x00, sizeof(struct gapk_state)); + gs->in.rtp.fd = -1; + gs->out.rtp.fd = -1; + + /* Parse / check options */ + rv = parse_options(gs, argc, argv); + if (rv > 0) { + print_help(argv[0]); + return 0; + } + if (rv < 0) + return rv; + + /* Check request */ + rv = check_options(gs); + if (rv) + return rv; + + /* Create processing queue */ + gs->pq = osmo_gapk_pq_create(); + if (!gs->pq) { + rv = -ENOMEM; + fprintf(stderr, "Error creating processing queue\n"); + goto error; + } + + /* Open source / destination files */ + rv = files_open(gs); + if (rv) { + fprintf(stderr, "Error opening file(s)\n"); + goto error; + } + + /* Handle input/output headers */ + rv = handle_headers(gs); + if (rv) { + fprintf(stderr, "Error handling header(s)\n"); + goto error; + } + + /* Make processing chain */ + rv = make_processing_chain(gs); + if (rv) { + fprintf(stderr, "Error making processing chain\n"); + goto error; + } + + signal(SIGINT, &signal_handler); + + /* Run the processing queue */ + rv = run(gs); + +error: + app_shutdown(); + return rv; +} diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 90779af..0000000 --- a/src/main.c +++ /dev/null @@ -1,679 +0,0 @@ -/* Main */ - -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * 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 . - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - - -struct gapk_options -{ - const char *fname_in; - struct { - const char *hostname; - uint16_t port; - } rtp_in; - const char *alsa_in; - const struct osmo_gapk_format_desc *fmt_in; - - const char *fname_out; - struct { - const char *hostname; - uint16_t port; - } rtp_out; - const char *alsa_out; - const struct osmo_gapk_format_desc *fmt_out; - - int benchmark; -}; - -struct gapk_state -{ - struct gapk_options opts; - - struct osmo_gapk_pq *pq; - - struct { - struct { - FILE *fh; - } file; - struct { - int fd; - } rtp; - } in; - - struct { - struct { - FILE *fh; - } file; - struct { - int fd; - } rtp; - } out; -}; - - -static void -print_help(char *progname) -{ - const struct osmo_gapk_codec_desc *codec; - int i; - - /* Header */ - fprintf(stdout, "Usage: %s [options]\n", progname); - fprintf(stdout, "\n"); - fprintf(stdout, "Options:\n"); - fprintf(stdout, " -i, --input-file=FILE\t\tInput file\n"); - fprintf(stdout, " -I, --input-rtp=HOST/PORT\tInput RTP stream\n"); - fprintf(stdout, " -o, --output-file=FILE\tOutput file\n"); - fprintf(stdout, " -O, --output-rtp=HOST/PORT\tOutput RTP stream\n"); -#ifdef HAVE_ALSA - fprintf(stdout, " -a, --input-alsa=dev\t\tInput ALSA stream\n"); - fprintf(stdout, " -A, --output-alsa=dev\t\tOutput ALSA stream\n"); -#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, "\n"); - - /* Print all codecs */ - fprintf(stdout, "Supported codecs:\n"); - fprintf(stdout, " name\tfmt enc dec\tdescription\n"); - - for (i=CODEC_INVALID+1; i<_CODEC_MAX; i++) { - codec = osmo_gapk_codec_get_from_type(i); - fprintf(stdout, " %4s %c %c %c \t%s\n", - codec->name, - '*', - codec->codec_encode ? '*' : ' ', - codec->codec_decode ? '*' : ' ', - codec->description - ); - } - - fprintf(stdout, "\n"); - - /* Print all formats */ - fprintf(stdout, "Supported formats:\n"); - - for (i=FMT_INVALID+1; i<_FMT_MAX; i++) { - const struct osmo_gapk_format_desc *fmt = osmo_gapk_fmt_get_from_type(i); - fprintf(stdout, " %-19s %s\n", - fmt->name, - fmt->description - ); - } - - fprintf(stdout, "\n"); -} - -static int -parse_host_port(const char *host_port, const char **host) -{ - char *dup = strdup(host_port); - char *tok; - - if (!dup) - return -ENOMEM; - - tok = strtok(dup, "/"); - if (!tok) - return -EINVAL; - *host = tok; - - tok = strtok(NULL, "/"); - if (!tok) - return -EINVAL; - - return atoi(tok); -} - -static int -parse_options(struct gapk_state *state, int argc, char *argv[]) -{ - const struct option long_options[] = { - {"input-file", 1, 0, 'i'}, - {"output-file", 1, 0, 'o'}, - {"input-rtp", 1, 0, 'I'}, - {"output-rtp", 1, 0, 'O'}, -#ifdef HAVE_ALSA - {"input-alsa", 1, 0, 'a'}, - {"output-alsa", 1, 0, 'A'}, -#endif - {"input-format", 1, 0, 'f'}, - {"output-format", 1, 0, 'g'}, - {"enable-benchmark", 0, 0, 'b'}, - {"help", 0, 0, 'h'}, - }; - const char *short_options = "i:o:I:O:f:g:bh" -#ifdef HAVE_ALSA - "a:A:" -#endif - ; - - struct gapk_options *opt = &state->opts; - - /* Set some defaults */ - memset(opt, 0x00, sizeof(*opt)); - - /* Parse */ - while (1) { - int c, rv; - int opt_idx; - - c = getopt_long( - argc, argv, short_options, long_options, &opt_idx); - if (c == -1) - break; - - switch (c) { - case 'i': - opt->fname_in = optarg; - break; - - case 'o': - opt->fname_out = optarg; - break; - - case 'I': - rv = parse_host_port(optarg, &opt->rtp_in.hostname); - if (rv < 0 || rv > 0xffff) { - fprintf(stderr, "[!] Invalid port: %d\n", rv); - return -EINVAL; - } - opt->rtp_in.port = rv; - break; -#ifdef HAVE_ALSA - case 'a': - opt->alsa_in = optarg; - break; - - case 'A': - opt->alsa_out = optarg; - break; -#endif - case 'O': - rv = parse_host_port(optarg, &opt->rtp_out.hostname); - if (rv < 0 || rv > 0xffff) { - fprintf(stderr, "[!] Invalid port: %d\n", rv); - return -EINVAL; - } - opt->rtp_out.port = rv; - break; - - case 'f': - opt->fmt_in = osmo_gapk_fmt_get_from_name(optarg); - if (!opt->fmt_in) { - fprintf(stderr, "[!] Unsupported format: %s\n", optarg); - return -EINVAL; - } - break; - - case 'g': - opt->fmt_out = osmo_gapk_fmt_get_from_name(optarg); - if (!opt->fmt_out) { - fprintf(stderr, "[!] Unsupported format: %s\n", optarg); - return -EINVAL; - } - break; - - case 'b': - opt->benchmark = 1; - break; - - case 'h': - return 1; - - default: - fprintf(stderr, "[+] Unknown option\n"); - return -EINVAL; - - } - } - - return 0; -} - -static int -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"); - return -EINVAL; - } - - /* Transcoding */ - if (gs->opts.fmt_in->codec_type != gs->opts.fmt_out->codec_type) { - const struct osmo_gapk_codec_desc *codec; - - /* Check source codec */ - codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_in->codec_type); - if (!codec) { - fprintf(stderr, "[!] 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); - return -ENOTSUP; - } - - /* Check destination codec */ - codec = osmo_gapk_codec_get_from_type(gs->opts.fmt_out->codec_type); - if (!codec) { - fprintf(stderr, "[!] 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); - 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"); - 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); - - fprintf(stderr, "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); - - fprintf(stderr, "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) -{ - if (gs->opts.fname_in) { - 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"); - perror("fopen"); - return -errno; - } - } else if (gs->opts.rtp_in.port) { - 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"); - return gs->in.rtp.fd; - } - } else if (gs->opts.alsa_in) { - printf("alsa_in, not stdin\n"); - } else - gs->in.file.fh = stdin; - - if (gs->opts.fname_out) { - 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"); - perror("fopen"); - return -errno; - } - } else if (gs->opts.rtp_out.port) { - 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"); - return gs->out.rtp.fd; - } - } else if (gs->opts.alsa_out) { - printf("alsa_out, not stdout\n"); - } else - gs->out.file.fh = stdout; - - return 0; -} - -static void -files_close(struct gapk_state *gs) -{ - if (gs->in.file.fh && gs->in.file.fh != stdin) - fclose(gs->in.file.fh); - if (gs->in.rtp.fd >= 0) - close(gs->in.rtp.fd); - if (gs->out.file.fh && gs->out.file.fh != stdout) - fclose(gs->out.file.fh); - if (gs->out.rtp.fd >= 0) - close(gs->out.rtp.fd); -} - -static int -handle_headers(struct gapk_state *gs) -{ - int rv; - unsigned int len; - - /* Input file header (remove & check it) */ - len = gs->opts.fmt_in->header_len; - if (len && gs->in.file.fh) { - uint8_t *buf; - - buf = malloc(len); - if (!buf) - return -ENOMEM; - - rv = fread(buf, len, 1, gs->in.file.fh); - if ((rv != 1) || - memcmp(buf, gs->opts.fmt_in->header, len)) - { - free(buf); - fprintf(stderr, "[!] Invalid header in input file"); - return -EINVAL; - } - - free(buf); - } - - /* Output file header (write it) */ - len = gs->opts.fmt_out->header_len; - if (len && gs->out.file.fh) { - rv = fwrite(gs->opts.fmt_out->header, len, 1, gs->out.file.fh); - if (rv != 1) - return -ENOSPC; - } - - return 0; -} - -static int -make_processing_chain(struct gapk_state *gs) -{ - 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; - - fmt_in = gs->opts.fmt_in; - fmt_out = gs->opts.fmt_out; - - 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); - need_enc = (fmt_out->codec_type != CODEC_PCM) && - (fmt_out->codec_type != fmt_in->codec_type); - - /* File read */ - if (gs->in.file.fh) - osmo_gapk_pq_queue_file_input(gs->pq, gs->in.file.fh, fmt_in->frame_len); - else if (gs->in.rtp.fd != -1) - 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) - osmo_gapk_pq_queue_alsa_input(gs->pq, gs->opts.alsa_in, fmt_in->frame_len); -#endif - else { - fprintf(stderr, "Unknown/invalid input\n"); - return -1; - } - - /* Decoding to PCM ? */ - if (need_dec) - { - /* Convert input to decoder input fmt */ - if (fmt_in->type != codec_in->codec_dec_format_type) - { - const struct osmo_gapk_format_desc *fmt_dec; - - 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); - return -EINVAL; - } - - osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0); - osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_dec, 1); - } - - /* Do decoding */ - 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 */ - osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_in, 0); - } - - /* Encoding from PCM ? */ - if (need_enc) - { - /* Do encoding */ - 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 osmo_gapk_format_desc *fmt_enc; - - 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); - return -EINVAL; - } - - 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 */ - osmo_gapk_pq_queue_fmt_convert(gs->pq, fmt_out, 1); - } - - /* File write */ - if (gs->out.file.fh) - osmo_gapk_pq_queue_file_output(gs->pq, gs->out.file.fh, fmt_out->frame_len); - else if (gs->out.rtp.fd != -1) - 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) - osmo_gapk_pq_queue_alsa_output(gs->pq, gs->opts.alsa_out, fmt_out->frame_len); -#endif - else { - fprintf(stderr, "Unknown/invalid output\n"); - return -1; - } - - return 0; -} - -static int -run(struct gapk_state *gs) -{ - int rv, frames; - - rv = osmo_gapk_pq_prepare(gs->pq); - if (rv) - return rv; - - for (frames=0; !(rv = osmo_gapk_pq_execute(gs->pq)); frames++); - - fprintf(stderr, "[+] Processed %d frames\n", frames); - - return frames > 0 ? 0 : rv; -} - - -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(); -} - -static void signal_handler(int signal) -{ - switch (signal) { - case SIGINT: - fprintf(stderr, "catching sigint, shutting down...\n"); - app_shutdown(); - exit(0); - break; - default: - break; - } -} - - -int main(int argc, char *argv[]) -{ - int rv; - - /* Clear state */ - memset(gs, 0x00, sizeof(struct gapk_state)); - gs->in.rtp.fd = -1; - gs->out.rtp.fd = -1; - - /* Parse / check options */ - rv = parse_options(gs, argc, argv); - if (rv > 0) { - print_help(argv[0]); - return 0; - } - if (rv < 0) - return rv; - - /* Check request */ - rv = check_options(gs); - if (rv) - return rv; - - /* Create processing queue */ - gs->pq = osmo_gapk_pq_create(); - if (!gs->pq) { - rv = -ENOMEM; - fprintf(stderr, "Error creating processing queue\n"); - goto error; - } - - /* Open source / destination files */ - rv = files_open(gs); - if (rv) { - fprintf(stderr, "Error opening file(s)\n"); - goto error; - } - - /* Handle input/output headers */ - rv = handle_headers(gs); - if (rv) { - fprintf(stderr, "Error handling header(s)\n"); - goto error; - } - - /* Make processing chain */ - rv = make_processing_chain(gs); - if (rv) { - fprintf(stderr, "Error making processing chain\n"); - goto error; - } - - signal(SIGINT, &signal_handler); - - /* Run the processing queue */ - rv = run(gs); - -error: - app_shutdown(); - return rv; -} -- cgit v1.2.3 From c35ba8a725405f7712618871c56a3b7fb3933e2a Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 16:36:56 +0300 Subject: libosmogapk: use Osmocom logging framework Since this change, the libosmogapk uses the Osmocom logging framework. By default, logging is disabled and could be enabled by the external applications calling the osmo_gapk_log_init() with a desired log target as an argument. --- include/Makefile.am | 2 ++ include/osmocom/gapk/common.h | 21 +++++++++++++++++++++ include/osmocom/gapk/logging.h | 28 ++++++++++++++++++++++++++++ src/Makefile.am | 5 +++++ src/app_osmo_gapk.c | 28 ++++++++++++++++++++++++++++ src/libosmogapk.map | 2 ++ src/logging.c | 27 +++++++++++++++++++++++++++ src/pq_alsa.c | 9 ++++++--- src/pq_codec.c | 3 ++- src/pq_file.c | 5 +++-- src/pq_format.c | 12 +++++++----- src/pq_rtp.c | 8 +++++--- src/procqueue.c | 7 ++++--- 13 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 include/osmocom/gapk/common.h create mode 100644 include/osmocom/gapk/logging.h create mode 100644 src/logging.c diff --git a/include/Makefile.am b/include/Makefile.am index 81419f7..c20d3ca 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,5 @@ noinst_HEADERS = \ + osmocom/gapk/logging.h \ osmocom/gapk/utils.h \ osmocom/gapk/bench.h \ $(NULL) @@ -9,6 +10,7 @@ nobase_include_HEADERS = \ osmocom/gapk/procqueue.h \ osmocom/gapk/formats.h \ osmocom/gapk/codecs.h \ + osmocom/gapk/common.h \ $(NULL) if ENABLE_GSMHR diff --git a/include/osmocom/gapk/common.h b/include/osmocom/gapk/common.h new file mode 100644 index 0000000..138882c --- /dev/null +++ b/include/osmocom/gapk/common.h @@ -0,0 +1,21 @@ +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + * + */ + +#pragma once + +void osmo_gapk_log_init(int subsys); diff --git a/include/osmocom/gapk/logging.h b/include/osmocom/gapk/logging.h new file mode 100644 index 0000000..eaa82ab --- /dev/null +++ b/include/osmocom/gapk/logging.h @@ -0,0 +1,28 @@ +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * 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 . + * + */ + +#pragma once + +#include + +extern int osmo_gapk_log_init_complete; +extern int osmo_gapk_log_subsys; + +#define LOGPGAPK(level, fmt, args...) \ + if (osmo_gapk_log_init_complete) \ + LOGP(osmo_gapk_log_subsys, level, fmt, ## args) diff --git a/src/Makefile.am b/src/Makefile.am index 2c52ec1..060d435 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,6 +76,11 @@ libosmogapk_la_SOURCES += \ benchmark.c \ $(NULL) +# Logging +libosmogapk_la_SOURCES += \ + logging.c \ + $(NULL) + # libosmogapk representative application bin_PROGRAMS = osmo-gapk diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 90779af..926f3ba 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -31,8 +31,12 @@ #include #include +#include +#include #include +#include +#include #include #include #include @@ -85,6 +89,25 @@ 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_DEBUG, + }, +}; + +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) @@ -620,6 +643,11 @@ int main(int argc, char *argv[]) { int rv; + /* 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; diff --git a/src/libosmogapk.map b/src/libosmogapk.map index 0ab0669..d8b8af3 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -1,6 +1,8 @@ LIBOSMOGAPK_1.0 { global: +osmo_gapk_log_init; + osmo_gapk_pq; osmo_gapk_pq_item; diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..96313ae --- /dev/null +++ b/src/logging.c @@ -0,0 +1,27 @@ +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * (C) 2017 by Vadim Yanitskiy + * + * 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 . + */ + +int osmo_gapk_log_init_complete = 0; +int osmo_gapk_log_subsys; + +void osmo_gapk_log_init(int subsys) +{ + osmo_gapk_log_subsys = subsys; + osmo_gapk_log_init_complete = 1; +} diff --git a/src/pq_alsa.c b/src/pq_alsa.c index d280de6..b91457e 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -147,7 +148,7 @@ out_close: snd_pcm_close(state->pcm_handle); 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; } @@ -162,7 +163,8 @@ out_print: int 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: Adding ALSA input " + "(dev='%s', blk_len=%u)\n", hwdev, blk_len); return pq_queue_alsa_op(pq, hwdev, blk_len, 1); } @@ -175,7 +177,8 @@ osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsign int 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: Adding ALSA output " + "(dev='%s', blk_len=%u)\n", 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 37fa1c9..f5da628 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -71,7 +72,7 @@ osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_d item->exit = codec->codec_exit; - fprintf(stderr, "[+] PQ: Adding Codec %s, %s format %s\n", codec->name, + LOGPGAPK(LOGL_DEBUG, "PQ: Adding codec %s, %s format %s\n", codec->name, enc_dec_n ? "encoding to" : "decoding from", fmt->name); if (!item->proc) diff --git a/src/pq_file.c b/src/pq_file.c index 2d0a6b0..b31ef52 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -97,7 +98,7 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in int 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: Adding file input (blk_len=%u)\n", blk_len); return pq_queue_file_op(pq, src, blk_len, 1); } @@ -110,6 +111,6 @@ osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int b int 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: Adding file output (blk_len=%u)\n", 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 08860a3..ae5386e 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -44,7 +45,8 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f 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; } @@ -54,14 +56,14 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f 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: Adding conversion from canon " + "to %s (for codec %s)\n", 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: Adding conversion from %s " + "to canon (for codec %s)\n", fmt->name, codec->name); item->len_in = fmt->frame_len; item->len_out = codec->canon_frame_len; item->state = fmt->conv_to_canon; diff --git a/src/pq_rtp.c b/src/pq_rtp.c index b68e84a..6e7a87d 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -27,6 +27,7 @@ #include +#include #include #include #include @@ -86,7 +87,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) @@ -241,7 +243,7 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i int 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: Adding RTP input (blk_len=%u)\n", blk_len); return pq_queue_rtp_op(pq, udp_fd, blk_len, 1); } @@ -253,6 +255,6 @@ osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, unsigned int b int 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: Adding RTP output (blk_len=%u)\n", blk_len); return pq_queue_rtp_op(pq, udp_fd, blk_len, 0); } diff --git a/src/procqueue.c b/src/procqueue.c index 00472d3..ffd3f6d 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -24,6 +24,7 @@ #include #include +#include /* crate a new (empty) processing queue */ struct osmo_gapk_pq * @@ -102,7 +103,7 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) llist_for_each_entry(item, &pq->items, list) { /* Make sure I/O data lengths are equal */ if (item->len_in && item->len_in != len_prev) { - fprintf(stderr, "[!] PQ item requires input size %u, " + LOGPGAPK(LOGL_ERROR, "PQ item requires input size %u, " "but previous output is %u\n", item->len_in, len_prev); return -EINVAL; } @@ -151,8 +152,8 @@ osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) /* Call item's processing handler */ rv = item->proc(item->state, item->buf, buf_prev, len_prev); if (rv < 0) { - fprintf(stderr, "[!] osmo_gapk_pq_execute(): " - "abort, item returned %d\n", rv); + LOGPGAPK(LOGL_ERROR, "Queue execution aborted: " + "item returned %d\n", rv); return rv; } -- cgit v1.2.3 From 4b7cd2c6772a43b3057368ca452be65691826aa5 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 16:48:27 +0300 Subject: osmo-gapk: drop useless printf calls The printf() writes the text into stdout, which may be undesirable in some use cases. Moreover, the printed information was redundant. So, let's drop such calls. --- src/app_osmo_gapk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 926f3ba..c2e8dd9 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -397,7 +397,7 @@ files_open(struct gapk_state *gs) return gs->in.rtp.fd; } } else if (gs->opts.alsa_in) { - printf("alsa_in, not stdin\n"); + /* Do nothing, ALSA source does the initialization itself */ } else gs->in.file.fh = stdin; @@ -419,7 +419,7 @@ files_open(struct gapk_state *gs) return gs->out.rtp.fd; } } else if (gs->opts.alsa_out) { - printf("alsa_out, not stdout\n"); + /* Do nothing, ALSA sink does the initialization itself */ } else gs->out.file.fh = stdout; -- cgit v1.2.3 From 0fe18af82d1bb1672ccec49f7b75a4c710d48d42 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 17:10:14 +0300 Subject: osmo-gapk: use Osmocom logging framework --- src/app_osmo_gapk.c | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index c2e8dd9..c921bb2 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -234,7 +234,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; @@ -251,7 +251,7 @@ 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; @@ -260,7 +260,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) case 'f': 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; @@ -268,7 +268,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) case 'g': 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; @@ -281,7 +281,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) return 1; default: - fprintf(stderr, "[+] Unknown option\n"); + LOGP(DAPP, LOGL_ERROR, "Unknown option\n"); return -EINVAL; } @@ -295,7 +295,7 @@ 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; } @@ -306,35 +306,35 @@ check_options(struct gapk_state *gs) /* Check source codec */ 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 = 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"); + LOGP(DAPP, LOGL_ERROR, "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"); + LOGP(DAPP, LOGL_ERROR, "You have to decide on either file or RTP output\n"); return -EINVAL; } @@ -360,7 +360,7 @@ benchmark_dump(void) cycles = osmo_gapk_bench_get_cycles(i, 1); frames = osmo_gapk_bench_get_frames(i, 1); - fprintf(stderr, "Codec %u (ENC): %llu cycles for %u frames" + LOGP(DAPP, LOGL_NOTICE, "Codec %u (ENC): %llu cycles for %u frames" " => %llu cycles/frame\n", i, cycles, frames, cycles / frames); } @@ -369,7 +369,7 @@ benchmark_dump(void) cycles = osmo_gapk_bench_get_cycles(i, 0); frames = osmo_gapk_bench_get_frames(i, 0); - fprintf(stderr, "Codec %u (DEC): %llu cycles for %u frames" + LOGP(DAPP, LOGL_NOTICE, "Codec %u (DEC): %llu cycles for %u frames" " => %llu cycles/frame\n", i, cycles, frames, cycles / frames); } @@ -382,7 +382,7 @@ files_open(struct gapk_state *gs) if (gs->opts.fname_in) { 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; } @@ -393,7 +393,7 @@ files_open(struct gapk_state *gs) 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) { @@ -404,7 +404,7 @@ files_open(struct gapk_state *gs) if (gs->opts.fname_out) { 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; } @@ -415,7 +415,7 @@ files_open(struct gapk_state *gs) 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) { @@ -459,7 +459,7 @@ handle_headers(struct gapk_state *gs) 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"); return -EINVAL; } @@ -506,7 +506,7 @@ make_processing_chain(struct gapk_state *gs) 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; } @@ -520,8 +520,8 @@ make_processing_chain(struct gapk_state *gs) 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; } @@ -559,8 +559,8 @@ make_processing_chain(struct gapk_state *gs) 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; } @@ -584,7 +584,7 @@ make_processing_chain(struct gapk_state *gs) 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; } @@ -602,7 +602,7 @@ run(struct gapk_state *gs) for (frames=0; !(rv = osmo_gapk_pq_execute(gs->pq)); frames++); - fprintf(stderr, "[+] Processed %d frames\n", frames); + LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", frames); return frames > 0 ? 0 : rv; } @@ -671,28 +671,28 @@ int main(int argc, char *argv[]) gs->pq = osmo_gapk_pq_create(); 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; } -- cgit v1.2.3 From 11943bf320ca5ed3e9efd099d27c3ed3b3631832 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 17:39:24 +0300 Subject: osmo-gapk: adjust application verbosity This change allows user to enable advanced verbosity using the '-v' command line option, which is disabled by default. --- src/app_osmo_gapk.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index c921bb2..4c13570 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -99,7 +99,7 @@ static struct log_info_cat gapk_log_info_cat[] = { .name = "DAPP", .description = "Application", .color = "\033[0;36m", - .enabled = 1, .loglevel = LOGL_DEBUG, + .enabled = 1, .loglevel = LOGL_NOTICE, }, }; @@ -130,6 +130,7 @@ print_help(char *progname) 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 */ @@ -199,9 +200,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) {"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:bh" + const char *short_options = "i:o:I:O:f:g:bvh" #ifdef HAVE_ALSA "a:A:" #endif @@ -277,6 +279,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) opt->benchmark = 1; break; + case 'v': + log_parse_category_mask(osmo_stderr_target, "DAPP"); + break; + case 'h': return 1; @@ -379,7 +385,10 @@ benchmark_dump(void) 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) { LOGP(DAPP, LOGL_ERROR, "Error while opening input file for reading\n"); @@ -387,6 +396,7 @@ files_open(struct gapk_state *gs) 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, @@ -398,10 +408,14 @@ files_open(struct gapk_state *gs) } } else if (gs->opts.alsa_in) { /* Do nothing, ALSA source does the initialization itself */ - } else + 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) { LOGP(DAPP, LOGL_ERROR, "Error while opening output file for writing\n"); @@ -409,6 +423,7 @@ files_open(struct gapk_state *gs) 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, @@ -420,8 +435,11 @@ files_open(struct gapk_state *gs) } } else if (gs->opts.alsa_out) { /* Do nothing, ALSA sink does the initialization itself */ - } else + 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; } @@ -429,6 +447,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) @@ -485,6 +505,8 @@ make_processing_chain(struct gapk_state *gs) int need_dec, need_enc; + LOGP(DAPP, LOGL_NOTICE, "Creating a processing queue\n"); + fmt_in = gs->opts.fmt_in; fmt_out = gs->opts.fmt_out; @@ -699,6 +721,7 @@ int main(int argc, char *argv[]) signal(SIGINT, &signal_handler); /* Run the processing queue */ + LOGP(DAPP, LOGL_NOTICE, "Init complete, starting processing queue...\n"); rv = run(gs); error: -- cgit v1.2.3 From b40a54dc97e28e31e4a9be8a3aa634eaafb219d5 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 17:51:35 +0300 Subject: osmo-gapk: abort the processing queue on SIGINT Instead of immediately shutting down the application, it is better to try to break the processing queue first, and stop the execution immediately if second SIGINT is received. --- src/app_osmo_gapk.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 4c13570..d02ccbe 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -67,8 +67,8 @@ struct gapk_options struct gapk_state { struct gapk_options opts; - struct osmo_gapk_pq *pq; + int exit; struct { struct { @@ -622,7 +622,11 @@ run(struct gapk_state *gs) if (rv) return rv; - for (frames=0; !(rv = osmo_gapk_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); @@ -649,11 +653,14 @@ static void app_shutdown(void) static void signal_handler(int signal) { + fprintf(stderr, "signal %u received\n", signal); + switch (signal) { case SIGINT: - fprintf(stderr, "catching sigint, shutting down...\n"); - app_shutdown(); - exit(0); + if (gs->exit++) { + app_shutdown(); + exit(0); + } break; default: break; -- cgit v1.2.3 From 1f6f807bb35228f7d6f50cf61283b9ceb8f46eee Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 7 Sep 2017 18:42:49 +0300 Subject: procqueue: add processing state callback In some cases it's required to wait for some queue items to finish processing. For example, the ALSA sink writes the audio samples to the buffer in non-blocking mode, so as soon as all of them will be written, a program may finish execution, causing the playback abort. To prevent that, this change extends the library's API, allowing each queue item to have a processing state callback that returns a positive integer if processing is not finished yet, and 0 otherwise. --- include/osmocom/gapk/procqueue.h | 1 + src/pq_alsa.c | 1 + src/pq_codec.c | 1 + src/pq_file.c | 1 + src/pq_format.c | 1 + src/pq_rtp.c | 1 + 6 files changed, 6 insertions(+) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index a72fd61..9b049a5 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -40,6 +40,7 @@ struct osmo_gapk_pq_item { * \param[in] in_len length of input data \a in * \returns number of output bytes written to \a out; negative on error */ int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len); + int (*wait)(void *state); void (*exit)(void *state); /*! \brief link to a processing queue */ diff --git a/src/pq_alsa.c b/src/pq_alsa.c index b91457e..779dd96 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -138,6 +138,7 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk 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 = NULL; item->exit = pq_cb_alsa_exit; return 0; diff --git a/src/pq_codec.c b/src/pq_codec.c index f5da628..e033a7d 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -71,6 +71,7 @@ osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_d } item->exit = codec->codec_exit; + item->wait = NULL; LOGPGAPK(LOGL_DEBUG, "PQ: Adding codec %s, %s format %s\n", codec->name, enc_dec_n ? "encoding to" : "decoding from", fmt->name); diff --git a/src/pq_file.c b/src/pq_file.c index b31ef52..d05f82a 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -83,6 +83,7 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in 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; return 0; diff --git a/src/pq_format.c b/src/pq_format.c index ae5386e..8ea8b86 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -70,6 +70,7 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f } item->proc = pq_cb_fmt_convert; + item->wait = NULL; return 0; } diff --git a/src/pq_rtp.c b/src/pq_rtp.c index 6e7a87d..1c37475 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -229,6 +229,7 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i 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; return 0; -- cgit v1.2.3 From a183ced71eb78c27123d29ea3e9bbc646bcd4fdc Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 8 Sep 2017 00:02:20 +0300 Subject: src/pq_alsa.c: implement processing state callback Using the snd_pcm_avail_update() call from ALSA API it's possible to know, how much samples are still to be processed. --- src/pq_alsa.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 779dd96..b434b5b 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -70,6 +70,13 @@ 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) { @@ -138,7 +145,7 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk 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 = NULL; + item->wait = pq_cb_alsa_wait; item->exit = pq_cb_alsa_exit; return 0; -- cgit v1.2.3 From 01f5c5bebf4b1a8415a9837a42b018b3c1932d0b Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 8 Sep 2017 00:05:02 +0300 Subject: osmo-gapk: wait until sink finish processing Previously the osmo-gapk application used to exit as soon as all the frames are processed, no matter has the sink finished its internal processing (e.g. ALSA playback). --- src/app_osmo_gapk.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index d02ccbe..16a614d 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -616,6 +616,7 @@ make_processing_chain(struct gapk_state *gs) static int run(struct gapk_state *gs) { + struct osmo_gapk_pq_item *item; int rv, frames; rv = osmo_gapk_pq_prepare(gs->pq); @@ -630,6 +631,14 @@ run(struct gapk_state *gs) LOGP(DAPP, LOGL_NOTICE, "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; } -- cgit v1.2.3 From 6831ebd958d2d1a66689e8adf9fc6f1d753c1544 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 8 Sep 2017 10:55:05 +0300 Subject: configure.ac: use actual bug report address in AC_INIT --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index fdbc787..16c8bb4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,7 @@ AC_PREREQ([2.65]) AC_INIT([gapk], - m4_esyscmd([./git-version-gen .tarball-version]), [main@lists.airprobe.org]) + m4_esyscmd([./git-version-gen .tarball-version]), + [openbsc@lists.osmocom.org]) AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) LT_INIT([disable-static]) -- cgit v1.2.3 From a4d88ae13bc60e3f6269334d633495668af0c640 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 8 Sep 2017 11:13:49 +0300 Subject: osmo-gapk: fix I/O combinations check Previously both ALSA source and sink were out of attention. --- src/app_osmo_gapk.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 16a614d..720e08b 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -332,15 +332,27 @@ check_options(struct gapk_state *gs) } } - /* Input combinations */ - if (gs->opts.fname_in && gs->opts.rtp_in.port) { - LOGP(DAPP, LOGL_ERROR, "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) { - LOGP(DAPP, LOGL_ERROR, "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; } -- cgit v1.2.3 From 3c20dac38c774afe2dfb769451a1d987c21f9c65 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 12:10:08 +0300 Subject: libosmogapk: use talloc for memory management --- src/benchmark.c | 8 +++----- src/codec_amr.c | 5 ++--- src/codec_efr.c | 4 ++-- src/pq_alsa.c | 10 ++++++---- src/pq_file.c | 12 +++++++----- src/pq_rtp.c | 12 +++++++----- src/procqueue.c | 15 +++++++++------ 7 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/benchmark.c b/src/benchmark.c index e9637b1..c523f55 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -17,9 +17,8 @@ * (C) 2014 Harald Welte */ -#include +#include #include -#include #include #include @@ -32,8 +31,7 @@ int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec) struct osmo_gapk_bench_cycles *bench; /* Allocate zero-initialized memory */ - bench = (struct osmo_gapk_bench_cycles *) - calloc(1, sizeof(struct osmo_gapk_bench_cycles)); + bench = talloc_zero(NULL, struct osmo_gapk_bench_cycles); if (!bench) return -ENOMEM; @@ -84,5 +82,5 @@ void osmo_gapk_bench_free(void) int i; for (i = 0; i < _CODEC_MAX; i++) - free(osmo_gapk_bench_codec[i]); + talloc_free(osmo_gapk_bench_codec[i]); } diff --git a/src/codec_amr.c b/src/codec_amr.c index 2fa7a2f..df35b49 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -27,8 +27,7 @@ #ifdef HAVE_OPENCORE_AMRNB -#include -#include +#include #include #include @@ -44,7 +43,7 @@ codec_amr_init(void) { struct codec_amr_state *st; - st = calloc(1, sizeof(*st)); + st = talloc_zero(NULL, struct codec_amr_state); if (!st) return NULL; diff --git a/src/codec_efr.c b/src/codec_efr.c index f5b7f83..98bfdcd 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -26,7 +26,7 @@ #ifdef HAVE_OPENCORE_AMRNB -#include +#include #include #include @@ -44,7 +44,7 @@ codec_efr_init(void) { struct codec_efr_state *st; - st = calloc(1, sizeof(*st)); + st = talloc_zero(NULL, struct codec_efr_state); if (!st) return NULL; diff --git a/src/pq_alsa.c b/src/pq_alsa.c index b434b5b..8355349 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -20,8 +20,7 @@ #include #include -#include -#include +#include #include #include @@ -92,7 +91,7 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk 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; @@ -148,13 +147,16 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk 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: LOGPGAPK(LOGL_ERROR, "Couldn't init ALSA device '%s': %s\n", alsa_dev, snd_strerror(rc)); diff --git a/src/pq_file.c b/src/pq_file.c index d05f82a..f3bb9a3 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include #include @@ -57,7 +56,7 @@ 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 @@ -66,7 +65,7 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in 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; @@ -75,7 +74,7 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in item = osmo_gapk_pq_add_item(pq); if (!item) { - free(state); + talloc_free(state); return -ENOMEM; } @@ -86,6 +85,9 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in item->wait = NULL; item->exit = pq_cb_file_exit; + /* Change state's talloc context from pq to item */ + talloc_steal(item, state); + return 0; } diff --git a/src/pq_rtp.c b/src/pq_rtp.c index 1c37475..27b868c 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -20,10 +20,9 @@ #include #include -#include -#include #include #include +#include #include @@ -190,7 +189,7 @@ 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 @@ -199,7 +198,7 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i 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; @@ -221,7 +220,7 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i item = osmo_gapk_pq_add_item(pq); if (!item) { - free(state); + talloc_free(state); return -ENOMEM; } @@ -232,6 +231,9 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i item->wait = NULL; item->exit = pq_cb_rtp_exit; + /* Change state's talloc context from pq to item */ + talloc_steal(item, state); + return 0; } diff --git a/src/procqueue.c b/src/procqueue.c index ffd3f6d..dcf55bc 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -33,7 +34,9 @@ osmo_gapk_pq_create(void) struct osmo_gapk_pq *pq; /* Allocate memory for a new processing queue */ - pq = (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_pq)); + pq = talloc_zero(NULL, struct osmo_gapk_pq); + if (!pq) + return NULL; /* Init its list of items */ INIT_LLIST_HEAD(&pq->items); @@ -54,7 +57,7 @@ osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq) /* Iterate over all items in queue */ llist_for_each_entry_safe(item, item_next, &pq->items, list) { /* Free output buffer memory */ - free(item->buf); + talloc_free(item->buf); /* Call exit handler if preset */ if (item->exit) @@ -62,10 +65,10 @@ osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq) /* Delete an item from list */ llist_del(&item->list); - free(item); + talloc_free(item); } - free(pq); + talloc_free(pq); } /*! allocate + add an item to a processing queue; return new item @@ -77,7 +80,7 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) struct osmo_gapk_pq_item *item; /* Allocate memory for a new item */ - item = calloc(1, sizeof(struct osmo_gapk_pq_item)); + item = talloc_zero(pq, struct osmo_gapk_pq_item); if (!item) return NULL; @@ -120,7 +123,7 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) buf_size = VAR_BUF_SIZE; /* Allocate memory for an output buffer */ - item->buf = malloc(buf_size); + item->buf = talloc_size(item, buf_size); if (!item->buf) return -ENOMEM; } else { -- cgit v1.2.3 From 14637746d3f5a45fba4987d9892c50ca07434fd6 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 13:48:38 +0300 Subject: libosmogapk: fix memory leak in both AMR and EFR codecs The memory, allocated by codec_efr_init() / codec_amr_init(), was not cleaned after calling the codec_exit(). Found using talloc memory debugging API. --- src/codec_amr.c | 2 ++ src/codec_efr.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/codec_amr.c b/src/codec_amr.c index df35b49..a2787d7 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -61,6 +61,8 @@ codec_amr_exit(void *state) Decoder_Interface_exit(st->decoder); Encoder_Interface_exit(st->encoder); + talloc_free(st); + return; } diff --git a/src/codec_efr.c b/src/codec_efr.c index 98bfdcd..ddd3790 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -62,6 +62,8 @@ codec_efr_exit(void *state) Decoder_Interface_exit(st->decoder); Encoder_Interface_exit(st->encoder); + talloc_free(st); + return; } -- cgit v1.2.3 From 750c896b4a9e619bbc6f712f82b8d602a1750f96 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 14:09:55 +0300 Subject: libosmogapk: rename the 'logging.c' to 'common.c' There are not so much code, related to internal logging subsystem. So, there is no reason to keep a few lines in a dedicated file. In the future one may also be used for other routines. --- src/Makefile.am | 4 ++-- src/common.c | 28 ++++++++++++++++++++++++++++ src/logging.c | 27 --------------------------- 3 files changed, 30 insertions(+), 29 deletions(-) create mode 100644 src/common.c delete mode 100644 src/logging.c diff --git a/src/Makefile.am b/src/Makefile.am index 060d435..8efd165 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,9 +76,9 @@ libosmogapk_la_SOURCES += \ benchmark.c \ $(NULL) -# Logging +# Common routines libosmogapk_la_SOURCES += \ - logging.c \ + common.c \ $(NULL) # libosmogapk representative application diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..1984d29 --- /dev/null +++ b/src/common.c @@ -0,0 +1,28 @@ +/* + * This file is part of gapk (GSM Audio Pocket Knife). + * + * (C) 2017 by Vadim Yanitskiy + * + * 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 . + */ + +/* Internal GAPK logging */ +int osmo_gapk_log_init_complete = 0; +int osmo_gapk_log_subsys; + +void osmo_gapk_log_init(int subsys) +{ + osmo_gapk_log_subsys = subsys; + osmo_gapk_log_init_complete = 1; +} diff --git a/src/logging.c b/src/logging.c deleted file mode 100644 index 96313ae..0000000 --- a/src/logging.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of gapk (GSM Audio Pocket Knife). - * - * (C) 2017 by Vadim Yanitskiy - * - * 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 . - */ - -int osmo_gapk_log_init_complete = 0; -int osmo_gapk_log_subsys; - -void osmo_gapk_log_init(int subsys) -{ - osmo_gapk_log_subsys = subsys; - osmo_gapk_log_init_complete = 1; -} -- cgit v1.2.3 From f23b74736458d2415dd1dfec0559af44e6353574 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 14:23:56 +0300 Subject: libosmogapk: introduce the internal root talloc context In order to simplify memory leak debugging, this change introduces the library's internal talloc context that may be changed by external application by calling the osmo_gapk_set_talloc_ctx(). --- include/osmocom/gapk/common.h | 1 + src/benchmark.c | 5 ++++- src/codec_amr.c | 5 ++++- src/codec_efr.c | 4 +++- src/common.c | 10 ++++++++++ src/libosmogapk.map | 1 + src/procqueue.c | 5 ++++- 7 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/osmocom/gapk/common.h b/include/osmocom/gapk/common.h index 138882c..920824e 100644 --- a/include/osmocom/gapk/common.h +++ b/include/osmocom/gapk/common.h @@ -18,4 +18,5 @@ #pragma once +void osmo_gapk_set_talloc_ctx(void *ctx); void osmo_gapk_log_init(int subsys); diff --git a/src/benchmark.c b/src/benchmark.c index c523f55..b3bb60b 100644 --- a/src/benchmark.c +++ b/src/benchmark.c @@ -23,6 +23,9 @@ #include #include +/* Internal root talloc context */ +extern TALLOC_CTX *gapk_root_ctx; + struct osmo_gapk_bench_cycles * osmo_gapk_bench_codec[_CODEC_MAX] = { NULL }; @@ -31,7 +34,7 @@ int osmo_gapk_bench_enable(enum osmo_gapk_codec_type codec) struct osmo_gapk_bench_cycles *bench; /* Allocate zero-initialized memory */ - bench = talloc_zero(NULL, struct osmo_gapk_bench_cycles); + bench = talloc_zero(gapk_root_ctx, struct osmo_gapk_bench_cycles); if (!bench) return -ENOMEM; diff --git a/src/codec_amr.c b/src/codec_amr.c index a2787d7..9c96290 100644 --- a/src/codec_amr.c +++ b/src/codec_amr.c @@ -32,6 +32,9 @@ #include #include +/* 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 = talloc_zero(NULL, struct codec_amr_state); + st = talloc_zero(gapk_root_ctx, struct codec_amr_state); if (!st) return NULL; diff --git a/src/codec_efr.c b/src/codec_efr.c index ddd3790..9804bd9 100644 --- a/src/codec_efr.c +++ b/src/codec_efr.c @@ -32,6 +32,8 @@ #include #include +/* Internal root talloc context */ +extern TALLOC_CTX *gapk_root_ctx; struct codec_efr_state { void *encoder; @@ -44,7 +46,7 @@ codec_efr_init(void) { struct codec_efr_state *st; - st = talloc_zero(NULL, struct codec_efr_state); + st = talloc_zero(gapk_root_ctx, struct codec_efr_state); if (!st) return NULL; diff --git a/src/common.c b/src/common.c index 1984d29..9448362 100644 --- a/src/common.c +++ b/src/common.c @@ -17,6 +17,16 @@ * along with gapk. If not, see . */ +#include + +/* 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 osmo_gapk_log_init_complete = 0; int osmo_gapk_log_subsys; diff --git a/src/libosmogapk.map b/src/libosmogapk.map index d8b8af3..a6ce08d 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -2,6 +2,7 @@ LIBOSMOGAPK_1.0 { global: osmo_gapk_log_init; +osmo_gapk_set_talloc_ctx; osmo_gapk_pq; osmo_gapk_pq_item; diff --git a/src/procqueue.c b/src/procqueue.c index dcf55bc..3303cce 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -27,6 +27,9 @@ #include #include +/* Internal root talloc context */ +extern TALLOC_CTX *gapk_root_ctx; + /* crate a new (empty) processing queue */ struct osmo_gapk_pq * osmo_gapk_pq_create(void) @@ -34,7 +37,7 @@ osmo_gapk_pq_create(void) struct osmo_gapk_pq *pq; /* Allocate memory for a new processing queue */ - pq = talloc_zero(NULL, struct osmo_gapk_pq); + pq = talloc_zero(gapk_root_ctx, struct osmo_gapk_pq); if (!pq) return NULL; -- cgit v1.2.3 From 5cabe1eeec55421954c052951a3dba00018af7cf Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 14:44:24 +0300 Subject: osmo-gapk: use talloc for memory management --- src/app_osmo_gapk.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 720e08b..2ce0a31 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,8 @@ #include #include +/* The root talloc context of application */ +TALLOC_CTX *app_root_ctx; struct gapk_options { @@ -62,6 +65,7 @@ struct gapk_options const struct osmo_gapk_format_desc *fmt_out; int benchmark; + int verbose; }; struct gapk_state @@ -281,6 +285,7 @@ parse_options(struct gapk_state *state, int argc, char *argv[]) case 'v': log_parse_category_mask(osmo_stderr_target, "DAPP"); + opt->verbose = 1; break; case 'h': @@ -482,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; @@ -490,12 +495,12 @@ handle_headers(struct gapk_state *gs) if ((rv != 1) || memcmp(buf, gs->opts.fmt_in->header, len)) { - free(buf); LOGP(DAPP, LOGL_ERROR, "Invalid header in input file"); + talloc_free(buf); return -EINVAL; } - free(buf); + talloc_free(buf); } /* Output file header (write it) */ @@ -670,6 +675,9 @@ static void app_shutdown(void) /* 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) @@ -683,6 +691,10 @@ static void signal_handler(int signal) exit(0); } break; + case SIGABRT: + case SIGUSR1: + case SIGUSR2: + talloc_report_full(app_root_ctx, stderr); default: break; } @@ -693,6 +705,10 @@ 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 */ @@ -747,6 +763,9 @@ int main(int argc, char *argv[]) } 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"); -- cgit v1.2.3 From 262ae0f98f21e91ff21f2082892f75a778d077a5 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 14:48:49 +0300 Subject: libosmogapk: drop an 'osmo' prefix from internal log variables It would be better to have an 'osmo_gapk' prefix for exposed symbols only. Both internal logging variables aren't exposed, so they shouldn't have one. --- include/osmocom/gapk/logging.h | 8 ++++---- src/common.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/osmocom/gapk/logging.h b/include/osmocom/gapk/logging.h index eaa82ab..60376f1 100644 --- a/include/osmocom/gapk/logging.h +++ b/include/osmocom/gapk/logging.h @@ -20,9 +20,9 @@ #include -extern int osmo_gapk_log_init_complete; -extern int osmo_gapk_log_subsys; +extern int gapk_log_init_complete; +extern int gapk_log_subsys; #define LOGPGAPK(level, fmt, args...) \ - if (osmo_gapk_log_init_complete) \ - LOGP(osmo_gapk_log_subsys, level, fmt, ## args) + if (gapk_log_init_complete) \ + LOGP(gapk_log_subsys, level, fmt, ## args) diff --git a/src/common.c b/src/common.c index 9448362..c7c5c32 100644 --- a/src/common.c +++ b/src/common.c @@ -28,11 +28,11 @@ void osmo_gapk_set_talloc_ctx(void *ctx) } /* Internal GAPK logging */ -int osmo_gapk_log_init_complete = 0; -int osmo_gapk_log_subsys; +int gapk_log_init_complete = 0; +int gapk_log_subsys; void osmo_gapk_log_init(int subsys) { - osmo_gapk_log_subsys = subsys; - osmo_gapk_log_init_complete = 1; + gapk_log_subsys = subsys; + gapk_log_init_complete = 1; } -- cgit v1.2.3 From 2286a36ace915864bce935f49374f12cb9384e5d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 20:43:28 +0300 Subject: procqueue: add human-readable name to osmo_gapk_pq Since this change, every processing queue may optionally have an associated human-readable name. If name is not required, NULL should be passed to the osmo_gapk_pq_create(). --- include/osmocom/gapk/procqueue.h | 5 ++++- src/app_osmo_gapk.c | 2 +- src/procqueue.c | 9 ++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index 9b049a5..dfd0db1 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -52,10 +52,13 @@ struct osmo_gapk_pq_item { struct osmo_gapk_pq { struct llist_head items; unsigned n_items; + + /*! \brief human-readable name */ + const char *name; }; /* Processing queue management */ -struct osmo_gapk_pq *osmo_gapk_pq_create(void); +struct osmo_gapk_pq *osmo_gapk_pq_create(const char *name); int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq); int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq); void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq); diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 2ce0a31..6543eef 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -734,7 +734,7 @@ int main(int argc, char *argv[]) return rv; /* Create processing queue */ - gs->pq = osmo_gapk_pq_create(); + gs->pq = osmo_gapk_pq_create("main"); if (!gs->pq) { rv = -ENOMEM; LOGP(DAPP, LOGL_ERROR, "Error creating processing queue\n"); diff --git a/src/procqueue.c b/src/procqueue.c index 3303cce..2c7b7fc 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -32,7 +32,7 @@ extern TALLOC_CTX *gapk_root_ctx; /* crate a new (empty) processing queue */ struct osmo_gapk_pq * -osmo_gapk_pq_create(void) +osmo_gapk_pq_create(const char *name) { struct osmo_gapk_pq *pq; @@ -41,6 +41,13 @@ osmo_gapk_pq_create(void) 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); -- cgit v1.2.3 From 408be3638b3cd84462632ae8fe0b92e93064ca57 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 20:57:13 +0300 Subject: procqueue: add item type enum (source, sink, proc) There are currently three types of prcessing queue items: - source (file, alsa, rtp) - proc (format, codec) - sink (file, alsa, rtp) Let's assign corresponding type for each item. This would facilitate logging and the queue checking. --- include/osmocom/gapk/procqueue.h | 8 ++++++++ src/libosmogapk.map | 1 + src/pq_alsa.c | 3 +++ src/pq_codec.c | 1 + src/pq_file.c | 3 +++ src/pq_format.c | 1 + src/pq_rtp.c | 3 +++ 7 files changed, 20 insertions(+) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index dfd0db1..f5b8d53 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -24,6 +24,12 @@ #include +enum osmo_gapk_pq_item_type { + OSMO_GAPK_ITEM_TYPE_SOURCE, + OSMO_GAPK_ITEM_TYPE_SINK, + OSMO_GAPK_ITEM_TYPE_PROC, +}; + struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ unsigned int len_in; @@ -45,6 +51,8 @@ struct osmo_gapk_pq_item { /*! \brief link to a processing queue */ struct llist_head list; + /*! \brief type of item */ + enum osmo_gapk_pq_item_type type; }; #define VAR_BUF_SIZE 320 diff --git a/src/libosmogapk.map b/src/libosmogapk.map index a6ce08d..e704c31 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -6,6 +6,7 @@ osmo_gapk_set_talloc_ctx; osmo_gapk_pq; osmo_gapk_pq_item; +osmo_gapk_pq_item_type; osmo_gapk_pq_create; osmo_gapk_pq_prepare; diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 8355349..3025c2a 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -140,6 +140,9 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk goto out_close; } + item->type = in_out_n ? + OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; item->state = state; diff --git a/src/pq_codec.c b/src/pq_codec.c index e033a7d..db99d5c 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -70,6 +70,7 @@ osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_d item->proc = codec->codec_decode; } + item->type = OSMO_GAPK_ITEM_TYPE_PROC; item->exit = codec->codec_exit; item->wait = NULL; diff --git a/src/pq_file.c b/src/pq_file.c index f3bb9a3..73a7099 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -78,6 +78,9 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in return -ENOMEM; } + item->type = in_out_n ? + OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; item->state = state; diff --git a/src/pq_format.c b/src/pq_format.c index 8ea8b86..dad1d9e 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -69,6 +69,7 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f item->state = fmt->conv_to_canon; } + item->type = OSMO_GAPK_ITEM_TYPE_PROC; item->proc = pq_cb_fmt_convert; item->wait = NULL; diff --git a/src/pq_rtp.c b/src/pq_rtp.c index 27b868c..799b324 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -224,6 +224,9 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i return -ENOMEM; } + item->type = in_out_n ? + OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; item->state = state; -- cgit v1.2.3 From 459791c488c6b66a5cd0d7cff9392a7a0b8ca733 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Sep 2017 21:44:16 +0300 Subject: procqueue: add item catedory and sub-category fields This change adds two meta-information fields to the processing queue item structure. Both of them will be used for more detailed logging and for the human-readable processing queue description. --- include/osmocom/gapk/procqueue.h | 5 +++++ src/libosmogapk.map | 1 + src/pq_alsa.c | 2 ++ src/pq_codec.c | 4 ++++ src/pq_file.c | 2 ++ src/pq_format.c | 4 ++++ src/pq_rtp.c | 2 ++ src/procqueue.c | 17 +++++++++++++++++ 8 files changed, 37 insertions(+) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index f5b8d53..c2f2675 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -53,6 +53,10 @@ struct osmo_gapk_pq_item { struct llist_head list; /*! \brief type of item */ enum osmo_gapk_pq_item_type type; + /*! \brief category name (src, format, codec, sink) */ + const char *cat_name; + /*! \brief sub-category name (file, rtp-amr, amr, alsa) */ + const char *sub_name; }; #define VAR_BUF_SIZE 320 @@ -70,6 +74,7 @@ struct osmo_gapk_pq *osmo_gapk_pq_create(const char *name); int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq); int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq); void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq); +char *osmo_gapk_pq_describe(struct osmo_gapk_pq *pq); /* Processing queue item management */ struct osmo_gapk_pq_item *osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq); diff --git a/src/libosmogapk.map b/src/libosmogapk.map index e704c31..5fd7a7a 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -12,6 +12,7 @@ osmo_gapk_pq_create; osmo_gapk_pq_prepare; osmo_gapk_pq_execute; osmo_gapk_pq_destroy; +osmo_gapk_pq_describe; osmo_gapk_pq_add_item; diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 3025c2a..5cdd9ce 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -142,6 +142,8 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->cat_name = in_out_n ? "source" : "sink"; + item->sub_name = "alsa"; item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; diff --git a/src/pq_codec.c b/src/pq_codec.c index db99d5c..b5dac5d 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -74,6 +74,10 @@ osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_d item->exit = codec->codec_exit; item->wait = NULL; + /* Meta information */ + item->cat_name = "codec"; + item->sub_name = codec->name; + LOGPGAPK(LOGL_DEBUG, "PQ: Adding codec %s, %s format %s\n", codec->name, enc_dec_n ? "encoding to" : "decoding from", fmt->name); diff --git a/src/pq_file.c b/src/pq_file.c index 73a7099..8a8f9c6 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -80,6 +80,8 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->cat_name = in_out_n ? "source" : "sink"; + item->sub_name = "file"; item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; diff --git a/src/pq_format.c b/src/pq_format.c index dad1d9e..c2bb52e 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -73,5 +73,9 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f 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 799b324..faab6c8 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -226,6 +226,8 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; + item->cat_name = in_out_n ? "source" : "sink"; + item->sub_name = "rtp"; item->len_in = in_out_n ? 0 : blk_len; item->len_out = in_out_n ? blk_len : 0; diff --git a/src/procqueue.c b/src/procqueue.c index 2c7b7fc..4de7a6a 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -176,3 +176,20 @@ osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) return 0; } + +char * +osmo_gapk_pq_describe(struct osmo_gapk_pq *pq) +{ + struct osmo_gapk_pq_item *item; + char *result = NULL; + int i = 0; + + /* 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 ? " -> " : ""); + } + + return result; +} -- cgit v1.2.3 From 3839a88ea681024752048c902b23144c42f4fa42 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 10 Sep 2017 16:00:43 +0300 Subject: procqueue: separate queue check function In order to give advanced control over a processing queue, it would be better to have the checking function separated from the osmo_gapk_pq_prepare(). Moreover, this change introduces an additional 'strict' checking mode that requires a queue to have a source item first and a sink item in the last position. --- include/osmocom/gapk/procqueue.h | 1 + src/app_osmo_gapk.c | 6 ++++ src/libosmogapk.map | 1 + src/procqueue.c | 66 ++++++++++++++++++++++++++++++---------- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index c2f2675..e73f73e 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -71,6 +71,7 @@ struct osmo_gapk_pq { /* Processing queue management */ struct osmo_gapk_pq *osmo_gapk_pq_create(const char *name); +int osmo_gapk_pq_check(struct osmo_gapk_pq *pq, int strict); int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq); int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq); void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq); diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 6543eef..2aac0aa 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -521,6 +521,7 @@ make_processing_chain(struct gapk_state *gs) 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"); @@ -627,6 +628,11 @@ make_processing_chain(struct gapk_state *gs) return -1; } + /* Check the processing queue in strict mode */ + rc = osmo_gapk_pq_check(gs->pq, 1); + if (rc) + return rc; + return 0; } diff --git a/src/libosmogapk.map b/src/libosmogapk.map index 5fd7a7a..4494cdb 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -14,6 +14,7 @@ osmo_gapk_pq_execute; osmo_gapk_pq_destroy; osmo_gapk_pq_describe; +osmo_gapk_pq_check; osmo_gapk_pq_add_item; osmo_gapk_pq_queue_file_input; diff --git a/src/procqueue.c b/src/procqueue.c index 4de7a6a..b95b3ec 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -103,24 +103,65 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) return item; } -/*! prepare a processing queue; allocates buffers; checks lengths +/*! 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 +osmo_gapk_pq_check(struct osmo_gapk_pq *pq, int strict) +{ + 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; + } + } + + /* Save pointer to the previous item */ + item_prev = item; + } + + 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; + } + + 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; +} + +/*! 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; - unsigned int len_prev = 0; /* Iterate over all items in queue */ llist_for_each_entry(item, &pq->items, list) { - /* Make sure I/O data lengths are equal */ - if (item->len_in && item->len_in != len_prev) { - LOGPGAPK(LOGL_ERROR, "PQ item requires input size %u, " - "but previous output is %u\n", item->len_in, len_prev); - return -EINVAL; - } - /* The sink item doesn't require an output buffer */ if (item->list.next != &pq->items) { unsigned int buf_size = item->len_out; @@ -136,14 +177,7 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) item->buf = talloc_size(item, buf_size); if (!item->buf) return -ENOMEM; - } else { - /* Make sure the last item is a sink */ - if (item->len_out) - return -EINVAL; } - - /* Store output length for further comparation */ - len_prev = item->len_out; } return 0; -- cgit v1.2.3 From 9e7e88927851fd6b2fa42d0a187bd7e65ccaccf1 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 10 Sep 2017 16:27:04 +0300 Subject: procqueue: use queue / item names in logging --- src/pq_alsa.c | 8 ++++---- src/pq_codec.c | 5 +++-- src/pq_file.c | 6 ++++-- src/pq_format.c | 8 ++++---- src/pq_rtp.c | 6 ++++-- src/procqueue.c | 5 +++-- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 5cdd9ce..84d2e20 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -178,8 +178,8 @@ out_print: int osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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); } @@ -192,8 +192,8 @@ osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsign int osmo_gapk_pq_queue_alsa_output(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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 b5dac5d..87afd82 100644 --- a/src/pq_codec.c +++ b/src/pq_codec.c @@ -78,8 +78,9 @@ osmo_gapk_pq_queue_codec(struct osmo_gapk_pq *pq, const struct osmo_gapk_codec_d item->cat_name = "codec"; item->sub_name = codec->name; - LOGPGAPK(LOGL_DEBUG, "PQ: Adding codec %s, %s format %s\n", codec->name, - enc_dec_n ? "encoding to" : "decoding from", fmt->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 8a8f9c6..8ad26d5 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -106,7 +106,8 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in int osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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); } @@ -119,6 +120,7 @@ osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int b int osmo_gapk_pq_queue_file_output(struct osmo_gapk_pq *pq, FILE *dst, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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 c2bb52e..2c4a2fd 100644 --- a/src/pq_format.c +++ b/src/pq_format.c @@ -56,14 +56,14 @@ osmo_gapk_pq_queue_fmt_convert(struct osmo_gapk_pq *pq, const struct osmo_gapk_f return -ENOMEM; if (to_from_n) { - LOGPGAPK(LOGL_DEBUG, "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 { - LOGPGAPK(LOGL_DEBUG, "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; diff --git a/src/pq_rtp.c b/src/pq_rtp.c index faab6c8..c1d9ffb 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -251,7 +251,8 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i int osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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); } @@ -263,6 +264,7 @@ osmo_gapk_pq_queue_rtp_input(struct osmo_gapk_pq *pq, int udp_fd, unsigned int b int osmo_gapk_pq_queue_rtp_output(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len) { - LOGPGAPK(LOGL_DEBUG, "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 b95b3ec..c6661b5 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -199,8 +199,9 @@ osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) /* Call item's processing handler */ rv = item->proc(item->state, item->buf, buf_prev, len_prev); if (rv < 0) { - LOGPGAPK(LOGL_ERROR, "Queue execution aborted: " - "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; } -- cgit v1.2.3 From 7279d9f05777855a0dc2873038bdb13557d174a3 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 10 Sep 2017 16:32:48 +0300 Subject: src/libosmogapk.map: export osmo_gapk_* with a wilcard --- src/libosmogapk.map | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/src/libosmogapk.map b/src/libosmogapk.map index 4494cdb..6cd817e 100644 --- a/src/libosmogapk.map +++ b/src/libosmogapk.map @@ -1,50 +1,4 @@ LIBOSMOGAPK_1.0 { -global: - -osmo_gapk_log_init; -osmo_gapk_set_talloc_ctx; - -osmo_gapk_pq; -osmo_gapk_pq_item; -osmo_gapk_pq_item_type; - -osmo_gapk_pq_create; -osmo_gapk_pq_prepare; -osmo_gapk_pq_execute; -osmo_gapk_pq_destroy; -osmo_gapk_pq_describe; - -osmo_gapk_pq_check; -osmo_gapk_pq_add_item; - -osmo_gapk_pq_queue_file_input; -osmo_gapk_pq_queue_file_output; -osmo_gapk_pq_queue_rtp_input; -osmo_gapk_pq_queue_rtp_output; -osmo_gapk_pq_queue_alsa_input; -osmo_gapk_pq_queue_alsa_output; -osmo_gapk_pq_queue_fmt_convert; -osmo_gapk_pq_queue_codec; - -osmo_gapk_format_desc; -osmo_gapk_format_type; -osmo_gapk_fmt_conv_cb_t; - -osmo_gapk_fmt_get_from_type; -osmo_gapk_fmt_get_from_name; - -osmo_gapk_codec_desc; -osmo_gapk_codec_type; -osmo_gapk_codec_conv_cb_t; - -osmo_gapk_codec_get_from_type; - -osmo_gapk_bench_codec; -osmo_gapk_bench_enable; -osmo_gapk_bench_free; - -osmo_gapk_bench_get_cycles; -osmo_gapk_bench_get_frames; - +global: osmo_gapk_*; local: *; }; -- cgit v1.2.3 From fb2326fbcf12abc47e3f24f6c2051e71d013705e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 12 Sep 2017 01:17:26 +0300 Subject: procqueue: set talloc name and context for queue description Previously a queue description string was allocated without setting proper parental talloc context and proper name. --- src/procqueue.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/procqueue.c b/src/procqueue.c index c6661b5..5a75296 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -219,6 +219,10 @@ osmo_gapk_pq_describe(struct osmo_gapk_pq *pq) 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", @@ -226,5 +230,11 @@ osmo_gapk_pq_describe(struct osmo_gapk_pq *pq) ++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; } -- cgit v1.2.3 From f496a998e520c3ab99d09cf279e64b0b9e52318e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 12 Sep 2017 01:30:48 +0300 Subject: procqueue: allocate an output buffer as named chunk The talloc_size() call sets the current file name and the current line number as name for chunk being allocated. This combination is not so informative during debugging, so let's use the static '.buffer' string as context name for item's output buffer. --- src/procqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/procqueue.c b/src/procqueue.c index 5a75296..78dee4d 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -174,7 +174,7 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) buf_size = VAR_BUF_SIZE; /* Allocate memory for an output buffer */ - item->buf = talloc_size(item, buf_size); + item->buf = talloc_named_const(item, buf_size, ".buffer"); if (!item->buf) return -ENOMEM; } -- cgit v1.2.3 From f069eb37fe48df4e6897d0614e008b676e06db8e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 12 Sep 2017 15:26:31 +0300 Subject: Init automake test environment --- .gitignore | 9 +++ Makefile.am | 2 +- configure.ac | 2 + test/common.sh | 13 ----- test/play_all_formats.sh | 14 ----- test/ref-files/hhgttg_part1_5.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.amr-efr | Bin 8006 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.amr-efr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.gsm | Bin 8250 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.gsm.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-efr | Bin 7750 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-efr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-fr | Bin 8250 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-fr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-hr | Bin 3500 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.racal-hr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-efr | Bin 7750 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi | Bin 3500 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf | Bin 3750 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-efr | Bin 8250 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-efr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-fr | Bin 8250 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-fr.s16 | Bin 80000 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-hr | Bin 8250 -> 0 bytes test/ref-files/hhgttg_part1_5.s16.ti-hr.s16 | Bin 80000 -> 0 bytes test/test_all_formats.sh | 62 --------------------- test/update_ref_files.sh | 22 -------- tests/Makefile.am | 58 +++++++++++++++++++ tests/common.sh | 13 +++++ tests/play_all_formats.sh | 14 +++++ tests/ref-files/hhgttg_part1_5.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.amr-efr | Bin 0 -> 8006 bytes tests/ref-files/hhgttg_part1_5.s16.amr-efr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.gsm | Bin 0 -> 8250 bytes tests/ref-files/hhgttg_part1_5.s16.gsm.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.racal-efr | Bin 0 -> 7750 bytes tests/ref-files/hhgttg_part1_5.s16.racal-efr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.racal-fr | Bin 0 -> 8250 bytes tests/ref-files/hhgttg_part1_5.s16.racal-fr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.racal-hr | Bin 0 -> 3500 bytes tests/ref-files/hhgttg_part1_5.s16.racal-hr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-efr | Bin 0 -> 7750 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi | Bin 0 -> 3500 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf | Bin 0 -> 3750 bytes tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.ti-efr | Bin 0 -> 8250 bytes tests/ref-files/hhgttg_part1_5.s16.ti-efr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.ti-fr | Bin 0 -> 8250 bytes tests/ref-files/hhgttg_part1_5.s16.ti-fr.s16 | Bin 0 -> 80000 bytes tests/ref-files/hhgttg_part1_5.s16.ti-hr | Bin 0 -> 8250 bytes tests/ref-files/hhgttg_part1_5.s16.ti-hr.s16 | Bin 0 -> 80000 bytes tests/test_all_formats.sh | 62 +++++++++++++++++++++ tests/testsuite.at | 2 + tests/update_ref_files.sh | 22 ++++++++ 59 files changed, 183 insertions(+), 112 deletions(-) delete mode 100644 test/common.sh delete mode 100755 test/play_all_formats.sh delete mode 100644 test/ref-files/hhgttg_part1_5.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.amr-efr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.amr-efr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.gsm delete mode 100644 test/ref-files/hhgttg_part1_5.s16.gsm.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-efr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-efr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-fr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-fr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-hr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.racal-hr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-efr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf delete mode 100644 test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-efr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-efr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-fr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-fr.s16 delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-hr delete mode 100644 test/ref-files/hhgttg_part1_5.s16.ti-hr.s16 delete mode 100755 test/test_all_formats.sh delete mode 100755 test/update_ref_files.sh create mode 100644 tests/Makefile.am create mode 100644 tests/common.sh create mode 100755 tests/play_all_formats.sh create mode 100644 tests/ref-files/hhgttg_part1_5.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.amr-efr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.amr-efr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.gsm create mode 100644 tests/ref-files/hhgttg_part1_5.s16.gsm.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-efr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-efr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-fr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-fr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-hr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.racal-hr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-efr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf create mode 100644 tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-efr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-efr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-fr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-fr.s16 create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-hr create mode 100644 tests/ref-files/hhgttg_part1_5.s16.ti-hr.s16 create mode 100755 tests/test_all_formats.sh create mode 100644 tests/testsuite.at create mode 100755 tests/update_ref_files.sh diff --git a/.gitignore b/.gitignore index 456b782..298604e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,15 @@ stamp-h1 libgsmhr/refsrc +# GNU autotest +tests/package.m4 +tests/atconfig +tests/atlocal +tests/testsuite +tests/testsuite.dir/ +tests/testsuite.log +tests/*/*_test + # final executables src/osmo-gapk diff --git a/Makefile.am b/Makefile.am index 4242427..0093f0e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,4 +12,4 @@ if ENABLE_GSMHR SUBDIRS += libgsmhr endif -SUBDIRS += src +SUBDIRS += src tests diff --git a/configure.ac b/configure.ac index 16c8bb4..180e380 100644 --- a/configure.ac +++ b/configure.ac @@ -12,6 +12,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CONFIG_SRCDIR([src/app_osmo_gapk.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_TESTDIR(tests) AC_CONFIG_FILES([ Makefile src/Makefile @@ -19,6 +20,7 @@ AC_CONFIG_FILES([ include/Makefile include/gsmhr/Makefile libosmogapk.pc + tests/Makefile ]) # Options diff --git a/test/common.sh b/test/common.sh deleted file mode 100644 index 5fded94..0000000 --- a/test/common.sh +++ /dev/null @@ -1,13 +0,0 @@ -# directory containing the reference files for comparing against -REFDIR=./ref-files - -if [ -f ../src/osmo-gapk ]; then - GAPK=../src/osmo-gapk -elif [ -f `which osmo-gapk` ]; then - GAPK=`which osmo-gapk` -else - exit 1 -fi -echo Using osmo-gapk found at $GAPK - -FORMATS="amr-efr gsm racal-hr racal-fr racal-efr ti-hr ti-fr ti-efr rtp-efr rtp-hr-etsi rtp-hr-ietf" diff --git a/test/play_all_formats.sh b/test/play_all_formats.sh deleted file mode 100755 index 5cebffb..0000000 --- a/test/play_all_formats.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -OUTDIR=/tmp -INFILE=$1 - -. ./common.sh - -for f in $FORMATS; do - BASE=`basename $INFILE` - PLAYFILE=$OUTDIR/$BASE.$f - echo - echo Format $f: Playing back $PLAYFILE - echo $GAPK -f $f -i $PLAYFILE -g rawpcm-s16le -A default - $GAPK -f $f -i $PLAYFILE -g rawpcm-s16le -A default -done diff --git a/test/ref-files/hhgttg_part1_5.s16 b/test/ref-files/hhgttg_part1_5.s16 deleted file mode 100644 index 80a594d..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.amr-efr b/test/ref-files/hhgttg_part1_5.s16.amr-efr deleted file mode 100644 index 00a11b0..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.amr-efr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.amr-efr.s16 b/test/ref-files/hhgttg_part1_5.s16.amr-efr.s16 deleted file mode 100644 index 829ed67..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.amr-efr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.gsm b/test/ref-files/hhgttg_part1_5.s16.gsm deleted file mode 100644 index ad3cf8f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.gsm and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.gsm.s16 b/test/ref-files/hhgttg_part1_5.s16.gsm.s16 deleted file mode 100644 index 28aa317..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.gsm.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-efr b/test/ref-files/hhgttg_part1_5.s16.racal-efr deleted file mode 100644 index b96be2e..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-efr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-efr.s16 b/test/ref-files/hhgttg_part1_5.s16.racal-efr.s16 deleted file mode 100644 index 829ed67..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-efr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-fr b/test/ref-files/hhgttg_part1_5.s16.racal-fr deleted file mode 100644 index e0a5397..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-fr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-fr.s16 b/test/ref-files/hhgttg_part1_5.s16.racal-fr.s16 deleted file mode 100644 index 28aa317..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-fr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-hr b/test/ref-files/hhgttg_part1_5.s16.racal-hr deleted file mode 100644 index 95881af..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-hr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.racal-hr.s16 b/test/ref-files/hhgttg_part1_5.s16.racal-hr.s16 deleted file mode 100644 index 27dfd5f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.racal-hr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-efr b/test/ref-files/hhgttg_part1_5.s16.rtp-efr deleted file mode 100644 index 9e4615e..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-efr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 b/test/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 deleted file mode 100644 index 829ed67..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi b/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi deleted file mode 100644 index 9a145d3..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 b/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 deleted file mode 100644 index 27dfd5f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf b/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf deleted file mode 100644 index e956e9d..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 b/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 deleted file mode 100644 index 27dfd5f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-efr b/test/ref-files/hhgttg_part1_5.s16.ti-efr deleted file mode 100644 index 9dd01ae..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-efr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-efr.s16 b/test/ref-files/hhgttg_part1_5.s16.ti-efr.s16 deleted file mode 100644 index e8f759f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-efr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-fr b/test/ref-files/hhgttg_part1_5.s16.ti-fr deleted file mode 100644 index 5bf4b83..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-fr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-fr.s16 b/test/ref-files/hhgttg_part1_5.s16.ti-fr.s16 deleted file mode 100644 index 28aa317..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-fr.s16 and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-hr b/test/ref-files/hhgttg_part1_5.s16.ti-hr deleted file mode 100644 index 29a16bf..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-hr and /dev/null differ diff --git a/test/ref-files/hhgttg_part1_5.s16.ti-hr.s16 b/test/ref-files/hhgttg_part1_5.s16.ti-hr.s16 deleted file mode 100644 index 27dfd5f..0000000 Binary files a/test/ref-files/hhgttg_part1_5.s16.ti-hr.s16 and /dev/null differ diff --git a/test/test_all_formats.sh b/test/test_all_formats.sh deleted file mode 100755 index 6da27af..0000000 --- a/test/test_all_formats.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh - - -# This script generates test data for all formats by doing the -# following: -# * encode the user-specified PCM file into each format -# * re-decode that format back to PCM -# -# Use this to generate test files that are to be shipped together with -# gapk. Always use the - - -# directory in which the temporary output is stored -OUTDIR=/tmp - -# name of the input s16le file to use for encoding and re-decoding -INFILE=$1 - -# source some common parameters -. ./common.sh - -RETVAL=0 - -for f in $FORMATS; do - BASE=`basename $INFILE` - OUTFILE=$OUTDIR/$BASE.$f - echo Format $f: Encoding $INFILE to $OUTFILE - $GAPK -f rawpcm-s16le -i $INFILE -g $f -o $OUTFILE - - # compare with reference - diff $OUTFILE $REFDIR/`basename $OUTFILE` - if [ $? -ne 0 ]; then - echo "===> FAIL" - RETVAL=1 - else - echo "===> PASS" - fi - echo - - DECFILE=$OUTFILE.s16 - echo Format $f: Decoding $OUTFILE to $DECFILE - $GAPK -f $f -i $OUTFILE -g rawpcm-s16le -o $DECFILE - - # compare with reference - diff $DECFILE $REFDIR/`basename $DECFILE` - if [ $? -ne 0 ]; then - echo "===> FAIL" - RETVAL=1 - else - echo "===> PASS" - fi - echo -done - -echo -n "Overall Verdict: " -if [ $RETVAL -ne 0 ]; then - echo "FAIL" -else - echo "PASS" -fi - -exit $RETVAL diff --git a/test/update_ref_files.sh b/test/update_ref_files.sh deleted file mode 100755 index 1d095ef..0000000 --- a/test/update_ref_files.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# This script re-generates the reference data shipped together with -# gapk. To be used by gapk maintainers only. - -. ./common.sh - -INFILE=$1 -OUTDIR=$REFDIR - - -for f in $FORMATS; do - BASE=`basename $INFILE` - OUTFILE=$OUTDIR/$BASE.$f - echo - echo Format $f: Encoding $INFILE to $OUTFILE - $GAPK -f rawpcm-s16le -i $INFILE -g $f -o $OUTFILE - - DECFILE=$OUTFILE.s16 - echo Format $f: Decoding $OUTFILE to $DECFILE - $GAPK -f $f -i $OUTFILE -g rawpcm-s16le -o $DECFILE -done diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..940e350 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,58 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCODEC_CFLAGS) \ + $(NULL) + +check_PROGRAMS = \ + $(NULL) + +# The `:;' works around a Bash 3.2 bug when the output is not writeable. +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + :;{ \ + echo '# Signature of the current package.' && \ + echo 'm4_define([AT_PACKAGE_NAME],' && \ + echo ' [$(PACKAGE_NAME)])' && \ + echo 'm4_define([AT_PACKAGE_TARNAME],' && \ + echo ' [$(PACKAGE_TARNAME)])' && \ + echo 'm4_define([AT_PACKAGE_VERSION],' && \ + echo ' [$(PACKAGE_VERSION)])' && \ + echo 'm4_define([AT_PACKAGE_STRING],' && \ + echo ' [$(PACKAGE_STRING)])' && \ + echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \ + echo ' [$(PACKAGE_BUGREPORT)])'; \ + echo 'm4_define([AT_PACKAGE_URL],' && \ + echo ' [$(PACKAGE_URL)])'; \ + } >'$(srcdir)/package.m4' + +EXTRA_DIST = \ + testsuite.at \ + $(TESTSUITE) \ + $(srcdir)/package.m4 \ + $(NULL) + +DISTCLEANFILES = atconfig +TESTSUITE = $(srcdir)/testsuite + +check-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) + +installcheck-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ + $(TESTSUITEFLAGS) + +clean-local: + test ! -f '$(TESTSUITE)' || \ + $(SHELL) '$(TESTSUITE)' --clean + +AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te +AUTOTEST = $(AUTOM4TE) --language=autotest +$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 + $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at + mv $@.tmp $@ diff --git a/tests/common.sh b/tests/common.sh new file mode 100644 index 0000000..5fded94 --- /dev/null +++ b/tests/common.sh @@ -0,0 +1,13 @@ +# directory containing the reference files for comparing against +REFDIR=./ref-files + +if [ -f ../src/osmo-gapk ]; then + GAPK=../src/osmo-gapk +elif [ -f `which osmo-gapk` ]; then + GAPK=`which osmo-gapk` +else + exit 1 +fi +echo Using osmo-gapk found at $GAPK + +FORMATS="amr-efr gsm racal-hr racal-fr racal-efr ti-hr ti-fr ti-efr rtp-efr rtp-hr-etsi rtp-hr-ietf" diff --git a/tests/play_all_formats.sh b/tests/play_all_formats.sh new file mode 100755 index 0000000..5cebffb --- /dev/null +++ b/tests/play_all_formats.sh @@ -0,0 +1,14 @@ +#!/bin/sh +OUTDIR=/tmp +INFILE=$1 + +. ./common.sh + +for f in $FORMATS; do + BASE=`basename $INFILE` + PLAYFILE=$OUTDIR/$BASE.$f + echo + echo Format $f: Playing back $PLAYFILE + echo $GAPK -f $f -i $PLAYFILE -g rawpcm-s16le -A default + $GAPK -f $f -i $PLAYFILE -g rawpcm-s16le -A default +done diff --git a/tests/ref-files/hhgttg_part1_5.s16 b/tests/ref-files/hhgttg_part1_5.s16 new file mode 100644 index 0000000..80a594d Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.amr-efr b/tests/ref-files/hhgttg_part1_5.s16.amr-efr new file mode 100644 index 0000000..00a11b0 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.amr-efr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.amr-efr.s16 b/tests/ref-files/hhgttg_part1_5.s16.amr-efr.s16 new file mode 100644 index 0000000..829ed67 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.amr-efr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.gsm b/tests/ref-files/hhgttg_part1_5.s16.gsm new file mode 100644 index 0000000..ad3cf8f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.gsm differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.gsm.s16 b/tests/ref-files/hhgttg_part1_5.s16.gsm.s16 new file mode 100644 index 0000000..28aa317 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.gsm.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-efr b/tests/ref-files/hhgttg_part1_5.s16.racal-efr new file mode 100644 index 0000000..b96be2e Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-efr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-efr.s16 b/tests/ref-files/hhgttg_part1_5.s16.racal-efr.s16 new file mode 100644 index 0000000..829ed67 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-efr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-fr b/tests/ref-files/hhgttg_part1_5.s16.racal-fr new file mode 100644 index 0000000..e0a5397 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-fr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-fr.s16 b/tests/ref-files/hhgttg_part1_5.s16.racal-fr.s16 new file mode 100644 index 0000000..28aa317 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-fr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-hr b/tests/ref-files/hhgttg_part1_5.s16.racal-hr new file mode 100644 index 0000000..95881af Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-hr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.racal-hr.s16 b/tests/ref-files/hhgttg_part1_5.s16.racal-hr.s16 new file mode 100644 index 0000000..27dfd5f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.racal-hr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-efr b/tests/ref-files/hhgttg_part1_5.s16.rtp-efr new file mode 100644 index 0000000..9e4615e Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-efr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 b/tests/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 new file mode 100644 index 0000000..829ed67 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi new file mode 100644 index 0000000..9a145d3 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 new file mode 100644 index 0000000..27dfd5f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf new file mode 100644 index 0000000..e956e9d Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 new file mode 100644 index 0000000..27dfd5f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-efr b/tests/ref-files/hhgttg_part1_5.s16.ti-efr new file mode 100644 index 0000000..9dd01ae Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-efr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-efr.s16 b/tests/ref-files/hhgttg_part1_5.s16.ti-efr.s16 new file mode 100644 index 0000000..e8f759f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-efr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-fr b/tests/ref-files/hhgttg_part1_5.s16.ti-fr new file mode 100644 index 0000000..5bf4b83 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-fr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-fr.s16 b/tests/ref-files/hhgttg_part1_5.s16.ti-fr.s16 new file mode 100644 index 0000000..28aa317 Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-fr.s16 differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-hr b/tests/ref-files/hhgttg_part1_5.s16.ti-hr new file mode 100644 index 0000000..29a16bf Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-hr differ diff --git a/tests/ref-files/hhgttg_part1_5.s16.ti-hr.s16 b/tests/ref-files/hhgttg_part1_5.s16.ti-hr.s16 new file mode 100644 index 0000000..27dfd5f Binary files /dev/null and b/tests/ref-files/hhgttg_part1_5.s16.ti-hr.s16 differ diff --git a/tests/test_all_formats.sh b/tests/test_all_formats.sh new file mode 100755 index 0000000..6da27af --- /dev/null +++ b/tests/test_all_formats.sh @@ -0,0 +1,62 @@ +#!/bin/sh + + +# This script generates test data for all formats by doing the +# following: +# * encode the user-specified PCM file into each format +# * re-decode that format back to PCM +# +# Use this to generate test files that are to be shipped together with +# gapk. Always use the + + +# directory in which the temporary output is stored +OUTDIR=/tmp + +# name of the input s16le file to use for encoding and re-decoding +INFILE=$1 + +# source some common parameters +. ./common.sh + +RETVAL=0 + +for f in $FORMATS; do + BASE=`basename $INFILE` + OUTFILE=$OUTDIR/$BASE.$f + echo Format $f: Encoding $INFILE to $OUTFILE + $GAPK -f rawpcm-s16le -i $INFILE -g $f -o $OUTFILE + + # compare with reference + diff $OUTFILE $REFDIR/`basename $OUTFILE` + if [ $? -ne 0 ]; then + echo "===> FAIL" + RETVAL=1 + else + echo "===> PASS" + fi + echo + + DECFILE=$OUTFILE.s16 + echo Format $f: Decoding $OUTFILE to $DECFILE + $GAPK -f $f -i $OUTFILE -g rawpcm-s16le -o $DECFILE + + # compare with reference + diff $DECFILE $REFDIR/`basename $DECFILE` + if [ $? -ne 0 ]; then + echo "===> FAIL" + RETVAL=1 + else + echo "===> PASS" + fi + echo +done + +echo -n "Overall Verdict: " +if [ $RETVAL -ne 0 ]; then + echo "FAIL" +else + echo "PASS" +fi + +exit $RETVAL diff --git a/tests/testsuite.at b/tests/testsuite.at new file mode 100644 index 0000000..09a77c3 --- /dev/null +++ b/tests/testsuite.at @@ -0,0 +1,2 @@ +AT_INIT +AT_BANNER([Regression tests.]) diff --git a/tests/update_ref_files.sh b/tests/update_ref_files.sh new file mode 100755 index 0000000..1d095ef --- /dev/null +++ b/tests/update_ref_files.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# This script re-generates the reference data shipped together with +# gapk. To be used by gapk maintainers only. + +. ./common.sh + +INFILE=$1 +OUTDIR=$REFDIR + + +for f in $FORMATS; do + BASE=`basename $INFILE` + OUTFILE=$OUTDIR/$BASE.$f + echo + echo Format $f: Encoding $INFILE to $OUTFILE + $GAPK -f rawpcm-s16le -i $INFILE -g $f -o $OUTFILE + + DECFILE=$OUTFILE.s16 + echo Format $f: Decoding $OUTFILE to $DECFILE + $GAPK -f $f -i $OUTFILE -g rawpcm-s16le -o $DECFILE +done -- cgit v1.2.3 From 1fe6a9b9ed92da4845f8c8cef10372a3e711a8ca Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 12 Sep 2017 15:32:52 +0300 Subject: tests: add procqueue test This test is intended to validate the processing queue management API. Moreover, the talloc debugging API is used to ensure that there are no memory leaks. First, four processing queues are being allocated. One of them is empty, while others have different count of items. Then the human-readable description is being generated for all of them. And finally, the processing and exit cllback are being tested. During the test execution, the talloc NULL-context tracking feature is enabled, allowing to observe every memory allocation within the libosmogapk, and to detect memory leaks. --- tests/Makefile.am | 13 ++ tests/procqueue/pq_test.c | 371 +++++++++++++++++++++++++++++++++++++++++++++ tests/procqueue/pq_test.ok | 60 ++++++++ tests/testsuite.at | 6 + 4 files changed, 450 insertions(+) create mode 100644 tests/procqueue/pq_test.c create mode 100644 tests/procqueue/pq_test.ok diff --git a/tests/Makefile.am b/tests/Makefile.am index 940e350..2d21abb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,6 +11,15 @@ AM_CFLAGS = \ $(NULL) check_PROGRAMS = \ + procqueue/pq_test \ + $(NULL) + +procqueue_pq_test_SOURCES = procqueue/pq_test.c +procqueue_pq_test_LDADD = \ + $(top_builddir)/src/libosmogapk.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCODEC_LIBS) \ + $(TALLOC_LIBS) \ $(NULL) # The `:;' works around a Bash 3.2 bug when the output is not writeable. @@ -37,6 +46,10 @@ EXTRA_DIST = \ $(srcdir)/package.m4 \ $(NULL) +EXTRA_DIST += \ + procqueue/pq_test.ok \ + $(NULL) + DISTCLEANFILES = atconfig TESTSUITE = $(srcdir)/testsuite diff --git a/tests/procqueue/pq_test.c b/tests/procqueue/pq_test.c new file mode 100644 index 0000000..d0d6670 --- /dev/null +++ b/tests/procqueue/pq_test.c @@ -0,0 +1,371 @@ +/* + * This file is part of GAPK (GSM Audio Pocket Knife). + * + * (C) 2017 by Vadim Yanitskiy + * + * 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 . + */ + +#include +#include +#include + +#include +#include + +/** + * This test is intended to validate the processing queue + * management API. Moreover, the talloc debugging API is + * used to ensure that there are no memory leaks. + * + * First, four processing queues are being allocated. One + * of them is empty, while others have different count of + * items. Then the human-readable description is being + * generated for all of them. And finally, the processing + * and exit callback are being tested. + * + * During the test execution, the talloc NULL-context + * tracking feature is enabled, allowing to observe every + * memory allocation within the libosmogapk, and to detect + * memory leaks. + */ + +static void talloc_ctx_walk_cb(const void *chunk, int depth, + int max_depth, int is_ref, void *data) +{ + const char *chunk_name = talloc_get_name(chunk); + int spaces_cnt; + + /* Hierarchical spacing */ + for (spaces_cnt = 0; spaces_cnt < depth; spaces_cnt++) + printf(" "); + + /* Chunk info */ + printf("chunk %s: depth=%d\n", chunk_name, depth); +} + +static int q3_i0_proc(void *state, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + int i; + + printf("Incoming data: "); + + for (i = 0; i < 10; i++) { + printf("%d ", i); + out[i] = i; + } + + printf("\n"); + + return 0; +} + +static int q3_i1_proc(void *state, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + int i; + + for (i = 0; i < 10; i++) + out[i] = in[i] % 2; + + return 0; +} + +static int q3_i2_proc(void *state, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + int i; + + printf("Outgoing data: "); + + for (i = 0; i < 10; i++) + printf("%d ", in[i]); + + printf("\n"); + + return 0; +} + +static void q3_exit(void *state) +{ + struct osmo_gapk_pq_item *item; + + /* Make sure the item's state is passed correctly */ + assert(state != NULL); + + item = (struct osmo_gapk_pq_item *) state; + printf("Calling exit callback for '%s/%s'\n", + item->cat_name, item->sub_name); +} + +int main(int argc, char **argv) +{ + /* Enable tracking the use of NULL memory contexts */ + talloc_enable_null_tracking(); + + /** + * 1. Processing queue allocation test + */ + struct osmo_gapk_pq *q0, *q1, *q2, *q3; + + printf("Processing queue allocation test:\n"); + + /* Allocate four queues */ + q0 = osmo_gapk_pq_create(NULL); + q1 = osmo_gapk_pq_create("q1"); + q2 = osmo_gapk_pq_create("q2"); + q3 = osmo_gapk_pq_create("q3"); + + /* Make sure all queues are allocated */ + assert(q0 != NULL); + assert(q1 != NULL); + assert(q2 != NULL); + assert(q3 != NULL); + + /* Print talloc memory hierarchy */ + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + printf("\n"); + + + /** + * 2. Item allocation test + */ + struct osmo_gapk_pq_item *q3_i0, *q3_i1, *q3_i2; + struct osmo_gapk_pq_item *q2_i0, *q2_i1; + struct osmo_gapk_pq_item *q1_i0; + + printf("Item allocation test:\n"); + + /* Make sure there are no items */ + assert(q0->n_items == 0); + assert(q1->n_items == 0); + assert(q2->n_items == 0); + assert(q3->n_items == 0); + + /* Allocate items */ + q3_i0 = osmo_gapk_pq_add_item(q3); + q3_i1 = osmo_gapk_pq_add_item(q3); + q3_i2 = osmo_gapk_pq_add_item(q3); + q2_i0 = osmo_gapk_pq_add_item(q2); + q2_i1 = osmo_gapk_pq_add_item(q2); + q1_i0 = osmo_gapk_pq_add_item(q1); + + /* Make sure all items are allocated */ + assert(q3_i0 != NULL); + assert(q3_i1 != NULL); + assert(q3_i2 != NULL); + assert(q2_i0 != NULL); + assert(q2_i1 != NULL); + assert(q1_i0 != NULL); + + /* Check item count */ + assert(q0->n_items == 0); + assert(q1->n_items == 1); + assert(q2->n_items == 2); + assert(q3->n_items == 3); + + /* Print talloc memory hierarchy */ + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + printf("\n"); + + + /** + * 3. Items persistence test + */ + struct osmo_gapk_pq_item *item; + + /* Make sure that q0 is empty, others are not */ + assert(llist_empty(&q0->items) == 1); + assert(llist_empty(&q1->items) == 0); + assert(llist_empty(&q2->items) == 0); + assert(llist_empty(&q3->items) == 0); + + /* A single item must be the first and the last in a queue */ + item = llist_first_entry(&q1->items, struct osmo_gapk_pq_item, list); + assert(item == q1_i0); + item = llist_last_entry(&q1->items, struct osmo_gapk_pq_item, list); + assert(item == q1_i0); + + /* Two items: one is the first, second is the last */ + item = llist_first_entry(&q2->items, struct osmo_gapk_pq_item, list); + assert(item == q2_i0); + item = llist_last_entry(&q2->items, struct osmo_gapk_pq_item, list); + assert(item == q2_i1); + + /* Three items: one is the first, third is the last */ + item = llist_first_entry(&q3->items, struct osmo_gapk_pq_item, list); + assert(item == q3_i0); + assert(item != q3_i1); + item = llist_last_entry(&q3->items, struct osmo_gapk_pq_item, list); + assert(item == q3_i2); + assert(item != q3_i1); + + + /** + * 4. Queue I/O data lengths check + */ + q3_i0->len_in = 10; + q3_i0->len_out = 20; + + q3_i1->len_in = 20; + q3_i1->len_out = 30; + + q3_i2->len_in = 30; + q3_i2->len_out = 10; + + /* Normal case */ + assert(osmo_gapk_pq_check(q3, 0) == 0); + + /* Abnormal case (I/O length mismatch) */ + q3_i0->len_out = 10; + assert(osmo_gapk_pq_check(q3, 0) != 0); + q3_i0->len_out = 20; + + /* Check queue in strict mode (requires src -> ... -> sink) */ + q3_i0->type = OSMO_GAPK_ITEM_TYPE_SOURCE; + q3_i1->type = OSMO_GAPK_ITEM_TYPE_PROC; + q3_i2->type = OSMO_GAPK_ITEM_TYPE_SINK; + + /* Normal case (src -> proc -> sink) */ + assert(osmo_gapk_pq_check(q3, 1) == 0); + + /* Abnormal case (proc -> proc -> sink) */ + q3_i0->type = OSMO_GAPK_ITEM_TYPE_PROC; + assert(osmo_gapk_pq_check(q3, 1) != 0); + q3_i0->type = OSMO_GAPK_ITEM_TYPE_SOURCE; + + + /** + * 5. Buffer allocation test + */ + printf("Queue preparation test:\n"); + + /* Prepare the queue */ + assert(osmo_gapk_pq_prepare(q3) == 0); + + /* Make sure buffers were allocated */ + assert(q3_i0->buf != NULL); + assert(q3_i1->buf != NULL); + + /* Currently, we don't allocate buffers for sinks */ + assert(q3_i2->buf == NULL); + + /* Compare required vs allocated buffer sizes */ + assert(talloc_total_size(q3_i0->buf) == q3_i0->len_out); + assert(talloc_total_size(q3_i1->buf) == q3_i1->len_out); + + /* Print talloc memory hierarchy */ + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + printf("\n"); + + + /** + * 6. Queue description test + */ + char *queue_desc; + + printf("Queue description test:\n"); + + /* An empty queue doesn't have description */ + queue_desc = osmo_gapk_pq_describe(q0); + assert(queue_desc == NULL); + + /* Fill in some data */ + q3_i0->cat_name = "source"; + q3_i0->sub_name = "file"; + q3_i1->cat_name = "proc"; + q3_i1->sub_name = "dummy"; + q3_i2->cat_name = "sink"; + q3_i2->sub_name = "alsa"; + + q2_i0->cat_name = "source"; + q2_i0->sub_name = "dummy"; + q2_i1->cat_name = "sink"; + q2_i1->sub_name = "dummy"; + + q1_i0->cat_name = "dummy"; + q1_i0->sub_name = "dummy"; + + queue_desc = osmo_gapk_pq_describe(q3); + assert(queue_desc != NULL); + printf("Queue q3 description: %s\n", queue_desc); + talloc_free(queue_desc); + + queue_desc = osmo_gapk_pq_describe(q2); + assert(queue_desc != NULL); + printf("Queue q2 description: %s\n", queue_desc); + talloc_free(queue_desc); + + queue_desc = osmo_gapk_pq_describe(q1); + assert(queue_desc != NULL); + printf("Queue q1 description: %s\n\n", queue_desc); + talloc_free(queue_desc); + + + /** + * 7. Queue execution test + */ + printf("Processing queue execution test:\n"); + + /* Make sure there are no callbacks by default */ + assert(q3_i0->proc == NULL); + assert(q3_i0->wait == NULL); + assert(q3_i0->exit == NULL); + + assert(q3_i1->proc == NULL); + assert(q3_i1->wait == NULL); + assert(q3_i1->exit == NULL); + + assert(q3_i2->proc == NULL); + assert(q3_i2->wait == NULL); + assert(q3_i2->exit == NULL); + + q3_i0->proc = &q3_i0_proc; + q3_i1->proc = &q3_i1_proc; + q3_i2->proc = &q3_i2_proc; + + assert(osmo_gapk_pq_execute(q3) == 0); + printf("\n"); + + + /** + * 8. Exit callback & deallocation tests + */ + printf("Processing queue exit callback test:\n"); + + q3_i0->state = q3_i0; + q3_i1->state = q3_i1; + q3_i2->state = q3_i2; + + q3_i0->exit = &q3_exit; + q3_i1->exit = &q3_exit; + q3_i2->exit = &q3_exit; + + osmo_gapk_pq_destroy(q0); + osmo_gapk_pq_destroy(q1); + osmo_gapk_pq_destroy(q2); + osmo_gapk_pq_destroy(q3); + + printf("\n"); + + + /** + * 9. Memory leak detection test + */ + printf("Processing queue deallocation test:\n"); + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + + return 0; +} diff --git a/tests/procqueue/pq_test.ok b/tests/procqueue/pq_test.ok new file mode 100644 index 0000000..abdb666 --- /dev/null +++ b/tests/procqueue/pq_test.ok @@ -0,0 +1,60 @@ +Processing queue allocation test: +chunk null_context: depth=0 + chunk struct osmo_gapk_pq 'q3': depth=1 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q2': depth=1 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q1': depth=1 + chunk .name: depth=2 + chunk struct osmo_gapk_pq: depth=1 + +Item allocation test: +chunk null_context: depth=0 + chunk struct osmo_gapk_pq 'q3': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk struct osmo_gapk_pq_item: depth=2 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q2': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q1': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .name: depth=2 + chunk struct osmo_gapk_pq: depth=1 + +Queue preparation test: +chunk null_context: depth=0 + chunk struct osmo_gapk_pq 'q3': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .buffer: depth=3 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .buffer: depth=3 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q2': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .name: depth=2 + chunk struct osmo_gapk_pq 'q1': depth=1 + chunk struct osmo_gapk_pq_item: depth=2 + chunk .name: depth=2 + chunk struct osmo_gapk_pq: depth=1 + +Queue description test: +Queue q3 description: source/file -> proc/dummy -> sink/alsa +Queue q2 description: source/dummy -> sink/dummy +Queue q1 description: dummy/dummy + +Processing queue execution test: +Incoming data: 0 1 2 3 4 5 6 7 8 9 +Outgoing data: 0 1 0 1 0 1 0 1 0 1 + +Processing queue exit callback test: +Calling exit callback for 'source/file' +Calling exit callback for 'proc/dummy' +Calling exit callback for 'sink/alsa' + +Processing queue deallocation test: +chunk null_context: depth=0 diff --git a/tests/testsuite.at b/tests/testsuite.at index 09a77c3..ea8498c 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,2 +1,8 @@ AT_INIT AT_BANNER([Regression tests.]) + +AT_SETUP([procqueue]) +AT_KEYWORDS([procqueue]) +cat $abs_srcdir/procqueue/pq_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/procqueue/pq_test], [0], [expout]) +AT_CLEANUP -- cgit v1.2.3 From 3e9e57fb400218a74c44f9e3ffb70cf5291410a4 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 12 Sep 2017 19:07:52 +0300 Subject: tests: add pq_file test This test is intended to check the file source / sink operability. To do that, the following processing chain is being composed: source/file -> proc/dummy -> sink/file (stdout) The source item opens the sample file named 'io_sample.txt' for reading. The next processing item simply converts all uppercase latters to the lowercase. The last one writes the result to stdout. This processing cycle is being repeated several times with different block length values. --- tests/Makefile.am | 11 ++++ tests/io/io_sample.txt | 1 + tests/io/pq_file_test.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++ tests/io/pq_file_test.ok | 12 ++++ tests/testsuite.at | 9 +++ 5 files changed, 182 insertions(+) create mode 100644 tests/io/io_sample.txt create mode 100644 tests/io/pq_file_test.c create mode 100644 tests/io/pq_file_test.ok diff --git a/tests/Makefile.am b/tests/Makefile.am index 2d21abb..555899c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -12,6 +12,7 @@ AM_CFLAGS = \ check_PROGRAMS = \ procqueue/pq_test \ + io/pq_file_test \ $(NULL) procqueue_pq_test_SOURCES = procqueue/pq_test.c @@ -22,6 +23,14 @@ procqueue_pq_test_LDADD = \ $(TALLOC_LIBS) \ $(NULL) +io_pq_file_test_SOURCES = io/pq_file_test.c +io_pq_file_test_LDADD = \ + $(top_builddir)/src/libosmogapk.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCODEC_LIBS) \ + $(TALLOC_LIBS) \ + $(NULL) + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ @@ -48,6 +57,8 @@ EXTRA_DIST = \ EXTRA_DIST += \ procqueue/pq_test.ok \ + io/pq_file_test.ok \ + io/io_sample.txt \ $(NULL) DISTCLEANFILES = atconfig diff --git a/tests/io/io_sample.txt b/tests/io/io_sample.txt new file mode 100644 index 0000000..707e019 --- /dev/null +++ b/tests/io/io_sample.txt @@ -0,0 +1 @@ +8217C8FB7675A95008F9089D883gapk diff --git a/tests/io/pq_file_test.c b/tests/io/pq_file_test.c new file mode 100644 index 0000000..6691db3 --- /dev/null +++ b/tests/io/pq_file_test.c @@ -0,0 +1,149 @@ +/* + * This file is part of GAPK (GSM Audio Pocket Knife). + * + * (C) 2017 by Vadim Yanitskiy + * + * 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 . + */ + +#include +#include +#include +#include + +#include +#include + +/** + * This test is intended to check the file source / sink + * operability. To do that, the following processing chain + * is being composed: + * + * source/file -> proc/dummy -> sink/file (stdout) + * + * The source item opens the sample file named 'io_sample.txt' + * for reading. The next processing item simply converts all + * uppercase latters to the lowercase. The last one writes + * the result to stdout. + * + * This processing cycle is being repeated several times + * with different block length values. + */ + +static void talloc_ctx_walk_cb(const void *chunk, int depth, + int max_depth, int is_ref, void *data) +{ + const char *chunk_name = talloc_get_name(chunk); + int spaces_cnt; + + /* Hierarchical spacing */ + for (spaces_cnt = 0; spaces_cnt < depth; spaces_cnt++) + printf(" "); + + /* Chunk info */ + printf("chunk %s: depth=%d\n", chunk_name, depth); +} + +static int pq_file_proc(void *state, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + int i; + + /* Change upper case to lower */ + for (i = 0; i < in_len; i++) + out[i] = (in[i] >= 65 && in[i] <= 90) ? + in[i] + 32 : in[i]; + + return in_len; +} + +static int pq_file_check(FILE *src_file, unsigned int blk_len) +{ + struct osmo_gapk_pq_item *proc_item; + struct osmo_gapk_pq *pq; + int rc; + + printf("Processing sample file with blk_len=%u:\n", blk_len); + + /* Allocate a processing queue */ + pq = osmo_gapk_pq_create("pq_file_check"); + assert(pq != NULL); + + /* Add a file sink */ + rc = osmo_gapk_pq_queue_file_input(pq, src_file, blk_len); + assert(rc == 0); + + /* Add a processing item */ + proc_item = osmo_gapk_pq_add_item(pq); + assert(proc_item != NULL); + + /* Set up I/O parameters */ + proc_item->type = OSMO_GAPK_ITEM_TYPE_PROC; + proc_item->len_in = blk_len; + proc_item->len_out = blk_len; + + /* Set the processing callback */ + proc_item->proc = &pq_file_proc; + + /* Add a sink item */ + rc = osmo_gapk_pq_queue_file_output(pq, stdout, blk_len); + assert(rc == 0); + + /* Check a queue in strict mode */ + rc = osmo_gapk_pq_check(pq, 1); + assert(rc == 0); + + /* Prepare a queue */ + rc = osmo_gapk_pq_prepare(pq); + assert(rc == 0); + + while (1) { + rc = osmo_gapk_pq_execute(pq); + if (rc) + break; + } + + /* Destroy processing queue */ + osmo_gapk_pq_destroy(pq); + + return 0; +} + +int main(int argc, char **argv) +{ + int i; + + /* Enable tracking the use of NULL memory contexts */ + talloc_enable_null_tracking(); + + /* Open sample file */ + FILE *sample_file = fopen(argv[1], "rb"); + assert(sample_file != NULL); + + /* Process sample file with different blk_len values */ + for (i = 2; i <= 32; i *= 2) { + pq_file_check(sample_file, i); + rewind(sample_file); + } + + printf("\n"); + + /* Close sample file */ + fclose(sample_file); + + /* Print talloc memory hierarchy */ + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + + return 0; +} diff --git a/tests/io/pq_file_test.ok b/tests/io/pq_file_test.ok new file mode 100644 index 0000000..8df71c3 --- /dev/null +++ b/tests/io/pq_file_test.ok @@ -0,0 +1,12 @@ +Processing sample file with blk_len=2: +8217c8fb7675a95008f9089d883gapk +Processing sample file with blk_len=4: +8217c8fb7675a95008f9089d883gapk +Processing sample file with blk_len=8: +8217c8fb7675a95008f9089d883gapk +Processing sample file with blk_len=16: +8217c8fb7675a95008f9089d883gapk +Processing sample file with blk_len=32: +8217c8fb7675a95008f9089d883gapk + +chunk null_context: depth=0 diff --git a/tests/testsuite.at b/tests/testsuite.at index ea8498c..bffbc52 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -6,3 +6,12 @@ AT_KEYWORDS([procqueue]) cat $abs_srcdir/procqueue/pq_test.ok > expout AT_CHECK([$abs_top_builddir/tests/procqueue/pq_test], [0], [expout]) AT_CLEANUP + +AT_SETUP([pq_file]) +AT_KEYWORDS([pq_file]) +cat $abs_srcdir/io/pq_file_test.ok > expout +AT_CHECK([ + $abs_top_builddir/tests/io/pq_file_test \ + $abs_top_builddir/tests/io/io_sample.txt], + [0], [expout]) +AT_CLEANUP -- cgit v1.2.3 From 9d2b15dc8a97ceefc5cd2e95a885bd306ec992be Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 14 Sep 2017 15:20:50 +0430 Subject: tests: add pq_rtp test This test is intended to check the RTP source / sink operability. To do this, two processing queues are being allocated: "generator": source/random -> sink/rtp "checker": source/rtp -> sink/checker The first one generates some amount of random bytes (payload), and stores them inside a buffer that is shared between both queues. After generation, a payload is being sent from the first queue via an RTP sink, and then being received by the second via an RTP source. As both queues do use a shared buffer, the last item of the second queue (named 'sink/checker') is able to compare a received payload with expected. --- tests/Makefile.am | 10 ++ tests/io/pq_rtp_test.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/io/pq_rtp_test.ok | 10 ++ tests/testsuite.at | 9 +- 4 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 tests/io/pq_rtp_test.c create mode 100644 tests/io/pq_rtp_test.ok diff --git a/tests/Makefile.am b/tests/Makefile.am index 555899c..8f53787 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,6 +13,7 @@ AM_CFLAGS = \ check_PROGRAMS = \ procqueue/pq_test \ io/pq_file_test \ + io/pq_rtp_test \ $(NULL) procqueue_pq_test_SOURCES = procqueue/pq_test.c @@ -31,6 +32,14 @@ io_pq_file_test_LDADD = \ $(TALLOC_LIBS) \ $(NULL) +io_pq_rtp_test_SOURCES = io/pq_rtp_test.c +io_pq_rtp_test_LDADD = \ + $(top_builddir)/src/libosmogapk.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCODEC_LIBS) \ + $(TALLOC_LIBS) \ + $(NULL) + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ @@ -58,6 +67,7 @@ EXTRA_DIST = \ EXTRA_DIST += \ procqueue/pq_test.ok \ io/pq_file_test.ok \ + io/pq_rtp_test.ok \ io/io_sample.txt \ $(NULL) diff --git a/tests/io/pq_rtp_test.c b/tests/io/pq_rtp_test.c new file mode 100644 index 0000000..cf6e2a6 --- /dev/null +++ b/tests/io/pq_rtp_test.c @@ -0,0 +1,349 @@ +/* + * This file is part of GAPK (GSM Audio Pocket Knife). + * + * (C) 2017 by Vadim Yanitskiy + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +/** + * This test is intended to check the RTP source / sink operability. + * To do this, two processing queues are being allocated: + * + * "generator": source/random -> sink/rtp + * "checker": source/rtp -> sink/checker + * + * The first one generates some amount of random bytes (payload), + * and stores them inside a buffer that is shared between both + * queues. + * + * After generation, a payload is being sent from the first + * queue via an RTP sink, and then being received by the second + * via an RTP source. + * + * As both queues do use a shared buffer, the last item of the + * second queue (named 'sink/checker') is able to compare a + * received payload with expected. + */ + +static void talloc_ctx_walk_cb(const void *chunk, int depth, + int max_depth, int is_ref, void *data) +{ + const char *chunk_name = talloc_get_name(chunk); + int spaces_cnt; + + /* Hierarchical spacing */ + for (spaces_cnt = 0; spaces_cnt < depth; spaces_cnt++) + printf(" "); + + /* Chunk info */ + printf("chunk %s: depth=%d\n", chunk_name, depth); +} + +#define RTP_TEST_BUF_LEN 128 + +struct rtp_test_state { + unsigned int payload_len; + unsigned int rtp_port; + int rtp_src_fd; + int rtp_dst_fd; + + uint8_t data[RTP_TEST_BUF_LEN]; + uint8_t *ptr; +}; + +static int src_rand_proc(void *data, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + struct rtp_test_state *state = (struct rtp_test_state *) data; + unsigned int i; + + /* Generate a random payload */ + for (i = 0; i < state->payload_len; i++) { + uint8_t byte = rand() % 0xff; + *(state->ptr + i) = byte; + out[i] = byte; + } + + return state->payload_len; +} + +static void src_rand_exit(void *data) +{ + struct rtp_test_state *state = (struct rtp_test_state *) data; + + if (state->rtp_src_fd >= 0) { + close(state->rtp_src_fd); + state->rtp_src_fd = -1; + } +} + +static int sink_chk_proc(void *data, uint8_t *out, const uint8_t *in, + unsigned int in_len) +{ + struct rtp_test_state *state = (struct rtp_test_state *) data; + unsigned int i; + + /* Make sure we have all bytes transferred */ + if (in_len != state->payload_len) { + printf("Data length mismatch!\n"); + return -EINVAL; + } + + for (i = 0; i < in_len; i++) { + if (in[i] != *(state->ptr + i)) { + printf("Data mismatch!\n"); + return -EINVAL; + } + } + + return in_len; +} + +static void sink_chk_exit(void *data) +{ + struct rtp_test_state *state = (struct rtp_test_state *) data; + + if (state->rtp_dst_fd >= 0) { + close(state->rtp_dst_fd); + state->rtp_dst_fd = -1; + } +} + +/* Allocates: source/random -> sink/rtp */ +static int init_gen_queue(struct osmo_gapk_pq *pq, + struct rtp_test_state *state, unsigned int payload_len) +{ + int rc; + + /* Allocate memory for the 'source/random' */ + struct osmo_gapk_pq_item *src_rand = osmo_gapk_pq_add_item(pq); + if (!src_rand) + return -ENOMEM; + + /* Fill in meta information */ + src_rand->type = OSMO_GAPK_ITEM_TYPE_SOURCE; + src_rand->cat_name = "source"; + src_rand->sub_name = "random"; + + /* Set I/O buffer lengths */ + state->payload_len = payload_len; + src_rand->len_out = payload_len; + + /* Set proc / exit callbacks and state */ + src_rand->proc = &src_rand_proc; + src_rand->exit = &src_rand_exit; + src_rand->state = state; + + + /* Init connection socket */ + state->rtp_dst_fd = osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, + IPPROTO_UDP, "127.0.0.1", state->rtp_port, OSMO_SOCK_F_CONNECT); + if (state->rtp_dst_fd < 0) { + printf("Could not init connection socket\n"); + return -EINVAL; + } + + /* Init an RTP sink */ + rc = osmo_gapk_pq_queue_rtp_output(pq, state->rtp_dst_fd, payload_len); + if (rc) { + printf("Could not init an RTP sink\n"); + return rc; + } + + /* Check and prepare */ + rc = osmo_gapk_pq_check(pq, 1); + if (rc) { + printf("Queue check failed\n"); + return rc; + } + + rc = osmo_gapk_pq_prepare(pq); + if (rc) { + printf("Queue preparation failed\n"); + return rc; + } + + return 0; +} + +/* Allocates: source/rtp -> sink/checker */ +static int init_chk_queue(struct osmo_gapk_pq *pq, + struct rtp_test_state *state, unsigned int payload_len) +{ + int rc; + + /* Init listening socket */ + state->rtp_src_fd = osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, + IPPROTO_UDP, "127.0.0.1", 0, OSMO_SOCK_F_BIND); + if (state->rtp_src_fd < 0) { + printf("Could not init listening socket\n"); + return -EINVAL; + } + + /* Init an RTP source on any available port */ + rc = osmo_gapk_pq_queue_rtp_input(pq, state->rtp_src_fd, payload_len); + if (rc) { + printf("Could not init an RTP sink\n"); + return rc; + } + + /* Determine on which port are we listening */ + struct sockaddr_in adr_inet; + socklen_t len_inet; + + len_inet = sizeof(adr_inet); + rc = getsockname(state->rtp_src_fd, + (struct sockaddr *) &adr_inet, &len_inet); + if (rc) + return -EINVAL; + + /* Save assigned port to shared state */ + state->rtp_port = (unsigned int) ntohs(adr_inet.sin_port); + + + /* Allocate memory for the 'sink/checker' */ + struct osmo_gapk_pq_item *sink_chk = osmo_gapk_pq_add_item(pq); + if (!sink_chk) + return -ENOMEM; + + /* Fill in meta information */ + sink_chk->type = OSMO_GAPK_ITEM_TYPE_SINK; + sink_chk->cat_name = "sink"; + sink_chk->sub_name = "checker"; + + /* Set I/O buffer lengths */ + sink_chk->len_in = payload_len; + + /* Set proc / exit callbacks and state */ + sink_chk->proc = &sink_chk_proc; + sink_chk->exit = &sink_chk_exit; + sink_chk->state = state; + + /* Check and prepare */ + rc = osmo_gapk_pq_check(pq, 1); + if (rc) { + printf("Queue check failed\n"); + return rc; + } + + rc = osmo_gapk_pq_prepare(pq); + if (rc) { + printf("Queue preparation failed\n"); + return rc; + } + + return 0; +} + +static int rtp_test(struct rtp_test_state *state, unsigned int payload_len) +{ + struct osmo_gapk_pq *q_gen, *q_chk; + unsigned int i, chunks; + int rc; + + /* Allocate two queues */ + q_gen = osmo_gapk_pq_create("generator"); + q_chk = osmo_gapk_pq_create("checker"); + + /* Make sure both queues are allocated */ + if (!q_gen || !q_chk) { + rc = -ENOMEM; + goto exit; + } + + /* Init both queues: generator and checker */ + rc = init_chk_queue(q_chk, state, payload_len); + if (rc) + goto exit; + + rc = init_gen_queue(q_gen, state, payload_len); + if (rc) + goto exit; + + /* Calculate how much chunks do we have */ + chunks = RTP_TEST_BUF_LEN / payload_len; + + /* Execute both queues */ + for (i = 0; i < chunks; i++) { + /* Move data pointer */ + state->ptr = state->data + i * payload_len; + + /* Generate and send a payload */ + rc = osmo_gapk_pq_execute(q_gen); + if (rc) { + printf("Queue '%s' execution aborted on chunk %u/%u\n", + q_gen->name, i + 1, chunks); + goto exit; + } + + /* TODO: prevent test hang if nothing was being sent */ + + /* Receive and check a payload */ + rc = osmo_gapk_pq_execute(q_chk); + if (rc) { + printf("Queue '%s' execution aborted on chunk %u/%u\n", + q_gen->name, i + 1, chunks); + goto exit; + } + } + + printf("Payload len=%u check ok\n", payload_len); + +exit: + /* Deallocate both queues and data */ + osmo_gapk_pq_destroy(q_gen); + osmo_gapk_pq_destroy(q_chk); + + return rc; +} + +int main(int argc, char **argv) +{ + struct rtp_test_state state; + unsigned int len; + + /* Enable tracking the use of NULL memory contexts */ + talloc_enable_null_tracking(); + + /* Init pseudo-random generator */ + srand(time(NULL)); + + /* Perform testing with different payload size values */ + for (len = 1; len <= RTP_TEST_BUF_LEN; len *= 2) + assert(rtp_test(&state, len) == 0); + printf("\n"); + + /* Memory leak detection test */ + talloc_report_depth_cb(NULL, 0, 10, &talloc_ctx_walk_cb, NULL); + + return 0; +} diff --git a/tests/io/pq_rtp_test.ok b/tests/io/pq_rtp_test.ok new file mode 100644 index 0000000..bae485f --- /dev/null +++ b/tests/io/pq_rtp_test.ok @@ -0,0 +1,10 @@ +Payload len=1 check ok +Payload len=2 check ok +Payload len=4 check ok +Payload len=8 check ok +Payload len=16 check ok +Payload len=32 check ok +Payload len=64 check ok +Payload len=128 check ok + +chunk null_context: depth=0 diff --git a/tests/testsuite.at b/tests/testsuite.at index bffbc52..1127f2b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -7,7 +7,7 @@ cat $abs_srcdir/procqueue/pq_test.ok > expout AT_CHECK([$abs_top_builddir/tests/procqueue/pq_test], [0], [expout]) AT_CLEANUP -AT_SETUP([pq_file]) +AT_SETUP([io/pq_file]) AT_KEYWORDS([pq_file]) cat $abs_srcdir/io/pq_file_test.ok > expout AT_CHECK([ @@ -15,3 +15,10 @@ AT_CHECK([ $abs_top_builddir/tests/io/io_sample.txt], [0], [expout]) AT_CLEANUP + +AT_SETUP([io/pq_rtp]) +AT_KEYWORDS([pq_rtp]) +cat $abs_srcdir/io/pq_rtp_test.ok > expout +AT_CHECK([ + $abs_top_builddir/tests/io/pq_rtp_test], [0], [expout]) +AT_CLEANUP -- cgit v1.2.3 From 10076f0acce2274fdb363cd69ee83becdef6d6c8 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 15 Sep 2017 19:17:21 +0430 Subject: osmo-gapk: fix I/O count check condition The stdin / stdout operation was broken by a new check condition, introduced by the 15fa605576a81803c57a144231e9e9720aa133a1. --- src/app_osmo_gapk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c index 2aac0aa..729ea25 100644 --- a/src/app_osmo_gapk.c +++ b/src/app_osmo_gapk.c @@ -355,7 +355,7 @@ check_options(struct gapk_state *gs) if (gs->opts.alsa_out) sink_count++; - if (src_count != 1 || sink_count != 1) { + 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; -- cgit v1.2.3 From f59f3f1ba8bc1cdf7c406867e3611f810ddc28c7 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 15 Sep 2017 19:34:44 +0430 Subject: tests: add format / codec transcoding tests This test group is intended to check the format / codec transcoding capabilities of the library. The reference files are used to ensure that encoding or decoding was successful. The following formats are currently being tested: - amr_efr - gsm - racal_hr - racal_fr - racal_efr - ti_hr - ti_fr - ti_efr - rtp_efr - rtp_hr_etsi - rtp_hr_ietf --- tests/Makefile.am | 1 + tests/testsuite.at | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/tests/Makefile.am b/tests/Makefile.am index 8f53787..cda5c2d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -69,6 +69,7 @@ EXTRA_DIST += \ io/pq_file_test.ok \ io/pq_rtp_test.ok \ io/io_sample.txt \ + ref-files/* \ $(NULL) DISTCLEANFILES = atconfig diff --git a/tests/testsuite.at b/tests/testsuite.at index 1127f2b..7367bc5 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -22,3 +22,223 @@ cat $abs_srcdir/io/pq_rtp_test.ok > expout AT_CHECK([ $abs_top_builddir/tests/io/pq_rtp_test], [0], [expout]) AT_CLEANUP + +AT_SETUP([conv/enc/amr_efr]) +AT_KEYWORDS([amr_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.amr-efr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g amr-efr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/gsm]) +AT_KEYWORDS([gsm]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.gsm > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g gsm +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/racal_hr]) +AT_KEYWORDS([racal_hr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-hr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g racal-hr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/racal_fr]) +AT_KEYWORDS([racal_fr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-fr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g racal-fr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/racal_efr]) +AT_KEYWORDS([racal_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-efr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g racal-efr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/ti_hr]) +AT_KEYWORDS([ti_hr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-hr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g ti-hr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/ti_fr]) +AT_KEYWORDS([ti_fr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-fr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g ti-fr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/ti_efr]) +AT_KEYWORDS([ti_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-efr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g ti-efr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/rtp_efr]) +AT_KEYWORDS([rtp_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-efr > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g rtp-efr +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/rtp_hr_etsi]) +AT_KEYWORDS([rtp_hr_etsi]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g rtp-hr-etsi +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/enc/rtp_hr_ietf]) +AT_KEYWORDS([rtp_hr_ietf]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16 \ + -f rawpcm-s16le -g rtp-hr-ietf +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/amr_efr]) +AT_KEYWORDS([amr_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.amr-efr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.amr-efr \ + -f amr-efr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/gsm]) +AT_KEYWORDS([gsm]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.gsm.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.gsm \ + -f gsm -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/racal_hr]) +AT_KEYWORDS([racal_hr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-hr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-hr \ + -f racal-hr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/racal_fr]) +AT_KEYWORDS([racal_fr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-fr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-fr \ + -f racal-fr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/racal_efr]) +AT_KEYWORDS([racal_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-efr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.racal-efr \ + -f racal-efr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/ti_hr]) +AT_KEYWORDS([ti_hr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-hr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-hr \ + -f ti-hr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/ti_fr]) +AT_KEYWORDS([ti_fr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-fr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-fr \ + -f ti-fr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/ti_efr]) +AT_KEYWORDS([ti_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-efr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.ti-efr \ + -f ti-efr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/rtp_efr]) +AT_KEYWORDS([rtp_efr]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-efr.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-efr \ + -f rtp-efr -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/rtp_hr_etsi]) +AT_KEYWORDS([rtp_hr_etsi]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-etsi \ + -f rtp-hr-etsi -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([conv/dec/rtp_hr_ietf]) +AT_KEYWORDS([rtp_hr_ietf]) +cat $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf.s16 > expout +AT_CHECK([ + $abs_top_builddir/src/osmo-gapk \ + -i $abs_srcdir/ref-files/hhgttg_part1_5.s16.rtp-hr-ietf \ + -f rtp-hr-ietf -g rawpcm-s16le +], [0], [expout], [ignore]) +AT_CLEANUP -- cgit v1.2.3 From 2254861efb0216b55d04926b339220ecf9e31aa5 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 9 Jan 2018 00:13:15 +0600 Subject: pq_alsa.c: fix memory leak after pq_cb_alsa_exit() Abusing the talloc hierarchical nature may cause some problems, e.g. on embedded systems with emulated talloc API. Let's release the memory allocated for a state explicitly. Change-Id: Ie675a92b1e52a4886dc447af19f65ff5e12a4c40 --- src/pq_alsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 84d2e20..676e8e7 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -81,6 +81,7 @@ pq_cb_alsa_exit(void *_state) { struct pq_state_alsa *state = _state; snd_pcm_close(state->pcm_handle); + talloc_free(state); } static int -- cgit v1.2.3 From 6f34c8f3017629ea4865543e901b61ac893e0356 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 15 Jan 2018 00:25:44 +0600 Subject: procqueue: introduce and use shared cat_name definitions Let's use the common string representation for item category names, defined in the shared header, instead of defining them in every file. Change-Id: Ie0c449d77fa383cad27f67b8ce902bd071342dbb --- include/osmocom/gapk/procqueue.h | 4 ++++ src/pq_alsa.c | 3 ++- src/pq_file.c | 3 ++- src/pq_rtp.c | 3 ++- tests/io/pq_rtp_test.c | 4 ++-- tests/procqueue/pq_test.c | 12 +++++++----- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index e73f73e..6b929d7 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -30,6 +30,10 @@ enum osmo_gapk_pq_item_type { OSMO_GAPK_ITEM_TYPE_PROC, }; +#define OSMO_GAPK_CAT_NAME_SOURCE "source" +#define OSMO_GAPK_CAT_NAME_SINK "sink" +#define OSMO_GAPK_CAT_NAME_PROC "proc" + struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ unsigned int len_in; diff --git a/src/pq_alsa.c b/src/pq_alsa.c index 676e8e7..3550221 100644 --- a/src/pq_alsa.c +++ b/src/pq_alsa.c @@ -143,7 +143,8 @@ pq_queue_alsa_op(struct osmo_gapk_pq *pq, const char *alsa_dev, unsigned int blk item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; - item->cat_name = in_out_n ? "source" : "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; diff --git a/src/pq_file.c b/src/pq_file.c index 8ad26d5..22dc9cd 100644 --- a/src/pq_file.c +++ b/src/pq_file.c @@ -80,7 +80,8 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; - item->cat_name = in_out_n ? "source" : "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; diff --git a/src/pq_rtp.c b/src/pq_rtp.c index c1d9ffb..a50013a 100644 --- a/src/pq_rtp.c +++ b/src/pq_rtp.c @@ -226,7 +226,8 @@ pq_queue_rtp_op(struct osmo_gapk_pq *pq, int udp_fd, unsigned int blk_len, int i item->type = in_out_n ? OSMO_GAPK_ITEM_TYPE_SOURCE : OSMO_GAPK_ITEM_TYPE_SINK; - item->cat_name = in_out_n ? "source" : "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; diff --git a/tests/io/pq_rtp_test.c b/tests/io/pq_rtp_test.c index cf6e2a6..f4070b7 100644 --- a/tests/io/pq_rtp_test.c +++ b/tests/io/pq_rtp_test.c @@ -151,7 +151,7 @@ static int init_gen_queue(struct osmo_gapk_pq *pq, /* Fill in meta information */ src_rand->type = OSMO_GAPK_ITEM_TYPE_SOURCE; - src_rand->cat_name = "source"; + src_rand->cat_name = OSMO_GAPK_CAT_NAME_SOURCE; src_rand->sub_name = "random"; /* Set I/O buffer lengths */ @@ -237,7 +237,7 @@ static int init_chk_queue(struct osmo_gapk_pq *pq, /* Fill in meta information */ sink_chk->type = OSMO_GAPK_ITEM_TYPE_SINK; - sink_chk->cat_name = "sink"; + sink_chk->cat_name = OSMO_GAPK_CAT_NAME_SINK; sink_chk->sub_name = "checker"; /* Set I/O buffer lengths */ diff --git a/tests/procqueue/pq_test.c b/tests/procqueue/pq_test.c index d0d6670..198108d 100644 --- a/tests/procqueue/pq_test.c +++ b/tests/procqueue/pq_test.c @@ -283,16 +283,18 @@ int main(int argc, char **argv) assert(queue_desc == NULL); /* Fill in some data */ - q3_i0->cat_name = "source"; + q3_i0->cat_name = OSMO_GAPK_CAT_NAME_SOURCE; q3_i0->sub_name = "file"; - q3_i1->cat_name = "proc"; + + q3_i1->cat_name = OSMO_GAPK_CAT_NAME_PROC; q3_i1->sub_name = "dummy"; - q3_i2->cat_name = "sink"; + + q3_i2->cat_name = OSMO_GAPK_CAT_NAME_SINK; q3_i2->sub_name = "alsa"; - q2_i0->cat_name = "source"; + q2_i0->cat_name = OSMO_GAPK_CAT_NAME_SOURCE; q2_i0->sub_name = "dummy"; - q2_i1->cat_name = "sink"; + q2_i1->cat_name = OSMO_GAPK_CAT_NAME_SINK; q2_i1->sub_name = "dummy"; q1_i0->cat_name = "dummy"; -- cgit v1.2.3