⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivtv-yuv.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	   the y source coord into two parts. */	if (window->src_y < 8) {		src_y_minor_uv = window->src_y;		src_y_major_uv = 0;	}	else {		src_y_minor_uv = 8;		src_y_major_uv = window->src_y - 8;	}	src_y_minor_y = src_y_minor_uv;	src_y_major_y = src_y_major_uv;	if (window->offset_y) src_y_minor_y += 16;	if (window->interlaced_y)		reg_2918 = (window->dst_h << 16) | (window->src_h + src_y_minor_y);	else		reg_2918 = (window->dst_h << 16) | ((window->src_h + src_y_minor_y) << 1);	if (window->interlaced_uv)		reg_291c = (window->dst_h << 16) | ((window->src_h + src_y_minor_uv) >> 1);	else		reg_291c = (window->dst_h << 16) | (window->src_h + src_y_minor_uv);	reg_2964_base = (src_y_minor_y * ((window->dst_h << 16)/window->src_h)) >> 14;	reg_2968_base = (src_y_minor_uv * ((window->dst_h << 16)/window->src_h)) >> 14;	if (window->dst_h / 2 >= window->src_h && !window->interlaced_y) {		master_height = (window->src_h * 0x00400000) / window->dst_h;		if ((window->src_h * 0x00400000) - (master_height * window->dst_h) >= window->dst_h / 2) master_height ++;		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 3;		reg_2930 = master_height;		reg_2940 = master_height >> 1;		reg_2964_base >>= 3;		reg_2968_base >>= 3;		reg_296c = 0x00000000;	}	else if (window->dst_h >= window->src_h) {		master_height = (window->src_h * 0x00400000) / window->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height >> 1;		reg_296c = 0x00000000;		if (window->interlaced_y) {			reg_2964_base >>= 3;		}		else {			reg_296c ++;			reg_2964_base >>= 2;		}		if (window->interlaced_uv) reg_2928 >>= 1;		reg_2968_base >>= 3;	}	else if (window->dst_h >= window->src_h / 2) {		master_height = (window->src_h * 0x00200000) / window->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height;		reg_296c = 0x00000101;		if (window->interlaced_y) {			reg_2964_base >>= 2;		}		else {			reg_296c ++;			reg_2964_base >>= 1;		}		if (window->interlaced_uv) reg_2928 >>= 1;		reg_2968_base >>= 2;	}	else {		master_height = (window->src_h * 0x00100000) / window->dst_h;		master_height = (master_height >> 1) + (master_height & 1);		reg_2920 = master_height >> 2;		reg_2928 = master_height >> 2;		reg_2930 = master_height;		reg_2940 = master_height;		reg_2964_base >>= 1;		reg_2968_base >>= 2;		reg_296c = 0x00000102;	}	/* FIXME These registers change depending on scaled / unscaled output	   We really need to work out what they should be */	if (window->src_h == window->dst_h){		reg_2934 = 0x00020000;		reg_293c = 0x00100000;		reg_2944 = 0x00040000;		reg_294c = 0x000b0000;	}	else {		reg_2934 = 0x00000FF0;		reg_293c = 0x00000FF0;		reg_2944 = 0x00000FF0;		reg_294c = 0x00000FF0;	}	/* The first line to be displayed */	reg_2950 = 0x00010000 + src_y_major_y;	if (window->interlaced_y) reg_2950 += 0x00010000;	reg_2954 = reg_2950 + 1;	reg_2958 = 0x00010000 + (src_y_major_y >> 1);	if (window->interlaced_uv) reg_2958 += 0x00010000;	reg_295c = reg_2958 + 1;	if (itv->yuv_info.decode_height == 480)		reg_289c = 0x011e0017;	else		reg_289c = 0x01500017;	if (window->dst_y < 0)		reg_289c = (reg_289c - ((window->dst_y & ~1)<<15))-(window->dst_y >>1);	else		reg_289c = (reg_289c + ((window->dst_y & ~1)<<15))+(window->dst_y >>1);	/* How much of the source to decode.	   Take into account the source offset */	reg_2960 = ((src_y_minor_y + window->src_h + src_y_major_y) - 1 ) |			((((src_y_minor_uv + window->src_h + src_y_major_uv) - 1) & ~1) << 15);	/* Calculate correct value for register 2964 */	if (window->src_h == window->dst_h)		reg_2964 = 1;	else {		reg_2964 = 2 + ((window->dst_h << 1) / window->src_h);		reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);	}	reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);	reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);	/* Okay, we've wasted time working out the correct value,	   but if we use it, it fouls the the window alignment.	   Fudge it to what we want... */	reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));	reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));	/* Deviate further from what it should be. I find the flicker headache	   inducing so try to reduce it slightly. Leave 2968 as-is otherwise	   colours foul. */	if ((reg_2964 != 0x00010001) && (window->dst_h / 2 <= window->src_h))		reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF)/2);	if (!window->interlaced_y) reg_2964 -= 0x00010001;	if (!window->interlaced_uv) reg_2968 -= 0x00010001;	reg_2964 += ((reg_2964_base << 16) | reg_2964_base);	reg_2968 += ((reg_2968_base << 16) | reg_2968_base);	/* Select the vertical filter */	if (window->src_h == window->dst_h) {		/* An exact size match uses filter 0/1 */		v_filter_1 = 0;		v_filter_2 = 1;	}	else {		/* Figure out which filter to use */		v_filter_1 = ((window->src_h << 16) / window->dst_h) >> 15;		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);		/* Only an exact size match can use filter 0 */		if (v_filter_1 == 0) v_filter_1 = 1;		v_filter_2 = v_filter_1;	}	write_reg(reg_2934, 0x02934);	write_reg(reg_293c, 0x0293c);	IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",itv->yuv_info.reg_2934, reg_2934, itv->yuv_info.reg_293c, reg_293c);	write_reg(reg_2944, 0x02944);	write_reg(reg_294c, 0x0294c);	IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",itv->yuv_info.reg_2944, reg_2944, itv->yuv_info.reg_294c, reg_294c);	/* Ensure 2970 is 0 (does it ever change ?) *//*	write_reg(0,0x02970); *//*	IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n",itv->yuv_info.reg_2970, 0); */	write_reg(reg_2930, 0x02938);	write_reg(reg_2930, 0x02930);	IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",itv->yuv_info.reg_2930, reg_2930, itv->yuv_info.reg_2938, reg_2930);	write_reg(reg_2928, 0x02928);	write_reg(reg_2928+0x514, 0x0292C);	IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",itv->yuv_info.reg_2928, reg_2928, itv->yuv_info.reg_292c, reg_2928+0x514);	write_reg(reg_2920, 0x02920);	write_reg(reg_2920+0x514, 0x02924);	IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",itv->yuv_info.reg_2920, reg_2920, itv->yuv_info.reg_2924, 0x514+reg_2920);	write_reg (reg_2918,0x02918);	write_reg (reg_291c,0x0291C);	IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",itv->yuv_info.reg_2918,reg_2918,itv->yuv_info.reg_291c,reg_291c);	write_reg(reg_296c, 0x0296c);	IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",itv->yuv_info.reg_296c, reg_296c);	write_reg(reg_2940, 0x02948);	write_reg(reg_2940, 0x02940);	IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",itv->yuv_info.reg_2940, reg_2940, itv->yuv_info.reg_2948, reg_2940);	write_reg(reg_2950, 0x02950);	write_reg(reg_2954, 0x02954);	IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",itv->yuv_info.reg_2950, reg_2950, itv->yuv_info.reg_2954, reg_2954);	write_reg(reg_2958, 0x02958);	write_reg(reg_295c, 0x0295C);	IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",itv->yuv_info.reg_2958, reg_2958, itv->yuv_info.reg_295c, reg_295c);	write_reg(reg_2960, 0x02960);	IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",itv->yuv_info.reg_2960, reg_2960);	write_reg(reg_2964, 0x02964);	write_reg(reg_2968, 0x02968);	IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",itv->yuv_info.reg_2964, reg_2964, itv->yuv_info.reg_2968, reg_2968);	write_reg( reg_289c,0x0289c);	IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",itv->yuv_info.reg_289c, reg_289c);	/* Only update filter 1 if we really need to */	if (v_filter_1 != itv->yuv_info.v_filter_1) {		ivtv_yuv_filter (itv,-1,v_filter_1,-1);		itv->yuv_info.v_filter_1 = v_filter_1;	}	/* Only update filter 2 if we really need to */	if (v_filter_2 != itv->yuv_info.v_filter_2) {		ivtv_yuv_filter (itv,-1,-1,v_filter_2);		itv->yuv_info.v_filter_2 = v_filter_2;	}}/* Modify the supplied coordinate information to fit the visible osd area */static u32 ivtv_yuv_window_setup (struct ivtv *itv, struct yuv_frame_info *window){	int osd_crop, lace_threshold;	u32 osd_scale;	u32 yuv_update = 0;	lace_threshold = itv->yuv_info.lace_threshold;	if (lace_threshold < 0)		lace_threshold = itv->yuv_info.decode_height - 1;	/* Work out the lace settings */	switch (itv->yuv_info.lace_mode) {		case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */			itv->yuv_info.frame_interlaced = 0;			if (window->tru_h < 512 || (window->tru_h > 576 && window->tru_h < 1021))				window->interlaced_y = 0;			else				window->interlaced_y = 1;			if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))				window->interlaced_uv = 0;			else				window->interlaced_uv = 1;			break;		case IVTV_YUV_MODE_AUTO:			if (window->tru_h <= lace_threshold || window->tru_h > 576 || window->tru_w > 720){				itv->yuv_info.frame_interlaced = 0;				if ((window->tru_h < 512) ||				  (window->tru_h > 576 && window->tru_h < 1021) ||				  (window->tru_w > 720 && window->tru_h < 1021))					window->interlaced_y = 0;				else					window->interlaced_y = 1;				if (window->tru_h < 1021 && (window->dst_h >= window->src_h /2))					window->interlaced_uv = 0;				else					window->interlaced_uv = 1;			}			else {				itv->yuv_info.frame_interlaced = 1;				window->interlaced_y = 1;				window->interlaced_uv = 1;			}			break;			case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */		default:			itv->yuv_info.frame_interlaced = 1;			window->interlaced_y = 1;			window->interlaced_uv = 1;			break;	}	/* Sorry, but no negative coords for src */	if (window->src_x < 0) window->src_x = 0;	if (window->src_y < 0) window->src_y = 0;	/* Can only reduce width down to 1/4 original size */	if ((osd_crop = window->src_w - ( 4 * window->dst_w )) > 0) {		window->src_x += osd_crop / 2;		window->src_w = (window->src_w - osd_crop) & ~3;		window->dst_w = window->src_w / 4;		window->dst_w += window->dst_w & 1;	}	/* Can only reduce height down to 1/4 original size */	if (window->src_h / window->dst_h >= 2) {		/* Overflow may be because we're running progressive, so force mode switch */		window->interlaced_y = 1;		/* Make sure we're still within limits for interlace */		if ((osd_crop = window->src_h - ( 4 * window->dst_h )) > 0) {			/* If we reach here we'll have to force the height. */			window->src_y += osd_crop / 2;			window->src_h = (window->src_h - osd_crop) & ~3;			window->dst_h = window->src_h / 4;			window->dst_h += window->dst_h & 1;		}	}	/* If there's nothing to safe to display, we may as well stop now */	if ((int)window->dst_w <= 2 || (int)window->dst_h <= 2 || (int)window->src_w <= 2 || (int)window->src_h <= 2) {		return IVTV_YUV_UPDATE_INVALID;	}	/* Ensure video remains inside OSD area */	osd_scale = (window->src_h << 16) / window->dst_h;	if ((osd_crop = window->pan_y - window->dst_y) > 0) {		/* Falls off the upper edge - crop */		window->src_y += (osd_scale * osd_crop) >> 16;		window->src_h -= (osd_scale * osd_crop) >> 16;		window->dst_h -= osd_crop;		window->dst_y = 0;	}	else {		window->dst_y -= window->pan_y;	}	if ((osd_crop = window->dst_h + window->dst_y - window->vis_h) > 0) {		/* Falls off the lower edge - crop */		window->dst_h -= osd_crop;		window->src_h -= (osd_scale * osd_crop) >> 16;	}	osd_scale = (window->src_w << 16) / window->dst_w;	if ((osd_crop = window->pan_x - window->dst_x) > 0) {		/* Fall off the left edge - crop */		window->src_x += (osd_scale * osd_crop) >> 16;		window->src_w -= (osd_scale * osd_crop) >> 16;		window->dst_w -= osd_crop;		window->dst_x = 0;	}	else {		window->dst_x -= window->pan_x;	}	if ((osd_crop = window->dst_w + window->dst_x - window->vis_w) > 0) {		/* Falls off the right edge - crop */		window->dst_w -= osd_crop;		window->src_w -= (osd_scale * osd_crop) >> 16;	}	/* The OSD can be moved. Track to it */	window->dst_x += itv->yuv_info.osd_x_offset;	window->dst_y += itv->yuv_info.osd_y_offset;	/* Width & height for both src & dst must be even.	   Same for coordinates. */	window->dst_w &= ~1;	window->dst_x &= ~1;	window->src_w += window->src_x & 1;	window->src_x &= ~1;	window->src_w &= ~1;	window->dst_w &= ~1;	window->dst_h &= ~1;	window->dst_y &= ~1;	window->src_h += window->src_y & 1;	window->src_y &= ~1;	window->src_h &= ~1;	window->dst_h &= ~1;	/* Due to rounding, we may have reduced the output size to <1/4 of the source	   Check again, but this time just resize. Don't change source coordinates */	if (window->dst_w < window->src_w / 4) {		window->src_w &= ~3;		window->dst_w = window->src_w / 4;		window->dst_w += window->dst_w & 1;	}	if (window->dst_h < window->src_h / 4) {

⌨️ 快捷键说明

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