mirror of
https://github.com/mpv-player/mpv
synced 2025-01-09 01:36:25 +01:00
General Timing Formula algorithm from a scratch.
vo_vesa.c so now adjust the timing to highest possible refresh rate using the monitor capabilities from a config file. patch by Rudolf Marek <MAREKR2@cs.felk.cvut.cz> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7070 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
0e6edc2840
commit
4ae1571dda
@ -6,13 +6,16 @@
|
||||
|
||||
extern int use_stdin;
|
||||
|
||||
#if defined(HAVE_FBDEV)||defined(HAVE_VESA)
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FBDEV
|
||||
extern char *fb_dev_name;
|
||||
extern char *fb_mode_cfgfile;
|
||||
extern char *fb_mode_name;
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
#else
|
||||
#ifdef HAVE_DIRECTFB
|
||||
extern char *fb_dev_name;
|
||||
|
@ -3,7 +3,7 @@ include config.mak
|
||||
|
||||
LIBNAME = libvo.a
|
||||
|
||||
SRCS=aspect.c aclib.c osd.c font_load.c spuenc.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c vo_yuv4mpeg.c $(OPTIONAL_SRCS) sub.c
|
||||
SRCS=aspect.c aclib.c osd.c font_load.c gtf.c spuenc.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c vo_yuv4mpeg.c $(OPTIONAL_SRCS) sub.c
|
||||
OBJS=$(SRCS:.c=.o)
|
||||
|
||||
ifeq ($(VIDIX),yes)
|
||||
|
297
libvo/gtf.c
Normal file
297
libvo/gtf.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (C) Rudolf Marek <r.marek@sh.cvut.cz> - Aug 2002
|
||||
*
|
||||
* You can redistribute this file under terms and conditions
|
||||
* of GNU General Public licence v2.
|
||||
*
|
||||
* GTF calculations formulas are taken from GTF_V1R1.xls
|
||||
* created by ANDY.MORRISH@NSC.COM
|
||||
*/
|
||||
|
||||
//Version 0.4
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "gtf.h"
|
||||
|
||||
#undef GTF_DEBUG
|
||||
|
||||
#ifdef GTF_DEBUG
|
||||
#define DEBUG_PRINTF(a,b) printf(a,b);
|
||||
#else
|
||||
#define DEBUG_PRINTF(a,b)
|
||||
#endif
|
||||
|
||||
static GTF_constants GTF_given_constants = { 3.0,550.0,1,8,1.8,8,40,20,128,600 };
|
||||
|
||||
static double round(double v)
|
||||
{
|
||||
return floor(v + 0.5);
|
||||
}
|
||||
|
||||
static void GetRoundedConstants(GTF_constants *c)
|
||||
{
|
||||
c->Vsync_need = round(GTF_given_constants.Vsync_need);
|
||||
c->min_Vsync_BP = GTF_given_constants.min_Vsync_BP;
|
||||
c->min_front_porch = round(GTF_given_constants.min_front_porch);
|
||||
c->char_cell_granularity = GTF_given_constants.char_cell_granularity;
|
||||
c->margin_width = GTF_given_constants.margin_width;
|
||||
c->sync_width = GTF_given_constants.sync_width;
|
||||
c->c = ((GTF_given_constants.c - GTF_given_constants.j)*(GTF_given_constants.k / 256)) + GTF_given_constants.j;
|
||||
c->j = GTF_given_constants.j;
|
||||
c->k = GTF_given_constants.k;
|
||||
c->m = (GTF_given_constants.k / 256) * GTF_given_constants.m;
|
||||
}
|
||||
|
||||
void GTF_calcTimings(double X,double Y,double freq, int type,
|
||||
int want_margins, int want_interlace,struct VesaCRTCInfoBlock *result )
|
||||
{
|
||||
GTF_constants c;
|
||||
double RR, margin_top, margin_bottom, margin_left, margin_right;
|
||||
double estimated_H_period,sync_plus_BP,BP,interlace,V_total_lines_field;
|
||||
double estimated_V_field_rate,actual_H_period,actual_V_field_freq;
|
||||
double total_active_pixels, ideal_duty_cycle, blanking_time, H_total_pixels;
|
||||
double H_freq, pixel_freq,actual_V_frame_freq;
|
||||
double H_sync_start, H_sync_end, H_back_porch, H_front_porch, H_sync_width;
|
||||
double V_back_porch, V_front_porch, V_sync_start, V_sync_end,V_sync_width;
|
||||
double ideal_H_period;
|
||||
GetRoundedConstants(&c);
|
||||
|
||||
|
||||
pixel_freq = RR = freq;
|
||||
|
||||
/* DETERMINE IF 1/2 LINE INTERLACE IS PRESENT */
|
||||
|
||||
interlace = 0;
|
||||
|
||||
if (want_interlace) {
|
||||
RR = RR * 2;
|
||||
Y=Y/2;
|
||||
interlace = 0.5;
|
||||
}
|
||||
|
||||
result->Flags = 0;
|
||||
|
||||
if ((Y==300)||(Y==200)||(Y==240))
|
||||
{
|
||||
Y*=2;
|
||||
result->Flags = VESA_CRTC_DOUBLESCAN; /* TODO: check if mode support */
|
||||
}
|
||||
|
||||
/* DETERMINE NUMBER OF LINES IN V MARGIN */
|
||||
/* DETERMINE NUMBER OF PIXELS IN H MARGIN [pixels] */
|
||||
|
||||
margin_left = margin_right = 0;
|
||||
margin_top = margin_bottom = 0;
|
||||
|
||||
if (want_margins) {
|
||||
margin_top = margin_bottom = (c.margin_width / 100) * Y;
|
||||
margin_left = round(( X* c.margin_width/100)/c.char_cell_granularity) \
|
||||
* c.char_cell_granularity;
|
||||
margin_right = margin_left;
|
||||
DEBUG_PRINTF("margin_left_right : %f\n",margin_right)
|
||||
DEBUG_PRINTF("margin_top_bottom : %f\n",margin_top)
|
||||
}
|
||||
|
||||
/* FIND TOTAL NUMBER OF ACTIVE PIXELS (IMAGE + MARGIN) [pixels] */
|
||||
|
||||
total_active_pixels = margin_left + margin_right + X;
|
||||
DEBUG_PRINTF("total_active_pixels: %f\n",total_active_pixels)
|
||||
|
||||
if (type == GTF_PF)
|
||||
{
|
||||
ideal_H_period = ((c.c-100)+(sqrt(((100-c.c)*(100-c.c) )+(0.4*c.m*(total_active_pixels + margin_left + margin_right) / freq))))/2/c.m*1000;
|
||||
|
||||
DEBUG_PRINTF("ideal_H_period: %f\n",ideal_H_period)
|
||||
|
||||
/* FIND IDEAL BLANKING DUTY CYCLE FROM FORMULA [%] */
|
||||
ideal_duty_cycle = c.c - (c.m * ideal_H_period /1000);
|
||||
DEBUG_PRINTF("ideal_duty_cycle: %f\n",ideal_duty_cycle)
|
||||
|
||||
/* FIND BLANKING TIME (TO NEAREST CHAR CELL) [pixels] */
|
||||
|
||||
blanking_time = round(total_active_pixels * ideal_duty_cycle \
|
||||
/ (100-ideal_duty_cycle) / (2*c.char_cell_granularity)) \
|
||||
* (2*c.char_cell_granularity);
|
||||
DEBUG_PRINTF("blanking_time : %f\n",blanking_time )
|
||||
|
||||
/* FIND TOTAL NUMBER OF PIXELS IN A LINE [pixels] */
|
||||
H_total_pixels = total_active_pixels + blanking_time ;
|
||||
DEBUG_PRINTF("H_total_pixels: %f\n",H_total_pixels)
|
||||
H_freq = freq / H_total_pixels * 1000;
|
||||
DEBUG_PRINTF("H_freq: %f\n",H_freq)
|
||||
actual_H_period = 1000 / H_freq;
|
||||
DEBUG_PRINTF("actual_H_period: %f\n",actual_H_period)
|
||||
sync_plus_BP = round(H_freq * c.min_Vsync_BP/1000);
|
||||
// sync_plus_BP = round( freq / H_total_pixels * c.min_Vsync_BP);
|
||||
|
||||
DEBUG_PRINTF("sync_plus_BP: %f\n",sync_plus_BP)
|
||||
|
||||
} else if (type == GTF_VF)
|
||||
{
|
||||
|
||||
/* ESTIMATE HORIZ. PERIOD [us] */
|
||||
|
||||
estimated_H_period = (( 1/RR ) - c.min_Vsync_BP/1000000 ) / (Y + (2 * margin_top) + c.min_front_porch + interlace) * 1000000;
|
||||
|
||||
DEBUG_PRINTF("estimated_H_period: %f\n",estimated_H_period)
|
||||
|
||||
/* FIND NUMBER OF LINES IN (SYNC + BACK PORCH) [lines] */
|
||||
|
||||
sync_plus_BP = round( c.min_Vsync_BP / estimated_H_period );
|
||||
DEBUG_PRINTF("sync_plus_BP: %f\n",sync_plus_BP)
|
||||
|
||||
} else if (type == GTF_HF)
|
||||
{
|
||||
sync_plus_BP = round(freq * c.min_Vsync_BP/1000);
|
||||
DEBUG_PRINTF("sync_plus_BP: %f\n",sync_plus_BP)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FIND TOTAL NUMBER OF LINES IN VERTICAL FIELD */
|
||||
|
||||
V_total_lines_field = sync_plus_BP+interlace+margin_bottom+margin_top+Y+c.min_front_porch;
|
||||
DEBUG_PRINTF("V_total_lines_field : %f\n",V_total_lines_field )
|
||||
|
||||
if (type == GTF_VF)
|
||||
{
|
||||
/* ESTIMATE VERTICAL FIELD RATE [hz] */
|
||||
|
||||
estimated_V_field_rate = 1 / estimated_H_period / V_total_lines_field * 1000000;
|
||||
DEBUG_PRINTF(" estimated_V_field_rate: %f\n", estimated_V_field_rate)
|
||||
/* FIND ACTUAL HORIZONTAL PERIOD [us] */
|
||||
|
||||
actual_H_period = estimated_H_period / (RR / estimated_V_field_rate);
|
||||
DEBUG_PRINTF("actual_H_period: %f\n",actual_H_period)
|
||||
/* FIND ACTUAL VERTICAL FIELD FREQUENCY [Hz] */
|
||||
|
||||
actual_V_field_freq = 1 / actual_H_period / V_total_lines_field * 1000000;
|
||||
DEBUG_PRINTF("actual_V_field_freq: %f\n",actual_V_field_freq)
|
||||
|
||||
/* FIND IDEAL BLANKING DUTY CYCLE FROM FORMULA [%] */
|
||||
ideal_duty_cycle = c.c - (c.m * actual_H_period /1000);
|
||||
DEBUG_PRINTF("ideal_duty_cycle: %f\n",ideal_duty_cycle)
|
||||
//if (type == GTF_VF)
|
||||
//{
|
||||
//moved
|
||||
//}
|
||||
} else if (type == GTF_HF)
|
||||
{
|
||||
/* FIND IDEAL BLANKING DUTY CYCLE FROM FORMULA [%] */
|
||||
ideal_duty_cycle = c.c - (c.m / freq);
|
||||
DEBUG_PRINTF("ideal_duty_cycle: %f\n",ideal_duty_cycle)
|
||||
}
|
||||
|
||||
/* FIND BLANKING TIME (TO NEAREST CHAR CELL) [pixels] */
|
||||
|
||||
if (!(type == GTF_PF))
|
||||
{
|
||||
blanking_time = round(total_active_pixels * ideal_duty_cycle \
|
||||
/ (100-ideal_duty_cycle) / (2*c.char_cell_granularity)) \
|
||||
* (2*c.char_cell_granularity);
|
||||
DEBUG_PRINTF("blanking_time : %f\n",blanking_time )
|
||||
}
|
||||
else
|
||||
// if (type == GTF_PF)
|
||||
{
|
||||
actual_V_field_freq = H_freq / V_total_lines_field * 1000;
|
||||
}
|
||||
|
||||
if (type == GTF_HF)
|
||||
{
|
||||
/* Hz */
|
||||
actual_V_field_freq = freq / V_total_lines_field * 1000;
|
||||
DEBUG_PRINTF("actual_V_field_freq: %f\n",actual_V_field_freq)
|
||||
}
|
||||
|
||||
|
||||
actual_V_frame_freq = actual_V_field_freq;
|
||||
|
||||
/* FIND ACTUAL VERTICAL FRAME FREQUENCY [Hz]*/
|
||||
|
||||
if (want_interlace) actual_V_frame_freq = actual_V_field_freq / 2;
|
||||
DEBUG_PRINTF("actual_V_frame_freq: %f\n",actual_V_frame_freq)
|
||||
|
||||
// V_freq = actual_V_frame_freq;
|
||||
// DEBUG_PRINTF("V_freq %f\n",V_freq)
|
||||
|
||||
|
||||
if (!(type == GTF_PF))
|
||||
{
|
||||
/* FIND TOTAL NUMBER OF PIXELS IN A LINE [pixels] */
|
||||
H_total_pixels = total_active_pixels + blanking_time ;
|
||||
DEBUG_PRINTF("H_total_pixels: %f\n",H_total_pixels)
|
||||
if (type == GTF_VF)
|
||||
{
|
||||
/* FIND PIXEL FREQUENCY [Mhz] */
|
||||
pixel_freq = H_total_pixels / actual_H_period ;
|
||||
DEBUG_PRINTF("pixel_freq: %f\n",pixel_freq)
|
||||
} else if (type == GTF_HF)
|
||||
{
|
||||
/* FIND PIXEL FREQUENCY [Mhz] */
|
||||
pixel_freq = H_total_pixels * freq / 1000 ;
|
||||
DEBUG_PRINTF("pixel_freq: %f\n",pixel_freq)
|
||||
actual_H_period = 1000/freq;
|
||||
}
|
||||
|
||||
/* FIND ACTUAL HORIZONTAL FREQUENCY [KHz] */
|
||||
|
||||
H_freq = 1000 / actual_H_period;
|
||||
DEBUG_PRINTF("H_freq %f\n",H_freq)
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* FIND NUMBER OF LINES IN BACK PORCH [lines] */
|
||||
|
||||
BP = sync_plus_BP - c.Vsync_need;
|
||||
DEBUG_PRINTF("BP: %f\n",BP)
|
||||
|
||||
/*------------------------------------------------------------------------------------------------*/
|
||||
/* FIND H SYNC WIDTH (TO NEAREST CHAR CELL) */
|
||||
H_sync_width = round(c.sync_width/100*H_total_pixels/c.char_cell_granularity)*c.char_cell_granularity;
|
||||
DEBUG_PRINTF("H_sync_width %f\n",H_sync_width)
|
||||
|
||||
/* FIND FRONT H PORCH(TO NEAREST CHAR CELL) */
|
||||
H_front_porch = (blanking_time/2) - H_sync_width;
|
||||
DEBUG_PRINTF("H_front_porch %f\n",H_front_porch)
|
||||
/* FIND BACK H PORCH(TO NEAREST CHAR CELL) */
|
||||
H_back_porch = H_sync_width + H_front_porch;
|
||||
DEBUG_PRINTF("H_back_porch%f\n",H_back_porch)
|
||||
|
||||
H_sync_start = H_total_pixels - (H_sync_width + H_back_porch);
|
||||
DEBUG_PRINTF("H_sync_start %f\n",H_sync_start)
|
||||
H_sync_end = H_total_pixels - H_back_porch;
|
||||
DEBUG_PRINTF("H_sync_end %f\n",H_sync_end)
|
||||
|
||||
V_back_porch = interlace + BP;
|
||||
DEBUG_PRINTF("V_back_porch%f\n",V_back_porch)
|
||||
V_front_porch = interlace + c.min_front_porch;
|
||||
DEBUG_PRINTF("V_front_porch%f\n",V_front_porch)
|
||||
|
||||
V_sync_width = c.Vsync_need;
|
||||
V_sync_start = V_total_lines_field - (V_sync_width + V_back_porch);
|
||||
DEBUG_PRINTF("V_sync_start %f\n",V_sync_start)
|
||||
V_sync_end = V_total_lines_field - V_back_porch;
|
||||
DEBUG_PRINTF("V_sync_end %f\n",V_sync_end)
|
||||
|
||||
result->hTotal = H_total_pixels;
|
||||
result-> hSyncStart = H_sync_start; /* Horizontal sync start in pixels */
|
||||
result-> hSyncEnd = H_sync_end; /* Horizontal sync end in pixels */
|
||||
result-> vTotal= V_total_lines_field; /* Vertical total in lines */
|
||||
result-> vSyncStart = V_sync_start; /* Vertical sync start in lines */
|
||||
result-> vSyncEnd = V_sync_end; /* Vertical sync end in lines */
|
||||
result-> Flags = (result->Flags)|VESA_CRTC_HSYNC_NEG; /* Flags (Interlaced, Double Scan etc) */
|
||||
|
||||
if (want_interlace)
|
||||
{
|
||||
result->Flags = (result->Flags) | VESA_CRTC_INTERLACED;
|
||||
}
|
||||
|
||||
result-> PixelClock = pixel_freq*1000000; /* Pixel clock in units of Hz */
|
||||
result-> RefreshRate = actual_V_frame_freq*100;/* Refresh rate in units of 0.01 Hz*/
|
||||
|
||||
}
|
||||
|
||||
|
48
libvo/gtf.h
Normal file
48
libvo/gtf.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __GTF_H
|
||||
#define __GTF_H
|
||||
|
||||
#include "linux/vbelib.h"
|
||||
|
||||
#define GTF_VF 0
|
||||
#define GTF_HF 1
|
||||
#define GTF_PF 2
|
||||
|
||||
|
||||
typedef struct {
|
||||
double Vsync_need; /* Number of lines for vert sync (default 3) */
|
||||
double min_Vsync_BP; /* Minimum vertical sync + back porch (us) (default 550)*/
|
||||
double min_front_porch; /* Minimum front porch in lines (default 1) */
|
||||
double char_cell_granularity; /* Character cell granularity in pixels (default 8) */
|
||||
double margin_width; /* Top/ bottom MARGIN size as % of height (%) (default 1.8) */
|
||||
double sync_width; /* Sync width percent of line period ( default 8) */
|
||||
double c; /* Blanking formula offset (default 40)*/
|
||||
double j; /* Blanking formula scaling factor weight (default 20)*/
|
||||
double k; /* Blanking formula scaling factor (default 128)*/
|
||||
double m; /* Blanking formula gradient (default 600)*/
|
||||
} GTF_constants;
|
||||
|
||||
//#ifndef __VESA_VBELIB_INCLUDED__
|
||||
// struct VesaCRTCInfoBlock {
|
||||
// unsigned short hTotal; /* Horizontal total in pixels */
|
||||
// unsigned short hSyncStart; /* Horizontal sync start in pixels */
|
||||
// unsigned short hSyncEnd; /* Horizontal sync end in pixels */
|
||||
// unsigned short vTotal; /* Vertical total in lines */
|
||||
// unsigned short vSyncStart; /* Vertical sync start in lines */
|
||||
// unsigned short vSyncEnd; /* Vertical sync end in lines */
|
||||
// unsigned char Flags; /* Flags (Interlaced, Double Scan etc) */
|
||||
// unsigned long PixelClock; /* Pixel clock in units of Hz */
|
||||
// unsigned short RefreshRate;/* Refresh rate in units of 0.01 Hz*/
|
||||
// unsigned char Reserved[40];/* remainder of CRTCInfoBlock*/
|
||||
//}__attribute__ ((packed));
|
||||
|
||||
//#define VESA_CRTC_DOUBLESCAN 0x01
|
||||
//#define VESA_CRTC_INTERLACED 0x02
|
||||
//#define VESA_CRTC_HSYNC_NEG 0x04
|
||||
//#define VESA_CRTC_VSYNC_NEG 0x08
|
||||
|
||||
//#endif
|
||||
|
||||
void GTF_calcTimings(double X,double Y,double freq, int type,
|
||||
int want_margins, int want_interlace,struct VesaCRTCInfoBlock *result);
|
||||
|
||||
#endif
|
@ -201,3 +201,85 @@ void libvo_register_options(void* cfg) {
|
||||
vo_dxr2_register_options(cfg);
|
||||
#endif
|
||||
}
|
||||
#if defined(HAVE_FBDEV)||defined(HAVE_VESA)
|
||||
/* Borrowed from vo_fbdev.c
|
||||
Monitor ranges related functions*/
|
||||
|
||||
char *monitor_hfreq_str = NULL;
|
||||
char *monitor_vfreq_str = NULL;
|
||||
char *monitor_dotclock_str = NULL;
|
||||
|
||||
float range_max(range_t *r)
|
||||
{
|
||||
float max = 0;
|
||||
|
||||
for (/* NOTHING */; (r->min != -1 && r->max != -1); r++)
|
||||
if (max < r->max) max = r->max;
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
int in_range(range_t *r, float f)
|
||||
{
|
||||
for (/* NOTHING */; (r->min != -1 && r->max != -1); r++)
|
||||
if (f >= r->min && f <= r->max)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
range_t *str2range(char *s)
|
||||
{
|
||||
float tmp_min, tmp_max;
|
||||
char *endptr = s; // to start the loop
|
||||
range_t *r = NULL;
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
for (i = 0; *endptr; i++) {
|
||||
if (*s == ',')
|
||||
goto out_err;
|
||||
if (!(r = (range_t *) realloc(r, sizeof(*r) * (i + 2)))) {
|
||||
printf("can't realloc 'r'\n");
|
||||
return NULL;
|
||||
}
|
||||
tmp_min = strtod(s, &endptr);
|
||||
if (*endptr == 'k' || *endptr == 'K') {
|
||||
tmp_min *= 1000.0;
|
||||
endptr++;
|
||||
} else if (*endptr == 'm' || *endptr == 'M') {
|
||||
tmp_min *= 1000000.0;
|
||||
endptr++;
|
||||
}
|
||||
if (*endptr == '-') {
|
||||
tmp_max = strtod(endptr + 1, &endptr);
|
||||
if (*endptr == 'k' || *endptr == 'K') {
|
||||
tmp_max *= 1000.0;
|
||||
endptr++;
|
||||
} else if (*endptr == 'm' || *endptr == 'M') {
|
||||
tmp_max *= 1000000.0;
|
||||
endptr++;
|
||||
}
|
||||
if (*endptr != ',' && *endptr)
|
||||
goto out_err;
|
||||
} else if (*endptr == ',' || !*endptr) {
|
||||
tmp_max = tmp_min;
|
||||
} else
|
||||
goto out_err;
|
||||
r[i].min = tmp_min;
|
||||
r[i].max = tmp_max;
|
||||
if (r[i].min < 0 || r[i].max < 0)
|
||||
goto out_err;
|
||||
s = endptr + 1;
|
||||
}
|
||||
r[i].min = r[i].max = -1;
|
||||
return r;
|
||||
out_err:
|
||||
if (r)
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Borrowed from vo_fbdev.c END */
|
||||
#endif
|
||||
|
||||
|
@ -241,4 +241,20 @@ extern float vo_fps;
|
||||
|
||||
extern char *vo_subdevice;
|
||||
|
||||
#if defined(HAVE_FBDEV)||defined(HAVE_VESA)
|
||||
|
||||
typedef struct {
|
||||
float min;
|
||||
float max;
|
||||
} range_t;
|
||||
|
||||
extern float range_max(range_t *r);
|
||||
extern int in_range(range_t *r, float f);
|
||||
extern range_t *str2range(char *s);
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -57,6 +57,14 @@ static signed int pre_init_err = -2;
|
||||
* fb.modes support *
|
||||
******************************/
|
||||
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
|
||||
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;
|
||||
@ -396,18 +404,6 @@ static float vsf(fb_mode_t *m) //vertical scan frequency
|
||||
return hsf(m) / vtotal;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float min;
|
||||
float max;
|
||||
} range_t;
|
||||
|
||||
static int in_range(range_t *r, float f)
|
||||
{
|
||||
for (/* NOTHING */; (r->min != -1 && r->max != -1); r++)
|
||||
if (f >= r->min && f <= r->max)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mode_works(fb_mode_t *m, range_t *hfreq, range_t *vfreq,
|
||||
range_t *dotclock)
|
||||
@ -558,58 +554,6 @@ static void fb_mode2fb_vinfo(fb_mode_t *m, struct fb_var_screeninfo *v)
|
||||
v->vmode = m->vmode;
|
||||
}
|
||||
|
||||
static range_t *str2range(char *s)
|
||||
{
|
||||
float tmp_min, tmp_max;
|
||||
char *endptr = s; // to start the loop
|
||||
range_t *r = NULL;
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
for (i = 0; *endptr; i++) {
|
||||
if (*s == ',')
|
||||
goto out_err;
|
||||
if (!(r = (range_t *) realloc(r, sizeof(*r) * (i + 2)))) {
|
||||
printf("can't realloc 'r'\n");
|
||||
return NULL;
|
||||
}
|
||||
tmp_min = strtod(s, &endptr);
|
||||
if (*endptr == 'k' || *endptr == 'K') {
|
||||
tmp_min *= 1000.0;
|
||||
endptr++;
|
||||
} else if (*endptr == 'm' || *endptr == 'M') {
|
||||
tmp_min *= 1000000.0;
|
||||
endptr++;
|
||||
}
|
||||
if (*endptr == '-') {
|
||||
tmp_max = strtod(endptr + 1, &endptr);
|
||||
if (*endptr == 'k' || *endptr == 'K') {
|
||||
tmp_max *= 1000.0;
|
||||
endptr++;
|
||||
} else if (*endptr == 'm' || *endptr == 'M') {
|
||||
tmp_max *= 1000000.0;
|
||||
endptr++;
|
||||
}
|
||||
if (*endptr != ',' && *endptr)
|
||||
goto out_err;
|
||||
} else if (*endptr == ',' || !*endptr) {
|
||||
tmp_max = tmp_min;
|
||||
} else
|
||||
goto out_err;
|
||||
r[i].min = tmp_min;
|
||||
r[i].max = tmp_max;
|
||||
if (r[i].min < 0 || r[i].max < 0)
|
||||
goto out_err;
|
||||
s = endptr + 1;
|
||||
}
|
||||
r[i].min = r[i].max = -1;
|
||||
return r;
|
||||
out_err:
|
||||
if (r)
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* vo_fbdev *
|
||||
@ -619,14 +563,7 @@ out_err:
|
||||
char *fb_dev_name = NULL;
|
||||
char *fb_mode_cfgfile = "/etc/fb.modes";
|
||||
char *fb_mode_name = NULL;
|
||||
char *monitor_hfreq_str = NULL;
|
||||
char *monitor_vfreq_str = NULL;
|
||||
char *monitor_dotclock_str = NULL;
|
||||
|
||||
/* fb.modes related variables */
|
||||
static range_t *monitor_hfreq = NULL;
|
||||
static range_t *monitor_vfreq = NULL;
|
||||
static range_t *monitor_dotclock = NULL;
|
||||
static fb_mode_t *fb_mode = NULL;
|
||||
|
||||
/* vt related variables */
|
||||
|
@ -16,7 +16,7 @@
|
||||
- refresh rate support (need additional info from mplayer)
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "gtf.h"
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
@ -54,6 +54,10 @@ extern vo_functions_t video_out_png;
|
||||
|
||||
extern int verbose;
|
||||
|
||||
extern char *monitor_hfreq_str;
|
||||
extern char *monitor_vfreq_str;
|
||||
extern char *monitor_dotclock_str;
|
||||
|
||||
#define MAX_BUFFERS 3
|
||||
|
||||
#ifndef max
|
||||
@ -523,18 +527,69 @@ unsigned fillMultiBuffer( unsigned long vsize, unsigned nbuffs )
|
||||
return i;
|
||||
}
|
||||
|
||||
static int set_refresh(unsigned x, unsigned y, unsigned mode,struct VesaCRTCInfoBlock *crtc_pass)
|
||||
{
|
||||
unsigned pixclk;
|
||||
float H_freq;
|
||||
|
||||
range_t *monitor_hfreq = NULL;
|
||||
range_t *monitor_vfreq = NULL;
|
||||
range_t *monitor_dotclock = NULL;
|
||||
|
||||
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) {
|
||||
printf("vo_vesa: you have to specify the capabilities of"
|
||||
" the monitor. Not changing refresh rate.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
H_freq = range_max(monitor_hfreq)/1000;
|
||||
|
||||
// printf("H_freq MAX %f\n",H_freq);
|
||||
|
||||
do
|
||||
{
|
||||
H_freq -= 0.1;
|
||||
GTF_calcTimings(x,y,H_freq,GTF_HF,0, 0,crtc_pass);
|
||||
// printf("PixelCLK %d\n",(unsigned)crtc_pass->PixelClock);
|
||||
}
|
||||
while (!in_range(monitor_vfreq,crtc_pass->RefreshRate/100));
|
||||
|
||||
pixclk = crtc_pass->PixelClock;
|
||||
// printf("PIXclk before %d\n",pixclk);
|
||||
vbeGetPixelClock(&mode,&pixclk);
|
||||
// printf("PIXclk after %d\n",pixclk);
|
||||
GTF_calcTimings(x,y,pixclk/1000000,GTF_PF,0,0,crtc_pass);
|
||||
// printf("Flags: %x\n",(unsigned) crtc_pass->Flags);
|
||||
/*
|
||||
printf("hTotal %d\n",crtc_pass->hTotal);
|
||||
printf("hSyncStart %d\n",crtc_pass->hSyncStart);
|
||||
printf("hSyncEnd %d\n",crtc_pass->hSyncEnd);
|
||||
|
||||
printf("vTotal %d\n",crtc_pass->vTotal);
|
||||
printf("vSyncStart %d\n",crtc_pass->vSyncStart);
|
||||
printf("vSyncEnd %d\n",crtc_pass->vSyncEnd);
|
||||
|
||||
printf("RR %d\n",crtc_pass->RefreshRate);
|
||||
printf("PixelCLK %d\n",(unsigned)crtc_pass->PixelClock);*/
|
||||
return 1;
|
||||
}
|
||||
/* fullscreen:
|
||||
* bit 0 (0x01) means fullscreen (-fs)
|
||||
* bit 1 (0x02) means mode switching (-vm)
|
||||
* bit 2 (0x04) enables software scaling (-zoom)
|
||||
* bit 3 (0x08) enables flipping (-flip) (NK: and for what?)
|
||||
*/
|
||||
|
||||
static uint32_t
|
||||
config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format,const vo_tune_info_t *info)
|
||||
{
|
||||
struct VbeInfoBlock vib;
|
||||
struct VbeInfoBlock vib;
|
||||
struct VesaModeInfoBlock vmib;
|
||||
struct VesaCRTCInfoBlock crtc_pass;
|
||||
size_t i,num_modes;
|
||||
uint32_t w,h;
|
||||
unsigned short *mode_ptr,win_seg;
|
||||
@ -831,11 +886,26 @@ config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uin
|
||||
PRINT_VBE_ERR("vbeSaveState",err);
|
||||
return -1;
|
||||
}
|
||||
if((err=vbeSetMode(video_mode,NULL)) != VBE_OK)
|
||||
/* TODO: check for VBE 3, monitor limitation
|
||||
user might pass refresh value
|
||||
GTF constants might be read from monitor
|
||||
for best results
|
||||
*/
|
||||
if (((int)(vib.VESAVersion >> 8) & 0xff) > 2) {
|
||||
|
||||
if (set_refresh(dstW,dstH,video_mode,&crtc_pass))
|
||||
video_mode = video_mode | 0x800;
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
if ((err=vbeSetMode(video_mode,&crtc_pass)) != VBE_OK)
|
||||
{
|
||||
PRINT_VBE_ERR("vbeSetMode",err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now we are in video mode!!!*/
|
||||
/* Below 'return -1' is impossible */
|
||||
if(verbose)
|
||||
|
@ -376,6 +376,26 @@ int vbeGetMode(unsigned *mode)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock) // in Hz
|
||||
{
|
||||
struct LRMI_regs r;
|
||||
int retval;
|
||||
memset(&r,0,sizeof(struct LRMI_regs));
|
||||
r.eax = 0x4f0b;
|
||||
r.ebx = 0;
|
||||
r.edx = *mode;
|
||||
r.ecx = *pixel_clock;
|
||||
if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
|
||||
retval = r.eax & 0xffff;
|
||||
if(retval == 0x4f)
|
||||
{
|
||||
*pixel_clock = r.ecx;
|
||||
retval = VBE_OK;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int vbeSaveState(void **data)
|
||||
{
|
||||
struct LRMI_regs r;
|
||||
|
@ -199,6 +199,7 @@ extern int vbeGetControllerInfo(struct VbeInfoBlock *);
|
||||
extern int vbeGetModeInfo(unsigned mode,struct VesaModeInfoBlock *);
|
||||
extern int vbeSetMode(unsigned mode,struct VesaCRTCInfoBlock *);
|
||||
extern int vbeGetMode(unsigned *mode);
|
||||
extern int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock);
|
||||
extern int vbeSaveState(void **data); /* note never copy this data */
|
||||
extern int vbeRestoreState(void *data);
|
||||
extern int vbeGetWindow(unsigned *win_num); /* win_A=0 or win_B=1 */
|
||||
|
Loading…
Reference in New Issue
Block a user