SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b) { switch_input_callback_function_t dtmf_func = NULL; switch_input_args_t args; switch_channel_t *channel_a = NULL, *channel_b = NULL; const char *err = "Channels not ready\n"; if (session_a.allocated && session_a.session && session_b.allocated && session_b.session) { channel_a = switch_core_session_get_channel(session_a.session); channel_b = switch_core_session_get_channel(session_b.session); if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { session_a.begin_allow_threads(); if (!switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_media_ready(channel_a)) { switch_channel_pre_answer(channel_a); } if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) { args = session_a.get_cb_args(); // get the cb_args data structure for session a dtmf_func = args.input_callback; // get the call back function err = NULL; switch_ivr_multi_threaded_bridge(session_a.session, session_b.session, dtmf_func, args.buf, args.buf); } session_a.end_allow_threads(); } } if (err) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a.session), SWITCH_LOG_ERROR, "%s", err); } }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session, const char *function, const char *target, switch_media_bug_callback_t callback, void *user_data, time_t stop_time, switch_media_bug_flag_t flags, switch_media_bug_t **new_bug) { switch_media_bug_t *bug, *bp; switch_size_t bytes; switch_event_t *event; int tap_only = 1, punt = 0; const char *p; if (!zstr(function)) { if ((flags & SMBF_ONE_ONLY)) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (!zstr(bp->function) && !strcasecmp(function, bp->function)) { punt = 1; break; } } switch_thread_rwlock_unlock(session->bug_rwlock); } } if (punt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); } if (!switch_channel_media_ready(session->channel)) { if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } } *new_bug = NULL; if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) { flags |= SMBF_ANSWER_REQ; } #if 0 if (flags & SMBF_WRITE_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } if (flags & SMBF_READ_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_READ_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } #endif if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) { return SWITCH_STATUS_MEMERR; } bug->callback = callback; bug->user_data = user_data; bug->session = session; bug->flags = flags; bug->function = "N/A"; bug->target = "N/A"; switch_core_session_get_read_impl(session, &bug->read_impl); switch_core_session_get_write_impl(session, &bug->write_impl); if (function) { bug->function = switch_core_session_strdup(session, function); } if (target) { bug->target = switch_core_session_strdup(session, target); } bug->stop_time = stop_time; bytes = bug->read_impl.decoded_bytes_per_packet; if (!bug->flags) { bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM); } if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) { switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool); } bytes = bug->write_impl.decoded_bytes_per_packet; if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool); } if ((bug->flags & SMBF_THREAD_LOCK)) { bug->thread_id = switch_thread_self(); } if (bug->callback) { switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT); if (result == SWITCH_FALSE) { switch_core_media_bug_destroy(bug); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n", switch_channel_get_name(session->channel)); return SWITCH_STATUS_GENERR; } } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel)); bug->ready = 1; switch_thread_rwlock_wrlock(session->bug_rwlock); bug->next = session->bugs; session->bugs = bug; for(bp = session->bugs; bp; bp = bp->next) { if (bp->ready && !switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { tap_only = 0; } } switch_thread_rwlock_unlock(session->bug_rwlock); *new_bug = bug; if (tap_only) { switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } else { switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { switch_status_t status = SWITCH_STATUS_FALSE; switch_frame_t *enc_frame = NULL, *write_frame = frame; unsigned int flag = 0, need_codec = 0, perfect = 0, do_bugs = 0, do_write = 0, do_resample = 0, ptime_mismatch = 0, pass_cng = 0, resample = 0; int did_write_resample = 0; switch_assert(session != NULL); switch_assert(frame != NULL); if (!switch_channel_ready(session->channel)) { return SWITCH_STATUS_FALSE; } if (switch_mutex_trylock(session->codec_write_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_write_mutex); } else { return SWITCH_STATUS_SUCCESS; } if (switch_test_flag(frame, SFF_CNG)) { if (switch_channel_test_flag(session->channel, CF_ACCEPT_CNG)) { pass_cng = 1; } else { return SWITCH_STATUS_SUCCESS; } } if (!(session->write_codec && switch_core_codec_ready(session->write_codec)) && !pass_cng) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no write codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); return SWITCH_STATUS_FALSE; } if (switch_channel_test_flag(session->channel, CF_HOLD)) { return SWITCH_STATUS_SUCCESS; } if (switch_test_flag(frame, SFF_PROXY_PACKET) || pass_cng) { /* Fast PASS! */ switch_mutex_lock(session->codec_write_mutex); status = perform_write(session, frame, flag, stream_id); switch_mutex_unlock(session->codec_write_mutex); return status; } switch_mutex_lock(session->codec_write_mutex); if (!(frame->codec && frame->codec->implementation)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has received a bad frame with no codec!\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_mutex_unlock(session->codec_write_mutex); return SWITCH_STATUS_FALSE; } switch_assert(frame->codec != NULL); switch_assert(frame->codec->implementation != NULL); if (!(switch_core_codec_ready(session->write_codec) && frame->codec) || !switch_channel_ready(session->channel) || !switch_channel_media_ready(session->channel)) { switch_mutex_unlock(session->codec_write_mutex); return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->write_codec->mutex); switch_mutex_lock(frame->codec->mutex); if (!(switch_core_codec_ready(session->write_codec) && switch_core_codec_ready(frame->codec))) goto error; if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) { if (session->write_impl.codec_id == frame->codec->implementation->codec_id || session->write_impl.microseconds_per_packet != frame->codec->implementation->microseconds_per_packet) { ptime_mismatch = TRUE; if ((switch_test_flag(frame->codec, SWITCH_CODEC_FLAG_PASSTHROUGH) || switch_test_flag(session->read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH)) || switch_channel_test_flag(session->channel, CF_PASSTHRU_PTIME_MISMATCH)) { status = perform_write(session, frame, flags, stream_id); goto error; } } need_codec = TRUE; } if (session->write_codec && !frame->codec) { need_codec = TRUE; } if (session->bugs && !need_codec) { do_bugs = TRUE; need_codec = TRUE; } if (frame->codec->implementation->actual_samples_per_second != session->write_impl.actual_samples_per_second) { need_codec = TRUE; do_resample = TRUE; } if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_WRITE_CODEC_RESET); switch_core_session_rwunlock(other_session); } switch_clear_flag(session, SSF_WRITE_TRANSCODE); } if (switch_test_flag(session, SSF_WRITE_CODEC_RESET)) { switch_core_codec_reset(session->write_codec); switch_clear_flag(session, SSF_WRITE_CODEC_RESET); } if (!need_codec) { do_write = TRUE; write_frame = frame; goto done; } if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY; switch_core_session_receive_message(session, &msg); switch_set_flag(session, SSF_WARN_TRANSCODE); } if (frame->codec) { session->raw_write_frame.datalen = session->raw_write_frame.buflen; status = switch_core_codec_decode(frame->codec, session->write_codec, frame->data, frame->datalen, session->write_impl.actual_samples_per_second, session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags); if (do_resample && status == SWITCH_STATUS_SUCCESS) { status = SWITCH_STATUS_RESAMPLE; } switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; write_frame = &session->raw_write_frame; write_frame->rate = frame->codec->implementation->actual_samples_per_second; if (!session->write_resampler) { switch_mutex_lock(session->resample_mutex); status = switch_resample_create(&session->write_resampler, frame->codec->implementation->actual_samples_per_second, session->write_impl.actual_samples_per_second, session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { goto done; } } break; case SWITCH_STATUS_SUCCESS: session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t); session->raw_write_frame.timestamp = frame->timestamp; session->raw_write_frame.rate = frame->rate; session->raw_write_frame.m = frame->m; session->raw_write_frame.ssrc = frame->ssrc; session->raw_write_frame.seq = frame->seq; session->raw_write_frame.payload = frame->payload; session->raw_write_frame.flags = 0; if (switch_test_flag(frame, SFF_PLC)) { session->raw_write_frame.flags |= SFF_PLC; } write_frame = &session->raw_write_frame; break; case SWITCH_STATUS_BREAK: status = SWITCH_STATUS_SUCCESS; goto error; case SWITCH_STATUS_NOOP: if (session->write_resampler) { switch_mutex_lock(session->resample_mutex); switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); switch_mutex_unlock(session->resample_mutex); } write_frame = frame; status = SWITCH_STATUS_SUCCESS; break; default: if (status == SWITCH_STATUS_NOT_INITALIZED) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); goto error; } if (ptime_mismatch) { status = perform_write(session, frame, flags, stream_id); status = SWITCH_STATUS_SUCCESS; goto error; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n", frame->codec->codec_interface->interface_name); goto error; } } if (session->write_resampler) { short *data = write_frame->data; switch_mutex_lock(session->resample_mutex); if (session->write_resampler) { switch_resample_process(session->write_resampler, data, write_frame->datalen / 2); memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2); write_frame->samples = session->write_resampler->to_len; write_frame->datalen = write_frame->samples * 2; write_frame->rate = session->write_resampler->to_rate; did_write_resample = 1; } switch_mutex_unlock(session->resample_mutex); } if (session->bugs) { switch_media_bug_t *bp; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { switch_bool_t ok = SWITCH_TRUE; if (!bp->ready) { continue; } if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (switch_test_flag(bp, SMBF_WRITE_STREAM)) { switch_mutex_lock(bp->write_mutex); switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen); switch_mutex_unlock(bp->write_mutex); if (bp->callback) { ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE); } } if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { do_bugs = 0; if (bp->callback) { bp->write_replace_frame_in = write_frame; bp->write_replace_frame_out = write_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) { write_frame = bp->write_replace_frame_out; } } } if (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) { ok = SWITCH_FALSE; } if (ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } if (do_bugs) { do_write = TRUE; write_frame = frame; goto done; } if (session->write_codec) { if (!ptime_mismatch && write_frame->codec && write_frame->codec->implementation && write_frame->codec->implementation->decoded_bytes_per_packet == session->write_impl.decoded_bytes_per_packet) { perfect = TRUE; } if (perfect) { if (write_frame->datalen < session->write_impl.decoded_bytes_per_packet) { memset(write_frame->data, 255, session->write_impl.decoded_bytes_per_packet - write_frame->datalen); write_frame->datalen = session->write_impl.decoded_bytes_per_packet; } enc_frame = write_frame; session->enc_write_frame.datalen = session->enc_write_frame.buflen; status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, session->write_impl.actual_samples_per_second, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */ case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); if (frame->codec->implementation->samples_per_packet != session->write_impl.samples_per_packet) { session->enc_write_frame.timestamp = 0; } else { session->enc_write_frame.timestamp = frame->timestamp; } session->enc_write_frame.payload = session->write_impl.ianacode; session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.seq = frame->seq; write_frame = &session->enc_write_frame; break; case SWITCH_STATUS_NOOP: enc_frame->codec = session->write_codec; enc_frame->samples = enc_frame->datalen / sizeof(int16_t); enc_frame->timestamp = frame->timestamp; enc_frame->m = frame->m; enc_frame->seq = frame->seq; enc_frame->ssrc = frame->ssrc; enc_frame->payload = enc_frame->codec->implementation->ianacode; write_frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); write_frame = NULL; goto error; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n", session->read_codec->codec_interface->interface_name); write_frame = NULL; goto error; } if (flag & SFF_CNG) { switch_set_flag(write_frame, SFF_CNG); } status = perform_write(session, write_frame, flags, stream_id); goto error; } else { if (!session->raw_write_buffer) { switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Write Buffer at %u bytes to accommodate %u->%u\n", (uint32_t) bytes_per_packet, write_frame->datalen, session->write_impl.decoded_bytes_per_packet); if ((status = switch_buffer_create_dynamic(&session->raw_write_buffer, bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES, bytes_per_packet * SWITCH_BUFFER_START_FRAMES, 0)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer Failed!\n"); goto error; } } if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen); status = SWITCH_STATUS_MEMERR; goto error; } status = SWITCH_STATUS_SUCCESS; while (switch_buffer_inuse(session->raw_write_buffer) >= session->write_impl.decoded_bytes_per_packet) { int rate; if (switch_channel_down(session->channel) || !session->raw_write_buffer) { goto error; } if ((session->raw_write_frame.datalen = (uint32_t) switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, session->write_impl.decoded_bytes_per_packet)) == 0) { goto error; } enc_frame = &session->raw_write_frame; session->raw_write_frame.rate = session->write_impl.actual_samples_per_second; session->enc_write_frame.datalen = session->enc_write_frame.buflen; session->enc_write_frame.timestamp = 0; if (frame->codec && frame->codec->implementation && switch_core_codec_ready(frame->codec)) { rate = frame->codec->implementation->actual_samples_per_second; } else { rate = session->write_impl.actual_samples_per_second; } status = switch_core_codec_encode(session->write_codec, frame->codec, enc_frame->data, enc_frame->datalen, rate, session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: resample++; session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; write_frame = &session->enc_write_frame; if (!session->write_resampler) { switch_mutex_lock(session->resample_mutex); if (!session->write_resampler) { status = switch_resample_create(&session->write_resampler, frame->codec->implementation->actual_samples_per_second, session->write_impl.actual_samples_per_second, session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); } switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { goto done; } } break; case SWITCH_STATUS_SUCCESS: session->enc_write_frame.codec = session->write_codec; session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t); session->enc_write_frame.m = frame->m; session->enc_write_frame.ssrc = frame->ssrc; session->enc_write_frame.payload = session->write_impl.ianacode; write_frame = &session->enc_write_frame; break; case SWITCH_STATUS_NOOP: if (session->write_resampler) { switch_mutex_lock(session->resample_mutex); if (session->write_resampler) { switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); } switch_mutex_unlock(session->resample_mutex); } enc_frame->codec = session->write_codec; enc_frame->samples = enc_frame->datalen / sizeof(int16_t); enc_frame->m = frame->m; enc_frame->ssrc = frame->ssrc; enc_frame->payload = enc_frame->codec->implementation->ianacode; write_frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); write_frame = NULL; goto error; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n", session->read_codec->codec_interface->interface_name, status); write_frame = NULL; goto error; } if (!did_write_resample && session->read_resampler) { short *data = write_frame->data; switch_mutex_lock(session->resample_mutex); if (session->read_resampler) { switch_resample_process(session->read_resampler, data, write_frame->datalen / 2); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2); write_frame->samples = session->read_resampler->to_len; write_frame->datalen = session->read_resampler->to_len * 2; write_frame->rate = session->read_resampler->to_rate; } switch_mutex_unlock(session->resample_mutex); } if (flag & SFF_CNG) { switch_set_flag(write_frame, SFF_CNG); } if (ptime_mismatch || resample) { write_frame->timestamp = 0; } if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { break; } } goto error; } } done: if (ptime_mismatch || resample) { write_frame->timestamp = 0; } if (do_write) { status = perform_write(session, write_frame, flags, stream_id); } error: switch_mutex_unlock(session->write_codec->mutex); switch_mutex_unlock(frame->codec->mutex); switch_mutex_unlock(session->codec_write_mutex); return status; }
SWITCH_DECLARE(bool) CoreSession::mediaReady() { this_check(false); sanity_check(false); return switch_channel_media_ready(channel) != 0; }
static switch_bool_t ladspa_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_ladspa_t *pvt = (switch_ladspa_t *) user_data; //switch_frame_t *frame = NULL; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch (type) { case SWITCH_ABC_TYPE_INIT: { switch_codec_implementation_t read_impl = { 0 }; LADSPA_PortDescriptor port_desc; int i = 0, j = 0, k = 0, str_idx = 0; switch_core_session_get_read_impl(pvt->session, &read_impl); if (!(pvt->library_handle = loadLADSPAPluginLibrary(pvt->plugin_name))) { return SWITCH_FALSE; } if (!(pvt->ldesc = findLADSPAPluginDescriptor(pvt->library_handle, pvt->plugin_name, pvt->label_name))) { return SWITCH_FALSE; } pvt->handle = pvt->ldesc->instantiate(pvt->ldesc, read_impl.actual_samples_per_second); dump_info(pvt->ldesc); for (i = 0; i < pvt->ldesc->PortCount; i++) { port_desc = pvt->ldesc->PortDescriptors[i]; if (LADSPA_IS_PORT_CONTROL(port_desc) && LADSPA_IS_PORT_INPUT(port_desc)) { LADSPA_Data dft = 0.0f; int found = find_default(pvt->ldesc, i, &dft); if (found && !pvt->has_config[j]) { pvt->config[j] = dft; pvt->has_config[j] = 1; } if (pvt->has_config[j]) { if (!check_range(pvt->ldesc, i, pvt->config[j])) { pvt->config[j] = dft; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_WARNING, "FALLING TO DEFAULT PARAM %d [%s] (%f)\n", j+1, pvt->ldesc->PortNames[i], pvt->config[j]); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "ADDING PARAM %d [%s] (%f)\n", j+1, pvt->ldesc->PortNames[i], pvt->config[j]); pvt->ldesc->connect_port(pvt->handle, i, &pvt->config[j++]); usleep(10000); } } if (LADSPA_IS_PORT_INPUT(port_desc) && LADSPA_IS_PORT_AUDIO(port_desc)) { int mapped = 0; if (pvt->str_idx && !zstr(pvt->str_config[str_idx])) { if (!strcasecmp(pvt->str_config[str_idx], "none")) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT NOTHING to port: %s\n", pvt->ldesc->PortNames[i] ); mapped = 1; } else if (!strncasecmp(pvt->str_config[str_idx], "file:", 5)) { char *file = pvt->str_config[str_idx] + 5; if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "CAN'T CONNECT FILE [%s] File already mapped\n", file); } else { if (switch_core_file_open(&pvt->fh, file, read_impl.number_of_channels, read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file); return SWITCH_FALSE; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT FILE [%s] to port: %s\n", file, pvt->ldesc->PortNames[i] ); pvt->ldesc->connect_port(pvt->handle, i, pvt->file_buf); mapped = 1; } } str_idx++; } if (!mapped) { pvt->ldesc->connect_port(pvt->handle, i, pvt->in_buf); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT CHANNEL AUDIO to port: %s\n", pvt->ldesc->PortNames[i] ); } } if (LADSPA_IS_PORT_OUTPUT(port_desc)) { if (LADSPA_IS_PORT_AUDIO(port_desc)) { pvt->ldesc->connect_port(pvt->handle, i, pvt->out_buf); } else if (k < MAX_INDEX) { pvt->ldesc->connect_port(pvt->handle, i, &pvt->out_ports[k++]); } } } } break; case SWITCH_ABC_TYPE_CLOSE: { if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&pvt->fh); } if (pvt->handle && pvt->ldesc) { pvt->ldesc->cleanup(pvt->handle); } if (pvt->library_handle) { unloadLADSPAPluginLibrary(pvt->library_handle); } } break; case SWITCH_ABC_TYPE_WRITE_REPLACE: case SWITCH_ABC_TYPE_READ_REPLACE: { switch_frame_t *rframe; int16_t *slin, abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; switch_size_t olen = 0; if (type == SWITCH_ABC_TYPE_READ_REPLACE) { rframe = switch_core_media_bug_get_read_replace_frame(bug); } else { rframe = switch_core_media_bug_get_write_replace_frame(bug); } slin = rframe->data; if (switch_channel_media_ready(channel)) { switch_short_to_float(slin, pvt->in_buf, rframe->samples); if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) { olen = rframe->samples; if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) { switch_codec_implementation_t read_impl = { 0 }; char *file = switch_core_session_strdup(pvt->session, pvt->fh.file_path); switch_core_session_get_read_impl(pvt->session, &read_impl); switch_core_file_close(&pvt->fh); if (switch_core_file_open(&pvt->fh, file, read_impl.number_of_channels, read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file); return SWITCH_FALSE; } olen = rframe->samples; if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot READ file: %s\n", file); return SWITCH_FALSE; } } switch_short_to_float(abuf, pvt->file_buf, olen); } pvt->ldesc->run(pvt->handle, rframe->samples); switch_float_to_short(pvt->out_buf, slin, rframe->samples); } if (type == SWITCH_ABC_TYPE_READ_REPLACE) { switch_core_media_bug_set_read_replace_frame(bug, rframe); } else { switch_core_media_bug_set_write_replace_frame(bug, rframe); } if (pvt->skip && !--pvt->skip) { return SWITCH_FALSE; } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }