FS-7656 fix various edge cases with video and non video files mixed into a source, fix a typo bug in file_read_video and fix same bug in mod_vlc, add a new flag to file_read_video to check if the handle is has active video, make mod_conference move the video in and out of a layer when the stream has video or not
This commit is contained in:
parent
434d39d450
commit
385a3b545c
|
@ -916,6 +916,7 @@ SWITCH_DECLARE(switch_status_t) switch_dir_make_recursive(const char *path, swit
|
|||
SWITCH_DECLARE(switch_status_t) switch_dir_open(switch_dir_t ** new_dir, const char *dirname, switch_memory_pool_t *pool);
|
||||
SWITCH_DECLARE(switch_status_t) switch_dir_close(switch_dir_t *thedir);
|
||||
SWITCH_DECLARE(const char *) switch_dir_next_file(switch_dir_t *thedir, char *buf, switch_size_t len);
|
||||
SWITCH_DECLARE(uint32_t) switch_dir_count(switch_dir_t *thedir);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -2558,7 +2558,8 @@ typedef struct switch_frame_buffer_s switch_frame_buffer_t;
|
|||
|
||||
typedef enum {
|
||||
SVR_BLOCK = (1 << 0),
|
||||
SVR_FLUSH = (1 << 1)
|
||||
SVR_FLUSH = (1 << 1),
|
||||
SVR_CHECK = (1 << 2)
|
||||
} switch_video_read_flag_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -1578,6 +1578,10 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
|
|||
av_file_context_t *context = (av_file_context_t *)handle->private_info;
|
||||
int size;
|
||||
|
||||
if ((flags & SVR_CHECK)) {
|
||||
return SWITCH_STATUS_BREAK;
|
||||
}
|
||||
|
||||
if (!context->has_audio && context->has_video && switch_queue_size(context->eh.video_queue) > 0) {
|
||||
memset(data, 0, *len * handle->channels * 2);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
|
|
@ -1906,19 +1906,43 @@ static void check_flush(conference_member_t *member)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -2275,12 +2299,20 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
|
|||
|
||||
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) {
|
||||
|
@ -4989,24 +5021,6 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
|
|||
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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -102,25 +102,45 @@ struct local_stream_source {
|
|||
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;
|
||||
|
@ -128,6 +148,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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++;
|
||||
|
@ -137,14 +158,14 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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) {
|
||||
|
@ -171,6 +192,21 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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) {
|
||||
|
@ -204,11 +240,17 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -221,6 +263,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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);
|
||||
|
@ -265,6 +308,8 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
|
||||
retry:
|
||||
|
||||
source->has_video = switch_core_file_has_video(use_fh);
|
||||
|
||||
is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);
|
||||
|
||||
if (source->hup) {
|
||||
|
@ -281,8 +326,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (is_open) {
|
||||
if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
|
||||
switch_frame_t vid_frame = { 0 };
|
||||
|
@ -290,13 +334,21 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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;
|
||||
}
|
||||
|
@ -333,15 +385,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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;
|
||||
|
||||
|
@ -371,7 +415,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
}
|
||||
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;
|
||||
|
@ -380,6 +424,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
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;
|
||||
|
@ -389,19 +434,18 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,14 +528,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||
|
||||
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);
|
||||
|
@ -649,7 +686,22 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
|
|||
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;
|
||||
|
@ -661,7 +713,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
|
|||
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);
|
||||
|
@ -673,6 +725,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
|
|||
}
|
||||
|
||||
frame->img = (switch_image_t *) pop;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -694,10 +747,13 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
|
|||
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);
|
||||
|
@ -780,6 +836,8 @@ static void launch_thread(const char *name, const char *path, switch_xml_t direc
|
|||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1063,6 +1063,10 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
|
|||
size_t bytes = *len * sizeof(int16_t) * handle->channels, read;
|
||||
libvlc_state_t status;
|
||||
|
||||
if ((flags & SVR_CHECK)) {
|
||||
return SWITCH_STATUS_BREAK;
|
||||
}
|
||||
|
||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) {
|
||||
return vlc_file_av_read(handle, data, len);
|
||||
}
|
||||
|
@ -1143,7 +1147,7 @@ static switch_status_t vlc_file_read_video(switch_file_handle_t *handle, switch_
|
|||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if ((flags && SVR_BLOCK)) {
|
||||
if ((flags & SVR_BLOCK)) {
|
||||
status = switch_queue_pop(vcontext->video_queue, &pop);
|
||||
} else {
|
||||
status = switch_queue_trypop(vcontext->video_queue, &pop);
|
||||
|
|
|
@ -559,6 +559,34 @@ SWITCH_DECLARE(switch_status_t) switch_dir_close(switch_dir_t *thedir)
|
|||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(uint32_t) switch_dir_count(switch_dir_t *thedir)
|
||||
{
|
||||
const char *name;
|
||||
apr_int32_t finfo_flags = APR_FINFO_DIRENT | APR_FINFO_TYPE | APR_FINFO_NAME;
|
||||
uint32_t count = 0;
|
||||
|
||||
apr_dir_rewind(thedir->dir_handle);
|
||||
|
||||
while (apr_dir_read(&(thedir->finfo), finfo_flags, thedir->dir_handle) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
if (thedir->finfo.filetype != APR_REG && thedir->finfo.filetype != APR_LNK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(name = thedir->finfo.fname)) {
|
||||
name = thedir->finfo.name;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
apr_dir_rewind(thedir->dir_handle);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(const char *) switch_dir_next_file(switch_dir_t *thedir, char *buf, switch_size_t len)
|
||||
{
|
||||
const char *fname = NULL;
|
||||
|
|
Loading…
Reference in New Issue