[vlc-devel] [PATCH] vout: snapshot: fix snapshots cropping
Romain Vimont
rom at rom1v.com
Fri Nov 3 10:32:05 CET 2017
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
More information about the vlc-devel
mailing list