[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