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 = { 0 }; switch_frame_t *linear_frame, raw_frame = { 0 }; uint8_t pcmu_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; uint8_t raw_data[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; 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_REPLACE || type == SWITCH_ABC_TYPE_WRITE_REPLACE || type == SWITCH_ABC_TYPE_READ_PING) { int16_t *data; if (type == SWITCH_ABC_TYPE_READ_REPLACE || type == SWITCH_ABC_TYPE_READ_PING) { if (type == SWITCH_ABC_TYPE_READ_REPLACE) { linear_frame = switch_core_media_bug_get_read_replace_frame(bug); } else { switch_status_t status; raw_frame.data = raw_data; raw_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; linear_frame = &raw_frame; status = switch_core_media_bug_read(bug, &raw_frame, SWITCH_FALSE); if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { return SWITCH_TRUE; } } 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 */ memset(&pcmu_frame, 0, sizeof(pcmu_frame)); 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.payload = 0; } switch (type) { case SWITCH_ABC_TYPE_INIT: { 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); if (!oreka->mux_streams) { oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_WRITE); } } break; case SWITCH_ABC_TYPE_CLOSE: { if (oreka->mux_streams) { int16_t *data; raw_frame.data = raw_data; raw_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; linear_frame = &raw_frame; while (switch_core_media_bug_read(bug, &raw_frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { linear_frame = &raw_frame; 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; } memset(&pcmu_frame, 0, sizeof(pcmu_frame)); 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.payload = 0; switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame); } } 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); if (!oreka->mux_streams) { oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_WRITE); } } break; case SWITCH_ABC_TYPE_READ_REPLACE: case SWITCH_ABC_TYPE_READ_PING: { if (pcmu_frame.datalen) { if (switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame) > 0) { oreka->read_cnt++; if (oreka->read_cnt < 10) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (read)\n", pcmu_frame.datalen); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (read)\n", pcmu_frame.datalen); } } } break; case SWITCH_ABC_TYPE_WRITE_REPLACE: { if (pcmu_frame.datalen) { if (switch_rtp_write_frame(oreka->write_rtp_stream, &pcmu_frame) > 0) { oreka->write_cnt++; if (oreka->write_cnt < 10) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (write)\n", pcmu_frame.datalen); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (write)\n", pcmu_frame.datalen); } } } break; default: break; } return SWITCH_TRUE; }
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) { 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; uint8_t pcmu_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; uint8_t linear_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; 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; } /* 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++) { pcmu_data[i] = linear_to_ulaw(linear_samples[i]); } pcmu_frame.source = __FUNCTION__; pcmu_frame.data = pcmu_data; 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); } 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); } break; case SWITCH_ABC_TYPE_READ: { if (pcmu_frame.datalen) { if (switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame) > 0) { oreka->read_cnt++; if (oreka->read_cnt < 10) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (read)\n", pcmu_frame.datalen); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (read)\n", pcmu_frame.datalen); } } } break; case SWITCH_ABC_TYPE_WRITE: { if (pcmu_frame.datalen) { if (switch_rtp_write_frame(oreka->write_rtp_stream, &pcmu_frame) > 0) { oreka->write_cnt++; if (oreka->write_cnt < 10) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (write)\n", pcmu_frame.datalen); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (write)\n", pcmu_frame.datalen); } } } break; default: break; } done: return SWITCH_TRUE; }