[vlc-devel] [PATCH] video_output: blend subtitles with hw pics when taking a snaphost
Thomas Guillem
thomas at gllm.fr
Fri Mar 2 12:07:20 CET 2018
Fixes #19892
---
src/video_output/video_output.c | 76 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 3 deletions(-)
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index e1ae9f023a..32348e83a7 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -910,6 +910,59 @@ static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool fra
return VLC_SUCCESS;
}
+static picture_t *ConvertRGBAndBlendBufferNew(filter_t *filter)
+{
+ return picture_NewFromFormat(&filter->fmt_out.video);
+}
+
+static picture_t *ConvertRGBAndBlend(vout_thread_t *vout, picture_t *pic,
+ subpicture_t *subpic)
+{
+ /* This function will convert the pic to RGB32 and blend the subpic to it.
+ * The returned pic can't be used to display since the chroma will be
+ * different than the "vout display" one, but it can be used for snapshots.
+ * */
+
+ assert(vout->p->spu_blend);
+
+ filter_owner_t owner = {
+ .video = {
+ .buffer_new = ConvertRGBAndBlendBufferNew,
+ },
+ };
+ filter_chain_t *filterc = filter_chain_NewVideo(vout, false, &owner);
+ if (!filterc)
+ return NULL;
+
+ es_format_t src = vout->p->spu_blend->fmt_out;
+ es_format_t dst = src;
+ dst.video.i_chroma = VLC_CODEC_RGB32;
+
+ if (filter_chain_AppendConverter(filterc, &src, &dst) != 0)
+ {
+ filter_chain_Delete(filterc);
+ return NULL;
+ }
+
+ picture_Hold(pic);
+ pic = filter_chain_VideoFilter(filterc, pic);
+ filter_chain_Delete(filterc);
+
+ if (pic)
+ {
+ filter_t *swblend = filter_NewBlend(VLC_OBJECT(vout), &dst.video);
+ if (swblend)
+ {
+ bool success = picture_BlendSubpicture(pic, swblend, subpic) > 0;
+ filter_DeleteBlend(swblend);
+ if (success)
+ return pic;
+ }
+ picture_Release(pic);
+ }
+ return NULL;
+}
+
static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
{
vout_thread_sys_t *sys = vout->p;
@@ -1014,6 +1067,7 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
*/
bool is_direct = vout->p->decoder_pool == vout->p->display_pool;
picture_t *todisplay = filtered;
+ picture_t *snap_pic = todisplay;
if (do_early_spu && subpic) {
if (vout->p->spu_blend) {
picture_t *blent = picture_pool_Get(vout->p->private_pool);
@@ -1022,9 +1076,20 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
picture_Copy(blent, filtered);
if (picture_BlendSubpicture(blent, vout->p->spu_blend, subpic)) {
picture_Release(todisplay);
- todisplay = blent;
+ snap_pic = todisplay = blent;
} else
+ {
+ /* Blending failed, likely because the picture is opaque or
+ * read-only. Try to convert the opaque picture to a
+ * software RGB32 one before blending it. */
+ if (do_snapshot)
+ {
+ picture_t *copy = ConvertRGBAndBlend(vout, blent, subpic);
+ if (copy)
+ snap_pic = copy;
+ }
picture_Release(blent);
+ }
}
}
subpicture_Delete(subpic);
@@ -1050,14 +1115,19 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
VideoFormatCopyCropAr(&direct->format, &todisplay->format);
picture_Copy(direct, todisplay);
picture_Release(todisplay);
- todisplay = direct;
+ snap_pic = todisplay = direct;
}
/*
* Take a snapshot if requested
*/
if (do_snapshot)
- vout_snapshot_Set(&vout->p->snapshot, &vd->source, todisplay);
+ {
+ assert(snap_pic);
+ vout_snapshot_Set(&vout->p->snapshot, &vd->source, snap_pic);
+ if (snap_pic != todisplay)
+ picture_Release(snap_pic);
+ }
/* Render the direct buffer */
vout_UpdateDisplaySourceProperties(vd, &todisplay->format);
--
2.11.0
More information about the vlc-devel
mailing list