[vlc-devel] [PATCH 1/2] i420_rgb: only handle visible pixels

Steve Lhomme robux4 at videolabs.io
Tue Mar 8 16:45:20 CET 2016


fixes a crash similar to #16686 when an RGB output is used instead of YUYV
---
 modules/video_chroma/i420_rgb.h       |  40 +++----
 modules/video_chroma/i420_rgb16.c     |  52 ++++----
 modules/video_chroma/i420_rgb16_x86.c | 216 ++++++++++++++++++----------------
 modules/video_chroma/i420_rgb8.c      |  22 ++--
 4 files changed, 174 insertions(+), 156 deletions(-)

diff --git a/modules/video_chroma/i420_rgb.h b/modules/video_chroma/i420_rgb.h
index 3bef970..f9dfaad 100644
--- a/modules/video_chroma/i420_rgb.h
+++ b/modules/video_chroma/i420_rgb.h
@@ -173,7 +173,7 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
          * Rewind buffer and offset, then copy and scale line */              \
         p_buffer = p_buffer_start;                                            \
         p_offset = p_offset_start;                                            \
-        for( i_x = p_filter->fmt_out.video.i_width / 16; i_x--; )             \
+        for( i_x = (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width) / 16; i_x--; )             \
         {                                                                     \
             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
@@ -192,7 +192,7 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
         }                                                                     \
-        for( i_x = p_filter->fmt_out.video.i_width & 15; i_x--; )             \
+        for( i_x = (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width) & 15; i_x--; )             \
         {                                                                     \
             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
         }                                                                     \
@@ -215,7 +215,7 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
     {                                                                         \
         /* Horizontal scaling - we can't use a buffer due to dithering */     \
         p_offset = p_offset_start;                                            \
-        for( i_x = p_filter->fmt_out.video.i_width / 16; i_x--; )             \
+        for( i_x = (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width) / 16; i_x--; )             \
         {                                                                     \
             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                \
@@ -225,7 +225,7 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
     }                                                                         \
     else                                                                      \
     {                                                                         \
-        for( i_x = p_filter->fmt_in.video.i_width / 16; i_x--;  )             \
+        for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--;  )             \
         {                                                                     \
             CONVERT_4YUV_PIXEL( CHROMA )                                      \
             CONVERT_4YUV_PIXEL( CHROMA )                                      \
@@ -261,10 +261,10 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
     switch( i_vscale )                                                        \
     {                                                                         \
     case -1:                             /* vertical scaling factor is < 1 */ \
-        while( (i_scale_count -= p_filter->fmt_out.video.i_height) > 0 )      \
+        while( (i_scale_count -= (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height)) > 0 )      \
         {                                                                     \
             /* Height reduction: skip next source line */                     \
-            p_y += p_filter->fmt_in.video.i_width;                            \
+            p_y += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                            \
             i_y++;                                                            \
             if( (CHROMA == 420) || (CHROMA == 422) )                          \
             {                                                                 \
@@ -276,20 +276,20 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
             }                                                                 \
             else if( CHROMA == 444 )                                          \
             {                                                                 \
-                p_u += p_filter->fmt_in.video.i_width;                        \
-                p_v += p_filter->fmt_in.video.i_width;                        \
+                p_u += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                        \
+                p_v += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                        \
             }                                                                 \
         }                                                                     \
-        i_scale_count += p_filter->fmt_in.video.i_height;                     \
+        i_scale_count += (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);                     \
         break;                                                                \
     case 1:                              /* vertical scaling factor is > 1 */ \
-        while( (i_scale_count -= p_filter->fmt_in.video.i_height) > 0 )       \
+        while( (i_scale_count -= (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height)) > 0 )       \
         {                                                                     \
             /* Height increment: copy previous picture line */                \
-            memcpy( p_pic, p_pic_start, p_filter->fmt_out.video.i_width * BPP ); \
+            memcpy( p_pic, p_pic_start, (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width) * BPP ); \
             p_pic = (void*)((uint8_t*)p_pic + p_dest->p->i_pitch );           \
         }                                                                     \
-        i_scale_count += p_filter->fmt_out.video.i_height;                    \
+        i_scale_count += (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height);                    \
         break;                                                                \
     }                                                                         \
 
@@ -316,10 +316,10 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
     switch( i_vscale )                                                        \
     {                                                                         \
     case -1:                             /* vertical scaling factor is < 1 */ \
-        while( (i_scale_count -= p_filter->fmt_out.video.i_height) > 0 )      \
+        while( (i_scale_count -= (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height)) > 0 )      \
         {                                                                     \
             /* Height reduction: skip next source line */                     \
-            p_y += p_filter->fmt_in.video.i_width;                            \
+            p_y += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                            \
             i_y++;                                                            \
             if( (CHROMA == 420) || (CHROMA == 422) )                          \
             {                                                                 \
@@ -331,21 +331,21 @@ void I420_A8B8G8R8     ( filter_t *, picture_t *, picture_t * );
             }                                                                 \
             else if( CHROMA == 444 )                                          \
             {                                                                 \
-                p_u += p_filter->fmt_in.video.i_width;                        \
-                p_v += p_filter->fmt_in.video.i_width;                        \
+                p_u += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                        \
+                p_v += (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                        \
             }                                                                 \
         }                                                                     \
-        i_scale_count += p_filter->fmt_in.video.i_height;                     \
+        i_scale_count += (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);                     \
         break;                                                                \
     case 1:                              /* vertical scaling factor is > 1 */ \
-        while( (i_scale_count -= p_filter->fmt_in.video.i_height) > 0 )       \
+        while( (i_scale_count -= (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height)) > 0 )       \
         {                                                                     \
-            p_y -= p_filter->fmt_in.video.i_width;                            \
+            p_y -= (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width);                            \
             p_u -= i_chroma_width;                                            \
             p_v -= i_chroma_width;                                            \
             SCALE_WIDTH_DITHER( CHROMA );                                     \
         }                                                                     \
-        i_scale_count += p_filter->fmt_out.video.i_height;                    \
+        i_scale_count += (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height);                    \
         break;                                                                \
     }                                                                         \
 
diff --git a/modules/video_chroma/i420_rgb16.c b/modules/video_chroma/i420_rgb16.c
index 32df817..25e7206 100644
--- a/modules/video_chroma/i420_rgb16.c
+++ b/modules/video_chroma/i420_rgb16.c
@@ -119,7 +119,7 @@ void I420_RGB16( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
     int         i_uval, i_vval;                           /* U and V samples */
     int         i_red, i_green, i_blue;          /* U and V modified samples */
@@ -135,34 +135,36 @@ void I420_RGB16( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
             CONVERT_YUV_PIXEL(2);  CONVERT_Y_PIXEL(2);
@@ -222,7 +224,7 @@ void I420_RGB32( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
     int         i_uval, i_vval;                           /* U and V samples */
     int         i_red, i_green, i_blue;          /* U and V modified samples */
@@ -238,34 +240,36 @@ void I420_RGB32( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
             CONVERT_YUV_PIXEL(4);  CONVERT_Y_PIXEL(4);
diff --git a/modules/video_chroma/i420_rgb16_x86.c b/modules/video_chroma/i420_rgb16_x86.c
index 087f90f..0b111c3 100644
--- a/modules/video_chroma/i420_rgb16_x86.c
+++ b/modules/video_chroma/i420_rgb16_x86.c
@@ -115,7 +115,7 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
 
     /* Conversion buffer pointer */
@@ -127,19 +127,21 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
 
@@ -147,12 +149,12 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -166,11 +168,11 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)/16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_16_ALIGNED
@@ -217,12 +219,12 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)/16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_16_UNALIGNED
@@ -272,14 +274,14 @@ void I420_R5G5B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
 
 #else /* SSE2 */
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_16
@@ -345,7 +347,7 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint16_t *  p_pic_start;       /* beginning of the current line for copy */
 
     /* Conversion buffer pointer */
@@ -357,19 +359,21 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
 
@@ -377,12 +381,12 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -396,11 +400,11 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)/16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_16_ALIGNED
@@ -447,12 +451,12 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width/16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)/16; i_x--; )
             {
                 SSE2_CALL(
                     SSE2_INIT_16_UNALIGNED
@@ -502,14 +506,14 @@ void I420_R5G6B5( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
 
 #else /* SSE2 */
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_16
@@ -576,7 +580,7 @@ void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
     /* Conversion buffer pointer */
     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
@@ -587,31 +591,33 @@ void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width,
+               p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height,
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -625,11 +631,11 @@ void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_ALIGNED
@@ -676,12 +682,12 @@ void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_UNALIGNED
@@ -731,14 +737,14 @@ void I420_A8R8G8B8( filter_t *p_filter, picture_t *p_src,
 
 #else
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_32
@@ -804,7 +810,7 @@ void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
     /* Conversion buffer pointer */
     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
@@ -815,31 +821,33 @@ void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -853,11 +861,11 @@ void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_ALIGNED
@@ -904,12 +912,12 @@ void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_UNALIGNED
@@ -959,14 +967,14 @@ void I420_R8G8B8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
 
 #else
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_32
@@ -1032,7 +1040,7 @@ void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
     /* Conversion buffer pointer */
     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
@@ -1043,31 +1051,33 @@ void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -1081,11 +1091,11 @@ void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_ALIGNED
@@ -1132,12 +1142,12 @@ void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_UNALIGNED
@@ -1184,14 +1194,14 @@ void I420_B8G8R8A8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
 
 #else
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_32
@@ -1257,7 +1267,7 @@ void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int         i_right_margin;
     int         i_rewind;
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_chroma_width = p_filter->fmt_in.video.i_width / 2; /* chroma width */
+    int         i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2; /* chroma width */
     uint32_t *  p_pic_start;       /* beginning of the current line for copy */
     /* Conversion buffer pointer */
     uint32_t *  p_buffer_start = (uint32_t*)p_filter->p_sys->p_buffer;
@@ -1268,31 +1278,33 @@ void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
 
     /* Rule: when a picture of size (x1,y1) with aspect ratio r1 is rendered
      * on a picture of size (x2,y2) with aspect ratio r2, if x1 grows to x1'
      * then y1 grows to y1' = x1' * y2/x2 * r2/r1 */
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     /*
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
 
 #ifdef SSE2
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 15;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 15;
 
     /*
     ** SSE2 128 bits fetch/store instructions are faster
@@ -1306,11 +1318,11 @@ void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
                     ((intptr_t)p_buffer))) )
     {
         /* use faster SSE2 aligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_ALIGNED
@@ -1357,12 +1369,12 @@ void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     else
     {
         /* use slower SSE2 unaligned fetch and store */
-        for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+        for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
         {
             p_pic_start = p_pic;
             p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-            for ( i_x = p_filter->fmt_in.video.i_width / 16; i_x--; )
+            for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16; i_x--; )
             {
                 SSE2_CALL (
                     SSE2_INIT_32_UNALIGNED
@@ -1409,14 +1421,14 @@ void I420_A8B8G8R8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
 
 #else
 
-    i_rewind = (-p_filter->fmt_in.video.i_width) & 7;
+    i_rewind = (-(p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width)) & 7;
 
-    for( i_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+    for( i_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         p_pic_start = p_pic;
         p_buffer = b_hscale ? p_buffer_start : p_pic;
 
-        for ( i_x = p_filter->fmt_in.video.i_width / 8; i_x--; )
+        for ( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8; i_x--; )
         {
             MMX_CALL (
                 MMX_INIT_32
diff --git a/modules/video_chroma/i420_rgb8.c b/modules/video_chroma/i420_rgb8.c
index aadc47f..ddd402c 100644
--- a/modules/video_chroma/i420_rgb8.c
+++ b/modules/video_chroma/i420_rgb8.c
@@ -54,7 +54,7 @@ void I420_RGB8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     unsigned int i_real_y;                                          /* y % 4 */
     int          i_right_margin;
     int          i_scale_count;                      /* scale modulo counter */
-    unsigned int i_chroma_width = p_filter->fmt_in.video.i_width / 2;/* chroma width */
+    unsigned int i_chroma_width = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 2;/* chroma width */
 
     /* Lookup table */
     uint8_t *        p_lookup = p_filter->p_sys->p_base;
@@ -64,9 +64,11 @@ void I420_RGB8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     int *       p_offset;
 
     const int i_source_margin = p_src->p[0].i_pitch
-                                 - p_src->p[0].i_visible_pitch;
+                                 - p_src->p[0].i_visible_pitch
+                                 - p_filter->fmt_in.video.i_x_offset;
     const int i_source_margin_c = p_src->p[1].i_pitch
-                                 - p_src->p[1].i_visible_pitch;
+                                 - p_src->p[1].i_visible_pitch
+                                 - ( p_filter->fmt_in.video.i_x_offset / 2 );
 
     /* The dithering matrices */
     static const int dither10[4] = {  0x0,  0x8,  0x2,  0xa };
@@ -79,10 +81,10 @@ void I420_RGB8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
     static const int dither22[4] = {  0x6, 0x16,  0x2, 0x12 };
     static const int dither23[4] = { 0x1e,  0xe, 0x1a,  0xa };
 
-    SetOffset( p_filter->fmt_in.video.i_width,
-               p_filter->fmt_in.video.i_height,
-               p_filter->fmt_out.video.i_width,
-               p_filter->fmt_out.video.i_height,
+    SetOffset( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width),
+               (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height),
+               (p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.video.i_visible_width),
+               (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height),
                &b_hscale, &i_vscale, p_offset_start );
 
     i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
@@ -91,9 +93,9 @@ void I420_RGB8( filter_t *p_filter, picture_t *p_src, picture_t *p_dest )
      * Perform conversion
      */
     i_scale_count = ( i_vscale == 1 ) ?
-                    p_filter->fmt_out.video.i_height :
-                    p_filter->fmt_in.video.i_height;
-    for( i_y = 0, i_real_y = 0; i_y < p_filter->fmt_in.video.i_height; i_y++ )
+                    (p_filter->fmt_out.video.i_y_offset + p_filter->fmt_out.video.i_visible_height) :
+                    (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height);
+    for( i_y = 0, i_real_y = 0; i_y < (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height); i_y++ )
     {
         /* Do horizontal and vertical scaling */
         SCALE_WIDTH_DITHER( 420 );
-- 
2.7.2.windows.1



More information about the vlc-devel mailing list