vlc | branch: master | Steve Lhomme <[email protected]> | Thu Jul 28 14:46:35 2016 +0200| [031a152a712d89657741ca68dd3fcc465d091366] | committer: Jean-Baptiste Kempf
chroma: add a filter to convert VLC_CODEC_I420_10L to VLC_CODEC_P010 > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=031a152a712d89657741ca68dd3fcc465d091366 --- modules/MODULES_LIST | 1 + 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 ++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+) diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST index 658f9ca..4af3756 100644 --- a/modules/MODULES_LIST +++ b/modules/MODULES_LIST @@ -178,6 +178,7 @@ $Id$ * hqdn3d: High Quality denoising filter * http: HTTP Network access module * https: HTTP/TLS access module for HTTP 2.0 support + * i420_10_p010: I420 to NV12 in 10bits conversion, aka IA0L->P010 * i420_nv12: planar YUV to semi-planar YUV conversion functions * i420_rgb: planar YUV to packed RGB conversion functions * i420_rgb_mmx: MMX accelerated version of i420_rgb 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 <[email protected]> + * + * 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 () _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
