softidct.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:30k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: softidct.c 543 2006-01-07 22:06:24Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23.  
  24. #include "../common.h"
  25. #include "softidct.h"
  26. #ifndef MIPS64
  27. #define MemCpy8 memcpy
  28. #define MemSet8 memset
  29. #else
  30. static void MemCpy8(void* dst,void* src,int len)
  31. {
  32. __asm( "addi $6,$6,-16;"
  33. "bltz $6,cpyskip16;"
  34. "cpyloop16:"
  35. "ldr $10,0($5);"
  36. "addi $6,$6,-16;"
  37. "ldr $11,8($5);"
  38. #ifdef MIPSVR41XX
  39. ".set noreorder;"
  40. "cache 13,0($4);" //cache without loading
  41. ".set reorder;"
  42. #endif
  43. "sdr $10,0($4);"
  44. "addi $5,$5,16;"
  45. "sdr $11,8($4);"
  46. "addi $4,$4,16;"
  47. "bgez $6,cpyloop16;"
  48. "cpyskip16:"
  49. "andi $6,$6,8;"
  50. "beq $6,$0,cpyskip8;"
  51. "ldr $10,0($5);"
  52. "sdr $10,0($4);"
  53. "cpyskip8:");
  54. }
  55. static void MemSet8(void* dst,int v,int len) 
  56. {
  57. __asm( "dsll $10,$5,56;"
  58. "dsrl $11,$10,8;"
  59. "or $10,$10,$11;"
  60. "dsrl $11,$10,16;"
  61. "or $10,$10,$11;"
  62. "dsrl $11,$10,32;"
  63. "or $10,$10,$11;"
  64. "addi $6,$6,-16;"
  65. "bltz $6,setskip16;"
  66. "setloop16:"
  67. #ifdef MIPSVR41XX
  68. ".set noreorder;"
  69. "cache 13,0($4);" //cache without loading
  70. ".set reorder;"
  71. #endif
  72. "sdr $10,0($4);"
  73. "addi $6,$6,-16;"
  74. "sdr $10,8($4);"
  75. "addi $4,$4,16;"
  76. "bgez $6,setloop16;"
  77. "setskip16:"
  78. "andi $6,$6,8;"
  79. "beq $6,$0,setskip8;"
  80. "sdr $10,0($4);"
  81. "setskip8:");
  82. }
  83. #endif
  84. static void FillEdge(uint8_t *Ptr, int Width, int Height, int EdgeX, int EdgeY)
  85. {
  86. int n;
  87. uint8_t *p;
  88. int InnerWidth = Width - EdgeX*2;
  89. int InnerHeight = Height - EdgeY*2;
  90. // left and right
  91. p = Ptr + EdgeX + EdgeY * Width;
  92. for (n=0;n<InnerHeight;++n)
  93. {
  94. MemSet8(p-EdgeX, p[0], EdgeX);
  95. MemSet8(p+InnerWidth,p[InnerWidth-1], EdgeX);
  96. p += Width;
  97. }
  98. // top
  99. p = Ptr;
  100. for (n=0;n<EdgeY;++n)
  101. {
  102. MemCpy8(p, Ptr+EdgeY * Width, Width);
  103. p += Width;
  104. }
  105. // bottom
  106. p = Ptr + (Height-EdgeY)*Width;
  107. for (n=0;n<EdgeY;++n)
  108. {
  109. MemCpy8(p, Ptr+(Height-EdgeY-1)*Width, Width);
  110. p += Width;
  111. }
  112. }
  113. static void FillEdgeYUV(softidct* p,uint8_t *Ptr)
  114. {
  115. FillEdge(Ptr, p->BufWidth, p->BufHeight, EDGE, EDGE);
  116. Ptr += p->YToU;
  117. FillEdge(Ptr, p->BufWidth>>p->UVX2, p->BufHeight>>p->UVY2, EDGE>>p->UVX2, EDGE>>p->UVY2);
  118. Ptr += p->YToU >> (p->UVX2+p->UVY2);
  119. FillEdge(Ptr, p->BufWidth>>p->UVX2, p->BufHeight>>p->UVY2, EDGE>>p->UVX2, EDGE>>p->UVY2);
  120. }
  121. #if defined(MIPS64_WIN32) 
  122. static int TouchPages(softidct* p)
  123. {
  124. uint8_t* i;
  125. int Sum = 0;
  126. for (i=p->CodeBegin;i<p->CodeEnd;i+=p->CodePage)
  127. Sum += *i;
  128. return Sum;
  129. }
  130. #endif
  131. static int Lock(softidct* p,int No,planes Planes,int* Brightness,video* Format)
  132. {
  133. if (Brightness)
  134. *Brightness = 0;
  135. if (Format)
  136. {
  137. *Format = p->Out.Format.Format.Video;
  138. Format->Pitch = p->BufWidth;
  139. Format->Width = p->BufWidth - 2*EDGE;
  140. Format->Height = p->BufHeight - 2*EDGE;
  141. }
  142. if (No<0 || No>=p->BufCount)
  143. {
  144. Planes[0] = NULL;
  145. Planes[1] = NULL;
  146. Planes[2] = NULL;
  147. return ERR_INVALID_PARAM;
  148. }
  149. Planes[0] = p->Buffer[No] + EDGE + EDGE*p->BufWidth;
  150. Planes[1] = p->Buffer[No] + p->YToU + (EDGE >> p->UVX2) + (EDGE >> p->UVY2)*(p->BufWidth >> p->UVX2);
  151. Planes[2] = (uint8_t*)Planes[1] + (p->YToU >> (p->UVX2+p->UVY2));
  152. return ERR_NONE;
  153. }
  154. static void Unlock(softidct* p,int No)
  155. {
  156. }
  157. #if defined(CONFIG_IDCT_LOWRES)
  158. static const copyblock AllCopyBlock4x4[2][16] = //[Rounding][x][y]
  159. {
  160.    { CopyBlock4x4_00, CopyBlock4x4_01, CopyBlock4x4_02, CopyBlock4x4_03,
  161.  CopyBlock4x4_10, CopyBlock4x4_11, CopyBlock4x4_12, CopyBlock4x4_13,
  162.  CopyBlock4x4_20, CopyBlock4x4_21, CopyBlock4x4_22, CopyBlock4x4_23,
  163.  CopyBlock4x4_30, CopyBlock4x4_31, CopyBlock4x4_32, CopyBlock4x4_33 },
  164.    { CopyBlock4x4_00, CopyBlock4x4_01R, CopyBlock4x4_02R, CopyBlock4x4_03R,
  165.      CopyBlock4x4_10R, CopyBlock4x4_11R, CopyBlock4x4_12R, CopyBlock4x4_13R,
  166.      CopyBlock4x4_20R, CopyBlock4x4_21R, CopyBlock4x4_22R, CopyBlock4x4_23R,
  167.      CopyBlock4x4_30R, CopyBlock4x4_31R, CopyBlock4x4_32R, CopyBlock4x4_33R },
  168. };
  169. #ifndef MIPS32
  170. const addblock TableAddBlock4x4[16] = 
  171. {
  172. AddBlock4x4_00,AddBlock4x4_01,AddBlock4x4_02,AddBlock4x4_03,
  173. AddBlock4x4_10,AddBlock4x4_11,AddBlock4x4_12,AddBlock4x4_13,
  174. AddBlock4x4_20,AddBlock4x4_21,AddBlock4x4_22,AddBlock4x4_23,
  175. AddBlock4x4_30,AddBlock4x4_31,AddBlock4x4_32,AddBlock4x4_33,
  176. };
  177. #endif
  178. #endif
  179. static const copyblock AllCopyBlock[2][4] = //[Rounding][x][y]
  180. {
  181. { CopyBlock, CopyBlockHor, CopyBlockVer, CopyBlockHorVer },
  182. { CopyBlock, CopyBlockHorRound, CopyBlockVerRound, CopyBlockHorVerRound }
  183. };
  184. #ifdef MIPS64
  185. static const copyblock AllCopyBlockM[2][4] = //[Rounding][x][y]
  186. {
  187. { CopyMBlock, CopyMBlockHor, CopyMBlockVer, CopyMBlockHorVer },
  188. { CopyMBlock, CopyMBlockHorRound, CopyMBlockVerRound, CopyMBlockHorVerRound }
  189. };
  190. #endif
  191. static int UpdateRounding(softidct* p)
  192. {
  193. #if defined(CONFIG_IDCT_LOWRES)
  194. if (p->Shift)
  195. p->CopyBlock4x4 = AllCopyBlock4x4[p->Rounding];
  196. else
  197. #endif
  198. memcpy(p->CopyBlock,p->AllCopyBlock[p->Rounding],sizeof(copyblock)*4);
  199. #ifdef MIPS64
  200. p->CopyMBlock = AllCopyBlockM[p->Rounding]; // no shift, instead 16x16
  201. #endif
  202. return ERR_NONE;
  203. }
  204. static const idctprocess Process[3] =   // pixelformat
  205. {
  206. (idctprocess)Process420,
  207. (idctprocess)Process422,
  208. (idctprocess)Process444,
  209. };
  210. static const idctcopy Copy16x16[3] =  // pixelformat
  211. {
  212. (idctcopy)Copy420,
  213. NULL,
  214. NULL,
  215. };
  216. #ifdef CONFIG_IDCT_SWAP
  217. static const idctprocess ProcessSwap[3] =   // pixelformat
  218. {
  219. (idctprocess)Process420Swap,
  220. (idctprocess)Process422Swap,
  221. (idctprocess)Process444Swap
  222. };
  223. static const idctcopy Copy16x16Swap[3] =  // pixelformat
  224. {
  225. (idctcopy)Copy420Swap,
  226. NULL,
  227. NULL,
  228. };
  229. #endif
  230. #if defined(CONFIG_IDCT_LOWRES)
  231. static const idctprocess ProcessHalf[3] =   // pixelformat
  232. {
  233. (idctprocess)Process420Half,
  234. (idctprocess)Process422Half,
  235. (idctprocess)Process444Half
  236. };
  237. static const idctprocess ProcessQuarter[3] =   // pixelformat
  238. {
  239. (idctprocess)Process420Quarter,
  240. (idctprocess)Process422Quarter,
  241. (idctprocess)Process444Quarter,
  242. };
  243. static const idctcopy Copy16x16Half[3] =  // pixelformat
  244. {
  245. (idctcopy)Copy420Half,
  246. NULL,
  247. NULL,
  248. };
  249. #endif
  250. static bool_t AllocBuffer(softidct* p,int i,block* Block,uint8_t** Ptr)
  251. {
  252. #ifndef MIPS
  253. int Align = 32;
  254. int Offset = 0;
  255. #else
  256. int Align = 8192;
  257. int Offset = ((i>>1)+(i&1)*2)*2048;
  258. #endif
  259. if (!AllocBlock(p->BufSize+Align+Offset,Block,0,HEAP_ANYWR))
  260. return 0;
  261. if (i>=2 && AvailMemory()<64*1024)
  262. {
  263. FreeBlock(Block);
  264. ShowOutOfMemory();
  265. return 0;
  266. }
  267. *Ptr = (uint8_t*)(((uintptr_t)Block->Ptr + Align-1) & ~(Align-1)) + Offset;
  268. return 1;
  269. }
  270. static int SetBufferCount(softidct* p, int n, int Temp)
  271. {
  272. int i;
  273. n += Temp;
  274. if (n>p->MaxCount) return ERR_NOT_SUPPORTED;
  275. for (i=n;i<p->BufCount;++i)
  276. {
  277. FreeBlock(&p->_Buffer[i]);
  278. p->Buffer[i] = NULL;
  279. p->BufAlloc[i] = 0;
  280. }
  281. if (p->BufCount > n)
  282. p->BufCount = n;
  283. for (i=p->BufCount;i<n;++i)
  284. {
  285. if (!p->BufSize)
  286. p->Buffer[i] = NULL;
  287. else
  288. if (!AllocBuffer(p,i,&p->_Buffer[i],&p->Buffer[i]))
  289. {
  290. p->MaxCount = p->BufCount;
  291. break;
  292. }
  293. p->BufAlloc[i] = p->BufSize;
  294. p->BufBorder[i] = 0;
  295. p->BufFrameNo[i] = -1;
  296. p->BufCount = i+1;
  297. }
  298. if (p->ShowNext >= p->BufCount)
  299. p->ShowNext = -1;
  300. if (p->ShowCurr >= p->BufCount)
  301. p->ShowCurr = -1;
  302. p->LastTemp = Temp && p->BufCount == n;
  303. if (p->BufCount != n)
  304. return ERR_OUT_OF_MEMORY;
  305. return ERR_NONE;
  306. }
  307. static int UpdateFormat(softidct* p)
  308. {
  309. if (p->Out.Format.Type == PACKET_VIDEO)
  310. {
  311. int AlignX,AlignY,Mode;
  312. int BlockSize;
  313. PlanarYUV(&p->Out.Format.Format.Video.Pixel,&p->UVX2,&p->UVY2,NULL);
  314. AlignX = (8 << p->UVX2) - 1;
  315. AlignY = (8 << p->UVY2) - 1;
  316. if (!p->BufferWidth || !p->BufferHeight)
  317. p->BufWidth = p->BufHeight = 0;
  318. else
  319. {
  320. p->BufWidth = (((p->BufferWidth+AlignX)&~AlignX) >> p->Shift)+2*EDGE;
  321. p->BufHeight = (((p->BufferHeight+AlignY)&~AlignY) >> p->Shift)+2*EDGE;
  322. }
  323. if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
  324. SwapInt(&p->BufWidth,&p->BufHeight);
  325. p->YToU = p->BufHeight * p->BufWidth;
  326. p->BufSize = p->YToU + 2*(p->YToU >> (p->UVX2+p->UVY2));
  327. p->BufWidthUV = p->BufWidth >> p->UVX2;
  328. p->Out.Format.Format.Video.Pitch = p->BufWidth;
  329. BlockSize = 8 >> p->Shift;
  330. if (p->Out.Format.Format.Video.Pixel.Flags & PF_YUV420)
  331. {
  332. Mode = 0;
  333. p->Tab[0] = 2*(BlockSize); //Y[0;0] -> Y[0;1]
  334. p->Tab[1] = 2*(BlockSize*p->BufWidth-BlockSize); //Y[0;1] -> Y[1;0]
  335. p->Tab[2] = 2*(BlockSize); //Y[1;0] -> Y[1;1]
  336. p->Tab[4] = 2*(p->YToU >> 2); //U->V
  337. p->Tab[5] = 2*(0);
  338. }
  339. else 
  340. if (p->Out.Format.Format.Video.Pixel.Flags & PF_YUV422)
  341. {
  342. Mode = 1;
  343. p->Tab[0] = 2*(BlockSize); //Y[0;0] -> Y[0;1]
  344. p->Tab[2] = 2*(p->YToU >> 1); //U->V
  345. p->Tab[3] = 2*(0);
  346. }
  347. else
  348. if (p->Out.Format.Format.Video.Pixel.Flags & PF_YUV444)
  349. {
  350. Mode = 2;
  351. p->Tab[0] = 2*(p->YToU); //Y->U
  352. p->Tab[1] = 2*(p->YToU); //U->V
  353. p->Tab[2] = 2*(0);
  354. }
  355. else
  356. return ERR_NOT_SUPPORTED;
  357. if (Mode==0 && (p->Mode & IDCTMODE_QPEL))
  358. {
  359. p->IDCT.MComp8x8 = p->QPELMComp8x8;
  360. p->IDCT.MComp16x16 = p->QPELMComp16x16;
  361. }
  362. else
  363. {
  364. p->IDCT.MComp8x8 = (idctmcomp) SoftMComp8x8;
  365. p->IDCT.MComp16x16 = (idctmcomp) SoftMComp16x16;
  366. }
  367. #if defined(CONFIG_IDCT_LOWRES)
  368. if (p->Shift == 1)
  369. {
  370. p->IDCT.Process = ProcessHalf[Mode];
  371. p->IDCT.Copy16x16 = Copy16x16Half[Mode];
  372. p->IDCT.Intra8x8 = (idctintra)Intra8x8Half;
  373. }
  374. else
  375. if (p->Shift == 2)
  376. {
  377. p->IDCT.Process = ProcessQuarter[Mode];
  378. p->IDCT.Intra8x8 = (idctintra)Intra8x8Quarter;
  379. p->IDCT.Copy16x16 = NULL;
  380. }
  381. else
  382. #endif
  383. #ifdef CONFIG_IDCT_SWAP
  384. if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
  385. {
  386. p->IDCT.Process = ProcessSwap[Mode];
  387. p->IDCT.Copy16x16 = Copy16x16Swap[Mode];
  388. p->IDCT.Intra8x8 = p->Intra8x8Swap;
  389. p->IDCT.MComp8x8 = (idctmcomp) SoftMComp8x8Swap;
  390. p->IDCT.MComp16x16 = (idctmcomp) SoftMComp16x16Swap;
  391. if (Mode == 0)
  392. {
  393. p->Tab[0] = 2*(8*p->BufWidth); //Y[0;0] -> Y[1;0]
  394. p->Tab[1] = 2*(8-8*p->BufWidth); //Y[1;0] -> Y[0;1]
  395. p->Tab[2] = 2*(8*p->BufWidth); //Y[0;1] -> Y[1;1]
  396. }
  397. }
  398. else
  399. #endif
  400. {
  401. p->IDCT.Process = Process[Mode];
  402. p->IDCT.Copy16x16 = Copy16x16[Mode];
  403. p->IDCT.Intra8x8 = p->Intra8x8;
  404. }
  405. #if defined(MIPS64)
  406. p->IDCT.Inter8x8 = Inter8x8Add;
  407. #endif
  408. }
  409. return ConnectionUpdate((node*)p,IDCT_OUTPUT,p->Out.Pin.Node,p->Out.Pin.No);
  410. }
  411. #ifdef CONFIG_IDCT_SWAP
  412. static int ChangeSwap(softidct* p)
  413. {
  414. if (p->BufCount > 0)
  415. {
  416. int No;
  417. planes TmpPlanes;
  418. video TmpFormat;
  419. int Brightness;
  420. video Format[2];
  421. planes Planes[2];
  422. TmpFormat = p->Out.Format.Format.Video;
  423. TmpFormat.Width = p->BufWidth - 2*EDGE;
  424. TmpFormat.Height = p->BufHeight - 2*EDGE;
  425. if (SurfaceAlloc(TmpPlanes,&TmpFormat) == ERR_NONE)
  426. {
  427. if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
  428. {
  429. SurfaceCopy(&Format[0],&TmpFormat,Planes[0],TmpPlanes,NULL);
  430. Unlock(p,0);
  431. }
  432. for (No=1;No<p->BufCount;++No)
  433. if (Lock(p,No,Planes[0],&Brightness,&Format[0])==ERR_NONE)
  434. {
  435. SwapInt(&p->BufWidth,&p->BufHeight);
  436. if (Lock(p,0,Planes[1],&Brightness,&Format[1])==ERR_NONE)
  437. {
  438. block Tmp;
  439. SurfaceRotate(&Format[0],&Format[1],Planes[0],Planes[1],DIR_SWAPXY);
  440. Unlock(p,0);
  441. SwapPByte(&p->Buffer[No],&p->Buffer[0]);
  442. Tmp = p->_Buffer[0];
  443. p->_Buffer[0] = p->_Buffer[No];
  444. p->_Buffer[No] = Tmp;
  445. p->BufBorder[No] = 0;
  446. SwapInt(&p->BufAlloc[No],&p->BufAlloc[0]);
  447. }
  448. SwapInt(&p->BufWidth,&p->BufHeight);
  449. Unlock(p,No);
  450. }
  451. SwapInt(&p->BufWidth,&p->BufHeight);
  452. if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
  453. {
  454. SurfaceRotate(&TmpFormat,&Format[0],TmpPlanes,Planes[0],DIR_SWAPXY);
  455. Unlock(p,0);
  456. p->BufBorder[0] = 0;
  457. }
  458. SwapInt(&p->BufWidth,&p->BufHeight);
  459. SurfaceFree(TmpPlanes);
  460. }
  461. }
  462. p->Out.Format.Format.Video.Direction ^= DIR_SWAPXY;
  463. SwapInt(&p->Out.Format.Format.Video.Width,&p->Out.Format.Format.Video.Height);
  464. SwapInt(&p->OutWidth,&p->OutHeight);
  465. return UpdateFormat(p);
  466. }
  467. #endif
  468. static int Send(softidct* p,tick_t RefTime,const flowstate* State);
  469. static int VerifyShift(softidct* p,int Shift)
  470. {
  471. // have to keep dword pitch alignment
  472. if (p->BufferWidth && Shift>0)
  473. {
  474. int AlignX = (8 << p->UVX2) - 1;
  475. int BufWidth = ((p->BufferWidth+AlignX)&~AlignX) >> (Shift+p->UVX2);
  476. if (BufWidth & 1)
  477. {
  478. Shift -= 2;
  479. }
  480. else
  481. if (BufWidth & 3)
  482. {
  483. --Shift;
  484. }
  485. if (Shift<0)
  486. Shift=0;
  487. }
  488. return Shift;
  489. }
  490. static int SetShift(softidct* p,int Shift,int Count)
  491. {
  492. #if !defined(CONFIG_IDCT_LOWRES)
  493. return ERR_NOT_SUPPORTED;
  494. #else
  495. if (Shift<0 || Shift>2) 
  496. return ERR_NOT_SUPPORTED;
  497. #ifdef CONFIG_IDCT_SWAP
  498. if (Shift>0 && (p->Out.Format.Format.Video.Direction & DIR_SWAPXY))
  499. ChangeSwap(p);
  500. #endif
  501. Shift = VerifyShift(p,Shift);
  502. if (p->Shift != Shift)
  503. {
  504. flowstate State;
  505. blitfx FX;
  506. planes Src[MAXIDCTBUF];
  507. planes Dst;
  508. video SrcFormat;
  509. video DstFormat;
  510. uint8_t *TmpPtr = NULL;
  511. planes Tmp;
  512. block TmpBlock;
  513. int Diff = Shift - p->Shift;
  514. int i;
  515. if (AllocBlock(p->BufSize+16,&TmpBlock,0,HEAP_ANYWR))
  516. {
  517. TmpPtr = (uint8_t*)ALIGN16((uintptr_t)TmpBlock.Ptr);
  518. Tmp[0] = TmpPtr + EDGE + EDGE*p->BufWidth;
  519. Tmp[1] = TmpPtr + p->YToU + (EDGE >> p->UVX2) + (EDGE >> p->UVY2)*(p->BufWidth >> p->UVX2);
  520. Tmp[2] = (uint8_t*)Tmp[1] + (p->YToU >> (p->UVX2+p->UVY2));
  521. }
  522. for (i=0;i<Count;++i)
  523. Lock(p,i,Src[i],NULL,&SrcFormat);
  524. p->Out.Format.Format.Video.Width = p->OutWidth >> Shift;
  525. p->Out.Format.Format.Video.Height = p->OutHeight >> Shift;
  526. memset(&FX,0,sizeof(FX));
  527. if (Diff>0)
  528. {
  529. FX.ScaleX = SCALE_ONE >> Diff;
  530. FX.ScaleY = SCALE_ONE >> Diff;
  531. }
  532. else
  533. {
  534. FX.ScaleX = SCALE_ONE << -Diff;
  535. FX.ScaleY = SCALE_ONE << -Diff;
  536. }
  537. p->Shift = Shift;
  538. UpdateRounding(p);
  539. UpdateFormat(p);
  540. for (i=0;i<Count;++i)
  541. {
  542. if (TmpPtr)
  543. SurfaceCopy(&SrcFormat,&SrcFormat,Src[i],Tmp,NULL);
  544. if (p->BufAlloc[i] < p->BufSize)
  545. {
  546. uint8_t* Ptr;
  547. block Block;
  548. if (!AllocBuffer(p,i,&Block,&Ptr)) // realloc buffer if neccessary)
  549. {
  550. if (TmpPtr)
  551. FreeBlock(&TmpBlock);
  552. SetShift(p,Shift - Diff,i); // restore (shrinking won't need more memory)
  553. return ERR_OUT_OF_MEMORY;
  554. }
  555. FreeBlock(&p->_Buffer[i]);
  556. p->Buffer[i] = Ptr;
  557. p->_Buffer[i] = Block;
  558. p->BufAlloc[i] = p->BufSize;
  559. }
  560. if (TmpPtr)
  561. {
  562. Lock(p,i,Dst,NULL,&DstFormat);
  563. SurfaceCopy(&SrcFormat,&DstFormat,Tmp,Dst,&FX);
  564. }
  565. p->BufBorder[i] = 0;
  566. }
  567. if (TmpPtr)
  568. FreeBlock(&TmpBlock);
  569. State.CurrTime = TIME_RESEND;
  570. State.DropLevel = 0;
  571. Send(p,TIME_UNKNOWN,&State);
  572. }
  573. return ERR_NONE;
  574. #endif
  575. }
  576. static int UpdateMode(softidct* p)
  577. {
  578. if (p->Mode & ~p->ModeSupported)
  579. return ERR_NOT_SUPPORTED;
  580. #ifdef CONFIG_IDCT_SWAP
  581. if (p->Mode && (p->Out.Format.Format.Video.Direction & DIR_SWAPXY))
  582. ChangeSwap(p);
  583. #endif
  584. #if defined(CONFIG_IDCT_LOWRES)
  585. if (p->Mode && p->Shift)
  586. return SetShift(p,0,p->BufCount);
  587. #endif
  588. UpdateRounding(p);
  589. UpdateFormat(p);
  590. return ERR_NONE;
  591. }
  592. static int SetFormat(softidct* p, const video* Format)
  593. {
  594. SetBufferCount(p,0,0);
  595. PacketFormatClear(&p->Out.Format);
  596. if (Format)
  597. {
  598. size_t Area;
  599. if (!(Format->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444)))
  600. return ERR_NOT_SUPPORTED;
  601. p->Out.Format.Type = PACKET_VIDEO;
  602. p->Out.Format.Format.Video = *Format;
  603. if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
  604. SwapInt(&p->Out.Format.Format.Video.Width,&p->Out.Format.Format.Video.Height);
  605. p->Out.Format.Format.Video.Direction = 0;
  606. p->Out.Format.Format.Video.Pixel.Flags |= PF_16ALIGNED | PF_SAFEBORDER;
  607. p->MaxCount = MAXBUF;
  608. p->Rounding = 0;
  609. Area = p->Out.Format.Format.Video.Width * p->Out.Format.Format.Video.Height;
  610. if (Area >= 1024*1024 && AvailMemory() < Area*2)
  611. {
  612. video Desktop;
  613. size_t DesktopArea;
  614. QueryDesktop(&Desktop);
  615. DesktopArea = Desktop.Width * Desktop.Height;
  616. if (Area >= DesktopArea*4 && p->Shift<1)
  617. p->Shift = 1;
  618. if (Area >= DesktopArea*16 && p->Shift<2)
  619. p->Shift = 2;
  620. }
  621. p->Shift = VerifyShift(p,p->Shift);
  622. #if defined(MIPS64)
  623. if (p->Shift>0)
  624. return ERR_NOT_SUPPORTED; // fallback to mips32
  625. #endif
  626. p->OutWidth = p->Out.Format.Format.Video.Width;
  627. p->OutHeight = p->Out.Format.Format.Video.Height;
  628. p->Out.Format.Format.Video.Width >>= p->Shift;
  629. p->Out.Format.Format.Video.Height >>= p->Shift;
  630. UpdateRounding(p);
  631. }
  632. #ifdef FREESCALE_MX1
  633. if (p->MX1)
  634. {
  635. volatile int* Cmd = p->MX1-64; //0x22400
  636. volatile int* GCCR = p->MX1-6972; //0x1B810
  637. if (Format)
  638. {
  639. *GCCR |= 2;
  640. ThreadSleep(1);
  641. *Cmd = 0x284C+0x20;
  642. ThreadSleep(1);
  643. *Cmd = 0x284D;
  644. }
  645. else
  646. {
  647. *Cmd = 0x00;
  648. *GCCR &= ~2;
  649. }
  650. }
  651. #endif
  652. return UpdateFormat(p);
  653. }
  654. static int Set(softidct* p, int No, const void* Data, int Size)
  655. {
  656. flowstate State;
  657. int Result = ERR_INVALID_PARAM;
  658. switch (No)
  659. {
  660. case NODE_SETTINGSCHANGED:
  661. p->NeedLast = QueryAdvanced(ADVANCED_SLOW_VIDEO);
  662. break;
  663. case IDCT_SHOW: 
  664. SETVALUE(p->ShowNext,int,ERR_NONE); 
  665. if (p->ShowNext >= p->BufCount) p->ShowNext = -1;
  666. break;
  667. case FLOW_FLUSH:
  668. p->ShowCurr = -1;
  669. p->ShowNext = -1;
  670. return ERR_NONE;
  671. case IDCT_BACKUP: 
  672. assert(Size == sizeof(idctbackup));
  673. Result = IDCTRestore(&p->IDCT,(idctbackup*)Data);
  674. break;
  675. case IDCT_MODE: SETVALUECMP(p->Mode,int,UpdateMode(p),EqInt); break;
  676. case IDCT_BUFFERWIDTH: SETVALUE(p->BufferWidth,int,ERR_NONE); break;
  677. case IDCT_BUFFERHEIGHT: SETVALUE(p->BufferHeight,int,ERR_NONE); break;
  678. case IDCT_FORMAT:
  679. assert(Size == sizeof(video) || !Data);
  680. Result = SetFormat(p,(const video*)Data);
  681. break;
  682. case IDCT_OUTPUT|PIN_PROCESS: SETVALUE(p->Out.Process,packetprocess,ERR_NONE); break;
  683. #ifdef CONFIG_IDCT_SWAP
  684. case IDCT_OUTPUT|PIN_FORMAT:
  685. assert(Size == sizeof(packetformat) || !Data);
  686. if (Data && QueryAdvanced(ADVANCED_IDCTSWAP) && !p->Shift && !p->Mode &&
  687. !(p->Out.Format.Format.Video.Pixel.Flags & PF_YUV422) &&
  688. PacketFormatRotatedVideo(&p->Out.Format,(packetformat*)Data,DIR_SWAPXY))
  689. Result = ChangeSwap(p);
  690. break;
  691. #endif
  692. case IDCT_OUTPUT: SETVALUE(p->Out.Pin,pin,ERR_NONE); break;
  693. case IDCT_ROUNDING: SETVALUE(p->Rounding,bool_t,UpdateRounding(p)); break;
  694. case IDCT_SHIFT: 
  695. assert(Size == sizeof(int));
  696. Result = SetShift(p,*(const int*)Data,p->BufCount);
  697. break;
  698. case IDCT_BUFFERCOUNT:
  699. assert(Size == sizeof(int));
  700. Result = ERR_NONE;
  701. if (p->BufCount < *(const int*)Data)
  702. Result = SetBufferCount(p,*(const int*)Data,0);
  703. break;
  704. case FLOW_RESEND:
  705. State.CurrTime = TIME_RESEND;
  706. State.DropLevel = 0;
  707. Result = Send(p,TIME_UNKNOWN,&State);
  708. break;
  709. }
  710. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+p->BufCount)
  711. SETVALUE(p->BufFrameNo[No-IDCT_FRAMENO],int,ERR_NONE);
  712. return Result;
  713. }
  714. static int Get(softidct* p, int No, void* Data, int Size)
  715. {
  716. int Result = ERR_INVALID_PARAM;
  717. switch (No)
  718. {
  719. case FLOW_BUFFERED: GETVALUE(1,bool_t); break;
  720. case IDCT_OUTPUT|PIN_PROCESS: GETVALUE(p->Out.Process,packetprocess); break;
  721. case IDCT_OUTPUT|PIN_FORMAT: GETVALUE(p->Out.Format,packetformat); break;
  722. case IDCT_OUTPUT: GETVALUE(p->Out.Pin,pin); break;
  723. case IDCT_FORMAT: GETVALUE(p->Out.Format.Format.Video,video); break;
  724. case IDCT_ROUNDING: GETVALUE(p->Rounding,bool_t); break;
  725. case IDCT_SHIFT: GETVALUE(p->Shift,int); break;
  726. case IDCT_MODE: GETVALUE(p->Mode,int); break;
  727. case IDCT_BUFFERCOUNT: GETVALUE(p->BufCount - p->LastTemp,int); break;
  728. case IDCT_BUFFERWIDTH: GETVALUE(p->BufferWidth,int); break;
  729. case IDCT_BUFFERHEIGHT: GETVALUE(p->BufferHeight,int); break;
  730. case IDCT_SHOW: GETVALUE(p->ShowNext,int); break;
  731. case IDCT_BACKUP: 
  732. assert(Size == sizeof(idctbackup));
  733. Result = IDCTBackup(&p->IDCT,(idctbackup*)Data);
  734. break;
  735. }
  736. if (No>=IDCT_FRAMENO && No<IDCT_FRAMENO+p->BufCount)
  737. GETVALUE(p->BufFrameNo[No-IDCT_FRAMENO],int);
  738. return Result;
  739. }
  740. static void Drop(softidct* p)
  741. {
  742. int i;
  743. for (i=0;i<p->BufCount;++i)
  744. p->BufFrameNo[i] = -1;
  745. }
  746. static int Null(softidct* p,const flowstate* State,bool_t Empty)
  747. {
  748. packet* Packet = NULL;
  749. packet EmptyPacket;
  750. flowstate DropState;
  751. if (!State)
  752. {
  753. DropState.CurrTime = TIME_UNKNOWN;
  754. DropState.DropLevel = 1;
  755. State = &DropState;
  756. }
  757. if (Empty)
  758. {
  759. memset(&EmptyPacket,0,sizeof(EmptyPacket));
  760. EmptyPacket.RefTime = TIME_UNKNOWN;
  761. Packet = &EmptyPacket;
  762. }
  763. return p->Out.Process(p->Out.Pin.Node,Packet,State);
  764. }
  765. static int Send(softidct* p,tick_t RefTime,const flowstate* State)
  766. {
  767. packet Packet;
  768. int Result = ERR_INVALID_DATA;
  769. if (State->DropLevel)
  770. return p->Out.Process(p->Out.Pin.Node,NULL,State);
  771. if (p->ShowNext < 0)
  772. return ERR_NEED_MORE_DATA;
  773. if (p->ShowCurr == p->ShowNext)
  774. p->ShowCurr = -1;
  775. if (Lock(p,p->ShowNext,*(planes*)&Packet.Data,NULL,NULL) == ERR_NONE)
  776. {
  777. Lock(p,p->ShowCurr,*(planes*)&Packet.LastData,NULL,NULL);
  778. Packet.RefTime = RefTime;
  779. Result = p->Out.Process(p->Out.Pin.Node,&Packet,State);
  780. Unlock(p,p->ShowCurr);
  781. Unlock(p,p->ShowNext);
  782. }
  783. if (Result != ERR_BUFFER_FULL)
  784. p->ShowCurr = p->ShowNext;
  785. return Result;
  786. }
  787. static int FrameStart(softidct* p,int FrameNo,int* OldFrameNo,int DstNo,int BackNo,int FwdNo,int ShowNo,bool_t Drop)
  788. {
  789. #if defined(MIPS64_WIN32) 
  790. // win32 doesn't support 64bit natively. thread and process
  791. // changes won't save upper part of 64bit registers.
  792. // we have to disable interrupt and make sure all 1KB
  793. // code pages are in memory so no page loading is called
  794. // during code execution 
  795. p->KMode = KernelMode(1);
  796. TouchPages(p);
  797. DisableInterrupts();
  798. p->NextIRQ = 0;
  799. #endif
  800. if (!p->CopyBlock && (BackNo>=0 || FwdNo>=0))
  801. return ERR_NOT_SUPPORTED;
  802. #ifdef ARM
  803. // ShowCurr will be the next "LastData" in output packet
  804. // we don't want to lose it's content
  805. if (p->NeedLast && p->ShowCurr == DstNo)
  806. {
  807. int SwapNo;
  808. for (SwapNo=0;SwapNo<p->BufCount;++SwapNo)
  809. if (SwapNo != DstNo && SwapNo != BackNo && SwapNo != FwdNo && SwapNo != ShowNo)
  810. break;
  811. if (SwapNo < p->BufCount || SetBufferCount(p,p->BufCount,1)==ERR_NONE)
  812. {
  813. //DEBUG_MSG2("IDCT Swap %d,%d",SwapNo,DstNo);
  814. block Tmp;
  815. Tmp = p->_Buffer[SwapNo];
  816. p->_Buffer[SwapNo] = p->_Buffer[DstNo];
  817. p->_Buffer[DstNo] = Tmp;
  818. SwapPByte(&p->Buffer[SwapNo],&p->Buffer[DstNo]);
  819. SwapInt(&p->BufFrameNo[SwapNo],&p->BufFrameNo[DstNo]);
  820. SwapBool(&p->BufBorder[SwapNo],&p->BufBorder[DstNo]);
  821. SwapInt(&p->BufAlloc[SwapNo],&p->BufAlloc[DstNo]);
  822. p->ShowCurr = SwapNo;
  823. }
  824. }
  825. #endif
  826. p->ShowNext = ShowNo;
  827. if (OldFrameNo)
  828. *OldFrameNo = p->BufFrameNo[DstNo];
  829. p->BufFrameNo[DstNo] = FrameNo;
  830. p->Dst = p->Buffer[DstNo];
  831. p->Ref[0] = NULL;
  832. p->Ref[1] = NULL;
  833. p->RefMin[0] = NULL;
  834. p->RefMin[1] = NULL;
  835. p->RefMax[0] = NULL;
  836. p->RefMax[1] = NULL;
  837. if (BackNo>=0)
  838. {
  839. p->Ref[0] = p->Buffer[BackNo];
  840. if (!p->BufBorder[BackNo])
  841. {
  842. p->BufBorder[BackNo] = 1;
  843. FillEdgeYUV(p,p->Ref[0]);
  844. }
  845. p->RefMin[0] = p->Ref[0];
  846. p->RefMax[0] = p->Ref[0] + p->BufSize - ((8+8*p->BufWidthUV)>>p->Shift);
  847. }
  848. if (FwdNo>=0)
  849. {
  850. p->Ref[1] = p->Buffer[FwdNo];
  851. if (!p->BufBorder[FwdNo])
  852. {
  853. p->BufBorder[FwdNo] = 1;
  854. FillEdgeYUV(p,p->Ref[1]);
  855. }
  856. p->RefMin[1] = p->Ref[1];
  857. p->RefMax[1] = p->Ref[1] + p->BufSize - ((8+8*p->BufWidthUV)>>p->Shift);
  858. }
  859. p->BufBorder[DstNo] = 0; //invalidate border for dst
  860. #if !defined(MIPS64)
  861. #if defined(CONFIG_IDCT_LOWRES)
  862. if (p->Shift == 1)
  863. p->IDCT.Inter8x8 = p->Ref[1]!=NULL?(idctinter)Inter8x8BackFwdHalf:(idctinter)Inter8x8BackHalf;
  864. else
  865. #endif
  866. #ifdef CONFIG_IDCT_SWAP
  867. if (p->Out.Format.Format.Video.Direction & DIR_SWAPXY)
  868. p->IDCT.Inter8x8 = p->Inter8x8Swap[p->Ref[1]!=NULL];
  869. else
  870. #endif
  871. p->IDCT.Inter8x8 = p->Inter8x8[p->Ref[1]!=NULL];
  872. #endif
  873. p->inter8x8uv = p->IDCT.Inter8x8; // for qpel
  874. #ifdef FREESCALE_MX1
  875. if (p->MX1)
  876. p->MX1Pop = MX1PopNone;
  877. #endif
  878. return ERR_NONE;
  879. static void FrameEnd(softidct* p)
  880. {
  881. #ifdef MIPS64_WIN32
  882. EnableInterrupts();
  883. KernelMode(p->KMode);
  884. #endif
  885. #ifdef FREESCALE_MX1
  886. if (p->MX1)
  887. p->MX1Pop(p);
  888. #endif
  889. }
  890. static int Create(softidct* p)
  891. {
  892. #if defined(MMX)
  893. if (!(QueryPlatform(PLATFORM_CAPS) & CAPS_X86_MMX))
  894. return ERR_NOT_SUPPORTED;
  895. #endif
  896. #if defined(MIPS64)
  897. if (!QueryAdvanced(ADVANCED_VR41XX))
  898. return ERR_NOT_SUPPORTED;
  899. #if defined(MIPSVR41XX)
  900. if (!(QueryPlatform(PLATFORM_CAPS) & CAPS_MIPS_VR4120))
  901. return ERR_NOT_SUPPORTED;
  902. #endif
  903. #endif
  904. p->IDCT.Get = (nodeget)Get;
  905. p->IDCT.Set = (nodeset)Set;
  906. p->IDCT.Send = (idctsend)Send;
  907. p->IDCT.Null = (idctnull)Null;
  908. p->IDCT.Drop = (idctdrop)Drop;
  909. p->IDCT.Lock = (idctlock)Lock;
  910. p->IDCT.Unlock = (idctunlock)Unlock;
  911. p->IDCT.FrameStart = (idctframestart)FrameStart;
  912. p->IDCT.FrameEnd = (idctframeend)FrameEnd;
  913. #if !defined(MIPS64) && !defined(MIPS32)
  914. p->AddBlock[0] = AddBlock;
  915. p->AddBlock[1] = AddBlockHor;
  916. p->AddBlock[2] = AddBlockVer;
  917. p->AddBlock[3] = AddBlockHorVer;
  918. #endif
  919. memcpy(p->AllCopyBlock,AllCopyBlock,sizeof(AllCopyBlock));
  920. p->Intra8x8 = (idctintra)Intra8x8;
  921. #ifndef MIPS64
  922. p->Inter8x8[0] = (idctinter)Inter8x8Back;
  923. p->Inter8x8[1] = (idctinter)Inter8x8BackFwd;
  924. p->QPELInter = (idctinter)Inter8x8QPEL;
  925. p->QPELCopyBlockM = (copyblock)CopyBlockM;
  926. p->Inter8x8GMC = (idctinter)Inter8x8GMC;
  927. #endif
  928. #ifdef CONFIG_IDCT_SWAP
  929. p->Intra8x8Swap = (idctintra)Intra8x8Swap;
  930. #ifndef MIPS64
  931. p->Inter8x8Swap[0] = (idctinter)Inter8x8BackSwap;
  932. p->Inter8x8Swap[1] = (idctinter)Inter8x8BackFwdSwap;
  933. #endif
  934. #endif 
  935. #if defined(MIPS64_WIN32) 
  936. CodeFindPages(*(void**)&p->IDCT.Enum,&p->CodeBegin,&p->CodeEnd,&p->CodePage);
  937. #endif
  938. #if defined(ARM)
  939. #if defined(FREESCALE_MX1)
  940. if (QueryPlatform(PLATFORM_MODEL)==MODEL_ZODIAC)
  941. {
  942. p->MX1 = (int*)0x80022500;
  943. p->Intra8x8 = (idctintra)MX1Intra8x8;
  944. p->Inter8x8[0] = (idctinter)MX1Inter8x8Back;
  945. p->Inter8x8[1] = (idctinter)MX1Inter8x8BackFwd;
  946. #ifdef CONFIG_IDCT_SWAP
  947. p->Intra8x8Swap = (idctintra)MX1Intra8x8Swap;
  948. p->Inter8x8Swap[0] = (idctinter)MX1Inter8x8BackSwap;
  949. p->Inter8x8Swap[1] = (idctinter)MX1Inter8x8BackFwdSwap;
  950. #endif
  951. }
  952. else
  953. #endif
  954. #if (!defined(TARGET_PALMOS) && !defined(TARGET_SYMBIAN)) || (__GNUC__>=4) || (__GNUC__==3 && __GNUC_MINOR__>=4)
  955. if (!QueryAdvanced(ADVANCED_NOWMMX) && 
  956. (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_WMMX))
  957. {
  958. p->Intra8x8 = (idctintra)WMMXIntra8x8;
  959. p->Inter8x8[0] = (idctinter)WMMXInter8x8Back;
  960. p->Inter8x8[1] = (idctinter)WMMXInter8x8BackFwd;
  961. p->QPELInter = (idctinter)WMMXInter8x8QPEL;
  962. p->Inter8x8GMC = (idctinter)WMMXInter8x8GMC;
  963. p->QPELCopyBlockM = (copyblock)WMMXCopyBlockM;
  964. #ifdef CONFIG_IDCT_SWAP
  965. p->Intra8x8Swap = (idctintra)WMMXIntra8x8Swap;
  966. p->Inter8x8Swap[0] = (idctinter)WMMXInter8x8BackSwap;
  967. p->Inter8x8Swap[1] = (idctinter)WMMXInter8x8BackFwdSwap;
  968. #endif
  969. p->AllCopyBlock[0][0] = WMMXCopyBlock;
  970. p->AllCopyBlock[0][1] = WMMXCopyBlockHor;
  971. p->AllCopyBlock[0][2] = WMMXCopyBlockVer;
  972. p->AllCopyBlock[0][3] = WMMXCopyBlockHorVer;
  973. p->AllCopyBlock[1][0] = WMMXCopyBlock;
  974. p->AllCopyBlock[1][1] = WMMXCopyBlockHorRound;
  975. p->AllCopyBlock[1][2] = WMMXCopyBlockVerRound;
  976. p->AllCopyBlock[1][3] = WMMXCopyBlockHorVerRound;
  977. p->AddBlock[0] = WMMXAddBlock;
  978. p->AddBlock[1] = WMMXAddBlockHor;
  979. p->AddBlock[2] = WMMXAddBlockVer;
  980. p->AddBlock[3] = WMMXAddBlockHorVer;
  981. }
  982. else
  983. #endif // TARGET_PALMOS
  984. {}
  985. /* if (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_5E)
  986. {
  987. if (QueryPlatform(PLATFORM_ICACHE) >= 32768)
  988. {
  989. p->AllCopyBlock[0][0] = FastCopyBlock;
  990. p->AllCopyBlock[0][1] = FastCopyBlockHor;
  991. p->AllCopyBlock[0][2] = FastCopyBlockVer;
  992. p->AllCopyBlock[0][3] = FastCopyBlockHorVer;
  993. p->AllCopyBlock[0][0] = FastCopyBlock;
  994. p->AllCopyBlock[1][1] = FastCopyBlockHorRound;
  995. p->AllCopyBlock[1][2] = FastCopyBlockVerRound;
  996. p->AllCopyBlock[1][3] = FastCopyBlockHorVerRound;
  997. p->AddBlock[0] = FastAddBlock;
  998. p->AddBlock[1] = FastAddBlockHor;
  999. p->AddBlock[2] = FastAddBlockVer;
  1000. p->AddBlock[3] = FastAddBlockHorVer;
  1001. }
  1002. else
  1003. {
  1004. p->AllCopyBlock[0][0] = PreLoadCopyBlock;
  1005. p->AllCopyBlock[0][1] = PreLoadCopyBlockHor;
  1006. p->AllCopyBlock[0][2] = PreLoadCopyBlockVer;
  1007. p->AllCopyBlock[0][3] = PreLoadCopyBlockHorVer;
  1008. p->AllCopyBlock[0][0] = PreLoadCopyBlock;
  1009. p->AllCopyBlock[1][1] = PreLoadCopyBlockHorRound;
  1010. p->AllCopyBlock[1][2] = PreLoadCopyBlockVerRound;
  1011. p->AllCopyBlock[1][3] = PreLoadCopyBlockHorVerRound;
  1012. p->AddBlock[0] = PreLoadAddBlock;
  1013. p->AddBlock[1] = PreLoadAddBlockHor;
  1014. p->AddBlock[2] = PreLoadAddBlockVer;
  1015. p->AddBlock[3] = PreLoadAddBlockHorVer;
  1016. }
  1017. }
  1018. */
  1019. #endif //ARM
  1020. p->Tmp = (uint8_t*)ALIGN16((uintptr_t)p->_Tmp);
  1021. p->MaxCount = MAXBUF;
  1022. p->BufCount = 0;
  1023. p->LastTemp = 0;
  1024. p->ShowCurr = -1;
  1025. p->ShowNext = -1;
  1026. return ERR_NONE;
  1027. }
  1028. static const nodedef SoftIDCT =
  1029. {
  1030. sizeof(softidct),
  1031. #if defined(MPEG4_EXPORTS)
  1032. MPEG4IDCT_ID,
  1033. IDCT_CLASS,
  1034. PRI_DEFAULT+20,
  1035. #elif defined(MSMPEG4_EXPORTS)
  1036. MSMPEG4IDCT_ID,
  1037. IDCT_CLASS,
  1038. PRI_DEFAULT+10,
  1039. #else
  1040. SOFTIDCT_ID,
  1041. IDCT_CLASS,
  1042. PRI_DEFAULT,
  1043. #endif
  1044. (nodecreate)Create,
  1045. };
  1046. void SoftIDCT_Init()
  1047. {
  1048. NodeRegisterClass(&SoftIDCT);
  1049. }
  1050. void SoftIDCT_Done()
  1051. {
  1052. NodeUnRegisterClass(SoftIDCT.Class);
  1053. }