[vlc-devel] [PATCH] chroma: add a filter to convert VLC_CODEC_I420_10L to VLC_CODEC_P010

Steve Lhomme robux4 at videolabs.io
Thu Jul 28 14:46:35 CEST 2016


---
 modules/video_chroma/Makefile.am    |   6 ++
 modules/video_chroma/copy.c         |  40 +++++++++++
 modules/video_chroma/copy.h         |   3 +
 modules/video_chroma/i420_10_p010.c | 132 ++++++++++++++++++++++++++++++++++++
 4 files changed, 181 insertions(+)
 create mode 100644 modules/video_chroma/i420_10_p010.c

diff --git a/modules/video_chroma/Makefile.am b/modules/video_chroma/Makefile.am
index 2c5265e..0545c9b 100644
--- a/modules/video_chroma/Makefile.am
+++ b/modules/video_chroma/Makefile.am
@@ -26,6 +26,11 @@ libi420_nv12_plugin_la_SOURCES = video_chroma/i420_nv12.c \
 libi420_nv12_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
 	-DMODULE_NAME_IS_i420_nv12
 
+libi420_10_p010_plugin_la_SOURCES = video_chroma/i420_10_p010.c \
+	video_chroma/copy.c video_chroma/copy.h
+libi420_10_p010_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
+	-DMODULE_NAME_IS_i420_10_p010
+
 libi422_i420_plugin_la_SOURCES = video_chroma/i422_i420.c
 
 libi422_yuy2_plugin_la_SOURCES = video_chroma/i422_yuy2.c video_chroma/i422_yuy2.h
@@ -44,6 +49,7 @@ chroma_LTLIBRARIES = \
 	libi420_rgb_plugin.la \
 	libi420_yuy2_plugin.la \
 	libi420_nv12_plugin.la \
+	libi420_10_p010_plugin.la \
 	libi422_i420_plugin.la \
 	libi422_yuy2_plugin.la \
 	libgrey_yuv_plugin.la \
diff --git a/modules/video_chroma/copy.c b/modules/video_chroma/copy.c
index c053282..a0b1de5 100644
--- a/modules/video_chroma/copy.c
+++ b/modules/video_chroma/copy.c
@@ -521,6 +521,46 @@ void CopyFromI420ToNv12(picture_t *dst, uint8_t *src[3], size_t src_pitch[3],
     }
 }
 
+void CopyFromI420_10ToP010(picture_t *dst, uint8_t *src[3], size_t src_pitch[3],
+                        unsigned height, copy_cache_t *cache)
+{
+    (void) cache;
+
+    const int i_extra_pitch_dst_y = (dst->p[0].i_pitch  - src_pitch[0]) / 2;
+    const int i_extra_pitch_src_y = (src_pitch[Y_PLANE] - src_pitch[0]) / 2;
+    uint16_t *dstY = dst->p[0].p_pixels;
+    uint16_t *srcY = src[Y_PLANE];
+    for (unsigned y = 0; y < height; y++) {
+        for (unsigned x = 0; x < (src_pitch[0] / 2); x++) {
+            *dstY++ = *srcY++ << 6;
+        }
+        dstY += i_extra_pitch_dst_y;
+        srcY += i_extra_pitch_src_y;
+    }
+
+    const unsigned copy_lines = height / 2;
+    const unsigned copy_pitch = src_pitch[1] / 2;
+
+    const int i_extra_pitch_uv = dst->p[1].i_pitch / 2 - 2 * copy_pitch;
+    const int i_extra_pitch_u  = src_pitch[U_PLANE] / 2 - copy_pitch;
+    const int i_extra_pitch_v  = src_pitch[V_PLANE] / 2 - copy_pitch;
+
+    uint16_t *dstUV = dst->p[1].p_pixels;
+    uint16_t *srcU  = src[U_PLANE];
+    uint16_t *srcV  = src[V_PLANE];
+    for ( unsigned int line = 0; line < copy_lines; line++ )
+    {
+        for ( unsigned int col = 0; col < copy_pitch; col++ )
+        {
+            *dstUV++ = *srcU++ << 6;
+            *dstUV++ = *srcV++ << 6;
+        }
+        dstUV += i_extra_pitch_uv;
+        srcU  += i_extra_pitch_u;
+        srcV  += i_extra_pitch_v;
+    }
+}
+
 
 void CopyFromYv12(picture_t *dst, uint8_t *src[3], size_t src_pitch[3],
                   unsigned height, copy_cache_t *cache)
diff --git a/modules/video_chroma/copy.h b/modules/video_chroma/copy.h
index 8776f95..f5a56cc 100644
--- a/modules/video_chroma/copy.h
+++ b/modules/video_chroma/copy.h
@@ -50,4 +50,7 @@ void CopyFromNv12ToI420(picture_t *dst, uint8_t *src[2], size_t src_pitch[2],
 void CopyFromI420ToNv12(picture_t *dst, uint8_t *src[3], size_t src_pitch[3],
                         unsigned height, copy_cache_t *cache);
 
+void CopyFromI420_10ToP010(picture_t *dst, uint8_t *src[3], size_t src_pitch[3],
+                        unsigned height, copy_cache_t *cache);
+
 #endif
diff --git a/modules/video_chroma/i420_10_p010.c b/modules/video_chroma/i420_10_p010.c
new file mode 100644
index 0000000..dd65202
--- /dev/null
+++ b/modules/video_chroma/i420_10_p010.c
@@ -0,0 +1,132 @@
+/*****************************************************************************
+ * i420_10_P010.c : Planar YUV 4:2:0 to SemiPlanar P010 4:2:0
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * Authors: Steve Lhomme <robux4 at videolabs.io>
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_filter.h>
+#include "copy.h"
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static void I420_10_P010( filter_t *, picture_t *, picture_t * );
+static picture_t *I420_10_P010_Filter( filter_t *, picture_t * );
+
+struct filter_sys_t
+{
+    copy_cache_t cache;
+};
+
+/*****************************************************************************
+ * Create: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    if ( p_filter->fmt_out.video.i_chroma != VLC_CODEC_P010 )
+        return -1;
+
+    /* video must be even, because 4:2:0 is subsampled by 2 in both ways */
+    if( p_filter->fmt_in.video.i_width  & 1
+     || p_filter->fmt_in.video.i_height & 1 )
+    {
+        return -1;
+    }
+
+    /* resizing not supported */
+    if( p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width !=
+            p_filter->fmt_out.video.i_x_offset + p_filter->fmt_out.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_y_offset + p_filter->fmt_out.video.i_visible_height
+       || p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
+        return -1;
+
+    if ( p_filter->fmt_in.video.i_chroma != VLC_CODEC_I420_10L)
+        return -1;
+
+    filter_sys_t *p_sys = calloc(1, sizeof(filter_sys_t));
+    if (!p_sys)
+         return VLC_ENOMEM;
+
+    p_filter->pf_video_filter = I420_10_P010_Filter;
+    CopyInitCache( &p_sys->cache, p_filter->fmt_in.video.i_x_offset +
+                                  p_filter->fmt_in.video.i_visible_width );
+    p_filter->p_sys = p_sys;
+
+    return 0;
+}
+
+static void Delete(vlc_object_t *p_this)
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys = p_filter->p_sys;
+    CopyCleanCache( &p_sys->cache );
+}
+
+/* Following functions are local */
+VIDEO_FILTER_WRAPPER( I420_10_P010 )
+
+/*****************************************************************************
+ * planar I420 4:2:0 10-bit Y:U:V to semiplanar P010 10/16-bit 4:2:0 Y:UV
+ *****************************************************************************/
+static void I420_10_P010( filter_t *p_filter, picture_t *p_src,
+                                           picture_t *p_dst )
+{
+    p_dst->format.i_x_offset = p_src->format.i_x_offset;
+    p_dst->format.i_y_offset = p_src->format.i_y_offset;
+
+    size_t pitch[3] = {
+        p_src->p[Y_PLANE].i_pitch,
+        p_src->p[U_PLANE].i_pitch,
+        p_src->p[V_PLANE].i_pitch,
+    };
+
+    uint8_t *plane[3] = {
+        (uint8_t*)p_src->p[Y_PLANE].p_pixels,
+        (uint8_t*)p_src->p[U_PLANE].p_pixels,
+        (uint8_t*)p_src->p[V_PLANE].p_pixels,
+    };
+
+    CopyFromI420_10ToP010( p_dst, plane, pitch,
+                        p_src->format.i_y_offset + p_src->format.i_visible_height,
+                        &p_filter->p_sys->cache );
+}
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin ()
+    set_description( N_("YUV 10-bits planar to semiplanar 10-bits conversions") )
+    set_capability( "video filter2", 160 )
+    set_callbacks( Create, Delete )
+vlc_module_end ()
-- 
2.8.2



More information about the vlc-devel mailing list