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); } }
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 }
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; }
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; }
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; }
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; }
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; }
/* 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; }