mirror of https://gerrit.osmocom.org/gapk
Add AMR codec support
After merging this change, there is support for the AMR codec (by means of libopencore-amr, which is already used for EFR). In terms of gapk formats, we introdude * the "amr-opencore" format, which serves both as the canonical format, and as the input format to opencore-amrnb itself. * the "rtp-amr" format, which is the payload of RFC4867 octet-aligned mode You can use the following command for a real-time RTP playback for AMR frames: ./gapk -I 0.0.0.0/30000 -f rtp-amr -A default -g rawpcm-s16le
This commit is contained in:
parent
494d92c3c7
commit
8b01f0ca05
|
@ -33,6 +33,7 @@ enum codec_type {
|
|||
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,
|
||||
};
|
||||
|
||||
|
|
|
@ -48,6 +48,10 @@ enum format_type {
|
|||
FMT_TI_FR,
|
||||
FMT_TI_EFR,
|
||||
|
||||
/* AMR encoded data, variable length */
|
||||
FMT_AMR_OPENCORE,
|
||||
FMT_RTP_AMR,
|
||||
|
||||
_FMT_MAX,
|
||||
};
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ AM_LDFLAGS=$(LIBOSMOCODEC_LIBS) $(LIBOSMOCORE_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_rawpcm.c fmt_ti.c benchmark.c \
|
||||
codecs.c codec_pcm.c codec_hr.c codec_fr.c codec_efr.c
|
||||
fmt_amr_opencore.c fmt_rtp_amr.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
|
||||
|
||||
bin_PROGRAMS = gapk
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/* AMR (GSM 06.90) codec */
|
||||
/* (C) 2017 Harald Welte <laforge@gnumonks.org> */
|
||||
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/benchmark.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCORE_AMRNB
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <opencore-amrnb/interf_dec.h>
|
||||
#include <opencore-amrnb/interf_enc.h>
|
||||
|
||||
struct codec_amr_state {
|
||||
void *encoder;
|
||||
void *decoder;
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
codec_amr_init(void)
|
||||
{
|
||||
struct codec_amr_state *st;
|
||||
|
||||
st = calloc(1, sizeof(*st));
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->encoder = Encoder_Interface_init(0);
|
||||
st->decoder = Decoder_Interface_init();
|
||||
|
||||
return (void *)st;
|
||||
}
|
||||
|
||||
static void
|
||||
codec_amr_exit(void *state)
|
||||
{
|
||||
struct codec_amr_state *st = state;
|
||||
|
||||
Decoder_Interface_exit(st->decoder);
|
||||
Encoder_Interface_exit(st->encoder);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
codec_amr_encode(void *state, uint8_t *cod, const uint8_t *pcm, unsigned int pcm_len)
|
||||
{
|
||||
struct codec_amr_state *st = state;
|
||||
int rv;
|
||||
|
||||
BENCHMARK_START;
|
||||
rv = Encoder_Interface_Encode(
|
||||
st->encoder,
|
||||
MR122,
|
||||
(const short*) pcm,
|
||||
(unsigned char*) cod,
|
||||
1
|
||||
);
|
||||
BENCHMARK_STOP(CODEC_EFR, 1);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
codec_amr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod_len)
|
||||
{
|
||||
struct codec_amr_state *st = state;
|
||||
|
||||
printf("%s(): %u bytes in\n", __func__, cod_len);
|
||||
|
||||
BENCHMARK_START;
|
||||
Decoder_Interface_Decode(
|
||||
st->decoder,
|
||||
(const unsigned char*) cod,
|
||||
(short *) pcm,
|
||||
0
|
||||
);
|
||||
BENCHMARK_STOP(CODEC_EFR, 0);
|
||||
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENCORE_AMRNB */
|
||||
|
||||
|
||||
const struct codec_desc codec_amr_desc = {
|
||||
.type = CODEC_AMR,
|
||||
.name = "amr",
|
||||
.description = "GSM 26.071 Adaptive Multi Rate codec",
|
||||
.canon_frame_len = 0,
|
||||
#ifdef HAVE_OPENCORE_AMRNB
|
||||
.codec_enc_format_type = FMT_AMR_OPENCORE,
|
||||
.codec_dec_format_type = FMT_AMR_OPENCORE,
|
||||
.codec_init = codec_amr_init,
|
||||
.codec_exit = codec_amr_exit,
|
||||
.codec_encode = codec_amr_encode,
|
||||
.codec_decode = codec_amr_decode,
|
||||
#endif
|
||||
};
|
|
@ -26,6 +26,7 @@ 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;
|
||||
|
||||
|
||||
const struct codec_desc *
|
||||
|
@ -36,6 +37,7 @@ codec_get_from_type(enum codec_type type)
|
|||
case CODEC_HR: return &codec_hr_desc;
|
||||
case CODEC_FR: return &codec_fr_desc;
|
||||
case CODEC_EFR: return &codec_efr_desc;
|
||||
case CODEC_AMR: return &codec_amr_desc;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* Input format to libopencore-amrnb: Exactly like our canonical AMR */
|
||||
/* (C) 2017 Harald Welte <laforge@gnumonks.org> */
|
||||
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
static int
|
||||
amr_opencore_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
memcpy(dst, src, src_len);
|
||||
return src_len;
|
||||
}
|
||||
|
||||
static int
|
||||
amr_opencore_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
memcpy(dst, src, src_len);
|
||||
return src_len;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_amr_opencore = {
|
||||
.type = FMT_AMR_OPENCORE,
|
||||
.codec_type = CODEC_AMR,
|
||||
.name = "amr-opencore",
|
||||
.description = "Input format to libopencore-amrnb",
|
||||
|
||||
.frame_len = 0,
|
||||
.conv_from_canon = amr_opencore_from_canon,
|
||||
.conv_to_canon = amr_opencore_to_canon,
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
/* AMR RTP Payload according to RFC4867. Only one codec frame per RTP */
|
||||
/* (C) 2017 by Harald Welte <laforge@gnumonks.org> */
|
||||
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/codec/codec.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
/* conversion function: RTP payload -> canonical format */
|
||||
static int
|
||||
rtp_amr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
/* add Payload Header according to RFC4867 4.4.1 */
|
||||
dst[0] = 0xf0; /* no request */
|
||||
memcpy(dst+1, src, src_len);
|
||||
|
||||
return src_len+1;
|
||||
}
|
||||
|
||||
/* conversion function: canonical format -> RTP payload */
|
||||
static int
|
||||
rtp_amr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
/* skip Payload Header according to RFC4867 4.4.1 */
|
||||
memcpy(dst, src+1, src_len-1);
|
||||
|
||||
return src_len-1;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_rtp_amr = {
|
||||
.type = FMT_RTP_AMR,
|
||||
.codec_type = CODEC_AMR,
|
||||
.name = "rtp-amr",
|
||||
.description = "RTP payload for AMR according to RFC4867",
|
||||
|
||||
.frame_len = 0,
|
||||
.conv_from_canon = rtp_amr_from_canon,
|
||||
.conv_to_canon = rtp_amr_to_canon,
|
||||
};
|
|
@ -34,6 +34,8 @@ 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;
|
||||
|
||||
static const struct format_desc *supported_formats[_FMT_MAX] = {
|
||||
[FMT_INVALID] = NULL,
|
||||
|
@ -48,6 +50,8 @@ static const struct format_desc *supported_formats[_FMT_MAX] = {
|
|||
[FMT_TI_HR] = &fmt_ti_hr,
|
||||
[FMT_TI_FR] = &fmt_ti_fr,
|
||||
[FMT_TI_EFR] = &fmt_ti_efr,
|
||||
[FMT_AMR_OPENCORE] = &fmt_amr_opencore,
|
||||
[FMT_RTP_AMR] = &fmt_rtp_amr,
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue