📄 deintl.cpp
字号:
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 void
Deinterlace_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, mm7
ALIGN 16
line_loop:
mov ebx, pels_div8 // ebx -> pels/8 (rounded down)
ALIGN 16
pel_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 done
last_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_loop
done:
emms
}
}
////////////////////////////////////////////////////////
//
// Deinterlace_I420_Slow
//
// Slow deinterlacing of I420 data,
// with Rigorous Edge Interpolation using
// Optical Flow
//
////////////////////////////////////////////////////////
static void
Deinterlace_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 + -