Change-Id: Iad98e1753fef1927c0e8a7493372141372a38224laforge/rtpsource
parent
7cb125d895
commit
9389188621
@ -0,0 +1,54 @@ |
||||
#include <osmocom/core/talloc.h> |
||||
#include <osmocom/core/utils.h> |
||||
#include <osmocom/core/linuxlist.h> |
||||
|
||||
#include "rtp_provider.h" |
||||
#include "internal.h" |
||||
|
||||
|
||||
static LLIST_HEAD(g_providers); |
||||
static LLIST_HEAD(g_prov_instances); |
||||
|
||||
void rtp_provider_register(struct rtp_provider *prov) |
||||
{ |
||||
llist_add_tail(&prov->list, &g_providers); |
||||
} |
||||
|
||||
const struct rtp_provider *rtp_provider_find(const char *name) |
||||
{ |
||||
struct rtp_provider *p; |
||||
llist_for_each_entry(p, &g_providers, list) { |
||||
if (!strcmp(name, p->name)) |
||||
return p; |
||||
} |
||||
LOGP(DMAIN, LOGL_ERROR, "Couldn't find RTP provider '%s'\n", name); |
||||
return NULL; |
||||
} |
||||
|
||||
struct rtp_provider_instance * |
||||
rtp_provider_instance_alloc(void *ctx, const struct rtp_provider *provider, enum codec_type codec) |
||||
{ |
||||
struct rtp_provider_instance *pi; |
||||
|
||||
pi = talloc_zero(ctx, struct rtp_provider_instance); |
||||
if (!pi) |
||||
return NULL; |
||||
|
||||
pi->provider = provider; |
||||
pi->codec = codec; |
||||
llist_add_tail(&pi->list, &g_prov_instances); |
||||
|
||||
return pi; |
||||
} |
||||
|
||||
void rtp_provider_instance_free(struct rtp_provider_instance *pi) |
||||
{ |
||||
llist_del(&pi->list); |
||||
talloc_free(pi); |
||||
} |
||||
|
||||
int rtp_provider_instance_gen_frame(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size) |
||||
{ |
||||
OSMO_ASSERT(pi->provider); |
||||
return pi->provider->rtp_gen(pi, out, out_size); |
||||
} |
@ -0,0 +1,51 @@ |
||||
#pragma once |
||||
#include <stdint.h> |
||||
#include <osmocom/core/linuxlist.h> |
||||
|
||||
enum codec_type { |
||||
CODEC_ULAW, |
||||
CODEC_ALAW, |
||||
CODEC_GSM_FR, |
||||
CODEC_GSM_EFR, |
||||
CODEC_GSM_HR, |
||||
CODEC_AMR_4_75, |
||||
CODEC_AMR_5_15, |
||||
CODEC_AMR_5_90, |
||||
CODEC_AMR_6_70, |
||||
CODEC_AMR_7_40, |
||||
CODEC_AMR_7_95, |
||||
CODEC_AMR_10_2, |
||||
CODEC_AMR_12_2, |
||||
CODEC_AMR_SID, |
||||
_NUM_CODECS |
||||
}; |
||||
|
||||
struct rtp_provider_instance; |
||||
|
||||
struct rtp_provider { |
||||
/* global list of RTP providers */ |
||||
struct llist_head list; |
||||
const char *name; |
||||
|
||||
/* generate the next RTP packet; return length in octests or negative on error */ |
||||
int (*rtp_gen)(struct rtp_provider_instance *inst, uint8_t *out, size_t out_size); |
||||
}; |
||||
|
||||
struct rtp_provider_instance { |
||||
/* entry in global list of RTP provider instances */ |
||||
struct llist_head list; |
||||
/* pointer to provider of which we are an instance */ |
||||
const struct rtp_provider *provider; |
||||
/* codec payload we are to generate */ |
||||
enum codec_type codec; |
||||
|
||||
/* private user data */ |
||||
void *priv; |
||||
}; |
||||
|
||||
void rtp_provider_register(struct rtp_provider *prov); |
||||
const struct rtp_provider *rtp_provider_find(const char *name); |
||||
|
||||
struct rtp_provider_instance *rtp_provider_instance_alloc(void *ctx, const struct rtp_provider *provider, enum codec_type codec); |
||||
void rtp_provider_instance_free(struct rtp_provider_instance *pi); |
||||
int rtp_provider_instance_gen_frame(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size); |
@ -0,0 +1,107 @@ |
||||
|
||||
#include <errno.h> |
||||
#include <osmocom/codec/codec.h> |
||||
#include <osmocom/core/utils.h> |
||||
|
||||
#include "rtp_provider.h" |
||||
#include "internal.h" |
||||
|
||||
static struct rtp_provider static_provider; |
||||
|
||||
static const uint8_t len4codec[_NUM_CODECS] = { |
||||
[CODEC_ULAW] = 160, |
||||
[CODEC_ALAW] = 160, |
||||
[CODEC_GSM_FR] = GSM_FR_BYTES, |
||||
[CODEC_GSM_EFR] = GSM_EFR_BYTES, |
||||
[CODEC_GSM_HR] = GSM_HR_BYTES, |
||||
[CODEC_AMR_4_75] = 12, |
||||
[CODEC_AMR_5_15] = 13, |
||||
[CODEC_AMR_5_90] = 15, |
||||
[CODEC_AMR_6_70] = 17, |
||||
[CODEC_AMR_7_40] = 19, |
||||
[CODEC_AMR_7_95] = 20, |
||||
[CODEC_AMR_10_2] = 26, |
||||
[CODEC_AMR_12_2] = 31, |
||||
[CODEC_AMR_SID] = 5, |
||||
}; |
||||
|
||||
/* generate a static / fixed RTP payload of matching codec/mode */ |
||||
static int rtp_gen_static(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size) |
||||
{ |
||||
uint8_t len; |
||||
|
||||
OSMO_ASSERT(pi->provider == &static_provider); |
||||
|
||||
len = len4codec[pi->codec]; |
||||
if (out_size < len) { |
||||
LOGP(DMAIN, LOGL_ERROR, "out_size %zu < %u\n", out_size, len); |
||||
return -EINVAL; |
||||
} |
||||
|
||||
memset(out, 0, len); |
||||
|
||||
switch (pi->codec) { |
||||
case CODEC_ULAW: |
||||
case CODEC_ALAW: |
||||
break; |
||||
case CODEC_GSM_FR: |
||||
out[0] = (out[0] & 0x0f) | 0xD0; /* mask in first four bit for FR */ |
||||
break; |
||||
case CODEC_GSM_EFR: |
||||
out[0] = (out[0] & 0x0f) | 0xC0; /* mask in first four bit for EFR */ |
||||
break; |
||||
case CODEC_GSM_HR: |
||||
break; |
||||
case CODEC_AMR_4_75: |
||||
out[0] = 0 << 4; |
||||
out[1] = 0 << 3; |
||||
break; |
||||
case CODEC_AMR_5_15: |
||||
out[0] = 1 << 4; |
||||
out[1] = 1 << 3; |
||||
break; |
||||
case CODEC_AMR_5_90: |
||||
out[0] = 2 << 4; |
||||
out[1] = 2 << 3; |
||||
break; |
||||
case CODEC_AMR_6_70: |
||||
out[0] = 3 << 4; |
||||
out[1] = 3 << 3; |
||||
break; |
||||
case CODEC_AMR_7_40: |
||||
out[0] = 4 << 4; |
||||
out[1] = 4 << 3; |
||||
break; |
||||
case CODEC_AMR_7_95: |
||||
out[0] = 5 << 4; |
||||
out[1] = 5 << 3; |
||||
break; |
||||
case CODEC_AMR_10_2: |
||||
out[0] = 6 << 4; |
||||
out[1] = 6 << 3; |
||||
break; |
||||
case CODEC_AMR_12_2: |
||||
out[0] = 7 << 4; |
||||
out[1] = 7 << 3; |
||||
break; |
||||
case CODEC_AMR_SID: |
||||
out[0] = 2 << 4; /* CMR: 5.90 */ |
||||
out[0] = 8 << 3; |
||||
break; |
||||
default: |
||||
OSMO_ASSERT(0); |
||||
} |
||||
|
||||
return len; |
||||
} |
||||
|
||||
|
||||
static struct rtp_provider static_provider = { |
||||
.name = "static", |
||||
.rtp_gen = &rtp_gen_static, |
||||
}; |
||||
|
||||
static void __attribute__((constructor)) rtp_provider_static_constr(void) |
||||
{ |
||||
rtp_provider_register(&static_provider); |
||||
} |
Loading…
Reference in new issue