📄 video_output.c
字号:
/***************************************************************************** * video_output.c : video output thread * This module describes the programming interface for video output threads. * It includes functions allowing to open a new thread, send pictures to a * thread, and destroy a previously oppened video output thread. ***************************************************************************** * Copyright (C) 2000 VideoLAN * * Authors: * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "defs.h"#include <errno.h> /* ENOMEM */#include <stdlib.h> /* free() */#include <stdio.h> /* sprintf() */#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_text.h"#include "video_spu.h"#include "video_yuv.h"#include "intf_msg.h"#include "main.h"/***************************************************************************** * Local prototypes *****************************************************************************/static int BinaryLog ( u32 i );static void MaskToShift ( int *pi_left, int *pi_right, u32 i_mask );static int InitThread ( vout_thread_t *p_vout );static void RunThread ( vout_thread_t *p_vout );static void ErrorThread ( vout_thread_t *p_vout );static void EndThread ( vout_thread_t *p_vout );static void DestroyThread ( vout_thread_t *p_vout, int i_status );static void Print ( vout_thread_t *p_vout, int i_x, int i_y, int i_h_align, int i_v_align, unsigned char *psz_text );static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y, int i_w, int i_h );static void SetBufferPicture ( vout_thread_t *p_vout, picture_t *p_pic );static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );static void RenderSubPicture ( vout_thread_t *p_vout, subpicture_t *p_subpic );static void RenderInterface ( vout_thread_t *p_vout );static int RenderIdle ( vout_thread_t *p_vout );static void RenderInfo ( vout_thread_t *p_vout );static void Synchronize ( vout_thread_t *p_vout, s64 i_delay );static int Manage ( vout_thread_t *p_vout );static int Align ( vout_thread_t *p_vout, int *pi_x, int *pi_y, int i_width, int i_height, int i_h_align, int i_v_align );static void SetPalette ( p_vout_thread_t p_vout, u16 *red, u16 *green, u16 *blue, u16 *transp );/***************************************************************************** * vout_CreateThread: creates a new video output thread ***************************************************************************** * This function creates a new video output thread, and returns a pointer * to its description. On error, it returns NULL. * If pi_status is NULL, then the function will block until the thread is ready. * If not, it will be updated using one of the THREAD_* constants. *****************************************************************************/vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, int i_width, int i_height, int *pi_status, int i_method, void *p_data ){ vout_thread_t * p_vout; /* thread descriptor */ int i_status; /* thread status */ int i_index; /* index for array initialization */ char * psz_method; /* Allocate descriptor */ intf_DbgMsg("\n"); p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) ); if( p_vout == NULL ) { intf_ErrMsg( "error: %s\n", strerror(ENOMEM) ); return( NULL ); } /* Request an interface plugin */ psz_method = main_GetPszVariable( VOUT_METHOD_VAR, VOUT_DEFAULT_METHOD ); if( RequestPlugin( &p_vout->vout_plugin, "vout", psz_method ) < 0 ) { intf_ErrMsg( "error: could not open video plugin vout_%s.so\n", psz_method ); free( p_vout ); return( NULL ); } /* Get plugins */ p_vout->p_sys_create = GetPluginFunction( p_vout->vout_plugin, "vout_SysCreate" ); p_vout->p_sys_init = GetPluginFunction( p_vout->vout_plugin, "vout_SysInit" ); p_vout->p_sys_end = GetPluginFunction( p_vout->vout_plugin, "vout_SysEnd" ); p_vout->p_sys_destroy = GetPluginFunction( p_vout->vout_plugin, "vout_SysDestroy" ); p_vout->p_sys_manage = GetPluginFunction( p_vout->vout_plugin, "vout_SysManage" ); p_vout->p_sys_display = GetPluginFunction( p_vout->vout_plugin, "vout_SysDisplay" ); /* Initialize thread properties - thread id and locks will be initialized * later */ p_vout->b_die = 0; p_vout->b_error = 0; p_vout->b_active = 0; p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status; *p_vout->pi_status = THREAD_CREATE; /* Initialize some fields used by the system-dependant method - these fields will * probably be modified by the method, and are only preferences */ p_vout->i_changes = 0; p_vout->i_width = i_width; p_vout->i_height = i_height; p_vout->i_bytes_per_line = i_width * 2; p_vout->i_screen_depth = 15; p_vout->i_bytes_per_pixel = 2; p_vout->f_gamma = VOUT_GAMMA; p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT ); p_vout->b_info = 0; p_vout->b_interface = 0; p_vout->b_scale = 0; p_vout->p_set_palette = SetPalette; intf_DbgMsg( "wished configuration: %dx%d, %d/%d bpp (%d Bpl)\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line ); /* Initialize idle screen */ p_vout->last_display_date = mdate(); p_vout->last_display_date = 0; p_vout->last_idle_date = 0;#ifdef STATS /* Initialize statistics fields */ p_vout->render_time = 0; p_vout->c_fps_samples = 0;#endif /* Initialize buffer index */ p_vout->i_buffer_index = 0; /* Initialize pictures and subpictures - translation tables and functions * will be initialized later in InitThread */ for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++) { p_vout->p_picture[i_index].i_type = EMPTY_PICTURE; p_vout->p_picture[i_index].i_status = FREE_PICTURE; } for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++) { p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE; p_vout->p_subpicture[i_index].i_status= FREE_SUBPICTURE; } p_vout->i_pictures = 0; /* Initialize synchronization informations */ p_vout->i_synchro_level = VOUT_SYNCHRO_LEVEL_START; /* Create and initialize system-dependant method - this function issues its * own error messages */ if( p_vout->p_sys_create( p_vout, psz_display, i_root_window, p_data ) ) { TrashPlugin( p_vout->vout_plugin ); free( p_vout ); return( NULL ); } intf_DbgMsg("actual configuration: %dx%d, %d/%d bpp (%d Bpl), masks: 0x%x/0x%x/0x%x\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_bytes_per_pixel * 8, p_vout->i_bytes_per_line, p_vout->i_red_mask, p_vout->i_green_mask, p_vout->i_blue_mask ); /* Calculate shifts from system-updated masks */ MaskToShift( &p_vout->i_red_lshift, &p_vout->i_red_rshift, p_vout->i_red_mask ); MaskToShift( &p_vout->i_green_lshift, &p_vout->i_green_rshift, p_vout->i_green_mask ); MaskToShift( &p_vout->i_blue_lshift, &p_vout->i_blue_rshift, p_vout->i_blue_mask ); /* Set some useful colors */ p_vout->i_white_pixel = RGB2PIXEL( p_vout, 255, 255, 255 ); p_vout->i_black_pixel = RGB2PIXEL( p_vout, 0, 0, 0 ); p_vout->i_gray_pixel = RGB2PIXEL( p_vout, 128, 128, 128 ); p_vout->i_blue_pixel = RGB2PIXEL( p_vout, 0, 0, 50 ); /* Load fonts - fonts must be initialized after the system method since * they may be dependant on screen depth and other thread properties */ p_vout->p_default_font = vout_LoadFont( DATA_PATH "/" VOUT_DEFAULT_FONT ); if( p_vout->p_default_font == NULL ) { p_vout->p_default_font = vout_LoadFont( "share/" VOUT_DEFAULT_FONT ); } if( p_vout->p_default_font == NULL ) { p_vout->p_sys_destroy( p_vout ); TrashPlugin( p_vout->vout_plugin ); free( p_vout ); return( NULL ); } p_vout->p_large_font = vout_LoadFont( DATA_PATH "/" VOUT_LARGE_FONT ); if( p_vout->p_large_font == NULL ) { p_vout->p_large_font = vout_LoadFont( "share/" VOUT_LARGE_FONT ); } if( p_vout->p_large_font == NULL ) { vout_UnloadFont( p_vout->p_default_font ); p_vout->p_sys_destroy( p_vout ); TrashPlugin( p_vout->vout_plugin ); free( p_vout ); return( NULL ); } /* Create thread and set locks */ vlc_mutex_init( &p_vout->picture_lock ); vlc_mutex_init( &p_vout->subpicture_lock ); vlc_mutex_init( &p_vout->change_lock ); vlc_mutex_lock( &p_vout->change_lock ); if( vlc_thread_create( &p_vout->thread_id, "video output", (void *) RunThread, (void *) p_vout) ) { intf_ErrMsg("error: %s\n", strerror(ENOMEM)); vout_UnloadFont( p_vout->p_default_font ); vout_UnloadFont( p_vout->p_large_font ); p_vout->p_sys_destroy( p_vout ); TrashPlugin( p_vout->vout_plugin ); free( p_vout ); return( NULL ); } intf_Msg("Video display initialized (%dx%d, %d/%d bpp)\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_bytes_per_pixel * 8 ); /* If status is NULL, wait until the thread is created */ if( pi_status == NULL ) { do { msleep( THREAD_SLEEP ); }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR) && (i_status != THREAD_FATAL) ); if( i_status != THREAD_READY ) { return( NULL ); } } return( p_vout );}/***************************************************************************** * vout_DestroyThread: destroys a previously created thread ***************************************************************************** * Destroy a terminated thread. * The function will request a destruction of the specified thread. If pi_error * is NULL, it will return once the thread is destroyed. Else, it will be * update using one of the THREAD_* constants. *****************************************************************************/void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status ){ int i_status; /* thread status */ /* Set status */ intf_DbgMsg("\n"); p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status; *p_vout->pi_status = THREAD_DESTROY; /* Request thread destruction */ p_vout->b_die = 1; /* If status is NULL, wait until thread has been destroyed */ if( pi_status == NULL ) { do { msleep( THREAD_SLEEP ); }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR) && (i_status != THREAD_FATAL) ); }}/***************************************************************************** * vout_DisplaySubPicture: display a subpicture unit ***************************************************************************** * Remove the reservation flag of an subpicture, which will cause it to be ready * for display. The picture does not need to be locked, since it is ignored by * the output thread if is reserved. *****************************************************************************/void vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ){#ifdef DEBUG_VIDEO char psz_begin_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */ char psz_end_date[MSTRTIME_MAX_SIZE]; /* buffer for date string */#endif#ifdef DEBUG /* Check if status is valid */ if( p_subpic->i_status != RESERVED_SUBPICTURE ) { intf_DbgMsg("error: subpicture %p has invalid status %d\n", p_subpic, p_subpic->i_status ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -