📄 deintl.cpp
字号:
Deinterlace_I420_FlipFlop(unsigned char *frame, unsigned char *tempFrame, int pels, int lines, int pitch, int format){ int lineCounter; // reorder the frame, even field on top, Y, Cr then Cb for(lineCounter=0;lineCounter<lines;lineCounter+=2) { memcpy(tempFrame+((lineCounter>>1)*(pels)), /* Flawfinder: ignore */ frame+lineCounter*pels,pels); } for(lineCounter=0;lineCounter<(lines>>1);lineCounter+=2) { memcpy(tempFrame+((lineCounter>>1)*(pels>>1)) + (pels*lines) /* Flawfinder: ignore */ ,frame+(pels*lines)+lineCounter*(pels>>1),(pels>>1)); } for(lineCounter=0;lineCounter<(lines>>1);lineCounter+=2) { memcpy(tempFrame+((lineCounter>>1)*(pels>>1)) +(pels*lines*5/4) /* Flawfinder: ignore */ ,frame+(pels*lines*5/4)+lineCounter*(pels>>1),(pels>>1)); } for(lineCounter=1;lineCounter<lines+1;lineCounter+=2) { memcpy(tempFrame+((lines-1)-(lineCounter>>1))*pels, /* Flawfinder: ignore */ frame+lineCounter*pels,pels); } for(lineCounter=1;lineCounter<(lines>>1)+1;lineCounter+=2) { memcpy(tempFrame + (pels*lines) + /* Flawfinder: ignore */ (((lines>>1)-1)-(lineCounter>>1))*(pels>>1),frame+(pels*lines)+lineCounter*(pels>>1),(pels>>1)); } for(lineCounter=1;lineCounter<(lines>>1)+1;lineCounter+=2) { memcpy(tempFrame + (pels*lines*5/4) + /* Flawfinder: ignore */ (((lines>>1)-1)-(lineCounter>>1))*(pels>>1),frame+(pels*lines*5/4)+lineCounter*(pels>>1),(pels>>1)); } memcpy(frame,tempFrame,(pels*lines*3)/2); /* Flawfinder: ignore */ return;}#ifdef _M_IX86//////////////////////////////////////////////////////////// Deinterlace_I420_MMX//// MMX optimized deinterlacing of I420 data, using both fields//////////////////////////////////////////////////////////static voidDeinterlace_I420_MMX(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format){ int line_shift; int pels_div8; pels_div8 = (pels >> 3); // round down line_shift = ((pitch << 1) - (pels & ~7)); __asm { mov ecx, lines // ecx -> lines shr ecx, 1 // ecx -> lines/2 mov edx, pitch // pitch mov eax, edx neg eax // -pitch mov esi, frame // esi -> current frame add esi, pitch; // move esi to the next line pxor mm7, mm7ALIGN 16line_loop: mov ebx, pels_div8 // ebx -> pels/8 (rounded down)ALIGN 16pel_loop: // median = (upper & A) | (mid & B) | (lower & C) // e.g.... movq mm0,[esi+eax] // 1 2 1 3 2 3 1 3 = mm0 = (upper) movq mm1,[esi] // 2 1 3 1 3 2 1 3 = mm1 = (mid) movq mm2,[esi+edx] // 3 3 2 2 1 1 2 3 = mm2 = (lower) movq mm3,mm1 // 2 1 3 1 3 2 1 3 = mm3 psubusb mm3,mm0 // 1 0 2 0 1 0 0 0 = mm3 pcmpeqb mm3,mm7 // 0 1 0 1 0 1 1 1 = mm3 = (upper > mid) movq mm4,mm2 // 3 3 2 2 1 1 2 3 = mm4 psubusb mm4,mm1 // 1 2 0 1 0 0 1 0 = mm4 pcmpeqb mm4,mm7 // 0 0 1 0 1 1 0 1 = mm4 = (mid > lower) movq mm6,mm3 // 0 1 0 1 0 1 1 1 = mm6 pxor mm6,mm4 // 0 1 1 1 1 0 1 0 = mm6 = ~(B) pandn mm6,mm1 // 2 0 0 0 0 2 1 0 = mm6 = (mid & B) movq mm5,mm2 // 3 3 2 2 1 1 2 3 = mm5 psubusb mm5,mm0 // 2 1 1 0 0 0 1 0 = mm5 pcmpeqb mm5,mm7 // 0 0 0 1 1 1 0 1 = mm5 = (upper > lower) movq mm1,mm5 // 0 0 0 1 1 1 0 1 = mm1 pxor mm1,mm3 // 0 1 0 0 1 0 1 0 = mm1 = (A) pand mm1,mm0 // 0 2 0 0 2 0 1 0 = mm1 = (upper & A) por mm6,mm1 // 2 2 0 0 2 2 1 0 = mm6 = (upper & A) | (mid & B) pxor mm4,mm5 // 0 0 1 1 0 0 0 1 = mm4 = (C) pand mm4,mm2 // 0 0 2 2 0 0 0 3 = mm4 = (lower & C) por mm6,mm4 // 2 2 2 2 2 2 1 3 = mm6 = (upper & A) | (mid & B) | (lower & C) movq [esi],mm6 lea esi,[esi+8] dec ebx jnz pel_loop // any pels left??? mov ebx, pels and ebx, 0x07 jnz last_pels add esi, line_shift; // move esi to the next line dec ecx jnz line_loop jmp donelast_pels: // take care of last four pels movd mm0,[esi+eax] movd mm1,[esi] movd mm2,[esi+edx] movq mm3,mm1 // 2 1 3 1 3 2 1 3 = mm3 psubusb mm3,mm0 // 1 0 2 0 1 0 0 0 = mm3 pcmpeqb mm3,mm7 // 0 1 0 1 0 1 1 1 = mm3 = (upper > mid) movq mm4,mm2 // 3 3 2 2 1 1 2 3 = mm4 psubusb mm4,mm1 // 1 2 0 1 0 0 1 0 = mm4 pcmpeqb mm4,mm7 // 0 0 1 0 1 1 0 1 = mm4 = (mid > lower) movq mm6,mm3 // 0 1 0 1 0 1 1 1 = mm6 pxor mm6,mm4 // 0 1 1 1 1 0 1 0 = mm6 = ~(B) pandn mm6,mm1 // 2 0 0 0 0 2 1 0 = mm6 = (mid & B) movq mm5,mm2 // 3 3 2 2 1 1 2 3 = mm5 psubusb mm5,mm0 // 2 1 1 0 0 0 1 0 = mm5 pcmpeqb mm5,mm7 // 0 0 0 1 1 1 0 1 = mm5 = (upper > lower) movq mm1,mm5 // 0 0 0 1 1 1 0 1 = mm1 pxor mm1,mm3 // 0 1 0 0 1 0 1 0 = mm1 = (A) pand mm1,mm0 // 0 2 0 0 2 0 1 0 = mm1 = (upper & A) por mm6,mm1 // 2 2 0 0 2 2 1 0 = mm6 = (upper & A) | (mid & B) pxor mm4,mm5 // 0 0 1 1 0 0 0 1 = mm4 = (C) pand mm4,mm2 // 0 0 2 2 0 0 0 3 = mm4 = (lower & C) por mm6,mm4 // 2 2 2 2 2 2 1 3 = mm6 = (upper & A) | (mid & B) | (lower & C) movd [esi],mm6 add esi, line_shift; // move esi to the next line dec ecx jnz line_loopdone: emms }}//////////////////////////////////////////////////////////// Deinterlace_I420_Slow//// Slow deinterlacing of I420 data, // with Rigorous Edge Interpolation using // Optical Flow//////////////////////////////////////////////////////////static voidDeinterlace_I420_EdgeInterp(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format){ int line, pel, mcountfr=1, mcountfi=1, D1=0; unsigned char *fpr, *fpg, *pfpg, *pfpr; unsigned char *fp1, *pfp1; unsigned char *fp2, *pfp2; unsigned char *fp3, *pfp3; # define IFrMThresh 10 # define IFsMThresh 20 # define FlowThresh 1200 # define StrictFlowThresh 5 # define adj 10 int frm =1; int diff1; int tmp; int *tempLine, *ptempLine; tempLine = (int*)malloc(pels*sizeof(int)); for (line = 1; line < lines - 2; line += 2) { int a,b,c,d,e,f; int D1 =0; unsigned char *tfp3; memset(tempLine, -1, pels*sizeof(int)); fpr = frame + line*pitch; fpg = fpr; fp2 = fpg + adj; ptempLine = &tempLine[0] + adj; // prev line fp1 = fp2 - pitch; // next line fp3 = fp2 + pitch; // previous frame if (prev_frame != 0) { pfpr = prev_frame + line * pitch; pfpg = pfpr; pfp2 = pfpg + adj; pfp1 = pfp2 - pitch; pfp3 = pfp2 + pitch; } else { Deinterlace_RGB24_Fast(frame, prev_frame, pels, lines, pitch, format); free(tempLine); return; } // initialize for (pel = adj; pel < (pels - adj); pel += 1) { int moving = 0; int fi, fD; int minf; int pix; int error2, error21, error22, error3, d2=0, j; // Load *next* pels a = (int)(*fp1); b = (int)(*fp2); c = (int)(*fp3); // intra frame D1 = *(fp1+1) - *(fp1-1); D1 = ABS(D1); if( D1 > 20) { d = *(fp1+1); e = *(fp1-1); tfp3 = fp3; tmp = (a - *(tfp3)); minf = DIFF_FCN(tmp); tmp = (d - *(tfp3+1)); minf += DIFF_FCN(tmp); tmp = (e - *(tfp3-1)); minf += DIFF_FCN(tmp); fi = 0; tfp3--; for (j=-1; j>=-adj; j--) { tmp = (a - *(tfp3)); fD = DIFF_FCN(tmp); if (fD > minf) goto gskip; tmp = (d - *(tfp3+1)); fD= fD + DIFF_FCN(tmp); if (fD > minf) goto gskip; tmp = (e - *(tfp3-1)); fD= fD + DIFF_FCN(tmp); if(fD<minf) { minf = fD; fi = j; }gskip: tfp3--; } tfp3 = fp3 + 1; for (j=1; j<=adj; j++) { tmp = (a - *(tfp3)); fD = DIFF_FCN(tmp); if (fD > minf) goto gskip2; tmp = (d - *(tfp3+1)); fD += DIFF_FCN(tmp); if (fD > minf) goto gskip2; tmp = (e - *(tfp3-1)); fD += DIFF_FCN(tmp); if(fD<minf) { minf = fD; fi = j; }gskip2: tfp3++; } #ifdef TIME_DEINTERLACE //num_flow++; #endif if (minf < FlowThresh) { if ((fi == 1) || (fi == -1) || (fi == 0)) { tempLine[pel] = (*fp1 + *fp3)/2; } else { f = *(fp3+ fi); pix = (a + f) / 2; d2 = (int)(fi)/2; f = *(fp1 + d2); tmp = (pix - f); error2 = ABS(tmp); f = *(fp1 + d2 + 1); pix = (d + *(fp3 + fi + 1))/2; tmp = (pix - f); error21 = ABS(tmp); f = *(fp1 + d2 -1); pix = (e + *(fp3 + fi - 1))/2; tmp = (pix - f); error22 = ABS(tmp); if(error2 < 15 && ( ((error21 < 15) && (error22 > 25)) || ((error21 > 25) && (error22 < 15)) ) ) { pix = (a + *(fp3+fi)) / 2; tempLine[pel + d2] = pix; pix = (d + *(fp3 + fi + 1))/2; tempLine[pel + d2 + 1] = pix; pix = (e + *(fp3 + fi - 1))/2; tempLine[pel + d2 - 1] = pix; goto gadvance; } pix = (a + *(fp3 + fi))/2; f = *(fp3 + d2); tmp = (pix - f); error3 = ABS(tmp); f = *(fp3 + d2 + 1); pix = (d + *(fp3 + fi + 1))/2; tmp = (pix - f); error21 = ABS(tmp); f = *(fp3 + d2 -1); pix = (e + *(fp3 + fi - 1))/2; tmp = (pix - f); error22 = ABS(tmp); pix = (a + *(fp3 + fi))/2; if( error3 < 15 && ( ((error21 < 15) && (error22 > 25)) || ((error21 > 25) && (error22 < 15))) ) { tempLine[pel + d2] = pix; pix = (d + *(fp3 + fi + 1))/2; tempLine[pel + d2 + 1] = pix; pix = (e + *(fp3 + fi - 1))/2; tempLine[pel + d2 - 1] = pix; goto gadvance; } else { /* *fp2 = 0; *fpr2 = 0; *fpb2 = 255; tempLine[pel] = 0; */ } } } else { /* *fp2 = 0; *fpr2 = 255; *fpb2 = 0; tempLine[pel] = 0; */ } }gadvance: fp1++; fp2++; fp3++; pfp1++; pfp2++; pfp3++; ptempLine++; } // current frame // current line fp2 = fpg; // prev line fp1 = fp2 - pitch; // next line fp3 = fp2 + pitch; // current frame //prev frame // current line pfp2 = pfpg; // prev line pfp1 = pfp2 - pitch; // next line pfp3 = pfp2 + pitch; ptempLine = &tempLine[0]; for (pel = 0; pel < pels-1; pel += 1) { // change tmp = (*fp1 - *(fp3)); diff1 = DIFF_FCN(tmp); tmp = (*(fp1-1) - *(fp3-1)); diff1 += DIFF_FCN(tmp); tmp = (*(fp3+1) - *(pfp3+1)); diff1 += DIFF_FCN(tmp); if( ABS(diff1) > 4800 ) { // horiz tmp = (*fp1 - *(pfp1)); diff1 = DIFF_FCN(tmp); tmp = (*(fp1-1) - *(pfp1-1)); diff1 += DIFF_FCN(tmp); tmp = (*(fp1+1) - *(pfp1+1)); diff1 += DIFF_FCN(tmp); tmp = (*fp3 - *(pfp3)); diff1 += DIFF_FCN(tmp); tmp = (*(fp3-1) - *(pfp3-1)); diff1 += DIFF_FCN(tmp); tmp = (*(fp3+1) - *(pfp3+1)); diff1 += DIFF_FCN(tmp); if (diff1 < 2400) { // not moving *fp2 = MEDIAN_3(*fp1,*fp2,*fp3); } else { if (*ptempLine != -1) { *fp2 = (unsigned char) *ptempLine; } else { tmp = (*fp1 + *fp3)/2; *fp2 = (unsigned char) tmp; } #ifdef TIME_DEINTERLACE num_avg++; #endif } } else { // not horiz // avg if (*ptempLine != -1) { D1 = *(fp1+1) - *(fp1-1); D1 = ABS(D1); if( D1 > 20) { *fp2 = (unsigned char) *ptempLine; } else { tmp = (*fp1 + *fp3)/2; *fp2 = (unsigned char) tmp; // not vertical } } else { tmp = (*fp1 + *fp3)/2; *fp2 = (unsigned char) tmp; } #ifdef TIME_DEINTERLACE num_avg++; #endif } fp1++; fp2++; fp3++; pfp1++; pfp2++; pfp3++; ptempLine++; } } free(tempLine); return;} #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -