📄 invtelec.cpp
字号:
for (i = 0; i < PULLDOWN_HIST_LEN; i++)
{
state->pulldownTimeHist[i] = timestamp;
}
state->lastRemovedTimestamp = timestamp;
state->firstFrame = FALSE;
goto TOO_EARLY;
}
// Calculate Sum of Differences for even and odd lines...
// If we know that the frame is de-interlaced, then the stats
// for the "odd" lines are invalid. So just measure "even"
// lines then copy into "odd" SAD (so the rest of the algorithm
// will work).
ll = (pels >> 2);
if (bDeInterlaced)
{
pNew = (LONG32 *)data;
pOld = (LONG32 *)prevData;
ll = (pels >> 2);
for (i = 0; i < lines; i += 2) // only do the luma.
{
for (j = 0; j < ll; j++)
{
temp = (float)((pNew[j]&0xff00) - (pOld[j]&0xFF00));
sumEven += ((float)(1./(256.*256.)))*(temp*temp);
}
pOld += 2*ll;
pNew += 2*ll;
}
sumOdd = sumEven;
}
else
{
switch (state->impl_id)
{
#ifdef ALLOW_MMX_INVTELE
case INVTELE_IMPL_ID_MMX:
{
SumSqaredFrameDiff_MMX(
data, prevData,
pels, lines, pels,
&sumEven, &sumOdd);
sumAll = 0.5f * (sumEven + sumOdd);
}
break;
#endif
case INVTELE_IMPL_ID_C:
default:
{
pNew = (LONG32 *)data;
pOld = (LONG32 *)prevData;
for (i = 0; i < lines; i += 2) // only do the luma.
{
for (j = 0; j < ll; j++)
{
temp = (float)((pNew[j]&0xff00) - (pOld[j]&0xFF00));
sumEven += ((float)(1./(256.*256.)))*(temp*temp);
temp = (float)((pNew[j+ll]&0xFF00) - (pOld[j+ll]&0xFF00));
sumOdd += ((float)(1./(256.*256.)))*(temp*temp);
}
pOld += 2*ll;
pNew += 2*ll;
}
sumAll = sumEven + sumOdd;
sumEven /= (ll * (lines>>1));
sumOdd /= (ll * (lines>>1));
sumAll /= (ll * lines);
}
break;
}
}
sceneChangeFlag = (sumAll > 7500)?(TRUE):(FALSE);
if (sumEven > 100) sumEven=100;
if (sumOdd > 100) sumOdd=100;
if (sumAll > 100) sumAll=100;
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"ssd are %f %f at time %d\n",sumEven,sumOdd,timestamp);
#endif
// Compensate for 30 vs 29.97fps captures.
if ((sumEven == 0) && (sumOdd == 0) &&
(state->NTSCTrackingFrameCounter > 500) && (frameRate > 29.98))
{
state->pulldownTimeHist[PULLDOWN_HIST_LEN-1] = timestamp;
state->NTSCTrackingFrameCounter = 0;
goto REMOVE_FRAME;
}
state->NTSCTrackingFrameCounter++;
// In case we dropped a frame
timeSinceLastFrame = CALCULATE_ELAPSED_TICKS(state->pulldownTimeHist[PULLDOWN_HIST_LEN-1], timestamp);
while(timeSinceLastFrame > 50)
{
for(i=0;i<PULLDOWN_HIST_LEN-1;i++)
{
state->pulldownSadHistEven[i] = state->pulldownSadHistEven[i+1];
state->pulldownSadHistOdd[i] = state->pulldownSadHistOdd[i+1];
state->pulldownSadHistAll[i] = state->pulldownSadHistAll[i+1];
state->pulldownTimeHist[i] = state->pulldownTimeHist[i+1];
}
state->pulldownSadHistEven[i] = MISSING_SAD;
state->pulldownSadHistOdd[i] = MISSING_SAD;
state->pulldownSadHistAll[i] = MISSING_SAD;
state->pulldownTimeHist[i] = timestamp;
timeSinceLastFrame -= 33;
state->frameRemovalPattern--;
if (state->frameRemovalPattern < 0)
state->frameRemovalPattern = 4;
state->frameCountMod--;
if (state->frameCountMod < 0)
state->frameCountMod = 4;
}
// Update the history
for(i = 0; i < PULLDOWN_HIST_LEN - 1; i++)
{
state->pulldownSadHistEven[i] = state->pulldownSadHistEven[i+1];
state->pulldownSadHistOdd[i] = state->pulldownSadHistOdd[i+1];
state->pulldownSadHistAll[i] = state->pulldownSadHistAll[i+1];
state->pulldownTimeHist[i] = state->pulldownTimeHist[i+1];
}
state->frameRemovalPattern--;
if (state->frameRemovalPattern < 0)
state->frameRemovalPattern = 4;
state->frameCountMod--;
if (state->frameCountMod < 0)
state->frameCountMod = 4;
state->pulldownSadHistEven[i] = sumEven;
state->pulldownSadHistOdd[i] = sumOdd;
state->pulldownSadHistAll[i] = sumAll;
state->pulldownTimeHist[i] = timestamp;
// If removal on, and we have no pattern established, wait a while.
if ((state->pulldownSadHistEven[PULLDOWN_HIST_LEN - 5] == UN_INIT_SAD) ||
(state->pulldownSadHistOdd[PULLDOWN_HIST_LEN - 5] == UN_INIT_SAD) ||
(state->pulldownSadHistAll[PULLDOWN_HIST_LEN - 5] == UN_INIT_SAD))
{
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"gotoing - too early\n");
#endif
goto TOO_EARLY;
}
histLength = 0;
while (state->pulldownSadHistAll[histLength] == UN_INIT_SAD)
{
histLength += 5;
if (histLength > PULLDOWN_HIST_LEN - 10)
goto TOO_EARLY;
}
if ((bDeInterlaced) || (state->ulPulldownActiveTimerProg > 90 && state->ulPulldownActiveTimerIntl < 10))
{
// Skip interlaced telecine tests
goto PROGRESSIVE_TESTS;
}
// Gather statistics from SAD history
// Run through tests looking at the last 20, then 15, then 10, then 5 frames
for (patternStart = histLength; patternStart < PULLDOWN_HIST_LEN; patternStart += 5)
{
for (i = 0; i < 5;i++)
{
// Stats for "even" lines
inGroupMeanEven[i] = 0;
outGroupMeanEven[i] = 0;
inGroupStdEven[i] = 0;
outGroupStdEven[i] = 0;
inGroupCountEven = 0;
outGroupCountEven = 0;
outMinEven[i] = 255*255;
inMinEven[i] = 255*255;
outMaxEven[i] = 0;
inMaxEven[i] = 0;
for (j = patternStart + i; j < PULLDOWN_HIST_LEN; j++)
{
if (state->pulldownSadHistEven[j] == MISSING_SAD ||
state->pulldownSadHistEven[j] == UN_INIT_SAD)
continue;
if (((j - i) % 5) == 0)
{
inGroupMeanEven[i] += state->pulldownSadHistEven[j];
inGroupStdEven[i] += state->pulldownSadHistEven[j]*state->pulldownSadHistEven[j];
if (inMaxEven[i] < state->pulldownSadHistEven[j])
inMaxEven[i] = state->pulldownSadHistEven[j];
if (inMinEven[i] > state->pulldownSadHistOdd[j])
inMinEven[i] = state->pulldownSadHistOdd[j];
inGroupCountEven++;
}
else
{
outGroupMeanEven[i]+= state->pulldownSadHistEven[j];
outGroupStdEven[i]+= state->pulldownSadHistEven[j]*state->pulldownSadHistEven[j];
if (outMinEven[i] > state->pulldownSadHistEven[j])
outMinEven[i] = state->pulldownSadHistEven[j];
if (outMaxEven[i] < state->pulldownSadHistEven[j])
outMaxEven[i] = state->pulldownSadHistEven[j];
outGroupCountEven++;
}
}
// Is there enough valid data to analyze?
if ((inGroupCountEven > 1) && (outGroupCountEven > 3))
{
inGroupMeanEven[i] = inGroupMeanEven[i]/inGroupCountEven;
if ((inGroupStdEven[i]/inGroupCountEven)-(inGroupMeanEven[i]*inGroupMeanEven[i]) > 0.0f)
inGroupStdEven[i] = (float)sqrt((inGroupStdEven[i]/inGroupCountEven)-(inGroupMeanEven[i]*inGroupMeanEven[i]));
else
inGroupStdEven[i] = 0.0f;
outGroupMeanEven[i] = outGroupMeanEven[i]/outGroupCountEven;
if ((outGroupStdEven[i]/outGroupCountEven)-(outGroupMeanEven[i]*outGroupMeanEven[i]) > 0.0f)
outGroupStdEven[i] = (float)sqrt((outGroupStdEven[i]/outGroupCountEven)-(outGroupMeanEven[i]*outGroupMeanEven[i]));
else
outGroupStdEven[i] = 0.0f;
groupValidFlagEven[i] = TRUE;
}
else
{
inGroupMeanEven[i] = 0;
outGroupMeanEven[i] = 0;
inGroupStdEven[i] = 1;
outGroupStdEven[i] = 1;
groupValidFlagEven[i] = FALSE;
}
// Stats for "odd" lines
inGroupMeanOdd[i] = 0;
outGroupMeanOdd[i] = 0;
inGroupStdOdd[i] = 0;
outGroupStdOdd[i] = 0;
inGroupCountOdd = 0;
outGroupCountOdd = 0;
outMinOdd[i] = 255*255;
inMinOdd[i] = 255*255;
outMaxOdd[i] = 0;
inMaxOdd[i] = 0;
for (j = patternStart + i; j < PULLDOWN_HIST_LEN; j++)
{
if (state->pulldownSadHistOdd[j] == MISSING_SAD ||
state->pulldownSadHistOdd[j] == UN_INIT_SAD)
continue;
if (((j - i) % 5) == 0)
{
inGroupMeanOdd[i] += state->pulldownSadHistOdd[j];
inGroupStdOdd[i] += state->pulldownSadHistOdd[j]*state->pulldownSadHistOdd[j];
if (inMaxOdd[i] < state->pulldownSadHistOdd[j])
inMaxOdd[i] = state->pulldownSadHistOdd[j];
if (inMinOdd[i] > state->pulldownSadHistOdd[j])
inMinOdd[i] = state->pulldownSadHistOdd[j];
inGroupCountOdd++;
}
else
{
outGroupMeanOdd[i] += state->pulldownSadHistOdd[j];
outGroupStdOdd[i] += state->pulldownSadHistOdd[j]*state->pulldownSadHistOdd[j];
if (outMinOdd[i] > state->pulldownSadHistOdd[j])
outMinOdd[i] = state->pulldownSadHistOdd[j];
if (outMaxOdd[i] < state->pulldownSadHistOdd[j])
outMaxOdd[i] = state->pulldownSadHistOdd[j];
outGroupCountOdd++;
}
}
// Is there enough valid data to analyze?
if ((inGroupCountOdd > 1) && (outGroupCountOdd > 3))
{
inGroupMeanOdd[i] = inGroupMeanOdd[i]/inGroupCountOdd;
if ((inGroupStdOdd[i]/inGroupCountOdd)-(inGroupMeanOdd[i]*inGroupMeanOdd[i]) > 0.0f)
inGroupStdOdd[i] = (float)sqrt((inGroupStdOdd[i]/inGroupCountOdd)-(inGroupMeanOdd[i]*inGroupMeanOdd[i]));
else
inGroupStdOdd[i] = 0.0f;
outGroupMeanOdd[i] = outGroupMeanOdd[i]/outGroupCountOdd;
if ((outGroupStdOdd[i]/outGroupCountOdd)-(outGroupMeanOdd[i]*outGroupMeanOdd[i]) > 0.0f)
outGroupStdOdd[i] = (float)sqrt((outGroupStdOdd[i]/outGroupCountOdd)-(outGroupMeanOdd[i]*outGroupMeanOdd[i]));
else
outGroupStdOdd[i] = 0.0f;
groupValidFlagOdd[i] = TRUE;
}
else
{
inGroupMeanOdd[i] = 0;
outGroupMeanOdd[i] = 0;
inGroupStdOdd[i] = 1;
outGroupStdOdd[i] = 1;
groupValidFlagOdd[i] = FALSE;
}
}
// Do we have a clear pattern? Always trust this test.
for (i = 0; i < 5; i++)
{
if (groupValidFlagEven[i] == FALSE)
continue;
if (groupValidFlagOdd[i] == FALSE)
continue;
if (groupValidFlagEven[(i+2)%5] == FALSE)
continue;
if (groupValidFlagOdd[(i+2)%5] == FALSE)
continue;
if ((inGroupMeanEven[i]+inThresh[patternStart]*inGroupStdEven[i] < outGroupMeanEven[i] - outThresh[patternStart]*outGroupStdEven[i]) &&
(inGroupMeanOdd[(i+2)%5]+inThresh[patternStart]*inGroupStdOdd[(i+2)%5] < outGroupMeanOdd[(i+2)%5] - outThresh[patternStart]*outGroupStdOdd[(i+2)%5]) &&
(inGroupMeanEven[i]+inGroupStdEven[i] < inGroupMeanOdd[i]) &&
(inGroupMeanOdd[(i+2)%5]+inGroupStdOdd[(i+2)%5] < inGroupMeanEven[(i+2)%5]))
{
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"clear pattern, i is %d, pulldown timer is %d, patternStart is %d\n",i,state->ulPulldownActiveTimerIntl,patternStart);
#endif
// Set the removal pattern phase
state->frameRemovalPattern = i;
// If this is the right frame remove it!
if (i == (PULLDOWN_HIST_LEN - 1) % 5)
{
// Set a counter that goes up if we have a consistent pattern 80+% of the time, down otherwise
if ((timestamp - state->lastRemovedTimestamp > 145) &&
(timestamp - state->lastRemovedTimestamp < 175))
{
if (state->ulPulldownActiveTimerIntl < 95)
state->ulPulldownActiveTimerIntl += 5;
else
{
state->ulPulldownActiveTimerIntl = 100;
state->bInterlacedTelecineSeen = TRUE;
}
if (state->ulPulldownActiveTimerProg > 5)
state->ulPulldownActiveTimerProg -= 5;
else
state->ulPulldownActiveTimerProg = 0;
}
else if (timestamp - state->lastRemovedTimestamp < 300)
{
if (state->ulPulldownActiveTimerIntl > 5)
state->ulPulldownActiveTimerIntl -= 5;
else
state->ulPulldownActiveTimerIntl = 0;
}
state->lastRemovedTimestamp = timestamp;
goto REMOVE_FRAME;
}
else if (i == ((PULLDOWN_HIST_LEN - 2) % 5))
{
obviousPatternFlag = TRUE;
goto INTERLEAVE_ODD;
}
else
goto DO_NOTHING;
}
if ((inGroupMeanOdd[i]+inThresh[patternStart]*inGroupStdOdd[i] < outGroupMeanOdd[i] - outThresh[patternStart]*outGroupStdOdd[i]) &&
(inGroupMeanEven[(i+2)%5]+inThresh[patternStart]*inGroupStdEven[(i+2)%5] < outGroupMeanEven[(i+2)%5] - outThresh[patternStart]*outGroupStdEven[(i+2)%5]) &&
(inGroupMeanOdd[i]+inGroupStdOdd[i] < inGroupMeanEven[i]) &&
(inGroupMeanEven[(i+2)%5]+inGroupStdEven[(i+2)%5] < inGroupMeanOdd[(i+2)%5]))
{
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"clear pattern, i is %d, pulldown timer is %d, patternStart is %d\n",i,state->ulPulldownActiveTimerIntl,patternStart);
#endif
// Set the removal pattern phase
state->frameRemovalPattern=i;
// If this is the right frame remove it!
if (i == (PULLDOWN_HIST_LEN - 1) % 5)
{
// Set a counter that goes up if we have a consistent pattern 80+% of the time, down otherwise
if ((timestamp - state->lastRemovedTimestamp > 145) &&
(timestamp - state->lastRemovedTimestamp < 175))
{
if (state->ulPulldownActiveTimerIntl < 95)
state->ulPulldownActiveTimerIntl += 5;
else
{
state->ulPulldownActiveTimerIntl = 100;
state->bInterlacedTelecineSeen = TRUE;
}
if (state->ulPulldownActiveTimerProg > 5)
state->ulPulldownActiveTimerProg -= 5;
else
state->ulPulldownActiveTimerProg = 0;
}
else if (timestamp - state->lastRemovedTimestamp < 300)
{
if (state->ulPulldownActiveTimerIntl > 5)
state->ulPulldownActiveTimerIntl -= 5;
else
state->ulPulldownActiveTimerIntl = 0;
}
state->lastRemovedTimestamp = timestamp;
goto REMOVE_FRAME;
}
else if (i == ((PULLDOWN_HIST_LEN - 2) % 5))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -