]> git.sesse.net Git - vlc/blobdiff - modules/video_filter/transform.c
Added partial support for > 8 bits YUV video in the deinterlace filter.
[vlc] / modules / video_filter / transform.c
index ab88b74e447b114cbac10bc5a1a7412814b6cd72..087110d97f23ab4c14d874d2b64039a5542bfd6c 100644 (file)
@@ -129,16 +129,16 @@ static void Plane16_##f(plane_t *restrict dst, const plane_t *restrict src) \
 { \
     const uint16_t *src_pixels = (const uint16_t *)src->p_pixels; \
     uint16_t *restrict dst_pixels = (uint16_t *)dst->p_pixels; \
-    unsigned src_pitch = src->i_pitch / 2; \
-    unsigned dst_pitch = dst->i_pitch / 2; \
+    unsigned src_width = src->i_pitch / 2; \
+    unsigned dst_width = dst->i_pitch / 2; \
     unsigned dst_visible_width = dst->i_visible_pitch / 2; \
  \
     for (int y = 0; y < dst->i_visible_lines; y++) { \
         for (unsigned x = 0; x < dst_visible_width; x++) { \
             int sx, sy; \
-            (f)(&sx, &sy, dst_visible_width, dst->i_visible_lines, x, y);\
-            dst_pixels[y * dst_pitch + x] = \
-                src_pixels[sy * src_pitch + sx]; \
+            (f)(&sx, &sy, dst_visible_width, dst->i_visible_lines, x, y); \
+            dst_pixels[y * dst_width + x] = \
+                src_pixels[sy * src_width + sx]; \
         } \
     } \
 } \
@@ -147,16 +147,50 @@ static void Plane32_##f(plane_t *restrict dst, const plane_t *restrict src) \
 { \
     const uint32_t *src_pixels = (const uint32_t *)src->p_pixels; \
     uint32_t *restrict dst_pixels = (uint32_t *)dst->p_pixels; \
-    unsigned src_pitch = src->i_pitch / 4; \
-    unsigned dst_pitch = dst->i_pitch / 4; \
+    unsigned src_width = src->i_pitch / 4; \
+    unsigned dst_width = dst->i_pitch / 4; \
     unsigned dst_visible_width = dst->i_visible_pitch / 4; \
  \
     for (int y = 0; y < dst->i_visible_lines; y++) { \
         for (unsigned x = 0; x < dst_visible_width; x++) { \
             int sx, sy; \
-            (f)(&sx, &sy, dst_visible_width, dst->i_visible_lines, x, y);\
-            dst_pixels[y * dst_pitch + x] = \
-                src_pixels[sy * src_pitch + sx]; \
+            (f)(&sx, &sy, dst_visible_width, dst->i_visible_lines, x, y); \
+            dst_pixels[y * dst_width + x] = \
+                src_pixels[sy * src_width + sx]; \
+        } \
+    } \
+} \
+ \
+static void YUYV_##f(plane_t *restrict dst, const plane_t *restrict src) \
+{ \
+    unsigned dst_visible_width = dst->i_visible_pitch / 2; \
+ \
+    for (int y = 0; y < dst->i_visible_lines; y += 2) { \
+        for (unsigned x = 0; x < dst_visible_width; x+= 2) { \
+            int sx0, sy0, sx1, sy1; \
+            (f)(&sx0, &sy0, dst_visible_width, dst->i_visible_lines, x, y); \
+            (f)(&sx1, &sy1, dst_visible_width, dst->i_visible_lines, \
+                x + 1, y + 1); \
+            dst->p_pixels[(y + 0) * dst->i_pitch + 2 * (x + 0)] = \
+                src->p_pixels[sy0 * src->i_pitch + 2 * sx0]; \
+            dst->p_pixels[(y + 0) * dst->i_pitch + 2 * (x + 1)] = \
+                src->p_pixels[sy1 * src->i_pitch + 2 * sx0]; \
+            dst->p_pixels[(y + 1) * dst->i_pitch + 2 * (x + 0)] = \
+                src->p_pixels[sy0 * src->i_pitch + 2 * sx1]; \
+            dst->p_pixels[(y + 1) * dst->i_pitch + 2 * (x + 1)] = \
+                src->p_pixels[sy1 * src->i_pitch + 2 * sx1]; \
+ \
+            int sx, sy, u, v; \
+            (f)(&sx, &sy, dst_visible_width / 2, dst->i_visible_lines / 2, \
+                x / 2, y / 2); \
+            u = (1 + src->p_pixels[2 * sy * src->i_pitch + 4 * sx + 1] + \
+                src->p_pixels[(2 * sy + 1) * src->i_pitch + 4 * sx + 1]) / 2; \
+            v = (1 + src->p_pixels[2 * sy * src->i_pitch + 4 * sx + 3] + \
+                src->p_pixels[(2 * sy + 1) * src->i_pitch + 4 * sx + 3]) / 2; \
+            dst->p_pixels[(y + 0) * dst->i_pitch + 2 * x + 1] = u; \
+            dst->p_pixels[(y + 0) * dst->i_pitch + 2 * x + 3] = v; \
+            dst->p_pixels[(y + 1) * dst->i_pitch + 2 * x + 1] = u; \
+            dst->p_pixels[(y + 1) * dst->i_pitch + 2 * x + 3] = v; \
         } \
     } \
 }
@@ -177,10 +211,11 @@ typedef struct {
     void      (*plane8) (plane_t *dst, const plane_t *src);
     void      (*plane16)(plane_t *dst, const plane_t *src);
     void      (*plane32)(plane_t *dst, const plane_t *src);
+    void      (*yuyv)(plane_t *dst, const plane_t *src);
 } transform_description_t;
 
 #define DESC(str, rotated, f, invf) \
-    { str, rotated, f, invf, Plane8_##f, Plane16_##f, Plane32_##f }
+    { str, rotated, f, invf, Plane8_##f, Plane16_##f, Plane32_##f, YUYV_##f }
 
 static const transform_description_t descriptions[] = {
     DESC("90",            true,  R90,           R270),
@@ -311,8 +346,10 @@ static int Open(vlc_object_t *object)
     /* Deal with weird packed formats */
     switch (src->i_chroma) {
         case VLC_CODEC_YUYV:
-        case VLC_CODEC_UYVY:
         case VLC_CODEC_YVYU:
+            sys->plane = dsc->is_rotated ? dsc->yuyv : dsc->plane32;
+            break;
+        case VLC_CODEC_UYVY:
         case VLC_CODEC_VYUY:
             if (dsc->is_rotated) {
                 msg_Err(filter, "Format rotation not possible (chroma %4.4s)",
@@ -353,329 +390,3 @@ static void Close(vlc_object_t *object)
 
     free(sys);
 }
-
-#if 0
-static void FilterI422( vout_thread_t *p_vout,
-                        const picture_t *p_pic, picture_t *p_outpic )
-{
-    int i_index;
-    switch( p_vout->p_sys->i_mode )
-    {
-        case TRANSFORM_MODE_180:
-        case TRANSFORM_MODE_HFLIP:
-        case TRANSFORM_MODE_VFLIP:
-            /* Fall back on the default implementation */
-            FilterPlanar( p_vout, p_pic, p_outpic );
-            return;
-
-        case TRANSFORM_MODE_90:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                int i_pitch = p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-                uint8_t *p_out_end = p_out +
-                    p_outpic->p[i_index].i_visible_lines *
-                    p_outpic->p[i_index].i_pitch;
-
-                if( i_index == 0 )
-                {
-                    for( ; p_out < p_out_end ; )
-                    {
-                        uint8_t *p_line_end;
-
-                        p_out_end -= p_outpic->p[i_index].i_pitch
-                                      - p_outpic->p[i_index].i_visible_pitch;
-                        p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
-                            i_pitch;
-
-                        for( ; p_in < p_line_end ; )
-                        {
-                            p_line_end -= i_pitch;
-                            *(--p_out_end) = *p_line_end;
-                        }
-
-                        p_in++;
-                    }
-                }
-                else /* i_index == 1 or 2 */
-                {
-                    for( ; p_out < p_out_end ; )
-                    {
-                        uint8_t *p_line_end, *p_out_end2;
-
-                        p_out_end -= p_outpic->p[i_index].i_pitch
-                                      - p_outpic->p[i_index].i_visible_pitch;
-                        p_out_end2 = p_out_end - p_outpic->p[i_index].i_pitch;
-                        p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
-                            i_pitch;
-
-                        for( ; p_in < p_line_end ; )
-                        {
-                            uint8_t p1, p2;
-
-                            p_line_end -= i_pitch;
-                            p1 = *p_line_end;
-                            p_line_end -= i_pitch;
-                            p2 = *p_line_end;
-
-                            /* Trick for (x+y)/2 without overflow, based on
-                             *   x + y == (x ^ y) + 2 * (x & y) */
-                            *(--p_out_end) = (p1 & p2) + ((p1 ^ p2) / 2);
-                            *(--p_out_end2) = (p1 & p2) + ((p1 ^ p2) / 2);
-                        }
-
-                        p_out_end = p_out_end2;
-                        p_in++;
-                    }
-                }
-            }
-            break;
-
-        case TRANSFORM_MODE_270:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                int i_pitch = p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-                uint8_t *p_out_end = p_out +
-                    p_outpic->p[i_index].i_visible_lines *
-                    p_outpic->p[i_index].i_pitch;
-
-                if( i_index == 0 )
-                {
-                    for( ; p_out < p_out_end ; )
-                    {
-                        uint8_t *p_in_end;
-
-                        p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
-                            i_pitch;
-
-                        for( ; p_in < p_in_end ; )
-                        {
-                            p_in_end -= i_pitch;
-                            *p_out++ = *p_in_end;
-                        }
-
-                        p_out += p_outpic->p[i_index].i_pitch
-                                  - p_outpic->p[i_index].i_visible_pitch;
-                        p_in++;
-                    }
-                }
-                else /* i_index == 1 or 2 */
-                {
-                    for( ; p_out < p_out_end ; )
-                    {
-                        uint8_t *p_in_end, *p_out2;
-
-                        p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
-                            i_pitch;
-                        p_out2 = p_out + p_outpic->p[i_index].i_pitch;
-
-                        for( ; p_in < p_in_end ; )
-                        {
-                            uint8_t p1, p2;
-
-                            p_in_end -= i_pitch;
-                            p1 = *p_in_end;
-                            p_in_end -= i_pitch;
-                            p2 = *p_in_end;
-
-                            /* Trick for (x+y)/2 without overflow, based on
-                             *   x + y == (x ^ y) + 2 * (x & y) */
-                            *p_out++ = (p1 & p2) + ((p1 ^ p2) / 2);
-                            *p_out2++ = (p1 & p2) + ((p1 ^ p2) / 2);
-                        }
-
-                        p_out2 += p_outpic->p[i_index].i_pitch
-                                   - p_outpic->p[i_index].i_visible_pitch;
-                        p_out = p_out2;
-                        p_in++;
-                    }
-                }
-            }
-            break;
-
-        default:
-            break;
-    }
-}
-
-static void FilterYUYV( vout_thread_t *p_vout,
-                        const picture_t *p_pic, picture_t *p_outpic )
-{
-    int i_index;
-    int i_y_offset, i_u_offset, i_v_offset;
-    if( GetPackedYuvOffsets( p_pic->format.i_chroma, &i_y_offset,
-                             &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
-        return;
-
-    switch( p_vout->p_sys->i_mode )
-    {
-        case TRANSFORM_MODE_VFLIP:
-            /* Fall back on the default implementation */
-            FilterPlanar( p_vout, p_pic, p_outpic );
-            return;
-
-        case TRANSFORM_MODE_90:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                int i_pitch = p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-                uint8_t *p_out_end = p_out +
-                    p_outpic->p[i_index].i_visible_lines *
-                    p_outpic->p[i_index].i_pitch;
-
-                int i_offset  = i_u_offset;
-                int i_offset2 = i_v_offset;
-                for( ; p_out < p_out_end ; )
-                {
-                    uint8_t *p_line_end;
-
-                    p_out_end -= p_outpic->p[i_index].i_pitch
-                                  - p_outpic->p[i_index].i_visible_pitch;
-                    p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
-                        i_pitch;
-
-                    for( ; p_in < p_line_end ; )
-                    {
-                        p_line_end -= i_pitch;
-                        p_out_end -= 4;
-                        p_out_end[i_y_offset+2] = p_line_end[i_y_offset];
-                        p_out_end[i_u_offset] = p_line_end[i_offset];
-                        p_line_end -= i_pitch;
-                        p_out_end[i_y_offset] = p_line_end[i_y_offset];
-                        p_out_end[i_v_offset] = p_line_end[i_offset2];
-                    }
-
-                    p_in += 2;
-
-                    {
-                        int a = i_offset;
-                        i_offset = i_offset2;
-                        i_offset2 = a;
-                    }
-                }
-            }
-            break;
-
-        case TRANSFORM_MODE_180:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
-                                            * p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-
-                for( ; p_in < p_in_end ; )
-                {
-                    uint8_t *p_line_start = p_in_end
-                                             - p_pic->p[i_index].i_pitch;
-                    p_in_end -= p_pic->p[i_index].i_pitch
-                                 - p_pic->p[i_index].i_visible_pitch;
-
-                    for( ; p_line_start < p_in_end ; )
-                    {
-                        p_in_end -= 4;
-                        p_out[i_y_offset] = p_in_end[i_y_offset+2];
-                        p_out[i_u_offset] = p_in_end[i_u_offset];
-                        p_out[i_y_offset+2] = p_in_end[i_y_offset];
-                        p_out[i_v_offset] = p_in_end[i_v_offset];
-                        p_out += 4;
-                    }
-
-                    p_out += p_outpic->p[i_index].i_pitch
-                              - p_outpic->p[i_index].i_visible_pitch;
-                }
-            }
-            break;
-
-        case TRANSFORM_MODE_270:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                int i_pitch = p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-                uint8_t *p_out_end = p_out +
-                    p_outpic->p[i_index].i_visible_lines *
-                    p_outpic->p[i_index].i_pitch;
-
-                int i_offset  = i_u_offset;
-                int i_offset2 = i_v_offset;
-                for( ; p_out < p_out_end ; )
-                {
-                    uint8_t *p_in_end;
-
-                    p_in_end = p_in
-                             + p_pic->p[i_index].i_visible_lines * i_pitch;
-
-                    for( ; p_in < p_in_end ; )
-                    {
-                        p_in_end -= i_pitch;
-                        p_out[i_y_offset] = p_in_end[i_y_offset];
-                        p_out[i_u_offset] = p_in_end[i_offset];
-                        p_in_end -= i_pitch;
-                        p_out[i_y_offset+2] = p_in_end[i_y_offset];
-                        p_out[i_v_offset] = p_in_end[i_offset2];
-                        p_out += 4;
-                    }
-
-                    p_out += p_outpic->p[i_index].i_pitch
-                           - p_outpic->p[i_index].i_visible_pitch;
-                    p_in += 2;
-
-                    {
-                        int a = i_offset;
-                        i_offset = i_offset2;
-                        i_offset2 = a;
-                    }
-                }
-            }
-            break;
-
-        case TRANSFORM_MODE_HFLIP:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
-                                         * p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-
-                for( ; p_in < p_in_end ; )
-                {
-                    uint8_t *p_line_end = p_in
-                                        + p_pic->p[i_index].i_visible_pitch;
-
-                    for( ; p_in < p_line_end ; )
-                    {
-                        p_line_end -= 4;
-                        p_out[i_y_offset] = p_line_end[i_y_offset+2];
-                        p_out[i_u_offset] = p_line_end[i_u_offset];
-                        p_out[i_y_offset+2] = p_line_end[i_y_offset];
-                        p_out[i_v_offset] = p_line_end[i_v_offset];
-                        p_out += 4;
-                    }
-
-                    p_in += p_pic->p[i_index].i_pitch;
-                    p_out += p_outpic->p[i_index].i_pitch
-                                - p_outpic->p[i_index].i_visible_pitch;
-                }
-            }
-            break;
-
-        default:
-            break;
-    }
-}
-#endif