deintl.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:57k
源码类别:

Symbian

开发平台:

Visual C++

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