コード例 #1
0
ファイル: mod_webm.cpp プロジェクト: odmanV2/freecenter
static switch_status_t do_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
	uint32_t datalen = frame->datalen;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int is_iframe = 0;
	uint8_t *hdr = NULL;
	uint8_t start_bit;
	uint32_t used;
	bool is_key = false;
	webm_file_context_t *context = (webm_file_context_t *)handle->private_info;

	hdr = (uint8_t *)frame->data;

	switch_assert(frame->img);

	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], datalen, frame->m, start_bit, is_iframe);

	

	if (!context->video) {
		context->video_track_id = context->segment->AddVideoTrack(frame->img->d_w, frame->img->d_h, 0);
		if (!context->video_track_id) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}
		context->video = static_cast<mkvmuxer::VideoTrack*>(context->segment->GetTrackByNumber(context->video_track_id));
		context->video->SetStereoMode(0);
		context->video->set_codec_id("V_VP8");
		context->video->set_uid(0xDEADBEEF); // debug ?
	}

	buffer_vp8_packets(context, frame, &is_key);

	if (frame->m && (used = switch_buffer_inuse(context->buf))) {
		const void *data;
		int duration = 0;

		
		switch_buffer_peek_zerocopy(context->buf, &data);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VID samplecount: %u\n", context->timer.samplecount);

		switch_mutex_lock(context->mutex);
		switch_core_timer_sync(&context->timer);
		bool ret = false;
		ret = context->segment->AddFrame((const uint8_t *)data, used, context->video_track_id, context->timer.samplecount * 1000LL, is_key);
		switch_mutex_unlock(context->mutex);

		if (!ret) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add frame %d bytes, timecode: %llu\n", used, context->timer.samplecount * 1000LL);
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}

		switch_buffer_zero(context->buf);
	}

end:
	

	return status;
}
コード例 #2
0
ファイル: mod_loopback.c プロジェクト: gujun/sscore
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
{
	switch_channel_t *channel;
	private_t *tech_pvt;

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_ANSWER:
		if (tech_pvt->other_channel && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
			switch_channel_mark_answered(tech_pvt->other_channel);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_PROGRESS:
		if (tech_pvt->other_channel && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
			switch_channel_mark_pre_answered(tech_pvt->other_channel);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_BRIDGE:
		{
			switch_set_flag_locked(tech_pvt, TFLAG_BRIDGE);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
		{
			switch_clear_flag_locked(tech_pvt, TFLAG_BRIDGE);
		}
		break;
	default:
		break;
	}

	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_BRIDGE:
	case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
	case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
		{
			void *pop;

			while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
				switch_frame_t *frame = (switch_frame_t *) pop;
				switch_frame_free(&frame);
			}

			while (switch_queue_trypop(tech_pvt->other_tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
				switch_frame_t *frame = (switch_frame_t *) pop;
				switch_frame_free(&frame);
			}

			switch_core_timer_sync(&tech_pvt->timer);

		}
		break;
	default:
		break;
	}


	return SWITCH_STATUS_SUCCESS;
}
コード例 #3
0
ファイル: mod_mp4v2.c プロジェクト: odmanV2/freecenter
static switch_status_t do_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
	uint32_t datalen = frame->datalen;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int is_iframe = 0;
	uint32_t size;
	uint8_t *hdr = NULL;
	uint8_t fragment_type;
	uint8_t nal_type;
	uint8_t start_bit;
	mp4_file_context_t *context = handle->private_info;

	hdr = (uint8_t *)frame->data;
	fragment_type = hdr[0] & 0x1f;
	nal_type = hdr[1] & 0x1f;
	start_bit = hdr[1] & 0x80;
	is_iframe = (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5 || fragment_type ==7 || fragment_type ==8) ? 1 : 0;

	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], datalen, frame->m, start_bit, is_iframe);

	size = htonl(datalen);
	switch_buffer_write(context->buf, &size, 4);
	switch_buffer_write(context->buf, hdr, datalen);

	switch_mutex_lock(context->mutex);

	if (fragment_type == 7 && !context->sps_set) { //sps
		context->sps_set = 1;

		init_video_track(context->fd, &context->video, frame);
		if (context->video == MP4_INVALID_TRACK_ID) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}
	} else if (fragment_type == 8 && context->sps_set && !context->pps_set) { //pps
		MP4AddH264PictureParameterSet(context->fd, context->video, hdr, datalen);
		context->pps_set = 1;
	}

	if (nal_type == 7 || nal_type == 8 || frame->m == 0) {
	} else if (context->sps_set && context->pps_set) {
		uint32_t used = switch_buffer_inuse(context->buf);
		const void *data;
		int duration = 0;

		if (!context->timer.interval) {
			switch_core_timer_init(&context->timer, "soft", 1, 1, context->pool);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
		} else {
			switch_core_timer_sync(&context->timer);
		}

		duration = context->timer.samplecount - context->last_pts;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);
		switch_buffer_peek_zerocopy(context->buf, &data);

		if (context->last_pts == 0) { // first img, write at the very beginning so we don't see blank screen
			duration /= 2;
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);

			if (duration > context->offset) {
				duration -= context->offset;
			} else {
				duration = 0;
			}
		}

		context->last_pts = context->timer.samplecount;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);

		if (duration) {
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);
		}
		switch_buffer_zero(context->buf);
	}

end:
	switch_mutex_unlock(context->mutex);

	return status;
}
コード例 #4
0
ファイル: mod_mp4v2.c プロジェクト: odmanV2/freecenter
static switch_status_t mp4_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{
	uint32_t datalen = *len * 2 * handle->channels;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
	uint32_t encoded_rate;
	mp4_file_context_t *context = handle->private_info;
	uint32_t size = 0;

	context->audio_duration += *len;


	if (context->audio_type == MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE) {
		size = datalen;
		memcpy(buf, data, datalen);
	} else {
		switch_core_codec_encode(&context->audio_codec, NULL,
								data, datalen,
								handle->samplerate,
								buf, &size, &encoded_rate, NULL);
	}

	switch_mutex_lock(context->mutex);

	if (!context->timer.interval) {
		switch_core_timer_init(&context->timer, "soft", 1, 1, context->pool);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
	} else if(!context->audio_start) { // try make up some sampels if the video already start
		int i, count;
		uint8_t buf0[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };

		context->audio_start++;
		switch_core_timer_sync(&context->timer);

		count = context->timer.samplecount - context->offset;

		if (count > 0) {
			count /= *len;
		}

		if (context->audio_type != MP4_ULAW_AUDIO_TYPE) {
			count = 0; // todo: make this feature work for mp3/aac
		}

		if (count){
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video is short, make up %lu samples\n", count * (*len));
			MP4WriteSample(context->fd, context->audio, buf0, size, 0, 0, 1);
		}

		for (i = 1; i < count; i++) {
			MP4WriteSample(context->fd, context->audio, buf0, size, *len, 0, 1);
		}
	}

	if (context->audio_type == MP4_MPEG4_AUDIO_TYPE && size == 0) {
		// don't write 0
	} else {
		MP4WriteSample(context->fd, context->audio, buf, size, context->audio_duration, 0, 1);
		context->audio_duration = 0;
	}

	switch_mutex_unlock(context->mutex);

	return status;
}
コード例 #5
0
ファイル: mod_mp4v2.c プロジェクト: odmanV2/freecenter
static void record_video_thread(switch_core_session_t *session, void *obj)
{
	struct record_helper *eh = obj;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_status_t status;
	switch_frame_t *read_frame;
	uint bytes;
	MP4FileHandle mp4;
	MP4TrackId video;
	unsigned char buf[40960];
	int len = 0;
	uint8_t iframe = 0;
	uint32_t *size = (uint32_t *)buf;
	uint8_t *hdr = NULL;
	uint8_t fragment_type;
	uint8_t nal_type;
	uint8_t start_bit;
	uint8_t *sps = NULL;
	// uint8_t *pps = NULL;
	int sps_set = 0;
	int pps_set = 0;

	eh->up = 1;
	mp4 = eh->fd;

	/* Tell the channel to request a fresh vid frame */
	switch_core_session_request_video_refresh(session);

	len = 0;
	while (switch_channel_ready(channel) && eh->up) {
		status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);

		if (!SWITCH_READ_ACCEPTABLE(status)) {
			break;
		}

		if (switch_test_flag(read_frame, SFF_CNG)) {
			continue;
		}

		bytes = read_frame->datalen;

		if (bytes > 2000) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "xxxxxxxx buffer overflow\n");
			continue;
		}

		hdr = read_frame->data;
		fragment_type = hdr[0] & 0x1f;
		nal_type = hdr[1] & 0x1f;
		start_bit = hdr[1] & 0x80;
		iframe = (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5 || fragment_type ==7 || fragment_type ==8) ? 1 : 0;

#if 0
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], bytes, read_frame->m, start_bit, iframe);
#endif

		// echo back
		switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);

		if (fragment_type == 7 && !sps_set) { //sps
			sps = malloc(bytes);
			memcpy(sps, read_frame->data, bytes);
			sps_set = 1;

			switch_mutex_lock(eh->mutex);

			init_video_track(mp4, &video, read_frame);
			if (video == MP4_INVALID_TRACK_ID) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
				switch_mutex_unlock(eh->mutex);
				goto end;
			}

			switch_mutex_unlock(eh->mutex);
			continue;
		} else if (fragment_type == 8 && !pps_set) { //pps
			switch_mutex_lock(eh->mutex);
			MP4AddH264PictureParameterSet(mp4, video, read_frame->data, bytes);
			switch_mutex_unlock(eh->mutex);
			pps_set = 1;
			// continue;
		}

		if ((!sps_set) && (!pps_set)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting for SPS/PPS\n");
			// continue;
		}

		len += 4 + read_frame->datalen;

		if (len > 40960) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer overflow!!!! %d\n", len);
			len = 0;
			size = (uint32_t *)buf;
			continue;
		}

		*size = htonl(read_frame->datalen);
		memcpy(size + 1, read_frame->data, read_frame->datalen);

		size = (uint32_t *)((uint8_t *)size + 4 + read_frame->datalen);

		if (read_frame->m) {
			int duration = 0;

			switch_mutex_lock(eh->mutex);
			if (!eh->timer.interval) {
				switch_core_timer_init(&eh->timer, "soft", 1, 1, switch_core_session_get_pool(session));
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
			} else {
				switch_core_timer_sync(&eh->timer);
			}
			switch_mutex_unlock(eh->mutex);

			if (eh->last_pts) {
				duration = eh->timer.samplecount - eh->last_pts;
			}
			eh->last_pts = eh->timer.samplecount;

			switch_mutex_lock(eh->mutex);
			MP4WriteSample(mp4, video, buf, len, duration, 0, iframe);
			switch_mutex_unlock(eh->mutex);
			len = 0;
			size = (uint32_t *)buf;
		}

	}

end:
	eh->up = 0;
	return;
}
コード例 #6
0
ファイル: mod_loopback.c プロジェクト: hsaid/FreeSWITCH
static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
{
	switch_channel_t *channel;
	private_t *tech_pvt;
	int done = 1, pass = 0;
	
	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_ANSWER:
		if (tech_pvt->other_channel && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
			switch_channel_mark_answered(tech_pvt->other_channel);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_PROGRESS:
		if (tech_pvt->other_channel && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
			switch_channel_mark_pre_answered(tech_pvt->other_channel);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_RINGING:
		if (tech_pvt->other_channel && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
			switch_channel_mark_ring_ready(tech_pvt->other_channel);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_BRIDGE:
		{
			switch_set_flag_locked(tech_pvt, TFLAG_BRIDGE);
		}
		break;
	case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
		{
			switch_clear_flag_locked(tech_pvt, TFLAG_BRIDGE);
		}
		break;
	default:
		done = 0;
		break;
	}

	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_BRIDGE:
	case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
	case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
		{

			done = 1;
			switch_set_flag(tech_pvt, TFLAG_CLEAR);
			switch_set_flag(tech_pvt->other_tech_pvt, TFLAG_CLEAR);

			switch_core_timer_sync(&tech_pvt->timer);
			switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer);
		}
		break;
	default:
		break;
	}


	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_DISPLAY:
		{

			if (!zstr(msg->string_array_arg[0])) {
				switch_channel_set_profile_var(tech_pvt->other_channel, "callee_id_name", msg->string_array_arg[0]);
			}

			if (!zstr(msg->string_array_arg[1])) {
				switch_channel_set_profile_var(tech_pvt->other_channel, "callee_id_number", msg->string_array_arg[1]);
			}
			
			pass = 1;
		}
		break;
	default:
		break;
	}


	if (!done && tech_pvt->other_session && (pass || switch_test_flag(tech_pvt, TFLAG_RUNNING_APP))) {
		switch_status_t r = SWITCH_STATUS_FALSE;
		switch_core_session_t *other_session;
		
		if (switch_core_session_get_partner(tech_pvt->other_session, &other_session) == SWITCH_STATUS_SUCCESS) {
			r = switch_core_session_receive_message(other_session, msg);
			switch_core_session_rwunlock(other_session);
		}
		
		return r;
	}
	
	return SWITCH_STATUS_SUCCESS;
}
コード例 #7
0
ファイル: mod_loopback.c プロジェクト: hsaid/FreeSWITCH
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
	switch_channel_t *channel = NULL;
	private_t *tech_pvt = NULL;
	switch_status_t status = SWITCH_STATUS_FALSE;

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	if (switch_test_flag(frame, SFF_CNG) || 
		(switch_test_flag(tech_pvt, TFLAG_BOWOUT) && switch_test_flag(tech_pvt, TFLAG_BOWOUT_USED))) {
		switch_core_timer_sync(&tech_pvt->timer);
		switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer);
		return SWITCH_STATUS_SUCCESS;
	}

	switch_mutex_lock(tech_pvt->mutex);
	if (!switch_test_flag(tech_pvt, TFLAG_BOWOUT) &&
		tech_pvt->other_tech_pvt &&
		switch_test_flag(tech_pvt, TFLAG_BRIDGE) &&
		switch_test_flag(tech_pvt->other_tech_pvt, TFLAG_BRIDGE) &&
		switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
		switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) &&
		switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
		switch_channel_test_flag(tech_pvt->other_channel, CF_ANSWERED) && --tech_pvt->bowout_frame_count <= 0) {
		const char *a_uuid = NULL;
		const char *b_uuid = NULL;
		const char *vetoa, *vetob;


		vetoa = switch_channel_get_variable(tech_pvt->channel, "loopback_bowout");
		vetob = switch_channel_get_variable(tech_pvt->other_tech_pvt->channel, "loopback_bowout");

		if ((!vetoa || switch_true(vetoa)) && (!vetob || switch_true(vetob))) {
			switch_core_session_t *br_a, *br_b;
			switch_channel_t *ch_a = NULL, *ch_b = NULL;
			int good_to_go = 0;

			switch_mutex_unlock(tech_pvt->mutex);
			find_non_loopback_bridge(session, &br_a, &a_uuid);
			find_non_loopback_bridge(tech_pvt->other_session, &br_b, &b_uuid);
			switch_mutex_lock(tech_pvt->mutex);

			
			if (br_a) {
				ch_a = switch_core_session_get_channel(br_a);
				switch_core_media_bug_transfer_recordings(session, br_a);
			}

			if (br_b) {
				ch_b = switch_core_session_get_channel(br_b);
				switch_core_media_bug_transfer_recordings(tech_pvt->other_session, br_b);
			}
			
			if (ch_a && ch_b && switch_channel_test_flag(ch_a, CF_BRIDGED) && switch_channel_test_flag(ch_b, CF_BRIDGED)) {

				switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT);
				switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT);

				switch_clear_flag_locked(tech_pvt, TFLAG_WRITE);
				switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);

				switch_set_flag_locked(tech_pvt, TFLAG_BOWOUT_USED);
				switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_BOWOUT_USED);

				if (a_uuid && b_uuid) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
									  "%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel));
					
					/* channel_masquerade eat your heart out....... */
					switch_ivr_uuid_bridge(a_uuid, b_uuid);
					good_to_go = 1;
					switch_mutex_unlock(tech_pvt->mutex);
				}
			}

			if (br_a) switch_core_session_rwunlock(br_a);
			if (br_b) switch_core_session_rwunlock(br_b);
			
			if (good_to_go) {
				return SWITCH_STATUS_SUCCESS;
			}

		}
	}

	if (switch_test_flag(tech_pvt, TFLAG_LINKED) && tech_pvt->other_tech_pvt) {
		switch_frame_t *clone;
		
		if (frame->codec->implementation != tech_pvt->write_codec.implementation) {
			/* change codecs to match */
			tech_init(tech_pvt, session, frame->codec);
			tech_init(tech_pvt->other_tech_pvt, tech_pvt->other_session, frame->codec);
		}


		if (switch_frame_dup(frame, &clone) != SWITCH_STATUS_SUCCESS) {
			abort();
		}
		
		if ((status = switch_queue_trypush(tech_pvt->other_tech_pvt->frame_queue, clone)) != SWITCH_STATUS_SUCCESS) { 
			clear_queue(tech_pvt->other_tech_pvt);
			status = switch_queue_trypush(tech_pvt->other_tech_pvt->frame_queue, clone);
		}

		if (status == SWITCH_STATUS_SUCCESS) {
			switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);
		} else {
			switch_frame_free(&clone);
		}

		status = SWITCH_STATUS_SUCCESS;
	}

	switch_mutex_unlock(tech_pvt->mutex);

	return status;
}
コード例 #8
0
static switch_status_t engage_device(portaudio_stream_source_t *source, int restart)
{
	PaStreamParameters inputParameters, outputParameters;
	PaError err;
	int sample_rate = source->rate;
	int codec_ms = source->interval;

	switch_mutex_init(&source->device_lock, SWITCH_MUTEX_NESTED, module_pool);

	if (source->timer.timer_interface) {
		switch_core_timer_sync(&source->timer);
	}

	if (source->audio_stream) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (!switch_core_codec_ready(&source->read_codec)) {
		if (switch_core_codec_init(&source->read_codec,
								   "L16",
								   NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
								   NULL) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
			return SWITCH_STATUS_FALSE;
		}
	}

	switch_assert(source->read_codec.implementation);

	if (!switch_core_codec_ready(&source->write_codec)) {
		if (switch_core_codec_init(&source->write_codec,
								   "L16",
								   NULL,
								   sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
			switch_core_codec_destroy(&source->read_codec);
			return SWITCH_STATUS_FALSE;
		}
	}


	if (!source->timer.timer_interface) {
		if (switch_core_timer_init(&source->timer,
								   source->timer_name, codec_ms, source->read_codec.implementation->samples_per_packet,
								   module_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
			switch_core_codec_destroy(&source->read_codec);
			switch_core_codec_destroy(&source->write_codec);
			return SWITCH_STATUS_FALSE;
		}
	}

	source->read_frame.rate = sample_rate;
	source->read_frame.codec = &source->read_codec;

	switch_mutex_lock(source->device_lock);
	/* LOCKED ************************************************************************************************** */
	inputParameters.device = source->sourcedev;
	inputParameters.channelCount = 1;
	inputParameters.sampleFormat = SAMPLE_TYPE;
	inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
	inputParameters.hostApiSpecificStreamInfo = NULL;
	outputParameters.device = source->sourcedev;
	outputParameters.channelCount = 1;
	outputParameters.sampleFormat = SAMPLE_TYPE;
	outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
	outputParameters.hostApiSpecificStreamInfo = NULL;


	err = OpenAudioStream(&source->audio_stream, &inputParameters, NULL, sample_rate, paClipOff, source->read_codec.implementation->samples_per_packet, 0);
	/* UNLOCKED ************************************************************************************************* */
	if (err != paNoError) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening audio device retrying\n");
		switch_yield(1000000);
		err = OpenAudioStream(&source->audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff,
							  source->read_codec.implementation->samples_per_packet, 0);
	}

	switch_mutex_unlock(source->device_lock);
	if (err != paNoError) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device\n");
		switch_core_codec_destroy(&source->read_codec);
		switch_core_timer_destroy(&source->timer);
		return SWITCH_STATUS_FALSE;
	}


	return SWITCH_STATUS_SUCCESS;
}
コード例 #9
0
ファイル: mod_webm.cpp プロジェクト: odmanV2/freecenter
static switch_status_t webm_file_write(switch_file_handle_t *handle, void *data, size_t *len)
{

	uint32_t datalen = *len * 2 * handle->channels;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }, *bp = buf;
	uint32_t encoded_rate;
	webm_file_context_t *context = (webm_file_context_t *)handle->private_info;
	uint32_t size = 0;


	if (!context->vid_ready) {
		return status;
	}

	context->audio_duration += *len;

	if (switch_test_flag(handle, SWITCH_FILE_NATIVE)) {
		size = datalen;
		memcpy(buf, data, datalen);
	} else {
		uint32_t rb;

		if (!context->audio_ready) {
			int offset = 1200;
			int fps = handle->samplerate / *len;
			int lead_frames = (offset * fps) / 1000;

			for (int x = 0; x < lead_frames; x++) {
				switch_buffer_write(context->audio_buffer, buf, datalen);
			}
			context->audio_ready = 1;
		}

		switch_buffer_write(context->audio_buffer, data, datalen);
		rb = switch_buffer_read(context->audio_buffer, data, datalen);
		datalen = rb;
		size = SWITCH_RECOMMENDED_BUFFER_SIZE;
		switch_core_codec_encode(&context->audio_codec, NULL,
								data, datalen,
								handle->samplerate,
								buf, &size, &encoded_rate, NULL);
	}

	
	if (size > 0) {
		// timecode still need to figure out for sync

		switch_mutex_lock(context->mutex);
		switch_core_timer_sync(&context->timer);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Writing audio %d bytes, ts: %lld\n", size, context->timer.samplecount);
		bool ret = context->segment->AddFrame(bp, size, context->audio_track_id, context->timer.samplecount * 1000LL, true);
		// bool ret = context->segment->AddFrame((const uint8_t *)buf, size, context->audio_track_id, context->audio_duration, true);
		switch_mutex_unlock(context->mutex);

		if (!ret) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing audio %d bytes, pts: %lld or %lld\n", size, context->timer.samplecount * 1000LL, context->audio_duration);
		}
	}

	return status;
}