📄 video_yuv.c
字号:
/***************************************************************************** * video_yuv.c: YUV transformation functions * Provides functions to perform the YUV conversion. The functions provided here * are a complete and portable C implementation, and may be replaced in certain * case by optimized functions. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * * Authors: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "defs.h"#include <math.h> /* exp(), pow() */#include <errno.h> /* ENOMEM */#include <stdlib.h> /* free() */#include <string.h> /* strerror() */#include "config.h"#include "common.h"#include "threads.h"#include "mtime.h"#include "plugins.h"#include "video.h"#include "video_output.h"#include "video_yuv.h"#include "intf_msg.h"/***************************************************************************** * Constants *****************************************************************************//* Margins and offsets in conversion tables - Margins are used in case a RGB * RGB conversion would give a value outside the 0-255 range. Offsets have been * calculated to avoid using the same cache line for 2 tables. conversion tables * are 2*MARGIN + 256 long and stores pixels.*/#define RED_MARGIN 178#define GREEN_MARGIN 135#define BLUE_MARGIN 224#define RED_OFFSET 1501 /* 1323 to 1935 */#define GREEN_OFFSET 135 /* 0 to 526 */#define BLUE_OFFSET 818 /* 594 to 1298 */#define RGB_TABLE_SIZE 1935 /* total table size */#define GRAY_MARGIN 384#define GRAY_TABLE_SIZE 1024 /* total table size */#define PALETTE_TABLE_SIZE 2176 /* YUV -> 8bpp palette lookup table *//* macros used for YUV pixel conversions */#define SHIFT 20#define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))#define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))#define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))#define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))/***************************************************************************** * Local prototypes *****************************************************************************/static void SetGammaTable ( int *pi_table, double f_gamma );static void SetYUV ( vout_thread_t *p_vout );static void SetOffset ( int i_width, int i_height, int i_pic_width, int i_pic_height, boolean_t *pb_h_scaling, int *pi_v_scaling, int *p_offset );static void ConvertY4Gray8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertY4Gray16 ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertY4Gray24 ( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertY4Gray32 ( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV420RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV422RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV444RGB8 ( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width, int i_matrix_coefficients );/***************************************************************************** * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel conversion blocks ***************************************************************************** * These conversion routines are used by YUV conversion functions. * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer, * which is also modified. *****************************************************************************/#define CONVERT_Y_PIXEL( BPP ) \ /* Only Y sample is present */ \ p_ybase = p_yuv + *p_y++; \ *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \ p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \ + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];#define CONVERT_YUV_PIXEL( BPP ) \ /* Y, U and V samples are present */ \ i_uval = *p_u++; \ i_vval = *p_v++; \ i_red = (V_RED_COEF * i_vval) >> SHIFT; \ i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \ i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \ CONVERT_Y_PIXEL( BPP ) \/***************************************************************************** * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp ***************************************************************************** * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling *****************************************************************************/#define CONVERT_4YUV_PIXELS( CHROMA ) \ *p_pic++ = p_lookup[ \ (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \ + ((*p_u + dither20[i_real_y]) >> 5) * 9 \ + ((*p_v + dither20[i_real_y]) >> 5) ]; \ *p_pic++ = p_lookup[ \ (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \ + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \ + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \ *p_pic++ = p_lookup[ \ (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \ + ((*p_u + dither22[i_real_y]) >> 5) * 9 \ + ((*p_v + dither22[i_real_y]) >> 5) ]; \ *p_pic++ = p_lookup[ \ (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \ + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \ + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \#define CONVERT_4YUV_PIXELS_SCALE( CHROMA ) \ *p_pic++ = p_lookup[ \ (((*p_y + dither10[i_real_y]) >> 4) << 7) \ + ((*p_u + dither20[i_real_y]) >> 5) * 9 \ + ((*p_v + dither20[i_real_y]) >> 5) ]; \ b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \ p_y += *p_offset; \ p_u += *p_offset & b_jump_uv; \ p_v += *p_offset++ & b_jump_uv; \ *p_pic++ = p_lookup[ \ (((*p_y + dither11[i_real_y]) >> 4) << 7) \ + ((*p_u + dither21[i_real_y]) >> 5) * 9 \ + ((*p_v + dither21[i_real_y]) >> 5) ]; \ b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \ p_y += *p_offset; \ p_u += *p_offset & b_jump_uv; \ p_v += *p_offset++ & b_jump_uv; \ *p_pic++ = p_lookup[ \ (((*p_y + dither12[i_real_y]) >> 4) << 7) \ + ((*p_u + dither22[i_real_y]) >> 5) * 9 \ + ((*p_v + dither22[i_real_y]) >> 5) ]; \ b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \ p_y += *p_offset; \ p_u += *p_offset & b_jump_uv; \ p_v += *p_offset++ & b_jump_uv; \ *p_pic++ = p_lookup[ \ (((*p_y + dither13[i_real_y]) >> 4) << 7) \ + ((*p_u + dither23[i_real_y]) >> 5) * 9 \ + ((*p_v + dither23[i_real_y]) >> 5) ]; \ b_jump_uv = (b_jump_uv + *p_offset) & 0x1; \ p_y += *p_offset; \ p_u += *p_offset & b_jump_uv; \ p_v += *p_offset++ & b_jump_uv; \/***************************************************************************** * SCALE_WIDTH: scale a line horizontally ***************************************************************************** * This macro scales a line using rendering buffer and offset array. It works * for 1, 2 and 4 Bpp. *****************************************************************************/#define SCALE_WIDTH \ if( b_horizontal_scaling ) \ { \ /* Horizontal scaling, conversion has been done to buffer. \ * Rewind buffer and offset, then copy and scale line */ \ p_buffer = p_buffer_start; \ p_offset = p_offset_start; \ for( i_x = i_pic_width / 16; i_x--; ) \ { \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \ *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -