mirror of https://gerrit.osmocom.org/gapk
prepare gapk for dealing with variable-length frames
The existing architecture was modelled around fixed-length codec frame sizes, which of course fails with multi-rate codecs such as AMR.
This commit is contained in:
parent
62688b60c2
commit
5912848d2e
|
@ -38,7 +38,7 @@ enum codec_type {
|
|||
|
||||
#include <gapk/formats.h> /* need to import here because or enum interdep */
|
||||
|
||||
typedef int (*codec_conv_cb_t)(void *state, uint8_t *dst, const uint8_t *src);
|
||||
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;
|
||||
|
|
|
@ -53,7 +53,7 @@ enum format_type {
|
|||
|
||||
#include <gapk/codecs.h> /* need to import here because or enum interdep */
|
||||
|
||||
typedef int (*fmt_conv_cb_t)(uint8_t *dst, const uint8_t *src);
|
||||
typedef int (*fmt_conv_cb_t)(uint8_t *dst, const uint8_t *src, unsigned int src_len);
|
||||
|
||||
struct format_desc {
|
||||
enum format_type type;
|
||||
|
|
|
@ -29,7 +29,7 @@ struct pq_item {
|
|||
int len_in;
|
||||
int len_out;
|
||||
void *state;
|
||||
int (*proc)(void *state, uint8_t *out, const uint8_t *in);
|
||||
int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len);
|
||||
void (*exit)(void *state);
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#ifdef HAVE_OPENCORE_AMRNB
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <opencore-amrnb/interf_dec.h>
|
||||
#include <opencore-amrnb/interf_enc.h>
|
||||
|
@ -64,11 +65,12 @@ codec_efr_exit(void *state)
|
|||
}
|
||||
|
||||
static int
|
||||
codec_efr_encode(void *state, uint8_t *cod, const uint8_t *pcm)
|
||||
codec_efr_encode(void *state, uint8_t *cod, const uint8_t *pcm, unsigned int pcm_len)
|
||||
{
|
||||
struct codec_efr_state *st = state;
|
||||
int rv;
|
||||
|
||||
assert(pcm_len == PCM_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
rv = Encoder_Interface_Encode(
|
||||
st->encoder,
|
||||
|
@ -79,14 +81,18 @@ codec_efr_encode(void *state, uint8_t *cod, const uint8_t *pcm)
|
|||
);
|
||||
BENCHMARK_STOP(CODEC_EFR, 1);
|
||||
|
||||
return rv != 32;
|
||||
if (rv != 32)
|
||||
return -1;
|
||||
|
||||
return EFR_CANON_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
codec_efr_decode(void *state, uint8_t *pcm, const uint8_t *cod)
|
||||
codec_efr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod_len)
|
||||
{
|
||||
struct codec_efr_state *st = state;
|
||||
|
||||
assert(cod_len == EFR_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
Decoder_Interface_Decode(
|
||||
st->decoder,
|
||||
|
@ -96,7 +102,7 @@ codec_efr_decode(void *state, uint8_t *pcm, const uint8_t *cod)
|
|||
);
|
||||
BENCHMARK_STOP(CODEC_EFR, 0);
|
||||
|
||||
return 0;
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENCORE_AMRNB */
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/benchmark.h>
|
||||
|
||||
|
@ -50,28 +52,32 @@ codec_fr_exit(void *state)
|
|||
}
|
||||
|
||||
static int
|
||||
codec_fr_encode(void *state, uint8_t *cod, const uint8_t *pcm)
|
||||
codec_fr_encode(void *state, uint8_t *cod, const uint8_t *pcm, unsigned int pcm_len)
|
||||
{
|
||||
gsm gh = (gsm)state;
|
||||
uint8_t pcm_b[2*160]; /* local copy as libgsm src isn't const ! */
|
||||
memcpy(pcm_b, pcm, 2*160);
|
||||
uint8_t pcm_b[PCM_CANON_LEN]; /* local copy as libgsm src isn't const ! */
|
||||
assert(pcm_len == PCM_CANON_LEN);
|
||||
memcpy(pcm_b, pcm, PCM_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
gsm_encode(gh, (gsm_signal*)pcm, (gsm_byte*)cod);
|
||||
BENCHMARK_STOP(CODEC_FR, 1);
|
||||
return 0;
|
||||
return FR_CANON_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
codec_fr_decode(void *state, uint8_t *pcm, const uint8_t *cod)
|
||||
codec_fr_decode(void *state, uint8_t *pcm, const uint8_t *cod, unsigned int cod_len)
|
||||
{
|
||||
gsm gh = (gsm)state;
|
||||
uint8_t cod_b[33]; /* local copy as libgsm src isn't const ! */
|
||||
uint8_t cod_b[FR_CANON_LEN]; /* local copy as libgsm src isn't const ! */
|
||||
int rc;
|
||||
memcpy(cod_b, cod, 33);
|
||||
assert(cod_len == FR_CANON_LEN);
|
||||
memcpy(cod_b, cod, FR_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
rc = gsm_decode(gh, (gsm_byte*)cod_b, (gsm_signal*)pcm);
|
||||
BENCHMARK_STOP(CODEC_FR, 1);
|
||||
return rc;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBGSM */
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/benchmark.h>
|
||||
|
||||
|
@ -41,25 +43,31 @@ codec_hr_exit(void *_state)
|
|||
}
|
||||
|
||||
static int
|
||||
codec_hr_encode(void *_state, uint8_t *cod, const uint8_t *pcm)
|
||||
codec_hr_encode(void *_state, uint8_t *cod, const uint8_t *pcm, unsigned int pcm_len)
|
||||
{
|
||||
struct gsmhr *state = _state;
|
||||
int rc;
|
||||
assert(pcm_len == PCM_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
rc = gsmhr_encode(state, (int16_t *)cod, (const int16_t *)pcm);
|
||||
BENCHMARK_STOP(CODEC_HR, 1);
|
||||
return rc;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return HR_CANON_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
codec_hr_decode(void *_state, uint8_t *pcm, const uint8_t *cod)
|
||||
codec_hr_decode(void *_state, uint8_t *pcm, const uint8_t *cod, unsigned int cod_len)
|
||||
{
|
||||
struct gsmhr *state = _state;
|
||||
int rc;
|
||||
assert(cod_len == HR_CANON_LEN);
|
||||
BENCHMARK_START;
|
||||
rc = gsmhr_decode(state, (int16_t *)pcm, (const int16_t *)cod);
|
||||
BENCHMARK_STOP(CODEC_HR, 0);
|
||||
return rc;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBGSMHR */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <osmocom/codec/codec.h>
|
||||
|
||||
|
@ -25,13 +26,16 @@
|
|||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
#define EFR_LEN 32
|
||||
|
||||
/* conversion function: .amr file -> canonical format */
|
||||
static int
|
||||
amr_efr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
amr_efr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == EFR_CANON_LEN);
|
||||
|
||||
dst[ 0] = 0x3c;
|
||||
dst[31] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
|
@ -41,15 +45,17 @@ amr_efr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(&dst[1], di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return EFR_LEN;
|
||||
}
|
||||
|
||||
/* conversion function: canonical format -> .amr file */
|
||||
static int
|
||||
amr_efr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
amr_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == EFR_LEN);
|
||||
|
||||
if (src[0] != 0x3c)
|
||||
return -1;
|
||||
|
||||
|
@ -61,7 +67,7 @@ amr_efr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(&src[1], si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return EFR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_amr_efr = {
|
||||
|
@ -70,7 +76,7 @@ const struct format_desc fmt_amr_efr = {
|
|||
.name = "amr-efr",
|
||||
.description = "Classic .amr file containing EFR (=AMR 12.2k) data",
|
||||
|
||||
.frame_len = 32,
|
||||
.frame_len = EFR_LEN,
|
||||
.conv_from_canon = amr_efr_from_canon,
|
||||
.conv_to_canon = amr_efr_to_canon,
|
||||
|
||||
|
|
|
@ -17,36 +17,41 @@
|
|||
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/formats.h>
|
||||
|
||||
|
||||
#define GSM_LEN 33
|
||||
#define GSM_MAGIC 0xd
|
||||
|
||||
/* convert canonical -> .gsm */
|
||||
static int
|
||||
gsm_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
gsm_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == FR_CANON_LEN);
|
||||
|
||||
dst[0] = (GSM_MAGIC << 4) | (src[0] >> 4);
|
||||
for (i=1; i<33; i++)
|
||||
for (i=1; i<GSM_LEN; i++)
|
||||
dst[i] = (src[i-1] << 4) | (src[i] >> 4);
|
||||
|
||||
return 0;
|
||||
return GSM_LEN;
|
||||
}
|
||||
|
||||
/* convert .gsm -> canonical */
|
||||
static int
|
||||
gsm_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
gsm_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<32; i++)
|
||||
dst[i] = (src[i] << 4) | (src[i+1] >> 4);
|
||||
dst[32] = src[32] << 4;
|
||||
assert(src_len == GSM_LEN);
|
||||
|
||||
return 0;
|
||||
for (i=0; i<(GSM_LEN-1); i++)
|
||||
dst[i] = (src[i] << 4) | (src[i+1] >> 4);
|
||||
dst[GSM_LEN-1] = src[GSM_LEN-1] << 4;
|
||||
|
||||
return FR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_gsm = {
|
||||
|
@ -55,7 +60,7 @@ const struct format_desc fmt_gsm = {
|
|||
.name = "gsm",
|
||||
.description = "Classic .gsm file format",
|
||||
|
||||
.frame_len = 33,
|
||||
.frame_len = GSM_LEN,
|
||||
.conv_from_canon = gsm_from_canon,
|
||||
.conv_to_canon = gsm_to_canon,
|
||||
};
|
||||
|
|
|
@ -20,10 +20,14 @@
|
|||
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
#define HR_REF_DEC_LEN (22 * sizeof(uint16_t))
|
||||
#define HR_REF_ENC_LEN (20 * sizeof(uint16_t))
|
||||
|
||||
static const int params_unvoiced[] = {
|
||||
5, /* R0 */
|
||||
|
@ -122,11 +126,13 @@ hr_ref_to_canon(uint8_t *canon, const uint16_t *hr_ref)
|
|||
}
|
||||
|
||||
static int
|
||||
hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
uint16_t *hr_ref = (uint16_t *)dst;
|
||||
int rv;
|
||||
|
||||
assert(src_len == HR_CANON_LEN);
|
||||
|
||||
rv = hr_ref_from_canon(hr_ref, src);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
@ -136,28 +142,32 @@ hr_ref_dec_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
hr_ref[20] = 0; /* SID : 2 bit */
|
||||
hr_ref[21] = 0; /* TAF : 1 bit */
|
||||
|
||||
return 0;
|
||||
return HR_REF_DEC_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
hr_ref_dec_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
hr_ref_dec_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
const uint16_t *hr_ref = (const uint16_t *)src;
|
||||
int rv;
|
||||
|
||||
assert(src_len == HR_REF_DEC_LEN);
|
||||
|
||||
rv = hr_ref_to_canon(dst, hr_ref);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
return 0;
|
||||
return HR_CANON_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
uint16_t *hr_ref = (uint16_t *)dst;
|
||||
int rv;
|
||||
|
||||
assert(src_len == HR_CANON_LEN);
|
||||
|
||||
rv = hr_ref_from_canon(hr_ref, src);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
@ -165,20 +175,22 @@ hr_ref_enc_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
hr_ref[18] = 0; /* SP : 1 bit */
|
||||
hr_ref[19] = 0; /* VAD : 1 bit */
|
||||
|
||||
return 0;
|
||||
return HR_REF_ENC_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
hr_ref_enc_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
const uint16_t *hr_ref = (const uint16_t *)src;
|
||||
int rv;
|
||||
|
||||
assert(src_len == HR_REF_ENC_LEN);
|
||||
|
||||
rv = hr_ref_to_canon(dst, hr_ref);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
return 0;
|
||||
return HR_CANON_LEN;
|
||||
}
|
||||
|
||||
|
||||
|
@ -188,7 +200,7 @@ const struct format_desc fmt_hr_ref_dec = {
|
|||
.name = "hr-ref-dec",
|
||||
.description = "3GPP HR Reference decoder code parameters file format",
|
||||
|
||||
.frame_len = 22 * sizeof(uint16_t),
|
||||
.frame_len = HR_REF_DEC_LEN,
|
||||
.conv_from_canon = hr_ref_dec_from_canon,
|
||||
.conv_to_canon = hr_ref_dec_to_canon,
|
||||
};
|
||||
|
@ -199,7 +211,7 @@ const struct format_desc fmt_hr_ref_enc = {
|
|||
.name = "hr-ref-enc",
|
||||
.description = "3GPP HR Reference encoder code parameters file format",
|
||||
|
||||
.frame_len = 20 * sizeof(uint16_t),
|
||||
.frame_len = HR_REF_ENC_LEN,
|
||||
.conv_from_canon = hr_ref_enc_from_canon,
|
||||
.conv_to_canon = hr_ref_enc_to_canon,
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <osmocom/codec/codec.h>
|
||||
|
||||
|
@ -25,13 +26,18 @@
|
|||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
#define RACAL_HR_LEN 14
|
||||
#define RACAL_FR_LEN 33
|
||||
#define RACAL_EFR_LEN 31
|
||||
|
||||
static int
|
||||
racal_hr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_hr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i, voiced;
|
||||
const uint16_t *bit_mapping;
|
||||
|
||||
assert(src_len == HR_CANON_LEN);
|
||||
|
||||
voiced = (msb_get_bit(src, 34) << 1) | msb_get_bit(src, 35);
|
||||
|
||||
bit_mapping = voiced ?
|
||||
|
@ -44,15 +50,17 @@ racal_hr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
lsb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RACAL_HR_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
racal_hr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_hr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i, voiced;
|
||||
const uint16_t *bit_mapping;
|
||||
|
||||
assert(src_len == HR_CANON_LEN);
|
||||
|
||||
voiced = (lsb_get_bit(src, 94) << 1) | lsb_get_bit(src, 93);
|
||||
|
||||
bit_mapping = voiced ?
|
||||
|
@ -65,7 +73,7 @@ racal_hr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, lsb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RACAL_HR_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_racal_hr = {
|
||||
|
@ -74,17 +82,19 @@ const struct format_desc fmt_racal_hr = {
|
|||
.name = "racal-hr",
|
||||
.description = "Racal HR TCH/H recording",
|
||||
|
||||
.frame_len = 14,
|
||||
.frame_len = RACAL_HR_LEN,
|
||||
.conv_from_canon = racal_hr_from_canon,
|
||||
.conv_to_canon = racal_hr_to_canon,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
racal_fr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_fr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == FR_CANON_LEN);
|
||||
|
||||
dst[32] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<260; i++) {
|
||||
|
@ -93,14 +103,16 @@ racal_fr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
lsb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RACAL_FR_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
racal_fr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_fr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == RACAL_FR_LEN);
|
||||
|
||||
dst[32] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<260; i++) {
|
||||
|
@ -109,7 +121,7 @@ racal_fr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, lsb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return FR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_racal_fr = {
|
||||
|
@ -118,36 +130,40 @@ const struct format_desc fmt_racal_fr = {
|
|||
.name = "racal-fr",
|
||||
.description = "Racal FR TCH/F recording",
|
||||
|
||||
.frame_len = 33,
|
||||
.frame_len = RACAL_FR_LEN,
|
||||
.conv_from_canon = racal_fr_from_canon,
|
||||
.conv_to_canon = racal_fr_to_canon,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
racal_efr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_efr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == EFR_CANON_LEN);
|
||||
|
||||
dst[30] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<244; i++)
|
||||
lsb_put_bit(dst, i, msb_get_bit(src, i));
|
||||
|
||||
return 0;
|
||||
return RACAL_EFR_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
racal_efr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
racal_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == RACAL_EFR_LEN);
|
||||
|
||||
dst[30] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<244; i++)
|
||||
msb_put_bit(dst, i, lsb_get_bit(src, i));
|
||||
|
||||
return 0;
|
||||
return EFR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_racal_efr = {
|
||||
|
@ -156,7 +172,7 @@ const struct format_desc fmt_racal_efr = {
|
|||
.name = "racal-efr",
|
||||
.description = "Racal EFR TCH/F recording",
|
||||
|
||||
.frame_len = 31,
|
||||
.frame_len = RACAL_EFR_LEN,
|
||||
.conv_from_canon = racal_efr_from_canon,
|
||||
.conv_to_canon = racal_efr_to_canon,
|
||||
};
|
||||
|
|
|
@ -17,35 +17,40 @@
|
|||
* along with gapk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <gapk/codecs.h>
|
||||
#include <gapk/formats.h>
|
||||
|
||||
|
||||
static int
|
||||
rawpcm_s16le_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
rawpcm_s16le_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
const uint16_t *samples = (const uint16_t *)src;
|
||||
|
||||
assert(src_len == PCM_CANON_LEN);
|
||||
|
||||
for (i=0; i<160; i++) {
|
||||
uint16_t w = samples[i];
|
||||
dst[(i<<1) ] = w & 0xff;
|
||||
dst[(i<<1)+1] = (w >> 8) & 0xff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
rawpcm_s16le_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
rawpcm_s16le_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
uint16_t *samples = (uint16_t *)dst;
|
||||
|
||||
assert(src_len == PCM_CANON_LEN);
|
||||
|
||||
for (i=0; i<160; i++)
|
||||
samples[i] = (src[(i<<1)+1] << 8) | src[(i<<1)];
|
||||
|
||||
return 0;
|
||||
return PCM_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_rawpcm_s16le = {
|
||||
|
|
46
src/fmt_ti.c
46
src/fmt_ti.c
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <osmocom/codec/codec.h>
|
||||
|
||||
|
@ -33,14 +34,17 @@
|
|||
#include <gapk/formats.h>
|
||||
#include <gapk/utils.h>
|
||||
|
||||
#define TI_LEN 33
|
||||
|
||||
static int
|
||||
ti_hr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_hr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i, voiced;
|
||||
const uint16_t *bit_mapping;
|
||||
|
||||
memset(dst, 0x00, 33); /* Not even half the bits are written, so we pre-clear */
|
||||
assert(src_len == HR_CANON_LEN);
|
||||
|
||||
memset(dst, 0x00, TI_LEN); /* Not even half the bits are written, so we pre-clear */
|
||||
|
||||
voiced = (msb_get_bit(src, 34) << 1) | msb_get_bit(src, 35);
|
||||
|
||||
|
@ -54,15 +58,17 @@ ti_hr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
lsb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TI_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
ti_hr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_hr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i, voiced;
|
||||
const uint16_t *bit_mapping;
|
||||
|
||||
assert(src_len == TI_LEN);
|
||||
|
||||
voiced = (msb_get_bit(src, 94) << 1) | msb_get_bit(src, 93);
|
||||
|
||||
bit_mapping = voiced ?
|
||||
|
@ -75,7 +81,7 @@ ti_hr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return HR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_ti_hr = {
|
||||
|
@ -84,17 +90,19 @@ const struct format_desc fmt_ti_hr = {
|
|||
.name = "ti-hr",
|
||||
.description = "Texas Instrument HR TCH/H buffer format",
|
||||
|
||||
.frame_len = 33,
|
||||
.frame_len = TI_LEN,
|
||||
.conv_from_canon = ti_hr_from_canon,
|
||||
.conv_to_canon = ti_hr_to_canon,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
ti_fr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_fr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == FR_CANON_LEN);
|
||||
|
||||
dst[22] = dst[23] = 0x00; /* some bits won't be writter, pre-clear them */
|
||||
|
||||
for (i=0; i<260; i++) {
|
||||
|
@ -103,14 +111,16 @@ ti_fr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TI_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
ti_fr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_fr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == TI_LEN);
|
||||
|
||||
dst[32] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<260; i++) {
|
||||
|
@ -119,7 +129,7 @@ ti_fr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return FR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_ti_fr = {
|
||||
|
@ -128,17 +138,19 @@ const struct format_desc fmt_ti_fr = {
|
|||
.name = "ti-fr",
|
||||
.description = "Texas Instrument FR TCH/F buffer format",
|
||||
|
||||
.frame_len = 33,
|
||||
.frame_len = TI_LEN,
|
||||
.conv_from_canon = ti_fr_from_canon,
|
||||
.conv_to_canon = ti_fr_to_canon,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
ti_efr_from_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_efr_from_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == EFR_CANON_LEN);
|
||||
|
||||
memset(dst, 0x00, 33); /* pre-clear */
|
||||
|
||||
for (i=0; i<244; i++) {
|
||||
|
@ -169,14 +181,16 @@ ti_efr_from_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TI_LEN;
|
||||
}
|
||||
|
||||
static int
|
||||
ti_efr_to_canon(uint8_t *dst, const uint8_t *src)
|
||||
ti_efr_to_canon(uint8_t *dst, const uint8_t *src, unsigned int src_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(src_len == TI_LEN);
|
||||
|
||||
dst[30] = 0x00; /* last nibble won't written, pre-clear it */
|
||||
|
||||
for (i=0; i<244; i++) {
|
||||
|
@ -207,7 +221,7 @@ ti_efr_to_canon(uint8_t *dst, const uint8_t *src)
|
|||
msb_put_bit(dst, di, msb_get_bit(src, si));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return EFR_CANON_LEN;
|
||||
}
|
||||
|
||||
const struct format_desc fmt_ti_efr = {
|
||||
|
@ -216,7 +230,7 @@ const struct format_desc fmt_ti_efr = {
|
|||
.name = "ti-efr",
|
||||
.description = "Texas Instrument EFR TCH/F buffer format",
|
||||
|
||||
.frame_len = 33,
|
||||
.frame_len = TI_LEN,
|
||||
.conv_from_canon = ti_efr_from_canon,
|
||||
.conv_to_canon = ti_efr_to_canon,
|
||||
};
|
||||
|
|
|
@ -40,20 +40,22 @@ struct pq_state_alsa {
|
|||
};
|
||||
|
||||
static int
|
||||
pq_cb_alsa_input(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_alsa_input(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_alsa *state = _state;
|
||||
unsigned int num_samples = state->blk_len/2;
|
||||
int rv;
|
||||
rv = snd_pcm_readi(state->pcm_handle, out, num_samples);
|
||||
return rv == num_samples ? 0 : -1;
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
return rv * sizeof(uint16_t);
|
||||
}
|
||||
|
||||
static int
|
||||
pq_cb_alsa_output(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_alsa_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_alsa *state = _state;
|
||||
unsigned int num_samples = state->blk_len/2;
|
||||
unsigned int num_samples = in_len/2;
|
||||
int rv;
|
||||
rv = snd_pcm_writei(state->pcm_handle, in, num_samples);
|
||||
return rv == num_samples ? 0 : -1;
|
||||
|
|
|
@ -34,20 +34,22 @@ struct pq_state_file {
|
|||
|
||||
|
||||
static int
|
||||
pq_cb_file_input(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_file_input(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_file *state = _state;
|
||||
int rv;
|
||||
rv = fread(out, state->blk_len, 1, state->fh);
|
||||
return rv == 1 ? 0 : -1;
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
return rv * state->blk_len;
|
||||
}
|
||||
|
||||
static int
|
||||
pq_cb_file_output(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_file_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_file *state = _state;
|
||||
int rv;
|
||||
rv = fwrite(in, state->blk_len, 1, state->fh);
|
||||
rv = fwrite(in, in_len, 1, state->fh);
|
||||
return rv == 1 ? 0 : -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
|
||||
|
||||
static int
|
||||
pq_cb_fmt_convert(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_fmt_convert(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
fmt_conv_cb_t f = _state;
|
||||
return f(out, in);
|
||||
return f(out, in, in_len);
|
||||
}
|
||||
|
||||
/*! Add format conversion to processing queue
|
||||
|
|
10
src/pq_rtp.c
10
src/pq_rtp.c
|
@ -88,7 +88,7 @@ struct pq_state_rtp {
|
|||
|
||||
|
||||
static int
|
||||
pq_cb_rtp_input(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_rtp_input(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_rtp *state = _state;
|
||||
uint8_t buf[state->blk_len+256];
|
||||
|
@ -153,14 +153,14 @@ pq_cb_rtp_input(void *_state, uint8_t *out, const uint8_t *in)
|
|||
|
||||
memcpy(out, payload, payload_len);
|
||||
|
||||
return 0;
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int
|
||||
pq_cb_rtp_output(void *_state, uint8_t *out, const uint8_t *in)
|
||||
pq_cb_rtp_output(void *_state, uint8_t *out, const uint8_t *in, unsigned int in_len)
|
||||
{
|
||||
struct pq_state_rtp *state = _state;
|
||||
int len = state->blk_len + sizeof(struct rtp_hdr);
|
||||
int len = in_len + sizeof(struct rtp_hdr);
|
||||
uint8_t buf[len];
|
||||
struct rtp_hdr *rtph = (struct rtp_hdr *)buf;
|
||||
uint8_t *payload;
|
||||
|
@ -178,7 +178,7 @@ pq_cb_rtp_output(void *_state, uint8_t *out, const uint8_t *in)
|
|||
rtph->ssrc = htonl(state->ssrc);
|
||||
|
||||
payload = buf + sizeof(*rtph);
|
||||
memcpy(payload, in, state->blk_len);
|
||||
memcpy(payload, in, in_len);
|
||||
|
||||
rv = write(state->fd, buf, len);
|
||||
return rv == len ? 0 : -1;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <gapk/procqueue.h>
|
||||
|
||||
|
||||
#define VAR_BUF_SIZE 320
|
||||
#define MAX_PQ_ITEMS 8
|
||||
|
||||
struct pq {
|
||||
|
@ -98,11 +98,16 @@ pq_prepare(struct pq *pq)
|
|||
for (i=0; i<pq->n_items; i++) {
|
||||
struct pq_item *item = pq->items[i];
|
||||
|
||||
if (item->len_in != len_prev)
|
||||
if (item->len_in && item->len_in != len_prev)
|
||||
return -EINVAL;
|
||||
|
||||
if (i < (pq->n_items-1)) {
|
||||
pq->buffers[i] = malloc(item->len_out);
|
||||
unsigned int buf_size = item->len_out;
|
||||
/* variable-length codec output, use maximum
|
||||
* known buffer size */
|
||||
if (!buf_size)
|
||||
buf_size = VAR_BUF_SIZE;
|
||||
pq->buffers[i] = malloc(buf_size);
|
||||
if (!pq->buffers[i])
|
||||
return -ENOMEM;
|
||||
} else{
|
||||
|
@ -124,8 +129,10 @@ pq_execute(struct pq *pq)
|
|||
{
|
||||
int i;
|
||||
void *buf_prev, *buf;
|
||||
unsigned int len_prev;
|
||||
|
||||
buf_prev = NULL;
|
||||
len_prev = 0;
|
||||
|
||||
for (i=0; i<pq->n_items; i++) {
|
||||
int rv;
|
||||
|
@ -133,11 +140,14 @@ pq_execute(struct pq *pq)
|
|||
|
||||
buf = i < (pq->n_items-1) ? pq->buffers[i] : NULL;
|
||||
|
||||
rv = item->proc(item->state, buf, buf_prev);
|
||||
if (rv)
|
||||
rv = item->proc(item->state, buf, buf_prev, len_prev);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "pq_execute(): abort, item returned %d\n", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
buf_prev = buf;
|
||||
len_prev = rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue