mach64_vid.c

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

C
1,080
字号
static int mach64_get_caps(vidix_capability_t *to){    memcpy(to, &mach64_cap, sizeof(vidix_capability_t));    return 0;}static unsigned mach64_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch){  unsigned pitch,spy,spv,spu;  spy = spv = spu = 0;  switch(spitch->y)  {    case 16:    case 32:    case 64:    case 128:    case 256: spy = spitch->y; break;    default: break;  }  switch(spitch->u)  {    case 16:    case 32:    case 64:    case 128:    case 256: spu = spitch->u; break;    default: break;  }  switch(spitch->v)  {    case 16:    case 32:    case 64:    case 128:    case 256: spv = spitch->v; break;    default: break;  }  switch(fourcc)  {	/* 4:2:0 */	case IMGFMT_IYUV:	case IMGFMT_YV12:	case IMGFMT_I420:		if(spy > 16 && spu == spy/2 && spv == spy/2)	pitch = spy;		else						pitch = 32;		break;	case IMGFMT_YVU9:		if(spy > 32 && spu == spy/4 && spv == spy/4)	pitch = spy;		else						pitch = 64;		break;	default:		if(spy >= 16)	pitch = spy;		else		pitch = 16;		break;  }  return pitch;}static void mach64_compute_framesize(vidix_playback_t *info){  unsigned pitch,awidth;  pitch = mach64_query_pitch(info->fourcc,&info->src.pitch);  switch(info->fourcc)  {    case IMGFMT_I420:    case IMGFMT_YV12:    case IMGFMT_IYUV:		awidth = (info->src.w + (pitch-1)) & ~(pitch-1);		info->frame_size = awidth*(info->src.h+info->src.h/2);		break;    case IMGFMT_YVU9:		awidth = (info->src.w + (pitch-1)) & ~(pitch-1);		info->frame_size = awidth*(info->src.h+info->src.h/8);		break;//    case IMGFMT_RGB32:    case IMGFMT_BGR32:		awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);		info->frame_size = (awidth*info->src.h);		break;    /* YUY2 YVYU, RGB15, RGB16 */    default:			awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);		info->frame_size = (awidth*info->src.h);		break;  }  info->frame_size+=256; // so we have some space for alignment & such  info->frame_size&=~16;}static void mach64_vid_stop_video( void ){    mach64_fifo_wait(14);    OUTREG(OVERLAY_SCALE_CNTL, 0x80000000);    OUTREG(OVERLAY_EXCLUSIVE_HORZ, 0);    OUTREG(OVERLAY_EXCLUSIVE_VERT, 0);    OUTREG(SCALER_H_COEFF0, 0x00002000);    OUTREG(SCALER_H_COEFF1, 0x0D06200D);    OUTREG(SCALER_H_COEFF2, 0x0D0A1C0D);    OUTREG(SCALER_H_COEFF3, 0x0C0E1A0C);    OUTREG(SCALER_H_COEFF4, 0x0C14140C);    OUTREG(VIDEO_FORMAT, 0xB000B);    OUTREG(OVERLAY_TEST, 0x0);}static void mach64_vid_display_video( void ){    uint32_t vf;    mach64_fifo_wait(14);    OUTREG(OVERLAY_Y_X_START,			besr.y_x_start);    OUTREG(OVERLAY_Y_X_END,			besr.y_x_end);    OUTREG(OVERLAY_SCALE_INC,			besr.scale_inc);    OUTREG(SCALER_BUF_PITCH,			besr.vid_buf_pitch);    OUTREG(SCALER_HEIGHT_WIDTH,			besr.height_width);    OUTREG(SCALER_BUF0_OFFSET,			mach64_buffer_base[0][0]);    OUTREG(SCALER_BUF0_OFFSET_U,		mach64_buffer_base[0][1]);    OUTREG(SCALER_BUF0_OFFSET_V,		mach64_buffer_base[0][2]);    OUTREG(SCALER_BUF1_OFFSET,			mach64_buffer_base[0][0]);    OUTREG(SCALER_BUF1_OFFSET_U,		mach64_buffer_base[0][1]);    OUTREG(SCALER_BUF1_OFFSET_V,		mach64_buffer_base[0][2]);    mach64_wait_vsync();        mach64_fifo_wait(4);    OUTREG(OVERLAY_SCALE_CNTL, 0xC4000003);// OVERLAY_SCALE_CNTL bits & what they seem to affect// bit 0 no effect// bit 1 yuv2rgb coeff related// bit 2 horizontal interpolation if 0// bit 3 vertical interpolation if 0// bit 4 chroma encoding (0-> 128=neutral / 1-> 0->neutral)// bit 5-6 gamma correction// bit 7 nothing visible if set// bit 8-27 no effect// bit 28-31 nothing interresting just crashed my system when i played with them  :(    mach64_wait_for_idle();    vf = INREG(VIDEO_FORMAT);// Bits 16-19 seem to select the format// 0x0  dunno behaves strange// 0x1  dunno behaves strange// 0x2  dunno behaves strange// 0x3  BGR15// 0x4  BGR16// 0x5  BGR16 (hmm, that need investigation, 2 BGR16 formats, i guess 1 will have only 5bits for green)// 0x6  BGR32// 0x7  BGR32 with somehow mixed even / odd pixels ?// 0x8	YYYYUVUV// 0x9	YVU9// 0xA	YV12// 0xB	YUY2// 0xC	UYVY// 0xD  UYVY (no difference is visible if i switch between C/D for every even/odd frame)// 0xE  dunno behaves strange// 0xF  dunno behaves strange// Bit 28 all values are assumed to be 7 bit with chroma=64 for black (tested with YV12 & YUY2)// the remaining bits seem to have no effect    switch(besr.fourcc)    {	/* BGR formats */	case IMGFMT_BGR15: OUTREG(VIDEO_FORMAT, 0x00030000);  break;	case IMGFMT_BGR16: OUTREG(VIDEO_FORMAT, 0x00040000);  break;	case IMGFMT_BGR32: OUTREG(VIDEO_FORMAT, 0x00060000);  break;        /* 4:2:0 */	case IMGFMT_IYUV:	case IMGFMT_I420:	case IMGFMT_YV12:  OUTREG(VIDEO_FORMAT, 0x000A0000);  break;	case IMGFMT_YVU9:  OUTREG(VIDEO_FORMAT, 0x00090000);  break;        /* 4:2:2 */        case IMGFMT_YVYU:	case IMGFMT_UYVY:  OUTREG(VIDEO_FORMAT, 0x000C0000); break;	case IMGFMT_YUY2:	default:           OUTREG(VIDEO_FORMAT, 0x000B0000); break;    }    if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();}static int mach64_vid_init_video( vidix_playback_t *config ){    uint32_t src_w,src_h,dest_w,dest_h,pitch,h_inc,v_inc,left,leftUV,top,ecp,y_pos;    int is_420,best_pitch,mpitch;    int src_offset_y, src_offset_u, src_offset_v;    unsigned int i;    mach64_vid_stop_video();/* warning, if left or top are != 0 this will fail, as the framesize is too small then */    left = config->src.x;    top =  config->src.y;    src_h = config->src.h;    src_w = config->src.w;    is_420 = 0;    if(config->fourcc == IMGFMT_YV12 ||       config->fourcc == IMGFMT_I420 ||       config->fourcc == IMGFMT_IYUV) is_420 = 1;    best_pitch = mach64_query_pitch(config->fourcc,&config->src.pitch);    mpitch = best_pitch-1;    switch(config->fourcc)    {	case IMGFMT_YVU9:	/* 4:2:0 */	case IMGFMT_IYUV:	case IMGFMT_YV12:	case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;			  config->dest.pitch.y = 			  config->dest.pitch.u = 			  config->dest.pitch.v = best_pitch;			  besr.vid_buf_pitch= pitch;			  break;	/* RGB 4:4:4:4 */	case IMGFMT_RGB32:	case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;			  config->dest.pitch.y = 			  config->dest.pitch.u = 			  config->dest.pitch.v = best_pitch;			  besr.vid_buf_pitch= pitch>>2;			  break;	/* 4:2:2 */        default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */			  pitch = ((src_w*2) + mpitch) & ~mpitch;			  config->dest.pitch.y =			  config->dest.pitch.u =			  config->dest.pitch.v = best_pitch;			  besr.vid_buf_pitch= pitch>>1;			  break;    }    dest_w = config->dest.w;    dest_h = config->dest.h;    besr.fourcc = config->fourcc;    ecp = (INPLL(PLL_VCLK_CNTL) & PLL_ECP_DIV) >> 4;    if(__verbose>0) printf("[mach64] ecp: %d\n", ecp);    v_inc = src_h * mach64_get_vert_stretch();        if(mach64_is_interlace()) v_inc<<=1;    if(mach64_is_dbl_scan() ) v_inc>>=1;    v_inc>>=4; // convert 16.16 -> 20.12    v_inc/= dest_h;        h_inc = (src_w << (12+ecp)) / dest_w;    /* keep everything in 16.16 */    config->offsets[0] = 0;    for(i=1; i<config->num_frames; i++)        config->offsets[i] = config->offsets[i-1] + config->frame_size;    	/*FIXME the left / top stuff is broken (= zoom a src rectangle from a larger one)		1. the framesize isn't known as the outer src rectangle dimensions aren't known		2. the mach64 needs aligned addresses so it can't work anyway		   -> so we could shift the outer buffer to compensate that but that would mean		      alignment problems for the code which writes into it	*/        if(is_420)    {	config->offset.y= 0;	config->offset.u= (pitch*src_h + 15)&~15; 	config->offset.v= (config->offset.u + (pitch*src_h>>2) + 15)&~15;	if(besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)	{	  uint32_t tmp;	  tmp = config->offset.u;	  config->offset.u = config->offset.v;	  config->offset.v = tmp;	}			src_offset_y= config->offset.y + top*pitch + left;	src_offset_u= config->offset.u + (top*pitch>>2) + (left>>1);	src_offset_v= config->offset.v + (top*pitch>>2) + (left>>1);    }    else if(besr.fourcc == IMGFMT_YVU9)    {	config->offset.y= 0;	config->offset.u= (pitch*src_h + 15)&~15; 	config->offset.v= (config->offset.u + (pitch*src_h>>4) + 15)&~15;		src_offset_y= config->offset.y + top*pitch + left;	src_offset_u= config->offset.u + (top*pitch>>4) + (left>>1);	src_offset_v= config->offset.v + (top*pitch>>4) + (left>>1);    }    else if(besr.fourcc == IMGFMT_BGR32)    {      config->offset.y = config->offset.u = config->offset.v = 0;      src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 2);    }    else    {      config->offset.y = config->offset.u = config->offset.v = 0;      src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 1);    }    num_mach64_buffers= config->num_frames;    for(i=0; i<config->num_frames; i++)    {	mach64_buffer_base[i][0]= (mach64_overlay_offset + config->offsets[i] + src_offset_y)&~15;	mach64_buffer_base[i][1]= (mach64_overlay_offset + config->offsets[i] + src_offset_u)&~15;	mach64_buffer_base[i][2]= (mach64_overlay_offset + config->offsets[i] + src_offset_v)&~15;    }    leftUV = (left >> 17) & 15;    left = (left >> 16) & 15;    besr.scale_inc = ( h_inc << 16 ) | v_inc;    y_pos = config->dest.y;    if(mach64_is_dbl_scan()) y_pos*=2;    else    if(mach64_is_interlace()) y_pos/=2;    besr.y_x_start = y_pos | (config->dest.x << 16);    y_pos =config->dest.y + dest_h;    if(mach64_is_dbl_scan()) y_pos*=2;    else    if(mach64_is_interlace()) y_pos/=2;    besr.y_x_end = y_pos | ((config->dest.x + dest_w) << 16);    besr.height_width = ((src_w - left)<<16) | (src_h - top);    return 0;}static int is_supported_fourcc(uint32_t fourcc){    switch(fourcc)    {    case IMGFMT_YV12:    case IMGFMT_I420:    case IMGFMT_YVU9:    case IMGFMT_IYUV:	return supports_planar;    case IMGFMT_YUY2:    case IMGFMT_UYVY:    case IMGFMT_BGR15:    case IMGFMT_BGR16:    case IMGFMT_BGR32:	return 1;    default:	return 0;    }}static int mach64_query_fourcc(vidix_fourcc_t *to){    if(is_supported_fourcc(to->fourcc))    {	to->depth = VID_DEPTH_ALL;	to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY;	return 0;    }    else  to->depth = to->flags = 0;    return ENOSYS;}static int mach64_config_playback(vidix_playback_t *info){  if(!is_supported_fourcc(info->fourcc)) return ENOSYS;  mach64_compute_framesize(info);  if(info->num_frames>4) info->num_frames=4;  for(;info->num_frames>0; info->num_frames--)  {      mach64_overlay_offset = mach64_ram_size - info->frame_size*info->num_frames;      mach64_overlay_offset &= 0xffff0000;      if(mach64_overlay_offset>0) break;  }  if(info->num_frames <= 0) return EINVAL;  info->dga_addr = (char *)mach64_mem_base + mach64_overlay_offset;  mach64_vid_init_video(info);  return 0;}static int mach64_playback_on(void){  mach64_vid_display_video();  return 0;}static int mach64_playback_off(void){  mach64_vid_stop_video();  return 0;}static int mach64_frame_sel(unsigned int frame){    uint32_t off[6];    int i;    int last_frame= (frame-1+num_mach64_buffers) % num_mach64_buffers;//printf("Selecting frame %d\n", frame);        /*    buf3-5 always should point onto second buffer for better    deinterlacing and TV-in    */    if(num_mach64_buffers==1) return 0;    for(i=0; i<3; i++)    {    	off[i]  = mach64_buffer_base[frame][i];    	off[i+3]= mach64_buffer_base[last_frame][i];    }    mach64_wait_for_idle();    mach64_fifo_wait(7);    OUTREG(SCALER_BUF0_OFFSET,		off[0]);    OUTREG(SCALER_BUF0_OFFSET_U,	off[1]);    OUTREG(SCALER_BUF0_OFFSET_V,	off[2]);    OUTREG(SCALER_BUF1_OFFSET,		off[3]);    OUTREG(SCALER_BUF1_OFFSET_U,	off[4]);    OUTREG(SCALER_BUF1_OFFSET_V,	off[5]);    if(num_mach64_buffers==2) mach64_wait_vsync(); //only wait for vsync if we do double buffering           if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();    return 0;}static vidix_video_eq_t equal ={ VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION , 0, 0, 0, 0, 0, 0, 0, 0 };static int mach64_get_eq( vidix_video_eq_t * eq){  memcpy(eq,&equal,sizeof(vidix_video_eq_t));  return 0;}static int mach64_set_eq( const vidix_video_eq_t * eq){  int br,sat;    if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;    if(eq->cap & VEQ_CAP_CONTRAST)   equal.contrast   = eq->contrast;    if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;    if(eq->cap & VEQ_CAP_HUE)        equal.hue        = eq->hue;    if(eq->cap & VEQ_CAP_RGB_INTENSITY)    {      equal.red_intensity   = eq->red_intensity;      equal.green_intensity = eq->green_intensity;      equal.blue_intensity  = eq->blue_intensity;    }    equal.flags = eq->flags;    br = equal.brightness * 64 / 1000;    if(br < -64) br = -64; if(br > 63) br = 63;    sat = (equal.saturation + 1000) * 16 / 1000;    if(sat < 0) sat = 0; if(sat > 31) sat = 31;    OUTREG(SCALER_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));  return 0;}static int mach64_get_gkeys(vidix_grkey_t *grkey){    memcpy(grkey, &mach64_grkey, sizeof(vidix_grkey_t));    return(0);}static int mach64_set_gkeys(const vidix_grkey_t *grkey){    memcpy(&mach64_grkey, grkey, sizeof(vidix_grkey_t));    if(mach64_grkey.ckey.op == CKEY_TRUE)    {	besr.ckey_on=1;	switch(mach64_vid_get_dbpp())	{	case 15:		besr.graphics_key_msk=0x7FFF;		besr.graphics_key_clr=			  ((mach64_grkey.ckey.blue &0xF8)>>3)			| ((mach64_grkey.ckey.green&0xF8)<<2)			| ((mach64_grkey.ckey.red  &0xF8)<<7);		break;	case 16:		besr.graphics_key_msk=0xFFFF;		besr.graphics_key_clr=			  ((mach64_grkey.ckey.blue &0xF8)>>3)			| ((mach64_grkey.ckey.green&0xFC)<<3)			| ((mach64_grkey.ckey.red  &0xF8)<<8);		//besr.graphics_key_clr=le2me_32(besr.graphics_key_clr);		break;	case 24:		besr.graphics_key_msk=0xFFFFFF;		besr.graphics_key_clr=			  ((mach64_grkey.ckey.blue &0xFF))			| ((mach64_grkey.ckey.green&0xFF)<<8)			| ((mach64_grkey.ckey.red  &0xFF)<<16);		break;	case 32:		besr.graphics_key_msk=0xFFFFFF;		besr.graphics_key_clr=			  ((mach64_grkey.ckey.blue &0xFF))			| ((mach64_grkey.ckey.green&0xFF)<<8)			| ((mach64_grkey.ckey.red  &0xFF)<<16);		break;	default:		besr.ckey_on=0;		besr.graphics_key_msk=0;		besr.graphics_key_clr=0;	}    }    else    {	besr.ckey_on=0;	besr.graphics_key_msk=0;	besr.graphics_key_clr=0;    }    mach64_fifo_wait(4);    OUTREG(OVERLAY_GRAPHICS_KEY_MSK, besr.graphics_key_msk);    OUTREG(OVERLAY_GRAPHICS_KEY_CLR, besr.graphics_key_clr);//    OUTREG(OVERLAY_VIDEO_KEY_MSK, 0);//    OUTREG(OVERLAY_VIDEO_KEY_CLR, 0);    if(besr.ckey_on)    	OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_EQ|CMP_MIX_AND);    else    	OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND);    return(0);}VDXDriver mach64_drv = {  "mach64",  NULL,  .probe = mach64_probe,  .get_caps = mach64_get_caps,  .query_fourcc = mach64_query_fourcc,  .init = mach64_init,  .destroy = mach64_destroy,  .config_playback = mach64_config_playback,  .playback_on = mach64_playback_on,  .playback_off = mach64_playback_off,  .frame_sel = mach64_frame_sel,  .get_eq = mach64_get_eq,  .set_eq = mach64_set_eq,  .get_gkey = mach64_get_gkeys,  .set_gkey = mach64_set_gkeys,};

⌨️ 快捷键说明

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