deintl.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:57k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. ////////////////////////////////////////////////////////
  36. // defines
  37. ////////////////////////////////////////////////////////
  38. // Defineing TIME_DEINTERLACE will time the deinterlacer
  39. // and write a file with filename TIME_DEINTERLACE_FILENAME
  40. // with the times.
  41. //#define TIME_DEINTERLACE
  42. //#define TIME_DEINTERLACE_FILENAME "d:\dintl.log"
  43. ////////////////////////////////////////////////////////
  44. // include files
  45. ////////////////////////////////////////////////////////
  46. #include "hlxclib/stdlib.h"
  47. #include "hlxclib/string.h"
  48. #define INTL_I420_CODE
  49. #ifdef TIME_DEINTERLACE
  50. #include "hlxclib/stdio.h"
  51. #endif
  52. #include "mmx_util.h"
  53. #include "deintl.h"
  54. ////////////////////////////////////////////////////////
  55. // internal prototypes
  56. ////////////////////////////////////////////////////////
  57. static void
  58. Deinterlace_RGB24(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  59. static void
  60. Deinterlace_I420(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  61. static void
  62. Deinterlace_RGB24_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  63. static void
  64. Deinterlace_I420_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  65. static void
  66. Deinterlace_I420_Advanced(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  67. static void
  68. Deinterlace_I420_EdgeInterp(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  69. static void
  70. Deinterlace_RGB24_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field);
  71. static void
  72. Deinterlace_I420_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field);
  73. static void
  74. Deinterlace_I420_FlipFlop(unsigned char *frame, unsigned char *temp_frame, int pels, int lines, int pitch, int format);
  75. #ifdef _M_IX86
  76. static void
  77. Deinterlace_I420_MMX(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format);
  78. #endif
  79. int
  80. C_DetectInterlace_I420(unsigned char *frame, unsigned char *prev_frame, int first_frame, int pels, int lines, int pitch);
  81. ////////////////////////////////////////////////////////
  82. // macros
  83. ////////////////////////////////////////////////////////
  84. #define MEDIAN_3(a,b,c)
  85. ((a > b)?
  86. (
  87. (b > c)?
  88. (b):
  89. (
  90. (a > c)?
  91. (c):
  92. (a)
  93. )
  94. ):
  95. (
  96. (a > c)?
  97. (a):
  98. (
  99. (b > c)?
  100. (c):
  101. (b)
  102. )
  103. ))
  104. #define MABS(v) (tmp=(v),((tmp)^(tmp>>31)))
  105. #define ABS(a)  (((a) < 0) ? (-(a)) : (a))
  106. #define DIFF_FCN(v) ((v)*(v)) // Squared difference
  107. static const int SQUARED_TAB[255+255+1] = {
  108.     65025,  64516,  64009,  63504,  63001,  62500,
  109.     62001,  61504,  61009,  60516,  60025,  59536,  59049,  58564,  58081,  57600,
  110.     57121,  56644,  56169,  55696,  55225,  54756,  54289,  53824,  53361,  52900,
  111.     52441,  51984,  51529,  51076,  50625,  50176,  49729,  49284,  48841,  48400,
  112.     47961,  47524,  47089,  46656,  46225,  45796,  45369,  44944,  44521,  44100,
  113.     43681,  43264,  42849,  42436,  42025,  41616,  41209,  40804,  40401,  40000,
  114.     39601,  39204,  38809,  38416,  38025,  37636,  37249,  36864,  36481,  36100,
  115.     35721,  35344,  34969,  34596,  34225,  33856,  33489,  33124,  32761,  32400,
  116.     32041,  31684,  31329,  30976,  30625,  30276,  29929,  29584,  29241,  28900,
  117.     28561,  28224,  27889,  27556,  27225,  26896,  26569,  26244,  25921,  25600,
  118.     25281,  24964,  24649,  24336,  24025,  23716,  23409,  23104,  22801,  22500,
  119.     22201,  21904,  21609,  21316,  21025,  20736,  20449,  20164,  19881,  19600,
  120.     19321,  19044,  18769,  18496,  18225,  17956,  17689,  17424,  17161,  16900,
  121.     16641,  16384,  16129,  15876,  15625,  15376,  15129,  14884,  14641,  14400,
  122.     14161,  13924,  13689,  13456,  13225,  12996,  12769,  12544,  12321,  12100,
  123.     11881,  11664,  11449,  11236,  11025,  10816,  10609,  10404,  10201,  10000,
  124.     9801,   9604,   9409,   9216,   9025,   8836,   8649,   8464,   8281,   8100,
  125.     7921,   7744,   7569,   7396,   7225,   7056,   6889,   6724,   6561,   6400,
  126.     6241,   6084,   5929,   5776,   5625,   5476,   5329,   5184,   5041,   4900,
  127.     4761,   4624,   4489,   4356,   4225,   4096,   3969,   3844,   3721,   3600,
  128.     3481,   3364,   3249,   3136,   3025,   2916,   2809,   2704,   2601,   2500,
  129.     2401,   2304,   2209,   2116,   2025,   1936,   1849,   1764,   1681,   1600,
  130.     1521,   1444,   1369,   1296,   1225,   1156,   1089,   1024,   961,    900,
  131.     841,    784,    729,    676,    625,    576,    529,    484,    441,    400,
  132.     361,    324,    289,    256,    225,    196,    169,    144,    121,    100,
  133.     81,     64,     49,     36,     25,     16,     9,      4,      1,      0,
  134.     1,      4,      9,      16,     25,     36,     49,     64,     81,     100,
  135.     121,    144,    169,    196,    225,    256,    289,    324,    361,    400,
  136.     441,    484,    529,    576,    625,    676,    729,    784,    841,    900,
  137.     961,    1024,   1089,   1156,   1225,   1296,   1369,   1444,   1521,   1600,
  138.     1681,   1764,   1849,   1936,   2025,   2116,   2209,   2304,   2401,   2500,
  139.     2601,   2704,   2809,   2916,   3025,   3136,   3249,   3364,   3481,   3600,
  140.     3721,   3844,   3969,   4096,   4225,   4356,   4489,   4624,   4761,   4900,
  141.     5041,   5184,   5329,   5476,   5625,   5776,   5929,   6084,   6241,   6400,
  142.     6561,   6724,   6889,   7056,   7225,   7396,   7569,   7744,   7921,   8100,
  143.     8281,   8464,   8649,   8836,   9025,   9216,   9409,   9604,   9801,   10000,
  144.     10201,  10404,  10609,  10816,  11025,  11236,  11449,  11664,  11881,  12100,
  145.     12321,  12544,  12769,  12996,  13225,  13456,  13689,  13924,  14161,  14400,
  146.     14641,  14884,  15129,  15376,  15625,  15876,  16129,  16384,  16641,  16900,
  147.     17161,  17424,  17689,  17956,  18225,  18496,  18769,  19044,  19321,  19600,
  148.     19881,  20164,  20449,  20736,  21025,  21316,  21609,  21904,  22201,  22500,
  149.     22801,  23104,  23409,  23716,  24025,  24336,  24649,  24964,  25281,  25600,
  150.     25921,  26244,  26569,  26896,  27225,  27556,  27889,  28224,  28561,  28900,
  151.     29241,  29584,  29929,  30276,  30625,  30976,  31329,  31684,  32041,  32400,
  152.     32761,  33124,  33489,  33856,  34225,  34596,  34969,  35344,  35721,  36100,
  153.     36481,  36864,  37249,  37636,  38025,  38416,  38809,  39204,  39601,  40000,
  154.     40401,  40804,  41209,  41616,  42025,  42436,  42849,  43264,  43681,  44100,
  155.     44521,  44944,  45369,  45796,  46225,  46656,  47089,  47524,  47961,  48400,
  156.     48841,  49284,  49729,  50176,  50625,  51076,  51529,  51984,  52441,  52900,
  157.     53361,  53824,  54289,  54756,  55225,  55696,  56169,  56644,  57121,  57600,
  158.     58081,  58564,  59049,  59536,  60025,  60516,  61009,  61504,  62001,  62500,
  159.     63001,  63504,  64009,  64516,  65025
  160. };
  161. #define MSQUARED(v) (SQUARED_TAB[(v) + 255])
  162. // Some thresholds
  163. #define INTL_DIFF_THRESH 40000
  164. #define INTL_HORIZ_THRESH 80
  165. #ifdef TIME_DEINTERLACE
  166. static unsigned int num_avg = 0;
  167. static unsigned int num_med = 0;
  168. #endif
  169. int
  170. InitDeinterlace (
  171. int pels, int lines, int pitch, 
  172. int format, 
  173. INTL_MODE mode, 
  174. T_DEINTL_STATE **state)
  175. {
  176. T_DEINTL_STATE *new_state = 0;
  177. if (*state == 0)
  178. {
  179. new_state = (T_DEINTL_STATE *)malloc(sizeof(T_DEINTL_STATE));
  180. }
  181. if (new_state == 0)
  182. return 1;
  183. new_state->pels = pels;
  184. new_state->lines = lines;
  185. new_state->pitch = pitch;
  186. new_state->format = format;
  187. new_state->detection_measure = (lines > 242)?(16):(0);
  188. new_state->commit_deinterlace = FALSE;
  189. *state = new_state;
  190. return 0;
  191. }
  192. void
  193. FreeDeinterlace (T_DEINTL_STATE **state)
  194. {
  195. if (*state != 0)
  196. free(*state);
  197. *state = 0;
  198. }
  199. BOOL
  200. IsContentInterlaced (T_DEINTL_STATE *state)
  201. {
  202. if (state != 0)
  203. return (state->commit_deinterlace == 1)?(TRUE):(FALSE);
  204. return FALSE;
  205. }
  206. void
  207. ResetDeinterlace (T_DEINTL_STATE *state)
  208. {
  209. state->detection_measure = 0;
  210. state->commit_deinterlace = FALSE;
  211. }
  212. ////////////////////////////////////////////////////////
  213. //
  214. // Deinterlace
  215. //
  216. // Top level function to deinterlace a video frame
  217. //
  218. // Parameters:
  219. // frame: Pointer to the frame to deinterlace
  220. // prev_frame: Pointer to the previous frame.
  221. // Better results are achieved by giving
  222. // the previous *interlaced* frame
  223. // pels,
  224. // lines,
  225. // pitch: Frame dimensions
  226. // format: INTL_FORMAT_RGB24 or INTL_FORMAT_I420
  227. // mode: Choose either using both fields or
  228. // to remove one field entirely
  229. // (see 'deintl.h')
  230. //
  231. ////////////////////////////////////////////////////////
  232. int
  233. Deinterlace(
  234. unsigned char *frame, 
  235. unsigned char *prev_frame,
  236. int pels, int lines, int pitch,
  237. int format,
  238. int first_frame, 
  239. INTL_MODE mode,
  240. T_DEINTL_STATE *state)
  241. {
  242. if (pels == 0)
  243. pels = state->pels;
  244. if (lines == 0)
  245. lines = state->lines;
  246. if (pitch == 0)
  247. pitch = state->pitch;
  248. if (format == 0)
  249. format = state->format;
  250. unsigned char *pfp = (first_frame == TRUE)?(NULL):(prev_frame);
  251. // Unless were going to do detection first (i.e. in INTL_MODE_SMART_AUTO mode),
  252. // don't de-interlace when there is less than 242 lines.  This is a little
  253. // check to prevent unintentional de-interlacing of probable progressive frames.
  254. if (lines < 242 && mode != INTL_MODE_SMART_AUTO)
  255. return 0;
  256. // Run detection
  257. if (mode == INTL_MODE_SMART_AUTO)
  258. {
  259. unsigned char *detection_frame;
  260. unsigned char *detection_prev_frame;
  261. int res;
  262. if (format == INTL_FORMAT_I420)
  263. {
  264. // point to the Y-Plane
  265. detection_frame = frame;
  266. detection_prev_frame = prev_frame;
  267. }
  268. if (format == INTL_FORMAT_RGB24)
  269. {
  270. // point to the G-Plane
  271. detection_frame = frame + pels * lines;
  272. detection_prev_frame = prev_frame + pels * lines;
  273. }
  274. // Perform detection
  275. res = C_DetectInterlace_I420(
  276. detection_frame, 
  277. detection_prev_frame, 
  278. first_frame, 
  279. pels, lines, pitch);
  280. // Update the "detection measure" based on result of detection
  281. switch (res)
  282. {
  283. case INTL_STRONG_INTERLACE:
  284. {
  285. state->detection_measure = (31 * state->detection_measure + 256) >> 5;
  286. }
  287. break;
  288. case INTL_WEAK_INTERLACE:
  289. {
  290. state->detection_measure = (31 * state->detection_measure + 256) >> 5;
  291. }
  292. break;
  293. case INTL_WEAK_PROGRESSIVE:
  294. {
  295. state->detection_measure = (31 * state->detection_measure + 0) >> 5;
  296. }
  297. break;
  298. case INTL_STRONG_PROGRESSIVE:
  299. {
  300. state->detection_measure = 0;
  301. }
  302. break;
  303. }
  304. // If the detection measure is above a threshold, set this flag used
  305. // to indicate we are confident the content is interlaced.
  306. if (state->detection_measure > 128)
  307. {
  308. state->commit_deinterlace = TRUE;
  309. }
  310. // If the detection measure is above this threshold, we should
  311. // de-interlace this frame. Otherwise, return without de-interlacing
  312. if (state->detection_measure > 16)
  313. {
  314. mode = INTL_MODE_SMART;
  315. }
  316. else
  317. {
  318. return 0;
  319. }
  320. }
  321. #ifdef TIME_DEINTERLACE
  322. FILE *fp = NULL;
  323. double proc_time;
  324. USE_CODEC_TIMER;
  325. num_avg = 0;
  326. num_med = 0;
  327. START_CODEC_TIMER;
  328. #endif
  329. switch (format)
  330. {
  331. #ifdef INTL_RBG24_CODE
  332. case INTL_FORMAT_RGB24:
  333. Deinterlace_RGB24_Fast(frame, pfp, pels, lines, pitch, format);
  334. break;
  335. #endif
  336. #ifdef INTL_I420_CODE
  337. case INTL_FORMAT_I420:
  338. #ifdef USE_MMX_DEINTERLACING //_M_IX86
  339.         if (checkMmxAvailablity() & CPU_HAS_MMX)
  340. Deinterlace_I420_MMX(frame, pfp, pels, lines, pitch, format);
  341. else
  342. #endif
  343. // Neelesh's new deinterlacer.
  344. Deinterlace_I420_Advanced(frame, pfp, pels, lines, pitch, format);
  345. break;
  346. #endif
  347. }
  348. #ifdef TIME_DEINTERLACE
  349. STOP_CODEC_TIMER(proc_time);
  350. fp = fopen(TIME_DEINTERLACE_FILENAME,"a+");
  351. if (fp != NULL)
  352. {
  353. fprintf(fp,"deinterlace timet%ft%dt%dn",proc_time,num_avg,num_med);
  354. fclose(fp);
  355. }
  356. #endif
  357. return 1;
  358. }
  359. ////////////////////////////////////////////////////////
  360. //
  361. // C_DetectInterlace_I420
  362. //
  363. // Top level function to detect the presense of 
  364. // interlaced video content
  365. //
  366. // Parameters:
  367. // frame: Pointer to the frame to deinterlace
  368. // prev_frame: Pointer to the previous frame.
  369. // pels,
  370. // lines,
  371. // pitch: Frame dimensions
  372. //
  373. ////////////////////////////////////////////////////////
  374. // Threshold: If 8x8 SAD is above MOVEMENT_THRESH then
  375. // we'll decide that the block is in motion
  376. #define MOVEMENT_THRESH (400)
  377. // This is the factor by which 8x8 are skipped (not checked).
  378. // SKIP_FACTOR = 1 means no skipping.
  379. #define SKIP_FACTOR 4
  380. #ifdef DEBUG
  381. // This increments with each call, 
  382. // and is useful for debugging a specific frame.
  383. static unsigned int call_count = 0;
  384. #endif
  385. int
  386. C_DetectInterlace_I420(
  387. unsigned char *frame, 
  388. unsigned char *prev_frame, 
  389. int first_frame, 
  390. int pels, int lines, int pitch)
  391. {
  392. unsigned int image_size = (unsigned int)(pels * lines);
  393. // pre-calculated image size used for determining thresholds
  394. unsigned int interlaced_blocks = 0;
  395. // count of the number of 8x8 blocks that look to be interlaced
  396. unsigned int progressive_blocks = 0;
  397. // count of the number of 8x8 blocks that look to be progressive
  398. unsigned int step1v_tot = 0;
  399. // running total of the 1-step squared vertical difference of pixels
  400. unsigned int step2v_tot = 0;
  401. // running total of the 2-step squared vertical difference of pixels
  402. unsigned int step1h_tot = 0;
  403. // running total of the 1-step squared horizontal difference of pixels
  404. unsigned int step2h_tot = 0;
  405. // running total of the 2-step squared horizontal difference of pixels
  406. unsigned char *fp, *pp;
  407. unsigned char *f0, *f1, *f2, *f3;
  408. // various temporary frame pointers
  409. int i, j, k; // loop counter
  410. int tmp; // intermediate values for correlation and SAD macro
  411. int d0, d1; // SAD counters
  412. #ifdef DEBUG
  413. call_count++;
  414. #endif
  415. // We have no detection scheme for the first frame yet.
  416. if (first_frame)
  417. {
  418. return INTL_NO_DETECTION;
  419. }
  420. // Loop through tiled 8x8 blocks of the image
  421. for (i = 8; i < lines - 8; i += 8)
  422. {
  423. // Start pointer at new line
  424. fp = frame + i * pitch + (i & (8*(SKIP_FACTOR - 1))) + 8;
  425. pp = prev_frame + i * pitch + (i &  (8*(SKIP_FACTOR - 1))) + 8;
  426. for (j = 8; j < pels - 8; j += 8 * SKIP_FACTOR)
  427. {
  428. f0 = fp;
  429. f1 = f0 + pitch;
  430. f2 = pp;
  431. f3 = f2 + pitch;
  432. d0 = d1 = 0;
  433. // Calculate SAD for even and odd lines of 8x8 block.
  434. // We're doing a partial SAD here for speed.
  435. for (k = 0; k < 4; k++)
  436. {
  437. d0 += MABS(f0[0] - f2[0]);
  438. d0 += MABS(f0[2] - f2[2]);
  439. d0 += MABS(f0[4] - f2[4]);
  440. d0 += MABS(f0[6] - f2[6]);
  441. d1 += MABS(f1[1] - f3[1]);
  442. d1 += MABS(f1[3] - f3[3]);
  443. d1 += MABS(f1[5] - f3[5]);
  444. d1 += MABS(f1[7] - f3[7]);
  445. f0 += 2 * pitch;
  446. f1 += 2 * pitch;
  447. f2 += 2 * pitch;
  448. f3 += 2 * pitch;
  449. }
  450. d0 <<= 1;
  451. d1 <<= 1;
  452. // If there is enough difference to determine movement,
  453. // check this region for indications of interlaced artifacts
  454. if (d0 > MOVEMENT_THRESH || d1 > MOVEMENT_THRESH)
  455. {
  456. int step1v_corr = 0;
  457. int step2v_corr = 0;
  458. int step1h_corr = 0;
  459. int step2h_corr = 0;
  460. f0 = fp;
  461. f1 = f0 + pitch;
  462. f2 = f1 + pitch;
  463. // Determine 1 and 2 step pixel differences for 8x8 region
  464. for (k = 0; k < 4; k++)
  465. {
  466. tmp = f0[1] - f1[1];
  467. step1v_corr += MSQUARED(tmp);
  468. tmp = f0[1] - f2[1];
  469. step2v_corr += MSQUARED(tmp);
  470. tmp = f1[0] - f1[1];
  471. step1h_corr += MSQUARED(tmp);
  472. tmp = f1[0] - f1[2];
  473. step2h_corr += MSQUARED(tmp);
  474. tmp = f0[3] - f1[3];
  475. step1v_corr += MSQUARED(tmp);
  476. tmp = f0[3] - f2[3];
  477. step2v_corr += MSQUARED(tmp);
  478. tmp = f1[2] - f1[3];
  479. step1h_corr += MSQUARED(tmp);
  480. tmp = f1[2] - f1[4];
  481. step2h_corr += MSQUARED(tmp);
  482. tmp = f0[5] - f1[5];
  483. step1v_corr += MSQUARED(tmp);
  484. tmp = f0[5] - f2[5];
  485. step2v_corr += MSQUARED(tmp);
  486. tmp = f1[4] - f1[5];
  487. step1h_corr += MSQUARED(tmp);
  488. tmp = f1[4] - f1[6];
  489. step2h_corr += MSQUARED(tmp);
  490. tmp = f0[7] - f1[7];
  491. step1v_corr += MSQUARED(tmp);
  492. tmp = f0[7] - f2[7];
  493. step2v_corr += MSQUARED(tmp);
  494. tmp = f1[6] - f1[7];
  495. step1h_corr += MSQUARED(tmp);
  496. tmp = f1[6] - f1[8];
  497. step2h_corr += MSQUARED(tmp);
  498. f0 += 2 * pitch;
  499. f1 += 2 * pitch;
  500. f2 += 2 * pitch;
  501. }
  502. // These conditions indicate the block 
  503. // is very likely interlaced.
  504. if (step1v_corr > step2v_corr && 
  505. step1h_corr < (40*40*4*4) &&
  506. step2v_corr < (40*40*4*4))
  507. {
  508. interlaced_blocks++;
  509. }
  510. // These conditions indicate the block 
  511. // is very likely progressive.
  512. if (step1v_corr < 2 * step2v_corr && 
  513. step1h_corr < (40*40*4*4) &&
  514. step1v_corr < (40*40*4*4))
  515. {
  516. progressive_blocks++;
  517. }
  518. // Maintain totals
  519. step1v_tot += step1v_corr;
  520. step2v_tot += step2v_corr;
  521. step1h_tot += step1h_corr;
  522. step2h_tot += step2h_corr;
  523. }
  524. // Jump to the next 8x8 block
  525. fp += 8 * SKIP_FACTOR;
  526. pp += 8 * SKIP_FACTOR;
  527. }
  528. }
  529. #if (SKIP_FACTOR != 1)
  530. // If we're skipping some 8x8 block, 
  531. // acount for this by multiplying by skip factor
  532. interlaced_blocks *= SKIP_FACTOR;
  533. progressive_blocks *= SKIP_FACTOR;
  534. step1v_tot *= SKIP_FACTOR;
  535. step2v_tot *= SKIP_FACTOR;
  536. step1h_tot *= SKIP_FACTOR;
  537. step2h_tot *= SKIP_FACTOR;
  538. #endif
  539. // Scale these values. 
  540. // (Done to prevent overflow during later multiplies)
  541. step1v_tot /= image_size;
  542. step2v_tot /= image_size;
  543. step1h_tot /= image_size;
  544. step2h_tot /= image_size;
  545. // Interlaced Tests
  546. if (interlaced_blocks > progressive_blocks &&
  547. interlaced_blocks > (image_size >> 12))
  548. {
  549. return INTL_WEAK_INTERLACE;
  550. }
  551. if (step1v_tot * step2h_tot > step1h_tot * step2v_tot &&
  552. step1v_tot > step2v_tot &&
  553. 2 * interlaced_blocks > progressive_blocks &&
  554. interlaced_blocks > (image_size >> 10))
  555. {
  556. return INTL_WEAK_INTERLACE;
  557. }
  558. // Progressive Tests
  559. if (progressive_blocks > (image_size >> 10) &&
  560. progressive_blocks > (interlaced_blocks << 4))
  561. {
  562. return INTL_WEAK_PROGRESSIVE;
  563. }
  564. return INTL_NO_DETECTION;
  565. }
  566. ////////////////////////////////////////////////////////
  567. //
  568. // Deinterlace_RGB24_Fast
  569. //
  570. // Fast deinterlacing of RGB24 data, using both fields
  571. //
  572. ////////////////////////////////////////////////////////
  573. static void
  574. Deinterlace_RGB24_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  575. {
  576. int line, pel;
  577. unsigned char *fp1,*pfp1;
  578. unsigned char *fp2,*pfp2;
  579. unsigned char *fp3,*pfp3;
  580. unsigned char *fpr;
  581. unsigned char *fpb;
  582. // Only handle RGB for now...
  583. if (format != INTL_FORMAT_RGB24)
  584. return;
  585. for (line = 1; line < lines - 2; line += 2)
  586. {
  587. unsigned int a,b,c,d,e,f;
  588. int c_nw,c_ne,c_se,c_sw;
  589. int diff,tmp;
  590. int prev_mode = INTL_LINE_REMOVE_AVG;
  591. int mode = INTL_LINE_REMOVE_AVG;
  592. int next_mode = INTL_LINE_REMOVE_AVG;
  593. // current frame
  594. fpr = frame + line * pitch;
  595. fp2 = fpr + pels * lines;
  596. fp1 = fp2 - pitch;
  597. fp3 = fp2 + pitch;
  598. fpb = fp2 + pels * lines;
  599. // previous frame
  600. if (prev_frame != 0)
  601. {
  602. pfp2 = prev_frame + pels * lines + line * pitch;
  603. pfp1 = pfp2 - pitch;
  604. pfp3 = pfp2 + pitch;
  605. }
  606. else
  607. {
  608. pfp2 = fp2;
  609. pfp1 = fp1;
  610. pfp3 = fp3;
  611. }
  612. // initialize
  613. for (pel = 0; pel < pels - 4; pel += 4)
  614. {
  615. // Load *next* 4 pels
  616. a = ((unsigned int *)fp1)[1];
  617. b = ((unsigned int *)fp2)[1];
  618. c = ((unsigned int *)fp3)[1];
  619. // Get corners
  620. c_nw = (a >> 24);
  621. c_ne = (a & 0xff);
  622. c_sw = (c >> 24);
  623. c_se = (c & 0xff);
  624. // Edge detect
  625. tmp = c_nw + c_ne - c_sw - c_se;
  626. if ((tmp < 100) && (tmp > -100))
  627. {
  628. next_mode = INTL_LINE_REMOVE_AVG;
  629. goto proc;
  630. }
  631. tmp = c_ne + c_se - c_nw - c_sw;
  632. if (tmp > 100)
  633. {
  634. next_mode = INTL_LINE_REMOVE_AVG;
  635. goto proc;
  636. }
  637. if (tmp < -100)
  638. {
  639. next_mode = INTL_LINE_REMOVE_AVG;
  640. goto proc;
  641. }
  642. // Load previous pels
  643. d = ((unsigned int *)pfp1)[1];
  644. e = ((unsigned int *)pfp2)[1];
  645. f = ((unsigned int *)pfp3)[1];
  646. // Diff with previous pels
  647. tmp = c_nw;
  648. tmp -= (d >> 24);
  649. diff = tmp ^ (tmp >> 31);
  650. tmp = c_ne;
  651. tmp -= (d & 0xff);
  652. diff += tmp ^ (tmp >> 31);
  653. if (diff > 100)
  654. {
  655. next_mode = INTL_LINE_REMOVE_AVG;
  656. goto proc;
  657. }
  658. tmp = c_sw;
  659. tmp -= (f >> 24);
  660. diff += tmp ^ (tmp >> 31);
  661. tmp = c_se;
  662. tmp -= (f & 0xff);
  663. diff += tmp ^ (tmp >> 31);
  664. if (diff > 200)
  665. {
  666. next_mode = INTL_LINE_REMOVE_AVG;
  667. goto proc;
  668. }
  669. tmp = (b >> 24);
  670. tmp -= (e >> 24);
  671. diff += tmp ^ (tmp >> 31);
  672. tmp = (b & 0xff);
  673. tmp -= (e & 0xff);
  674. diff += tmp ^ (tmp >> 31);
  675. if (diff > 300)
  676. {
  677. next_mode = INTL_LINE_REMOVE_AVG;
  678. goto proc;
  679. }
  680. next_mode = INTL_LINE_REMOVE_MEDIAN;
  681. proc:
  682. if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN || next_mode == INTL_LINE_REMOVE_MEDIAN)
  683. {
  684. // median
  685. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  686. fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
  687. fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
  688. fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);
  689. fpr[0] = MEDIAN_3(fpr[-pitch],fpr[0],fpr[pitch]);
  690. fpr[1] = MEDIAN_3(fpr[-pitch+1],fpr[1],fpr[pitch+1]);
  691. fpr[2] = MEDIAN_3(fpr[-pitch+2],fpr[2],fpr[pitch+2]);
  692. fpr[3] = MEDIAN_3(fpr[-pitch+3],fpr[3],fpr[pitch+3]);
  693. fpb[0] = MEDIAN_3(fpb[-pitch],fpb[0],fpb[pitch]);
  694. fpb[1] = MEDIAN_3(fpb[-pitch+1],fpb[1],fpb[pitch+1]);
  695. fpb[2] = MEDIAN_3(fpb[-pitch+2],fpb[2],fpb[pitch+2]);
  696. fpb[3] = MEDIAN_3(fpb[-pitch+3],fpb[3],fpb[pitch+3]);
  697. #ifdef TIME_DEINTERLACE
  698. num_med++;
  699. #endif
  700. }
  701. else
  702. {
  703. // average
  704. a = ((unsigned int *)fp1)[0];
  705. c = ((unsigned int *)fp3)[0];
  706. ((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  707. a = ((unsigned int *)(fpr - pitch))[0];
  708. c = ((unsigned int *)(fpr + pitch))[0];
  709. ((unsigned int*)fpr)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  710. a = ((unsigned int *)(fpb - pitch))[0];
  711. c = ((unsigned int *)(fpb + pitch))[0];
  712. ((unsigned int*)fpb)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  713. #ifdef TIME_DEINTERLACE
  714. num_avg++;
  715. #endif
  716. }
  717. prev_mode = mode;
  718. mode = next_mode;
  719. fp1 += 4;
  720. fp2 += 4;
  721. fp3 += 4;
  722. pfp1 += 4;
  723. pfp2 += 4;
  724. pfp3 += 4;
  725. fpr += 4;
  726. fpb += 4;
  727. }
  728. // last 4 pels
  729. if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN)
  730. {
  731. // median
  732. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  733. fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
  734. fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
  735. fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);
  736. fpr[0] = MEDIAN_3(fpr[-pitch],fpr[0],fpr[pitch]);
  737. fpr[1] = MEDIAN_3(fpr[-pitch+1],fpr[1],fpr[pitch+1]);
  738. fpr[2] = MEDIAN_3(fpr[-pitch+2],fpr[2],fpr[pitch+2]);
  739. fpr[3] = MEDIAN_3(fpr[-pitch+3],fpr[3],fpr[pitch+3]);
  740. fpb[0] = MEDIAN_3(fpb[-pitch],fpb[0],fpb[pitch]);
  741. fpb[1] = MEDIAN_3(fpb[-pitch+1],fpb[1],fpb[pitch+1]);
  742. fpb[2] = MEDIAN_3(fpb[-pitch+2],fpb[2],fpb[pitch+2]);
  743. fpb[3] = MEDIAN_3(fpb[-pitch+3],fpb[3],fpb[pitch+3]);
  744. #ifdef TIME_DEINTERLACE
  745. num_med++;
  746. #endif
  747. }
  748. else
  749. {
  750. // average
  751. a = ((unsigned int *)fp1)[0];
  752. c = ((unsigned int *)fp3)[0];
  753. ((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  754. a = ((unsigned int *)(fpr - pitch))[0];
  755. c = ((unsigned int *)(fpr + pitch))[0];
  756. ((unsigned int*)fpr)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  757. a = ((unsigned int *)(fpb - pitch))[0];
  758. c = ((unsigned int *)(fpb + pitch))[0];
  759. ((unsigned int*)fpb)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  760. #ifdef TIME_DEINTERLACE
  761. num_avg++;
  762. #endif
  763. }
  764. }
  765. }
  766. ////////////////////////////////////////////////////////
  767. //
  768. // Deinterlace_RGB24
  769. //
  770. // Slow deinterlacing of RGB24 data, using both fields
  771. //
  772. ////////////////////////////////////////////////////////
  773. static void
  774. Deinterlace_RGB24(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  775. {
  776. int line, pel;
  777. unsigned char *fp1,*pfp1;
  778. unsigned char *fp2,*pfp2;
  779. unsigned char *fp3,*pfp3;
  780. int tmp;
  781. // Only handle RGB for now...
  782. if (format != INTL_FORMAT_RGB24)
  783. return;
  784. for (line = 1; line < lines - 2; line += 2)
  785. {
  786. int a,b,c,d,e;
  787. int mode = INTL_LINE_REMOVE_AVG;
  788. fp1 = frame + line * pitch;
  789. fp2 = frame + pels*lines + line * pitch;
  790. fp3 = frame + 2 * pels*lines + line * pitch;
  791. if (prev_frame != 0)
  792. {
  793. pfp1 = prev_frame + line * pitch;
  794. pfp2 = prev_frame + pels*lines + line * pitch;
  795. pfp3 = prev_frame + 2 * pels*lines + line * pitch;
  796. }
  797. else
  798. {
  799. pfp1 = fp1;
  800. pfp2 = fp2;
  801. pfp3 = fp3;
  802. }
  803. // initialize
  804. tmp = (int)(fp1[-pitch]) + (int)(fp2[-pitch]) + (int)(fp3[-pitch]) - (int)(pfp1[-pitch]) - (int)(pfp2[-pitch]) - (int)(pfp3[-pitch]);
  805. a = DIFF_FCN(tmp);
  806. tmp = (int)(fp1[0]) + (int)(fp2[0]) + (int)(fp3[0]) - (int)(pfp1[0]) - (int)(pfp2[0]) - (int)(pfp3[0]);
  807. a += DIFF_FCN(tmp);
  808. tmp = (int)(fp1[pitch]) + (int)(fp2[pitch]) + (int)(fp3[pitch]) - (int)(pfp1[pitch]) - (int)(pfp2[pitch]) - (int)(pfp3[pitch]);
  809. a += DIFF_FCN(tmp);
  810. fp1++;pfp1++;
  811. fp2++;pfp2++;
  812. fp3++;pfp3++;
  813. tmp = (int)(fp1[-pitch]) + (int)(fp2[-pitch]) + (int)(fp3[-pitch]) - (int)(pfp1[-pitch]) - (int)(pfp2[-pitch]) - (int)(pfp3[-pitch]);
  814. b = DIFF_FCN(tmp);
  815. tmp = (int)(fp1[0]) + (int)(fp2[0]) + (int)(fp3[0]) - (int)(pfp1[0]) - (int)(pfp2[0]) - (int)(pfp3[0]);
  816. b += DIFF_FCN(tmp);
  817. tmp = (int)(fp1[pitch]) + (int)(fp2[pitch]) + (int)(fp3[pitch]) - (int)(pfp1[pitch]) - (int)(pfp2[pitch]) - (int)(pfp3[pitch]);
  818. b += DIFF_FCN(tmp);
  819. fp1++;pfp1++;
  820. fp2++;pfp2++;
  821. fp3++;pfp3++;
  822. tmp = (int)(fp1[-pitch]) + (int)(fp2[-pitch]) + (int)(fp3[-pitch]) - (int)(pfp1[-pitch]) - (int)(pfp2[-pitch]) - (int)(pfp3[-pitch]);
  823. c = DIFF_FCN(tmp);
  824. tmp = (int)(fp1[0]) + (int)(fp2[0]) + (int)(fp3[0]) - (int)(pfp1[0]) - (int)(pfp2[0]) - (int)(pfp3[0]);
  825. c += DIFF_FCN(tmp);
  826. tmp = (int)(fp1[pitch]) + (int)(fp2[pitch]) + (int)(fp3[pitch]) - (int)(pfp1[pitch]) - (int)(pfp2[pitch]) - (int)(pfp3[pitch]);
  827. c += DIFF_FCN(tmp);
  828. tmp = (int)(fp1[-pitch+1]) + (int)(fp2[-pitch+1]) + (int)(fp3[-pitch+1]) - (int)(pfp1[-pitch+1]) - (int)(pfp2[-pitch+1]) - (int)(pfp3[-pitch+1]);
  829. d = DIFF_FCN(tmp);
  830. tmp = (int)(fp1[1]) + (int)(fp2[1]) + (int)(fp3[1]) - (int)(pfp1[1]) - (int)(pfp2[1]) - (int)(pfp3[1]);
  831. d += DIFF_FCN(tmp);
  832. tmp = (int)(fp1[pitch+1]) + (int)(fp2[pitch+1]) + (int)(fp3[pitch+1]) - (int)(pfp1[pitch+1]) - (int)(pfp2[pitch+1]) - (int)(pfp3[pitch+1]);
  833. d += DIFF_FCN(tmp);
  834. for (pel = 2; pel < pels - 2; pel++)
  835. {
  836. tmp = (int)(fp1[-pitch+2]) + (int)(fp2[-pitch+2]) + (int)(fp3[-pitch+2]) - (int)(pfp1[-pitch+2]) - (int)(pfp2[-pitch+2]) - (int)(pfp3[-pitch+2]);
  837. e = DIFF_FCN(tmp);
  838. tmp = (int)(fp1[2]) + (int)(fp2[2]) + (int)(fp3[2]) - (int)(pfp1[2]) - (int)(pfp2[2]) - (int)(pfp3[2]);
  839. e += DIFF_FCN(tmp);
  840. tmp = (int)(fp1[pitch+2]) + (int)(fp2[pitch+2]) + (int)(fp3[pitch+2]) - (int)(pfp1[pitch+2]) - (int)(pfp2[pitch+2]) - (int)(pfp3[pitch+2]);
  841. e += DIFF_FCN(tmp);
  842. if (mode == INTL_LINE_REMOVE_MEDIAN)
  843. {
  844. if (a + b + c + d + e > INTL_DIFF_THRESH)
  845. {
  846. a =  MABS(fp2[-pitch-2] - fp2[-pitch+1]);
  847. a += MABS(fp2[pitch-2] - fp2[pitch+1]);
  848. a += MABS(fp2[-pitch-1] - fp2[-pitch+2]);
  849. a += MABS(fp2[pitch-1] - fp2[pitch+2]);
  850. a <<= 1;
  851. a -= MABS(fp2[-pitch-2] - fp2[pitch-2]);
  852. a -= MABS(fp2[-pitch-1] - fp2[pitch-1]);
  853. a -= MABS(fp2[-pitch+1] - fp2[pitch+1]);
  854. a -= MABS(fp2[-pitch+2] - fp2[pitch+2]);
  855. if (a > 0)
  856. {
  857. mode = INTL_LINE_REMOVE_AVG;
  858. }
  859. }
  860. }
  861. else
  862. {
  863. if (a + b + c + d + e < INTL_DIFF_THRESH)
  864. {
  865. a =  MABS(fp2[-pitch-2] - fp2[-pitch+1]);
  866. a += MABS(fp2[pitch-2] - fp2[pitch+1]);
  867. a += MABS(fp2[-pitch-1] - fp2[-pitch+2]);
  868. a += MABS(fp2[pitch-1] - fp2[pitch+2]);
  869. a <<= 1;
  870. a -= MABS(fp2[-pitch-2] - fp2[pitch-2]);
  871. a -= MABS(fp2[-pitch-1] - fp2[pitch-1]);
  872. a -= MABS(fp2[-pitch+1] - fp2[pitch+1]);
  873. a -= MABS(fp2[-pitch+2] - fp2[pitch+2]);
  874. if (a < 0)
  875. {
  876. mode = INTL_LINE_REMOVE_MEDIAN;
  877. }
  878. }
  879. }
  880. if (mode == INTL_LINE_REMOVE_MEDIAN)
  881. {
  882. // median
  883. fp1[0] = MEDIAN_3(fp1[-pitch],fp1[0],fp1[pitch]);
  884. fp2[0] = MEDIAN_3(fp2[-pitch],fp2[0],fp2[pitch]);
  885. fp3[0] = MEDIAN_3(fp3[-pitch],fp3[0],fp3[pitch]);
  886. }
  887. else
  888. {
  889. // average
  890. tmp = fp1[-pitch];
  891. tmp += fp1[pitch];
  892. fp1[0] = (tmp >> 1);
  893. tmp = fp2[-pitch];
  894. tmp += fp2[pitch];
  895. fp2[0] = (tmp >> 1);
  896. tmp = fp3[-pitch];
  897. tmp += fp3[pitch];
  898. fp3[0] = (tmp >> 1);
  899. }
  900. a = b;
  901. b = c;
  902. c = d;
  903. d = e;
  904. fp1++;pfp1++;
  905. fp2++;pfp2++;
  906. fp3++;pfp3++;
  907. }
  908. }
  909. }
  910. ////////////////////////////////////////////////////////
  911. //
  912. // Deinterlace_I420_Fast
  913. //
  914. // Fast deinterlacing of I420 data, using both fields
  915. //
  916. ////////////////////////////////////////////////////////
  917. static void
  918. Deinterlace_I420_Fast(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  919. {
  920. int line, pel;
  921. unsigned char *fp1,*pfp1;
  922. unsigned char *fp2,*pfp2;
  923. unsigned char *fp3,*pfp3;
  924. // Only handle RGB for now...
  925. if (format != INTL_FORMAT_I420)
  926. return;
  927. for (line = 1; line < lines - 2; line += 2)
  928. {
  929. unsigned int a,b,c,d,e,f;
  930. int c_nw,c_ne,c_se,c_sw;
  931. int diff,tmp;
  932. int prev_mode = INTL_LINE_REMOVE_AVG;
  933. int mode = INTL_LINE_REMOVE_AVG;
  934. int next_mode = INTL_LINE_REMOVE_AVG;
  935. // current frame
  936. fp2 = frame + line * pitch;
  937. fp1 = fp2 - pitch;
  938. fp3 = fp2 + pitch;
  939. // previous frame
  940. if (prev_frame != 0)
  941. {
  942. pfp2 = prev_frame + line * pitch;
  943. pfp1 = pfp2 - pitch;
  944. pfp3 = pfp2 + pitch;
  945. }
  946. else
  947. {
  948. pfp2 = fp2;
  949. pfp1 = fp1;
  950. pfp3 = fp3;
  951. }
  952. // initialize
  953. for (pel = 0; pel < pels - 4; pel += 4)
  954. {
  955. // Load *next* 4 pels
  956. a = ((unsigned int *)fp1)[1];
  957. b = ((unsigned int *)fp2)[1];
  958. c = ((unsigned int *)fp3)[1];
  959. // Get corners
  960. c_nw = (a >> 24);
  961. c_ne = (a & 0xff);
  962. c_sw = (c >> 24);
  963. c_se = (c & 0xff);
  964. // Edge detect
  965. tmp = c_nw + c_ne - c_sw - c_se;
  966. if ((tmp < 100) && (tmp > -100))
  967. {
  968. next_mode = INTL_LINE_REMOVE_AVG;
  969. goto proc;
  970. }
  971. tmp = c_ne + c_se - c_nw - c_sw;
  972. if (tmp > 100)
  973. {
  974. next_mode = INTL_LINE_REMOVE_AVG;
  975. goto proc;
  976. }
  977. if (tmp < -100)
  978. {
  979. next_mode = INTL_LINE_REMOVE_AVG;
  980. goto proc;
  981. }
  982. // Load previous pels
  983. d = ((unsigned int *)pfp1)[1];
  984. e = ((unsigned int *)pfp2)[1];
  985. f = ((unsigned int *)pfp3)[1];
  986. // Diff with previous pels
  987. tmp = c_nw;
  988. tmp -= (d >> 24);
  989. diff = tmp ^ (tmp >> 31);
  990. tmp = c_ne;
  991. tmp -= (d & 0xff);
  992. diff += tmp ^ (tmp >> 31);
  993. if (diff > 100)
  994. {
  995. next_mode = INTL_LINE_REMOVE_AVG;
  996. goto proc;
  997. }
  998. tmp = c_sw;
  999. tmp -= (f >> 24);
  1000. diff += tmp ^ (tmp >> 31);
  1001. tmp = c_se;
  1002. tmp -= (f & 0xff);
  1003. diff += tmp ^ (tmp >> 31);
  1004. if (diff > 200)
  1005. {
  1006. next_mode = INTL_LINE_REMOVE_AVG;
  1007. goto proc;
  1008. }
  1009. tmp = (b >> 24);
  1010. tmp -= (e >> 24);
  1011. diff += tmp ^ (tmp >> 31);
  1012. tmp = (b & 0xff);
  1013. tmp -= (e & 0xff);
  1014. diff += tmp ^ (tmp >> 31);
  1015. if (diff > 300)
  1016. {
  1017. next_mode = INTL_LINE_REMOVE_AVG;
  1018. goto proc;
  1019. }
  1020. next_mode = INTL_LINE_REMOVE_MEDIAN;
  1021. proc:
  1022. if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN || next_mode == INTL_LINE_REMOVE_MEDIAN)
  1023. {
  1024. // median
  1025. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  1026. fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
  1027. fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
  1028. fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);
  1029. #ifdef TIME_DEINTERLACE
  1030. num_med++;
  1031. #endif
  1032. }
  1033. else
  1034. {
  1035. // average
  1036. a = ((unsigned int *)fp1)[0];
  1037. c = ((unsigned int *)fp3)[0];
  1038. ((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  1039. #ifdef TIME_DEINTERLACE
  1040. num_avg++;
  1041. #endif
  1042. }
  1043. prev_mode = mode;
  1044. mode = next_mode;
  1045. fp1 += 4;
  1046. fp2 += 4;
  1047. fp3 += 4;
  1048. pfp1 += 4;
  1049. pfp2 += 4;
  1050. pfp3 += 4;
  1051. }
  1052. // last 4 pels
  1053. if (mode == INTL_LINE_REMOVE_MEDIAN || prev_mode == INTL_LINE_REMOVE_MEDIAN)
  1054. {
  1055. // median
  1056. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  1057. fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
  1058. fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
  1059. fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);
  1060. #ifdef TIME_DEINTERLACE
  1061. num_med++;
  1062. #endif
  1063. }
  1064. else
  1065. {
  1066. // average
  1067. a = ((unsigned int *)fp1)[0];
  1068. c = ((unsigned int *)fp3)[0];
  1069. ((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  1070. #ifdef TIME_DEINTERLACE
  1071. num_avg++;
  1072. #endif
  1073. }
  1074. }
  1075. }
  1076. ////////////////////////////////////////////////////////
  1077. //
  1078. // Deinterlace_I420_Advanced
  1079. //
  1080. // Slow deinterlacing of I420 data, using Edge Interpolation
  1081. //
  1082. ////////////////////////////////////////////////////////
  1083. void
  1084. Deinterlace_I420_Advanced(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  1085. {
  1086. int line, pel;
  1087. unsigned char *fpy, *pfpy;
  1088. unsigned char *fp1, *pfp1;
  1089. unsigned char *fp2, *pfp2;
  1090. unsigned char *fp3, *pfp3;
  1091. int edge1, edge2, pedge1, pedge2, diff1, diff2;
  1092. unsigned int a, c;
  1093. int tmp, pitch2;
  1094. pitch2= pitch<<1;
  1095. for (line = 1; line < lines - 2; line += 2)
  1096. {
  1097. fpy = frame + line*pitch;
  1098. // current frame
  1099. // current line
  1100. fp2 = fpy;
  1101. // prev line
  1102. fp1 = fp2 - pitch;
  1103. // next line
  1104. fp3 = fp2 + pitch;
  1105. // current frame
  1106. // previous frame
  1107. if (prev_frame != 0)
  1108. {
  1109. pfpy = prev_frame + line * pitch;
  1110. pfp2 = pfpy;
  1111. pfp1 = pfp2 - pitch;
  1112. pfp3 = pfp2 + pitch;
  1113. }
  1114. else
  1115. {
  1116. pfp2 = fp2;
  1117. pfp1 = fp1;
  1118. pfp3 = fp3;
  1119. }
  1120. // handle first pel
  1121. tmp = (*fp1 + *fp3) >> 1;
  1122. *fp2 = (unsigned char) tmp;
  1123. fp1++;
  1124. fp2++;
  1125. fp3++;
  1126. pfp1++;
  1127. edge1 = (*fp1) + *(fp1+1) +*(fp1+2);
  1128. edge2=  (*fp3) + *(fp3+1) +*(fp3+2);
  1129. for (pel = 1; pel < pels-4; pel += 1)
  1130. {
  1131. edge1+=*(fp1+3);
  1132. edge2+=*(fp3+3);
  1133. tmp = (edge1 - edge2);
  1134. if( tmp > 160 || tmp < -160) {
  1135. // horiz
  1136. pfp3 = pfp1 + pitch2;
  1137. pedge1= *pfp1 + *(pfp1+1) + *(pfp1+2) + *(pfp1+3);
  1138. pedge2= *pfp3 + *(pfp3+1) + *(pfp3+2) + *(pfp3+3);
  1139. diff1 = (edge1 - pedge1);
  1140. if (diff1 < 0) diff1=-(diff1);
  1141. //diff1 = ABS(diff1);
  1142. diff2 = (edge2  - pedge2);
  1143. if (diff2 < 0) diff2=-(diff2);
  1144. //diff2 = ABS(diff2);
  1145. if ((diff1 + diff2) < 200) {
  1146. // not moving
  1147. *fp2 = MEDIAN_3(*fp1,*fp2,*fp3);
  1148. *(fp2+1) = MEDIAN_3(*(fp1+1),*(fp2+1),*(fp3+1));
  1149. #ifdef TIME_DEINTERLACE
  1150. num_med++;
  1151. #endif
  1152. edge1 -= *fp1;
  1153. edge2 -= *fp3;
  1154. fp1++;
  1155. fp2++;
  1156. fp3++;
  1157. pfp1++;
  1158. pel++;
  1159. edge1+=*(fp1+3);
  1160. edge2+=*(fp3+3);
  1161. } else {
  1162. tmp = *(fp2-1) + *fp1 + *fp3;
  1163. tmp *= 21845;
  1164. *fp2 =  (unsigned char) (tmp >> 16);
  1165. //tmp = (*(fp2-1)<<1) + *fp1 + *fp3;
  1166. //*fp2 =  (unsigned char) (tmp >> 2);
  1167. #ifdef TIME_DEINTERLACE
  1168. num_avg++;
  1169. #endif
  1170. }
  1171. } else {
  1172. // not horiz
  1173. // average
  1174. tmp = (*fp1 + *fp3) >> 1;
  1175. *fp2 = (unsigned char) tmp;
  1176. #ifdef TIME_DEINTERLACE
  1177. num_avg++;
  1178. #endif
  1179. }
  1180. edge1 -= (*fp1);
  1181. edge2 -= (*fp3);
  1182. fp1++;
  1183. fp2++;
  1184. fp3++;
  1185. pfp1++;
  1186. }
  1187. // handle last four pels
  1188. // last 4 pels
  1189. pfp3 = pfp1 + pitch2;
  1190. pedge1= *pfp1 + *(pfp1+1) + *(pfp1+2) + *(pfp1+3);
  1191. pedge2= *pfp3 + *(pfp3+1) + *(pfp3+2) + *(pfp3+3);
  1192. diff1 = (edge1 - pedge1);
  1193. diff1 = ABS(diff1);
  1194. diff2 = (edge2  - pedge2);
  1195. diff2 = ABS(diff2);
  1196. if ((diff1 + diff2) < 200) {
  1197. // not moving
  1198. // median
  1199. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  1200. fp2[1] = MEDIAN_3(fp1[1],fp2[1],fp3[1]);
  1201. fp2[2] = MEDIAN_3(fp1[2],fp2[2],fp3[2]);
  1202. fp2[3] = MEDIAN_3(fp1[3],fp2[3],fp3[3]);
  1203. #ifdef TIME_DEINTERLACE
  1204. num_med++;
  1205. #endif
  1206. }
  1207. else
  1208. {
  1209. // average
  1210. a = ((unsigned int *)fp1)[0];
  1211. c = ((unsigned int *)fp3)[0];
  1212. ((unsigned int*)fp2)[0] = (((a^c)>>1) & 0x7F7F7F7F) + (a&c);
  1213. #ifdef TIME_DEINTERLACE
  1214. num_avg++;
  1215. #endif
  1216. }
  1217. }
  1218. }
  1219. ////////////////////////////////////////////////////////
  1220. //
  1221. // Deinterlace_I420
  1222. //
  1223. // Slow deinterlacing of I420 data, using both fields
  1224. //
  1225. ////////////////////////////////////////////////////////
  1226. static void
  1227. Deinterlace_I420(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  1228. {
  1229. int line, pel;
  1230. unsigned char *fp1,*pfp1; // line above
  1231. unsigned char *fp2,*pfp2; // current line
  1232. unsigned char *fp3,*pfp3; // line below
  1233. int tmp;
  1234. // Only handle RGB for now...
  1235. if (format != INTL_FORMAT_I420)
  1236. return;
  1237. for (line = 1; line < lines - 2; line += 2)
  1238. {
  1239. int a,b,c,d,e;
  1240. int mode = INTL_LINE_REMOVE_AVG;
  1241. // set pointers
  1242. fp1 = frame + (line - 1) * pitch;
  1243. fp2 = fp1 + pitch;
  1244. fp3 = fp2 + pitch;
  1245. if (prev_frame != 0)
  1246. {
  1247. pfp2 = prev_frame + line * pitch;
  1248. pfp1 = pfp1 - pitch;
  1249. pfp3 = pfp2 + pitch;
  1250. }
  1251. else
  1252. {
  1253. pfp2 = fp2;
  1254. pfp1 = fp1;
  1255. pfp3 = fp3;
  1256. }
  1257. // initialize
  1258. // a
  1259. tmp = (int)(*fp1++);
  1260. tmp -= (int)(*pfp1++);
  1261. a = DIFF_FCN(tmp);
  1262. tmp = (int)(*fp2++);
  1263. tmp -= (int)(*pfp2++);
  1264. a += DIFF_FCN(tmp);
  1265. tmp = (int)(*fp3++);
  1266. tmp -= (int)(*pfp3++);
  1267. a += DIFF_FCN(tmp);
  1268. // b
  1269. tmp = (int)(*fp1++);
  1270. tmp -= (int)(*pfp1++);
  1271. b = DIFF_FCN(tmp);
  1272. tmp = (int)(*fp2++);
  1273. tmp -= (int)(*pfp2++);
  1274. b += DIFF_FCN(tmp);
  1275. tmp = (int)(*fp3++);
  1276. tmp -= (int)(*pfp3++);
  1277. b += DIFF_FCN(tmp);
  1278. // c
  1279. tmp = (int)(*fp1);
  1280. tmp -= (int)(*pfp1);
  1281. c = DIFF_FCN(tmp);
  1282. tmp = (int)(*fp2);
  1283. tmp -= (int)(*pfp2);
  1284. c += DIFF_FCN(tmp);
  1285. tmp = (int)(*fp3);
  1286. tmp -= (int)(*pfp3);
  1287. c += DIFF_FCN(tmp);
  1288. // d
  1289. tmp = (int)(fp1[1]);
  1290. tmp -= (int)(pfp1[1]);
  1291. d = DIFF_FCN(tmp);
  1292. tmp = (int)(fp2[1]);
  1293. tmp -= (int)(pfp2[1]);
  1294. d += DIFF_FCN(tmp);
  1295. tmp = (int)(fp3[1]);
  1296. tmp -= (int)(pfp3[1]);
  1297. d += DIFF_FCN(tmp);
  1298. for (pel = 2; pel < pels - 2; pel++)
  1299. {
  1300. // e
  1301. tmp = (int)(fp1[2]);
  1302. tmp -= (int)(pfp1[2]);
  1303. e = DIFF_FCN(tmp);
  1304. tmp = (int)(fp2[2]);
  1305. tmp -= (int)(pfp2[2]);
  1306. e += DIFF_FCN(tmp);
  1307. tmp = (int)(fp3[2]);
  1308. tmp -= (int)(pfp3[2]);
  1309. e += DIFF_FCN(tmp);
  1310. // should we switch line removal mode?
  1311. if (mode == INTL_LINE_REMOVE_MEDIAN)
  1312. {
  1313. if (a + b + c + d + e > INTL_DIFF_THRESH)
  1314. {
  1315. a =  MABS(fp1[-2] - fp1[+1]);
  1316. a += MABS(fp3[-2] - fp3[+1]);
  1317. a += MABS(fp1[-1] - fp1[+2]);
  1318. a += MABS(fp3[-1] - fp3[+2]);
  1319. a <<= 1;
  1320. a += MABS(fp1[-2] - fp3[-2]);
  1321. a += MABS(fp1[-1] - fp3[-1]);
  1322. a += MABS(fp1[+1] - fp3[+1]);
  1323. a += MABS(fp1[+2] - fp3[+2]);
  1324. if (a > 0)
  1325. {
  1326. mode = INTL_LINE_REMOVE_AVG;
  1327. }
  1328. }
  1329. }
  1330. else
  1331. {
  1332. if (a + b + c + d + e < INTL_DIFF_THRESH)
  1333. {
  1334. a =  MABS(fp1[-2] - fp1[+1]);
  1335. a += MABS(fp3[-2] - fp3[+1]);
  1336. a += MABS(fp1[-1] - fp1[+2]);
  1337. a += MABS(fp3[-1] - fp3[+2]);
  1338. a <<= 1;
  1339. a += MABS(fp1[-2] - fp3[-2]);
  1340. a += MABS(fp1[-1] - fp3[-1]);
  1341. a += MABS(fp1[+1] - fp3[+1]);
  1342. a += MABS(fp1[+2] - fp3[+2]);
  1343. if (a < 0)
  1344. {
  1345. mode = INTL_LINE_REMOVE_MEDIAN;
  1346. }
  1347. }
  1348. }
  1349. if (mode == INTL_LINE_REMOVE_MEDIAN)
  1350. {
  1351. // median
  1352. fp2[0] = MEDIAN_3(fp1[0],fp2[0],fp3[0]);
  1353. }
  1354. else
  1355. {
  1356. // average
  1357. tmp = fp1[0];
  1358. tmp += fp3[0];
  1359. fp2[0] = (tmp >> 1);
  1360. }
  1361. // shift difference measures
  1362. a = b;
  1363. b = c;
  1364. c = d;
  1365. d = e;
  1366. // move pointers
  1367. fp1++;pfp1++;
  1368. fp2++;pfp2++;
  1369. fp3++;pfp3++;
  1370. }
  1371. }
  1372. }
  1373. ////////////////////////////////////////////////////////
  1374. //
  1375. // Deinterlace_RGB24_Field
  1376. //
  1377. // Replaces 'frame' with only one field.
  1378. //  The result is an image with dimesions pels x lines/2
  1379. //
  1380. ////////////////////////////////////////////////////////
  1381. static void
  1382. Deinterlace_RGB24_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field)
  1383. {
  1384. int line;
  1385. unsigned char *in,*out;
  1386. lines >>= 1;
  1387. // R
  1388. in  = frame + field * pitch;
  1389. out = frame;
  1390. for (line = field; line < lines; line++)
  1391. {
  1392. memcpy(out, in, pels); /* Flawfinder: ignore */
  1393. out += pitch;
  1394. in  += (pitch << 1);
  1395. }
  1396. // G
  1397. in  = frame + pels * (lines << 1);
  1398. out = frame + pels * lines;
  1399. for (line = 0; line < lines; line++)
  1400. {
  1401. memcpy(out, in, pels); /* Flawfinder: ignore */
  1402. out += pitch;
  1403. in  += (pitch << 1);
  1404. }
  1405. // B
  1406. in  = frame + pels * (lines << 1) * 2;
  1407. out = frame + pels * lines * 2;
  1408. for (line = 0; line < lines; line++)
  1409. {
  1410. memcpy(out, in, pels); /* Flawfinder: ignore */
  1411. out += pitch;
  1412. in  += (pitch << 1);
  1413. }
  1414. }
  1415. ////////////////////////////////////////////////////////
  1416. //
  1417. // Deinterlace_I420_Field
  1418. //
  1419. // Replaces 'frame' with only one field.
  1420. //  The result is an image with dimesions pels x lines/2
  1421. //
  1422. ////////////////////////////////////////////////////////
  1423. static void
  1424. Deinterlace_I420_Field(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format, int field)
  1425. {
  1426. register int line;
  1427. register unsigned char *in,*out;
  1428. int in_pitch;
  1429. int out_pitch;
  1430. int out_lines;
  1431. // Y
  1432. in_pitch = (pitch << 1);
  1433. out_pitch = pitch;
  1434. out_lines = (lines >> 1) & ~3;
  1435. in  = frame + field * pitch;
  1436. out = frame;
  1437. for (line = 0; line < out_lines; line++)
  1438. {
  1439. memcpy(out, in, pels); /* Flawfinder: ignore */
  1440. out += out_pitch;
  1441. in  += in_pitch;
  1442. }
  1443. pels >>= 1;
  1444. lines >>= 1;
  1445. in_pitch >>= 1;
  1446. out_pitch >>= 1;
  1447. out_lines >>= 1;
  1448. // U
  1449. in  = frame + ((pels * lines) << 2);
  1450. out = frame + ((pels * out_lines) << 2);
  1451. for (line = 0; line < out_lines; line++)
  1452. {
  1453. memcpy(out, in, pels); /* Flawfinder: ignore */
  1454. out += out_pitch;
  1455. in  += in_pitch;
  1456. }
  1457. // V
  1458. in  = frame + pels * lines * 5;
  1459. out = frame + pels * out_lines * 5;
  1460. for (line = 0; line < out_lines; line++)
  1461. {
  1462. memcpy(out, in, pels); /* Flawfinder: ignore */
  1463. out += out_pitch;
  1464. in  += in_pitch;
  1465. }
  1466. }
  1467. ////////////////////////////////////////////////////////
  1468. //
  1469. // Deinterlace_I420_FlipFlop
  1470. //
  1471. // The Odd field is put at the top of the frame,
  1472. //  the Even field is put up-side-down at the bottom.
  1473. //
  1474. ////////////////////////////////////////////////////////
  1475. static void
  1476. Deinterlace_I420_FlipFlop(unsigned char *frame, unsigned char *tempFrame, int pels, int lines, int pitch, int format)
  1477. {
  1478. int lineCounter;
  1479. //  reorder the frame, even field on top, Y, Cr then Cb
  1480. for(lineCounter=0;lineCounter<lines;lineCounter+=2)
  1481. {
  1482. memcpy(tempFrame+((lineCounter>>1)*(pels)), /* Flawfinder: ignore */
  1483. frame+lineCounter*pels,pels);
  1484. }
  1485. for(lineCounter=0;lineCounter<(lines>>1);lineCounter+=2)
  1486. {
  1487. memcpy(tempFrame+((lineCounter>>1)*(pels>>1)) + (pels*lines) /* Flawfinder: ignore */
  1488. ,frame+(pels*lines)+lineCounter*(pels>>1),(pels>>1));
  1489. }
  1490. for(lineCounter=0;lineCounter<(lines>>1);lineCounter+=2)
  1491. {
  1492. memcpy(tempFrame+((lineCounter>>1)*(pels>>1)) +(pels*lines*5/4) /* Flawfinder: ignore */
  1493. ,frame+(pels*lines*5/4)+lineCounter*(pels>>1),(pels>>1));
  1494. }
  1495. for(lineCounter=1;lineCounter<lines+1;lineCounter+=2)
  1496. {
  1497. memcpy(tempFrame+((lines-1)-(lineCounter>>1))*pels, /* Flawfinder: ignore */
  1498. frame+lineCounter*pels,pels);
  1499. }
  1500. for(lineCounter=1;lineCounter<(lines>>1)+1;lineCounter+=2)
  1501. {
  1502. memcpy(tempFrame + (pels*lines) + /* Flawfinder: ignore */
  1503. (((lines>>1)-1)-(lineCounter>>1))*(pels>>1),frame+(pels*lines)+lineCounter*(pels>>1),(pels>>1));
  1504. }
  1505. for(lineCounter=1;lineCounter<(lines>>1)+1;lineCounter+=2)
  1506. {
  1507. memcpy(tempFrame + (pels*lines*5/4) + /* Flawfinder: ignore */
  1508. (((lines>>1)-1)-(lineCounter>>1))*(pels>>1),frame+(pels*lines*5/4)+lineCounter*(pels>>1),(pels>>1));
  1509. }
  1510. memcpy(frame,tempFrame,(pels*lines*3)/2); /* Flawfinder: ignore */
  1511. return;
  1512. }
  1513. #ifdef _M_IX86
  1514. ////////////////////////////////////////////////////////
  1515. //
  1516. // Deinterlace_I420_MMX
  1517. //
  1518. // MMX optimized deinterlacing of I420 data, using both fields
  1519. //
  1520. ////////////////////////////////////////////////////////
  1521. static void
  1522. Deinterlace_I420_MMX(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  1523. {
  1524. int line_shift;
  1525. int pels_div8;
  1526. pels_div8 = (pels >> 3); // round down
  1527. line_shift = ((pitch << 1) - (pels & ~7));
  1528. __asm {
  1529. mov ecx, lines // ecx -> lines
  1530. shr ecx, 1 // ecx -> lines/2
  1531. mov edx, pitch // pitch
  1532. mov eax, edx
  1533. neg eax // -pitch
  1534. mov esi, frame // esi -> current frame
  1535. add esi, pitch; // move esi to the next line
  1536. pxor mm7, mm7
  1537. ALIGN 16
  1538. line_loop:
  1539. mov ebx, pels_div8 // ebx -> pels/8 (rounded down)
  1540. ALIGN 16
  1541. pel_loop:
  1542. // median = (upper & A) | (mid & B) | (lower & C)
  1543. // e.g....
  1544. movq mm0,[esi+eax] // 1 2 1 3 2 3 1 3 = mm0 = (upper)
  1545. movq mm1,[esi] // 2 1 3 1 3 2 1 3 = mm1 = (mid)
  1546. movq mm2,[esi+edx] // 3 3 2 2 1 1 2 3 = mm2 = (lower)
  1547. movq mm3,mm1 // 2 1 3 1 3 2 1 3 = mm3
  1548. psubusb mm3,mm0 // 1 0 2 0 1 0 0 0 = mm3
  1549. pcmpeqb mm3,mm7 // 0 1 0 1 0 1 1 1 = mm3 = (upper > mid)
  1550. movq mm4,mm2 // 3 3 2 2 1 1 2 3 = mm4
  1551. psubusb mm4,mm1 // 1 2 0 1 0 0 1 0 = mm4
  1552. pcmpeqb mm4,mm7 // 0 0 1 0 1 1 0 1 = mm4 = (mid > lower)
  1553. movq mm6,mm3 // 0 1 0 1 0 1 1 1 = mm6
  1554. pxor mm6,mm4 // 0 1 1 1 1 0 1 0 = mm6 = ~(B)
  1555. pandn mm6,mm1 // 2 0 0 0 0 2 1 0 = mm6 = (mid & B)
  1556. movq mm5,mm2 // 3 3 2 2 1 1 2 3 = mm5
  1557. psubusb mm5,mm0 // 2 1 1 0 0 0 1 0 = mm5
  1558. pcmpeqb mm5,mm7 // 0 0 0 1 1 1 0 1 = mm5 = (upper > lower)
  1559. movq mm1,mm5 // 0 0 0 1 1 1 0 1 = mm1
  1560. pxor mm1,mm3 // 0 1 0 0 1 0 1 0 = mm1 = (A)
  1561. pand mm1,mm0 // 0 2 0 0 2 0 1 0 = mm1 = (upper & A)
  1562. por   mm6,mm1 // 2 2 0 0 2 2 1 0 = mm6 = (upper & A) | (mid & B)
  1563. pxor mm4,mm5 // 0 0 1 1 0 0 0 1 = mm4 = (C)
  1564. pand mm4,mm2 // 0 0 2 2 0 0 0 3 = mm4 = (lower & C)
  1565. por   mm6,mm4 // 2 2 2 2 2 2 1 3 = mm6 = (upper & A) | (mid & B) | (lower & C)
  1566. movq [esi],mm6
  1567. lea esi,[esi+8]
  1568. dec ebx
  1569. jnz pel_loop
  1570. // any pels left???
  1571. mov ebx, pels
  1572. and ebx, 0x07
  1573. jnz last_pels
  1574. add esi, line_shift; // move esi to the next line
  1575. dec ecx
  1576. jnz line_loop
  1577. jmp done
  1578. last_pels:
  1579. // take care of last four pels
  1580. movd mm0,[esi+eax]
  1581. movd mm1,[esi]
  1582. movd mm2,[esi+edx]
  1583. movq mm3,mm1 // 2 1 3 1 3 2 1 3 = mm3
  1584. psubusb mm3,mm0 // 1 0 2 0 1 0 0 0 = mm3
  1585. pcmpeqb mm3,mm7 // 0 1 0 1 0 1 1 1 = mm3 = (upper > mid)
  1586. movq mm4,mm2 // 3 3 2 2 1 1 2 3 = mm4
  1587. psubusb mm4,mm1 // 1 2 0 1 0 0 1 0 = mm4
  1588. pcmpeqb mm4,mm7 // 0 0 1 0 1 1 0 1 = mm4 = (mid > lower)
  1589. movq mm6,mm3 // 0 1 0 1 0 1 1 1 = mm6
  1590. pxor mm6,mm4 // 0 1 1 1 1 0 1 0 = mm6 = ~(B)
  1591. pandn mm6,mm1 // 2 0 0 0 0 2 1 0 = mm6 = (mid & B)
  1592. movq mm5,mm2 // 3 3 2 2 1 1 2 3 = mm5
  1593. psubusb mm5,mm0 // 2 1 1 0 0 0 1 0 = mm5
  1594. pcmpeqb mm5,mm7 // 0 0 0 1 1 1 0 1 = mm5 = (upper > lower)
  1595. movq mm1,mm5 // 0 0 0 1 1 1 0 1 = mm1
  1596. pxor mm1,mm3 // 0 1 0 0 1 0 1 0 = mm1 = (A)
  1597. pand mm1,mm0 // 0 2 0 0 2 0 1 0 = mm1 = (upper & A)
  1598. por   mm6,mm1 // 2 2 0 0 2 2 1 0 = mm6 = (upper & A) | (mid & B)
  1599. pxor mm4,mm5 // 0 0 1 1 0 0 0 1 = mm4 = (C)
  1600. pand mm4,mm2 // 0 0 2 2 0 0 0 3 = mm4 = (lower & C)
  1601. por   mm6,mm4 // 2 2 2 2 2 2 1 3 = mm6 = (upper & A) | (mid & B) | (lower & C)
  1602. movd [esi],mm6
  1603. add esi, line_shift; // move esi to the next line
  1604. dec ecx
  1605. jnz line_loop
  1606. done:
  1607. emms
  1608. }
  1609. }
  1610. ////////////////////////////////////////////////////////
  1611. //
  1612. // Deinterlace_I420_Slow
  1613. //
  1614. // Slow deinterlacing of I420 data, 
  1615. //  with Rigorous Edge Interpolation using 
  1616. //  Optical Flow
  1617. //
  1618. ////////////////////////////////////////////////////////
  1619. static void
  1620. Deinterlace_I420_EdgeInterp(unsigned char *frame, unsigned char *prev_frame, int pels, int lines, int pitch, int format)
  1621. {
  1622. int line, pel, mcountfr=1, mcountfi=1, D1=0;
  1623. unsigned char *fpr, *fpg, *pfpg, *pfpr;
  1624. unsigned char *fp1, *pfp1;
  1625. unsigned char *fp2, *pfp2;
  1626. unsigned char *fp3, *pfp3;
  1627. # define IFrMThresh 10
  1628. # define IFsMThresh 20
  1629. # define FlowThresh 1200
  1630. # define StrictFlowThresh 5
  1631. # define adj 10
  1632. int frm =1;
  1633. int diff1;
  1634. int tmp;
  1635. int *tempLine, *ptempLine;
  1636. tempLine = (int*)malloc(pels*sizeof(int));
  1637. for (line = 1; line < lines - 2; line += 2)
  1638. {
  1639. int a,b,c,d,e,f;
  1640. int D1 =0;
  1641. unsigned char *tfp3;
  1642. memset(tempLine, -1, pels*sizeof(int));
  1643. fpr = frame + line*pitch;
  1644. fpg = fpr;
  1645. fp2 = fpg + adj;
  1646. ptempLine = &tempLine[0] + adj;
  1647. // prev line
  1648. fp1 = fp2 - pitch;
  1649. // next line
  1650. fp3 = fp2 + pitch;
  1651. // previous frame
  1652. if (prev_frame != 0)
  1653. {
  1654. pfpr = prev_frame + line * pitch;
  1655. pfpg = pfpr;
  1656. pfp2 = pfpg + adj;
  1657. pfp1 = pfp2 - pitch;
  1658. pfp3 = pfp2 + pitch;
  1659. }
  1660. else
  1661. {
  1662. Deinterlace_RGB24_Fast(frame, prev_frame, pels, lines, pitch, format);
  1663. free(tempLine);
  1664. return;
  1665. }
  1666. // initialize
  1667. for (pel = adj; pel < (pels - adj); pel += 1)
  1668. {
  1669. int moving = 0;
  1670. int fi, fD;
  1671. int minf;
  1672. int pix;
  1673. int error2, error21, error22, error3, d2=0, j;
  1674. // Load *next* pels
  1675. a = (int)(*fp1);
  1676. b = (int)(*fp2);
  1677. c = (int)(*fp3);
  1678. // intra frame
  1679. D1 = *(fp1+1) - *(fp1-1);
  1680. D1 = ABS(D1);
  1681. if( D1 > 20) { 
  1682. d = *(fp1+1);
  1683. e = *(fp1-1);
  1684. tfp3 = fp3;
  1685. tmp = (a - *(tfp3));
  1686. minf = DIFF_FCN(tmp);
  1687. tmp = (d - *(tfp3+1));
  1688. minf += DIFF_FCN(tmp);
  1689. tmp = (e - *(tfp3-1));
  1690. minf += DIFF_FCN(tmp);
  1691. fi = 0;
  1692. tfp3--;
  1693. for (j=-1; j>=-adj; j--) {
  1694. tmp = (a - *(tfp3));
  1695. fD = DIFF_FCN(tmp);
  1696. if (fD > minf)
  1697. goto gskip;
  1698. tmp = (d - *(tfp3+1));
  1699. fD= fD + DIFF_FCN(tmp);
  1700. if (fD > minf)
  1701. goto gskip;
  1702. tmp = (e - *(tfp3-1));
  1703. fD= fD + DIFF_FCN(tmp);
  1704. if(fD<minf) {
  1705. minf = fD;
  1706. fi = j;
  1707. }
  1708. gskip:
  1709. tfp3--;
  1710. }
  1711. tfp3 = fp3 + 1;
  1712. for (j=1; j<=adj; j++) {
  1713. tmp = (a - *(tfp3));
  1714. fD = DIFF_FCN(tmp);
  1715. if (fD > minf)
  1716. goto gskip2;
  1717. tmp = (d - *(tfp3+1));
  1718. fD += DIFF_FCN(tmp);
  1719. if (fD > minf)
  1720. goto gskip2;
  1721. tmp = (e - *(tfp3-1));
  1722. fD += DIFF_FCN(tmp);
  1723. if(fD<minf) {
  1724. minf = fD;
  1725. fi = j;
  1726. }
  1727. gskip2:
  1728. tfp3++;
  1729. }
  1730. #ifdef TIME_DEINTERLACE
  1731. //num_flow++;
  1732. #endif
  1733. if (minf < FlowThresh)  {
  1734. if ((fi == 1) || (fi == -1) || (fi == 0)) {
  1735. tempLine[pel] = (*fp1 + *fp3)/2;
  1736. } else {
  1737. f = *(fp3+ fi);
  1738. pix = (a + f) / 2;
  1739. d2 = (int)(fi)/2;
  1740. f = *(fp1 + d2);
  1741. tmp = (pix - f);
  1742. error2 = ABS(tmp);
  1743. f = *(fp1 + d2 + 1);
  1744. pix = (d + *(fp3 + fi + 1))/2;
  1745. tmp = (pix - f);
  1746. error21 = ABS(tmp);
  1747. f = *(fp1 + d2 -1);
  1748. pix = (e + *(fp3 + fi - 1))/2;
  1749. tmp = (pix - f);
  1750. error22 = ABS(tmp);
  1751. if(error2 < 15 && ( ((error21 < 15) && (error22 > 25)) || ((error21 > 25) && (error22 < 15)) ) ) {
  1752. pix = (a + *(fp3+fi)) / 2;
  1753. tempLine[pel + d2] = pix;
  1754. pix = (d + *(fp3 + fi + 1))/2;
  1755. tempLine[pel + d2 + 1] = pix;
  1756. pix = (e + *(fp3 + fi - 1))/2;
  1757. tempLine[pel + d2 - 1] = pix;
  1758. goto gadvance;
  1759. }
  1760. pix = (a + *(fp3 + fi))/2;
  1761. f = *(fp3 + d2);
  1762. tmp = (pix - f);
  1763. error3 = ABS(tmp);
  1764. f = *(fp3 + d2 + 1);
  1765. pix = (d + *(fp3 + fi + 1))/2;
  1766. tmp = (pix - f);
  1767. error21 = ABS(tmp);
  1768. f = *(fp3 + d2 -1);
  1769. pix = (e + *(fp3 + fi - 1))/2;
  1770. tmp = (pix - f);
  1771. error22 = ABS(tmp);
  1772. pix = (a + *(fp3 + fi))/2;
  1773. if( error3 < 15 && ( ((error21 < 15) && (error22 > 25)) || ((error21 > 25) && (error22 < 15))) ) {
  1774. tempLine[pel + d2] = pix;
  1775. pix = (d + *(fp3 + fi + 1))/2;
  1776. tempLine[pel + d2 + 1] = pix;
  1777. pix = (e + *(fp3 + fi - 1))/2;
  1778. tempLine[pel + d2 - 1] = pix;
  1779. goto gadvance;
  1780. } else {
  1781. /*
  1782. *fp2 = 0;
  1783. *fpr2 = 0;
  1784. *fpb2 = 255;
  1785. tempLine[pel] = 0;
  1786. */
  1787. }
  1788. }
  1789. } else {
  1790. /*
  1791. *fp2 = 0;
  1792. *fpr2 = 255;
  1793. *fpb2 = 0;
  1794. tempLine[pel] = 0;
  1795. */
  1796. }
  1797. }
  1798. gadvance:
  1799. fp1++;
  1800. fp2++;
  1801. fp3++;
  1802. pfp1++;
  1803. pfp2++;
  1804. pfp3++;
  1805. ptempLine++;
  1806. }
  1807. // current frame
  1808. // current line
  1809. fp2 = fpg;
  1810. // prev line
  1811. fp1 = fp2 - pitch;
  1812. // next line
  1813. fp3 = fp2 + pitch;
  1814. // current frame
  1815. //prev frame
  1816. // current line
  1817. pfp2 = pfpg;
  1818. // prev line
  1819. pfp1 = pfp2 - pitch;
  1820. // next line
  1821. pfp3 = pfp2 + pitch;
  1822. ptempLine = &tempLine[0];
  1823. for (pel = 0; pel < pels-1; pel += 1)
  1824. {
  1825. // change
  1826. tmp = (*fp1 - *(fp3));
  1827. diff1 = DIFF_FCN(tmp);
  1828. tmp = (*(fp1-1) - *(fp3-1));
  1829. diff1 += DIFF_FCN(tmp);
  1830. tmp = (*(fp3+1) - *(pfp3+1));
  1831. diff1 += DIFF_FCN(tmp);
  1832. if( ABS(diff1) > 4800 ) {
  1833. // horiz
  1834. tmp = (*fp1 - *(pfp1));
  1835. diff1 = DIFF_FCN(tmp);
  1836. tmp = (*(fp1-1) - *(pfp1-1));
  1837. diff1 += DIFF_FCN(tmp);
  1838. tmp = (*(fp1+1) - *(pfp1+1));
  1839. diff1 += DIFF_FCN(tmp);
  1840. tmp = (*fp3 - *(pfp3));
  1841. diff1 += DIFF_FCN(tmp);
  1842. tmp = (*(fp3-1) - *(pfp3-1));
  1843. diff1 += DIFF_FCN(tmp);
  1844. tmp = (*(fp3+1) - *(pfp3+1));
  1845. diff1 += DIFF_FCN(tmp);
  1846. if (diff1 < 2400) {
  1847. // not moving
  1848. *fp2 = MEDIAN_3(*fp1,*fp2,*fp3);
  1849. } else {
  1850. if (*ptempLine != -1) {
  1851. *fp2 = (unsigned char) *ptempLine;
  1852. } else {
  1853. tmp = (*fp1 + *fp3)/2;
  1854. *fp2 =  (unsigned char) tmp;
  1855. }
  1856. #ifdef TIME_DEINTERLACE
  1857. num_avg++;
  1858. #endif
  1859. }
  1860. } else {
  1861. // not horiz
  1862. // avg
  1863. if (*ptempLine != -1) {
  1864. D1 = *(fp1+1) - *(fp1-1);
  1865. D1 = ABS(D1);
  1866. if( D1 > 20) { 
  1867. *fp2 = (unsigned char) *ptempLine;
  1868. } else {
  1869. tmp = (*fp1 + *fp3)/2;
  1870. *fp2 =  (unsigned char) tmp;
  1871. // not vertical
  1872. }
  1873. } else {
  1874. tmp = (*fp1 + *fp3)/2;
  1875. *fp2 =  (unsigned char) tmp;
  1876. }
  1877. #ifdef TIME_DEINTERLACE
  1878. num_avg++;
  1879. #endif
  1880. }
  1881. fp1++;
  1882. fp2++;
  1883. fp3++;
  1884. pfp1++;
  1885. pfp2++;
  1886. pfp3++;
  1887. ptempLine++;
  1888. }
  1889. }
  1890. free(tempLine);
  1891. return;
  1892. }
  1893. #endif