⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blend.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * 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 + -