📄 deintl.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: deintl.cpp,v 1.7.32.1 2004/07/09 01:55:14 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */////////////////////////////////////////////////////////// defines////////////////////////////////////////////////////////// Defineing TIME_DEINTERLACE will time the deinterlacer// and write a file with filename TIME_DEINTERLACE_FILENAME// with the times.//#define TIME_DEINTERLACE//#define TIME_DEINTERLACE_FILENAME "d:\\dintl.log"////////////////////////////////////////////////////////// include files////////////////////////////////////////////////////////#include "hlxclib/stdlib.h"#include "hlxclib/string.h"#define INTL_I420_CODE#ifdef TIME_DEINTERLACE#include "hlxclib/stdio.h"#endif#include "mmx_util.h"#include "deintl.h"////////////////////////////////////////////////////////// internal prototypes////////////////////////////////////////////////////////static voidDeinterlace_RGB24(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_I420(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_RGB24_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_I420_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_I420_Advanced(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_I420_EdgeInterp(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);static voidDeinterlace_RGB24_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field);static voidDeinterlace_I420_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field);static voidDeinterlace_I420_FlipFlop(unsigned char *frame, unsigned char *temp_frame, int pels, int lines, int pitch, int format);#ifdef _M_IX86static voidDeinterlace_I420_MMX(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);#endifintC_DetectInterlace_I420(unsigned char *frame, unsigned char *prev_frame, int first_frame, int pels, int lines, int pitch);////////////////////////////////////////////////////////// macros////////////////////////////////////////////////////////#define MEDIAN_3(a,b,c) \ ((a > b)? \ ( \ (b > c)? \ (b): \ ( \ (a > c)? \ (c): \ (a) \ ) \ ): \ ( \ (a > c)? \ (a): \ ( \ (b > c)? \ (c): \ (b) \ ) \ )) \#define MABS(v) (tmp=(v),((tmp)^(tmp>>31)))#define ABS(a) (((a) < 0) ? (-(a)) : (a))#define DIFF_FCN(v) ((v)*(v)) // Squared differencestatic const int SQUARED_TAB[255+255+1] = { 65025, 64516, 64009, 63504, 63001, 62500, 62001, 61504, 61009, 60516, 60025, 59536, 59049, 58564, 58081, 57600, 57121, 56644, 56169, 55696, 55225, 54756, 54289, 53824, 53361, 52900, 52441, 51984, 51529, 51076, 50625, 50176, 49729, 49284, 48841, 48400, 47961, 47524, 47089, 46656, 46225, 45796, 45369, 44944, 44521, 44100, 43681, 43264, 42849, 42436, 42025, 41616, 41209, 40804, 40401, 40000, 39601, 39204, 38809, 38416, 38025, 37636, 37249, 36864, 36481, 36100, 35721, 35344, 34969, 34596, 34225, 33856, 33489, 33124, 32761, 32400, 32041, 31684, 31329, 30976, 30625, 30276, 29929, 29584, 29241, 28900, 28561, 28224, 27889, 27556, 27225, 26896, 26569, 26244, 25921, 25600, 25281, 24964, 24649, 24336, 24025, 23716, 23409, 23104, 22801, 22500, 22201, 21904, 21609, 21316, 21025, 20736, 20449, 20164, 19881, 19600, 19321, 19044, 18769, 18496, 18225, 17956, 17689, 17424, 17161, 16900, 16641, 16384, 16129, 15876, 15625, 15376, 15129, 14884, 14641, 14400, 14161, 13924, 13689, 13456, 13225, 12996, 12769, 12544, 12321, 12100, 11881, 11664, 11449, 11236, 11025, 10816, 10609, 10404, 10201, 10000, 9801, 9604, 9409, 9216, 9025, 8836, 8649, 8464, 8281, 8100, 7921, 7744, 7569, 7396, 7225, 7056, 6889, 6724, 6561, 6400, 6241, 6084, 5929, 5776, 5625, 5476, 5329, 5184, 5041, 4900, 4761, 4624, 4489, 4356, 4225, 4096, 3969, 3844, 3721, 3600, 3481, 3364, 3249, 3136, 3025, 2916, 2809, 2704, 2601, 2500, 2401, 2304, 2209, 2116, 2025, 1936, 1849, 1764, 1681, 1600, 1521, 1444, 1369, 1296, 1225, 1156, 1089, 1024, 961, 900, 841, 784, 729, 676, 625, 576, 529, 484, 441, 400, 361, 324, 289, 256, 225, 196, 169, 144, 121, 100, 81, 64, 49, 36, 25, 16, 9, 4, 1, 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000, 10201, 10404, 10609, 10816, 11025, 11236, 11449, 11664, 11881, 12100, 12321, 12544, 12769, 12996, 13225, 13456, 13689, 13924, 14161, 14400, 14641, 14884, 15129, 15376, 15625, 15876, 16129, 16384, 16641, 16900, 17161, 17424, 17689, 17956, 18225, 18496, 18769, 19044, 19321, 19600, 19881, 20164, 20449, 20736, 21025, 21316, 21609, 21904, 22201, 22500, 22801, 23104, 23409, 23716, 24025, 24336, 24649, 24964, 25281, 25600, 25921, 26244, 26569, 26896, 27225, 27556, 27889, 28224, 28561, 28900, 29241, 29584, 29929, 30276, 30625, 30976, 31329, 31684, 32041, 32400, 32761, 33124, 33489, 33856, 34225, 34596, 34969, 35344, 35721, 36100, 36481, 36864, 37249, 37636, 38025, 38416, 38809, 39204, 39601, 40000, 40401, 40804, 41209, 41616, 42025, 42436, 42849, 43264, 43681, 44100, 44521, 44944, 45369, 45796, 46225, 46656, 47089, 47524, 47961, 48400, 48841, 49284, 49729, 50176, 50625, 51076, 51529, 51984, 52441, 52900, 53361, 53824, 54289, 54756, 55225, 55696, 56169, 56644, 57121, 57600, 58081, 58564, 59049, 59536, 60025, 60516, 61009, 61504, 62001, 62500, 63001, 63504, 64009, 64516, 65025};#define MSQUARED(v) (SQUARED_TAB[(v) + 255])// Some thresholds#define INTL_DIFF_THRESH 40000#define INTL_HORIZ_THRESH 80#ifdef TIME_DEINTERLACEstatic unsigned int num_avg = 0;static unsigned int num_med = 0;#endifintInitDeinterlace ( int pels, int lines, int pitch, int format, INTL_MODE mode, T_DEINTL_STATE **state){ T_DEINTL_STATE *new_state = 0; if (*state == 0) { new_state = (T_DEINTL_STATE *)malloc(sizeof(T_DEINTL_STATE)); } if (new_state == 0) return 1; new_state->pels = pels; new_state->lines = lines; new_state->pitch = pitch; new_state->format = format; new_state->detection_measure = (lines > 242)?(16):(0); new_state->commit_deinterlace = FALSE; *state = new_state; return 0;}voidFreeDeinterlace (T_DEINTL_STATE **state){ if (*state != 0) free(*state); *state = 0;}BOOLIsContentInterlaced (T_DEINTL_STATE *state){ if (state != 0) return (state->commit_deinterlace == 1)?(TRUE):(FALSE); return FALSE;}voidResetDeinterlace (T_DEINTL_STATE *state){ state->detection_measure = 0; state->commit_deinterlace = FALSE;}//////////////////////////////////////////////////////////// Deinterlace//// Top level function to deinterlace a video frame//// Parameters:// frame: Pointer to the frame to deinterlace// prev_frame: Pointer to the previous frame.// Better results are achieved by giving// the previous *interlaced* frame// pels,// lines,// pitch: Frame dimensions// format: INTL_FORMAT_RGB24 or INTL_FORMAT_I420// mode: Choose either using both fields or// to remove one field entirely// (see 'deintl.h')//////////////////////////////////////////////////////////intDeinterlace( unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int first_frame, INTL_MODE mode, T_DEINTL_STATE *state){ if (pels == 0) pels = state->pels; if (lines == 0) lines = state->lines; if (pitch == 0) pitch = state->pitch; if (format == 0) format = state->format; unsigned char *pfp = (first_frame == TRUE)?(NULL):(prev_frame); // Unless were going to do detection first (i.e. in INTL_MODE_SMART_AUTO mode), // don't de-interlace when there is less than 242 lines. This is a little // check to prevent unintentional de-interlacing of probable progressive frames. if (lines < 242 && mode != INTL_MODE_SMART_AUTO) return 0; // Run detection if (mode == INTL_MODE_SMART_AUTO) { unsigned char *detection_frame; unsigned char *detection_prev_frame; int res; if (format == INTL_FORMAT_I420) { // point to the Y-Plane detection_frame = frame; detection_prev_frame = prev_frame; } if (format == INTL_FORMAT_RGB24) { // point to the G-Plane detection_frame = frame + pels * lines; detection_prev_frame = prev_frame + pels * lines; } // Perform detection res = C_DetectInterlace_I420( detection_frame, detection_prev_frame, first_frame, pels, lines, pitch); // Update the "detection measure" based on result of detection switch (res) { case INTL_STRONG_INTERLACE: { state->detection_measure = (31 * state->detection_measure + 256) >> 5; } break; case INTL_WEAK_INTERLACE: { state->detection_measure = (31 * state->detection_measure + 256) >> 5; } break; case INTL_WEAK_PROGRESSIVE: { state->detection_measure = (31 * state->detection_measure + 0) >> 5; } break; case INTL_STRONG_PROGRESSIVE: { state->detection_measure = 0; } break; } // If the detection measure is above a threshold, set this flag used // to indicate we are confident the content is interlaced. if (state->detection_measure > 128) { state->commit_deinterlace = TRUE; } // If the detection measure is above this threshold, we should // de-interlace this frame. Otherwise, return without de-interlacing if (state->detection_measure > 16) { mode = INTL_MODE_SMART; } else { return 0; } }#ifdef TIME_DEINTERLACE FILE *fp = NULL; double proc_time; USE_CODEC_TIMER; num_avg = 0; num_med = 0; START_CODEC_TIMER;#endif switch (format) {#ifdef INTL_RBG24_CODE case INTL_FORMAT_RGB24: Deinterlace_RGB24_Fast(frame, pfp, pels, lines, pitch, format); break;#endif#ifdef INTL_I420_CODE case INTL_FORMAT_I420:#ifdef USE_MMX_DEINTERLACING //_M_IX86 if (checkMmxAvailablity() & CPU_HAS_MMX) Deinterlace_I420_MMX(frame, pfp, pels, lines, pitch, format); else#endif // Neelesh's new deinterlacer. Deinterlace_I420_Advanced(frame, pfp, pels, lines, pitch, format); break;#endif }#ifdef TIME_DEINTERLACE STOP_CODEC_TIMER(proc_time); fp = fopen(TIME_DEINTERLACE_FILENAME,"a+"); if (fp != NULL) { fprintf(fp,"deinterlace time\t%f\t%d\t%d\n",proc_time,num_avg,num_med); fclose(fp); }#endif return 1;}//////////////////////////////////////////////////////////// C_DetectInterlace_I420//// Top level function to detect the presense of // interlaced video content//// Parameters:// frame: Pointer to the frame to deinterlace// prev_frame: Pointer to the previous frame.// pels,// lines,// pitch: Frame dimensions//////////////////////////////////////////////////////////// Threshold: If 8x8 SAD is above MOVEMENT_THRESH then// we'll decide that the block is in motion#define MOVEMENT_THRESH (400)// This is the factor by which 8x8 are skipped (not checked).// SKIP_FACTOR = 1 means no skipping.#define SKIP_FACTOR 4#ifdef DEBUG// This increments with each call, // and is useful for debugging a specific frame.static unsigned int call_count = 0;#endifintC_DetectInterlace_I420( unsigned char *frame, unsigned char *prev_frame, int first_frame, int pels, int lines, int pitch){ unsigned int image_size = (unsigned int)(pels * lines); // pre-calculated image size used for determining thresholds unsigned int interlaced_blocks = 0; // count of the number of 8x8 blocks that look to be interlaced unsigned int progressive_blocks = 0; // count of the number of 8x8 blocks that look to be progressive unsigned int step1v_tot = 0; // running total of the 1-step squared vertical difference of pixels unsigned int step2v_tot = 0; // running total of the 2-step squared vertical difference of pixels unsigned int step1h_tot = 0; // running total of the 1-step squared horizontal difference of pixels unsigned int step2h_tot = 0; // running total of the 2-step squared horizontal difference of pixels unsigned char *fp, *pp; unsigned char *f0, *f1, *f2, *f3; // various temporary frame pointers int i, j, k; // loop counter int tmp; // intermediate values for correlation and SAD macro int d0, d1; // SAD counters#ifdef DEBUG call_count++;#endif // We have no detection scheme for the first frame yet. if (first_frame) { return INTL_NO_DETECTION; } // Loop through tiled 8x8 blocks of the image for (i = 8; i < lines - 8; i += 8) { // Start pointer at new line fp = frame + i * pitch + (i & (8*(SKIP_FACTOR - 1))) + 8; pp = prev_frame + i * pitch + (i & (8*(SKIP_FACTOR - 1))) + 8; for (j = 8; j < pels - 8; j += 8 * SKIP_FACTOR) { f0 = fp; f1 = f0 + pitch; f2 = pp; f3 = f2 + pitch; d0 = d1 = 0; // Calculate SAD for even and odd lines of 8x8 block. // We're doing a partial SAD here for speed. for (k = 0; k < 4; k++) { d0 += MABS(f0[0] - f2[0]); d0 += MABS(f0[2] - f2[2]); d0 += MABS(f0[4] - f2[4]); d0 += MABS(f0[6] - f2[6]); d1 += MABS(f1[1] - f3[1]); d1 += MABS(f1[3] - f3[3]); d1 += MABS(f1[5] - f3[5]); d1 += MABS(f1[7] - f3[7]); f0 += 2 * pitch; f1 += 2 * pitch; f2 += 2 * pitch; f3 += 2 * pitch; } d0 <<= 1; d1 <<= 1; // If there is enough difference to determine movement, // check this region for indications of interlaced artifacts if (d0 > MOVEMENT_THRESH || d1 > MOVEMENT_THRESH) { int step1v_corr = 0; int step2v_corr = 0; int step1h_corr = 0; int step2h_corr = 0; f0 = fp; f1 = f0 + pitch; f2 = f1 + pitch; // Determine 1 and 2 step pixel differences for 8x8 region for (k = 0; k < 4; k++) { tmp = f0[1] - f1[1]; step1v_corr += MSQUARED(tmp); tmp = f0[1] - f2[1]; step2v_corr += MSQUARED(tmp); tmp = f1[0] - f1[1]; step1h_corr += MSQUARED(tmp); tmp = f1[0] - f1[2]; step2h_corr += MSQUARED(tmp); tmp = f0[3] - f1[3]; step1v_corr += MSQUARED(tmp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -