123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- #include "precompile.h"
- #include "audiortp.h"
- #include "audioframe.h"
- #include "audiostream.h"
- #include "audiocontext.h"
- #include "audiolog.h"
- #include "other/jbuf.h"
- #include <assert.h>
- #include "memutil.h"
- #define CIRC_LEN(rd, wr, n) (((wr)+(n)-(rd))%(n))
- #define CIRC_ADD(old, val, n) (((old)+(n)+(val))%(n))
- #define CIRC_SUB(old, val, n) (((old)+(n)-(val))%(n))
- #define CIRC_INC(i, n) CIRC_ADD(i, 1, n)
- #define CIRC_DEC(i, n) CIRC_SUB(i, 1, n)
- #define CIRC_IS_EMPTY(rd, wr) ((rd) == (wr))
- #define JB_MAX 10
- #define DTMF_DURATION 1600
- #define DTMF_DURATION_STEP 320
- #define DTMF_VOLUME 10
- static const char digitmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '*', '#','A', 'B', 'C', 'D'};
- static __inline int digit2event(int digit) {
- int event;
- switch (digit) {
- case '0':case '1':case '2':case '3':case '4':
- case '5':case '6':case '7':case '8':case '9':
- event = digit - '0';
- break;
- case '*':
- event = 10;
- break;
- case '#':
- event = 11;
- break;
- case 'a':case 'b':case 'c':case 'd':
- event = 12 + digit - 'a';
- break;
- default:
- return -1;
- }
- return event;
- }
- static int send_dtmf_digit(rtp_session_t *sess, rtp_dtmf_event *digit, unsigned dtmf_pt)
- {
- rtp_state *st = rtp_session_get_rtp_state(sess);
- rtp_session_send(sess, 0, dtmf_pt, digit->e, 0, (const char*)digit, sizeof(rtp_dtmf_event));
- if (digit->e) {
- rtp_session_send(sess, 0, dtmf_pt, digit->e, 0, (const char*)digit, sizeof(rtp_dtmf_event));
- rtp_session_send(sess, 0, dtmf_pt, digit->e, 0, (const char*)digit, sizeof(rtp_dtmf_event));
- }
- return 0;
- }
- static int pt2bitsample(int pt)
- {
- switch (pt) {
- case RTP_PT_PCM16:
- return 16;
- case RTP_PT_PCM8:
- case RTP_PT_PCMA:
- case RTP_PT_PCMU:
- return 8;
- case RTP_PT_G729:
- return 1;
- default:
- break;
- }
- assert(0);
- return 0;
- }
- static apr_status_t read_frame(void *self, audioframe_t *frame)
- {
- audiortp_t *audiortp = CONTAINING_RECORD(self, audiortp_t, base);
- char buf[SUGGEST_FRAME_SIZE];
- unsigned short seq;
- unsigned mark;
- unsigned ts;
- unsigned pt;
- int i;
- int max_recv_cnt = 5; // max
- int new_dtmf = 0;
- audiortp->m_rtp_tick++;
- /* read packet from net */
- for (i = 0 ; i < max_recv_cnt; ++i) {
- int ret = rtp_session_recv_hook(audiortp->m_rtpsession, &pt, &mark, &ts, &seq, buf, sizeof(buf), audiortp->m_on_recv_hook, audiortp->m_hook_data);
- if (ret <= 0)
- break;
- audiortp->m_last_rtp_tick = audiortp->m_rtp_tick;
- if (pt == audiortp->m_recv_dtmf_pt) { /* dtmf */
- if (ret == sizeof(rtp_dtmf_event)) {
- int digit[2];
- int digit_cnt = 0;
- int j;
- rtp_dtmf_event *dtmf = (rtp_dtmf_event *)&buf[0];
- if (ts != audiortp->m_recving_dtmf_ts) {
- audiortp->m_recving_dtmf_ts = ts;
- if (!audiortp->m_recving_dtmf_event.e)
- digit[digit_cnt++] = audiortp->m_recving_dtmf_event.event;
- audiortp->m_recving_dtmf_event.event = dtmf->event;
- audiortp->m_recving_dtmf_event.e = dtmf->e;
- if (audiortp->m_recving_dtmf_event.e)
- digit[digit_cnt++] = audiortp->m_recving_dtmf_event.event;
- } else {
- if (dtmf->e) { /* end bit set */
- if (!audiortp->m_recving_dtmf_event.e) {
- audiortp->m_recving_dtmf_event.e = 1;
- audiortp->m_recving_dtmf_event.event = dtmf->event;
- digit[digit_cnt++] = audiortp->m_recving_dtmf_event.event;
- } else {
- if (audiortp->m_recving_dtmf_event.event == 0xff) {
- audiortp->m_recving_dtmf_event.event = dtmf->event;
- digit[digit_cnt++] = audiortp->m_recving_dtmf_event.event;
- }
- }
- } else {
- audiortp->m_recving_dtmf_event.event = dtmf->event;
- }
- }
- for (j = 0; j < digit_cnt; ++j) {
- if (digit[j] < sizeof(digitmap)) {
- int ch = digitmap[digit[j]];
- audiostream_raise_event(self, STREAM_EVT_RTP_DTMF, digit[j], 0);
- EnterCriticalSection(&audiortp->m_dtmf_lock);
- if (audiortp->m_recv_dtmf_cnt < MAX_DTMF)
- audiortp->m_recv_dtmf[audiortp->m_recv_dtmf_cnt++] = digit[j];
- LeaveCriticalSection(&audiortp->m_dtmf_lock);
- }
- }
- if (digit_cnt > 0)
- new_dtmf = digit[digit_cnt-1]; // the last one
- }
- } else if (pt == audiortp->m_recv_pt) { /* audio frame */
- if (ret == audiortp->m_recv_psize) {
- int time_span = (audiortp->m_recv_clock / 1000 * audiortp->m_recv_ptime);
- jbuf_put_frame2(audiortp->m_jitterbuf, &buf[0], ret, 0, ts / time_span, NULL);
- }
- } else {
- break;
- }
- audiortp->m_last_rtp_tick = audiortp->m_rtp_tick;
- }
- if (audiortp->m_timeout > 0) {
- unsigned int diffms = (audiortp->m_rtp_tick - audiortp->m_last_rtp_tick) * FRAME_TIME;
- if (diffms >= (unsigned)audiortp->m_timeout) {
- audiostream_raise_event(self, STREAM_EVT_RTP_TIMEOUT, 0, 0);
- }
- }
- {
- char frm_type;
- jbuf_get_frame(audiortp->m_jitterbuf, frame->buffer, &frm_type);
- if (frm_type == JB_NORMAL_FRAME) {
- frame->size = audiortp->m_jbuf_psize;
- } else {
- frame->size = 0;
- }
- }
- frame->dtmf = new_dtmf;
- return APR_SUCCESS;
- }
- static apr_status_t write_frame(void *self, const audioframe_t *frame)
- {
- audiortp_t *audiortp = CONTAINING_RECORD(self, audiortp_t, base);
- int dtmf = 0;
- EnterCriticalSection(&audiortp->m_dtmf_lock);
- if (frame->dtmf && CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF-1) {
- rtp_dtmf_event *dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
- dtmf->event = (unsigned char)digit2event(frame->dtmf);
- dtmf->e_vol = DTMF_VOLUME;
- dtmf->p = 0;
- dtmf->e = 0;
- dtmf->duration = 0;
- audiortp->m_send_dtmf_wr = CIRC_INC(audiortp->m_send_dtmf_wr, MAX_DTMF);
- }
- if (!CIRC_IS_EMPTY(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr)) {
- rtp_dtmf_event *digit = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_rd];
- send_dtmf_digit(audiortp->m_rtpsession, digit, audiortp->m_send_dtmf_pt);
- dtmf = 1;
- digit->duration += DTMF_DURATION_STEP;
- if (!digit->e) {
- if (digit->duration == DTMF_DURATION) {
- digit->e = 1;
- }
- } else {
- audiortp->m_send_dtmf_rd = CIRC_INC(audiortp->m_send_dtmf_rd, MAX_DTMF);
- rtp_session_advance_timestamp(audiortp->m_rtpsession, DTMF_DURATION);
- }
- }
- LeaveCriticalSection(&audiortp->m_dtmf_lock);
- if (dtmf) {
- /* because we send dtmf, so ignore this frame */
- return 0;
- }
- if (frame->size < (unsigned long)audiortp->m_send_psize) {
- if (frame->size) {
- memcpy(audiortp->m_SendSample.buffer + audiortp->m_SendSample.size, frame->buffer, frame->size);
- audiortp->m_SendSample.size += frame->size;
- } else {
- char tmp[160];
- int tmp_cnt = FRAME_TIME * audiortp->m_send_clock / 1000 * audiortp->m_send_samplebit / 8;
- memset(tmp, 0, tmp_cnt);
- memcpy(audiortp->m_SendSample.buffer + audiortp->m_SendSample.size, tmp, tmp_cnt);
- audiortp->m_SendSample.size += tmp_cnt;
- }
- if (audiortp->m_SendSample.size >= (unsigned long)audiortp->m_send_psize) {
- //printf("send out %d\n", audiortp->m_send_psize);
- rtp_session_send_hook(audiortp->m_rtpsession, 0,
- audiortp->m_send_pt, 0, audiortp->m_send_ptime*audiortp->m_send_clock/1000,
- audiortp->m_SendSample.buffer, audiortp->m_send_psize, audiortp->m_on_send_hook, audiortp->m_hook_data);
- if (audiortp->m_SendSample.size > (unsigned long)audiortp->m_send_psize) {
- audiortp->m_SendSample.size -= audiortp->m_send_psize;
- memmove(audiortp->m_SendSample.buffer,
- audiortp->m_SendSample.buffer+audiortp->m_send_psize,
- audiortp->m_SendSample.size);
- } else {
- audiortp->m_SendSample.size = 0;
- }
- }
- } else {
- int delta_ts = audiortp->m_send_ptime*audiortp->m_send_clock/1000;
- rtp_session_send_hook(audiortp->m_rtpsession, 0,
- audiortp->m_send_pt, 0, delta_ts, frame->buffer, audiortp->m_send_psize, audiortp->m_on_send_hook, audiortp->m_hook_data);
- if (frame->size > (unsigned long)audiortp->m_send_psize) {
- audiortp->m_SendSample.size = frame->size-audiortp->m_send_psize;
- memcpy(audiortp->m_SendSample.buffer,
- frame->buffer+audiortp->m_send_psize,
- audiortp->m_SendSample.size);
- }
- }
- return APR_SUCCESS;
- }
- static audiostream_vtbl_t g_stream_vtbl = {
- &read_frame,
- &write_frame,
- };
- void audiortp_destroy(audiortp_t *self)
- {
- audiortp_t *audiortp = (audiortp_t *)self;
- DeleteCriticalSection(&audiortp->m_dtmf_lock);
- }
- apr_status_t audiortp_create(apr_pool_t *pool, audioengine_t *engine, rtp_session_t *sess, audiortp_t **p_audiortp)
- {
- audiortp_t *audiortp;
- audiortp = apr_palloc(pool, sizeof(audiortp_t));
- memset(audiortp, 0, sizeof(audiortp_t));
- audiostream_init(engine, &g_stream_vtbl, &audiortp->base);
- audiortp->m_rtpsession = sess;
- audiortp->m_SendSample.buffer = apr_palloc(pool, SUGGEST_FRAME_SIZE);
- audiortp->m_SendSample.size = 0;
- audiortp->m_SendSample.dtmf = 0;
- audiortp->m_RecvSample.buffer = apr_palloc(pool, SUGGEST_FRAME_SIZE);
- audiortp->m_RecvSample.size = 0;
- audiortp->m_RecvSample.dtmf = 0;
- audiortp->m_send_ptime = 0;
- audiortp->m_recv_ptime = 0;
- audiortp->m_send_psize = 0;
- audiortp->m_recv_psize = 0;
- audiortp->m_send_samplebit = 0;
- audiortp->m_recv_samplebit = 0;
- audiortp->m_timeout = -1;
- audiortp->m_send_pt = -1;
- audiortp->m_recv_pt = -1;
- audiortp->m_send_clock = 8000;
- audiortp->m_recv_clock = 8000;
- audiortp->m_send_dtmf_rd = 0;
- audiortp->m_send_dtmf_wr = 0;
- audiortp->m_recv_dtmf_cnt = 0;
- audiortp->m_recving_dtmf_ts = 0;
- audiortp->m_recving_dtmf_event.e = 1;
- audiortp->m_recving_dtmf_event.event = 0xff;
- audiortp->m_rtp_tick = 0;
- audiortp->m_last_rtp_tick = 0;
- audiortp->m_jitterbuf = 0;
- audiortp->m_on_recv_hook = NULL;
- audiortp->m_on_send_hook = NULL;
- audiortp->m_hook_data = NULL;
- InitializeCriticalSection(&audiortp->m_dtmf_lock);
- *p_audiortp = audiortp;
- return APR_SUCCESS;
- }
- apr_status_t audiortp_set_param(audiortp_t *audiortp, int flag, const void *ptr)
- {
- audiortp_t *rtp = (audiortp_t *)audiortp;
- switch (flag) {
- case AUDIO_RTP_FLAG_RECV_PTIME:
- rtp->m_recv_ptime = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_SEND_PTIME:
- rtp->m_send_ptime = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_RECV_PT:
- rtp->m_recv_pt = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_SEND_PT:
- rtp->m_send_pt = *(const int*)ptr;
- break;
- case AUDIO_RTP_FLAG_TIMEOUT:
- rtp->m_timeout = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_SEND_DTMF:
- rtp->m_send_dtmf_pt = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_RECV_DTMF:
- rtp->m_recv_dtmf_pt = *(const int *)ptr;
- break;
- case AUDIO_RTP_FLAG_SEND_CLOCK:
- rtp->m_send_clock = *(const int*)ptr;
- break;
- case AUDIO_RTP_FLAG_RECV_CLOCK:
- rtp->m_recv_clock = *(const int*)ptr;
- break;
- case AUDIO_RTP_FLAG_SEND_HOOK:
- rtp->m_on_send_hook = /**(void (**)(const char*,int,void*))*/(void*)ptr;
- break;
- case AUDIO_RTP_FLAG_RECV_HOOK:
- rtp->m_on_recv_hook = /**(void (**)(const char*,int,void*))*/(void*)ptr;
- break;
- case AUDIO_RTP_FLAG_HOOK_ARG:
- rtp->m_hook_data = /**(void**)*/(void*)ptr;
- break;
- default:
- return APR_BADARG;
- }
- return APR_SUCCESS;
- }
- apr_status_t audiortp_get_param(audiortp_t *audiortp, int flag, void *ptr)
- {
- audiortp_t *rtp = (audiortp_t *)audiortp;
- switch (flag) {
- case AUDIO_RTP_FLAG_RECV_PTIME:
- *(int *)ptr = rtp->m_recv_ptime;
- break;
- case AUDIO_RTP_FLAG_SEND_PTIME:
- *(int *)ptr = rtp->m_send_ptime;
- break;
- case AUDIO_RTP_FLAG_RECV_PT:
- *(int *)ptr = rtp->m_recv_pt;
- break;
- case AUDIO_RTP_FLAG_SEND_PT:
- *(int*)ptr = rtp->m_send_pt;
- break;
- case AUDIO_RTP_FLAG_TIMEOUT:
- *(int *)ptr = rtp->m_timeout;
- break;
- case AUDIO_RTP_FLAG_SEND_DTMF:
- *(int *)ptr = rtp->m_send_dtmf_pt;
- break;
- case AUDIO_RTP_FLAG_RECV_DTMF:
- *(int *)ptr = rtp->m_recv_dtmf_pt;
- break;
- case AUDIO_RTP_FLAG_SEND_CLOCK:
- *(int*)ptr = rtp->m_send_clock;
- break;
- case AUDIO_RTP_FLAG_RECV_CLOCK:
- *(int*)ptr = rtp->m_recv_clock;
- break;
- case AUDIO_RTP_FLAG_SEND_HOOK:
- *(void (**)(const char*,int,void*))ptr = rtp->m_on_send_hook;
- break;
- case AUDIO_RTP_FLAG_RECV_HOOK:
- *(void (**)(const char*,int,void*))ptr = rtp->m_on_recv_hook;
- break;
- case AUDIO_RTP_FLAG_HOOK_ARG:
- *(void**)ptr = rtp->m_hook_data;
- break;
- default:
- return APR_BADARG;
- }
- return APR_SUCCESS;
- }
- apr_status_t audiortp_init(audiortp_t *ar)
- {
- audiortp_t *audiortp = (audiortp_t *)ar;
- audiortp->m_send_samplebit = pt2bitsample(audiortp->m_send_pt);
- audiortp->m_recv_samplebit = pt2bitsample(audiortp->m_recv_pt);
- audiortp->m_send_psize = audiortp->m_send_ptime * audiortp->m_send_clock / 1000 * audiortp->m_send_samplebit / 8;
- audiortp->m_recv_psize = audiortp->m_recv_ptime * audiortp->m_recv_clock / 1000 * audiortp->m_recv_samplebit / 8;
- audiortp->m_jbuf_ptime = audiortp->m_recv_ptime;
- audiortp->m_jbuf_psize = audiortp->m_jbuf_ptime * audiortp->m_recv_clock / 1000 * audiortp->m_recv_samplebit / 8;
- jbuf_create(audiortp->m_jbuf_psize, audiortp->m_jbuf_ptime, JB_MAX, &audiortp->m_jitterbuf);
- jbuf_set_adaptive(audiortp->m_jitterbuf, 0, 7, JB_MAX);
- DEBUG_TRACE("audiortp init, send_psize:%d, recv_psize:%d", audiortp->m_send_psize, audiortp->m_recv_psize);
- return APR_SUCCESS;
- }
- apr_status_t audiortp_term(audiortp_t *self)
- {
- audiortp_t *audiortp = (audiortp_t *)self;
- jbuf_destroy(audiortp->m_jitterbuf);
- audiortp->m_jitterbuf = 0;
- return APR_SUCCESS;
- }
- apr_status_t audiortp_send_dtmf(audiortp_t *self, const char *digits, unsigned cnt)
- {
- audiortp_t *audiortp = (audiortp_t *)self;
- unsigned count = 0;
- if (!(audiostream_get_direction(&audiortp->base)&STREAM_DIR_WRITE)) {
- AUDIO_LOG_ERROR("audio rtp cannot used for send!");
- return APR_EGENERAL;
- }
- if (!digits || !cnt)
- return -1;
- if (!(audiostream_get_direction(&audiortp->base)&STREAM_DIR_WRITE))
- return -1;
- EnterCriticalSection(&audiortp->m_dtmf_lock);
- while (CIRC_LEN(audiortp->m_send_dtmf_rd, audiortp->m_send_dtmf_wr, MAX_DTMF) < MAX_DTMF-1 && count < cnt) {
- rtp_dtmf_event *dtmf = &audiortp->m_send_dtmf[audiortp->m_send_dtmf_wr];
- dtmf->event = (unsigned char)digit2event(digits[count]);
- dtmf->e_vol = DTMF_VOLUME;
- dtmf->p = 0;
- dtmf->e = 0;
- dtmf->duration = 0;
- audiortp->m_send_dtmf_wr = CIRC_INC(audiortp->m_send_dtmf_wr, MAX_DTMF);
- count ++;
- }
- LeaveCriticalSection(&audiortp->m_dtmf_lock);
- return APR_SUCCESS;
- }
- apr_status_t audiortp_recv_dtmf(audiortp_t *self, char *digits, unsigned *cnt)
- {
- audiortp_t *audiortp = (audiortp_t *)self;
- unsigned count = 0;
- int i = 0;
- if (!(audiostream_get_direction(&audiortp->base)&STREAM_DIR_READ)) {
- AUDIO_LOG_ERROR("audio rtp cannot used for recv!");
- return APR_EGENERAL;
- }
- if (!digits)
- return APR_BADARG;
- EnterCriticalSection(&audiortp->m_dtmf_lock);
- while (count < *cnt && i < audiortp->m_recv_dtmf_cnt) {
- digits[count++] = audiortp->m_recv_dtmf[i++];
- }
- if (i < audiortp->m_recv_dtmf_cnt)
- memmove(&audiortp->m_recv_dtmf[0], &audiortp->m_recv_dtmf[i], audiortp->m_recv_dtmf_cnt-i);
- audiortp->m_recv_dtmf_cnt -= i;
- *cnt = count;
- LeaveCriticalSection(&audiortp->m_dtmf_lock);
- return APR_SUCCESS;
- }
- apr_status_t audiortp_reset_jitter(audiortp_t *audiortp)
- {
- jbuf_reset(audiortp->m_jitterbuf);
- return APR_SUCCESS;
- }
|