}
}
-static void patch_fnode(conference_obj_t *conference, conference_file_node_t *fnode, switch_frame_t *write_frame)
+static void patch_fnode(conference_obj_t *conference, conference_file_node_t *fnode)
{
if (fnode && fnode->layer_id > -1) {
mcu_layer_t *layer = &conference->canvas->layers[fnode->layer_id];
-
- if (switch_core_file_read_video(&fnode->fh, write_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
+ switch_frame_t file_frame = { 0 };
+ switch_status_t status = switch_core_file_read_video(&fnode->fh, &file_frame, SVR_FLUSH);
+
+ if (status == SWITCH_STATUS_SUCCESS) {
switch_img_free(&layer->cur_img);
- layer->cur_img = write_frame->img;
+ layer->cur_img = file_frame.img;
layer->tagged = 1;
+ } else if (status == SWITCH_STATUS_IGNORE) {
+ if (conference->canvas && fnode->layer_id > -1 ) {
+ canvas_del_fnode_layer(conference, fnode);
+ }
}
}
}
+static void fnode_check_video(conference_obj_t *conference, conference_file_node_t *fnode) {
+ if (switch_core_file_has_video(&fnode->fh) && switch_core_file_read_video(&fnode->fh, NULL, SVR_CHECK) == SWITCH_STATUS_BREAK) {
+ int full_screen = 0;
+
+ if (fnode->fh.params) {
+ full_screen = switch_true(switch_event_get_header(fnode->fh.params, "full-screen"));
+ }
+
+ if (full_screen) {
+ conference->canvas->play_file = 1;
+ conference->playing_video_file = 1;
+ } else {
+ canvas_set_fnode_layer(conference, fnode, -1);
+ }
+ }
+}
+
+
static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thread, void *obj)
{
conference_obj_t *conference = (conference_obj_t *) obj;
switch_mutex_unlock(conference->member_mutex);
- if (conference->async_fnode && conference->async_fnode->layer_id > -1) {
- patch_fnode(conference, conference->async_fnode, &write_frame);
- }
+ if (conference->async_fnode) {
+ if (conference->async_fnode->layer_id > -1) {
+ patch_fnode(conference, conference->async_fnode);
+ } else {
+ fnode_check_video(conference, conference->async_fnode);
+ }
+ }
- if (conference->fnode && conference->fnode->layer_id > -1) {
- patch_fnode(conference, conference->fnode, &write_frame);
+ if (conference->fnode) {
+ if (conference->fnode->layer_id > -1) {
+ patch_fnode(conference, conference->fnode);
+ } else {
+ fnode_check_video(conference, conference->fnode);
+ }
}
if (!conference->playing_video_file) {
return SWITCH_STATUS_SUCCESS;
}
-static void fnode_check_video(conference_obj_t *conference, conference_file_node_t *fnode) {
-
- if (switch_core_file_has_video(&fnode->fh)) {
- int full_screen = 0;
-
- if (fnode->fh.params) {
- full_screen = switch_true(switch_event_get_header(fnode->fh.params, "full-screen"));
- }
-
- if (full_screen) {
- conference->canvas->play_file = 1;
- conference->playing_video_file = 1;
- } else {
- canvas_set_fnode_layer(conference, fnode, -1);
- }
- }
-}
-
static void conference_command_handler(switch_live_array_t *la, const char *cmd, const char *sessid, cJSON *jla, void *user_data)
{
}
switch_file_handle_t chime_fh;
switch_queue_t *video_q;
int has_video;
+ switch_image_t *blank_img;
};
typedef struct local_stream_source local_stream_source_t;
-static int do_rand(void)
+static int do_rand(uint32_t count)
{
double r;
int index;
+
+ if (count < 3) return 0;
+
r = ((double) rand() / ((double) (RAND_MAX) + (double) (1)));
- index = (int) (r * 9) + 1;
+ index = (int) (r * count) + 1;
+
return index;
}
+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);
+ }
+
+}
+
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
local_stream_source_t *source = obj;
switch_file_handle_t fh = { 0 };
local_stream_context_t *cp;
- char file_buf[128] = "", path_buf[512] = "";
+ char file_buf[128] = "", path_buf[512] = "", last_path[512];
switch_timer_t timer = { 0 };
int fd = -1;
switch_buffer_t *audio_buffer;
switch_size_t used;
int skip = 0;
switch_memory_pool_t *temp_pool = NULL;
+ uint32_t dir_count = 0, do_shuffle = 0;
switch_mutex_lock(globals.mutex);
THREADS++;
source->prebuf = DEFAULT_PREBUFFER_SIZE;
}
+ if (source->shuffle) {
+ do_shuffle = 1;
+ }
+
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);
- if (source->shuffle) {
- skip = do_rand();
- }
-
switch_thread_rwlock_create(&source->rwlock, source->pool);
if (RUNNING) {
goto done;
}
+ if (fd > -1) {
+ dir_count = 0;
+ while (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
+ dir_count++;
+ }
+ lseek(fd, 0, SEEK_SET);
+ } else {
+ dir_count = switch_dir_count(source->dir_handle);
+ }
+
+ if (do_shuffle) {
+ skip = do_rand(dir_count);
+ do_shuffle = 0;
+ }
+
switch_yield(1000000);
while (RUNNING && !source->stopped) {
}
}
+ if (dir_count > 1 && !strcmp(last_path, path_buf)) {
+ continue;
+ }
+
if (skip > 0) {
skip--;
continue;
}
+ switch_set_string(last_path, path_buf);
+
fname = path_buf;
fh.prebuf = source->prebuf;
fh.pre_buffer_datalen = source->prebuf;
continue;
}
+
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);
retry:
+ source->has_video = switch_core_file_has_video(use_fh);
+
is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);
if (source->hup) {
}
}
}
-
-
+
if (is_open) {
if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
switch_frame_t vid_frame = { 0 };
if (switch_core_file_read_video(use_fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
if (vid_frame.img) {
source->has_video = 1;
- switch_queue_push(source->video_q, vid_frame.img);
+
+ if (source->total) {
+ switch_queue_push(source->video_q, vid_frame.img);
+ } else {
+ flush_video_queue(source->video_q);
+ }
}
}
+ } else {
+ source->has_video = 0;
}
if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
switch_core_file_close(use_fh);
+
if (use_fh == &source->chime_fh) {
source->chime_counter = source->rate * source->chime_freq;
}
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
if (!source->total) {
- switch_mutex_lock(source->mutex);
-
- while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
- switch_img_free(&img);
- }
-
- switch_mutex_unlock(source->mutex);
-
+ flush_video_queue(source->video_q);
} else {
uint32_t bused = 0;
}
switch_mutex_unlock(source->mutex);
- switch_mutex_lock(source->mutex);
+
while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
switch_image_t *img = (switch_image_t *) pop;
switch_image_t *imgcp = NULL;
switch_queue_push(source->context_list->video_q, img);
} else {
if (source->context_list) {
+ switch_mutex_lock(source->mutex);
for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
if (cp->video_q) {
imgcp = NULL;
}
}
}
+ switch_mutex_unlock(source->mutex);
}
switch_img_free(&img);
}
}
- switch_mutex_unlock(source->mutex);
-
}
}
}
switch_core_timer_destroy(&timer);
if (RUNNING && source->shuffle) {
- skip = do_rand();
+ skip = do_rand(dir_count);
}
}
switch_buffer_destroy(&audio_buffer);
- if (source->video_q) {
- void *pop;
-
- while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
- switch_img_free(&img);
- }
- }
+ flush_video_queue(source->video_q);
if (fd > -1) {
close(fd);
if (!(context->ready && context->source->ready)) {
return SWITCH_STATUS_FALSE;
}
-
+
+ if (!context->source->has_video) {
+ if (frame && context->source->blank_img) {
+ switch_image_t *img = NULL;
+
+ switch_img_copy(context->source->blank_img, &img);
+ frame->img = img;
+ return SWITCH_STATUS_SUCCESS;
+ }
+ 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;
return SWITCH_STATUS_FALSE;
}
- if ((flags && SVR_BLOCK)) {
+ if ((flags & SVR_BLOCK)) {
status = switch_queue_pop(context->video_q, &pop);
} else {
status = switch_queue_trypop(context->video_q, &pop);
}
frame->img = (switch_image_t *) pop;
+
return SWITCH_STATUS_SUCCESS;
}
if ((bytes = switch_buffer_read(context->audio_buffer, data, need))) {
*len = bytes / 2 / handle->real_channels;
} else {
- if (need > 2560) {
- need = 2560;
+ size_t blank = (handle->samplerate / 20) * 2 * handle->real_channels;
+
+ if (need > blank) {
+ need = blank;
}
- memset(data, 255, need);
+
+ memset(data, 0, need);
*len = need / 2 / handle->real_channels;
}
switch_mutex_unlock(context->audio_mutex);
}
} else if (!strcasecmp(var, "timer-name")) {
source->timer_name = switch_core_strdup(source->pool, val);
+ } else if (!strcasecmp(var, "blank-img") && !zstr(val)) {
+ source->blank_img = switch_img_read_png(val, SWITCH_IMG_FMT_I420);
}
}