This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 50671a018d3954cdb10bcdf418f122eb27ab9e9b Author: Marton Balint <[email protected]> AuthorDate: Sun Jan 11 21:37:19 2026 +0100 Commit: Marton Balint <[email protected]> CommitDate: Wed Jan 21 22:02:50 2026 +0000 fftools/ffplay: add a new -video_bg option for transparent video It allows controlling the background of a transparent video. Default is a checker board pattern. Signed-off-by: Marton Balint <[email protected]> --- doc/ffplay.texi | 7 ++++++ fftools/ffplay.c | 58 ++++++++++++++++++++++++++++++++++++++++++----- fftools/ffplay_renderer.h | 13 +++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/doc/ffplay.texi b/doc/ffplay.texi index 93f77eeece..0b6b905532 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -208,6 +208,13 @@ Vulkan configuration using a list of @var{key}=@var{value} pairs separated by Use HW accelerated decoding. Enable this option will enable vulkan renderer automatically. +@item -video_bg @var{pattern} +Set the video background pattern used for transparent videos. For solid color +patterns you can use the color name or color code as specified in the +@ref{color syntax,,Color section in the ffmpeg-utils(1) manual,ffmpeg-utils}. +You can also use the special @code{tiles} keyword for a checker board style +pattern. This is also the default. + @end table @section While playing diff --git a/fftools/ffplay.c b/fftools/ffplay.c index dcd20e70bc..ca5d6305f7 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -37,6 +37,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/dict.h" #include "libavutil/fifo.h" +#include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/time.h" #include "libavutil/bprint.h" @@ -267,6 +268,7 @@ typedef struct VideoState { AVComplexFloat *rdft_data; int xpos; double last_vis_time; + RenderParams render_params; SDL_Texture *vis_texture; SDL_Texture *sub_texture; SDL_Texture *vid_texture; @@ -350,6 +352,7 @@ static int find_stream_info = 1; static int filter_nbthreads = 0; static int enable_vulkan = 0; static char *vulkan_params = NULL; +static char *video_background = NULL; static const char *hwaccel = NULL; /* current context */ @@ -963,11 +966,44 @@ static void set_sdl_yuv_conversion_mode(AVFrame *frame) #endif } +static void draw_video_background(VideoState *is) +{ + const int tile_size = VIDEO_BACKGROUND_TILE_SIZE; + SDL_Rect *rect = &is->render_params.target_rect; + SDL_BlendMode blendMode; + + if (!SDL_GetTextureBlendMode(is->vid_texture, &blendMode) && blendMode == SDL_BLENDMODE_BLEND) { + switch (is->render_params.video_background_type) { + case VIDEO_BACKGROUND_TILES: + SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255); + fill_rectangle(rect->x, rect->y, rect->w, rect->h); + SDL_SetRenderDrawColor(renderer, 222, 222, 222, 255); + for (int x = 0; x < rect->w; x += tile_size * 2) + fill_rectangle(rect->x + x, rect->y, FFMIN(tile_size, rect->w - x), rect->h); + for (int y = 0; y < rect->h; y += tile_size * 2) + fill_rectangle(rect->x, rect->y + y, rect->w, FFMIN(tile_size, rect->h - y)); + SDL_SetRenderDrawColor(renderer, 237, 237, 237, 255); + for (int y = 0; y < rect->h; y += tile_size * 2) { + int h = FFMIN(tile_size, rect->h - y); + for (int x = 0; x < rect->w; x += tile_size * 2) + fill_rectangle(x + rect->x, y + rect->y, FFMIN(tile_size, rect->w - x), h); + } + break; + case VIDEO_BACKGROUND_COLOR: { + const uint8_t *c = is->render_params.video_background_color; + SDL_SetRenderDrawColor(renderer, c[0], c[1], c[2], c[3]); + fill_rectangle(rect->x, rect->y, rect->w, rect->h); + break; + } + } + } +} + static void video_image_display(VideoState *is) { Frame *vp; Frame *sp = NULL; - SDL_Rect rect; + SDL_Rect *rect = &is->render_params.target_rect; vp = frame_queue_peek_last(&is->pictq); if (vk_renderer) { @@ -1020,7 +1056,7 @@ static void video_image_display(VideoState *is) } } - calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); + calculate_display_rect(rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); set_sdl_yuv_conversion_mode(vp->frame); if (!vp->uploaded) { @@ -1032,15 +1068,16 @@ static void video_image_display(VideoState *is) vp->flip_v = vp->frame->linesize[0] < 0; } - SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0); + draw_video_background(is); + SDL_RenderCopyEx(renderer, is->vid_texture, NULL, rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0); set_sdl_yuv_conversion_mode(NULL); if (sp) { #if USE_ONEPASS_SUBTITLE_RENDER - SDL_RenderCopy(renderer, is->sub_texture, NULL, &rect); + SDL_RenderCopy(renderer, is->sub_texture, NULL, rect); #else int i; - double xratio = (double)rect.w / (double)sp->width; - double yratio = (double)rect.h / (double)sp->height; + double xratio = (double)rect->w / (double)sp->width; + double yratio = (double)rect->h / (double)sp->height; for (i = 0; i < sp->sub.num_rects; i++) { SDL_Rect *sub_rect = (SDL_Rect*)sp->sub.rects[i]; SDL_Rect target = {.x = rect.x + sub_rect->x * xratio, @@ -3228,6 +3265,14 @@ static VideoState *stream_open(const char *filename, av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume); if (startup_volume > 100) av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume); + if (video_background) { + if (strcmp(video_background, "tiles")) { + if (av_parse_color(is->render_params.video_background_color, video_background, -1, NULL) >= 0) + is->render_params.video_background_type = VIDEO_BACKGROUND_COLOR; + else + goto fail; + } + } startup_volume = av_clip(startup_volume, 0, 100); startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME); is->audio_volume = startup_volume; @@ -3741,6 +3786,7 @@ static const OptionDef options[] = { { "filter_threads", OPT_TYPE_INT, OPT_EXPERT, { &filter_nbthreads }, "number of filter threads per graph" }, { "enable_vulkan", OPT_TYPE_BOOL, 0, { &enable_vulkan }, "enable vulkan renderer" }, { "vulkan_params", OPT_TYPE_STRING, OPT_EXPERT, { &vulkan_params }, "vulkan configuration using a list of key=value pairs separated by ':'" }, + { "video_bg", OPT_TYPE_STRING, OPT_EXPERT, { &video_background }, "set video background for transparent videos" }, { "hwaccel", OPT_TYPE_STRING, OPT_EXPERT, { &hwaccel }, "use HW accelerated decoding" }, { NULL, }, }; diff --git a/fftools/ffplay_renderer.h b/fftools/ffplay_renderer.h index dd8e9c06e7..05f739b3ba 100644 --- a/fftools/ffplay_renderer.h +++ b/fftools/ffplay_renderer.h @@ -25,6 +25,19 @@ typedef struct VkRenderer VkRenderer; +#define VIDEO_BACKGROUND_TILE_SIZE 64 + +enum VideoBackgroundType { + VIDEO_BACKGROUND_TILES, + VIDEO_BACKGROUND_COLOR, +}; + +typedef struct RenderParams { + SDL_Rect target_rect; + uint8_t video_background_color[4]; + enum VideoBackgroundType video_background_type; +} RenderParams; + VkRenderer *vk_get_renderer(void); int vk_renderer_create(VkRenderer *renderer, SDL_Window *window, _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
