[vlc-commits] [Git][videolan/vlc][master] 4 commits: display: add an option to display SPUs in black bars
Steve Lhomme (@robUx4)
gitlab at videolan.org
Thu Mar 28 15:17:41 UTC 2024
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
c7f0adde by Steve Lhomme at 2024-03-28T14:54:23+00:00
display: add an option to display SPUs in black bars
To do that we need the video to fill the entire window.
- - - - -
d39c000d by Steve Lhomme at 2024-03-28T14:54:23+00:00
vout_subpictures: only pass the width/height of the output area
The subpicture doesn't need to know more.
- - - - -
d423ca07 by Steve Lhomme at 2024-03-28T14:54:23+00:00
video_output: pass the display size to subpicture rendering for blending displays
We already pass the position of the video in the display. So we have both information all the time.
Plus the format SAR was already using the display SAR.
- - - - -
349e7c09 by Steve Lhomme at 2024-03-28T14:54:23+00:00
vout_subpictures: show subtitles in black bars
This is disabling the subtitle area "stacking" as it forces the source
subtitle subpicture to be absolute. But absolute subpictures have absolute
coordinates inside the (unscaled) video. They are not meant to be shown
outside of the video area.
- - - - -
9 changed files:
- include/vlc_spu.h
- include/vlc_vout_display.h
- lib/media_player.c
- modules/stream_out/transcode/video.c
- modules/video_output/splitter.c
- src/libvlc-module.c
- src/video_output/video_output.c
- src/video_output/vout_intf.c
- src/video_output/vout_subpictures.c
Changes:
=====================================
include/vlc_spu.h
=====================================
@@ -83,6 +83,7 @@ VLC_API void spu_PutSubpicture( spu_t *, subpicture_t * );
*/
VLC_API struct vlc_render_subpicture * spu_Render( spu_t *spu, const vlc_fourcc_t *p_chroma_list,
const video_format_t *p_fmt_dst, const video_format_t *p_fmt_src,
+ bool spu_in_full_window,
const struct vout_display_place_t *video_position,
vlc_tick_t system_now, vlc_tick_t pts,
bool ignore_osd );
=====================================
include/vlc_vout_display.h
=====================================
@@ -99,6 +99,7 @@ struct vout_display_placement {
vlc_video_align_t align; /**< Alignment within the window */
enum vlc_video_fitting fitting; /**< Scaling/fitting mode */
vlc_rational_t zoom; /**< Zoom ratio (if fitting is disabled) */
+ bool full_fill; /**< whether the rendering will take the whole display */
};
/**
=====================================
lib/media_player.c
=====================================
@@ -703,6 +703,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
var_Create (mp, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
var_Create (mp, "osd", VLC_VAR_BOOL); // off
+ var_Create (mp, "spu-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
doinherit = module_exists("marq") ? VLC_VAR_DOINHERIT : 0;
var_Create(mp, "marq-marquee", VLC_VAR_STRING);
=====================================
modules/stream_out/transcode/video.c
=====================================
@@ -468,7 +468,7 @@ static picture_t * RenderSubpictures( sout_stream_id_sys_t *id, picture_t *p_pic
fmt.i_sar_den = fmt.i_sar_num = 1;
vlc_render_subpicture *p_subpic = spu_Render( id->p_spu, NULL, &fmt,
- &outfmt, NULL, vlc_tick_now(), p_pic->date,
+ &outfmt, false, NULL, vlc_tick_now(), p_pic->date,
false );
/* Overlay subpicture */
=====================================
modules/video_output/splitter.c
=====================================
@@ -287,6 +287,7 @@ static int vlc_vidsplit_Open(vout_display_t *vd,
.align = { 0, 0 } /* TODO */,
.fitting = VLC_VIDEO_FIT_SMALLER,
.zoom = { 1, 1 },
+ .full_fill = true,
},
};
const char *modname = output->psz_module;
=====================================
src/libvlc-module.c
=====================================
@@ -787,6 +787,10 @@ static const char* const ppsz_restore_playback_desc[] = {
#define SPU_LONGTEXT N_( \
"You can completely disable the sub-picture processing.")
+#define SPU_FULL_TEXT N_("Display sub-pictures on full window")
+#define SPU_FULL_LONGTEXT N_( \
+ "It allows showing subtitles in black bars.")
+
#define SECONDARY_SUB_POSITION_TEXT N_("Position of secondary subtitles")
#define SECONDARY_SUB_POSITION_LONGTEXT N_( \
"Place on video where to display secondary subtitles (default bottom center).")
@@ -1748,6 +1752,8 @@ vlc_module_begin ()
add_bool( "spu", true, SPU_TEXT, SPU_LONGTEXT )
change_safe ()
+ add_bool( "spu-fill", true, SPU_FULL_TEXT, SPU_FULL_LONGTEXT )
+ change_safe ()
add_bool( "osd", true, OSD_TEXT, OSD_LONGTEXT )
add_module("text-renderer", "text renderer", "any",
TEXTRENDERER_TEXT, TEXTRENDERER_LONGTEXT)
=====================================
src/video_output/video_output.c
=====================================
@@ -682,6 +682,7 @@ static void VoutGetDisplayCfg(vout_thread_sys_t *p_vout, const video_format_t *f
const int display_height = var_GetInteger(vout, "height");
cfg->display.width = display_width > 0 ? display_width : 0;
cfg->display.height = display_height > 0 ? display_height : 0;
+ cfg->display.full_fill = var_GetBool(vout, "spu-fill");
cfg->display.fitting = var_GetBool(vout, "autoscale")
? var_InheritFit(VLC_OBJECT(vout)) : VLC_VIDEO_FIT_NONE;
unsigned msar_num, msar_den;
@@ -1121,14 +1122,14 @@ static vlc_render_subpicture *RenderSPUs(vout_thread_sys_t *sys,
const vlc_fourcc_t *subpicture_chromas,
const video_format_t *spu_frame,
vlc_tick_t system_now, vlc_tick_t render_subtitle_date,
- bool ignore_osd,
+ bool ignore_osd, bool spu_in_full_window,
const vout_display_place_t *video_position)
{
if (unlikely(sys->spu == NULL))
return NULL;
return spu_Render(sys->spu,
subpicture_chromas, spu_frame,
- sys->display->source, video_position,
+ sys->display->source, spu_in_full_window, video_position,
system_now, render_subtitle_date,
ignore_osd);
}
@@ -1164,6 +1165,8 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
const bool vd_does_blending = !do_snapshot &&
vd->info.subpicture_chromas &&
*vd->info.subpicture_chromas != 0;
+ const bool spu_in_full_window = vd->cfg->display.full_fill &&
+ vd_does_blending;
//FIXME: Denying blending_before_converter if vd->source->orientation != ORIENT_NORMAL
//will have the effect that snapshots miss the subpictures. We do this
@@ -1183,10 +1186,12 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
fmt_spu = *vd->source;
fmt_spu.i_sar_num = vd->cfg->display.sar.num;
fmt_spu.i_sar_den = vd->cfg->display.sar.den;
+ fmt_spu.i_x_offset = 0;
+ fmt_spu.i_y_offset = 0;
fmt_spu.i_width =
- fmt_spu.i_visible_width = place.width;
+ fmt_spu.i_visible_width = vd->cfg->display.width;
fmt_spu.i_height =
- fmt_spu.i_visible_height = place.height;
+ fmt_spu.i_visible_height = vd->cfg->display.height;
} else {
if (blending_before_converter) {
fmt_spu = *vd->source;
@@ -1223,7 +1228,7 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
if (!vd_does_blending && blending_before_converter && sys->spu_blend) {
vlc_render_subpicture *subpic = RenderSPUs(sys, NULL, &fmt_spu_rot,
system_now, render_subtitle_date,
- do_snapshot, video_place);
+ do_snapshot, spu_in_full_window, video_place);
if (subpic) {
picture_t *blent = picture_pool_Get(sys->private_pool);
if (blent) {
@@ -1273,7 +1278,7 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
{
vlc_render_subpicture *subpic = RenderSPUs(sys, NULL, &fmt_spu_rot,
system_now, render_subtitle_date,
- do_snapshot, video_place);
+ do_snapshot, spu_in_full_window, video_place);
if (subpic)
{
picture_BlendSubpicture(todisplay, sys->spu_blend, subpic);
@@ -1285,7 +1290,7 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
if (vd_does_blending)
*out_subpic = RenderSPUs(sys, vd->info.subpicture_chromas, &fmt_spu_rot,
system_now, render_subtitle_date,
- false, video_place);
+ false, spu_in_full_window, video_place);
else
*out_subpic = NULL;
=====================================
src/video_output/vout_intf.c
=====================================
@@ -298,6 +298,10 @@ void vout_CreateVars( vout_thread_t *p_vout )
/* Viewpoint */
var_Create( p_vout, "viewpoint", VLC_VAR_ADDRESS );
var_Create( p_vout, "viewpoint-changeable", VLC_VAR_BOOL );
+
+ /* SPU in full window */
+ var_Create( p_vout, "spu-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
+ | VLC_VAR_ISCOMMAND );
}
void vout_IntfInit( vout_thread_t *p_vout )
=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -135,6 +135,8 @@ struct spu_private_t {
subpicture_t *p_processed;
video_format_t fmtsrc;
video_format_t fmtdst;
+ bool spu_in_full_window;
+ vout_display_place_t video_position;
vlc_fourcc_t chroma_list[SPU_CHROMALIST_COUNT+1];
bool live;
} prerender;
@@ -579,12 +581,13 @@ static void SpuAreaFixOverlap(spu_area_t *dst,
}
-static void SpuAreaFitInside(spu_area_t *area, const spu_area_t *boundary)
+static void SpuAreaFitInside(spu_area_t *area, const unsigned boundary_width,
+ const unsigned boundary_height)
{
spu_area_t a = spu_area_scaled(*area);
bool modified = false;
- const int i_error_x = (a.x + a.width) - boundary->width;
+ const int i_error_x = (a.x + a.width) - boundary_width;
if (i_error_x > 0)
{
a.x -= i_error_x;
@@ -596,7 +599,7 @@ static void SpuAreaFitInside(spu_area_t *area, const spu_area_t *boundary)
modified = true;
}
- const int i_error_y = (a.y + a.height) - boundary->height;
+ const int i_error_y = (a.y + a.height) - boundary_height;
if (i_error_y > 0)
{
a.y -= i_error_y;
@@ -952,7 +955,7 @@ static struct subpicture_region_rendered *SpuRenderRegion(spu_t *spu,
subpicture_region_t *region,
const spu_scale_t scale_size, bool apply_scale,
const vlc_fourcc_t *chroma_list,
- const video_format_t *fmt,
+ const unsigned output_width, const unsigned output_height,
const spu_area_t *subtitle_area, size_t subtitle_area_count,
vlc_tick_t render_date)
{
@@ -1036,10 +1039,7 @@ static struct subpicture_region_rendered *SpuRenderRegion(spu_t *spu,
if (subpic->b_subtitle)
restrained.y -= y_margin;
- spu_area_t display = spu_area_create(0, 0, fmt->i_visible_width,
- fmt->i_visible_height,
- spu_scale_unit());
- SpuAreaFitInside(&restrained, &display);
+ SpuAreaFitInside(&restrained, output_width, output_height);
/* Fix the position for the current scale_size */
x_offset = spu_scale_w(restrained.x, restrained.scale);
@@ -1317,6 +1317,23 @@ static void spu_UpdateOriginalSize(spu_t *spu, subpicture_t *subpic,
}
}
+static bool IsSubpicInVideo(const subpicture_t *subpic, bool spu_in_full_window)
+{
+ // no spu outside video allowed
+ if (!spu_in_full_window)
+ return true;
+
+ // absolute spu in video coordinates
+ if (subpic->b_absolute)
+ return true;
+
+ // only subtitle SPUs allowed outside video
+ if (!subpic->b_subtitle)
+ return true;
+
+ return false;
+}
+
/**
* This function renders all sub picture units in the list.
*/
@@ -1326,6 +1343,7 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
const vlc_fourcc_t *chroma_list,
const video_format_t *fmt_dst,
const video_format_t *fmt_src,
+ bool spu_in_full_window,
const vout_display_place_t *video_position,
vlc_tick_t system_now,
vlc_tick_t render_subtitle_date,
@@ -1380,6 +1398,16 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
const unsigned i_original_width = subpic->i_original_picture_width;
const unsigned i_original_height = subpic->i_original_picture_height;
+ const bool subpic_in_video = IsSubpicInVideo(subpic, spu_in_full_window);
+
+ unsigned output_width, output_height;
+ if (subpic_in_video) {
+ output_width = video_position->width;
+ output_height = video_position->height;
+ } else {
+ output_width = fmt_dst->i_visible_width;
+ output_height = fmt_dst->i_visible_height;
+ }
/* Render all regions
* We always transform non absolute subtitle into absolute one on the
@@ -1410,9 +1438,9 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
};
if (region_sar.num <= 0 || region_sar.den <= 0) {
- const uint64_t i_sar_num = (uint64_t)fmt_dst->i_visible_width *
+ const uint64_t i_sar_num = (uint64_t)output_width *
fmt_dst->i_sar_num * i_original_height;
- const uint64_t i_sar_den = (uint64_t)fmt_dst->i_visible_height *
+ const uint64_t i_sar_den = (uint64_t)output_height *
fmt_dst->i_sar_den * i_original_width;
vlc_ureduce(®ion_sar.num, ®ion_sar.den,
@@ -1426,9 +1454,9 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
// position the rendered video, rather than the whole output format
// expand the width using the SAR
spu_scale_t scale;
- scale = spu_scale_createq((uint64_t)video_position->height * fmt_dst->i_sar_den * region_sar.num,
+ scale = spu_scale_createq((uint64_t)output_height * fmt_dst->i_sar_den * region_sar.num,
(uint64_t)i_original_height * fmt_dst->i_sar_num * region_sar.den,
- video_position->height,
+ output_height,
i_original_height);
/* Check scale validity */
@@ -1448,7 +1476,7 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
output_last_ptr = SpuRenderRegion(spu, &area,
&forced_subpic, entry->channel_order,
rendered_region, scale, !external_scale,
- chroma_list, fmt_dst,
+ chroma_list, output_width, output_height,
subtitle_area, subtitle_area_count,
subpic->b_subtitle ? render_subtitle_date : system_now);
if (rendered_region != region)
@@ -1456,9 +1484,11 @@ static vlc_render_subpicture *SpuRenderSubpictures(spu_t *spu,
if (unlikely(output_last_ptr == NULL))
continue;
- // place the region inside the video area
- output_last_ptr->place.x += video_position->x;
- output_last_ptr->place.y += video_position->y;
+ if (subpic_in_video) {
+ // place the region inside the video area
+ output_last_ptr->place.x += video_position->x;
+ output_last_ptr->place.y += video_position->y;
+ }
vlc_vector_push(&output->regions, output_last_ptr);
@@ -1610,6 +1640,8 @@ static int SubSourceDelProxyCallbacks(filter_t *filter, void *opaque)
static void spu_PrerenderWake(spu_private_t *sys,
const video_format_t *fmt_dst,
const video_format_t *fmt_src,
+ bool spu_in_full_window,
+ const vout_display_place_t *video_position,
const vlc_fourcc_t *chroma_list)
{
vlc_mutex_lock(&sys->prerender.lock);
@@ -1623,6 +1655,8 @@ static void spu_PrerenderWake(spu_private_t *sys,
video_format_Clean(&sys->prerender.fmtsrc);
video_format_Copy(&sys->prerender.fmtsrc, fmt_src);
}
+ sys->prerender.spu_in_full_window = spu_in_full_window;
+ sys->prerender.video_position = *video_position;
for(size_t i=0; i<SPU_CHROMALIST_COUNT; i++)
{
@@ -1744,6 +1778,13 @@ static void * spu_PrerenderThread(void *priv)
video_format_Copy(&fmtdst, &sys->prerender.fmtdst);
video_format_Copy(&fmtsrc, &sys->prerender.fmtsrc);
+ if (IsSubpicInVideo(sys->prerender.p_processed, sys->prerender.spu_in_full_window))
+ {
+ fmtdst.i_width = fmtdst.i_visible_width = sys->prerender.video_position.width;
+ fmtdst.i_height = fmtdst.i_visible_height = sys->prerender.video_position.height;
+ fmtdst.i_sar_num = fmtdst.i_sar_den = 1;
+ }
+
vlc_mutex_unlock(&sys->prerender.lock);
spu_PrerenderText(spu, sys->prerender.p_processed,
@@ -2137,6 +2178,7 @@ vlc_render_subpicture *spu_Render(spu_t *spu,
const vlc_fourcc_t *chroma_list,
const video_format_t *fmt_dst,
const video_format_t *fmt_src,
+ bool spu_in_full_window,
const vout_display_place_t *video_position,
vlc_tick_t system_now,
vlc_tick_t render_subtitle_date,
@@ -2209,7 +2251,7 @@ vlc_render_subpicture *spu_Render(spu_t *spu,
}
/* wake up prerenderer, we have some video size and chroma */
- spu_PrerenderWake(sys, fmt_dst, fmt_src, chroma_list);
+ spu_PrerenderWake(sys, fmt_dst, fmt_src, spu_in_full_window, video_position, chroma_list);
vlc_mutex_lock(&sys->lock);
@@ -2236,8 +2278,16 @@ vlc_render_subpicture *spu_Render(spu_t *spu,
subpic->i_start = entry->start;
subpic->i_stop = entry->stop;
+ video_format_t fmtdst = *fmt_dst;
+ if (IsSubpicInVideo(subpic, spu_in_full_window))
+ {
+ fmtdst.i_width = fmtdst.i_visible_width = video_position->width;
+ fmtdst.i_height = fmtdst.i_visible_height = video_position->height;
+ fmtdst.i_sar_num = fmtdst.i_sar_den = 1;
+ }
+
subpicture_Update(subpic,
- fmt_src, fmt_dst,
+ fmt_src, &fmtdst,
subpic->b_subtitle ? render_subtitle_date : system_now);
}
@@ -2251,6 +2301,7 @@ vlc_render_subpicture *spu_Render(spu_t *spu,
chroma_list,
fmt_dst,
fmt_src,
+ spu_in_full_window,
video_position,
system_now,
render_subtitle_date,
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8b09d72394f3ec75b388aaaea4415331f535c4a4...349e7c09eeea8e947eb560d4890a784e1772aa22
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8b09d72394f3ec75b388aaaea4415331f535c4a4...349e7c09eeea8e947eb560d4890a784e1772aa22
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list