- Fixed conf switch on reinit-ing conf port TX buf.
- Updated conf switch to enable RX/TX level adjustment. - Added VAD & PLC setting in passthrough codecs. - Changed G711 fourcc codes. - Updated bits-to-bytes calculations all over the places. - Minor update: changed log level for dumping jbuf states in stream. git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/aps-direct@2445 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
bfa860b133
commit
d5c54ab720
|
@ -300,31 +300,26 @@ typedef struct pjmedia_frame_ext_subframe {
|
|||
*/
|
||||
PJ_INLINE(void) pjmedia_frame_ext_append_subframe(pjmedia_frame_ext *frm,
|
||||
const void *src,
|
||||
pj_uint16_t bitlen,
|
||||
pj_uint16_t samples_cnt)
|
||||
unsigned bitlen,
|
||||
unsigned samples_cnt)
|
||||
{
|
||||
pjmedia_frame_ext_subframe *fsub;
|
||||
pj_uint8_t *p;
|
||||
unsigned i, tmp;
|
||||
unsigned i;
|
||||
|
||||
p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext);
|
||||
for (i = 0; i < frm->subframe_cnt; ++i) {
|
||||
pjmedia_frame_ext_subframe *fsub;
|
||||
fsub = (pjmedia_frame_ext_subframe*) p;
|
||||
p += sizeof(fsub->bitlen) + (fsub->bitlen >> 3);
|
||||
if (fsub->bitlen & 0x07)
|
||||
++p;
|
||||
p += sizeof(fsub->bitlen) + ((fsub->bitlen+7) >> 3);
|
||||
}
|
||||
|
||||
tmp = bitlen >> 3;
|
||||
if (bitlen & 0x07)
|
||||
++tmp;
|
||||
|
||||
pj_memcpy(p, &bitlen, sizeof(bitlen));
|
||||
if (tmp)
|
||||
pj_memcpy(p + sizeof(bitlen), src, tmp);
|
||||
fsub = (pjmedia_frame_ext_subframe*) p;
|
||||
fsub->bitlen = (pj_uint16_t)bitlen;
|
||||
if (bitlen)
|
||||
pj_memcpy(fsub->data, src, (bitlen+7) >> 3);
|
||||
|
||||
frm->subframe_cnt++;
|
||||
frm->samples_cnt = frm->samples_cnt + samples_cnt;
|
||||
frm->samples_cnt = frm->samples_cnt + (pj_uint16_t)samples_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -348,9 +343,7 @@ PJ_INLINE(pjmedia_frame_ext_subframe*)
|
|||
p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext);
|
||||
for (i = 0; i < n; ++i) {
|
||||
sf = (pjmedia_frame_ext_subframe*) p;
|
||||
p += sizeof(sf->bitlen) + (sf->bitlen >> 3);
|
||||
if (sf->bitlen & 0x07)
|
||||
++p;
|
||||
p += sizeof(sf->bitlen) + ((sf->bitlen+7) >> 3);
|
||||
}
|
||||
|
||||
sf = (pjmedia_frame_ext_subframe*) p;
|
||||
|
@ -383,9 +376,7 @@ PJ_INLINE(pj_status_t)
|
|||
move_src = (pj_uint8_t*)pjmedia_frame_ext_get_subframe(frm, n);
|
||||
sf = pjmedia_frame_ext_get_subframe(frm, frm->subframe_cnt-1);
|
||||
move_len = (pj_uint8_t*)sf - move_src + sizeof(sf->bitlen) +
|
||||
(sf->bitlen >> 3);
|
||||
if (sf->bitlen & 0x07)
|
||||
++move_len;
|
||||
((sf->bitlen+7) >> 3);
|
||||
pj_memmove((pj_uint8_t*)frm+sizeof(pjmedia_frame_ext),
|
||||
move_src, move_len);
|
||||
|
||||
|
|
|
@ -196,8 +196,8 @@ typedef union pjmedia_fourcc {
|
|||
* FourCC identifier definitions.
|
||||
*/
|
||||
#define PJMEDIA_FOURCC_L16 PJMEDIA_FOURCC_PACK(' ', 'L', '1', '6')
|
||||
#define PJMEDIA_FOURCC_G711A PJMEDIA_FOURCC_PACK('G', '7', '1', '1')
|
||||
#define PJMEDIA_FOURCC_G711U PJMEDIA_FOURCC_PACK('U', 'L', 'A', 'W')
|
||||
#define PJMEDIA_FOURCC_PCMA PJMEDIA_FOURCC_PACK('A', 'L', 'A', 'W')
|
||||
#define PJMEDIA_FOURCC_PCMU PJMEDIA_FOURCC_PACK('u', 'L', 'A', 'W')
|
||||
#define PJMEDIA_FOURCC_AMR PJMEDIA_FOURCC_PACK(' ', 'A', 'M', 'R')
|
||||
#define PJMEDIA_FOURCC_G729 PJMEDIA_FOURCC_PACK('G', '7', '2', '9')
|
||||
#define PJMEDIA_FOURCC_ILBC PJMEDIA_FOURCC_PACK('I', 'L', 'B', 'C')
|
||||
|
|
|
@ -162,6 +162,8 @@ static struct codec_desc {
|
|||
unsigned def_bitrate; /* Default bitrate of this codec. */
|
||||
unsigned max_bitrate; /* Maximum bitrate of this codec. */
|
||||
pj_uint8_t frm_per_pkt; /* Default num of frames per packet.*/
|
||||
pj_uint8_t vad; /* VAD enabled/disabled. */
|
||||
pj_uint8_t plc; /* PLC enabled/disabled. */
|
||||
parse_cb parse; /* Callback to parse bitstream. */
|
||||
pack_cb pack; /* Callback to pack bitstream. */
|
||||
pjmedia_codec_fmtp dec_fmtp; /* Decoder's fmtp params. */
|
||||
|
@ -172,7 +174,7 @@ codec_desc[] =
|
|||
# if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
|
||||
{1, "AMR", PJMEDIA_RTP_PT_AMR, {PJMEDIA_FOURCC_AMR},
|
||||
8000, 1, 160,
|
||||
12200, 12200, 2,
|
||||
7400, 12200, 2, 1, 1,
|
||||
&parse_amr, &pack_amr
|
||||
/*, {1, {{{"octet-align", 11}, {"1", 1}}} } */
|
||||
},
|
||||
|
@ -181,30 +183,30 @@ codec_desc[] =
|
|||
# if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
|
||||
{1, "G729", PJMEDIA_RTP_PT_G729, {PJMEDIA_FOURCC_G729},
|
||||
8000, 1, 80,
|
||||
8000, 8000, 2
|
||||
8000, 8000, 2, 1, 1
|
||||
},
|
||||
# endif
|
||||
|
||||
# if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
|
||||
{1, "iLBC", PJMEDIA_RTP_PT_ILBC, {PJMEDIA_FOURCC_ILBC},
|
||||
8000, 1, 240,
|
||||
13333, 15200, 2,
|
||||
13333, 15200, 1, 1, 1,
|
||||
NULL, NULL,
|
||||
{1, {{{"mode", 4}, {"30", 2}}} }
|
||||
},
|
||||
# endif
|
||||
|
||||
# if PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU
|
||||
{1, "PCMU", PJMEDIA_RTP_PT_PCMU, {PJMEDIA_FOURCC_G711U},
|
||||
{1, "PCMU", PJMEDIA_RTP_PT_PCMU, {PJMEDIA_FOURCC_PCMU},
|
||||
8000, 1, 80,
|
||||
64000, 64000, 2
|
||||
64000, 64000, 2, 1, 1
|
||||
},
|
||||
# endif
|
||||
|
||||
# if PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA
|
||||
{1, "PCMA", PJMEDIA_RTP_PT_PCMA, {PJMEDIA_FOURCC_G711A},
|
||||
{1, "PCMA", PJMEDIA_RTP_PT_PCMA, {PJMEDIA_FOURCC_PCMA},
|
||||
8000, 1, 80,
|
||||
64000, 64000, 2
|
||||
64000, 64000, 2, 1, 1
|
||||
},
|
||||
# endif
|
||||
};
|
||||
|
@ -246,15 +248,17 @@ static pj_status_t pack_amr ( codec_private_t *codec_data,
|
|||
unsigned len;
|
||||
|
||||
sf = pjmedia_frame_ext_get_subframe(input, i);
|
||||
|
||||
len = sf->bitlen >> 3;
|
||||
if (sf->bitlen & 0x07)
|
||||
++len;
|
||||
len = (sf->bitlen + 7) >> 3;
|
||||
|
||||
info = (pjmedia_codec_amr_bit_info*) &frames[i].bit_info;
|
||||
pj_bzero(info, sizeof(*info));
|
||||
info->frame_type = pjmedia_codec_amr_get_mode2(enc_setting->amr_nb,
|
||||
len);
|
||||
|
||||
if (len == 0) {
|
||||
info->frame_type = (pj_uint8_t)(enc_setting->amr_nb? 14 : 15);
|
||||
} else {
|
||||
info->frame_type = pjmedia_codec_amr_get_mode2(enc_setting->amr_nb,
|
||||
len);
|
||||
}
|
||||
info->good_quality = 1;
|
||||
info->mode = setting->enc_mode;
|
||||
|
||||
|
@ -449,9 +453,9 @@ static pj_status_t default_attr ( pjmedia_codec_factory *factory,
|
|||
|
||||
/* Default flags. */
|
||||
attr->setting.frm_per_pkt = codec_desc[i].frm_per_pkt;
|
||||
attr->setting.plc = 0;
|
||||
attr->setting.plc = codec_desc[i].plc;
|
||||
attr->setting.penh= 0;
|
||||
attr->setting.vad = 0;
|
||||
attr->setting.vad = codec_desc[i].vad;
|
||||
attr->setting.cng = attr->setting.vad;
|
||||
attr->setting.dec_fmtp = codec_desc[i].dec_fmtp;
|
||||
|
||||
|
@ -759,13 +763,21 @@ static pj_status_t codec_encode( pjmedia_codec *codec,
|
|||
sf = pjmedia_frame_ext_get_subframe(input_, i);
|
||||
pj_assert(sf);
|
||||
|
||||
sf_len = sf->bitlen >> 3;
|
||||
if (sf->bitlen & 0x07)
|
||||
++sf_len;
|
||||
sf_len = (sf->bitlen + 7) >> 3;
|
||||
|
||||
pj_memcpy(p, sf->data, sf_len);
|
||||
p += sf_len;
|
||||
output->size += sf_len;
|
||||
|
||||
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
|
||||
/* If there is SID or DTX frame, break the loop. */
|
||||
if (desc->pt == PJMEDIA_RTP_PT_G729 &&
|
||||
sf_len < codec_data->avg_frame_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#define SLOT_TYPE unsigned
|
||||
#define INVALID_SLOT ((SLOT_TYPE)-1)
|
||||
#define BUFFER_SIZE PJMEDIA_MAX_MTU
|
||||
#define MAX_LEVEL (32767)
|
||||
#define MIN_LEVEL (-32768)
|
||||
|
||||
/*
|
||||
* DON'T GET CONFUSED WITH TX/RX!!
|
||||
|
@ -152,6 +154,10 @@ static pj_status_t create_conf_port( pj_pool_t *pool,
|
|||
conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
|
||||
conf_port->tx_setting = PJMEDIA_PORT_ENABLE;
|
||||
|
||||
/* Default level adjustment is 128 (which means no adjustment) */
|
||||
conf_port->tx_adj_level = NORMAL_LEVEL;
|
||||
conf_port->rx_adj_level = NORMAL_LEVEL;
|
||||
|
||||
/* Create transmit flag array */
|
||||
conf_port->listener_slots = (SLOT_TYPE*)
|
||||
pj_pool_zalloc(pool,
|
||||
|
@ -165,7 +171,6 @@ static pj_status_t create_conf_port( pj_pool_t *pool,
|
|||
/* Init pjmedia_frame structure in the TX buffer. */
|
||||
f = (pjmedia_frame*)conf_port->tx_buf;
|
||||
f->buf = conf_port->tx_buf + sizeof(pjmedia_frame);
|
||||
f->size = 0;
|
||||
|
||||
/* Done */
|
||||
*p_conf_port = conf_port;
|
||||
|
@ -672,6 +677,8 @@ PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
|
|||
}
|
||||
|
||||
if (i != src_port->listener_cnt) {
|
||||
pjmedia_frame_ext *f;
|
||||
|
||||
pj_assert(src_port->listener_cnt > 0 &&
|
||||
src_port->listener_cnt < conf->max_ports);
|
||||
pj_assert(dst_port->transmitter_cnt > 0 &&
|
||||
|
@ -682,8 +689,12 @@ PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
|
|||
--src_port->listener_cnt;
|
||||
--dst_port->transmitter_cnt;
|
||||
|
||||
/* Clean up sink TX buffer. */
|
||||
pj_bzero(dst_port->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
/* Cleanup listener TX buffer. */
|
||||
f = (pjmedia_frame_ext*)dst_port->tx_buf;
|
||||
f->base.type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f->base.size = 0;
|
||||
f->samples_cnt = 0;
|
||||
f->subframe_cnt = 0;
|
||||
|
||||
PJ_LOG(4,(THIS_FILE,
|
||||
"Port %d (%.*s) stop transmitting to port %d (%.*s)",
|
||||
|
@ -776,6 +787,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
|
|||
while (conf_port->listener_cnt) {
|
||||
unsigned dst_slot;
|
||||
struct conf_port *dst_port;
|
||||
pjmedia_frame_ext *f;
|
||||
|
||||
dst_slot = conf_port->listener_slots[conf_port->listener_cnt-1];
|
||||
dst_port = conf->ports[dst_slot];
|
||||
|
@ -784,8 +796,12 @@ PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
|
|||
pj_assert(conf->connect_cnt > 0);
|
||||
--conf->connect_cnt;
|
||||
|
||||
/* Clean up TX buffer. */
|
||||
pj_bzero(dst_port->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
/* Cleanup & reinit listener TX buffer. */
|
||||
f = (pjmedia_frame_ext*)dst_port->tx_buf;
|
||||
f->base.type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f->base.size = 0;
|
||||
f->samples_cnt = 0;
|
||||
f->subframe_cnt = 0;
|
||||
}
|
||||
|
||||
/* Remove the port. */
|
||||
|
@ -856,6 +872,8 @@ PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf,
|
|||
info->samples_per_frame = conf_port->info->samples_per_frame;
|
||||
info->bits_per_sample = conf_port->info->bits_per_sample;
|
||||
info->format = conf_port->port->info.format;
|
||||
info->tx_adj_level = conf_port->tx_adj_level - NORMAL_LEVEL;
|
||||
info->rx_adj_level = conf_port->rx_adj_level - NORMAL_LEVEL;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -934,6 +952,11 @@ PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf,
|
|||
|
||||
conf_port = conf->ports[slot];
|
||||
|
||||
/* Level adjustment is applicable only for ports that work with raw PCM. */
|
||||
PJ_ASSERT_RETURN(conf_port->info->format.u32 == 0 ||
|
||||
conf_port->info->format.u32 == PJMEDIA_FOURCC_L16,
|
||||
PJ_EIGNORED);
|
||||
|
||||
/* Set normalized adjustment level. */
|
||||
conf_port->rx_adj_level = adj_level + NORMAL_LEVEL;
|
||||
|
||||
|
@ -964,6 +987,14 @@ PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf,
|
|||
|
||||
conf_port = conf->ports[slot];
|
||||
|
||||
/* Level adjustment is applicable only for ports that work with raw PCM. */
|
||||
PJ_ASSERT_RETURN(conf_port->info->format.u32 == 0 ||
|
||||
conf_port->info->format.u32 == PJMEDIA_FOURCC_L16,
|
||||
PJ_EIGNORED);
|
||||
|
||||
/* Set normalized adjustment level. */
|
||||
conf_port->tx_adj_level = adj_level + NORMAL_LEVEL;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1032,6 +1063,28 @@ static pj_status_t write_frame(struct conf_port *cport_dst,
|
|||
if (nsamples_to_copy > nsamples_req)
|
||||
nsamples_to_copy = nsamples_req;
|
||||
|
||||
/* Adjust TX level. */
|
||||
if (cport_dst->tx_adj_level != NORMAL_LEVEL) {
|
||||
pj_int16_t *p, *p_end;
|
||||
|
||||
p = f_start;
|
||||
p_end = p + nsamples_to_copy;
|
||||
while (p < p_end) {
|
||||
pj_int32_t itemp = *p;
|
||||
|
||||
/* Adjust the level */
|
||||
itemp = (itemp * cport_dst->tx_adj_level) >> 7;
|
||||
|
||||
/* Clip the signal if it's too loud */
|
||||
if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
|
||||
else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
|
||||
|
||||
/* Put back in the buffer. */
|
||||
*p = (pj_int16_t)itemp;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
pjmedia_copy_samples((pj_int16_t*)frm_dst->buf + (frm_dst->size>>1),
|
||||
f_start,
|
||||
nsamples_to_copy);
|
||||
|
@ -1131,8 +1184,6 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
|
||||
unsigned ci, i;
|
||||
|
||||
PJ_TODO(ADJUST_RX_TX_LEVEL_FOR_PCM_FRAMES);
|
||||
|
||||
/* Must lock mutex */
|
||||
pj_mutex_lock(conf->mutex);
|
||||
|
||||
|
@ -1173,7 +1224,7 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
pjmedia_frame *f = (pjmedia_frame*)conf->buf;
|
||||
pj_status_t status;
|
||||
unsigned j;
|
||||
pj_int32_t level;
|
||||
pj_int32_t level = 0;
|
||||
|
||||
pj_add_timestamp32(&cport->ts_rx, cport->info->samples_per_frame);
|
||||
|
||||
|
@ -1185,18 +1236,41 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
if (status != PJ_SUCCESS)
|
||||
continue;
|
||||
|
||||
/* Calculate RX level. */
|
||||
/* Calculate & adjust RX level. */
|
||||
if (f->type == PJMEDIA_FRAME_TYPE_AUDIO) {
|
||||
level = pjmedia_calc_avg_signal((const pj_int16_t*)f->buf,
|
||||
f->size >>1 );
|
||||
if (cport->rx_adj_level != NORMAL_LEVEL) {
|
||||
pj_int16_t *p = (pj_int16_t*)f->buf;
|
||||
pj_int16_t *end;
|
||||
|
||||
end = p + (f->size >> 1);
|
||||
while (p < end) {
|
||||
pj_int32_t itemp = *p;
|
||||
|
||||
/* Adjust the level */
|
||||
itemp = (itemp * cport->rx_adj_level) >> 7;
|
||||
|
||||
/* Clip the signal if it's too loud */
|
||||
if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
|
||||
else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
|
||||
|
||||
level += PJ_ABS(itemp);
|
||||
|
||||
/* Put back in the buffer. */
|
||||
*p = (pj_int16_t)itemp;
|
||||
++p;
|
||||
}
|
||||
level /= (f->size >> 1);
|
||||
} else {
|
||||
level = pjmedia_calc_avg_signal((const pj_int16_t*)f->buf,
|
||||
f->size >> 1);
|
||||
}
|
||||
} else if (f->type == PJMEDIA_FRAME_TYPE_EXTENDED) {
|
||||
/* For extended frame, TX level is unknown, so we just set
|
||||
* it to NORMAL_LEVEL.
|
||||
*/
|
||||
level = NORMAL_LEVEL;
|
||||
} else { /* PJMEDIA_FRAME_TYPE_NONE */
|
||||
level = 0;
|
||||
}
|
||||
|
||||
cport->rx_level = pjmedia_linear2ulaw(level) ^ 0xff;
|
||||
|
||||
/* Put the frame to all listeners. */
|
||||
|
@ -1220,8 +1294,11 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Set listener TX level equal to transmitter RX level. */
|
||||
listener->tx_level = cport->rx_level;
|
||||
/* Set listener TX level based on transmitter RX level &
|
||||
* listener TX level.
|
||||
*/
|
||||
listener->tx_level = (cport->rx_level * listener->tx_adj_level)
|
||||
>> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1241,10 +1318,16 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
|
||||
if (cport->tx_setting==PJMEDIA_PORT_MUTE || cport->transmitter_cnt==0)
|
||||
{
|
||||
pjmedia_frame_ext *f;
|
||||
|
||||
/* Clear left-over samples in tx_buffer, if any, so that it won't
|
||||
* be transmitted next time we have audio signal.
|
||||
*/
|
||||
pj_bzero(cport->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
f = (pjmedia_frame_ext*)cport->tx_buf;
|
||||
f->base.type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f->base.size = 0;
|
||||
f->samples_cnt = 0;
|
||||
f->subframe_cnt = 0;
|
||||
|
||||
cport->tx_level = 0;
|
||||
|
||||
|
@ -1279,8 +1362,9 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
pj_uint16_t samples_per_subframe;
|
||||
|
||||
if (f_src_->samples_cnt < this_cport->info->samples_per_frame) {
|
||||
pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
frame->type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f_dst->base.type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f_dst->samples_cnt = 0;
|
||||
f_dst->subframe_cnt = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1302,8 +1386,8 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
|
||||
} else if (f_src->type == PJMEDIA_FRAME_TYPE_AUDIO) {
|
||||
if ((f_src->size>>1) < this_cport->info->samples_per_frame) {
|
||||
pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
frame->type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
frame->size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1320,9 +1404,12 @@ static pj_status_t get_frame(pjmedia_port *this_port,
|
|||
this_cport->info->samples_per_frame,
|
||||
f_src->size >> 1);
|
||||
} else { /* PJMEDIA_FRAME_TYPE_NONE */
|
||||
pjmedia_frame_ext *f_dst = (pjmedia_frame_ext*)frame;
|
||||
|
||||
/* Reset TX buffer */
|
||||
pj_bzero(this_cport->tx_buf, sizeof(pjmedia_frame_ext));
|
||||
frame->type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f_dst->base.type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
f_dst->samples_cnt = 0;
|
||||
f_dst->subframe_cnt = 0;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
|
@ -1341,7 +1428,7 @@ static pj_status_t put_frame(pjmedia_port *this_port,
|
|||
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
|
||||
struct conf_port *cport = conf->ports[this_port->port_data.ldata];
|
||||
unsigned j;
|
||||
pj_int32_t level;
|
||||
pj_int32_t level = 0;
|
||||
|
||||
pj_add_timestamp32(&cport->ts_rx, cport->info->samples_per_frame);
|
||||
|
||||
|
@ -1357,18 +1444,41 @@ static pj_status_t put_frame(pjmedia_port *this_port,
|
|||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Calculate RX level. */
|
||||
/* Calculate & adjust RX level. */
|
||||
if (f->type == PJMEDIA_FRAME_TYPE_AUDIO) {
|
||||
level = pjmedia_calc_avg_signal((const pj_int16_t*)f->buf,
|
||||
f->size >>1 );
|
||||
if (cport->rx_adj_level != NORMAL_LEVEL) {
|
||||
pj_int16_t *p = (pj_int16_t*)f->buf;
|
||||
pj_int16_t *end;
|
||||
|
||||
end = p + (f->size >> 1);
|
||||
while (p < end) {
|
||||
pj_int32_t itemp = *p;
|
||||
|
||||
/* Adjust the level */
|
||||
itemp = (itemp * cport->rx_adj_level) >> 7;
|
||||
|
||||
/* Clip the signal if it's too loud */
|
||||
if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
|
||||
else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
|
||||
|
||||
level += PJ_ABS(itemp);
|
||||
|
||||
/* Put back in the buffer. */
|
||||
*p = (pj_int16_t)itemp;
|
||||
++p;
|
||||
}
|
||||
level /= (f->size >> 1);
|
||||
} else {
|
||||
level = pjmedia_calc_avg_signal((const pj_int16_t*)f->buf,
|
||||
f->size >> 1);
|
||||
}
|
||||
} else if (f->type == PJMEDIA_FRAME_TYPE_EXTENDED) {
|
||||
/* For extended frame, TX level is unknown, so we just set
|
||||
* it to NORMAL_LEVEL.
|
||||
*/
|
||||
level = NORMAL_LEVEL;
|
||||
} else { /* PJMEDIA_FRAME_TYPE_NONE. */
|
||||
level = 0;
|
||||
}
|
||||
|
||||
cport->rx_level = pjmedia_linear2ulaw(level) ^ 0xff;
|
||||
|
||||
/* Put the frame to all listeners. */
|
||||
|
@ -1401,8 +1511,10 @@ static pj_status_t put_frame(pjmedia_port *this_port,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Set listener TX level equal to transmitter RX level. */
|
||||
listener->tx_level = cport->rx_level;
|
||||
/* Set listener TX level based on transmitter RX level & listener
|
||||
* TX level.
|
||||
*/
|
||||
listener->tx_level = (cport->rx_level * listener->tx_adj_level) >> 8;
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
|
|
@ -482,7 +482,7 @@ static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame)
|
|||
}
|
||||
|
||||
if (frame_type == PJMEDIA_JB_MISSING_FRAME) {
|
||||
PJ_LOG(1,(stream->port.info.name.ptr, "Frame lost!"));
|
||||
PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost!"));
|
||||
} else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
|
||||
/* Jitter buffer is empty. Check if this is the first "empty"
|
||||
* state.
|
||||
|
@ -492,7 +492,7 @@ static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame)
|
|||
|
||||
/* Report the state of jitter buffer */
|
||||
pjmedia_jbuf_get_state(stream->jb, &jb_state);
|
||||
PJ_LOG(1,(stream->port.info.name.ptr,
|
||||
PJ_LOG(5,(stream->port.info.name.ptr,
|
||||
"Jitter buffer empty (prefetch=%d)",
|
||||
jb_state.prefetch));
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame)
|
|||
pjmedia_jbuf_get_state(stream->jb, &jb_state);
|
||||
|
||||
if (stream->jb_last_frm != frame_type) {
|
||||
PJ_LOG(1,(stream->port.info.name.ptr,
|
||||
PJ_LOG(5,(stream->port.info.name.ptr,
|
||||
"Jitter buffer is bufferring (prefetch=%d)",
|
||||
jb_state.prefetch));
|
||||
}
|
||||
|
|
|
@ -778,8 +778,8 @@ static void RecCb(TAPSCommBuffer &buf, void *user_data)
|
|||
}
|
||||
break;
|
||||
|
||||
case PJMEDIA_FOURCC_G711U:
|
||||
case PJMEDIA_FOURCC_G711A:
|
||||
case PJMEDIA_FOURCC_PCMU:
|
||||
case PJMEDIA_FOURCC_PCMA:
|
||||
{
|
||||
unsigned samples_processed = 0;
|
||||
|
||||
|
@ -857,13 +857,10 @@ static void PlayCb(TAPSCommBuffer &buf, void *user_data)
|
|||
/* AMR header for APS is one byte, the format (may be!):
|
||||
* 0xxxxy00, where xxxx:frame type, y:not sure.
|
||||
*/
|
||||
unsigned len = sf->bitlen>>3;
|
||||
unsigned len = (sf->bitlen+7)>>3;
|
||||
enum {SID_FT = 8 };
|
||||
pj_uint8_t amr_header = 4, ft = SID_FT;
|
||||
|
||||
if (sf->bitlen & 0x07)
|
||||
++len;
|
||||
|
||||
if (len >= pjmedia_codec_amrnb_framelen[0])
|
||||
ft = pjmedia_codec_amr_get_mode2(PJ_TRUE, len);
|
||||
|
||||
|
@ -975,8 +972,8 @@ static void PlayCb(TAPSCommBuffer &buf, void *user_data)
|
|||
}
|
||||
break;
|
||||
|
||||
case PJMEDIA_FOURCC_G711U:
|
||||
case PJMEDIA_FOURCC_G711A:
|
||||
case PJMEDIA_FOURCC_PCMU:
|
||||
case PJMEDIA_FOURCC_PCMA:
|
||||
{
|
||||
unsigned samples_ready = 0;
|
||||
unsigned samples_req = aps_g711_frame_len;
|
||||
|
@ -1104,8 +1101,9 @@ static pj_status_t sound_open(pjmedia_dir dir,
|
|||
if (strm->setting.format.u32 == 0)
|
||||
strm->setting.format.u32 = PJMEDIA_FOURCC_L16;
|
||||
|
||||
/* Set audio engine settings. */
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
/* Set audio engine fourcc. */
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_PCMU ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_PCMA ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_L16)
|
||||
{
|
||||
aps_setting.fourcc = TFourCC(KMCPFourCCIdG711);
|
||||
|
@ -1113,33 +1111,41 @@ static pj_status_t sound_open(pjmedia_dir dir,
|
|||
aps_setting.fourcc = TFourCC(strm->setting.format.u32);
|
||||
}
|
||||
|
||||
/* Set audio engine mode. */
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_AMR)
|
||||
{
|
||||
aps_setting.mode = (TAPSCodecMode)strm->setting.bitrate;
|
||||
} else if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_L16 ||
|
||||
(strm->setting.format.u32 == PJMEDIA_FOURCC_ILBC &&
|
||||
strm->setting.mode == 30))
|
||||
}
|
||||
else if (strm->setting.format.u32 == PJMEDIA_FOURCC_PCMU ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_L16 ||
|
||||
(strm->setting.format.u32 == PJMEDIA_FOURCC_ILBC &&
|
||||
strm->setting.mode == 30))
|
||||
{
|
||||
aps_setting.mode = EULawOr30ms;
|
||||
} else {
|
||||
}
|
||||
else if (strm->setting.format.u32 == PJMEDIA_FOURCC_PCMA ||
|
||||
(strm->setting.format.u32 == PJMEDIA_FOURCC_ILBC &&
|
||||
strm->setting.mode == 20))
|
||||
{
|
||||
aps_setting.mode = EALawOr20ms;
|
||||
}
|
||||
|
||||
/* Disable VAD on L16 and G711. */
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_L16 ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_G711U ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_G711A)
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_PCMU ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_PCMA ||
|
||||
strm->setting.format.u32 == PJMEDIA_FOURCC_L16)
|
||||
{
|
||||
aps_setting.vad = EFalse;
|
||||
} else {
|
||||
aps_setting.vad = strm->setting.vad;
|
||||
}
|
||||
|
||||
/* Set other audio engine attributes. */
|
||||
aps_setting.plc = strm->setting.plc;
|
||||
aps_setting.cng = strm->setting.cng;
|
||||
aps_setting.loudspk = strm->setting.loudspk;
|
||||
|
||||
/* Set audio engine callbacks. */
|
||||
if (strm->setting.format.u32 == PJMEDIA_FOURCC_L16) {
|
||||
aps_play_cb = &PlayCbPcm;
|
||||
aps_rec_cb = &RecCbPcm;
|
||||
|
@ -1148,7 +1154,7 @@ static pj_status_t sound_open(pjmedia_dir dir,
|
|||
aps_rec_cb = &RecCb;
|
||||
}
|
||||
|
||||
// Create the audio engine.
|
||||
/* Create the audio engine. */
|
||||
TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm,
|
||||
aps_rec_cb, aps_play_cb,
|
||||
strm, aps_setting));
|
||||
|
|
Loading…
Reference in New Issue