diff --git a/src/include/switch_core.h b/src/include/switch_core.h index cb24be1cef..a935b2570b 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -251,6 +251,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_pop(switch_core_session_t SWITCH_DECLARE(switch_status_t) switch_core_media_bug_exec_all(switch_core_session_t *orig_session, const char *function, switch_media_bug_exec_cb_t cb, void *user_data); +SWITCH_DECLARE(uint32_t) switch_core_media_bug_patch_video(switch_core_session_t *orig_session, switch_frame_t *frame); SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function); /*! \brief Add a media bug to the session diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 000611bea4..a73ee619e0 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -489,7 +489,8 @@ typedef enum { SWITCH_ABC_TYPE_TAP_NATIVE_WRITE, SWITCH_ABC_TYPE_CLOSE, SWITCH_ABC_TYPE_READ_VIDEO_PING, - SWITCH_ABC_TYPE_STREAM_VIDEO_PING + SWITCH_ABC_TYPE_STREAM_VIDEO_PING, + SWITCH_ABC_TYPE_VIDEO_PATCH } switch_abc_type_t; typedef struct { @@ -1731,7 +1732,8 @@ typedef enum { SMBF_MASK = (1 << 16), SMBF_READ_VIDEO_PING = (1 << 17), SMBF_READ_VIDEO_STREAM = (1 << 18), - SMBF_WRITE_VIDEO_STREAM = (1 << 19) + SMBF_WRITE_VIDEO_STREAM = (1 << 19), + SMBF_VIDEO_PATCH = (1 << 20) } switch_media_bug_flag_enum_t; typedef uint32_t switch_media_bug_flag_t; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 329ffb77d3..0050f4782e 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -391,6 +391,7 @@ typedef struct mcu_layer_s { int member_id; int idx; int tagged; + int bugged; int screen_w; int screen_h; int x_pos; @@ -1100,6 +1101,15 @@ static void scale_and_patch(conference_obj_t *conference, mcu_layer_t *layer, sw switch_assert(layer->img); if (switch_img_scale(img, &layer->img, img_w, img_h) == SWITCH_STATUS_SUCCESS) { + if (layer->bugged && layer->member_id > -1) { + conference_member_t *member; + if ((member = conference_member_get(conference, layer->member_id))) { + switch_frame_t write_frame = { 0 }; + write_frame.img = layer->img; + switch_core_media_bug_patch_video(member->session, &write_frame); + switch_thread_rwlock_unlock(member->rwlock); + } + } switch_img_patch(IMG, layer->img, x_pos, y_pos); } @@ -1921,11 +1931,12 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread } else { img = imember->avatar_png_img; } - + + layer = NULL; + if (img) { int i; - layer = NULL; used++; switch_mutex_lock(conference->canvas->mutex); @@ -2030,6 +2041,10 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread img = NULL; layer->tagged = 1; + + if (switch_core_media_bug_count(imember->session, "patch:video")) { + layer->bugged = 1; + } } } @@ -2073,6 +2088,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread } layer->tagged = 0; } + layer->bugged = 0; } } @@ -2162,14 +2178,14 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread write_frame.packetlen = 0; //switch_core_session_write_video_frame(imember->session, &write_frame, SWITCH_IO_FLAG_NONE, 0); - + if (switch_frame_buffer_dup(imember->fb, &write_frame, &dupframe) == SWITCH_STATUS_SUCCESS) { switch_queue_push(imember->mux_out_queue, dupframe); dupframe = NULL; } if (imember->session) { - switch_core_session_rwunlock(imember->session); + switch_core_session_rwunlock(imember->session); } } diff --git a/src/mod/applications/mod_cv/mod_cv.cpp b/src/mod/applications/mod_cv/mod_cv.cpp index 3ce074047b..4baad69194 100644 --- a/src/mod/applications/mod_cv/mod_cv.cpp +++ b/src/mod/applications/mod_cv/mod_cv.cpp @@ -195,11 +195,10 @@ static void context_render_text(cv_context_t *context, struct overlay *overlay, if (!text) text = overlay->text; int len = strlen(text); + if (len < 5) len = 5; - - width = (int) (float)(font_size * 0.75f * len); - + width = (int) (float)(font_size * .95f * len); switch_color_set_rgb(&bgcolor, overlay->bg); @@ -817,7 +816,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi } } - if (context->debug || !context->overlay_count) { + if (context->rawImage && (context->debug || !context->overlay_count)) { libyuv::RGB24ToI420((uint8_t *)context->rawImage->imageData, context->w * 3, frame->img->planes[0], frame->img->stride[0], frame->img->planes[1], frame->img->stride[1], @@ -1151,6 +1150,7 @@ static switch_bool_t cv_bug_callback(switch_media_bug_t *bug, void *user_data, s } break; case SWITCH_ABC_TYPE_READ_VIDEO_PING: + case SWITCH_ABC_TYPE_VIDEO_PATCH: { switch_frame_t *frame = switch_core_media_bug_get_video_ping_frame(bug); video_thread_callback(context->session, frame, context); @@ -1173,6 +1173,8 @@ SWITCH_STANDARD_APP(cv_bug_start_function) int x, n; char *argv[25] = { 0 }; int argc; + switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING; + const char *function = "mod_cv"; if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_cv_bug_"))) { if (!zstr(data) && !strcasecmp(data, "stop")) { @@ -1197,9 +1199,14 @@ SWITCH_STANDARD_APP(cv_bug_start_function) parse_params(context, 1, argc, argv); } + if (!strcasecmp(argv[0], "patch") || !strcasecmp(argv[1], "patch")) { + function = "patch:video"; + flags = SMBF_VIDEO_PATCH; + } + switch_thread_rwlock_rdlock(MODULE_INTERFACE->rwlock); - if ((status = switch_core_media_bug_add(session, "cv_bug", NULL, cv_bug_callback, context, 0, SMBF_READ_VIDEO_PING, &bug)) != SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_media_bug_add(session, function, NULL, cv_bug_callback, context, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure!\n"); switch_thread_rwlock_unlock(MODULE_INTERFACE->rwlock); return; @@ -1227,6 +1234,8 @@ SWITCH_STANDARD_API(cv_bug_api_function) char *nested_cascade_path = NULL; char *lbuf = NULL; int x, n, i; + switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING; + const char *function = "mod_cv"; if (zstr(cmd)) { goto usage; @@ -1256,7 +1265,7 @@ SWITCH_STANDARD_API(cv_bug_api_function) switch_channel_set_private(channel, "_cv_bug_", NULL); switch_core_media_bug_remove(rsession, &bug); stream->write_function(stream, "+OK Success\n"); - } else if (!strcasecmp(action, "start") || !strcasecmp(action, "mod")) { + } else if (!strcasecmp(action, "start") || !strcasecmp(action, "mod") || !strcasecmp(action, "patch")) { context = (cv_context_t *) switch_core_media_bug_get_user_data(bug); switch_assert(context); parse_params(context, 2, argc, argv); @@ -1268,7 +1277,7 @@ SWITCH_STANDARD_API(cv_bug_api_function) goto done; } - if (!zstr(action) && strcasecmp(action, "start")) { + if (!zstr(action) && strcasecmp(action, "start") && strcasecmp(action, "patch")) { goto usage; } @@ -1281,7 +1290,13 @@ SWITCH_STANDARD_API(cv_bug_api_function) switch_thread_rwlock_rdlock(MODULE_INTERFACE->rwlock); - if ((status = switch_core_media_bug_add(rsession, "cv_bug", NULL, cv_bug_callback, context, 0, SMBF_READ_VIDEO_PING, &bug)) != SWITCH_STATUS_SUCCESS) { + if (!strcasecmp(action, "patch")) { + function = "patch:video"; + flags = SMBF_VIDEO_PATCH; + } + + if ((status = switch_core_media_bug_add(rsession, function, NULL, + cv_bug_callback, context, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "-ERR Failure!\n"); switch_thread_rwlock_unlock(MODULE_INTERFACE->rwlock); goto done; diff --git a/src/switch_core_media_bug.c b/src/switch_core_media_bug.c index 993231b28e..8c27f4beae 100644 --- a/src/switch_core_media_bug.c +++ b/src/switch_core_media_bug.c @@ -832,6 +832,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_pop(switch_core_session_t return SWITCH_STATUS_FALSE; } + SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function) { switch_media_bug_t *bp; @@ -850,6 +851,41 @@ SWITCH_DECLARE(uint32_t) switch_core_media_bug_count(switch_core_session_t *orig return x; } +SWITCH_DECLARE(uint32_t) switch_core_media_bug_patch_video(switch_core_session_t *orig_session, switch_frame_t *frame) +{ + switch_media_bug_t *bp; + uint32_t x = 0, ok = SWITCH_TRUE, prune = 0; + + if (orig_session->bugs) { + switch_thread_rwlock_rdlock(orig_session->bug_rwlock); + for (bp = orig_session->bugs; bp; bp = bp->next) { + if (!switch_test_flag(bp, SMBF_PRUNE) && !switch_test_flag(bp, SMBF_LOCK) && !strcmp(bp->function, "patch:video")) { + if (bp->ready && frame->img && switch_test_flag(bp, SMBF_VIDEO_PATCH)) { + bp->ping_frame = frame; + if (bp->callback) { + if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_VIDEO_PATCH) == SWITCH_FALSE + || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) { + ok = SWITCH_FALSE; + } + } + bp->ping_frame = NULL; + } + + if (ok == SWITCH_FALSE) { + switch_set_flag(bp, SMBF_PRUNE); + prune++; + } else x++; + } + } + switch_thread_rwlock_unlock(orig_session->bug_rwlock); + if (prune) { + switch_core_media_bug_prune(orig_session); + } + } + + return x; +} + SWITCH_DECLARE(switch_status_t) switch_core_media_bug_exec_all(switch_core_session_t *orig_session, const char *function, switch_media_bug_exec_cb_t cb, void *user_data) { diff --git a/src/switch_core_video.c b/src/switch_core_video.c index 63d02dff3b..35a9c51ce4 100644 --- a/src/switch_core_video.c +++ b/src/switch_core_video.c @@ -836,7 +836,7 @@ SWITCH_DECLARE(switch_image_t *) switch_img_write_text_img(int w, int h, const c if (len < 5) len = 5; - width = (int) (float)(font_size * 0.75f * len); + width = (int) (float)(font_size * 0.95f * len); txtimg = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, font_size * 2, 1);