📄 ivtv-yuv.c
字号:
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 + -