[vlc-devel] [PATCH 1/2] Add i_aligned_width and i_aligned_height
Thomas Guillem
thomas at gllm.fr
Thu Dec 11 17:08:38 CET 2014
There are currently no ways for the scaler (swscale, vdpau_chroma) or direct
video output (XVideo) to differentiate the crop rectangle of the source video
and the source video rectangle itself. Consequently bilinear scaling bleeds the
non-video padding bytes into the video.
To solve this issue, add 2 new variables in video_format_t: i_aligned_width and
i_aligned_height. These 2 variables should be used by decoders that need an
aligned buffer (the case of avcodec when using direct rendering).
(refs #13062)
---
include/vlc_es.h | 6 ++++++
src/Makefile.am | 1 +
src/input/decoder.c | 2 ++
src/misc/es_format.c | 31 +++++++++++++++++++++++++------
src/misc/es_format.h | 29 +++++++++++++++++++++++++++++
src/misc/image.c | 4 +++-
src/misc/picture.c | 26 +++++++++++++++++---------
src/video_output/display.c | 5 ++++-
src/video_output/video_output.c | 3 +++
9 files changed, 90 insertions(+), 17 deletions(-)
create mode 100644 src/misc/es_format.h
diff --git a/include/vlc_es.h b/include/vlc_es.h
index dd87f6b..e44bf9e 100644
--- a/include/vlc_es.h
+++ b/include/vlc_es.h
@@ -200,6 +200,12 @@ struct video_format_t
unsigned int i_width; /**< picture width */
unsigned int i_height; /**< picture height */
+
+ /* i_aligned_* are set by decoders that need aligned pictures.
+ * if 0, i_width and i_height will be used for picture allocation */
+ unsigned int i_aligned_width; /**< picture aligned width */
+ unsigned int i_aligned_height; /**< picture aligned height */
+
unsigned int i_x_offset; /**< start offset of visible area */
unsigned int i_y_offset; /**< start offset of visible area */
unsigned int i_visible_width; /**< width of visible area */
diff --git a/src/Makefile.am b/src/Makefile.am
index e200669..54b09d8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -444,6 +444,7 @@ SOURCES_libvlc_common = \
misc/block.c \
misc/fourcc.c \
misc/es_format.c \
+ misc/es_format.h \
misc/picture.c \
misc/picture_fifo.c \
misc/picture_pool.c \
diff --git a/src/input/decoder.c b/src/input/decoder.c
index fd615d7..feb93e1 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -2014,6 +2014,8 @@ static int vout_update_format( decoder_t *p_dec )
if( p_owner->p_vout == NULL
|| p_dec->fmt_out.video.i_width != p_owner->fmt.video.i_width
|| p_dec->fmt_out.video.i_height != p_owner->fmt.video.i_height
+ || p_dec->fmt_out.video.i_aligned_width != p_owner->fmt.video.i_aligned_width
+ || p_dec->fmt_out.video.i_aligned_height != p_owner->fmt.video.i_aligned_height
|| p_dec->fmt_out.video.i_visible_width != p_owner->fmt.video.i_visible_width
|| p_dec->fmt_out.video.i_visible_height != p_owner->fmt.video.i_visible_height
|| p_dec->fmt_out.video.i_x_offset != p_owner->fmt.video.i_x_offset
diff --git a/src/misc/es_format.c b/src/misc/es_format.c
index 27622bc..8837f9d 100644
--- a/src/misc/es_format.c
+++ b/src/misc/es_format.c
@@ -128,15 +128,18 @@ void video_format_FixRgb( video_format_t *p_fmt )
p_fmt->i_bmask );
}
-void video_format_Setup( video_format_t *p_fmt, vlc_fourcc_t i_chroma,
- int i_width, int i_height,
- int i_visible_width, int i_visible_height,
- int i_sar_num, int i_sar_den )
+void video_format_SetupAligned( video_format_t *p_fmt, vlc_fourcc_t i_chroma,
+ int i_width, int i_height,
+ int i_aligned_width, int i_aligned_height,
+ int i_visible_width, int i_visible_height,
+ int i_sar_num, int i_sar_den )
{
p_fmt->i_chroma = vlc_fourcc_GetCodec( VIDEO_ES, i_chroma );
p_fmt->i_width = i_width;
+ p_fmt->i_aligned_width = i_aligned_width;
p_fmt->i_visible_width = i_visible_width;
p_fmt->i_height = i_height;
+ p_fmt->i_aligned_height = i_aligned_height;
p_fmt->i_visible_height = i_visible_height;
p_fmt->i_x_offset =
p_fmt->i_y_offset = 0;
@@ -219,6 +222,16 @@ void video_format_Setup( video_format_t *p_fmt, vlc_fourcc_t i_chroma,
}
}
+void video_format_Setup( video_format_t *p_fmt, vlc_fourcc_t i_chroma,
+ int i_width, int i_height,
+ int i_visible_width, int i_visible_height,
+ int i_sar_num, int i_sar_den )
+{
+ video_format_SetupAligned( p_fmt, i_chroma, i_width, i_height, 0, 0,
+ i_visible_width, i_visible_height,
+ i_sar_num, i_sar_den );
+}
+
void video_format_CopyCrop( video_format_t *p_dst, const video_format_t *p_src )
{
p_dst->i_x_offset = p_src->i_x_offset;
@@ -345,8 +358,10 @@ void video_format_TransformBy( video_format_t *fmt, video_transform_t transform
video_format_t scratch = *fmt;
fmt->i_width = scratch.i_height;
+ fmt->i_aligned_width = scratch.i_aligned_height;
fmt->i_visible_width = scratch.i_visible_height;
fmt->i_height = scratch.i_width;
+ fmt->i_aligned_height = scratch.i_aligned_width;
fmt->i_visible_height = scratch.i_visible_width;
fmt->i_x_offset = scratch.i_y_offset;
fmt->i_y_offset = scratch.i_x_offset;
@@ -382,6 +397,8 @@ bool video_format_IsSimilar( const video_format_t *p_fmt1, const video_format_t
return false;
if( v1.i_width != v2.i_width || v1.i_height != v2.i_height ||
+ v1.i_aligned_width != v2.i_aligned_width ||
+ v1.i_aligned_height != v2.i_aligned_height ||
v1.i_visible_width != v2.i_visible_width ||
v1.i_visible_height != v2.i_visible_height ||
v1.i_x_offset != v2.i_x_offset || v1.i_y_offset != v2.i_y_offset )
@@ -411,9 +428,11 @@ void video_format_Print( vlc_object_t *p_this,
const char *psz_text, const video_format_t *fmt )
{
msg_Dbg( p_this,
- "%s sz %ix%i, of (%i,%i), vsz %ix%i, 4cc %4.4s, sar %i:%i, msk r0x%x g0x%x b0x%x",
+ "%s sz %ix%i, align %ix%i, of (%i,%i), vsz %ix%i, 4cc %4.4s, sar %i:%i, msk r0x%x g0x%x b0x%x",
psz_text,
- fmt->i_width, fmt->i_height, fmt->i_x_offset, fmt->i_y_offset,
+ fmt->i_width, fmt->i_height,
+ fmt->i_aligned_width, fmt->i_aligned_height,
+ fmt->i_x_offset, fmt->i_y_offset,
fmt->i_visible_width, fmt->i_visible_height,
(char*)&fmt->i_chroma,
fmt->i_sar_num, fmt->i_sar_den,
diff --git a/src/misc/es_format.h b/src/misc/es_format.h
new file mode 100644
index 0000000..f8611ae
--- /dev/null
+++ b/src/misc/es_format.h
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * es_format.h: Private es_format_t helpers.
+ *****************************************************************************
+ * Copyright (C) 1999-2014 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/**
+ * It will fill up a video_format_t using the given arguments.
+ * Note that the video_format_t must already be initialized.
+ */
+void video_format_SetupAligned( video_format_t *, vlc_fourcc_t i_chroma,
+ int i_width, int i_height, int i_aligned_width, int i_aligned_height,
+ int i_visible_width, int i_visible_height,
+ int i_sar_num, int i_sar_den );
+
diff --git a/src/misc/image.c b/src/misc/image.c
index 906470a..73c235e 100644
--- a/src/misc/image.c
+++ b/src/misc/image.c
@@ -477,7 +477,9 @@ static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
if( p_fmt_in->i_chroma == p_fmt_out->i_chroma &&
p_fmt_in->i_width == p_fmt_out->i_width &&
- p_fmt_in->i_height == p_fmt_out->i_height )
+ p_fmt_in->i_height == p_fmt_out->i_height &&
+ p_fmt_in->i_aligned_width == p_fmt_out->i_aligned_width &&
+ p_fmt_in->i_aligned_height == p_fmt_out->i_aligned_height )
{
/* Duplicate image */
picture_Release( p_pif ); /* XXX: Better fix must be possible */
diff --git a/src/misc/picture.c b/src/misc/picture.c
index 6aa5b05..a380787 100644
--- a/src/misc/picture.c
+++ b/src/misc/picture.c
@@ -38,6 +38,8 @@
#include <vlc_image.h>
#include <vlc_block.h>
+#include "es_format.h"
+
/**
* Allocate a new picture in the heap.
*
@@ -153,9 +155,10 @@ int picture_Setup( picture_t *p_picture, const video_format_t *restrict fmt )
p_picture->i_nb_fields = 2;
- video_format_Setup( &p_picture->format, fmt->i_chroma, fmt->i_width, fmt->i_height,
- fmt->i_visible_width, fmt->i_visible_height,
- fmt->i_sar_num, fmt->i_sar_den );
+ video_format_SetupAligned( &p_picture->format, fmt->i_chroma, fmt->i_width, fmt->i_height,
+ fmt->i_aligned_width, fmt->i_aligned_height,
+ fmt->i_visible_width, fmt->i_visible_height,
+ fmt->i_sar_num, fmt->i_sar_den );
const vlc_chroma_description_t *p_dsc =
vlc_fourcc_GetChromaDescription( p_picture->format.i_chroma );
@@ -180,8 +183,12 @@ int picture_Setup( picture_t *p_picture, const video_format_t *restrict fmt )
}
i_modulo_h = LCM( i_modulo_h, 32 );
- const int i_width_aligned = ( fmt->i_width + i_modulo_w - 1 ) / i_modulo_w * i_modulo_w;
- const int i_height_aligned = ( fmt->i_height + i_modulo_h - 1 ) / i_modulo_h * i_modulo_h;
+ int i_width_aligned = fmt->i_aligned_width == 0 ? fmt->i_width
+ : fmt->i_aligned_width;
+ i_width_aligned = ( i_width_aligned + i_modulo_w - 1 ) / i_modulo_w * i_modulo_w;
+ int i_height_aligned = fmt->i_aligned_height == 0 ? fmt->i_height
+ : fmt->i_aligned_height;
+ i_height_aligned = ( i_height_aligned + i_modulo_h - 1 ) / i_modulo_h * i_modulo_h;
const int i_height_extra = 2 * i_ratio_h; /* This one is a hack for some ASM functions */
for( unsigned i = 0; i < p_dsc->plane_count; i++ )
{
@@ -208,10 +215,11 @@ picture_t *picture_NewFromResource( const video_format_t *p_fmt, const picture_r
video_format_t fmt = *p_fmt;
/* It is needed to be sure all information are filled */
- video_format_Setup( &fmt, p_fmt->i_chroma,
- p_fmt->i_width, p_fmt->i_height,
- p_fmt->i_visible_width, p_fmt->i_visible_height,
- p_fmt->i_sar_num, p_fmt->i_sar_den );
+ video_format_SetupAligned( &fmt, p_fmt->i_chroma,
+ p_fmt->i_width, p_fmt->i_height,
+ p_fmt->i_aligned_width, p_fmt->i_aligned_height,
+ p_fmt->i_visible_width, p_fmt->i_visible_height,
+ p_fmt->i_sar_num, p_fmt->i_sar_den );
if( p_fmt->i_x_offset < p_fmt->i_width &&
p_fmt->i_y_offset < p_fmt->i_height &&
p_fmt->i_visible_width > 0 && p_fmt->i_x_offset + p_fmt->i_visible_width <= p_fmt->i_width &&
diff --git a/src/video_output/display.c b/src/video_output/display.c
index 4c1b133..374c000 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -1238,6 +1238,9 @@ static vout_display_t *DisplayNew(vout_thread_t *vout,
osys->event.fifo = NULL;
osys->source = *source;
+ /* display should only use original video size */
+ osys->source.i_aligned_width =
+ osys->source.i_aligned_height = 0;
osys->crop.left = 0;
osys->crop.top = 0;
osys->crop.right = 0;
@@ -1262,7 +1265,7 @@ static vout_display_t *DisplayNew(vout_thread_t *vout,
vout_display_t *p_display = vout_display_New(VLC_OBJECT(vout),
module, !is_wrapper,
- source, cfg, &owner);
+ &osys->source, cfg, &owner);
if (!p_display) {
free(osys);
return NULL;
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 2a6fe2a..c179692 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -716,6 +716,9 @@ static void ThreadChangeFilters(vout_thread_t *vout,
es_format_t fmt_target;
es_format_InitFromVideo(&fmt_target, source ? source : &vout->p->filter.format);
+ /* filters should use original video size */
+ fmt_target.video.i_aligned_width =
+ fmt_target.video.i_aligned_height = 0;
es_format_t fmt_current = fmt_target;
--
2.1.3
More information about the vlc-devel
mailing list