vo_fbdev.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,205 行 · 第 1/3 页
C
1,205 行
/* * Video driver for Framebuffer device * by Szabolcs Berecz <szabi@inf.elte.hu> * (C) 2001 * * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 * Some fixes and small improvements by Joey Parrish <joey@nicewarrior.org> */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <errno.h>#include <ctype.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/kd.h>#include <linux/fb.h>#include "config.h"#include "video_out.h"#include "video_out_internal.h"#include "fastmemcpy.h"#include "sub.h"#ifdef CONFIG_VIDIX#include "vosub_vidix.h"#endif#include "aspect.h"#include "mp_msg.h"static vo_info_t info = { "Framebuffer Device", "fbdev", "Szabolcs Berecz <szabi@inf.elte.hu>", ""};LIBVO_EXTERN(fbdev)#ifdef CONFIG_VIDIX/* Name of VIDIX driver */static const char *vidix_name = NULL;static vidix_grkey_t gr_key;#endifstatic signed int pre_init_err = -2;/******************************* fb.modes support *******************************/static range_t *monitor_hfreq = NULL;static range_t *monitor_vfreq = NULL;static range_t *monitor_dotclock = NULL;typedef struct { char *name; uint32_t xres, yres, vxres, vyres, depth; uint32_t pixclock, left, right, upper, lower, hslen, vslen; uint32_t sync; uint32_t vmode;} fb_mode_t;#define MAX_NR_TOKEN 16#define MAX_LINE_LEN 1000#define RET_EOF -1#define RET_EOL -2static int validate_mode(fb_mode_t *m){ if (!m->xres) { mp_msg(MSGT_VO, MSGL_V, "needs geometry "); return 0; } if (!m->pixclock) { mp_msg(MSGT_VO, MSGL_V, "needs timings "); return 0; } return 1;}static FILE *fp;static int line_num = 0;static char *line;static char *token[MAX_NR_TOKEN];static int get_token(int num){ static int read_nextline = 1; static int line_pos; int i; char c; if (num >= MAX_NR_TOKEN) { mp_msg(MSGT_VO, MSGL_V, "get_token(): max >= MAX_NR_TOKEN!\n"); goto out_eof; } if (read_nextline) { if (!fgets(line, MAX_LINE_LEN, fp)) goto out_eof; line_pos = 0; ++line_num; read_nextline = 0; } for (i = 0; i < num; i++) { while (isspace(line[line_pos])) ++line_pos; if (line[line_pos] == '\0' || line[line_pos] == '#') { read_nextline = 1; goto out_eol; } token[i] = line + line_pos; c = line[line_pos]; if (c == '"' || c == '\'') { token[i]++; while (line[++line_pos] != c && line[line_pos]) /* NOTHING */; if (!line[line_pos]) goto out_eol; line[line_pos] = ' '; } else { for (/* NOTHING */; !isspace(line[line_pos]) && line[line_pos]; line_pos++) /* NOTHING */; } if (!line[line_pos]) { read_nextline = 1; if (i == num - 1) goto out_ok; goto out_eol; } line[line_pos++] = '\0'; }out_ok: return i;out_eof: return RET_EOF;out_eol: return RET_EOL;}static fb_mode_t *fb_modes = NULL;static int nr_modes = 0;static int parse_fbmode_cfg(char *cfgfile){#define CHECK_IN_MODE_DEF\ if (!in_mode_def) {\ mp_msg(MSGT_VO, MSGL_V, "'needs 'mode' first");\ goto err_out_print_linenum;\ } fb_mode_t *mode = NULL; char *endptr; // strtoul()... int in_mode_def = 0; int tmp, i; /* If called more than once, reuse parsed data */ if (nr_modes) return nr_modes; mp_msg(MSGT_VO, MSGL_V, "Reading %s: ", cfgfile); if ((fp = fopen(cfgfile, "r")) == NULL) { mp_msg(MSGT_VO, MSGL_V, "can't open '%s': %s\n", cfgfile, strerror(errno)); return -1; } if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { mp_msg(MSGT_VO, MSGL_V, "can't get memory for 'line': %s\n", strerror(errno)); return -2; } /* * check if the cfgfile starts with 'mode' */ while ((tmp = get_token(1)) == RET_EOL) /* NOTHING */; if (tmp == RET_EOF) goto out; if (!strcmp(token[0], "mode")) goto loop_enter; goto err_out_parse_error; while ((tmp = get_token(1)) != RET_EOF) { if (tmp == RET_EOL) continue; if (!strcmp(token[0], "mode")) { if (in_mode_def) { mp_msg(MSGT_VO, MSGL_V, "'endmode' required"); goto err_out_print_linenum; } if (!validate_mode(mode)) goto err_out_not_valid; loop_enter: if (!(fb_modes = (fb_mode_t *) realloc(fb_modes, sizeof(fb_mode_t) * (nr_modes + 1)))) { mp_msg(MSGT_VO, MSGL_V, "can't realloc 'fb_modes' (nr_modes = %d):" " %s\n", nr_modes, strerror(errno)); goto err_out; } mode=fb_modes + nr_modes; ++nr_modes; memset(mode,0,sizeof(fb_mode_t)); if (get_token(1) < 0) goto err_out_parse_error; for (i = 0; i < nr_modes - 1; i++) { if (!strcmp(token[0], fb_modes[i].name)) { mp_msg(MSGT_VO, MSGL_V, "mode name '%s' isn't unique", token[0]); goto err_out_print_linenum; } } if (!(mode->name = strdup(token[0]))) { mp_msg(MSGT_VO, MSGL_V, "can't strdup -> 'name': %s\n", strerror(errno)); goto err_out; } in_mode_def = 1; } else if (!strcmp(token[0], "geometry")) { CHECK_IN_MODE_DEF; if (get_token(5) < 0) goto err_out_parse_error; mode->xres = strtoul(token[0], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->yres = strtoul(token[1], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->vxres = strtoul(token[2], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->vyres = strtoul(token[3], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->depth = strtoul(token[4], &endptr, 0); if (*endptr) goto err_out_parse_error; } else if (!strcmp(token[0], "timings")) { CHECK_IN_MODE_DEF; if (get_token(7) < 0) goto err_out_parse_error; mode->pixclock = strtoul(token[0], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->left = strtoul(token[1], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->right = strtoul(token[2], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->upper = strtoul(token[3], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->lower = strtoul(token[4], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->hslen = strtoul(token[5], &endptr, 0); if (*endptr) goto err_out_parse_error; mode->vslen = strtoul(token[6], &endptr, 0); if (*endptr) goto err_out_parse_error; } else if (!strcmp(token[0], "endmode")) { CHECK_IN_MODE_DEF; in_mode_def = 0; } else if (!strcmp(token[0], "accel")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; /* * it's only used for text acceleration * so we just ignore it. */ } else if (!strcmp(token[0], "hsync")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "low")) mode->sync &= ~FB_SYNC_HOR_HIGH_ACT; else if(!strcmp(token[0], "high")) mode->sync |= FB_SYNC_HOR_HIGH_ACT; else goto err_out_parse_error; } else if (!strcmp(token[0], "vsync")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "low")) mode->sync &= ~FB_SYNC_VERT_HIGH_ACT; else if(!strcmp(token[0], "high")) mode->sync |= FB_SYNC_VERT_HIGH_ACT; else goto err_out_parse_error; } else if (!strcmp(token[0], "csync")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "low")) mode->sync &= ~FB_SYNC_COMP_HIGH_ACT; else if(!strcmp(token[0], "high")) mode->sync |= FB_SYNC_COMP_HIGH_ACT; else goto err_out_parse_error; } else if (!strcmp(token[0], "extsync")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "false")) mode->sync &= ~FB_SYNC_EXT; else if(!strcmp(token[0], "true")) mode->sync |= FB_SYNC_EXT; else goto err_out_parse_error; } else if (!strcmp(token[0], "laced")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "false")) mode->vmode = FB_VMODE_NONINTERLACED; else if (!strcmp(token[0], "true")) mode->vmode = FB_VMODE_INTERLACED; else goto err_out_parse_error; } else if (!strcmp(token[0], "double")) { CHECK_IN_MODE_DEF; if (get_token(1) < 0) goto err_out_parse_error; if (!strcmp(token[0], "false")) ; else if (!strcmp(token[0], "true")) mode->vmode = FB_VMODE_DOUBLE; else goto err_out_parse_error; } else goto err_out_parse_error; } if (!validate_mode(mode)) goto err_out_not_valid;out: mp_msg(MSGT_VO, MSGL_V, "%d modes\n", nr_modes); free(line); fclose(fp); return nr_modes;err_out_parse_error: mp_msg(MSGT_VO, MSGL_V, "parse error");err_out_print_linenum: mp_msg(MSGT_VO, MSGL_V, " at line %d\n", line_num);err_out: if (fb_modes) { free(fb_modes); fb_modes = NULL; } nr_modes = 0; free(line); free(fp); return -2;err_out_not_valid: mp_msg(MSGT_VO, MSGL_V, "previous mode is not correct"); goto err_out_print_linenum;}static fb_mode_t *find_mode_by_name(char *name){ int i; for (i = 0; i < nr_modes; i++) if (!strcmp(name, fb_modes[i].name)) return fb_modes + i; return NULL;}static float dcf(fb_mode_t *m) //driving clock frequency{ return 1e12f / m->pixclock;}static float hsf(fb_mode_t *m) //horizontal scan frequency{ int htotal = m->left + m->xres + m->right + m->hslen; return dcf(m) / htotal;}static float vsf(fb_mode_t *m) //vertical scan frequency{ int vtotal = m->upper + m->yres + m->lower + m->vslen; return hsf(m) / vtotal;}static int mode_works(fb_mode_t *m, range_t *hfreq, range_t *vfreq, range_t *dotclock){ float h = hsf(m); float v = vsf(m); float d = dcf(m); int ret = 1; mp_msg(MSGT_VO, MSGL_DBG2, "mode %dx%d:", m->xres, m->yres); if (!in_range(hfreq, h)) { ret = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?