/***************************************************************************** * yuvp.c: YUVP to YUVA/RGBA chroma converter ***************************************************************************** * Copyright (C) 2008 VLC authors and VideoLAN * $Id$ * * Authors: Laurent Aimar < fenrir @ videolan.org > * * 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 #include #include #include #include /* TODO: * Add anti-aliasing support (specially for DVD where only 4 colors are used) */ /***************************************************************************** * Module descriptor *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); vlc_module_begin () set_description( N_("YUVP converter") ) set_capability( "video converter", 10 ) set_callbacks( Open, Close ) vlc_module_end () /**************************************************************************** * Local prototypes ****************************************************************************/ static picture_t *Filter( filter_t *, picture_t * ); static void Yuv2Rgb( uint8_t *r, uint8_t *g, uint8_t *b, int y1, int u1, int v1 ); /***************************************************************************** * Open: probe the filter and return score *****************************************************************************/ static int Open( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t*)p_this; /* It only supports YUVP to YUVA/RGBA without scaling * (if scaling is required another filter can do it) */ if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_YUVP || ( p_filter->fmt_out.video.i_chroma != VLC_CODEC_YUVA && p_filter->fmt_out.video.i_chroma != VLC_CODEC_RGBA && p_filter->fmt_out.video.i_chroma != VLC_CODEC_ARGB ) || p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width || p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height || p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation ) { return VLC_EGENERIC; } p_filter->pf_video_filter = Filter; msg_Dbg( p_filter, "YUVP to %4.4s converter", (const char*)&p_filter->fmt_out.video.i_chroma ); return VLC_SUCCESS; } /***************************************************************************** * Close: clean up the filter *****************************************************************************/ static void Close( vlc_object_t *p_this ) { VLC_UNUSED(p_this ); } /**************************************************************************** * Filter: the whole thing ****************************************************************************/ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) { picture_t *p_out; if( !p_pic ) return NULL; const video_palette_t *p_yuvp = p_filter->fmt_in.video.p_palette; assert( p_yuvp != NULL ); assert( p_filter->fmt_in.video.i_chroma == VLC_CODEC_YUVP ); assert( p_filter->fmt_in.video.i_width == p_filter->fmt_out.video.i_width ); assert( p_filter->fmt_in.video.i_height == p_filter->fmt_out.video.i_height ); /* Request output picture */ p_out = filter_NewPicture( p_filter ); if( !p_out ) { picture_Release( p_pic ); return NULL; } if( p_filter->fmt_out.video.i_chroma == VLC_CODEC_YUVA ) { for( unsigned int y = 0; y < p_filter->fmt_in.video.i_height; y++ ) { const uint8_t *p_line = &p_pic->p->p_pixels[y*p_pic->p->i_pitch]; uint8_t *p_y = &p_out->Y_PIXELS[y*p_out->Y_PITCH]; uint8_t *p_u = &p_out->U_PIXELS[y*p_out->U_PITCH]; uint8_t *p_v = &p_out->V_PIXELS[y*p_out->V_PITCH]; uint8_t *p_a = &p_out->A_PIXELS[y*p_out->A_PITCH]; for( unsigned int x = 0; x < p_filter->fmt_in.video.i_width; x++ ) { const int v = p_line[x]; if( v > p_yuvp->i_entries ) /* maybe assert ? */ continue; p_y[x] = p_yuvp->palette[v][0]; p_u[x] = p_yuvp->palette[v][1]; p_v[x] = p_yuvp->palette[v][2]; p_a[x] = p_yuvp->palette[v][3]; } } } else { video_palette_t rgbp; assert( p_filter->fmt_out.video.i_chroma == VLC_CODEC_ARGB || p_filter->fmt_out.video.i_chroma == VLC_CODEC_RGBA ); /* Create a RGBA palette */ rgbp.i_entries = p_yuvp->i_entries; const uint8_t r = p_filter->fmt_out.video.i_chroma == VLC_CODEC_ARGB ? 1 : 0; const uint8_t g = p_filter->fmt_out.video.i_chroma == VLC_CODEC_ARGB ? 2 : 1; const uint8_t b = p_filter->fmt_out.video.i_chroma == VLC_CODEC_ARGB ? 3 : 2; const uint8_t a = p_filter->fmt_out.video.i_chroma == VLC_CODEC_ARGB ? 0 : 3; for( int i = 0; i < p_yuvp->i_entries; i++ ) { if( p_yuvp->palette[i][3] == 0 ) { memset( rgbp.palette[i], 0, sizeof( rgbp.palette[i] ) ); continue; } Yuv2Rgb( &rgbp.palette[i][r], &rgbp.palette[i][g], &rgbp.palette[i][b], p_yuvp->palette[i][0], p_yuvp->palette[i][1], p_yuvp->palette[i][2] ); rgbp.palette[i][a] = p_yuvp->palette[i][3]; } for( unsigned int y = 0; y < p_filter->fmt_in.video.i_height; y++ ) { const uint8_t *p_line = &p_pic->p->p_pixels[y*p_pic->p->i_pitch]; uint8_t *p_pixels = &p_out->p->p_pixels[y*p_out->p->i_pitch]; for( unsigned int x = 0; x < p_filter->fmt_in.video.i_width; x++ ) { const int v = p_line[x]; if( v >= rgbp.i_entries ) /* maybe assert ? */ continue; p_pixels[4*x+0] = rgbp.palette[v][0]; p_pixels[4*x+1] = rgbp.palette[v][1]; p_pixels[4*x+2] = rgbp.palette[v][2]; p_pixels[4*x+3] = rgbp.palette[v][3]; } } } picture_CopyProperties( p_out, p_pic ); picture_Release( p_pic ); return p_out; } /* FIXME copied from blend.c */ static inline uint8_t vlc_uint8( int v ) { if( v > 255 ) return 255; else if( v < 0 ) return 0; return v; } static void Yuv2Rgb( uint8_t *r, uint8_t *g, uint8_t *b, int y1, int u1, int v1 ) { /* macros used for YUV pixel conversions */ # define SCALEBITS 10 # define ONE_HALF (1 << (SCALEBITS - 1)) # define FIX(x) ((int) ((x) * (1<> SCALEBITS ); *g = vlc_uint8( (y + g_add) >> SCALEBITS ); *b = vlc_uint8( (y + b_add) >> SCALEBITS ); #undef FIX }