void AsyncIOServer::Stop() {
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AsyncIOServer::Stop() \n");
	mRunning = false;

	// 停止监听socket
	mTcpServer.Stop();

	// 停止处理线程
	if( mpHandleThreads != NULL ) {
		for(int i = 0; i < mThreadCount; i++) {
			switch_status_t retval;
			switch_thread_join(&retval, mpHandleThreads[i]);
		}
	}

	// 销毁处理队列
	unsigned int size;
	void* pop = NULL;
	while(true) {
		size = switch_queue_size(mpHandleQueue);
		if( size == 0 ) {
			break;
		} else {
			switch_queue_pop(mpHandleQueue, &pop);
		}
	}

	mpPool = NULL;

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AsyncIOServer::Stop( finish ) \n");
}
static void flush_video_queue(switch_queue_t *q)
{
	void *pop;

	if (switch_queue_size(q) == 0) {
		return;
	}

	while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
		switch_image_t *img = (switch_image_t *) pop;
		switch_img_free(&img);
	}

}
示例#3
0
SWITCH_DECLARE(void) switch_core_memory_reclaim_logger(void)
{
#ifdef SWITCH_LOG_RECYCLE
	void *pop;
	int size = switch_queue_size(LOG_RECYCLE_QUEUE);
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Returning %d recycled log node(s) %d bytes\n", size,
					  (int) sizeof(switch_log_node_t) * size);
	while (switch_queue_trypop(LOG_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
		switch_log_node_free(&pop);
	}
#else
	return;
#endif

}
示例#4
0
SWITCH_DECLARE(void) switch_core_memory_reclaim(void)
{
#if !defined(PER_POOL_LOCK) && !defined(INSTANTLY_DESTROY_POOLS)
	switch_memory_pool_t *pool;
	void *pop = NULL;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Returning %d recycled memory pool(s)\n",
					  switch_queue_size(memory_manager.pool_recycle_queue) + switch_queue_size(memory_manager.pool_queue));

	while (switch_queue_trypop(memory_manager.pool_recycle_queue, &pop) == SWITCH_STATUS_SUCCESS) {
		pool = (switch_memory_pool_t *) pop;
		if (!pool) {
			break;
		}
#ifdef USE_MEM_LOCK
		switch_mutex_lock(memory_manager.mem_lock);
#endif
		apr_pool_destroy(pool);
#ifdef USE_MEM_LOCK
		switch_mutex_unlock(memory_manager.mem_lock);
#endif
	}
#endif
	return;
}
示例#5
0
switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn, switch_bool_t destroy)
{
  switch_status_t status = SWITCH_STATUS_SUCCESS;

  switch_assert(conn_pool != NULL);
  switch_assert(conn != NULL);

  switch_mutex_lock(conn_pool->mutex);
  if (destroy || conn_pool->size > conn_pool->max_connections) {
#ifdef MONGO_POOL_DEBUG
    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: Destroy connection %p\n", conn);
#endif
    mongo_connection_destroy(&conn);
    conn_pool->size--;
  } else {
#ifdef MONGO_POOL_DEBUG
    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: push connection %p\n", conn);
#endif
    status = switch_queue_push(conn_pool->connections, conn);
  }

  switch_mutex_unlock(conn_pool->mutex);

#ifdef MONGO_POOL_DEBUG
  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL: put size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif

  return status;
}
示例#6
0
DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool)
{
  DBClientBase *conn = NULL;
  void *data = NULL;

  switch_assert(conn_pool != NULL);

  switch_mutex_lock(conn_pool->mutex);

  if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) {
    conn = (DBClientBase *) data;
  } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) {
    if (++conn_pool->size > conn_pool->max_connections) {
      switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n");
    }
  }

  switch_mutex_unlock(conn_pool->mutex);

#ifdef MONGO_POOL_DEBUG
  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "POOL get: size %d conn: %p\n", (int) switch_queue_size(conn_pool->connections), conn);
#endif

  return conn;
}
示例#7
0
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_CNG) || switch_test_flag(tech_pvt, TFLAG_BOWOUT)) {
		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 = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
		const char *b_uuid = switch_channel_get_variable(tech_pvt->other_channel, SWITCH_SIGNAL_BOND_VARIABLE);
		const char *vetoa, *vetob;

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

		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_clear_flag_locked(tech_pvt, TFLAG_WRITE);
			switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);

			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);
				switch_mutex_unlock(tech_pvt->mutex);
				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_queue_size(tech_pvt->other_tech_pvt->frame_queue) < FRAME_QUEUE_LEN) {
			if (switch_frame_dup(frame, &clone) != SWITCH_STATUS_SUCCESS) {
				abort();
			}

			if (switch_queue_trypush(tech_pvt->other_tech_pvt->frame_queue, clone) != SWITCH_STATUS_SUCCESS) {
				switch_frame_free(&clone);
			}

			switch_set_flag_locked(tech_pvt->other_tech_pvt, TFLAG_WRITE);
		}

		status = SWITCH_STATUS_SUCCESS;
	}

	switch_mutex_unlock(tech_pvt->mutex);

	return status;
}
示例#8
0
static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj)
{
	memory_manager.pool_thread_running = 1;

	while (memory_manager.pool_thread_running == 1) {
		int len = switch_queue_size(memory_manager.pool_queue);

		if (len) {
			int x = len, done = 0;

			switch_yield(1000000);
#ifdef USE_MEM_LOCK
			switch_mutex_lock(memory_manager.mem_lock);
#endif
			while (x > 0) {
				void *pop = NULL;
				if (switch_queue_pop(memory_manager.pool_queue, &pop) != SWITCH_STATUS_SUCCESS || !pop) {
					done = 1;
					break;
				}
#if defined(PER_POOL_LOCK) || defined(DESTROY_POOLS)
#ifdef USE_MEM_LOCK
				switch_mutex_lock(memory_manager.mem_lock);
#endif

#ifdef DEBUG_ALLOC
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%p DESTROY POOL\n", (void *) pop);	
#endif
				apr_pool_destroy(pop);
#ifdef USE_MEM_LOCK
				switch_mutex_unlock(memory_manager.mem_lock);
#endif
#else
				apr_pool_mutex_set(pop, NULL);
#ifdef DEBUG_ALLOC
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%p DESTROY POOL\n", (void *) pop);	
#endif
				apr_pool_clear(pop);
				if (switch_queue_trypush(memory_manager.pool_recycle_queue, pop) != SWITCH_STATUS_SUCCESS) {
#ifdef USE_MEM_LOCK
					switch_mutex_lock(memory_manager.mem_lock);
#endif
#ifdef DEBUG_ALLOC
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%p DESTROY POOL\n", (void *) pop);	
#endif
					apr_pool_destroy(pop);
#ifdef USE_MEM_LOCK
					switch_mutex_unlock(memory_manager.mem_lock);
#endif

				}
#endif
				x--;
			}
#ifdef USE_MEM_LOCK
			switch_mutex_unlock(memory_manager.mem_lock);
#endif
			if (done) {
				goto done;
			}
		} else {
			switch_yield(1000000);
		}
	}

  done:
	switch_core_memory_reclaim();

	{
		void *pop = NULL;
		while (switch_queue_trypop(memory_manager.pool_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
#ifdef USE_MEM_LOCK
			switch_mutex_lock(memory_manager.mem_lock);
#endif
			apr_pool_destroy(pop);
			pop = NULL;
#ifdef USE_MEM_LOCK
			switch_mutex_unlock(memory_manager.mem_lock);
#endif

		}
	}

	memory_manager.pool_thread_running = 0;

	return NULL;
}
示例#9
0
/* marshall frames from the call leg to the conference thread for muxing to other call legs */
void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *obj)
{
	switch_event_t *event;
	conference_member_t *member = obj;
	switch_channel_t *channel;
	switch_status_t status;
	switch_frame_t *read_frame = NULL;
	uint32_t hangover = 40, hangunder = 5, hangover_hits = 0, hangunder_hits = 0, diff_level = 400;
	switch_core_session_t *session = member->session;
	uint32_t flush_len;
	switch_frame_t tmp_frame = { 0 };

	if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
		goto end;
	}

	switch_assert(member != NULL);

	conference_utils_member_clear_flag_locked(member, MFLAG_TALKING);

	channel = switch_core_session_get_channel(session);

	switch_core_session_get_read_impl(session, &member->read_impl);

	switch_channel_audio_sync(channel);

	flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 2 * member->conference->channels * (500 / member->conference->interval);

	/* As long as we have a valid read, feed that data into an input buffer where the conference thread will take it
	   and mux it with any audio from other channels. */

	while (conference_utils_member_test_flag(member, MFLAG_RUNNING) && switch_channel_ready(channel)) {

		if (switch_channel_ready(channel) && switch_channel_test_app_flag(channel, CF_APP_TAGGED)) {
			switch_yield(100000);
			continue;
		}

		/* Read a frame. */
		status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);

		switch_mutex_lock(member->read_mutex);

		/* end the loop, if appropriate */
		if (!SWITCH_READ_ACCEPTABLE(status) || !conference_utils_member_test_flag(member, MFLAG_RUNNING)) {
			switch_mutex_unlock(member->read_mutex);
			break;
		}

		if (switch_channel_test_flag(channel, CF_VIDEO) && !conference_utils_member_test_flag(member, MFLAG_ACK_VIDEO)) {
			conference_utils_member_set_flag_locked(member, MFLAG_ACK_VIDEO);
			conference_video_check_avatar(member, SWITCH_FALSE);
			switch_core_session_video_reinit(member->session);
			conference_video_set_floor_holder(member->conference, member, SWITCH_FALSE);
		} else if (conference_utils_member_test_flag(member, MFLAG_ACK_VIDEO) && !switch_channel_test_flag(channel, CF_VIDEO)) {
			conference_video_check_avatar(member, SWITCH_FALSE);
		}

		/* if we have caller digits, feed them to the parser to find an action */
		if (switch_channel_has_dtmf(channel)) {
			char dtmf[128] = "";

			switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));

			if (conference_utils_member_test_flag(member, MFLAG_DIST_DTMF)) {
				conference_member_send_all_dtmf(member, member->conference, dtmf);
			} else if (member->dmachine) {
				char *p;
				char str[2] = "";
				for (p = dtmf; p && *p; p++) {
					str[0] = *p;
					switch_ivr_dmachine_feed(member->dmachine, str, NULL);
				}
			}
		} else if (member->dmachine) {
			switch_ivr_dmachine_ping(member->dmachine, NULL);
		}

		if (switch_queue_size(member->dtmf_queue)) {
			switch_dtmf_t *dt;
			void *pop;

			if (switch_queue_trypop(member->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
				dt = (switch_dtmf_t *) pop;
				switch_core_session_send_dtmf(member->session, dt);
				free(dt);
			}
		}

		if (switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) {
			member->reset_media = 10;
			switch_channel_audio_sync(member->channel);
			switch_channel_clear_flag(member->channel, CF_CONFERENCE_RESET_MEDIA);
		}

		if (member->reset_media) {
			if (--member->reset_media > 0) {
				goto do_continue;
			}

			if (conference_member_setup_media(member, member->conference)) {
				switch_mutex_unlock(member->read_mutex);
				break;
			}

			member->loop_loop = 1;
			
			goto do_continue;			
		}

		if (switch_test_flag(read_frame, SFF_CNG)) {
			if (member->conference->agc_level) {
				member->nt_tally++;
			}

			if (hangunder_hits) {
				hangunder_hits--;
			}
			if (conference_utils_member_test_flag(member, MFLAG_TALKING)) {
				if (++hangover_hits >= hangover) {
					hangover_hits = hangunder_hits = 0;
					conference_utils_member_clear_flag_locked(member, MFLAG_TALKING);
					conference_member_update_status_field(member);
					conference_member_check_agc_levels(member);
					conference_member_clear_avg(member);
					member->score_iir = 0;
					member->floor_packets = 0;

					if (test_eflag(member->conference, EFLAG_STOP_TALKING) &&
						switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
						conference_member_add_event_data(member, event);
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-talking");
						switch_event_fire(&event);
					}
				}
			}

			goto do_continue;
		}

		if (member->nt_tally > (int32_t)(member->read_impl.actual_samples_per_second / member->read_impl.samples_per_packet) * 3) {
			member->agc_volume_in_level = 0;
			conference_member_clear_avg(member);
		}

		/* Check for input volume adjustments */
		if (!member->conference->agc_level) {
			member->conference->agc_level = 0;
			conference_member_clear_avg(member);
		}


		/* if the member can speak, compute the audio energy level and */
		/* generate events when the level crosses the threshold        */
		if ((conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) || conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT))) {
			uint32_t energy = 0, i = 0, samples = 0, j = 0;
			int16_t *data;
			int agc_period = (member->read_impl.actual_samples_per_second / member->read_impl.samples_per_packet) / 4;


			data = read_frame->data;
			member->score = 0;

			if (member->volume_in_level) {
				switch_change_sln_volume(read_frame->data, (read_frame->datalen / 2) * member->conference->channels, member->volume_in_level);
			}

			if (member->agc_volume_in_level) {
				switch_change_sln_volume_granular(read_frame->data, (read_frame->datalen / 2) * member->conference->channels, member->agc_volume_in_level);
			}

			if ((samples = read_frame->datalen / sizeof(*data) / member->read_impl.number_of_channels)) {
				for (i = 0; i < samples; i++) {
					energy += abs(data[j]);
					j += member->read_impl.number_of_channels;
				}

				member->score = energy / samples;
			}

			if (member->vol_period) {
				member->vol_period--;
			}

			if (member->conference->agc_level && member->score &&
				conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&
				conference_member_noise_gate_check(member)
				) {
				int last_shift = abs((int)(member->last_score - member->score));

				if (member->score && member->last_score && last_shift > 900) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7,
									  "AGC %s:%d drop anomalous shift of %d\n",
									  member->conference->name,
									  member->id, last_shift);

				} else {
					member->avg_tally += member->score;
					member->avg_itt++;
					if (!member->avg_itt) member->avg_itt++;
					member->avg_score = member->avg_tally / member->avg_itt;
				}

				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG7,
								  "AGC %s:%d diff:%d level:%d cur:%d avg:%d vol:%d\n",
								  member->conference->name,
								  member->id, member->conference->agc_level - member->avg_score, member->conference->agc_level,
								  member->score, member->avg_score, member->agc_volume_in_level);

				if (++member->agc_concur >= agc_period) {
					if (!member->vol_period) {
						conference_member_check_agc_levels(member);
					}
					member->agc_concur = 0;
				}
			} else {
				member->nt_tally++;
			}

			member->score_iir = (int) (((1.0 - SCORE_DECAY) * (float) member->score) + (SCORE_DECAY * (float) member->score_iir));

			if (member->score_iir > SCORE_MAX_IIR) {
				member->score_iir = SCORE_MAX_IIR;
			}

			if (conference_member_noise_gate_check(member)) {
				uint32_t diff = member->score - member->energy_level;
				if (hangover_hits) {
					hangover_hits--;
				}

				if (member->conference->agc_level) {
					member->nt_tally = 0;
				}

				if (member == member->conference->floor_holder) {
					member->floor_packets++;
				}

				if (diff >= diff_level || ++hangunder_hits >= hangunder) {

					hangover_hits = hangunder_hits = 0;
					member->last_talking = switch_epoch_time_now(NULL);

					if (!conference_utils_member_test_flag(member, MFLAG_TALKING)) {
						conference_utils_member_set_flag_locked(member, MFLAG_TALKING);
						conference_member_update_status_field(member);
						member->floor_packets = 0;

						if (test_eflag(member->conference, EFLAG_START_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&
							switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
							conference_member_add_event_data(member, event);
							switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-talking");
							switch_event_fire(&event);
						}

						if (conference_utils_member_test_flag(member, MFLAG_MUTE_DETECT) && !conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {

							if (!zstr(member->conference->mute_detect_sound)) {
								conference_utils_member_set_flag(member, MFLAG_INDICATE_MUTE_DETECT);
							}

							if (test_eflag(member->conference, EFLAG_MUTE_DETECT) &&
								switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
								conference_member_add_event_data(member, event);
								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "mute-detect");
								switch_event_fire(&event);
							}
						}
					}
				}
			} else {
				if (hangunder_hits) {
					hangunder_hits--;
				}

				if (member->conference->agc_level) {
					member->nt_tally++;
				}

				if (conference_utils_member_test_flag(member, MFLAG_TALKING) && conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK)) {
					switch_event_t *event;
					if (++hangover_hits >= hangover) {
						hangover_hits = hangunder_hits = 0;
						conference_utils_member_clear_flag_locked(member, MFLAG_TALKING);
						conference_member_update_status_field(member);
						conference_member_check_agc_levels(member);
						conference_member_clear_avg(member);

						if (test_eflag(member->conference, EFLAG_STOP_TALKING) &&
							switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
							conference_member_add_event_data(member, event);
							switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-talking");
							switch_event_fire(&event);
						}
					}
				}
			}


			member->last_score = member->score;

			if (member == member->conference->floor_holder) {
				if (member->id != member->conference->video_floor_holder &&
					(member->floor_packets > member->conference->video_floor_packets || member->energy_level == 0)) {
					conference_video_set_floor_holder(member->conference, member, SWITCH_FALSE);
				}
			}
		}
		
		/* skip frames that are not actual media or when we are muted or silent */
		if ((conference_utils_member_test_flag(member, MFLAG_TALKING) || member->energy_level == 0 || conference_utils_test_flag(member->conference, CFLAG_AUDIO_ALWAYS))
			&& conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) &&	!conference_utils_test_flag(member->conference, CFLAG_WAIT_MOD)
			&& (member->conference->count > 1 || (member->conference->record_count && member->conference->count >= member->conference->min_recording_participants))) {
			switch_audio_resampler_t *read_resampler = member->read_resampler;
			void *data;
			uint32_t datalen;

			if (read_resampler) {
				int16_t *bptr = (int16_t *) read_frame->data;
				int len = (int) read_frame->datalen;

				switch_resample_process(read_resampler, bptr, len / 2 / member->read_impl.number_of_channels);
				memcpy(member->resample_out, read_resampler->to, read_resampler->to_len * 2 * member->read_impl.number_of_channels);
				len = read_resampler->to_len * 2 * member->read_impl.number_of_channels;
				datalen = len;
				data = member->resample_out;
			} else {
				data = read_frame->data;
				datalen = read_frame->datalen;
			}

			tmp_frame.data = data;
			tmp_frame.datalen = datalen;
			tmp_frame.rate = member->conference->rate;
			conference_member_check_channels(&tmp_frame, member, SWITCH_TRUE);


			if (datalen) {
				switch_size_t ok = 1;

				/* Write the audio into the input buffer */
				switch_mutex_lock(member->audio_in_mutex);
				if (switch_buffer_inuse(member->audio_buffer) > flush_len) {
					switch_buffer_toss(member->audio_buffer, tmp_frame.datalen);
				}
				ok = switch_buffer_write(member->audio_buffer, tmp_frame.data, tmp_frame.datalen);
				switch_mutex_unlock(member->audio_in_mutex);
				if (!ok) {
					switch_mutex_unlock(member->read_mutex);
					break;
				}
			}
		}

	do_continue:

		switch_mutex_unlock(member->read_mutex);

	}

	if (switch_queue_size(member->dtmf_queue)) {
		switch_dtmf_t *dt;
		void *pop;

		while (switch_queue_trypop(member->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
			dt = (switch_dtmf_t *) pop;
			free(dt);
		}
	}


	switch_resample_destroy(&member->read_resampler);
	switch_core_session_rwunlock(session);

 end:

	conference_utils_member_clear_flag_locked(member, MFLAG_ITHREAD);

	return NULL;
}
static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
{
	void *pop;
	local_stream_context_t *context = handle->private_info;
	switch_status_t status;
	switch_time_t now;

	if (!(context->ready && context->source->ready)) {
		return SWITCH_STATUS_FALSE;
	}

	if (!context->source->has_video) {
		if (frame) {
			switch_image_t *src_img = context->source->cover_art;

			if (!src_img) {
				src_img = context->source->blank_img;
			}

			if (src_img) {
				switch_image_t *img = NULL;
			
				if (context->sent_png && --context->sent_png > 0) {
					return SWITCH_STATUS_BREAK;
				}

				context->sent_png = 50;
				switch_img_copy(src_img, &img);

				if (context->last_w && context->last_h) {
					switch_img_fit(&img, context->last_w, context->last_h, SWITCH_FIT_SIZE);
				}

				frame->img = img;
				goto got_img;
			}
		}
		return SWITCH_STATUS_IGNORE;
	}

	if ((flags & SVR_CHECK)) {
		return SWITCH_STATUS_BREAK;
	}

	while(context->ready && context->source->ready && (flags & SVR_FLUSH) && switch_queue_size(context->video_q) > 1) {
		if (switch_queue_trypop(context->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
			switch_image_t *img = (switch_image_t *) pop;
			switch_img_free(&img);
		}
	}

	if (!(context->ready && context->source->ready)) {
		return SWITCH_STATUS_FALSE;
	}
	
	if ((flags & SVR_BLOCK)) {
		status = switch_queue_pop(context->video_q, &pop);
	} else {
		status = switch_queue_trypop(context->video_q, &pop);
	}

	if (status == SWITCH_STATUS_SUCCESS) {
		if (!pop) {
			return SWITCH_STATUS_FALSE;
		}

		frame->img = (switch_image_t *) pop;
		context->sent_png = 0;
		context->last_w = frame->img->d_w;
		context->last_h = frame->img->d_h;
		goto got_img;
	}

	return (flags & SVR_FLUSH) ? SWITCH_STATUS_BREAK : status;

 got_img:

	if (context->pop_count > 0) {
		switch_rgb_color_t bgcolor = { 0 };
		switch_color_set_rgb(&bgcolor, "#000000");
		switch_img_fill(frame->img, 0, 0, frame->img->d_w, frame->img->d_h, &bgcolor);
		context->pop_count--;
	}
	
	now = switch_micro_time_now();

	if (context->banner_img) {
		if (now >= context->banner_timeout) {
			switch_img_free(&context->banner_img);
		}
	}

	if (context->serno != context->source->serno) {
		switch_img_free(&context->banner_img);
		context->banner_timeout = 0;
		context->serno = context->source->serno;
		context->pop_count = 5;
	}
	
	if (context->source->banner_txt) {
		if ((!context->banner_timeout || context->banner_timeout >= now)) {
			if (!context->banner_img) {
				context->banner_img = switch_img_write_text_img(context->last_w, context->last_h, SWITCH_TRUE, context->source->banner_txt);
				context->banner_timeout = now + 5000000;
			}
		}
	} else {
		if (context->banner_img) {
			switch_img_free(&context->banner_img);
		}
		context->banner_timeout = 0;
	}

	if (frame->img && context->banner_img && frame->img->d_w >= context->banner_img->d_w) {
		//switch_img_overlay(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h, 100);
		switch_img_patch(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h);
	}
	
	return SWITCH_STATUS_SUCCESS;
}