📄 blend.c
字号:
/***************************************************************************** * blend.c: alpha blend 2 pictures together ***************************************************************************** * Copyright (C) 2003-2008 the VideoLAN team * $Id: c4a99f9abf11ca13612c395762fd4ebb528dac88 $ * * Authors: Gildas Bazin <gbazin@videolan.org> * Antoine Cellerier <dionoea @t videolan dot org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU 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 <assert.h>#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_vout.h>#include "vlc_filter.h"/***************************************************************************** * Module descriptor *****************************************************************************/static int OpenFilter ( vlc_object_t * );static void CloseFilter( vlc_object_t * );vlc_module_begin(); set_description( N_("Video pictures blending") ); set_capability( "video blending", 100 ); set_callbacks( OpenFilter, CloseFilter );vlc_module_end();/***************************************************************************** * filter_sys_t : filter descriptor *****************************************************************************/struct filter_sys_t{ int i_dummy;};#define FCC_YUVA VLC_FOURCC('Y','U','V','A')#define FCC_YUVP VLC_FOURCC('Y','U','V','P')#define FCC_RGBA VLC_FOURCC('R','G','B','A')#define FCC_I420 VLC_FOURCC('I','4','2','0')#define FCC_YV12 VLC_FOURCC('Y','V','1','2')#define FCC_YUY2 VLC_FOURCC('Y','U','Y','2')#define FCC_UYVY VLC_FOURCC('U','Y','V','Y')#define FCC_YVYU VLC_FOURCC('Y','V','Y','U')#define FCC_RV15 VLC_FOURCC('R','V','1','5')#define FCC_RV16 VLC_FOURCC('R','V','1','6')#define FCC_RV24 VLC_FOURCC('R','V','2','4')#define FCC_RV32 VLC_FOURCC('R','V','3','2')/**************************************************************************** * Local prototypes ****************************************************************************/static void Blend( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int );/* YUVA */static void BlendYUVAI420( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendYUVARV16( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendYUVARV24( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendYUVAYUVPacked( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );/* I420, YV12 */static void BlendI420I420( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendI420I420_no_alpha( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int );static void BlendI420R16( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendI420R24( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendI420YUVPacked( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );/* YUVP */static void BlendPalI420( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendPalYUVPacked( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendPalRV( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );/* RGBA */static void BlendRGBAI420( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendRGBAYUVPacked( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendRGBAR16( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );static void BlendRGBAR24( filter_t *, picture_t *, picture_t *, picture_t *, int, int, int, int, int );/***************************************************************************** * OpenFilter: probe the filter and return score *****************************************************************************/static int OpenFilter( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys; /* Check if we can handle that format. * We could try to use a chroma filter if we can't. */ int in_chroma = p_filter->fmt_in.video.i_chroma; int out_chroma = p_filter->fmt_out.video.i_chroma; if( ( in_chroma != FCC_YUVA && in_chroma != FCC_I420 && in_chroma != FCC_YV12 && in_chroma != FCC_YUVP && in_chroma != FCC_RGBA ) || ( out_chroma != FCC_I420 && out_chroma != FCC_YUY2 && out_chroma != FCC_YV12 && out_chroma != FCC_UYVY && out_chroma != FCC_YVYU && out_chroma != FCC_RV15 && out_chroma != FCC_YVYU && out_chroma != FCC_RV16 && out_chroma != FCC_RV24 && out_chroma != FCC_RV32 ) ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t)); if( !p_sys ) return VLC_ENOMEM; /* Misc init */ p_filter->pf_video_blend = Blend; msg_Dbg( p_filter, "chroma: %4.4s -> %4.4s", (char *)&p_filter->fmt_in.video.i_chroma, (char *)&p_filter->fmt_out.video.i_chroma ); return VLC_SUCCESS;}/***************************************************************************** * CloseFilter: clean up the filter *****************************************************************************/static void CloseFilter( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys = p_filter->p_sys; free( p_sys );}/**************************************************************************** * Blend: the whole thing **************************************************************************** * This function is called just after the thread is launched. ****************************************************************************/typedef void (*BlendFunction)( filter_t *, picture_t *, picture_t *, picture_t *, int , int , int , int , int );#define FCC_PLANAR_420 { FCC_I420, FCC_YV12, 0 }#define FCC_PACKED_422 { FCC_YUY2, FCC_UYVY, FCC_YVYU, 0 }#define FCC_RGB_16 { FCC_RV15, FCC_RV16, 0 }#define FCC_RGB_24 { FCC_RV24, FCC_RV32, 0 }#define BLEND_CFG( fccSrc, fctPlanar, fctPacked, fctRgb16, fctRgb24 ) \ { .src = fccSrc, .p_dst = FCC_PLANAR_420, .pf_blend = fctPlanar }, \ { .src = fccSrc, .p_dst = FCC_PACKED_422, .pf_blend = fctPacked }, \ { .src = fccSrc, .p_dst = FCC_RGB_16, .pf_blend = fctRgb16 }, \ { .src = fccSrc, .p_dst = FCC_RGB_24, .pf_blend = fctRgb24 }static const struct{ vlc_fourcc_t src; vlc_fourcc_t p_dst[16]; BlendFunction pf_blend;} p_blend_cfg[] = { BLEND_CFG( FCC_YUVA, BlendYUVAI420, BlendYUVAYUVPacked, BlendYUVARV16, BlendYUVARV24 ), BLEND_CFG( FCC_YUVP, BlendPalI420, BlendPalYUVPacked, BlendPalRV, BlendPalRV ), BLEND_CFG( FCC_RGBA, BlendRGBAI420, BlendRGBAYUVPacked, BlendRGBAR16, BlendRGBAR24 ), BLEND_CFG( FCC_I420, BlendI420I420, BlendI420YUVPacked, BlendI420R16, BlendI420R24 ), BLEND_CFG( FCC_YV12, BlendI420I420, BlendI420YUVPacked, BlendI420R16, BlendI420R24 ), { 0, {0,}, NULL }};static void Blend( filter_t *p_filter, picture_t *p_dst, picture_t *p_dst_orig, picture_t *p_src, int i_x_offset, int i_y_offset, int i_alpha ){ int i_width, i_height; if( i_alpha == 0 ) return; i_width = __MIN((int)p_filter->fmt_out.video.i_visible_width - i_x_offset, (int)p_filter->fmt_in.video.i_visible_width); i_height = __MIN((int)p_filter->fmt_out.video.i_visible_height -i_y_offset, (int)p_filter->fmt_in.video.i_visible_height); if( i_width <= 0 || i_height <= 0 ) return; video_format_FixRgb( &p_filter->fmt_out.video ); video_format_FixRgb( &p_filter->fmt_in.video );#if 0 msg_Dbg( p_filter, "chroma: %4.4s -> %4.4s\n", (char *)&p_filter->fmt_in.video.i_chroma, (char *)&p_filter->fmt_out.video.i_chroma );#endif for( int i = 0; p_blend_cfg[i].src != 0; i++ ) { if( p_blend_cfg[i].src != p_filter->fmt_in.video.i_chroma ) continue; for( int j = 0; p_blend_cfg[i].p_dst[j] != 0; j++ ) { if( p_blend_cfg[i].p_dst[j] != p_filter->fmt_out.video.i_chroma ) continue; p_blend_cfg[i].pf_blend( p_filter, p_dst, p_dst_orig, p_src, i_x_offset, i_y_offset, i_width, i_height, i_alpha ); return; } } msg_Dbg( p_filter, "no matching alpha blending routine " "(chroma: %4.4s -> %4.4s)", (char *)&p_filter->fmt_in.video.i_chroma, (char *)&p_filter->fmt_out.video.i_chroma );}/*********************************************************************** * Utils ***********************************************************************/static inline uint8_t vlc_uint8( int v ){ if( v > 255 ) return 255; else if( v < 0 ) return 0; return v;}#define MAX_TRANS 255#define TRANS_BITS 8static inline int vlc_blend( int v1, int v2, int a ){ /* TODO bench if the tests really increase speed */ if( a == 0 ) return v2; else if( a == MAX_TRANS ) return v1; return ( v1 * a + v2 * (MAX_TRANS - a ) ) >> TRANS_BITS;}static inline int vlc_alpha( int t, int a ){ if( a == 255 ) return t; return (t * a) / 255;}static inline void yuv_to_rgb( int *r, int *g, int *b, uint8_t y1, uint8_t u1, uint8_t v1 ){ /* macros used for YUV pixel conversions */# define SCALEBITS 10# define ONE_HALF (1 << (SCALEBITS - 1))# define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) int y, cb, cr, r_add, g_add, b_add; cb = u1 - 128; cr = v1 - 128; r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF; g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + ONE_HALF; b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF; y = (y1 - 16) * FIX(255.0/219.0); *r = vlc_uint8( (y + r_add) >> SCALEBITS ); *g = vlc_uint8( (y + g_add) >> SCALEBITS ); *b = vlc_uint8( (y + b_add) >> SCALEBITS );#undef FIX#undef ONE_HALF#undef SCALEBITS}static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -