FS-8811 #comment please test

This commit is contained in:
Anthony Minessale 2016-03-03 18:37:42 -06:00
parent c366e3615f
commit 66fe6e5a46
3 changed files with 213 additions and 89 deletions

View File

@ -2808,6 +2808,8 @@ SWITCH_STANDARD_APP(playback_function)
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
status = switch_ivr_play_file(session, &fh, file, &args);
switch_assert(!(fh.flags & SWITCH_FILE_OPEN));
switch (status) {
case SWITCH_STATUS_SUCCESS:

View File

@ -68,10 +68,13 @@ struct local_stream_context {
int sent_png;
int last_w;
int last_h;
int newres;
int serno;
int pop_count;
switch_size_t blank;
switch_image_t *banner_img;
switch_time_t banner_timeout;
switch_memory_pool_t *pool;
struct local_stream_context *next;
};
@ -116,6 +119,7 @@ struct local_stream_source {
int serno;
switch_size_t abuflen;
switch_byte_t *abuf;
switch_timer_t timer;
};
typedef struct local_stream_source local_stream_source_t;
@ -173,28 +177,30 @@ switch_status_t list_streams(const char *line, const char *cursor, switch_consol
static int do_rand(uint32_t count)
{
double r;
int index;
int r = 0;
if (count < 3) return 0;
switch_mutex_lock(globals.mutex);
r = (rand() % count) + 1;
switch_mutex_unlock(globals.mutex);
r = ((double) rand() / ((double) (RAND_MAX) + (double) (1)));
index = (int) (r * count) + 1;
return index;
return r;
}
static void flush_video_queue(switch_queue_t *q)
{
void *pop;
void *pop = NULL;
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);
if (pop) {
switch_image_t *img = (switch_image_t *) pop;
switch_img_free(&img);
} else {
break;
}
}
}
@ -204,8 +210,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
volatile local_stream_source_t *s = (local_stream_source_t *) obj;
local_stream_source_t *source = (local_stream_source_t *) s;
switch_file_handle_t fh = { 0 };
char file_buf[128] = "", path_buf[512] = "", last_path[512], png_buf[512] = "", tmp_buf[512] = "";
switch_timer_t timer = { 0 };
char file_buf[128] = "", path_buf[512] = "", last_path[512] = "", png_buf[512] = "", tmp_buf[512] = "";
int fd = -1;
switch_buffer_t *audio_buffer;
switch_byte_t *dist_buf;
@ -227,12 +232,21 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
do_shuffle = 1;
}
if (source->prebuf < source->abuflen) {
source->prebuf = source->abuflen;
}
switch_queue_create(&source->video_q, 500, source->pool);
switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0);
dist_buf = switch_core_alloc(source->pool, source->prebuf + 10);
switch_thread_rwlock_create(&source->rwlock, source->pool);
if (switch_core_timer_init(&source->timer, source->timer_name, source->interval, (int)source->samples, source->pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
RUNNING = 0;
}
if (RUNNING) {
source->ready = 1;
switch_mutex_lock(globals.mutex);
@ -242,6 +256,11 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
while (RUNNING && !source->stopped && source->ready) {
const char *fname;
if (source->dir_handle) {
switch_dir_close(source->dir_handle);
source->dir_handle = NULL;
}
if (temp_pool) {
switch_core_destroy_memory_pool(&temp_pool);
@ -277,6 +296,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
while (RUNNING && !source->stopped) {
switch_size_t olen;
const char *artist = NULL, *title = NULL;
char tmp_space[128] = "";
if (fd > -1) {
char *pb;
@ -305,6 +325,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
}
}
if (dir_count > 1 && !strcmp(last_path, path_buf)) {
continue;
}
@ -328,25 +349,19 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
continue;
}
switch_buffer_zero(audio_buffer);
if (switch_core_file_has_video(&fh)) {
flush_video_queue(source->video_q);
}
switch_buffer_zero(audio_buffer);
if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
switch_dir_close(source->dir_handle);
source->dir_handle = NULL;
goto done;
}
switch_img_free(&source->cover_art);
switch_set_string(tmp_buf, path_buf);
if ((p = strrchr(tmp_buf, '/'))) {
*p++ = '\0';
switch_snprintf(png_buf, sizeof(png_buf), "%s/art/%s.png", tmp_buf, p);
if (switch_file_exists(png_buf, source->pool) == SWITCH_STATUS_SUCCESS) {
if (switch_file_exists(png_buf, temp_pool) == SWITCH_STATUS_SUCCESS) {
source->cover_art = switch_img_read_png(png_buf, SWITCH_IMG_FMT_I420);
}
}
@ -357,22 +372,68 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, &artist);
switch_core_file_get_string(&fh, SWITCH_AUDIO_COL_STR_TITLE, &title);
if (!title && !artist) {
char *e, *p, *args[3];
int argc;
switch_set_string(tmp_space, path_buf);
p = tmp_space;
while((e = strchr(p, '/'))) {
*e = '\0';
p = e+1;
}
argc = switch_split(p, '-', args);
if (argc > 0) {
while(*args[0] == ' ') {
args[0]++;
}
while(end_of(args[0]) == ' ') {
end_of(args[0]) = '\0';
}
artist = args[0];
if (argc > 1) {
while(*args[1] == ' ') {
args[1]++;
}
while(end_of(args[1]) == ' ') {
end_of(args[1]) = '\0';
}
title = args[1];
}
if (!title) {
title = artist;
artist = NULL;
}
} else {
title = p;
artist = NULL;
}
}
if (title && (source->cover_art || switch_core_file_has_video(&fh))) {
const char *format = "#cccccc:#333333:FreeSans.ttf:3%:";
if (artist) {
source->banner_txt = switch_mprintf("%s%s (%s)", format, title, artist);
} else {
source->banner_txt = switch_mprintf("%s%s", format, title);
}
}
while (RUNNING && !source->stopped) {
int is_open;
switch_file_handle_t *use_fh = &fh;
switch_core_timer_next(&timer);
switch_core_timer_next(&source->timer);
olen = source->samples;
if (source->chime_total) {
@ -419,9 +480,10 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
source->hup = 0;
if (is_open) {
is_open = 0;
switch_core_file_close(use_fh);
flush_video_queue(source->video_q);
switch_buffer_zero(audio_buffer);
if (use_fh == &source->chime_fh) {
source->chime_counter = source->rate * source->chime_freq;
switch_core_file_close(&fh);
@ -431,10 +493,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
}
}
if (!is_open) {
switch_buffer_zero(audio_buffer);
break;
} else {
if (is_open) {
int svr = 0;
if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
@ -473,6 +532,8 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
olen = source->samples;
}
switch_assert(source->abuflen >= olen * 2 * source->channels);
if (switch_core_file_read(use_fh, source->abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
switch_core_file_close(use_fh);
flush_video_queue(source->video_q);
@ -510,35 +571,41 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
break;
}
source->prebuf = (uint32_t)(source->samples * 2 * source->channels);
if (!source->total) {
flush_video_queue(source->video_q);
switch_buffer_zero(audio_buffer);
} else if (used > source->samples * 2 * source->channels) {
//if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
} else if (used && (!is_open || used >= source->abuflen)) {
void *pop;
uint32_t bused;
uint32_t bused = 0;
local_stream_context_t *cp = NULL;
switch_assert(source->abuflen <= source->prebuf);
used = switch_buffer_read(audio_buffer, dist_buf, source->abuflen);
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
bused = 0;
switch_mutex_lock(source->mutex);
for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
if (source->has_video) {
switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
} else {
switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
}
if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
if (!cp->ready) {
continue;
}
switch_mutex_lock(cp->audio_mutex);
if (switch_test_flag(cp->handle, SWITCH_FILE_OPEN)) {
if (source->has_video) {
switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
} else {
switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
}
if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
switch_mutex_unlock(cp->audio_mutex);
continue;
}
}
bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
if (bused > source->samples * 768) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n",
cp->func, cp->file, cp->line, bused, (long)source->samples);
@ -552,15 +619,24 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
switch_image_t *img = (switch_image_t *) pop;
switch_image_t *img;
switch_image_t *imgcp = NULL;
if (source->total == 1) {
switch_queue_push(source->context_list->video_q, img);
} else {
if (source->context_list) {
switch_mutex_lock(source->mutex);
if (!pop) break;
img = (switch_image_t *) pop;
switch_mutex_lock(source->mutex);
if (source->context_list) {
if (source->total == 1) {
switch_queue_push(source->context_list->video_q, img);
} else {
for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
if (!cp->ready) {
continue;
}
if (cp->video_q) {
imgcp = NULL;
switch_img_copy(img, &imgcp);
@ -570,24 +646,20 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
}
}
}
}
switch_mutex_unlock(source->mutex);
}
switch_img_free(&img);
}
switch_img_free(&img);
}
switch_mutex_unlock(source->mutex);
}
}
}
switch_core_timer_destroy(&timer);
if (RUNNING && source->shuffle) {
skip = do_rand(dir_count);
}
}
switch_dir_close(source->dir_handle);
source->dir_handle = NULL;
if (source->full_reload) {
if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name);
@ -635,6 +707,9 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
source->part_reload = 0;
if (source->timer.interval) {
switch_core_timer_destroy(&source->timer);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
@ -647,6 +722,15 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
done:
if (source->dir_handle) {
switch_dir_close(source->dir_handle);
source->dir_handle = NULL;
}
if (source->timer.interval) {
switch_core_timer_destroy(&source->timer);
}
switch_safe_free(source->banner_txt);
if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
@ -692,6 +776,7 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
local_stream_source_t *source;
char *alt_path = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_memory_pool_t *pool;
/* already buffering a step back, so always disable it */
handle->pre_buffer_datalen = 0;
@ -727,11 +812,20 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
goto end;
}
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
//if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
// abort();
//}
pool = handle->memory_pool;
if ((context = switch_core_alloc(pool, sizeof(*context))) == 0) {
abort();
}
switch_queue_create(&context->video_q, 500, handle->memory_pool);
context->pool = pool;
switch_queue_create(&context->video_q, 500, context->pool);
handle->samples = 0;
handle->samplerate = source->rate;
@ -744,7 +838,7 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
handle->interval = source->interval;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening Stream [%s] %dhz\n", path, handle->samplerate);
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
if (switch_buffer_create_dynamic(&context->audio_buffer, 512, 1024, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
status = SWITCH_STATUS_MEMERR;
@ -779,36 +873,50 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
static switch_status_t local_stream_file_close(switch_file_handle_t *handle)
{
local_stream_context_t *cp, *last = NULL, *context = handle->private_info;
local_stream_context_t *context = NULL, *last = NULL, *cp = NULL;
local_stream_source_t *source;
context = handle->private_info;
switch_assert(context);
//pool = context->pool;
source = context->source;
context->ready = 0;
switch_mutex_lock(context->source->mutex);
for (cp = context->source->context_list; cp; cp = cp->next) {
switch_mutex_lock(source->mutex);
for (cp = source->context_list; cp; cp = cp->next) {
if (cp == context) {
if (last) {
last->next = cp->next;
} else {
context->source->context_list = cp->next;
}
source->context_list = cp->next;
}
break;
}
last = cp;
}
switch_mutex_lock(context->audio_mutex);
if (context->source->has_video) {
if (source->has_video) {
flush_video_queue(context->video_q);
switch_queue_trypush(context->video_q, NULL);
switch_queue_interrupt_all(context->video_q);
flush_video_queue(context->video_q);
}
source->total--;
switch_img_free(&context->banner_img);
context->source->total--;
switch_mutex_unlock(context->source->mutex);
switch_buffer_destroy(&context->audio_buffer);
switch_thread_rwlock_unlock(context->source->rwlock);
switch_mutex_unlock(context->audio_mutex);
//switch_core_destroy_memory_pool(&pool);
context->handle = NULL;
handle->private_info = NULL;
switch_mutex_unlock(source->mutex);
switch_thread_rwlock_unlock(source->rwlock);
return SWITCH_STATUS_SUCCESS;
}
@ -887,6 +995,9 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
frame->img = (switch_image_t *) pop;
context->sent_png = 0;
if (frame->img->d_w != context->last_w || frame->img->d_h != context->last_h) {
context->newres = 1;
}
context->last_w = frame->img->d_w;
context->last_h = frame->img->d_h;
goto got_img;
@ -920,6 +1031,10 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
if (context->source->banner_txt) {
if ((!context->banner_timeout || context->banner_timeout >= now)) {
if (context->newres) {
switch_img_free(&context->banner_img);
context->newres = 0;
}
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;
@ -935,6 +1050,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
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);
//switch_img_patch(frame->img, context->banner_img, 0, 0);
}
return SWITCH_STATUS_SUCCESS;
@ -944,29 +1060,36 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
{
local_stream_context_t *context = handle->private_info;
switch_size_t bytes = 0;
size_t need = *len * 2 * handle->real_channels;
size_t need;
if (!context->source->ready) {
if (!(context->ready && context->source->ready)) {
*len = 0;
return SWITCH_STATUS_FALSE;
}
switch_mutex_lock(context->audio_mutex);
need = *len * 2 * context->source->channels;
if ((bytes = switch_buffer_read(context->audio_buffer, data, need))) {
*len = bytes / 2 / handle->real_channels;
*len = bytes / 2 / context->source->channels;
} else {
size_t blank = (handle->samplerate / 20) * 2 * handle->real_channels;
size_t blank;
switch_assert(handle->samplerate <= 48000);
switch_assert(handle->real_channels <= 2);
blank = (handle->samplerate / 4) * 2 * handle->real_channels;
if (need > blank) {
need = blank;
}
memset(data, 0, need);
*len = need / 2 / handle->real_channels;
*len = need / 2 / context->source->channels;
}
switch_mutex_unlock(context->audio_mutex);
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
@ -1059,8 +1182,8 @@ static void launch_thread(const char *name, const char *path, switch_xml_t direc
}
source->samples = switch_samples_per_packet(source->rate, source->interval);
source->abuflen = (source->samples * 2 * source->channels) + 1024;
source->abuf = switch_core_alloc(source->pool, source->abuflen);
source->abuflen = (source->samples * 2 * source->channels);
source->abuf = switch_core_alloc(source->pool, source->abuflen + 1024);
switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);
switch_threadattr_create(&thd_attr, source->pool);
switch_threadattr_detach_set(thd_attr, 1);

View File

@ -782,6 +782,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
switch_resample_destroy(&fh->resampler);
if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {
switch_core_destroy_memory_pool(&fh->memory_pool);
}
fh->memory_pool = NULL;
switch_safe_free(fh->dbuf);
if (fh->spool_path) {
char *command;
@ -799,16 +806,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
free(command);
}
UNPROTECT_INTERFACE(fh->file_interface);
if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {
switch_core_destroy_memory_pool(&fh->memory_pool);
}
switch_safe_free(fh->dbuf);
return status;
}