FS-5302 --resolve

This commit is contained in:
Anthony Minessale 2013-04-19 15:25:11 -05:00 committed by Brian West
parent e1da1e7b38
commit f92528436f
2 changed files with 90 additions and 52 deletions

View File

@ -52,10 +52,12 @@ typedef struct oreka_session_s {
uint32_t read_cnt;
uint32_t write_cnt;
switch_media_bug_t *read_bug;
switch_media_bug_t *write_bug;
//switch_media_bug_t *write_bug;
switch_event_t *invite_extra_headers;
switch_event_t *bye_extra_headers;
int usecnt;
switch_audio_resampler_t *read_resampler;
switch_audio_resampler_t *write_resampler;
} oreka_session_t;
struct {
@ -117,6 +119,7 @@ static int oreka_setup_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
const char *err = "unknown error";
const char *type_str = type == FS_OREKA_READ ? "read" : "write";
if (type == FS_OREKA_READ) {
status = switch_core_session_get_read_impl(oreka->session, &oreka->read_impl);
codec_impl = &oreka->read_impl;
@ -150,6 +153,10 @@ static int oreka_setup_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
res = -1;
goto done;
}
switch_rtp_intentional_bugs(rtp_stream, RTP_BUG_SEND_LINEAR_TIMESTAMPS);
done:
if (res == -1) {
if (rtp_port) {
@ -379,57 +386,105 @@ done:
return rc;
}
static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type, oreka_stream_type_t stype, const char *stype_str)
static switch_bool_t oreka_audio_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
oreka_session_t *oreka = user_data;
switch_core_session_t *session = oreka->session;
switch_frame_t pcmu_frame;
switch_frame_t linear_frame = { 0 };
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_frame_t pcmu_frame = { 0 };
switch_frame_t *linear_frame;
uint8_t pcmu_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint8_t linear_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint8_t resample_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint32_t linear_len = 0;
uint32_t i = 0;
int16_t *linear_samples = NULL;
if (type == SWITCH_ABC_TYPE_READ || type == SWITCH_ABC_TYPE_WRITE) {
memset(&linear_frame, 0, sizeof(linear_frame));
linear_frame.data = linear_data;
linear_frame.buflen = sizeof(linear_data);
status = switch_core_media_bug_read(bug, &linear_frame, SWITCH_TRUE);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error reading media bug: %d\n", status);
goto done;
}
if (!linear_frame.datalen) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Linear frame with no length!\n");
goto done;
}
if (type == SWITCH_ABC_TYPE_READ_REPLACE || type == SWITCH_ABC_TYPE_WRITE_REPLACE) {
int16_t *data;
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
linear_frame = switch_core_media_bug_get_read_replace_frame(bug);
if (oreka->read_resampler) {
data = (int16_t *) linear_frame->data;
switch_resample_process(oreka->read_resampler, data, (int) linear_frame->datalen / 2);
linear_len = oreka->read_resampler->to_len * 2;
memcpy(resample_data, oreka->read_resampler->to, linear_len);
linear_samples = (int16_t *)resample_data;
} else {
linear_samples = linear_frame->data;
linear_len = linear_frame->datalen;
}
}
if (type == SWITCH_ABC_TYPE_WRITE_REPLACE) {
linear_frame = switch_core_media_bug_get_write_replace_frame(bug);
if (oreka->write_resampler) {
data = (int16_t *) linear_frame->data;
switch_resample_process(oreka->write_resampler, data, (int) linear_frame->datalen / 2);
linear_len = oreka->write_resampler->to_len * 2;
memcpy(resample_data, oreka->write_resampler->to, linear_len);
linear_samples = (int16_t *)resample_data;
} else {
linear_samples = linear_frame->data;
linear_len = linear_frame->datalen;
}
}
/* convert the L16 frame into PCMU */
linear_samples = linear_frame.data;
memset(&pcmu_frame, 0, sizeof(pcmu_frame));
for (i = 0; i < linear_frame.datalen/sizeof(int16_t); i++) {
for (i = 0; i < linear_len / sizeof(int16_t); i++) {
pcmu_data[i] = linear_to_ulaw(linear_samples[i]);
}
pcmu_frame.source = __FUNCTION__;
pcmu_frame.data = pcmu_data;
pcmu_frame.datalen = i;
pcmu_frame.datalen = i;
pcmu_frame.payload = 0;
}
switch (type) {
case SWITCH_ABC_TYPE_INIT:
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Starting Oreka recording for %s stream\n", stype_str);
oreka_send_sip_message(oreka, FS_OREKA_START, stype);
switch_codec_implementation_t read_impl;
switch_core_session_get_read_impl(session, &read_impl);
if (read_impl.actual_samples_per_second != 8000) {
switch_resample_create(&oreka->read_resampler,
read_impl.actual_samples_per_second,
8000,
320, SWITCH_RESAMPLE_QUALITY, 1);
switch_resample_create(&oreka->write_resampler,
read_impl.actual_samples_per_second,
8000,
320, SWITCH_RESAMPLE_QUALITY, 1);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Starting Oreka recording for audio stream\n");
oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_READ);
oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_WRITE);
}
break;
case SWITCH_ABC_TYPE_CLOSE:
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Stopping Oreka recording for %s stream\n", stype_str);
oreka_send_sip_message(oreka, FS_OREKA_STOP, stype);
if (oreka->read_resampler) {
switch_resample_destroy(&oreka->read_resampler);
}
if (oreka->write_resampler) {
switch_resample_destroy(&oreka->write_resampler);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Stopping Oreka recording for audio stream\n");
oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_READ);
oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_WRITE);
}
break;
case SWITCH_ABC_TYPE_READ:
case SWITCH_ABC_TYPE_READ_REPLACE:
{
if (pcmu_frame.datalen) {
if (switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame) > 0) {
@ -443,7 +498,7 @@ static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_dat
}
}
break;
case SWITCH_ABC_TYPE_WRITE:
case SWITCH_ABC_TYPE_WRITE_REPLACE:
{
if (pcmu_frame.datalen) {
if (switch_rtp_write_frame(oreka->write_rtp_stream, &pcmu_frame) > 0) {
@ -460,19 +515,10 @@ static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_dat
default:
break;
}
done:
return SWITCH_TRUE;
}
static switch_bool_t oreka_read_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
return oreka_core_callback(bug, user_data, type, FS_OREKA_READ, "read");
}
static switch_bool_t oreka_write_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
return oreka_core_callback(bug, user_data, type, FS_OREKA_WRITE, "write");
}
SWITCH_STANDARD_APP(oreka_start_function)
{
@ -491,10 +537,6 @@ SWITCH_STANDARD_APP(oreka_start_function)
switch_core_media_bug_remove(session, &oreka->read_bug);
oreka->read_bug = NULL;
}
if (oreka->write_bug) {
switch_core_media_bug_remove(session, &oreka->write_bug);
oreka->write_bug = NULL;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Stopped oreka recorder\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run oreka recording 2 times on the same session!\n");
@ -516,22 +558,15 @@ SWITCH_STANDARD_APP(oreka_start_function)
}
oreka->session = session;
status = switch_core_media_bug_add(session, OREKA_BUG_NAME_READ, NULL, oreka_read_callback, oreka, 0,
(SMBF_READ_STREAM | SMBF_ANSWER_REQ), &bug);
status = switch_core_media_bug_add(session, OREKA_BUG_NAME_READ, NULL, oreka_audio_callback, oreka, 0,
(SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_ANSWER_REQ), &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to read media stream!\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to media stream!\n");
return;
}
oreka->read_bug = bug;
oreka->usecnt++;
bug = NULL;
status = switch_core_media_bug_add(session, OREKA_BUG_NAME_WRITE, NULL, oreka_write_callback, oreka, 0,
(SMBF_WRITE_STREAM | SMBF_ANSWER_REQ), &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to write media stream!\n");
return;
}
oreka->write_bug = bug;
oreka->usecnt++;
switch_channel_set_private(channel, OREKA_PRIVATE, oreka);

View File

@ -1303,6 +1303,9 @@ static uint8_t get_next_write_ts(switch_rtp_t *rtp_session, uint32_t timestamp)
}
} else {
rtp_session->ts += rtp_session->samples_per_interval;
if (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->ts > 0) {
rtp_session->ts = rtp_session->last_write_ts + rtp_session->samples_per_interval;
}
}
return m;