[vlc-devel] [PATCH] vout: snapshot: fix snapshots cropping

Rémi Denis-Courmont remi at remlab.net
Fri Nov 3 11:52:10 CET 2017


Le 3 novembre 2017 11:32:05 GMT+02:00, Romain Vimont <rom at rom1v.com> a écrit :
>The snapshot picture was created using picture_Copy(), which does not
>handle offsets. As a consequence, snapshots of cropped videos were
>broken.
>
>Therefore, add a function to easily clone the region of a picture into
>a new picture_t, and use it to create the snapshot.
>
>Fixes <https://trac.videolan.org/vlc/ticket/18970>.
>
>Signed-off-by: Romain Vimont <rom at rom1v.com>
>---
> include/vlc_picture.h       | 13 +++++++++++++
> src/misc/image.c            |  5 +++++
>src/misc/picture.c          | 39
>+++++++++++++++++++++++++++++++++++++++
> src/video_output/snapshot.c |  7 ++++---
> 4 files changed, 61 insertions(+), 3 deletions(-)
>
>diff --git a/include/vlc_picture.h b/include/vlc_picture.h
>index e25374634f..151c8833b7 100644
>--- a/include/vlc_picture.h
>+++ b/include/vlc_picture.h
>@@ -197,6 +197,19 @@ VLC_API void plane_CopyPixels( plane_t *p_dst,
>const plane_t *p_src );
> VLC_API void picture_Copy( picture_t *p_dst, const picture_t *p_src );
> 
> /**
>+ * This function will create a new picture containing the requested
>region.
>+ *
>+ * \param p_src pointer to the source picture.
>+ * \param i_x_offset the region x offset.
>+ * \param i_y_offset the region x offset.
>+ * \param i_width the region with.
>+ * \param i_height the region height.
>+ */
>+VLC_API picture_t *picture_CloneRegion( const picture_t *p_src,
>+                                        int i_x_offset, int
>i_y_offset,
>+                                        int i_width, int i_height );
>+
>+/**
>  * This function will export a picture to an encoded bitstream.
>  *
>  * pp_image will contain the encoded bitstream in psz_format format.
>diff --git a/src/misc/image.c b/src/misc/image.c
>index aa5dd43a2d..7c3ad995c8 100644
>--- a/src/misc/image.c
>+++ b/src/misc/image.c
>@@ -778,6 +778,11 @@ static filter_t *CreateFilter( vlc_object_t
>*p_this, const es_format_t *p_fmt_in
>     es_format_Copy( &p_filter->fmt_in, p_fmt_in );
>     es_format_Copy( &p_filter->fmt_out, p_fmt_in );
>     video_format_Copy( &p_filter->fmt_out.video, p_fmt_out );
>+
>+    /* whatever the input offset, write at offset 0 in the target
>image */
>+    p_filter->fmt_out.video.i_x_offset = 0;
>+    p_filter->fmt_out.video.i_y_offset = 0;
>+
>     p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
>p_filter->p_module = module_need( p_filter, "video converter", NULL,
>false );
> 
>diff --git a/src/misc/picture.c b/src/misc/picture.c
>index 59d0aaa359..4549514dfe 100644
>--- a/src/misc/picture.c
>+++ b/src/misc/picture.c
>@@ -381,6 +381,45 @@ void picture_Copy( picture_t *p_dst, const
>picture_t *p_src )
>     picture_CopyProperties( p_dst, p_src );
> }
> 
>+picture_t *picture_CloneRegion( const picture_t *p_src,
>+                                int i_x_offset, int i_y_offset,
>+                                int i_width, int i_height )
>+{
>+    /* allocate image with target height to avoid waste,
>+     * but use the source width (with margins) to call memcpy() only
>once */
>+    picture_t *p_dst = picture_New( p_src->format.i_chroma,
>+                                    p_src->format.i_width,
>+                                    i_height,
>+                                    p_src->format.i_sar_num,
>+                                    p_src->format.i_sar_den );
>+    if( !p_dst )
>+        return NULL;
>+
>+    picture_CopyProperties( p_dst, p_src );
>+
>+    /* only the left and right margins are kept in the target picture
>*/
>+    p_dst->format.i_visible_width = i_width;
>+    p_dst->format.i_x_offset = i_x_offset;
>+    p_dst->format.i_y_offset = 0;
>+
>+    const vlc_chroma_description_t *p_dsc =
>+        vlc_fourcc_GetChromaDescription( p_src->format.i_chroma );
>+    if( !p_dsc )
>+        return NULL;
>+
>+    for( int i = 0; i < p_src->i_planes; ++i )
>+    {
>+        /* add (den - 1) to get the result rounded up */
>+        int i_lines = (i_height + p_dsc->p[i].h.den - 1)
>+                    * p_dsc->p[i].h.num / p_dsc->p[i].h.den;
>+        int i_lines_offset = i_y_offset * p_dsc->p[i].h.num /
>p_dsc->p[i].h.den;
>+        memcpy( p_dst->p[i].p_pixels,
>+                p_src->p[i].p_pixels + i_lines_offset *
>p_src->p[i].i_pitch,
>+                i_lines * p_src->p[i].i_pitch );
>+    }
>+
>+    return p_dst;
>+}
> 
>/*****************************************************************************
>  *
>diff --git a/src/video_output/snapshot.c b/src/video_output/snapshot.c
>index ceade008cc..3ad7cdf009 100644
>--- a/src/video_output/snapshot.c
>+++ b/src/video_output/snapshot.c
>@@ -119,12 +119,13 @@ void vout_snapshot_Set(vout_snapshot_t *snap,
> 
>     vlc_mutex_lock(&snap->lock);
>     while (snap->request_count > 0) {
>-        picture_t *dup = picture_NewFromFormat(fmt);
>+        picture_t *dup = picture_CloneRegion( picture,
>fmt->i_x_offset,
>+                                                      
>fmt->i_y_offset,
>+                                                      
>fmt->i_visible_width,
>+                                                      
>fmt->i_visible_height );
>         if (!dup)
>             break;
> 
>-        picture_Copy(dup, picture);
>-
>         dup->p_next = snap->picture;
>         snap->picture = dup;
>         snap->request_count--;
>-- 
>2.11.0
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

I don't know why picture copy does not copy the offsets (not to say that there is no reason). But clone implies shallow copy.
-- 
Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté.


More information about the vlc-devel mailing list