📄 invtelec.cpp
字号:
ULONG32 inGroupCount,outGroupCount; float outMin[5],outMax[5],inMax[5]; BOOL groupValidFlag[5]; ULONG32 timeSinceLastFrame; BOOL obviousPatternFlag = FALSE; BOOL sceneChangeFlag = FALSE; if (state->firstFrame == TRUE) { // Initialize history timestamps with this first timestamp 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -