vo_vesa.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,140 行 · 第 1/3 页

C
1,140
字号
/* *  video_out_vesa.c * *	Copyright (C) Nick Kurshev <nickols_k@mail.ru> - Oct 2001 * *  You can redistribute this file under terms and conditions *  of GNU General Public licence v2. *  This file is partly based on vbetest.c from lrmi distributive. *//*  TODO:  - hw YUV support (need volunteers who have corresponding hardware)  - triple buffering (if it will really speedup playback).    note: triple buffering requires VBE 3.0 - need volunteers.*/#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "gtf.h"#include <mplaylib.h>#ifdef HAVE_MALLOC_H#include <uclib.h>#endif#include <mplaylib.h>#include <mplaylib.h>#include <stddef.h>#include <mplaylib.h>#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <vbe.h>#include "video_out.h"#include "video_out_internal.h"#include "fastmemcpy.h"#include "sub.h"#include "libavutil/common.h"#include "mpbswap.h"#include "aspect.h"#include "vesa_lvo.h"#ifdef CONFIG_VIDIX#include "vosub_vidix.h"#endif#include "mp_msg.h"#include "libswscale/swscale.h"#include "libmpcodecs/vf_scale.h"#ifdef HAVE_PNGextern vo_functions_t video_out_png;#endifextern char *monitor_hfreq_str;extern char *monitor_vfreq_str;extern char *monitor_dotclock_str;#define MAX_BUFFERS 3#ifndef max#define max(a,b) ((a)>(b)?(a):(b))#endif#ifndef min#define min(a,b) ((a)<(b)?(a):(b))#endif#define UNUSED(x) ((void)(x)) /**< Removes warning about unused arguments */static vo_info_t info = {	"VESA VBE 2.0 video output",	"vesa",	"Nick Kurshev <nickols_k@mail.ru>",        "Requires ROOT privileges"};LIBVO_EXTERN(vesa)/* driver data */struct win_frame{  uint8_t   *ptr;   /* pointer to window's frame memory */  uint32_t   low;   /* lowest boundary of frame */  uint32_t   high;  /* highest boundary of frame */  char       idx;   /* indicates index of relocatable frame (A=0 or B=1)                       special case for DGA: idx=-1		       idx=-2 indicates invalid frame, exists only in init() */};static void (*cpy_blk_fnc)(unsigned long,uint8_t *,unsigned long) = NULL;static uint32_t srcW=0,srcH=0,srcBpp,srcFourcc; /* source image description */static uint32_t dstBpp,dstW, dstH,dstFourcc; /* destinition image description */static struct SwsContext * sws = NULL;static int32_t x_offset,y_offset; /* to center image on screen */static unsigned init_mode=0; /* mode before run of mplayer */static void *init_state = NULL; /* state before run of mplayer */static struct win_frame win; /* real-mode window to video memory */static uint8_t *dga_buffer = NULL; /* for yuv2rgb and sw_scaling */static unsigned video_mode; /* selected video mode for playback */static struct VesaModeInfoBlock video_mode_info;static int flip_trigger = 0;static void (*draw_alpha_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);/* multibuffering */uint8_t*  video_base; /* should be never changed */uint32_t  multi_buff[MAX_BUFFERS]; /* contains offsets of buffers */uint8_t   multi_size=0; /* total number of buffers */uint8_t   multi_idx=0; /* active buffer *//* Linux Video Overlay */static const char *lvo_name = NULL;static int lvo_opened = 0;#ifdef CONFIG_VIDIXstatic const char *vidix_name = NULL;static int vidix_opened = 0;static vidix_grkey_t gr_key;#endif/* Neomagic TV out */static int neomagic_tvout = 0;static int neomagic_tvnorm = NEO_PAL; #define HAS_DGA()  (win.idx == -1)#define MOVIE_MODE (MODE_ATTR_COLOR | MODE_ATTR_GRAPHICS)#define FRAME_MODE (MODE_WIN_RELOCATABLE | MODE_WIN_WRITEABLE)static char * vbeErrToStr(int err){  char *retval;  static char sbuff[80];  if((err & VBE_VESA_ERROR_MASK) == VBE_VESA_ERROR_MASK)  {    sprintf(sbuff,"VESA failed = 0x4f%02x",(err & VBE_VESA_ERRCODE_MASK)>>8);    retval = sbuff;  }  else  switch(err)  {     case VBE_OK: retval = "No error"; break;    case VBE_VM86_FAIL: retval = "vm86() syscall failed"; break;    case VBE_OUT_OF_DOS_MEM: retval = "Out of DOS memory"; break;    case VBE_OUT_OF_MEM: retval = "Out of memory"; break;    case VBE_BROKEN_BIOS: retval = "Broken BIOS or DOS TSR"; break;    default: sprintf(sbuff,"Unknown or internal error: %i",err); retval=sbuff; break;  }  return retval;}#define PRINT_VBE_ERR(name,err) { mp_msg(MSGT_VO,MSGL_WARN, "vo_vesa: %s returns: %s\n",name,vbeErrToStr(err)); fflush(stdout); }static void vesa_term( void ){  int err;  if(lvo_opened) { vlvo_term();  lvo_opened = 0; }#ifdef CONFIG_VIDIX  else if(vidix_opened) { vidix_term();  vidix_opened = 0; }#endif  if(init_state) if((err=vbeRestoreState(init_state)) != VBE_OK) PRINT_VBE_ERR("vbeRestoreState",err);  init_state=NULL;  if(init_mode) if((err=vbeSetMode(init_mode,NULL)) != VBE_OK) PRINT_VBE_ERR("vbeSetMode",err);  init_mode=0;  if(HAS_DGA()) vbeUnmapVideoBuffer((unsigned long)win.ptr,win.high);  if(dga_buffer && !HAS_DGA()) free(dga_buffer);  vbeDestroy();  if(sws) sws_freeContext(sws);  sws=NULL;}#define VALID_WIN_FRAME(offset) (offset >= win.low && offset < win.high)#define VIDEO_PTR(offset) (win.ptr + offset - win.low)static inline void __vbeSwitchBank(unsigned long offset){  unsigned long gran;  unsigned new_offset;  int err;  gran = video_mode_info.WinGranularity*1024;  new_offset = offset / gran;  if(HAS_DGA()) { err = -1; goto show_err; }  if((err=vbeSetWindow(win.idx,new_offset)) != VBE_OK)  {    show_err:    vesa_term();    PRINT_VBE_ERR("vbeSetWindow",err);    mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_VESA_FatalErrorOccurred);    abort();  }  win.low = new_offset * gran;  win.high = win.low + video_mode_info.WinSize*1024;}static void __vbeSetPixel(int x, int y, int r, int g, int b){	int x_res = video_mode_info.XResolution;	int y_res = video_mode_info.YResolution;	int shift_r = video_mode_info.RedFieldPosition;	int shift_g = video_mode_info.GreenFieldPosition;	int shift_b = video_mode_info.BlueFieldPosition;	int pixel_size = (dstBpp+7)/8;	int bpl = video_mode_info.BytesPerScanLine;	int color;	unsigned offset;	if (x < 0 || x >= x_res || y < 0 || y >= y_res)	return;	r >>= 8 - video_mode_info.RedMaskSize;	g >>= 8 - video_mode_info.GreenMaskSize;	b >>= 8 - video_mode_info.BlueMaskSize;	color = (r << shift_r) | (g << shift_g) | (b << shift_b);	offset = y * bpl + (x * pixel_size);        if(!VALID_WIN_FRAME(offset)) __vbeSwitchBank(offset);	memcpy(VIDEO_PTR(offset), &color, pixel_size);}/*  Copies part of frame to video memory. Data should be in the same format  as video memory.*/static void __vbeCopyBlockFast(unsigned long offset,uint8_t *image,unsigned long size){  fast_memcpy(&win.ptr[offset],image,size);}static void __vbeCopyBlock(unsigned long offset,uint8_t *image,unsigned long size){   unsigned long delta,src_idx = 0;   while(size)   {	if(!VALID_WIN_FRAME(offset)) __vbeSwitchBank(offset);	delta = min(size,win.high - offset);	fast_memcpy(VIDEO_PTR(offset),&image[src_idx],delta);	src_idx += delta;	offset += delta;	size -= delta;   }}/*  Copies frame to video memory. Data should be in the same format as video  memory.*/#define PIXEL_SIZE() ((dstBpp+7)/8)#define SCREEN_LINE_SIZE(pixel_size) (video_mode_info.XResolution*(pixel_size) )#define IMAGE_LINE_SIZE(pixel_size) (dstW*(pixel_size))static void __vbeCopyData(uint8_t *image){   unsigned long i,j,image_offset,offset;   unsigned pixel_size,image_line_size,screen_line_size,x_shift;   pixel_size = PIXEL_SIZE();   screen_line_size = SCREEN_LINE_SIZE(pixel_size);   image_line_size = IMAGE_LINE_SIZE(pixel_size);   if(dstW == video_mode_info.XResolution)   {     /* Special case for zooming */     (*cpy_blk_fnc)(y_offset*screen_line_size,image,image_line_size*dstH);   }   else   {     x_shift = x_offset*pixel_size;     for(j=0,i=y_offset;j<dstH;i++,j++)     {       offset = i*screen_line_size+x_shift;       image_offset = j*image_line_size;       (*cpy_blk_fnc)(offset,&image[image_offset],image_line_size);     }   }}/* is called for yuv only */static int draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y){    int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;    uint8_t *dst[3]= {dga_buffer, NULL, NULL};    int dstStride[3];    if( mp_msg_test(MSGT_VO,MSGL_DBG3) )	mp_msg(MSGT_VO,MSGL_DBG3, "vo_vesa: draw_slice was called: w=%u h=%u x=%u y=%u\n",w,h,x,y);    dstStride[0]=dstride*((dstBpp+7)/8);    dstStride[1]=    dstStride[2]=dstStride[0]>>1;    if(HAS_DGA()) dst[0] += y_offset*SCREEN_LINE_SIZE(PIXEL_SIZE())+x_offset*PIXEL_SIZE();    sws_scale_ordered(sws,image,stride,y,h,dst,dstStride);    flip_trigger = 1;    return 0;}/* Please comment it out if you want have OSD within movie *//*#define OSD_OUTSIDE_MOVIE 1*/static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;#ifndef OSD_OUTSIDE_MOVIE   if(HAS_DGA())   {	x0 += x_offset;	y0 += y_offset;   }#endif   vo_draw_alpha_rgb32(w,h,src,srca,stride,dga_buffer+4*(y0*dstride+x0),4*dstride);}static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;#ifndef OSD_OUTSIDE_MOVIE   if(HAS_DGA())   {	x0 += x_offset;	y0 += y_offset;   }#endif   vo_draw_alpha_rgb24(w,h,src,srca,stride,dga_buffer+3*(y0*dstride+x0),3*dstride);}static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;#ifndef OSD_OUTSIDE_MOVIE   if(HAS_DGA())   {	x0 += x_offset;	y0 += y_offset;   }#endif   vo_draw_alpha_rgb16(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);}static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){   int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;#ifndef OSD_OUTSIDE_MOVIE   if(HAS_DGA())   {	x0 += x_offset;	y0 += y_offset;   }#endif   vo_draw_alpha_rgb15(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);}static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){  UNUSED(x0);  UNUSED(y0);  UNUSED(w);  UNUSED(h);  UNUSED(src);  UNUSED(srca);  UNUSED(stride);}static void draw_osd(void){ uint32_t w,h; if( mp_msg_test(MSGT_VO,MSGL_DBG3) )	mp_msg(MSGT_VO,MSGL_DBG3, "vo_vesa: draw_osd was called\n"); {#ifdef OSD_OUTSIDE_MOVIE   w = HAS_DGA()?video_mode_info.XResolution:dstW;   h = HAS_DGA()?video_mode_info.YResolution:dstH;#else   w = dstW;   h = dstH;#endif   if(dga_buffer) vo_draw_text(w,h,draw_alpha_fnc); }}static void flip_page(void)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?