vo_fbdev.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,205 行 · 第 1/3 页
C
1,205 行
if(pre_init_err == -2) { mp_msg(MSGT_VO, MSGL_ERR, "Internal fatal error: config() was called before preinit()\n"); return -1; } if (pre_init_err) return 1; if (fb_mode_name && !vm) { mp_msg(MSGT_VO, MSGL_ERR, "-fbmode can only be used with -vm\n"); return 1; } if (vm && (parse_fbmode_cfg(fb_mode_cfgfile) < 0)) return 1; if (d_width && (fs || vm)) { out_width = d_width; out_height = d_height; } else { out_width = width; out_height = height; } in_width = width; in_height = height; pixel_format = format; if (fb_mode_name) { if (!(fb_mode = find_mode_by_name(fb_mode_name))) { mp_msg(MSGT_VO, MSGL_ERR, "can't find requested video mode\n"); return 1; } fb_mode2fb_vinfo(fb_mode, &fb_vinfo); } else if (vm) { monitor_hfreq = str2range(monitor_hfreq_str); monitor_vfreq = str2range(monitor_vfreq_str); monitor_dotclock = str2range(monitor_dotclock_str); if (!monitor_hfreq || !monitor_vfreq || !monitor_dotclock) { mp_msg(MSGT_VO, MSGL_ERR, "you have to specify the capabilities of" " the monitor.\n"); return 1; } if (!(fb_mode = find_best_mode(out_width, out_height, monitor_hfreq, monitor_vfreq, monitor_dotclock))) { mp_msg(MSGT_VO, MSGL_ERR, "can't find best video mode\n"); return 1; } mp_msg(MSGT_VO, MSGL_V, "using mode %dx%d @ %.1fHz\n", fb_mode->xres, fb_mode->yres, vsf(fb_mode)); fb_mode2fb_vinfo(fb_mode, &fb_vinfo); } fb_bpp_we_want = fb_bpp; set_bpp(&fb_vinfo, fb_bpp); fb_vinfo.xres_virtual = fb_vinfo.xres; fb_vinfo.yres_virtual = fb_vinfo.yres; if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) { mp_msg(MSGT_VO, MSGL_V, "Can't set graphics mode: %s\n", strerror(errno)); close(fb_tty_fd); fb_tty_fd = -1; } if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) { mp_msg(MSGT_VO, MSGL_ERR, "Can't put VSCREENINFO: %s\n", strerror(errno)); if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) { mp_msg(MSGT_VO, MSGL_ERR, "Can't restore text mode: %s\n", strerror(errno)); } return 1; } fb_pixel_size = fb_vinfo.bits_per_pixel / 8; fb_bpp = fb_vinfo.red.length + fb_vinfo.green.length + fb_vinfo.blue.length + fb_vinfo.transp.length; if (fb_bpp_we_want != fb_bpp) mp_msg(MSGT_VO, MSGL_WARN, "requested %d bpp, got %d bpp!!!\n", fb_bpp_we_want, fb_bpp); switch (fb_bpp) { case 32: draw_alpha_p = vo_draw_alpha_rgb32; break; case 24: draw_alpha_p = vo_draw_alpha_rgb24; break; case 16: draw_alpha_p = vo_draw_alpha_rgb16; break; case 15: draw_alpha_p = vo_draw_alpha_rgb15; break; default: return 1; } fb_xres = fb_vinfo.xres; fb_yres = fb_vinfo.yres; if (vm || fs) { out_width = fb_xres; out_height = fb_yres; } if (out_width < in_width || out_height < in_height) { mp_msg(MSGT_VO, MSGL_ERR, "screensize is smaller than video size\n"); return 1; } first_row = (out_height - in_height) / 2; last_row = (out_height + in_height) / 2; if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { mp_msg(MSGT_VO, MSGL_ERR, "Can't get FSCREENINFO: %s\n", strerror(errno)); return 1; } lots_of_printf(); if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) { mp_msg(MSGT_VO, MSGL_ERR, "type %d not supported\n", fb_finfo.type); return 1; } switch (fb_finfo.visual) { case FB_VISUAL_TRUECOLOR: break; case FB_VISUAL_DIRECTCOLOR: mp_msg(MSGT_VO, MSGL_V, "creating cmap for directcolor\n"); if (ioctl(fb_dev_fd, FBIOGETCMAP, &fb_oldcmap)) { mp_msg(MSGT_VO, MSGL_ERR, "can't get cmap: %s\n", strerror(errno)); return 1; } if (!(cmap = make_directcolor_cmap(&fb_vinfo))) return 1; if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) { mp_msg(MSGT_VO, MSGL_ERR, "can't put cmap: %s\n", strerror(errno)); return 1; } fb_cmap_changed = 1; free(cmap->red); free(cmap->green); free(cmap->blue); free(cmap); break; default: mp_msg(MSGT_VO, MSGL_ERR, "visual: %d not yet supported\n", fb_finfo.visual); return 1; } fb_line_len = fb_finfo.line_length; fb_size = fb_finfo.smem_len; frame_buffer = NULL;#ifdef CONFIG_VIDIX if(vidix_name) { unsigned image_width,image_height,x_offset,y_offset; if(zoom || fs){ aspect_save_orig(width,height); aspect_save_prescale(d_width,d_height); aspect_save_screenres(fb_xres,fb_yres); aspect(&image_width,&image_height,fs ? A_ZOOM : A_NOZOOM); } else { image_width=width; image_height=height; } if(fb_xres > image_width) x_offset = (fb_xres - image_width) / 2; else x_offset = 0; if(fb_yres > image_height) y_offset = (fb_yres - image_height) / 2; else y_offset = 0; if(vidix_init(width,height,x_offset,y_offset,image_width, image_height,format,fb_bpp, fb_xres,fb_yres) != 0) { mp_msg(MSGT_VO, MSGL_ERR, "Can't initialize VIDIX driver\n"); vidix_name = NULL; vidix_term(); return -1; } else mp_msg(MSGT_VO, MSGL_V, "Using VIDIX\n"); vidix_start(); if (vidix_grkey_support()) { vidix_grkey_get(&gr_key); gr_key.key_op = KEYS_PUT; if (!(vo_colorkey & 0xff000000)) { gr_key.ckey.op = CKEY_TRUE; gr_key.ckey.red = (vo_colorkey & 0x00ff0000) >> 16; gr_key.ckey.green = (vo_colorkey & 0x0000ff00) >> 8; gr_key.ckey.blue = vo_colorkey & 0x000000ff; } else gr_key.ckey.op = CKEY_FALSE; vidix_grkey_set(&gr_key); } } else#endif { int x_offset=0,y_offset=0; if ((frame_buffer = (uint8_t *) mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev_fd, 0)) == (uint8_t *) -1) { mp_msg(MSGT_VO, MSGL_ERR, "Can't mmap %s: %s\n", fb_dev_name, strerror(errno)); return 1; } center = frame_buffer + ( (out_width - in_width) / 2 ) * fb_pixel_size + ( (out_height - in_height) / 2 ) * fb_line_len + x_offset * fb_pixel_size + y_offset * fb_line_len; mp_msg(MSGT_VO, MSGL_DBG2, "frame_buffer @ %p\n", frame_buffer); mp_msg(MSGT_VO, MSGL_DBG2, "center @ %p\n", center); mp_msg(MSGT_VO, MSGL_V, "pixel per line: %d\n", fb_line_len / fb_pixel_size); if (fs || vm) memset(frame_buffer, '\0', fb_line_len * fb_yres); } if (vt_doit && (vt_fd = open("/dev/tty", O_WRONLY)) == -1) { mp_msg(MSGT_VO, MSGL_ERR, "can't open /dev/tty: %s\n", strerror(errno)); vt_doit = 0; } if (vt_doit && !(vt_fp = fdopen(vt_fd, "w"))) { mp_msg(MSGT_VO, MSGL_ERR, "can't fdopen /dev/tty: %s\n", strerror(errno)); vt_doit = 0; } if (vt_doit) vt_set_textarea(last_row, fb_yres); return 0;}static int query_format(uint32_t format){ if (!fb_preinit(0)) return 0;#ifdef CONFIG_VIDIX if(vidix_name) return (vidix_query_fourcc(format));#endif if ((format & IMGFMT_BGR_MASK) == IMGFMT_BGR) { int bpp = format & 0xff; if (bpp == fb_bpp) return VFCAP_ACCEPT_STRIDE | VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; } return 0;}static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride){ unsigned char *dst; dst = center + fb_line_len * y0 + fb_pixel_size * x0; (*draw_alpha_p)(w, h, src, srca, stride, dst, fb_line_len);}static int draw_frame(uint8_t *src[]) { return 1; }static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y){ uint8_t *d; uint8_t *s; d = center + fb_line_len * y + fb_pixel_size * x; s = src[0]; while (h) { fast_memcpy(d, s, w * fb_pixel_size); d += fb_line_len; s += stride[0]; h--; } return 0;}static void check_events(void){}static void flip_page(void){}static void draw_osd(void){ vo_draw_text(in_width, in_height, draw_alpha);}static void uninit(void){ if (fb_cmap_changed) { if (ioctl(fb_dev_fd, FBIOPUTCMAP, &fb_oldcmap)) mp_msg(MSGT_VO, MSGL_WARN, "Can't restore original cmap\n"); fb_cmap_changed = 0; } if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) mp_msg(MSGT_VO, MSGL_WARN, "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); fb_orig_vinfo.xoffset = fb_vinfo.xoffset; fb_orig_vinfo.yoffset = fb_vinfo.yoffset; if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_orig_vinfo)) mp_msg(MSGT_VO, MSGL_WARN, "Can't reset original fb_var_screeninfo: %s\n", strerror(errno)); if (fb_tty_fd >= 0) { if (ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) mp_msg(MSGT_VO, MSGL_WARN, "Can't restore text mode: %s\n", strerror(errno)); } if (vt_doit) vt_set_textarea(0, fb_orig_vinfo.yres); close(fb_tty_fd); close(fb_dev_fd); if(frame_buffer) munmap(frame_buffer, fb_size); frame_buffer = NULL;#ifdef CONFIG_VIDIX if(vidix_name) vidix_term();#endif fb_preinit(1);}static int preinit(const char *vo_subdevice){ pre_init_err = 0; if(vo_subdevice) {#ifdef CONFIG_VIDIX if (memcmp(vo_subdevice, "vidix", 5) == 0) vidix_name = &vo_subdevice[5]; if(vidix_name) pre_init_err = vidix_preinit(vidix_name,&video_out_fbdev); else#endif { if (fb_dev_name) free(fb_dev_name); fb_dev_name = strdup(vo_subdevice); } } if(!pre_init_err) return (pre_init_err=(fb_preinit(0)?0:-1)); return(-1);}static uint32_t get_image(mp_image_t *mpi){ if ( !IMGFMT_IS_BGR(mpi->imgfmt) || (IMGFMT_BGR_DEPTH(mpi->imgfmt) != fb_bpp) || ((mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) || (mpi->flags & MP_IMGFLAG_PLANAR) || (mpi->flags & MP_IMGFLAG_YUV) || (mpi->width != in_width) || (mpi->height != in_height) ) return(VO_FALSE); mpi->planes[0] = center; mpi->stride[0] = fb_line_len; mpi->flags |= MP_IMGFLAG_DIRECT; return(VO_TRUE);}static int control(uint32_t request, void *data, ...){ switch (request) { case VOCTRL_GET_IMAGE: return get_image(data); case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); }#ifdef CONFIG_VIDIX if (vidix_name) { switch (request) { case VOCTRL_SET_EQUALIZER: { va_list ap; int value; va_start(ap, data); value = va_arg(ap, int); va_end(ap); return vidix_control(request, data, value); } case VOCTRL_GET_EQUALIZER: { va_list ap; int *value; va_start(ap, data); value = va_arg(ap, int*); va_end(ap); return vidix_control(request, data, value); } } }#endif return VO_NOTIMPL;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?