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 + -
显示快捷键?