📄 invtelec.cpp
字号:
state->frameRemovalPattern = (PULLDOWN_HIST_LEN-1)%5;
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"things look interlaced, pulldown timer is %d, patternStart is %d\n",state->ulPulldownActiveTimerProg,patternStart);
#endif
state->lastRemovedTimestamp = timestamp;
goto REMOVE_FRAME;
}
// Otherwise no pulldown!
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"no pattern, pulldown timer is %d, patternStart is %d\n",state->ulPulldownActiveTimerProg,patternStart);
#endif
if((inMax[(PULLDOWN_HIST_LEN-1)%5] > 30) || (outMax[(PULLDOWN_HIST_LEN-1)%5] >30))
if (state->ulPulldownActiveTimerProg > 0)
state->ulPulldownActiveTimerProg--;
NO_PATTERN:
// If there was no clear pattern, do nothing
state->checkNextFrameForProgressive = FALSE;
return INVTELE_RESULT_NO_PATTERN;
INTERLEAVE_ODD:
state->checkNextFrameForProgressive = FALSE;
// Test if data should be re-interleaved.
// Look at cross difference of old vs. re-stitched. Only replace if better
if (obviousPatternFlag == FALSE || sceneChangeFlag == TRUE)
{
switch (state->impl_id)
{
#ifdef ALLOW_MMX_INVTELE
case INVTELE_IMPL_ID_MMX:
{
RestitchCheck_MMX(data, prevData,
pels, lines, pels, &sumOld, &sumNew);
}
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) - (pNew[j+ll]&0xff00));
sumOld += (temp*temp);
temp = (float)((pNew[j]&0xff00) - (pOld[j+ll]&0xff00));
sumNew += (temp*temp);
}
pOld += 2*ll;
pNew += 2*ll;
}
}
break;
}
if (sumNew > sumOld)
{
return INVTELE_RESULT_FRAME_OK;
}
}
state->interleaveOddFlag = TRUE;
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"interleaving odd\n");
#endif
// Re-interleave
pNew = ((LONG32 *)data)+ll;
pOld = ((LONG32 *)prevData)+ll;
for (k = 1; k < lines; k += 2) // only do the luma.
{
memcpy(pNew,pOld,sizeof(ULONG32)*ll); /* Flawfinder: ignore */
pOld+=2*ll;
pNew+=2*ll;
}
return INVTELE_RESULT_FRAME_OK;
INTERLEAVE_EVEN:
state->checkNextFrameForProgressive = FALSE;
// Test if data should be re-interleaved.
// Look at cross difference of old vs. re-stitched. Only replace if better
if (obviousPatternFlag == FALSE || sceneChangeFlag == TRUE)
{
switch (state->impl_id)
{
#ifdef ALLOW_MMX_INVTELE
case INVTELE_IMPL_ID_MMX:
{
RestitchCheck_MMX(data + pels, prevData + pels,
pels, lines - 2, pels, &sumOld, &sumNew);
}
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) - (pNew[j+ll]&0xff00));
sumOld += (temp*temp);
temp = (float)((pNew[j+ll]&0xff00) - (pOld[j]&0xff00));
sumNew += (temp*temp);
}
pOld+=2*ll;
pNew+=2*ll;
}
}
break;
}
if (sumNew > sumOld)
{
return INVTELE_RESULT_FRAME_OK;
}
}
state->interleaveEvenFlag = TRUE;
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"interleaving even\n");
#endif
// Re-interleave
pNew = ((LONG32 *)data);
pOld = ((LONG32 *)prevData);
for (k = 0; k < lines; k += 2) // only do the luma.
{
memcpy(pNew,pOld,sizeof(ULONG32)*ll); /* Flawfinder: ignore */
pOld+=2*ll;
pNew+=2*ll;
}
return INVTELE_RESULT_FRAME_OK;
DO_NOTHING:
// One final check in this case
// If we are here, we think the frame is progressive.
// If we think the previous frame was also progressive, then
// the odd and even SADs should be somewhat similar. If not,
// we're in trouble.
if (state->checkNextFrameForProgressive)
{
if (state->ulPulldownActiveTimerProg < 10 &&
state->ulPulldownActiveTimerIntl > 90 &&
(sumEven > 8 * sumOdd || sumOdd > 8 * sumEven))
{
goto NO_PATTERN;
}
if (sceneChangeFlag == TRUE)
{
// Just return here because we want to be sure
// state->checkNextFrameForProgressive is TRUE
return INVTELE_RESULT_NO_PATTERN;
}
}
state->checkNextFrameForProgressive = TRUE;
return INVTELE_RESULT_FRAME_OK;
REMOVE_FRAME:
#ifdef CODEC_DEBUG_32PULLDOWN
fprintf(fp_log,"removing frame\n");
#endif
state->checkNextFrameForProgressive = FALSE;
return INVTELE_RESULT_DROP_FRAME;
TOO_EARLY:
state->checkNextFrameForProgressive = FALSE;
return INVTELE_RESULT_TOO_EARLY;
}
// Platform specific SSD functions
#ifdef ALLOW_MMX_INVTELE
void
SumSqaredFrameDiff_MMX(
unsigned char *frame,
unsigned char *prev_frame,
int pels,
int lines,
int pitch,
float *ssd_odd,
float *ssd_even)
{
unsigned int res_odd[2];
unsigned int res_even[2];
float pel_avg;
const unsigned int mask[2] = {0x00FF00FF, 0x00FF00FF};
int line_shift;
int pels_div8;
pels_div8 = (pels >> 3); // round down
line_shift = ((pitch) - (pels & ~7));
__asm {
mov ecx, lines // ecx -> lines
shr ecx, 1 // ecx -> lines/2
mov esi, frame // esi -> current frame
mov edi, prev_frame // edi -> previous frame
movq mm5, [mask]
pxor mm6, mm6 // mm6 -> odd ssd
pxor mm7, mm7 // mm7 -> even ssd
ALIGN 16
line_loop:
mov ebx, pels_div8 // ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop_even:
movq mm0,[esi]
movq mm1,[edi]
pand mm0, mm5
pand mm1, mm5
psubw mm0, mm1
pmaddwd mm0, mm0
paddd mm6, mm0
lea esi,[esi+8]
lea edi,[edi+8]
dec ebx
jnz pel_loop_even
add esi, line_shift; // move esi to the next line
add edi, line_shift; // move edi to the next line
mov ebx, pels_div8 // ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop_odd:
movq mm0,[esi]
movq mm1,[edi]
pand mm0, mm5
pand mm1, mm5
psubw mm0, mm1
pmaddwd mm0, mm0
paddd mm7, mm0
lea esi,[esi+8]
lea edi,[edi+8]
dec ebx
jnz pel_loop_odd
add esi, line_shift; // move esi to the next line
add edi, line_shift; // move edi to the next line
dec ecx
jnz line_loop
movq res_odd, mm6
movq res_even, mm7
emms
}
// fill "even" result
pel_avg = (float)(res_even[0] + res_even[1]);
pel_avg /= (float)((pels*lines)>>2);
*ssd_even = pel_avg;
// fill "odd" result
pel_avg = (float)(res_odd[0] + res_odd[1]);
pel_avg /= (float)((pels*lines)>>2);
*ssd_odd = pel_avg;
}
void
RestitchCheck_MMX(
unsigned char *frame,
unsigned char *prev_frame,
int pels,
int lines,
int pitch,
float *ssd_new,
float *ssd_old)
{
unsigned int res_new[2];
unsigned int res_old[2];
const unsigned int mask[2] = {0x00FF00FF, 0x00FF00FF};
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 esi, frame // esi -> current frame
mov edi, prev_frame // edi -> previous frame
mov edx, pitch // pitch
lea edi, [edi+edx] // edi -> previous frame + pitch
movq mm5, [mask]
pxor mm6, mm6 // mm6 -> odd ssd
pxor mm7, mm7 // mm7 -> even ssd
ALIGN 16
line_loop:
mov ebx, pels_div8 // ebx -> pels/8 (rounded down)
ALIGN 16
pel_loop:
movq mm0,[esi]
movq mm1,[esi + edx]
movq mm2,[edi]
pand mm0, mm5
pand mm1, mm5
pand mm2, mm5
psubw mm1, mm0
pmaddwd mm1, mm1
paddd mm6, mm1
psubw mm2, mm0
pmaddwd mm2, mm2
paddd mm7, mm2
lea esi, [esi+8]
lea edi, [edi+8]
dec ebx
jnz pel_loop
add esi, line_shift // move esi down 2 lines
add edi, line_shift // move edi down 2 lines
dec ecx
jnz line_loop
movq res_new, mm6
movq res_old, mm7
emms
}
// fill "new" result
*ssd_new = (float)(res_new[0] + res_new[1]);
// fill "old" result
*ssd_old = (float)(res_old[0] + res_old[1]);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -