vo_dxr2.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 956 行 · 第 1/2 页
C
956 行
#include "fastmemcpy.h"#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <mplaylib.h>#include <time.h>#include <errno.h>#include "config.h"#include "video_out.h"#include "video_out_internal.h"#include "mp_msg.h"#include "m_option.h"#include "sub.h"#include "get_path.h"#include "libmpdemux/mpeg_packetizer.h"#ifdef X11_FULLSCREEN#include "x11_common.h"#endif#include <dxr2ioctl.h>extern float monitor_aspect;extern float movie_aspect;int dxr2_fd = -1;static int movie_w,movie_h;static int playing = 0;// vo device used to blank the screen for the overlay initstatic vo_functions_t* sub_vo = NULL;static uint8_t* sub_img = NULL;static int sub_x,sub_y,sub_w,sub_h;static int sub_x_off,sub_y_off;static int sub_config_count;static int aspect;static int sub_vo_win = 0;static int use_ol = 1;static int ol_ratio = 1000;static char *norm = NULL;static char *ucode = NULL;static int ar_mode = DXR2_ASPECTRATIOMODE_LETTERBOX;static int mv_mode = DXR2_MACROVISION_OFF;static int _75ire_mode = DXR2_75IRE_OFF;static int bw_mode = DXR2_BLACKWHITE_OFF;static int interlaced_mode = DXR2_INTERLACED_ON;static int pixel_mode = DXR2_PIXEL_CCIR601;static int iec958_mode = DXR2_IEC958_DECODED;static int mute_mode = DXR2_AUDIO_MUTE_OFF;static int ignore_cache = 0;static int update_cache = 0;static int olw_cor = 0, olh_cor = 0,olx_cor = 0, oly_cor = 0;static int ol_osd = 0;static int ck_rmin = 0x40;static int ck_rmax = 0xFF;static int ck_r = 0xFF;static int ck_gmin = 0x00;static int ck_gmax = 0x20;static int ck_g = 0;static int ck_bmin = 0x40;static int ck_bmax = 0xFF;static int ck_b = 0xFF;static int cr_left = 0, cr_right = 0;static int cr_top = 55, cr_bot = 300;m_option_t dxr2_opts[] = { { "overlay", &use_ol, CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "nooverlay", &use_ol, CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "overlay-ratio", &ol_ratio, CONF_TYPE_INT, CONF_RANGE, 1, 2500, NULL }, { "ucode", &ucode, CONF_TYPE_STRING,0, 0, 0, NULL}, { "norm", &norm, CONF_TYPE_STRING,0, 0, 0, NULL}, { "ar-mode",&ar_mode, CONF_TYPE_INT, CONF_RANGE,0,2,NULL }, { "macrovision",&mv_mode,CONF_TYPE_INT,CONF_RANGE,0,3, NULL }, { "75ire",&_75ire_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "no75ire",&_75ire_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "bw",&bw_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "color",&bw_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "interlaced",&interlaced_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "nointerlaced",&interlaced_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "square-pixel",&pixel_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "ccir601-pixel",&pixel_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "iec958-encoded",&iec958_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "iec958-decoded",&iec958_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "mute", &mute_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "nomute",&mute_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "ignore-cache",&ignore_cache,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "update-cache",&update_cache,CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "olh-cor", &olh_cor, CONF_TYPE_INT, CONF_RANGE, -20, 20, NULL}, { "olw-cor", &olw_cor, CONF_TYPE_INT, CONF_RANGE, -20, 20, NULL}, { "olx-cor", &olx_cor, CONF_TYPE_INT, CONF_RANGE, -20, 20, NULL}, { "oly-cor", &oly_cor, CONF_TYPE_INT, CONF_RANGE, -20, 20, NULL}, { "ol-osd", &ol_osd, CONF_TYPE_FLAG, 0, 0, 1, NULL}, { "nool-osd", &ol_osd, CONF_TYPE_FLAG, 0, 1, 0, NULL}, { "ck-rmin", &ck_rmin, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-rmax", &ck_rmax, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-r", &ck_r, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-gmin", &ck_gmin, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-gmax", &ck_gmax, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-g", &ck_g, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-bmin", &ck_bmin, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-bmax", &ck_bmax, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "ck-b", &ck_b, CONF_TYPE_INT, CONF_RANGE, 0, 0xFF, NULL}, { "cr-left", &cr_left, CONF_TYPE_INT, CONF_RANGE, 0, 500, NULL}, { "cr-right", &cr_right, CONF_TYPE_INT, CONF_RANGE, 0, 500, NULL}, { "cr-top", &cr_top, CONF_TYPE_INT, CONF_RANGE, 0, 500, NULL}, { "cr-bot", &cr_bot, CONF_TYPE_INT, CONF_RANGE, 0, 500, NULL}, { NULL,NULL, 0, 0, 0, 0, NULL}};static vo_info_t info = { "DXR2 video out", "dxr2", "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>", ""};LIBVO_EXTERN (dxr2)static char *ucodesearchpath[] = { "/usr/local/lib/dxr2/dvd12.ux", "/usr/lib/dxr2/dvd12.ux", "/usr/src/dvd12.ux", NULL,};#define BUF_SIZE 2048static unsigned char dxr2buf[BUF_SIZE];static unsigned int dxr2bufpos = 0;int write_dxr2(unsigned char *data, int len){ int w = 0; if (dxr2_fd < 0) { mp_msg (MSGT_VO, MSGL_ERR, "DXR2 fd is not valid\n"); return 0; } while (len>0) if ((dxr2bufpos+len) <= BUF_SIZE) { fast_memcpy(dxr2buf+dxr2bufpos, data, len); dxr2bufpos+=len; len=0; } else { int copylen=BUF_SIZE-dxr2bufpos; if(copylen > 0) { fast_memcpy(dxr2buf+dxr2bufpos, data, copylen); dxr2bufpos += copylen; data+=copylen; len-=copylen; } w += write(dxr2_fd, dxr2buf, BUF_SIZE); if(w < 0) { mp_msg(MSGT_VO,MSGL_WARN,"DXR2 : write failed : %s \n",strerror(errno)); dxr2bufpos = 0; break; } dxr2bufpos -= w; if(dxr2bufpos) memmove(dxr2buf,dxr2buf + w,dxr2bufpos); } return w;}static void flush_dxr2(){ int w; while (dxr2bufpos) { w = write(dxr2_fd, dxr2buf, dxr2bufpos); if(w < 0) { mp_msg(MSGT_VO,MSGL_WARN,"DXR2 : write failed %s \n",strerror(errno)); dxr2bufpos = 0; break; } dxr2bufpos -= w; }}#define PACK_MAX_SIZE 2048static unsigned char pack[PACK_MAX_SIZE];static unsigned char mpg_eof[]={ 0x00, 0x00, 0x01, 0xb9};static void dxr2_send_eof(void){ write_dxr2(mpg_eof, sizeof(mpg_eof));}void dxr2_send_sub_packet(unsigned char* data,int len,int id,unsigned int timestamp) { int ptslen=5; if(dxr2_fd < 0) { mp_msg(MSGT_VO,MSGL_ERR,"DXR2 fd is not valid\n"); return; } if (((int) timestamp)<0) timestamp=0; mp_msg(MSGT_VO,MSGL_DBG2,"dxr2_send_sub_packet(timestamp=%d)\n", timestamp); // startcode: pack[0]=pack[1]=0;pack[2]=0x01; // stream id pack[3]=0xBD; while(len>=4){ int payload_size= PACK_MAX_SIZE-(7+ptslen+3); if(payload_size>len) payload_size= len; pack[4]=(3+ptslen+1+payload_size)>>8; pack[5]=(3+ptslen+1+payload_size)&255; pack[6]=0x81; if(ptslen){ int x; pack[7]=0x80; pack[8]=ptslen; // presentation time stamp: x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1; pack[9]=x; x=((((timestamp >> 15) & 0x7fff) << 1) | 1); pack[10]=x>>8; pack[11]=x&255; x=((((timestamp) & 0x7fff) << 1) | 1); pack[12]=x>>8; pack[13]=x&255; } else { pack[7]=0x00; pack[8]=0x00; } pack[ptslen+9] = id; write_dxr2(pack,7+ptslen+3); write_dxr2(data,payload_size); len -= payload_size; data += payload_size; ptslen = 0; }}static int dxr2_set_vga_params(dxr2_vgaParams_t* vga,int detect) { // Init the overlay, don't ask me how it work ;-) dxr2_sixArg_t oc; dxr2_oneArg_t om; dxr2_twoArg_t win; dxr2_fourArg_t crop; crop.arg1= cr_left; crop.arg2= cr_right; crop.arg3 = cr_top; crop.arg4 = cr_bot; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_CROPPING, &crop); oc.arg1 = 0x40; oc.arg2 = 0xff; oc.arg3 = 0x40; oc.arg4 = 0xff; oc.arg5 = 0x40; oc.arg6 = 0xff; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_COLOUR, &oc); om.arg = ol_ratio; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_RATIO,&om); win.arg1 = 100; win.arg2 = 3; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_POSITION,&win); win.arg1 = vo_screenwidth; win.arg2 = vo_screenheight; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_DIMENSION,&win); om.arg = 0; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_IN_DELAY,&om); if(detect) { // First we need a white screen uint8_t* img = malloc(vo_screenwidth*vo_screenheight*3); uint8_t* src[] = { img, NULL, NULL }; int stride[] = { vo_screenwidth * 3 , 0, 0 }; int cc = vo_config_count; memset(img,255,vo_screenwidth*vo_screenheight*3); vo_config_count = sub_config_count; if(sub_vo->config(vo_screenwidth,vo_screenheight,vo_screenwidth,vo_screenheight, VOFLAG_FULLSCREEN ,"DXR2 sub vo",IMGFMT_BGR24) != 0) { mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] sub vo config failed => No overlay\n"); sub_vo->uninit(); sub_vo = NULL; use_ol = 0; vo_config_count = cc; return 0; } sub_vo->draw_slice(src,stride,vo_screenwidth,vo_screenheight,0,0); sub_vo->flip_page(); free(img); sub_config_count++; vo_config_count = cc; om.arg = DXR2_OVERLAY_WINDOW_COLOUR_KEY; ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_MODE,&om); vga->xScreen = vo_screenwidth; vga->yScreen = vo_screenheight; vga->hOffWinKey = 100; vga->vOffWinKey = 3; ioctl(dxr2_fd, DXR2_IOC_CALCULATE_VGA_PARAMETERS, vga); } ioctl(dxr2_fd, DXR2_IOC_SET_VGA_PARAMETERS,vga); return 1;}static int dxr2_save_vga_params(dxr2_vgaParams_t* vga,char* name) { struct stat s; char* p = get_path("dxr2_cache"); int p_len = strlen(p), name_len = strlen(name); char cache_path[p_len + name_len + 2]; int ret; FILE* fd; if(stat(p,&s) !=0) { mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] No vga cache dir found (%s)\n",strerror(errno)); if(errno == EACCES) { free(p); return 0; } // Try to create the dir if(mkdir(p,S_IRWXU) != 0) { mp_msg(MSGT_VO,MSGL_ERR,"VO: [dxr2] Unable to create vga cache dir %s (%s)\n",p,strerror(errno)); free(p); return 0; } } sprintf(cache_path,"%s/%s",p,name); free(p); fd = fopen(cache_path,"w"); if(fd == NULL) { mp_msg(MSGT_VO,MSGL_ERR,"VO: [dxr2] Unable to open cache file %s for writing (%s)\n",cache_path,strerror(errno)); return 0; } ret = fprintf(fd,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", vga->hOffWinKey, vga->vOffWinKey, vga->xScreen, vga->yScreen, vga->hsyncPol, vga->vsyncPol, vga->blankStart, vga->blankWidth, vga->hOffset, vga->vOffset, vga->ratio, olx_cor, oly_cor, olw_cor, olh_cor); fclose(fd); return ret >= 11 ? 1 : 0;}static int dxr2_load_vga_params(dxr2_vgaParams_t* vga,char* name) { char* p = get_path("dxr2_cache"); int p_len = strlen(p), name_len = strlen(name); char cache_path[p_len + name_len + 2]; int ret; int xc,yc,wc,hc; FILE* fd; sprintf(cache_path,"%s/%s",p,name); free(p); fd = fopen(cache_path,"r"); if(fd == NULL) { mp_msg(MSGT_VO,MSGL_ERR,"VO: [dxr2] Unable to open cache file %s for reading (%s)\n",cache_path,strerror(errno)); return 0; } ret = fscanf(fd, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", &vga->hOffWinKey, &vga->vOffWinKey, &vga->xScreen, &vga->yScreen, &vga->hsyncPol, &vga->vsyncPol, &vga->blankStart, &vga->blankWidth, &vga->hOffset, &vga->vOffset, &vga->ratio, &xc, &yc, &wc, &hc); fclose(fd); if(ret > 11 && !olx_cor) olx_cor = xc; if(ret > 12 && !oly_cor) oly_cor = yc; if(ret > 13 && !olw_cor) olw_cor = wc; if(ret > 14 && !olh_cor) olh_cor = hc; return ret >= 11 ? 1 : 0;}static int dxr2_setup_vga_params(void) { const vo_info_t* vi = sub_vo->info; dxr2_vgaParams_t vga; int loaded = dxr2_load_vga_params(&vga,(char*)vi->short_name); if(!dxr2_set_vga_params(&vga,(update_cache || ignore_cache) ? 1 : !loaded )) return 0; if(!loaded || update_cache) dxr2_save_vga_params(&vga,(char*)vi->short_name); return 1;}static void dxr2_set_overlay_window(void) { uint8_t* src[] = { sub_img, NULL, NULL }; int stride[] = { movie_w * 3 , 0, 0 }; dxr2_twoArg_t win; int redisp = 0; int cc = vo_config_count; vo_config_count = sub_config_count; sub_vo->draw_slice(src,stride,movie_w,movie_h,0,0); sub_vo->flip_page(); vo_config_count = cc; mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] setting overlay with correction x=%d y=%d w=%d h=%d\n",olx_cor,oly_cor, olw_cor,olh_cor); // Sub vo isn't a windowed one, fill in the needed stuff if(!sub_vo_win) { if(vo_fs) { vo_dwidth = vo_screenwidth; vo_dheight = vo_screenheight; vo_dx = vo_dy = 0; } else { vo_dwidth = movie_w; vo_dheight = movie_h; vo_dx = (vo_screenwidth - vo_dwidth) / 2; vo_dy = (vo_screenheight - vo_dheight) / 2; } } if(sub_w != vo_dwidth || sub_h != vo_dheight) { int new_aspect = ((1<<16)*vo_dwidth + vo_dheight/2)/vo_dheight; sub_w = vo_dwidth; sub_h = vo_dheight; if(new_aspect > aspect)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?