aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.checkpatch.conf1
-rw-r--r--.gitignore5
-rw-r--r--COPYING (renamed from gpl-3.0.txt)0
-rw-r--r--Makefile.am16
-rw-r--r--README.md35
-rw-r--r--configure.ac27
-rw-r--r--contrib/gapk.spec.in151
-rwxr-xr-xcontrib/jenkins.sh1
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control37
-rw-r--r--debian/copyright23
-rw-r--r--debian/gapk.install1
-rw-r--r--debian/libosmogapk-dev.install3
-rw-r--r--debian/libosmogapk0.install1
-rwxr-xr-xdebian/rules12
-rw-r--r--debian/source/format1
-rw-r--r--include/osmocom/gapk/get_cycles.h10
-rw-r--r--libgsmhr/Makefile.am14
-rwxr-xr-xlibgsmhr/fetch_sources.py46
-rw-r--r--src/Makefile.am12
-rw-r--r--src/app_osmo_gapk.c69
-rw-r--r--src/fmt_rtp_amr.c9
-rw-r--r--src/fmt_rtp_efr.c20
-rw-r--r--src/fmt_rtp_hr_etsi.c6
-rw-r--r--src/fmt_rtp_hr_ietf.c6
-rw-r--r--src/pq_alsa.c4
-rw-r--r--src/pq_file.c4
-rw-r--r--src/pq_rtp.c26
-rw-r--r--tests/Makefile.am2
30 files changed, 470 insertions, 78 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..58a0b87
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1 @@
+--ignore NEW_TYPEDEFS
diff --git a/.gitignore b/.gitignore
index ffef58f..d2f9840 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,8 @@ autoscan-2.*.log
configure.scan
# autoreconf by-products
+.version
Makefile.in
-
aclocal.m4
autom4te.cache/
config.guess
@@ -49,8 +49,9 @@ tests/*/*_test
src/osmo-gapk
# temporary/backup files
-*.*~
+*~
.*.swp
/compile
.dirstamp
+contrib/gapk.spec
diff --git a/gpl-3.0.txt b/COPYING
index 94a9ed0..94a9ed0 100644
--- a/gpl-3.0.txt
+++ b/COPYING
diff --git a/Makefile.am b/Makefile.am
index 0093f0e..f2a2c31 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,8 +4,6 @@ ACLOCAL_AMFLAGS = -I m4
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libosmogapk.pc
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-
SUBDIRS = include
if ENABLE_GSMHR
@@ -13,3 +11,17 @@ SUBDIRS += libgsmhr
endif
SUBDIRS += src tests
+
+BUILT_SOURCES = \
+ $(top_srcdir)/.version \
+ $(NULL)
+EXTRA_DIST = \
+ git-version-gen \
+ .version \
+ $(NULL)
+
+# versioning magic
+$(top_srcdir)/.version:
+ echo $(VERSION) > $@-t && mv $@-t $@
+dist-hook:
+ echo $(VERSION) > $(distdir)/.tarball-version
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5cf880e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+gapk - GSM Audio Pocket Knife
+=============================
+
+The GSM Audio Pocket Knife is a tool that can help you to convert
+codec frames of all codecs in GSM networks between a variety of
+different formats / representations.
+
+It is part of the [Osmocom](https://osmocom.org/) Open Source Mobile
+Communications project.
+
+GIT Repository
+--------------
+
+You can clone from the official gapk.git repository using
+
+ git clone https://gitea.osmocom.org/osmocom/gapk.git
+
+There is a web interface at <https://gitea.osmocom.org/osmocom/gapk>.
+
+Documentation
+-------------
+
+Unfortunately none.
+
+Mailing List
+------------
+
+Discussions related to gapk are happening on the
+openbsc@lists.osmocom.org mailing list, please see
+https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
+options and the list archive.
+
+Please observe the [Osmocom Mailing List
+Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
+when posting.
diff --git a/configure.ac b/configure.ac
index 6551ae6..9a318bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,6 +6,8 @@ AC_INIT([gapk],
AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects])
LT_INIT([disable-static])
+CFLAGS="$CFLAGS -std=gnu11"
+
# kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -13,16 +15,12 @@ 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
- libgsmhr/Makefile
- include/Makefile
- include/gsmhr/Makefile
- libosmogapk.pc
- tests/atlocal
- tests/Makefile
-])
+
+dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
+AS_CASE(["$LD"],[*clang*],
+ [AS_CASE(["${host_os}"],
+ [*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
+
# Options
AC_ARG_ENABLE(gsmhr,
@@ -115,4 +113,13 @@ AC_TYPE_UINT8_T
AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset])
+AC_CONFIG_FILES([contrib/gapk.spec
+ Makefile
+ src/Makefile
+ libgsmhr/Makefile
+ include/Makefile
+ include/gsmhr/Makefile
+ libosmogapk.pc
+ tests/atlocal
+ tests/Makefile])
AC_OUTPUT
diff --git a/contrib/gapk.spec.in b/contrib/gapk.spec.in
new file mode 100644
index 0000000..e0466f4
--- /dev/null
+++ b/contrib/gapk.spec.in
@@ -0,0 +1,151 @@
+#
+# spec file for package gapk
+#
+# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+%define with_amr 1
+%define with_gsmhr 1
+%define sover 0
+
+Name: gapk
+Version: @VERSION@
+Release: 0
+Summary: GSM Audio Pocket Knife
+License: GPL-3.0-only
+Group: Productivity/Multimedia/Sound/Editors and Convertors
+URL: http://www.osmocom.org
+Source: gapk-%{version}.tar.xz
+# License: for libgsmhr see 3gpp website
+Source1: 0606_421.zip
+Patch1: gapk-disable-codec-dl-during-build.diff
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: libgsm-devel
+BuildRequires: libtool
+BuildRequires: pkgconfig
+BuildRequires: python
+BuildRequires: pkgconfig(alsa)
+BuildRequires: pkgconfig(libosmocodec)
+BuildRequires: pkgconfig(libosmocore)
+# Benchmarking is currently only supported on intel platforms...
+ExclusiveArch: %{ix86} x86_64
+%if 0%{with_amr}
+BuildRequires: libopencore-amr-devel
+%endif
+
+%description
+gapk is intented to be the GSM Audio Pocket Knife.
+It encodes/decodes several GSM-related audio-codes (HR,FR,EFR)
+
+%if 0%{with_gsmhr}
+%package -n libgsmhr0
+Summary: Shared Library part of libgsmhr
+License: NonFree
+Group: Development/Libraries/C and C++
+
+%description -n libgsmhr0
+libgsmhr contains a standard implementation of the European GSM 06.20
+provisional standard for GSM Half Rate speech speech transcoding.
+
+%package -n libgsmhr-devel
+Summary: Development files for the gsmhr library
+License: NonFree
+Group: Development/Libraries/C and C++
+Requires: libgsmhr0 = %{version}
+
+%description -n libgsmhr-devel
+libgsmhr contains a standard implementation of the European GSM 06.20
+provisional standard for GSM Half Rate speech speech transcoding.
+
+This subpackage contains libraries and header files for developing
+applications that want to make use of libgsmhr.
+%endif
+
+%package -n libosmogapk%{sover}
+Summary: Shared library part of GSM Audio Pocket Knife (GAPK)
+License: GPL-3.0-only
+Group: Development/Libraries/C and C++
+
+%description -n libosmogapk%{sover}
+Shared library part of GSM Audio Pocket Knife (GAPK).
+
+%package -n libosmogapk-devel
+Summary: Development files for the GAPK library
+License: GPL-3.0-only
+Group: Development/Libraries/C and C++
+Requires: libosmogapk%{sover} = %{version}
+
+%description -n libosmogapk-devel
+Shared library part of GSM Audio Pocket Knife (GAPK).
+
+This subpackage contains the development files for the Osmocom GAPK
+library.
+
+%prep
+%setup -q
+%if 0%{with_gsmhr}
+%patch1 -p1
+cp %{SOURCE1} libgsmhr/
+%endif
+
+%build
+echo "%{version}" >.tarball-version
+autoreconf -fi
+%configure \
+%if 0%{with_gsmhr}
+ --enable-gsmhr \
+%endif
+ --disable-static
+make V=1 %{?_smp_mflags}
+
+%install
+%make_install
+find %{buildroot} -type f -name "*.la" -delete -print
+
+%check
+%if 0%{with_gsmhr}
+## GSM HR tests (6,9,13,14) are known to be broken - https://osmocom.org/issues/2514
+make %{?_smp_mflags} check || :
+%else
+make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
+%endif
+
+%if 0%{with_gsmhr}
+%post -n libgsmhr0 -p /sbin/ldconfig
+%postun -n libgsmhr0 -p /sbin/ldconfig
+%endif
+
+%post -n libosmogapk%{sover} -p /sbin/ldconfig
+%postun -n libosmogapk%{sover} -p /sbin/ldconfig
+
+%files
+%doc COPYING
+%{_bindir}/osmo-gapk
+
+%if 0%{with_gsmhr}
+%files -n libgsmhr0
+%{_libdir}/libgsmhr.so.0*
+
+%files -n libgsmhr-devel
+%{_libdir}/libgsmhr.so
+%endif
+
+%files -n libosmogapk%{sover}
+%{_libdir}/libosmogapk.so.%{sover}*
+
+%files -n libosmogapk-devel
+%dir %{_includedir}/osmocom/
+%{_includedir}/osmocom/%{name}/
+%{_libdir}/libosmogapk.so
+%{_libdir}/pkgconfig/libosmogapk.pc
+
+%changelog
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index cf53c3a..2e9035d 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -38,5 +38,6 @@ autoreconf --install --force
$MAKE $PARALLEL_MAKE
LD_LIBRARY_PATH="$inst/lib" $MAKE check || cat-testlogs.sh
LD_LIBRARY_PATH="$inst/lib" DISTCHECK_CONFIGURE_FLAGS="" $MAKE distcheck || cat-testlogs.sh
+$MAKE maintainer-clean
osmo-clean-workspace.sh
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..4cbf688
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+gapk (1.1) unstable; urgency=medium
+
+ * Initial debian packaging
+
+ -- Oliver Smith <osmith@sysmocom.de> Mon, 18 Mar 2024 13:15:22 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+10
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..556bbf8
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,37 @@
+Source: gapk
+Section: net
+Priority: optional
+Maintainer: Osmocom team <openbsc@lists.osmocom.org>
+Build-Depends: debhelper (>= 10),
+ dh-autoreconf,
+ autotools-dev,
+ autoconf,
+ automake,
+ libtool,
+ pkg-config,
+ libasound2-dev,
+ libgsm1-dev,
+ libosmocore-dev (>= 0.3.2)
+Standards-Version: 4.1.4
+Vcs-Browser: https://gitea.osmocom.org/osmocom/gapk
+Vcs-Git: https://gerrit.osmocom.org/gapk
+Homepage: https://osmocom.org/projects/gapk/wiki/Gapk
+
+Package: gapk
+Architecture: any
+Multi-Arch: foreign
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: GSM Audio Pocket Knife converts between GSM related codecs
+
+Package: libosmogapk0
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Description: GSM Audio Pocket Knife converts between GSM related codecs
+
+Package: libosmogapk-dev
+Section: libdevel
+Architecture: any
+Depends: libosmogapk0 (= ${binary:Version}), ${misc:Depends}
+Description: GSM Audio Pocket Knife converts between GSM related codecs
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..8d7bd0c
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,23 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: gapk
+Source: https://gitea.osmocom.org/osmocom/gapk
+
+Files: *
+License: GPL-3.0+
+
+License: GPL-3.0+
+ This program 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.
+ .
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General Public License
+ Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
diff --git a/debian/gapk.install b/debian/gapk.install
new file mode 100644
index 0000000..1df36c6
--- /dev/null
+++ b/debian/gapk.install
@@ -0,0 +1 @@
+usr/bin/*
diff --git a/debian/libosmogapk-dev.install b/debian/libosmogapk-dev.install
new file mode 100644
index 0000000..ab755d6
--- /dev/null
+++ b/debian/libosmogapk-dev.install
@@ -0,0 +1,3 @@
+usr/include/*
+usr/lib/*/pkgconfig/libosmogapk.pc
+usr/lib/*/*.so
diff --git a/debian/libosmogapk0.install b/debian/libosmogapk0.install
new file mode 100644
index 0000000..3de3b10
--- /dev/null
+++ b/debian/libosmogapk0.install
@@ -0,0 +1 @@
+usr/lib/*/*.so.*
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..c854d74
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,12 @@
+#!/usr/bin/make -f
+
+%:
+ dh $@ --with autoreconf
+
+override_dh_auto_configure:
+ touch libgsmhr/.downloaded # Don't fetch 3GPP sources
+ dh_auto_configure
+
+# Print test results in case of a failure
+override_dh_auto_test:
+ dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/include/osmocom/gapk/get_cycles.h b/include/osmocom/gapk/get_cycles.h
index 40ac570..25376a1 100644
--- a/include/osmocom/gapk/get_cycles.h
+++ b/include/osmocom/gapk/get_cycles.h
@@ -103,6 +103,16 @@ static inline cycles_t get_cycles()
#endif
return ret & ~TICK_PRIV_BIT;
}
+#elif defined(__aarch64__)
+
+typedef unsigned long cycles_t;
+static inline cycles_t get_cycles(void)
+{
+ cycles_t cval;
+ asm volatile("isb" : : : "memory");
+ asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+ return cval;
+}
#elif defined(__PPC__)
#define CPU_FTR_601 0x00000100
typedef unsigned long cycles_t;
diff --git a/libgsmhr/Makefile.am b/libgsmhr/Makefile.am
index f36d759..ffbde21 100644
--- a/libgsmhr/Makefile.am
+++ b/libgsmhr/Makefile.am
@@ -1,3 +1,8 @@
+# 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
+
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS = -fPIC -Wall ${SYMBOL_VISIBILITY}
@@ -6,8 +11,6 @@ EXTRA_DIST = \
patches \
$(NULL)
-LIBVERSION=0:0:0
-
REFSRC_PATH=refsrc
REFSRC_SRC=refsrc/dtx.c refsrc/globdefs.c refsrc/host.c refsrc/sp_enc.c refsrc/sp_rom.c refsrc/vad.c refsrc/err_conc.c refsrc/homing.c refsrc/mathdp31.c refsrc/sp_dec.c refsrc/sp_frm.c refsrc/sp_sfrm.c
@@ -18,10 +21,11 @@ ${REFSRC_PATH}/.downloaded:
done
touch $@
-$(REFSRC_SRC) libgsmhr.c: ${REFSRC_PATH}/.downloaded
+$(REFSRC_SRC): ${REFSRC_PATH}/.downloaded
lib_LTLIBRARIES = libgsmhr.la
libgsmhr_la_SOURCES = $(REFSRC_SRC) libgsmhr.c
+libgsmhr_la_LDFLAGS = -version-info $(LIBVERSION)
libgsmhr_la_LIBADD = -ldl
clean-local:
@@ -29,3 +33,7 @@ clean-local:
distclean-local:
-rm -rf ${REFSRC_PATH}/
+
+# exclude files downloaded by fetch_sources.py
+dist-hook:
+ -rm -rf $(distdir)/$(REFSRC_PATH)
diff --git a/libgsmhr/fetch_sources.py b/libgsmhr/fetch_sources.py
index 6fb1b8e..178125c 100755
--- a/libgsmhr/fetch_sources.py
+++ b/libgsmhr/fetch_sources.py
@@ -1,35 +1,30 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
-import urllib2
+import logging as log
+import urllib.request
+import io
import os
import sys
import zipfile
-try:
- import cStringIO as StringIO
-except:
- import StringIO
+URL = "http://www.3gpp.org/ftp/Specs/archive/06_series/06.06/0606-421.zip"
-SRC = "http://www.3gpp.org/ftp/Specs/archive/06_series/06.06/0606-421.zip"
-HDR = {
- "User-Agent": "Mozilla/5.0 (X11; ArchLinux; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
-}
+def get_zipfile(data: bytes) -> zipfile.ZipFile:
+ return zipfile.ZipFile(io.BytesIO(data), 'r')
-def get_zipfile(data):
- return zipfile.ZipFile(StringIO.StringIO(data))
-
-def get_subfile_data(data, filename):
+def get_subfile_data(data: bytes, filename: str):
+ log.debug('Unpacking \'%s\'', filename)
z = get_zipfile(data)
return z.read(filename)
def process_file(z, e):
- fh = open(os.path.basename(e.filename.lower()), 'w')
- d = z.read(e).replace('\r','')
+ log.debug('Processing file \'%s\'', e.filename.lower())
+ fh = open(os.path.basename(e.filename.lower()), 'wb')
+ d = z.read(e).replace(b'\r', b'')
fh.write(d)
fh.close()
@@ -38,7 +33,7 @@ def main(*args):
# Args
if len(args) != 2:
- print "Usage: %s target_dir" % args[0]
+ print("Usage: %s target_dir" % args[0])
return
tgt = args[1]
@@ -49,9 +44,16 @@ def main(*args):
os.chdir(tgt)
# Get the original data
- req = urllib2.Request(SRC, headers = HDR)
- u = urllib2.urlopen(req)
- d = u.read()
+ log.info('Requesting file: %s', URL)
+ with urllib.request.urlopen(URL) as response:
+ log.debug('Response code: %d', response.code)
+ assert response.code == 200
+
+ for h in ('Last-Modified', 'Content-Type', 'Content-Length'):
+ log.debug('%s: %s', h, response.getheader(h))
+
+ log.info('Downloading %d bytes...', response.length)
+ d = response.read()
# Get DISK.zip
d = get_subfile_data(d, 'DISK.zip')
@@ -67,5 +69,7 @@ def main(*args):
process_file(z, e)
+log.basicConfig(format='[%(levelname)s] %(filename)s:%(lineno)d %(message)s', level=log.DEBUG)
+
if __name__ == '__main__':
main(*sys.argv)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8fdeff7..550e3b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,19 +20,22 @@ AM_CFLAGS = \
lib_LTLIBRARIES = libosmogapk.la
EXTRA_DIST = libosmogapk.map
-libosmogapk_la_LDFLAGS = \
+libosmogapk_la_LIBADD = \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCODEC_LIBS) \
${OPENCORE_AMRNB_LIBS} \
${LIBGSM_LIBS} \
$(LIBALSA_LIBS) \
+ $(NULL)
+
+libosmogapk_la_LDFLAGS = \
$(LTLDFLAGS_OSMOGAPK) \
-version-info $(LIBVERSION) \
-no-undefined \
$(NULL)
if ENABLE_GSMHR
-libosmogapk_la_LIBADD = $(top_builddir)/libgsmhr/libgsmhr.la
+libosmogapk_la_LIBADD += $(top_builddir)/libgsmhr/libgsmhr.la
endif
# Processing queue implementation
@@ -94,10 +97,7 @@ osmo_gapk_SOURCES = \
app_osmo_gapk.c \
$(NULL)
-osmo_gapk_LDFLAGS = \
- $(LIBOSMOCORE_LIBS) \
- $(NULL)
-
osmo_gapk_LDADD = \
libosmogapk.la \
+ $(LIBOSMOCORE_LIBS) \
$(NULL)
diff --git a/src/app_osmo_gapk.c b/src/app_osmo_gapk.c
index 91647ee..1e4e9a0 100644
--- a/src/app_osmo_gapk.c
+++ b/src/app_osmo_gapk.c
@@ -36,6 +36,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/select.h>
#include <osmocom/gapk/common.h>
#include <osmocom/gapk/codecs.h>
@@ -67,6 +68,7 @@ struct gapk_options
/* RTP payload type */
uint8_t rtp_pt_in, rtp_pt_out;
+ int throttle;
int benchmark;
int verbose;
};
@@ -75,6 +77,8 @@ struct gapk_state
{
struct gapk_options opts;
struct osmo_gapk_pq *pq;
+ struct osmo_fd timerfd; /* for optional throttling */
+ unsigned int num_frames;
int exit;
struct {
@@ -139,6 +143,7 @@ print_help(char *progname)
fprintf(stdout, " -p --rtp-pt-in=TYPE\t\tRTP payload type for incoming frames\n");
fprintf(stdout, " -P --rtp-pt-out=TYPE\t\tRTP payload type for outgoing frames\n");
fprintf(stdout, " -b, --enable-benchmark\tEnable codec benchmarking\n");
+ fprintf(stdout, " -t, --throttle\tEnable throttling (one codec frame every 20ms)\n");
fprintf(stdout, " -v, --verbose\t\t\tEnable debug messages\n");
fprintf(stdout, "\n");
@@ -211,10 +216,11 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
{"rtp-pt-in", 1, 0, 'p'},
{"rtp-pt-out", 1, 0, 'P'},
{"enable-benchmark", 0, 0, 'b'},
+ {"throttle", 0, 0, 't'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
};
- const char *short_options = "i:o:I:O:f:g:p:P:bvh"
+ const char *short_options = "i:o:I:O:f:g:p:P:btvh"
#ifdef HAVE_ALSA
"a:A:"
#endif
@@ -312,6 +318,10 @@ parse_options(struct gapk_state *state, int argc, char *argv[])
opt->benchmark = 1;
break;
+ case 't':
+ opt->throttle = 1;
+ break;
+
case 'v':
log_parse_category_mask(osmo_stderr_target, "DAPP");
opt->verbose = 1;
@@ -668,22 +678,65 @@ make_processing_chain(struct gapk_state *gs)
}
static int
+timerfd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+ struct gapk_state *gs = ofd->data;
+ uint64_t expire_count;
+ int rc;
+
+ rc = read(ofd->fd, (void *)&expire_count, sizeof(expire_count));
+ if (rc < 0 && errno == EAGAIN)
+ return 0;
+ OSMO_ASSERT(rc == sizeof(expire_count));
+
+ while (expire_count--) {
+ gs->num_frames++;
+ rc = osmo_gapk_pq_execute(gs->pq);
+ if (rc < 0)
+ gs->exit = true;
+ }
+ return 0;
+}
+
+static int
run(struct gapk_state *gs)
{
struct osmo_gapk_pq_item *item;
- int rv, frames;
+ int rv;
rv = osmo_gapk_pq_prepare(gs->pq);
if (rv)
return rv;
- for (frames = 0; !gs->exit; frames++) {
- rv = osmo_gapk_pq_execute(gs->pq);
- if (rv)
- break;
+ if (!gs->opts.throttle) {
+ for (gs->num_frames = 0; !gs->exit; gs->num_frames++) {
+ rv = osmo_gapk_pq_execute(gs->pq);
+ if (rv)
+ break;
+ }
+ } else {
+ /* setup timerfd based processing */
+ const struct timespec interval = {
+ .tv_sec = 0,
+ .tv_nsec = 20*1000*1000,
+ };
+ gs->timerfd.fd = -1;
+ rv = osmo_timerfd_setup(&gs->timerfd, timerfd_cb, gs);
+ OSMO_ASSERT(rv == 0);
+ rv = osmo_timerfd_schedule(&gs->timerfd, NULL, &interval);
+ OSMO_ASSERT(rv == 0);
+
+ /* actual processing loop */
+ while (!gs->exit)
+ osmo_select_main(0);
+
+ /* cleanup */
+ osmo_timerfd_disable(&gs->timerfd);
+ close(gs->timerfd.fd);
+ osmo_fd_unregister(&gs->timerfd);
}
- LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", frames);
+ LOGP(DAPP, LOGL_NOTICE, "Processed %d frames\n", gs->num_frames);
/* Wait for sink to process buffers */
item = llist_last_entry(&gs->pq->items, struct osmo_gapk_pq_item, list);
@@ -693,7 +746,7 @@ run(struct gapk_state *gs)
continue;
}
- return frames > 0 ? 0 : rv;
+ return gs->num_frames > 0 ? 0 : rv;
}
diff --git a/src/fmt_rtp_amr.c b/src/fmt_rtp_amr.c
index a6a3c9f..4982c83 100644
--- a/src/fmt_rtp_amr.c
+++ b/src/fmt_rtp_amr.c
@@ -27,6 +27,9 @@
#include <osmocom/gapk/formats.h>
#include <osmocom/gapk/utils.h>
+/* AMR SID frame is according to TS 126 101 4.2.3 */
+static const uint8_t SILENCE[] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00};
+
/* conversion function: RTP payload -> canonical format */
static int
rtp_amr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
@@ -42,6 +45,12 @@ rtp_amr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
static int
rtp_amr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
+ /* Detect severely damaged frames according to RFC4867 4.3.2 */
+ if ((src[1] & 0x04) == 0) {
+ src = SILENCE;
+ src_len = sizeof(SILENCE);
+ }
+
/* skip Payload Header according to RFC4867 4.4.1 */
memcpy(dst, src+1, src_len-1);
diff --git a/src/fmt_rtp_efr.c b/src/fmt_rtp_efr.c
index accfd4f..214010e 100644
--- a/src/fmt_rtp_efr.c
+++ b/src/fmt_rtp_efr.c
@@ -30,6 +30,17 @@
#define EFR_LEN 31
#define EFR_MAGIC 0xc
+/* EFR encoding starts with 0xc, if all other bits are 0 the packet is probably damaged */
+static const uint8_t DAMAGED_PACKET[EFR_LEN] = {
+ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/* EFR SID frame is according to TS 101 318 5.3.2 */
+static const uint8_t SILENCE[EFR_LEN] = {
+ 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
/* conversion function: RTP payload -> canonical format */
static int
rtp_efr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
@@ -52,7 +63,14 @@ rtp_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
int i;
- assert(src_len == EFR_LEN);
+ /* broken RTP frames may be short; substitute empty frame */
+ if (src_len != EFR_LEN) {
+ memset(dst, 0, EFR_CANON_LEN);
+ return EFR_CANON_LEN;
+ }
+
+ if (!memcmp(DAMAGED_PACKET, src, EFR_LEN))
+ src = SILENCE;
for (i=0; i<(EFR_LEN-1); i++)
dst[i] = (src[i] << 4) | (src[i+1] >> 4);
diff --git a/src/fmt_rtp_hr_etsi.c b/src/fmt_rtp_hr_etsi.c
index 9ed9b22..0b7e392 100644
--- a/src/fmt_rtp_hr_etsi.c
+++ b/src/fmt_rtp_hr_etsi.c
@@ -42,7 +42,11 @@ static int
rtp_hr_etsi_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
/* according to TS 101 318 */
- assert(src_len == HR_CANON_LEN);
+ /* broken RTP frames may be short; substitute empty frame */
+ if (src_len != HR_CANON_LEN) {
+ memset(dst, 0, HR_CANON_LEN);
+ return HR_CANON_LEN;
+ }
memcpy(dst, src, src_len);
return HR_CANON_LEN;
diff --git a/src/fmt_rtp_hr_ietf.c b/src/fmt_rtp_hr_ietf.c
index 4ee548f..a840d4b 100644
--- a/src/fmt_rtp_hr_ietf.c
+++ b/src/fmt_rtp_hr_ietf.c
@@ -60,7 +60,11 @@ static int
rtp_hr_ietf_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
{
/* according to RFC5993 */
- assert(src_len == HR_LEN);
+ /* broken RTP frames may be short; substitute empty frame */
+ if (src_len != HR_LEN) {
+ memset(dst, 0, HR_LEN);
+ return HR_CANON_LEN;
+ }
/* Remove ToC byte */
memcpy(dst, src+1, HR_CANON_LEN);
diff --git a/src/pq_alsa.c b/src/pq_alsa.c
index 3550221..50479e6 100644
--- a/src/pq_alsa.c
+++ b/src/pq_alsa.c
@@ -176,7 +176,7 @@ out_print:
* \param pq Processing Queue to add the ALSA input to
* \param[in] hwdev ALSA hardware device to use
* \param[in] blk_len block length to be read from device
- * \returns 0 on sucess; negative on error */
+ * \returns 0 on success; negative on error */
int
osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len)
{
@@ -190,7 +190,7 @@ osmo_gapk_pq_queue_alsa_input(struct osmo_gapk_pq *pq, const char *hwdev, unsign
* \param pq Processing Queue to add the ALSA output to
* \param[in] hwdev ALSA hardware device to use
* \param[in] blk_len block length to be written to device
- * \returns 0 on sucess; negative on error */
+ * \returns 0 on success; negative on error */
int
osmo_gapk_pq_queue_alsa_output(struct osmo_gapk_pq *pq, const char *hwdev, unsigned int blk_len)
{
diff --git a/src/pq_file.c b/src/pq_file.c
index 22dc9cd..d496eec 100644
--- a/src/pq_file.c
+++ b/src/pq_file.c
@@ -103,7 +103,7 @@ pq_queue_file_op(struct osmo_gapk_pq *pq, FILE *fh, unsigned int blk_len, int in
* \param pq Processing Queue to add the input file to
* \param[in] src caller-fopen()ed input file
* \param[in] blk_len block length to be read from file
- * \returns 0 on sucess; negative on error */
+ * \returns 0 on success; negative on error */
int
osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int blk_len)
{
@@ -117,7 +117,7 @@ osmo_gapk_pq_queue_file_input(struct osmo_gapk_pq *pq, FILE *src, unsigned int b
* \param pq Processing Queue to add the output file to
* \param[in] dst caller-fopen()ed output file
* \param[in] blk_len block length to be written to file
- * \returns 0 on sucess; negative on error */
+ * \returns 0 on success; negative on error */
int
osmo_gapk_pq_queue_file_output(struct osmo_gapk_pq *pq, FILE *dst, unsigned int blk_len)
{
diff --git a/src/pq_rtp.c b/src/pq_rtp.c
index 81eeb19..a5543a6 100644
--- a/src/pq_rtp.c
+++ b/src/pq_rtp.c
@@ -30,33 +30,21 @@
#include <osmocom/gapk/codecs.h>
#include <osmocom/gapk/formats.h>
#include <osmocom/gapk/procqueue.h>
-
-#ifndef __BYTE_ORDER
-# ifdef __APPLE__
-# define __BYTE_ORDER __DARWIN_BYTE_ORDER
-# define __LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
-# define __BIG_ENDIAN __DARWIN_BIG_ENDIAN
-# else
-# error "__BYTE_ORDER should be defined by someone"
-# endif
-#endif
+#include <osmocom/core/endian.h>
/* according to RFC 3550 */
struct rtp_hdr {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+#if OSMO_IS_LITTLE_ENDIAN
uint8_t csrc_count:4,
extension:1,
padding:1,
version:2;
uint8_t payload_type:7,
marker:1;
-#elif __BYTE_ORDER == __BIG_ENDIAN
- uint8_t version:2,
- padding:1,
- extension:1,
- csrc_count:4;
- uint8_t marker:1,
- payload_type:7;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t version:2, padding:1, extension:1, csrc_count:4;
+ uint8_t marker:1, payload_type:7;
#endif
uint16_t sequence;
uint32_t timestamp;
@@ -116,7 +104,7 @@ pq_cb_rtp_input(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_l
payload = buf + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
payload_len = rv - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
if (payload_len < 0) {
- rtp_err("non-existant RTP payload length %d\n", payload_len);
+ rtp_err("non-existent RTP payload length %d\n", payload_len);
return -1;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dee4060..e0a3c96 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,6 +10,8 @@ AM_CFLAGS = \
$(LIBOSMOCODEC_CFLAGS) \
$(NULL)
+AM_LDFLAGS = -no-install
+
check_PROGRAMS = \
procqueue/pq_test \
io/pq_file_test \