static switch_bool_t telecast_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_buffer_t *buffer = (switch_buffer_t *) user_data; uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; switch (type) { case SWITCH_ABC_TYPE_INIT: break; case SWITCH_ABC_TYPE_CLOSE: break; case SWITCH_ABC_TYPE_READ_PING: if (buffer) { if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { switch_buffer_lock(buffer); switch_buffer_write(buffer, frame.data, frame.datalen); switch_buffer_unlock(buffer); } } else { return SWITCH_FALSE; } break; case SWITCH_ABC_TYPE_READ: case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
/** * Process a buffer of audio data for call progress tones * * @param bug the session's media bug * @param user_data the detector * @param type the type of data available from the bug * @return SWITCH_TRUE */ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; tone_detector_t *detector = (tone_detector_t *)user_data; switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *channel = switch_core_session_get_channel(session); frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; switch(type) { case SWITCH_ABC_TYPE_INIT: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) initializing tone detector\n", switch_channel_get_name(channel)); tone_detector_init(detector); break; case SWITCH_ABC_TYPE_READ: { const char *detected_tone = NULL; if (!detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) detector is destroyed\n", switch_channel_get_name(channel)); return SWITCH_FALSE; } if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) error reading frame\n", switch_channel_get_name(channel)); return SWITCH_FALSE; } tone_detector_process_buffer(detector, frame.data, frame.samples, &detected_tone); if (detected_tone) { switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) DETECTED TONE: %s\n", switch_channel_get_name(channel), detected_tone); if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session)); switch_event_fire(&event); } } break; } case SWITCH_ABC_TYPE_WRITE: break; case SWITCH_ABC_TYPE_WRITE_REPLACE: break; case SWITCH_ABC_TYPE_READ_REPLACE: break; case SWITCH_ABC_TYPE_READ_PING: break; case SWITCH_ABC_TYPE_CLOSE: if (detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) destroying tone detector\n", switch_channel_get_name(channel)); tone_detector_destroy(detector); } break; } return SWITCH_TRUE; }
static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *channel = switch_core_session_get_channel(session); struct cap_cb *cb = (struct cap_cb *) user_data; switch (type) { case SWITCH_ABC_TYPE_INIT: break; case SWITCH_ABC_TYPE_CLOSE: { if (cb->buffer) { switch_buffer_destroy(&cb->buffer); } switch_channel_set_private(channel, "snapshot", NULL); } break; case SWITCH_ABC_TYPE_READ: if (cb->buffer) { uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; if (switch_mutex_trylock(cb->mutex) == SWITCH_STATUS_SUCCESS) { while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) { if (frame.datalen) switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen); } switch_mutex_unlock(cb->mutex); } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
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; }