I386.MPEGUtilities.Mod 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490
  1. (** AUTHOR "Yves Weber";
  2. PURPOSE "Some utilities used by the MPEGVideoDecoder module";
  3. *)
  4. MODULE MPEGUtilities;
  5. IMPORT
  6. SYSTEM, Machine, MPEGTables, Streams, KernelLog, Raster, Codecs;
  7. CONST
  8. (* required for iDCT (copied from DivXHelper.Mod) *)
  9. W1 = 2841; (* 2048*sqrt(2)*cos(1*pi/16) *)
  10. W2 = 2676; (* 2048*sqrt(2)*cos(2*pi/16) *)
  11. W3 = 2408; (* 2048*sqrt(2)*cos(3*pi/16) *)
  12. W5 = 1609; (* 2048*sqrt(2)*cos(5*pi/16) *)
  13. W6 = 1108; (* 2048*sqrt(2)*cos(6*pi/16) *)
  14. W7 = 565; (* 2048*sqrt(2)*cos(7*pi/16) *)
  15. EnableMMX = TRUE;
  16. VAR
  17. IdctBorder*: POINTER TO ARRAY OF LONGINT;
  18. ii: LONGINT;
  19. TYPE
  20. (* Helper Types *)
  21. PointerToArrayOfCHAR* = POINTER TO ARRAY OF CHAR;
  22. PointerToArrayOfLONGINT* = POINTER TO ARRAY OF LONGINT;
  23. Dequantizer* = OBJECT
  24. PROCEDURE DequantizeNonintraCoeffs*(
  25. coeffs: PointerToArrayOfLONGINT;
  26. nonintraQM: PointerToArrayOfLONGINT;
  27. qScale: LONGINT): BOOLEAN;
  28. VAR
  29. i: LONGINT;
  30. sign: LONGINT;
  31. BEGIN
  32. FOR i := 0 TO 63 DO
  33. IF coeffs[i] > 0 THEN
  34. sign := 1;
  35. ELSIF coeffs[i] = 0 THEN
  36. sign := 0;
  37. ELSE
  38. sign := -1;
  39. END;
  40. coeffs[i] := ((2*coeffs[i] + sign) * qScale * nonintraQM[i]) DIV 16;
  41. (* oddify towards zero *)
  42. IF (coeffs[i] MOD 2) = 0 THEN
  43. coeffs[i] := coeffs[i] - sign;
  44. END;
  45. (* ensure limits *)
  46. IF coeffs[i] > 2047 THEN
  47. coeffs[i] := 2047;
  48. END;
  49. IF coeffs[i] < -2048 THEN
  50. coeffs[i] := -2048;
  51. END;
  52. END;
  53. RETURN TRUE;
  54. END DequantizeNonintraCoeffs;
  55. (* Dequantizes the coefficients *)
  56. PROCEDURE DequantizeIntraCoeffs*(
  57. coeffs: PointerToArrayOfLONGINT;
  58. intraQM: PointerToArrayOfLONGINT;
  59. qScale: LONGINT;
  60. VAR prediction: LONGINT;
  61. first: BOOLEAN;
  62. mbSkipped: BOOLEAN): BOOLEAN;
  63. VAR
  64. i: LONGINT;
  65. BEGIN
  66. (* dequantize all coefficients *)
  67. FOR i := 1 TO 63 DO
  68. coeffs[i] := (2*coeffs[i]*qScale*intraQM[i]) DIV 16;
  69. IF ((coeffs[i] MOD 2) = 0) & (coeffs[i] # 0) THEN
  70. IF coeffs[i] > 0 THEN
  71. DEC(coeffs[i]);
  72. ELSE
  73. INC(coeffs[i]);
  74. END;
  75. END;
  76. (* ensure limits *)
  77. IF coeffs[i] > 2047 THEN
  78. coeffs[i] := 2047;
  79. END;
  80. IF coeffs[i] < -2048 THEN
  81. coeffs[i] := -2048;
  82. END;
  83. END;
  84. (* special handling of DC *)
  85. coeffs[0] := coeffs[0] * 8;
  86. (* calculate DC = DCold + difference for all type of blocks *)
  87. IF first & mbSkipped THEN
  88. prediction := 8*128;
  89. END;
  90. INC(prediction, coeffs[0]);
  91. coeffs[0] := prediction;
  92. RETURN TRUE;
  93. END DequantizeIntraCoeffs;
  94. (* Dequantizes the coefficients - MPEG2 version *)
  95. PROCEDURE DequantizeNonintraCoeffs2*(
  96. coeffs: PointerToArrayOfLONGINT;
  97. nonintraQM: PointerToArrayOfLONGINT;
  98. qScale: LONGINT);
  99. VAR
  100. i: LONGINT;
  101. sum: LONGINT;
  102. BEGIN
  103. FOR i := 0 TO 63 DO
  104. IF coeffs[i] # 0 THEN
  105. IF coeffs[i] > 0 THEN
  106. coeffs[i] := ((2 * coeffs[i] + 1) * nonintraQM[i] * qScale) DIV 32;
  107. ELSE
  108. coeffs[i] := ((2 * coeffs[i] - 1) * nonintraQM[i] * qScale) DIV 32;
  109. END;
  110. (* ensure limits *)
  111. IF coeffs[i] > 2047 THEN
  112. coeffs[i] := 2047;
  113. ELSIF coeffs[i] < -2048 THEN
  114. coeffs[i] := -2048;
  115. END;
  116. INC(sum, coeffs[i]);
  117. END;
  118. END;
  119. MismatchControl(coeffs[63], sum);
  120. END DequantizeNonintraCoeffs2;
  121. (* Dequantizes the coefficients - MPEG-2 version *)
  122. PROCEDURE DequantizeIntraCoeffs2*(
  123. coeffs: PointerToArrayOfLONGINT;
  124. intraQM: PointerToArrayOfLONGINT;
  125. qScale: LONGINT;
  126. dcPrecision: LONGINT);
  127. VAR
  128. i: LONGINT;
  129. sum: LONGINT;
  130. BEGIN
  131. (* special treatment of DC *)
  132. coeffs[0] := MPEGTables.DCM[dcPrecision] * coeffs[0];
  133. sum := coeffs[0];
  134. FOR i := 1 TO 63 DO
  135. coeffs[i] := ((2 * coeffs[i]) * intraQM[i] * qScale) DIV 32;
  136. (* ensure limits *)
  137. IF coeffs[i] > 2047 THEN
  138. coeffs[i] := 2047;
  139. END;
  140. IF coeffs[i] < -2048 THEN
  141. coeffs[i] := -2048;
  142. END;
  143. INC(sum, coeffs[i]);
  144. END;
  145. MismatchControl(coeffs[63], sum);
  146. END DequantizeIntraCoeffs2;
  147. (* Performs the mismatch contros - used for intra and non-intra - MPEG2 only *)
  148. PROCEDURE MismatchControl(VAR coeffs63: LONGINT; sum: LONGINT);
  149. BEGIN
  150. IF (sum MOD 2) = 0 THEN
  151. (* sum is even *)
  152. IF (coeffs63 MOD 2) = 1 THEN
  153. (* odd *)
  154. DEC(coeffs63);
  155. ELSE
  156. (* even *)
  157. INC(coeffs63);
  158. END;
  159. END;
  160. END MismatchControl;
  161. END Dequantizer;
  162. (* Object to store one decoded picture *)
  163. (* Color information is in one big array of char:
  164. yyyyyyyyyyyyyyyyyyyycbcbcbcbcbcbcrcrcrcrcrcrcr
  165. | | |
  166. 0 cbOffset crOffset
  167. for rgb, use the convention y->r, cb->g, cr->b
  168. *)
  169. Frame* = OBJECT
  170. VAR
  171. buffer*: PointerToArrayOfCHAR;
  172. cbOffset*, crOffset*: LONGINT;
  173. frameNr*: LONGINT;
  174. picType*: LONGINT; (* I, P or B-Frame -> 1, 2 or 3 *)
  175. END Frame;
  176. (* MPEG-2 Picture Coding Extension *)
  177. PicCodingExt* = OBJECT
  178. VAR
  179. dcPrecision*: LONGINT; (* DC precision *)
  180. picStructure*: LONGINT; (* picture structure *)
  181. topFieldFirst*: BOOLEAN;
  182. framePredFrameDct*: BOOLEAN;
  183. concealmentMV*: BOOLEAN; (* concealment motion vectors used *)
  184. qScaleType*: BOOLEAN;
  185. intraVlcFormat*: BOOLEAN;
  186. alternateScan*: BOOLEAN;
  187. repeatFirstField*: BOOLEAN;
  188. chroma420Type*: BOOLEAN;
  189. progressiveFrame*: BOOLEAN;
  190. PROCEDURE Dump*;
  191. BEGIN
  192. KernelLog.String("dc Precision: "); KernelLog.Int(dcPrecision, 0); KernelLog.Ln;
  193. KernelLog.String("picture structure: ");
  194. CASE picStructure OF
  195. 0: KernelLog.String("Reserved");
  196. | 1: KernelLog.String("Top Field");
  197. | 2: KernelLog.String("Bottom Field");
  198. | 3: KernelLog.String("Frame");
  199. END;
  200. KernelLog.Ln;
  201. KernelLog.String("top field first: "); IF topFieldFirst THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  202. KernelLog.String("frame pred frame dct: "); IF framePredFrameDct THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  203. KernelLog.String("concealment MV: "); IF concealmentMV THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  204. KernelLog.String("qScaleType: "); IF qScaleType THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  205. KernelLog.String("intraVlcFormat: "); IF intraVlcFormat THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  206. KernelLog.String("alternate scan: "); IF alternateScan THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  207. KernelLog.String("repeat first field: "); IF repeatFirstField THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  208. KernelLog.String("chroma 4:2:0 type: "); IF chroma420Type THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  209. KernelLog.String("progressiveFrame: "); IF progressiveFrame THEN KernelLog.String("TRUE") ELSE KernelLog.String("FALSE") END; KernelLog.Ln;
  210. END Dump;
  211. END PicCodingExt;
  212. (* everything about motion vectors *)
  213. (* MPEG-1 does not use all variables *)
  214. MotionVectorInfos* = OBJECT
  215. VAR
  216. fullPel*: ARRAY 2 OF ARRAY 2 OF BOOLEAN; (* full Pel or half Pel *)
  217. fCode*: ARRAY 2 OF ARRAY 2 OF LONGINT; (* MPEG-2 version of forw/back f code *)
  218. f*: ARRAY 2 OF ARRAY 2 OF LONGINT;
  219. rSize*: ARRAY 2 OF ARRAY 2 OF LONGINT;
  220. motionVerticalFieldSelect*: ARRAY 2 OF ARRAY 2 OF BOOLEAN; (* flag to choose reference field for prediction *)
  221. motionCode*: ARRAY 2 OF ARRAY 2 OF ARRAY 2 OF LONGINT;
  222. motionResidual*: ARRAY 2 OF ARRAY 2 OF ARRAY 2 OF LONGINT;
  223. dmVector*: ARRAY 2 OF LONGINT;
  224. mv*: ARRAY 2 OF ARRAY 2 OF ARRAY 2 OF LONGINT; (* calculated motion vectors *)
  225. pmv*: ARRAY 2 OF ARRAY 2 OF ARRAY 2 OF LONGINT; (* predictions *)
  226. PROCEDURE Dump*(r, s, t: LONGINT);
  227. BEGIN
  228. KernelLog.String("Motion Vector Type: ");
  229. IF s = 0 THEN
  230. KernelLog.String("Forward ");
  231. ELSE
  232. KernelLog.String("Backward ");
  233. END;
  234. IF t = 0 THEN
  235. KernelLog.String("Horizontal");
  236. ELSE
  237. KernelLog.String("Vertical");
  238. END;
  239. KernelLog.Ln;
  240. KernelLog.String("fCode: "); KernelLog.Int(fCode[s][t], 0); KernelLog.Ln;
  241. KernelLog.String("fullPel: "); IF fullPel[r][s] THEN KernelLog.String("TRUE"); ELSE KernelLog.String("FALSE"); END; KernelLog.Ln;
  242. KernelLog.String("f: "); KernelLog.Int(f[r][s], 0); KernelLog.Ln;
  243. KernelLog.String("rSize: "); KernelLog.Int(rSize[r][s], 0); KernelLog.Ln;
  244. KernelLog.String("motionVerticalFieldSelect: "); IF motionVerticalFieldSelect[r][s] THEN KernelLog.String("TRUE"); ELSE KernelLog.String("FALSE"); END; KernelLog.Ln;
  245. KernelLog.String("motionCode: "); KernelLog.Int(motionCode[r][s][t], 0); KernelLog.Ln;
  246. KernelLog.String("motionResidual: "); KernelLog.Int(motionResidual[r][s][t], 0); KernelLog.Ln;
  247. KernelLog.String("dmVector: "); KernelLog.Int(dmVector[t], 0); KernelLog.Ln;
  248. END Dump;
  249. END MotionVectorInfos;
  250. (* Inverse Discrete Cosine Transformation - copied (and slightly modified) from DivXHelper.Mod *)
  251. IDCT* = OBJECT
  252. PROCEDURE PerformIDCT*(block: PointerToArrayOfLONGINT );
  253. VAR
  254. i: LONGINT;
  255. BEGIN
  256. FOR i:= 0 TO 7 DO
  257. IDCTRow( block, i * 8)
  258. END;
  259. FOR i:= 0 TO 7 DO
  260. IDCTCol( block, i )
  261. END;
  262. END PerformIDCT;
  263. PROCEDURE IDCTRow( blk: PointerToArrayOfLONGINT; baseIndex: LONGINT);
  264. VAR
  265. x0, x1, x2, x3, x4, x5, x6, x7, x8: LONGINT;
  266. adr, tempAdr: LONGINT;
  267. BEGIN
  268. adr := ADDRESSOF( blk[baseIndex] );
  269. (* shortcut *)
  270. x1 := SYSTEM.GET32( adr + 4*SIZEOF(LONGINT) ) * 2048;
  271. x2 := SYSTEM.GET32( adr + 6*SIZEOF(LONGINT) );
  272. x3 := SYSTEM.GET32( adr + 2*SIZEOF(LONGINT) );
  273. x4 := SYSTEM.GET32( adr + SIZEOF(LONGINT) );
  274. x5 := SYSTEM.GET32( adr + 7*SIZEOF(LONGINT) );
  275. x6 := SYSTEM.GET32( adr + 5*SIZEOF(LONGINT) );
  276. x7 := SYSTEM.GET32( adr + 3*SIZEOF(LONGINT) );
  277. IF ( x1 = 0 ) & ( x2 = 0 ) & ( x3 = 0 ) & ( x4 = 0 ) & ( x5 = 0 ) & ( x6 = 0 ) & ( x7 = 0 ) THEN
  278. x0 := SYSTEM.GET32( adr ) * 8;
  279. SYSTEM.PUT32( adr , x0 );
  280. tempAdr := adr + SIZEOF( LONGINT );
  281. SYSTEM.PUT32( tempAdr, x0 );
  282. tempAdr := tempAdr + SIZEOF( LONGINT );
  283. SYSTEM.PUT32( tempAdr, x0 );
  284. tempAdr := tempAdr + SIZEOF( LONGINT );
  285. SYSTEM.PUT32( tempAdr, x0 );
  286. tempAdr := tempAdr + SIZEOF( LONGINT );
  287. SYSTEM.PUT32( tempAdr, x0 );
  288. tempAdr := tempAdr + SIZEOF( LONGINT );
  289. SYSTEM.PUT32( tempAdr, x0 );
  290. tempAdr := tempAdr + SIZEOF( LONGINT );
  291. SYSTEM.PUT32( tempAdr, x0 );
  292. tempAdr := tempAdr + SIZEOF( LONGINT );
  293. SYSTEM.PUT32( tempAdr, x0 );
  294. RETURN
  295. END;
  296. x0 := ( SYSTEM.GET32( adr ) * 2048 ) + 128; (* for proper rounding in the fourth stage *)
  297. (* first stage *)
  298. x8 := W7 * ( x4 + x5 );
  299. x4 := x8 + ( W1 - W7 ) * x4;
  300. x5 := x8 - ( W1 + W7 ) * x5;
  301. x8 := W3 * ( x6 + x7 );
  302. x6 := x8 - ( W3 - W5 ) * x6;
  303. x7 := x8 - ( W3 + W5 ) * x7;
  304. (* second stage *)
  305. x8 := x0 + x1;
  306. x0 := x0 - x1;
  307. x1 := W6 * ( x3 + x2 );
  308. x2 := x1 - ( W2 + W6 ) * x2;
  309. x3 := x1 + ( W2 - W6 ) * x3;
  310. x1 := x4 + x6;
  311. x4 := x4 - x6;
  312. x6 := x5 + x7;
  313. x5 := x5 - x7;
  314. (* third stage *)
  315. x7 := x8 + x3;
  316. x8 := x8 - x3;
  317. x3 := x0 + x2;
  318. x0 := x0 - x2;
  319. x2 := ( 181 * ( x4 + x5 ) + 128 ) DIV 256;
  320. x4 := ( 181 * ( x4 - x5 ) + 128 ) DIV 256;
  321. (* fourth stage *)
  322. SYSTEM.PUT32( adr, ( x7 + x1 ) DIV 256 );
  323. tempAdr := adr + SIZEOF( LONGINT );
  324. SYSTEM.PUT32( tempAdr, ( x3 + x2 ) DIV 256 );
  325. tempAdr := tempAdr + SIZEOF( LONGINT );
  326. SYSTEM.PUT32( tempAdr, ( x0 + x4 ) DIV 256 );
  327. tempAdr := tempAdr + SIZEOF( LONGINT );
  328. SYSTEM.PUT32( tempAdr, ( x8 + x6 ) DIV 256 );
  329. tempAdr := tempAdr + SIZEOF( LONGINT );
  330. SYSTEM.PUT32( tempAdr, ( x8 - x6 ) DIV 256 );
  331. tempAdr := tempAdr + SIZEOF( LONGINT );
  332. SYSTEM.PUT32( tempAdr, ( x0 - x4 ) DIV 256 );
  333. tempAdr := tempAdr + SIZEOF( LONGINT );
  334. SYSTEM.PUT32( tempAdr, ( x3 - x2 ) DIV 256 );
  335. tempAdr := tempAdr + SIZEOF( LONGINT );
  336. SYSTEM.PUT32( tempAdr, ( x7 - x1 ) DIV 256 )
  337. END IDCTRow;
  338. PROCEDURE IDCTCol( blk: PointerToArrayOfLONGINT; baseIndex: LONGINT );
  339. VAR
  340. x0, x1, x2, x3, x4, x5, x6, x7, x8: LONGINT;
  341. adr, tempAdr, sourceAdr: LONGINT;
  342. BEGIN
  343. adr := ADDRESSOF( blk[baseIndex] );
  344. (* shortcut *)
  345. x1 := SYSTEM.GET32( adr + 32*SIZEOF(LONGINT) ) * 256;
  346. x2 := SYSTEM.GET32( adr + 48*SIZEOF(LONGINT) );
  347. x3 := SYSTEM.GET32( adr + 16*SIZEOF(LONGINT) );
  348. x4 := SYSTEM.GET32( adr + 8*SIZEOF(LONGINT) );
  349. x5 := SYSTEM.GET32( adr + 56*SIZEOF(LONGINT) );
  350. x6 := SYSTEM.GET32( adr + 40*SIZEOF(LONGINT) );
  351. x7 := SYSTEM.GET32( adr + 24*SIZEOF(LONGINT) );
  352. IF ( x1 = 0 ) & ( x2 = 0 ) & ( x3 = 0 ) & ( x4 = 0 ) & ( x5 = 0 ) & ( x6 = 0 ) & ( x7 = 0 ) THEN
  353. x0 := IdctBorder[( ( SYSTEM.GET32( adr ) + 32 ) DIV 64 ) + 512]; (* +512 is the base offset in the array *)
  354. SYSTEM.PUT32( adr , x0 );
  355. tempAdr := adr + 8*SIZEOF( LONGINT );
  356. SYSTEM.PUT32( tempAdr, x0 );
  357. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  358. SYSTEM.PUT32( tempAdr, x0 );
  359. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  360. SYSTEM.PUT32( tempAdr, x0 );
  361. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  362. SYSTEM.PUT32( tempAdr, x0 );
  363. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  364. SYSTEM.PUT32( tempAdr, x0 );
  365. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  366. SYSTEM.PUT32( tempAdr, x0 );
  367. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  368. SYSTEM.PUT32( tempAdr, x0 );
  369. RETURN
  370. END;
  371. x0 := (SYSTEM.GET32( adr )* 256) + 8192;
  372. (* first stage *)
  373. x8 := W7 * ( x4 + x5 ) + 4;
  374. x4 := ( x8 + ( W1 - W7 ) * x4 ) DIV 8;
  375. x5 := ( x8 - ( W1 + W7) * x5 ) DIV 8;
  376. x8 := W3 * ( x6 + x7 ) + 4;
  377. x6 := ( x8 - ( W3 - W5 ) * x6 )DIV 8;
  378. x7 := ( x8 - ( W3 + W5 ) * x7 ) DIV 8;
  379. (* second stage *)
  380. x8 := x0 + x1;
  381. x0 := x0 - x1;
  382. x1 := W6 * ( x3 + x2 ) + 4;
  383. x2 := ( x1 - ( W2 + W6 ) * x2 ) DIV 8;
  384. x3 := ( x1 + ( W2 - W6 ) * x3 ) DIV 8;
  385. x1 := x4 + x6;
  386. x4 := x4 - x6;
  387. x6 := x5 + x7;
  388. x5 := x5 - x7;
  389. (* third stage *)
  390. x7 := x8 + x3;
  391. x8 := x8 - x3;
  392. x3 := x0 + x2;
  393. x0 := x0 - x2;
  394. x2 := ( 181 * ( x4 + x5 ) + 128 ) DIV 256;
  395. x4 := ( 181 * ( x4 - x5 ) + 128 ) DIV 256;
  396. (* fourth stage *)
  397. tempAdr := adr;
  398. sourceAdr := ADDRESSOF(IdctBorder[512] );
  399. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x7 + x1 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  400. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  401. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x3 + x2 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  402. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  403. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x0 + x4 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  404. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  405. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x8 + x6 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  406. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  407. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x8 - x6 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  408. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  409. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x0 - x4 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  410. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  411. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x3 - x2 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) );
  412. tempAdr := tempAdr + 8*SIZEOF( LONGINT );
  413. SYSTEM.PUT32( tempAdr, SYSTEM.GET32( ( ( ( x7 - x1 ) DIV 16384 )*SIZEOF(LONGINT) ) + sourceAdr ) )
  414. END IDCTCol;
  415. END IDCT;
  416. (* A demultiplexed (i.e. video or audio only) MPEG stream where single bits can be read *)
  417. (* Partially based on AVI.AVIStream *)
  418. BitStream* = OBJECT
  419. VAR
  420. first: LONGINT; (* First element in the ringbuffer *)
  421. last: LONGINT; (* Last element in the ringbuffer (only used until input reports EOF) *)
  422. bitIndex: LONGINT; (* Position (Bit) in the current LONGINT (buffer[0..3] or [4..7]) *)
  423. buffer: ARRAY 8 OF CHAR; (* Local buffer (two LONGINTs) *)
  424. bufAdr: LONGINT; (* Address of buffer[0] *)
  425. input: Codecs.DemuxStream; (* The underlying Reader *)
  426. eof: BOOLEAN; (* End of File *)
  427. bitsLeft: LONGINT; (* only used when eof is TRUE *)
  428. len: LONGINT;
  429. i: LONGINT;
  430. (* Constructor *)
  431. PROCEDURE & Init*( r: Codecs.DemuxStream );
  432. BEGIN
  433. ASSERT(r # NIL);
  434. first := 0;
  435. last := -1;
  436. bitIndex := 0;
  437. bufAdr := ADDRESSOF(buffer[0]);
  438. input := r;
  439. eof := FALSE;
  440. (* fill the buffer with the first bytes *)
  441. ReadLongintFromStream();
  442. ReadLongintFromStream();
  443. END Init;
  444. PROCEDURE Reset*;
  445. VAR
  446. dummy, result: LONGINT;
  447. BEGIN
  448. input.SetPosX(Codecs.SeekByte, 0, dummy, result);
  449. first := 0;
  450. last := -1;
  451. bitIndex := 0;
  452. bufAdr := ADDRESSOF(buffer[0]);
  453. eof := FALSE;
  454. (* fill the buffer with the first bytes *)
  455. ReadLongintFromStream();
  456. ReadLongintFromStream();
  457. END Reset;
  458. (* Read four bytes from the stream and write it to the buffer *)
  459. PROCEDURE ReadLongintFromStream;
  460. VAR
  461. read: LONGINT;
  462. BEGIN
  463. IF eof THEN RETURN END;
  464. input.Bytes(buffer, first, 4, read);
  465. IF (input.res = Streams.EOF) OR (read < 4) THEN
  466. eof := TRUE;
  467. bitsLeft := 32 + read*8;
  468. END;
  469. first := 4 - first;
  470. END ReadLongintFromStream;
  471. (* Align stream to next byte *)
  472. PROCEDURE ByteAlign*;
  473. BEGIN
  474. IF (bitIndex MOD 8) # 0 THEN
  475. SkipBits(8 - (bitIndex MOD 8));
  476. END;
  477. END ByteAlign;
  478. (* True if actual position is on byte boundary *)
  479. PROCEDURE IsAligned*(): BOOLEAN;
  480. BEGIN
  481. RETURN ((bitIndex MOD 8) = 0);
  482. END IsAligned;
  483. (* Read next n bits without advancing in stream. At least one, at most 32 Bits are allowed (this is not checked!) *)
  484. (* Returns -1 if eof *)
  485. PROCEDURE ShowBits*(n: LONGINT): LONGINT;
  486. VAR
  487. nbit: LONGINT;
  488. bufa, bufb: LONGINT;
  489. temp: LONGINT;
  490. BEGIN
  491. IF eof & (bitsLeft < n) THEN
  492. (* there are not enough bits -> return -1 *)
  493. RETURN -1;
  494. END;
  495. nbit := (bitIndex + n) - 32;
  496. IF nbit > 0 THEN
  497. (* we have to read both 32 bit values *)
  498. bufa := Machine.ChangeByteOrder(SYSTEM.GET32(bufAdr + first));
  499. bufb := Machine.ChangeByteOrder(SYSTEM.GET32(bufAdr + 4 - first));
  500. temp := LSH(LSH(bufa, bitIndex), nbit - bitIndex );
  501. RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LSH(bufb, nbit - 32)) + SYSTEM.VAL(SET, temp));
  502. ELSE
  503. (* the n bits are completely in the first 32 bits *)
  504. bufa := Machine.ChangeByteOrder(SYSTEM.GET32(bufAdr + first));
  505. RETURN LSH(LSH(bufa, bitIndex), n - 32);
  506. END;
  507. END ShowBits;
  508. (* Displays the content of the ringbuffer. Mainly used for debugging *)
  509. PROCEDURE ShowBuffer*;
  510. BEGIN
  511. KernelLog.Hex(ORD(buffer[0]), -1); KernelLog.String(" ");
  512. KernelLog.Hex(ORD(buffer[1]), -1); KernelLog.String(" ");
  513. KernelLog.Hex(ORD(buffer[2]), -1); KernelLog.String(" ");
  514. KernelLog.Hex(ORD(buffer[3]), -1); KernelLog.String(" ");
  515. KernelLog.Hex(ORD(buffer[4]), -1); KernelLog.String(" ");
  516. KernelLog.Hex(ORD(buffer[5]), -1); KernelLog.String(" ");
  517. KernelLog.Hex(ORD(buffer[6]), -1); KernelLog.String(" ");
  518. KernelLog.Hex(ORD(buffer[7]), -1); KernelLog.String(" ");
  519. KernelLog.String("first = "); KernelLog.Int(first, 0);
  520. END ShowBuffer;
  521. (* Read next n bits and advance bit stream. At most 32 bits are allowed *)
  522. PROCEDURE GetBits*( n: LONGINT): LONGINT;
  523. VAR
  524. ret: LONGINT;
  525. BEGIN
  526. ret := ShowBits( n );
  527. SkipBits( n );
  528. RETURN ret
  529. END GetBits;
  530. (* Skip next n bits. At most 32 bits are allowed *)
  531. PROCEDURE SkipBits*(n: LONGINT);
  532. BEGIN
  533. IF eof & (bitsLeft <= 0) THEN
  534. RETURN;
  535. END;
  536. IF eof THEN
  537. (* adjust bitsLeft *)
  538. DEC(bitsLeft, n);
  539. END;
  540. INC(bitIndex, n);
  541. IF bitIndex > 31 THEN
  542. ReadLongintFromStream();
  543. DEC(bitIndex, 32);
  544. END;
  545. END SkipBits;
  546. PROCEDURE Pos*(): Streams.Position;
  547. BEGIN
  548. RETURN input.Pos() - 8;
  549. END Pos;
  550. PROCEDURE SetPos*(pos: Streams.Position);
  551. VAR
  552. dummy, result: LONGINT;
  553. BEGIN
  554. input.SetPosX(Codecs.SeekByte, pos, dummy, result);
  555. first := 0;
  556. last := -1;
  557. bitIndex := 0;
  558. bufAdr := ADDRESSOF(buffer[0]);
  559. eof := FALSE;
  560. (* fill the buffer with the first bytes *)
  561. ReadLongintFromStream();
  562. ReadLongintFromStream();
  563. END SetPos;
  564. PROCEDURE HasMoreData*(): BOOLEAN;
  565. BEGIN
  566. RETURN ~(eof & (bitsLeft <= 0));
  567. END HasMoreData;
  568. END BitStream;
  569. (* Provides procedures to read multiple information from an MPEGBitStream *)
  570. StreamReader* = OBJECT
  571. VAR
  572. stream: BitStream;
  573. eof*: BOOLEAN;
  574. (* constructor *)
  575. PROCEDURE &init*(s: BitStream);
  576. BEGIN
  577. stream := s;
  578. eof := FALSE;
  579. END init;
  580. (* Read the next motion code from the stream *)
  581. PROCEDURE ReadMotionCode*(): LONGINT;
  582. VAR
  583. bits: LONGINT;
  584. res: WORD;
  585. BEGIN
  586. IF eof THEN RETURN 0 END;
  587. bits := stream.GetBits(1);
  588. IF bits = 1 THEN
  589. RETURN 0;
  590. ELSIF bits < 0 THEN
  591. eof := TRUE;
  592. RETURN 0;
  593. ELSE
  594. bits := stream.ShowBits(3);
  595. IF bits < 0 THEN eof := TRUE; RETURN 0 END;
  596. IF bits # 0 THEN
  597. res := MPEGTables.MC4[bits][0];
  598. stream.SkipBits(MPEGTables.MC4[bits][1]);
  599. bits := stream.GetBits(1);
  600. IF bits = 1 THEN
  601. RETURN -res;
  602. ELSIF bits < 0 THEN
  603. eof := TRUE;
  604. RETURN 0;
  605. ELSE
  606. RETURN res;
  607. END;
  608. ELSE
  609. stream.SkipBits(3);
  610. bits := stream.ShowBits(3);
  611. IF bits < 0 THEN eof := TRUE; RETURN 0 END;
  612. IF bits >= 3 THEN
  613. res := MPEGTables.MC7[bits][0];
  614. stream.SkipBits(MPEGTables.MC7[bits][1]);
  615. bits := stream.GetBits(1);
  616. IF bits = 1 THEN
  617. RETURN -res;
  618. ELSIF bits < 0 THEN
  619. eof := TRUE;
  620. RETURN 0;
  621. ELSE
  622. RETURN res;
  623. END;
  624. ELSE
  625. stream.SkipBits(1);
  626. bits := stream.ShowBits(5) - 12;
  627. IF bits <= -12 THEN eof := TRUE; RETURN 0 END;
  628. res := MPEGTables.MC10[bits][0];
  629. stream.SkipBits(MPEGTables.MC10[bits][1]);
  630. bits := stream.GetBits(1);
  631. IF bits = 1 THEN
  632. RETURN -res;
  633. ELSIF bits < 0 THEN
  634. eof := TRUE;
  635. RETURN 0;
  636. ELSE
  637. RETURN res;
  638. END;
  639. END;
  640. END;
  641. END;
  642. END ReadMotionCode;
  643. (* Read the next run/level code from the stream. Assumption: 10 = end of block (not 0/1) *)
  644. (* Returns EndOfBlock *)
  645. PROCEDURE ReadRunLevelCode*(c: PointerToArrayOfLONGINT; VAR cur: LONGINT; MPEG2: BOOLEAN): BOOLEAN;
  646. VAR
  647. run, length: LONGINT;
  648. level: LONGINT;
  649. index: LONGINT;
  650. BEGIN
  651. IF eof THEN RETURN TRUE END;
  652. length := 0;
  653. CASE stream.ShowBits(6) OF
  654. 0:
  655. (* 0000 00 -> CASE for the next 6 bits *)
  656. CASE stream.ShowBits(12) OF
  657. 1:
  658. (* 0000 0000 0001 -> RLC17*)
  659. stream.SkipBits(12);
  660. index := stream.ShowBits(4);
  661. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  662. run := MPEGTables.RLC17[index][0];
  663. level := MPEGTables.RLC17[index][1];
  664. length := 4;
  665. | 2..3:
  666. (* 0000 0000 0010 .. 0000 0000 0011 -> RLC16*)
  667. stream.SkipBits(11);
  668. index := stream.ShowBits(4);
  669. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  670. run := MPEGTables.RLC16[index][0];
  671. level := MPEGTables.RLC16[index][1];
  672. length := 4;
  673. | 4..7:
  674. (* 0000 0000 0100 .. 0000 0000 0111 -> no table (trivial) *)
  675. stream.SkipBits(10);
  676. index := stream.ShowBits(4);
  677. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  678. run := 0;
  679. level := 31-index;
  680. length := 4;
  681. | 8..15:
  682. (* 0000 0000 1000 .. 0000 0000 1111 -> RLC14*)
  683. stream.SkipBits(9);
  684. index := stream.ShowBits(4);
  685. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  686. run := MPEGTables.RLC14[index][0];
  687. level := MPEGTables.RLC14[index][1];
  688. length := 4;
  689. | 16..31:
  690. (* 0000 0001 0000 .. 0000 0001 1111 -> RLC13*)
  691. stream.SkipBits(8);
  692. index := stream.ShowBits(4);
  693. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  694. run := MPEGTables.RLC13[index][0];
  695. level := MPEGTables.RLC13[index][1];
  696. length := 4;
  697. | 32..63:
  698. (* 0000 0010 0000 .. 0000 0011 1111 -> RLC11*)
  699. stream.SkipBits(7);
  700. index := stream.ShowBits(3);
  701. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  702. run := MPEGTables.RLC11[index][0];
  703. level := MPEGTables.RLC11[index][1];
  704. length := 3;
  705. ELSE
  706. (* must be negative *)
  707. eof := TRUE;
  708. RETURN TRUE;
  709. END;
  710. | 1:
  711. (* 0000 01 -> Escape *)
  712. stream.SkipBits(6);
  713. run := stream.GetBits(6);
  714. IF run < 0 THEN eof := TRUE; RETURN TRUE END;
  715. IF ~MPEG2 THEN
  716. index := stream.GetBits(8);
  717. IF index = 0 THEN
  718. level := stream.GetBits(8);
  719. IF level < 0 THEN eof := TRUE; RETURN TRUE END;
  720. ELSIF index = 128 THEN
  721. level := -stream.GetBits(8);
  722. IF level > 0 THEN eof := TRUE; RETURN TRUE END;
  723. ELSIF index < 0 THEN
  724. eof := TRUE;
  725. RETURN TRUE;
  726. ELSE
  727. IF index > 127 THEN
  728. level := -256+index;
  729. ELSE
  730. level := index;
  731. END;
  732. END;
  733. ELSE
  734. (* MPEG-2 *)
  735. level := stream.GetBits(12);
  736. ASSERT(level # 0);
  737. IF level > 2047 THEN
  738. level := level - 4095; (* level + 1 - 2*2048 *)
  739. ELSIF level < 0 THEN
  740. eof := TRUE;
  741. RETURN TRUE;
  742. END;
  743. END;
  744. INC(cur, run);
  745. c[MPEGTables.ZZN[cur]] := level;
  746. INC(cur);
  747. RETURN FALSE;
  748. | 2..7:
  749. (* 0000 10 .. 0001 11 -> RLC8 *)
  750. index := stream.ShowBits(7) - 4;
  751. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  752. run := MPEGTables.RLC8[index][0];
  753. level := MPEGTables.RLC8[index][1];
  754. length := MPEGTables.RLC8[index][2];
  755. | 8..9:
  756. (* 0010 00 .. 0010 01 -> RLC9 *)
  757. index := stream.ShowBits(8) - 32;
  758. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  759. run := MPEGTables.RLC9[index][0];
  760. level := MPEGTables.RLC9[index][1];
  761. length := 8;
  762. | 10..31:
  763. (* 0010 10 .. 0111 11 -> RLC6 *)
  764. index := stream.ShowBits(5) - 5;
  765. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  766. run := MPEGTables.RLC6[index][0];
  767. level := MPEGTables.RLC6[index][1];
  768. length := MPEGTables.RLC6[index][2];
  769. | 32..47:
  770. (* 1000 00 .. 1011 11 -> End of Block *)
  771. stream.SkipBits(2);
  772. RETURN TRUE;
  773. | 48..63:
  774. (* 1100 00 .. 1111 11 -> 0/1 *)
  775. run := 0;
  776. level := 1;
  777. length := 2;
  778. ELSE
  779. eof := TRUE;
  780. RETURN TRUE;
  781. END;
  782. stream.SkipBits(length);
  783. index := stream.GetBits(1);
  784. IF index = 1 THEN
  785. level := -level;
  786. ELSIF index < 0 THEN
  787. eof := TRUE;
  788. RETURN TRUE;
  789. END;
  790. INC(cur, run);
  791. c[MPEGTables.ZZN[cur]] := level;
  792. INC(cur);
  793. RETURN FALSE;
  794. END ReadRunLevelCode;
  795. (* Read the next run/level code from the stream (second table, MPEG2 only) *)
  796. (* Returns EndOfBlock *)
  797. PROCEDURE ReadRunLevelCode2*(c: PointerToArrayOfLONGINT; VAR cur: LONGINT): BOOLEAN;
  798. VAR
  799. run, length: LONGINT;
  800. level: LONGINT;
  801. index: LONGINT;
  802. BEGIN
  803. IF eof THEN RETURN TRUE END;
  804. length := 0;
  805. CASE stream.ShowBits(6) OF
  806. 0:
  807. (* 0000 00 -> CASE for the next 6 bits *)
  808. CASE stream.ShowBits(12) OF
  809. 1:
  810. (* 0000 0000 0001 -> RLC17*)
  811. stream.SkipBits(12);
  812. index := stream.ShowBits(4);
  813. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  814. run := MPEGTables.RLC17[index][0];
  815. level := MPEGTables.RLC17[index][1];
  816. length := 4;
  817. | 2..3:
  818. (* 0000 0000 0010 .. 0000 0000 0011 -> RLC16*)
  819. stream.SkipBits(11);
  820. index := stream.ShowBits(4);
  821. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  822. run := MPEGTables.RLC16[index][0];
  823. level := MPEGTables.RLC16[index][1];
  824. length := 4;
  825. | 4..7:
  826. (* 0000 0000 0100 .. 0000 0000 0111 -> no table (trivial) *)
  827. stream.SkipBits(10);
  828. index := stream.ShowBits(4);
  829. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  830. run := 0;
  831. level := 31-index;
  832. length := 4;
  833. | 8..15:
  834. (* 0000 0000 1000 .. 0000 0000 1111 -> RLC14*)
  835. stream.SkipBits(9);
  836. index := stream.ShowBits(4);
  837. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  838. run := MPEGTables.RLC14[index][0];
  839. level := MPEGTables.RLC14[index][1];
  840. length := 4;
  841. | 16..31:
  842. (* 0000 0001 0000 .. 0000 0001 1111 -> RLC13*)
  843. stream.SkipBits(8);
  844. index := stream.ShowBits(4);
  845. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  846. run := MPEGTables.RLC13[index][0];
  847. level := MPEGTables.RLC13[index][1];
  848. length := 4;
  849. | 32..39:
  850. (* 0000 0010 0 -> 5/2*)
  851. run := 5;
  852. level := 2;
  853. length := 9;
  854. | 40..47:
  855. (* 0000 0010 1 -> 14/1*)
  856. run := 14;
  857. level := 1;
  858. length := 9;
  859. | 48..51:
  860. (* 0000 0011 00 -> 2/4*)
  861. run := 2;
  862. level := 4;
  863. length := 10;
  864. | 52..55:
  865. (* 0000 0011 01 -> 16/1*)
  866. run := 16;
  867. level := 1;
  868. length := 10;
  869. | 56..63:
  870. (* 0000 0011 1 -> 15/1*)
  871. run := 15;
  872. level := 1;
  873. length := 9;
  874. ELSE
  875. (* must be negative *)
  876. eof := TRUE;
  877. RETURN TRUE;
  878. END;
  879. | 1:
  880. (* 0000 01 -> Escape *)
  881. stream.SkipBits(6);
  882. run := stream.GetBits(6);
  883. IF run < 0 THEN eof := TRUE; RETURN TRUE END;
  884. level := stream.GetBits(12);
  885. ASSERT(level # 0);
  886. IF level > 2047 THEN
  887. level := level - 4095; (* level + 1 - 2*2048 *)
  888. ELSIF level < 0 THEN
  889. eof := TRUE;
  890. RETURN TRUE;
  891. END;
  892. INC(cur, run);
  893. c[MPEGTables.ZZN[cur]] := level;
  894. INC(cur);
  895. RETURN FALSE;
  896. | 2..7:
  897. (* 0000 10 .. 0001 11 -> RLC8_2 *)
  898. index := stream.ShowBits(7) - 4;
  899. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  900. run := MPEGTables.RLC8_2[index][0];
  901. level := MPEGTables.RLC8_2[index][1];
  902. length := MPEGTables.RLC8_2[index][2];
  903. | 8..9:
  904. (* 0010 00 .. 0010 01 -> RLC9_2 *)
  905. index := stream.ShowBits(8) - 32;
  906. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  907. run := MPEGTables.RLC9_2[index][0];
  908. level := MPEGTables.RLC9_2[index][1];
  909. length := 8;
  910. | 10..11:
  911. (* 0010 1 -> 2/1 *)
  912. run := 2;
  913. level := 1;
  914. length := 5;
  915. | 12..13:
  916. (* 0011 0 -> 1/2 *)
  917. run := 1;
  918. level := 2;
  919. length := 5;
  920. | 14..15:
  921. (* 0011 1 -> 3/1 *)
  922. run := 3;
  923. level := 1;
  924. length := 5;
  925. | 16..23:
  926. (* 010 -> 1/1 *)
  927. run := 1;
  928. level := 1;
  929. length := 3;
  930. | 24..27:
  931. (* 0110 -> End of Block *)
  932. stream.SkipBits(4);
  933. RETURN TRUE;
  934. | 28..31:
  935. (* 0111 -> 0/3 *)
  936. run := 0;
  937. level := 3;
  938. length := 4;
  939. | 32..47:
  940. (* 10 -> 0/1 *)
  941. run := 0;
  942. level := 1;
  943. length := 2;
  944. | 48..55:
  945. (* 110 -> 0/23 *)
  946. run := 0;
  947. level := 2;
  948. length := 3;
  949. | 56..57:
  950. (* 1110 0 -> 0/4 *)
  951. run := 0;
  952. level := 4;
  953. length := 5;
  954. | 58..59:
  955. (* 1110 1 -> 0/6 *)
  956. run := 0;
  957. level := 6;
  958. length := 5;
  959. | 60..63:
  960. (* 1111 00 .. 1111 11 -> RLC9_2_2 *)
  961. index := stream.ShowBits(8) - 240;
  962. IF index < 0 THEN eof := TRUE; RETURN TRUE END;
  963. run := MPEGTables.RLC9_2_2[index][0];
  964. level := MPEGTables.RLC9_2_2[index][1];
  965. length := MPEGTables.RLC9_2_2[index][2];
  966. ELSE
  967. eof := TRUE;
  968. RETURN TRUE;
  969. END;
  970. stream.SkipBits(length);
  971. index := stream.GetBits(1);
  972. IF index = 1 THEN
  973. level := -level;
  974. ELSIF index < 0 THEN
  975. eof := TRUE;
  976. RETURN TRUE;
  977. END;
  978. INC(cur, run);
  979. c[MPEGTables.ZZN[cur]] := level;
  980. INC(cur);
  981. RETURN FALSE;
  982. END ReadRunLevelCode2;
  983. (* Read the macroblock address increment *)
  984. (* Return value: > 0 -> increment; -1 -> error; -2 -> escape; -3 -> stuffing *)
  985. PROCEDURE ReadAddressIncrement*():LONGINT;
  986. VAR
  987. tmp: LONGINT;
  988. BEGIN
  989. IF eof THEN RETURN 0 END;
  990. CASE stream.ShowBits(4) OF
  991. 0:
  992. (* code length 7..11 *)
  993. stream.SkipBits(4);
  994. CASE stream.ShowBits(4) OF
  995. 0:
  996. (* illegal value *)
  997. RETURN -1;
  998. | 1:
  999. (* escape or stuffing *)
  1000. stream.SkipBits(4);
  1001. tmp := stream.GetBits(3);
  1002. IF tmp = 0 THEN
  1003. RETURN -2;
  1004. ELSIF tmp = 7 THEN
  1005. RETURN -3;
  1006. ELSIF tmp < 0 THEN
  1007. eof := TRUE;
  1008. RETURN 0;
  1009. ELSE
  1010. RETURN -1;
  1011. END;
  1012. | 2:
  1013. (* illegal value *)
  1014. RETURN -1;
  1015. | 3..5:
  1016. (* code length 10 or 11 *)
  1017. IF stream.ShowBits(6) >= 18 THEN
  1018. tmp := stream.GetBits(6);
  1019. RETURN (39-tmp);
  1020. ELSIF stream.ShowBits(6) < 0 THEN
  1021. eof := TRUE;
  1022. RETURN 0;
  1023. ELSE
  1024. tmp := stream.GetBits(7);
  1025. RETURN (57-tmp);
  1026. END;
  1027. | 6..11:
  1028. (* code length 8 *)
  1029. tmp := stream.GetBits(4);
  1030. IF tmp < 0 THEN eof := TRUE; RETURN 0 END;
  1031. RETURN (21-tmp);
  1032. | 12..15:
  1033. (* code length 7 *)
  1034. tmp := stream.GetBits(3);
  1035. IF tmp < 0 THEN eof := TRUE; RETURN 0 END;
  1036. RETURN (15-tmp);
  1037. ELSE
  1038. eof := TRUE;
  1039. RETURN 0;
  1040. END;
  1041. | 1:
  1042. (* code length 5 *)
  1043. tmp := stream.GetBits(5);
  1044. IF tmp < 0 THEN eof := TRUE; RETURN 0 END;
  1045. RETURN (9-tmp);
  1046. | 2:
  1047. (* code 0010 *)
  1048. stream.SkipBits(4);
  1049. RETURN 5;
  1050. | 3:
  1051. (* code 0011 *)
  1052. stream.SkipBits(4);
  1053. RETURN 4;
  1054. | 4,5:
  1055. (* code 010 *)
  1056. stream.SkipBits(3);
  1057. RETURN 3;
  1058. | 6,7:
  1059. (* code 011 *)
  1060. stream.SkipBits(3);
  1061. RETURN 2;
  1062. | 8..15:
  1063. (* code 1 *)
  1064. stream.SkipBits(1);
  1065. RETURN 1;
  1066. ELSE
  1067. eof := TRUE;
  1068. RETURN 0;
  1069. END;
  1070. END ReadAddressIncrement;
  1071. PROCEDURE ReadMacroBlockType*(type: LONGINT; VAR intra, pattern, back, forw, quant: BOOLEAN): BOOLEAN;
  1072. VAR
  1073. tmp: LONGINT;
  1074. BEGIN
  1075. IF eof THEN RETURN FALSE END;
  1076. intra := FALSE;
  1077. pattern := FALSE;
  1078. back := FALSE;
  1079. forw := FALSE;
  1080. quant := FALSE;
  1081. CASE type OF
  1082. 1: (* I-Picture *)
  1083. intra := TRUE;
  1084. tmp := stream.GetBits(1);
  1085. IF tmp = 1 THEN
  1086. RETURN TRUE;
  1087. ELSIF tmp < 0 THEN
  1088. eof := TRUE;
  1089. RETURN FALSE;
  1090. ELSE
  1091. tmp := stream.GetBits(1);
  1092. IF tmp = 1 THEN
  1093. quant := TRUE;
  1094. RETURN TRUE;
  1095. ELSIF tmp < 0 THEN
  1096. eof := TRUE;
  1097. RETURN FALSE;
  1098. ELSE
  1099. RETURN FALSE;
  1100. END;
  1101. END;
  1102. | 2: (* P-Picture *)
  1103. CASE stream.ShowBits(3) OF
  1104. 0:
  1105. stream.SkipBits(3);
  1106. CASE stream.ShowBits(3) OF
  1107. 0:
  1108. (* illegal value *)
  1109. RETURN FALSE;
  1110. | 1:
  1111. (* 0000 01 *)
  1112. stream.SkipBits(3);
  1113. intra := TRUE;
  1114. quant := TRUE;
  1115. RETURN TRUE;
  1116. | 2,3:
  1117. (* 0000 1 *)
  1118. stream.SkipBits(2);
  1119. pattern := TRUE;
  1120. quant := TRUE;
  1121. RETURN TRUE;
  1122. | 4,5:
  1123. (* 0001 0 *)
  1124. stream.SkipBits(2);
  1125. pattern := TRUE;
  1126. forw := TRUE;
  1127. quant := TRUE;
  1128. RETURN TRUE;
  1129. | 6,7:
  1130. (* 0001 1 *)
  1131. stream.SkipBits(2);
  1132. intra := TRUE;
  1133. RETURN TRUE;
  1134. ELSE
  1135. eof := TRUE;
  1136. RETURN FALSE;
  1137. END;
  1138. | 1:
  1139. (* 001 *)
  1140. stream.SkipBits(3);
  1141. forw := TRUE;
  1142. RETURN TRUE;
  1143. | 2,3:
  1144. (* 01 *)
  1145. stream.SkipBits(2);
  1146. pattern := TRUE;
  1147. RETURN TRUE;
  1148. | 4..7:
  1149. (* 1 *)
  1150. stream.SkipBits(1);
  1151. pattern := TRUE;
  1152. forw := TRUE;
  1153. RETURN TRUE;
  1154. ELSE
  1155. eof := TRUE;
  1156. RETURN FALSE;
  1157. END;
  1158. | 3: (* B-Picture *)
  1159. CASE stream.ShowBits(4) OF
  1160. 0:
  1161. stream.SkipBits(4);
  1162. tmp := stream.GetBits(2);
  1163. CASE tmp OF
  1164. 0:
  1165. (* illegal value *)
  1166. RETURN FALSE;
  1167. | 1:
  1168. (* 0000 01 *)
  1169. intra := TRUE;
  1170. quant := TRUE;
  1171. RETURN TRUE;
  1172. | 2:
  1173. (* 0000 10 *)
  1174. pattern := TRUE;
  1175. back := TRUE;
  1176. quant := TRUE;
  1177. RETURN TRUE;
  1178. | 3:
  1179. (* 0000 11 *)
  1180. pattern := TRUE;
  1181. forw := TRUE;
  1182. quant := TRUE;
  1183. RETURN TRUE;
  1184. ELSE
  1185. eof := TRUE;
  1186. RETURN FALSE;
  1187. END;
  1188. | 1:
  1189. stream.SkipBits(4);
  1190. tmp := stream.GetBits(1);
  1191. IF tmp = 0 THEN
  1192. (* 0001 0 *)
  1193. pattern := TRUE;
  1194. forw := TRUE;
  1195. back := TRUE;
  1196. quant := TRUE;
  1197. RETURN TRUE;
  1198. ELSIF tmp < 0 THEN
  1199. eof := TRUE;
  1200. RETURN FALSE;
  1201. ELSE
  1202. (* 0001 1 *)
  1203. intra := TRUE;
  1204. RETURN TRUE;
  1205. END;
  1206. | 2:
  1207. (* 0010 *)
  1208. stream.SkipBits(4);
  1209. forw := TRUE;
  1210. RETURN TRUE;
  1211. | 3:
  1212. (* 0011 *)
  1213. stream.SkipBits(4);
  1214. pattern := TRUE;
  1215. forw := TRUE;
  1216. RETURN TRUE;
  1217. | 4,5:
  1218. (* 010 *)
  1219. stream.SkipBits(3);
  1220. back := TRUE;
  1221. RETURN TRUE;
  1222. | 6,7:
  1223. (* 011 *)
  1224. stream.SkipBits(3);
  1225. pattern := TRUE;
  1226. back := TRUE;
  1227. RETURN TRUE;
  1228. | 8..11:
  1229. (* 10 *)
  1230. stream.SkipBits(2);
  1231. forw := TRUE;
  1232. back := TRUE;
  1233. RETURN TRUE;
  1234. | 12..15:
  1235. (* 11 *)
  1236. stream.SkipBits(2);
  1237. pattern := TRUE;
  1238. forw := TRUE;
  1239. back := TRUE;
  1240. RETURN TRUE;
  1241. ELSE
  1242. eof := TRUE;
  1243. RETURN FALSE;
  1244. END;
  1245. | 4: (* D-Picture *)
  1246. tmp := stream.GetBits(1);
  1247. IF tmp = 1 THEN
  1248. intra := TRUE;
  1249. RETURN TRUE;
  1250. ELSIF tmp < 0 THEN
  1251. eof := TRUE;
  1252. RETURN FALSE;
  1253. ELSE
  1254. RETURN FALSE;
  1255. END;
  1256. ELSE
  1257. RETURN FALSE; (* illegal picture type *)
  1258. END;
  1259. (* we should not reach this point *)
  1260. END ReadMacroBlockType;
  1261. PROCEDURE ReadSequenceExtension*(
  1262. VAR MainProfile: BOOLEAN;
  1263. VAR LevelID: LONGINT;
  1264. VAR ChromaFormat: LONGINT;
  1265. VAR videoWidth, videoHeight: LONGINT): BOOLEAN;
  1266. VAR
  1267. tmp: LONGINT;
  1268. BEGIN
  1269. IF eof THEN RETURN FALSE END;
  1270. (* escape bit, must be 0 for all currently defined profiles and levels *)
  1271. IF stream.ShowBits(1) # 0 THEN
  1272. IF stream.ShowBits(1) < 0 THEN
  1273. eof := TRUE;
  1274. RETURN FALSE;
  1275. ELSE
  1276. KernelLog.String("Profile/Level not supported"); KernelLog.Ln;
  1277. RETURN FALSE;
  1278. END;
  1279. ELSE
  1280. stream.SkipBits(1);
  1281. END;
  1282. (* Profile *)
  1283. CASE stream.ShowBits(3) OF
  1284. 0..3, 6, 7:
  1285. KernelLog.String("Profile not supported"); KernelLog.Ln;
  1286. RETURN FALSE;
  1287. | 4: (* Main Profile *)
  1288. MainProfile := TRUE;
  1289. | 5: (* Simple Profile *)
  1290. MainProfile := FALSE;
  1291. ELSE
  1292. eof := TRUE;
  1293. RETURN FALSE;
  1294. END;
  1295. stream.SkipBits(3);
  1296. (* Level *)
  1297. CASE stream.ShowBits(4) OF
  1298. 0..3, 5, 7, 9, 11..16:
  1299. KernelLog.String("Level not supported"); KernelLog.Ln;
  1300. RETURN FALSE;
  1301. | 4: (* High *)
  1302. IF MainProfile THEN
  1303. LevelID := 4;
  1304. ELSE
  1305. KernelLog.String("Level not supported"); KernelLog.Ln;
  1306. RETURN FALSE;
  1307. END;
  1308. | 6: (* High 1440 *)
  1309. IF MainProfile THEN
  1310. LevelID := 3;
  1311. ELSE
  1312. KernelLog.String("Level not supported"); KernelLog.Ln;
  1313. RETURN FALSE;
  1314. END;
  1315. | 8: (* Main *)
  1316. LevelID := 2;
  1317. | 10: (* Low *)
  1318. LevelID := 1;
  1319. ELSE
  1320. eof := TRUE;
  1321. RETURN FALSE;
  1322. END;
  1323. stream.SkipBits(4);
  1324. (* Progressive Bit *)
  1325. (* We ignore this bit because it is rarely used (even if the whole movie IS progressive) and therefore does not help that much *)
  1326. stream.SkipBits(1);
  1327. (* Chroma format *)
  1328. CASE stream.ShowBits(2) OF
  1329. 0: (* reserved *)
  1330. KernelLog.String("Illegal chroma format"); KernelLog.Ln;
  1331. | 1: (* 4:2:0, the only format required to be supported by MP@ML *)
  1332. ChromaFormat := 1;
  1333. | 2: (* 4:2:2, currently not supported - not sure if it will ever be... *)
  1334. KernelLog.String("4:2:2 chroma format is not supported"); KernelLog.Ln;
  1335. RETURN FALSE;
  1336. | 3: (* 4:4:4, currently not supported - not sure if it will ever be... *)
  1337. KernelLog.String("4:4:4: chroma format is not supported"); KernelLog.Ln;
  1338. RETURN FALSE;
  1339. ELSE
  1340. eof := TRUE;
  1341. RETURN FALSE;
  1342. END;
  1343. stream.SkipBits(2);
  1344. (* horizontal size extension *)
  1345. tmp := stream.GetBits(2);
  1346. IF tmp < 0 THEN RETURN FALSE END;
  1347. videoWidth := tmp * 4096 + videoWidth;
  1348. (* vertical size extension *)
  1349. tmp := stream.GetBits(2);
  1350. IF tmp < 0 THEN RETURN FALSE END;
  1351. videoHeight := tmp * 4096 + videoHeight;
  1352. (* ignore all the rest: bitrate (12), marker (1), vbv buffer (8), low delay (1), framerate (7) *)
  1353. stream.SkipBits(29);
  1354. RETURN TRUE;
  1355. END ReadSequenceExtension;
  1356. PROCEDURE ReadSequenceDisplayExtension*(): BOOLEAN;
  1357. BEGIN
  1358. IF eof THEN RETURN FALSE END;
  1359. (* Contains information about the source video format -> not important for the decoder *)
  1360. stream.SkipBits(7);
  1361. IF stream.ShowBits(1) = 1 THEN
  1362. stream.SkipBits(24);
  1363. END;
  1364. stream.SkipBits(30);
  1365. RETURN TRUE;
  1366. END ReadSequenceDisplayExtension;
  1367. PROCEDURE ReadQuantMatrixExtension*(): BOOLEAN;
  1368. BEGIN
  1369. IF eof THEN RETURN FALSE END;
  1370. END ReadQuantMatrixExtension;
  1371. PROCEDURE ReadCopyrightExtension*(): BOOLEAN;
  1372. BEGIN
  1373. IF eof THEN RETURN FALSE END;
  1374. END ReadCopyrightExtension;
  1375. PROCEDURE ReadPictureDisplayExtension*(): BOOLEAN;
  1376. BEGIN
  1377. IF eof THEN RETURN FALSE END;
  1378. END ReadPictureDisplayExtension;
  1379. PROCEDURE ReadPictureCodingExtension*(VAR pce: PicCodingExt; VAR mvi: MotionVectorInfos): BOOLEAN;
  1380. BEGIN
  1381. IF eof THEN RETURN FALSE END;
  1382. mvi.fCode[0][0] := stream.GetBits(4);
  1383. mvi.fCode[0][1] := stream.GetBits(4);
  1384. mvi.fCode[1][0] := stream.GetBits(4);
  1385. mvi.fCode[1][1] := stream.GetBits(4);
  1386. pce.dcPrecision := stream.GetBits(2);
  1387. pce.picStructure := stream.GetBits(2);
  1388. pce.topFieldFirst := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1389. pce.framePredFrameDct := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1390. pce.concealmentMV := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1391. pce.qScaleType := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1392. pce.intraVlcFormat := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1393. pce.alternateScan := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1394. pce.repeatFirstField := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1395. pce.chroma420Type := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1396. pce.progressiveFrame := stream.ShowBits(1) = 1; stream.SkipBits(1);
  1397. IF stream.ShowBits(1) = 1 THEN
  1398. stream.SkipBits(21);
  1399. ELSE
  1400. stream.SkipBits(1);
  1401. END;
  1402. IF stream.ShowBits(1) < 0 THEN
  1403. eof := TRUE;
  1404. RETURN FALSE;
  1405. END;
  1406. RETURN TRUE;
  1407. END ReadPictureCodingExtension;
  1408. PROCEDURE ReadQuantizerMatrix*(matrix: PointerToArrayOfLONGINT);
  1409. VAR
  1410. i, j: LONGINT;
  1411. tmp: LONGINT;
  1412. zzQM: ARRAY 64 OF LONGINT;
  1413. BEGIN
  1414. IF eof THEN RETURN END;
  1415. FOR i := 0 TO 63 DO
  1416. tmp := stream.GetBits(8);
  1417. IF tmp < 0 THEN
  1418. eof := TRUE;
  1419. RETURN;
  1420. ELSE
  1421. zzQM[i] := tmp;
  1422. END;
  1423. END;
  1424. FOR i := 0 TO 7 DO
  1425. FOR j := 0 TO 7 DO
  1426. matrix[i*8+j] := zzQM[MPEGTables.ZZ[i][j]];
  1427. END;
  1428. END;
  1429. END ReadQuantizerMatrix;
  1430. PROCEDURE ReadMotionVectors*(s: LONGINT; VAR mvi: MotionVectorInfos; frameMotionType: LONGINT);
  1431. BEGIN
  1432. IF eof THEN RETURN END;
  1433. IF frameMotionType # 1 THEN
  1434. IF frameMotionType # 2 THEN
  1435. mvi.motionVerticalFieldSelect[0][s] := (stream.GetBits(1) = 1);
  1436. END;
  1437. ReadMotionVectorsHelper(0, s, mvi);
  1438. ELSE
  1439. (* motionVectorCount = 2 *)
  1440. mvi.motionVerticalFieldSelect[0][s] := (stream.GetBits(1) = 1);
  1441. ReadMotionVectorsHelper(0, s, mvi);
  1442. mvi.motionVerticalFieldSelect[1][s] := (stream.GetBits(1) = 1);
  1443. ReadMotionVectorsHelper(1, s, mvi);
  1444. END;
  1445. IF stream.ShowBits(1) < 0 THEN
  1446. eof := TRUE;
  1447. END;
  1448. END ReadMotionVectors;
  1449. PROCEDURE ReadMotionVectorsHelper(r, s: LONGINT; VAR mvi: MotionVectorInfos);
  1450. BEGIN
  1451. IF eof THEN RETURN END;
  1452. mvi.motionCode[r][s][0] := ReadMotionCode();
  1453. IF (mvi.fCode[s][0] # 1) & (mvi.motionCode[r][s][0] # 0) THEN
  1454. mvi.motionResidual[r][s][0] := stream.GetBits(mvi.fCode[s][0] - 1);
  1455. END;
  1456. IF FALSE THEN
  1457. CASE stream.ShowBits(2) OF
  1458. 0,1: mvi.dmVector[0] := 0;
  1459. stream.SkipBits(1);
  1460. | 2: mvi.dmVector[0] := 1;
  1461. stream.SkipBits(2);
  1462. | 3: mvi.dmVector[0] := -1;
  1463. stream.SkipBits(2);
  1464. END;
  1465. END;
  1466. mvi.motionCode[r][s][1] := ReadMotionCode();
  1467. IF (mvi.fCode[s][1] # 1) & (mvi.motionCode[r][s][1] # 0) THEN
  1468. mvi.motionResidual[r][s][1] := stream.GetBits(mvi.fCode[s][1] - 1);
  1469. END;
  1470. IF FALSE THEN (* interlaced videos only *)
  1471. CASE stream.ShowBits(2) OF
  1472. 0,1: mvi.dmVector[1] := 0;
  1473. stream.SkipBits(1);
  1474. | 2: mvi.dmVector[1] := 1;
  1475. stream.SkipBits(2);
  1476. | 3: mvi.dmVector[1] := -1;
  1477. stream.SkipBits(2);
  1478. END;
  1479. END;
  1480. IF stream.ShowBits(1) < 0 THEN
  1481. eof := TRUE;
  1482. END;
  1483. END ReadMotionVectorsHelper;
  1484. END StreamReader;
  1485. TYPE MMXConsts = POINTER TO MMXConstsDesc;
  1486. TYPE MMXConstsDesc = RECORD
  1487. mmwMultY, mmwMultUG, mmwMultUB, mmwMultVR, mmwMultVG: HUGEINT;
  1488. (* various masks and other constants *)
  1489. mmb10, mmw0080, mmw00ff, mmwCutRed, mmwCutGreen, mmwCutBlue: HUGEINT;
  1490. mask5, mask6, maskBlue: HUGEINT;
  1491. END;
  1492. (* Convert colorspace (copied and slightly edited from the DivXPlayer) *)
  1493. TYPE ColorSpace* = OBJECT
  1494. VAR
  1495. mmxConsts: MMXConsts;
  1496. (* initialize rgb lookup tables *)
  1497. PROCEDURE &Init*;
  1498. BEGIN
  1499. NEW( mmxConsts );
  1500. mmxConsts.mmwMultY := 2568256825682568H;
  1501. mmxConsts.mmwMultUG := 0F36EF36EF36EF36EH;
  1502. mmxConsts.mmwMultUB := 40CF40CF40CF40CFH;
  1503. mmxConsts.mmwMultVR := 3343334333433343H;
  1504. mmxConsts.mmwMultVG := 0E5E2E5E2E5E2E5E2H;
  1505. (* various masks and other constants *)
  1506. mmxConsts.mmb10 := 1010101010101010H;
  1507. mmxConsts.mmw0080 := 0080008000800080H;
  1508. mmxConsts.mmw00ff := 00FF00FF00FF00FFH;
  1509. mmxConsts.mmwCutRed := 7C007C007C007C00H;
  1510. mmxConsts.mmwCutGreen := 03E003E003E003E0H;
  1511. mmxConsts.mmwCutBlue := 001F001F001F001FH;
  1512. mmxConsts.mask5 := 0F8F8F8F8F8F8F8F8H;
  1513. mmxConsts.mask6 := 0FCFCFCFCFCFCFCFCH;
  1514. mmxConsts.maskBlue := 1F1F1F1F1F1F1F1FH;
  1515. END Init;
  1516. (* Convert picture from one colorspace to an another *)
  1517. PROCEDURE Convert*(
  1518. src: PointerToArrayOfCHAR;
  1519. srcYBaseOffset: LONGINT;
  1520. yStride: LONGINT;
  1521. srcUBaseOffset, srcVBaseOffset,uvStride: LONGINT;
  1522. img: Raster.Image;
  1523. width, height, dstStride: LONGINT );
  1524. BEGIN
  1525. IF img.fmt.code = Raster.BGR888.code THEN
  1526. ConvertYUVToRGB888( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1527. dstStride );
  1528. ELSIF img.fmt.code = Raster.BGR565.code THEN
  1529. IF EnableMMX THEN
  1530. ConvertYUVToRGB565MMX( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1531. dstStride );
  1532. ELSE
  1533. ConvertYUVToRGB565( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1534. dstStride );
  1535. END;
  1536. END;
  1537. END Convert;
  1538. (* Convert picture from YUV -> RGB 565, mmx version *)
  1539. PROCEDURE ConvertYUVToRGB565MMX(
  1540. puc: PointerToArrayOfCHAR;
  1541. pucYBaseOffset: LONGINT;
  1542. strideY: LONGINT;
  1543. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT;
  1544. pucOut: Raster.Image;
  1545. widthY, heightY, strideOut: LONGINT );
  1546. VAR
  1547. y, horizCount: LONGINT;
  1548. pusOut: LONGINT;
  1549. BEGIN
  1550. strideOut := widthY*2;
  1551. IF heightY < 0 THEN
  1552. (* we are flipping our output upside-down *)
  1553. heightY := -heightY;
  1554. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1555. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1556. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1557. strideY := -strideY;
  1558. strideUV := -strideUV;
  1559. END;
  1560. pusOut := pucOut.adr;
  1561. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1562. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1563. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1564. horizCount := -(widthY DIV 8);
  1565. FOR y := 0 TO heightY-1 DO
  1566. ScanLine565MMX(horizCount, pucVBaseOffset, pucUBaseOffset, pucYBaseOffset, pusOut,
  1567. ADDRESSOF( mmxConsts.mmwMultY ) );
  1568. pucYBaseOffset := pucYBaseOffset + strideY;
  1569. IF ( y MOD 2 ) > 0 THEN
  1570. pucUBaseOffset := pucUBaseOffset + strideUV;
  1571. pucVBaseOffset := pucVBaseOffset + strideUV
  1572. END;
  1573. pusOut := pusOut + strideOut;
  1574. END;
  1575. END ConvertYUVToRGB565MMX;
  1576. PROCEDURE ScanLine565MMX(horizCount, pucV, pucU, pucY, pucOut: LONGINT; mmxConsts: LONGINT);
  1577. CODE { SYSTEM.MMX, SYSTEM.PentiumPro }
  1578. PUSH ECX
  1579. MOV EAX, [EBP+pucOut]
  1580. MOV EBX, [EBP+pucY]
  1581. MOV ECX, [EBP+pucU]
  1582. MOV EDX, [EBP+pucV]
  1583. MOV EDI, [EBP+horizCount]
  1584. MOV ESI, [EBP+mmxConsts]
  1585. horizLoop:
  1586. ; load data
  1587. MOVD MMX2, [ECX] ; mm2 = ________u3u2u1u0
  1588. MOVD MMX3, [EDX] ; mm3 = ________v3v2v1v0
  1589. MOVQ MMX0, [EBX] ; mm0 = y7y6y5y4y3y2y1y0
  1590. PXOR MMX7, MMX7 ; zero mm7
  1591. ; convert chroma part
  1592. PUNPCKLBW MMX2, MMX7 ; MMX2 = __U3__U2__U1__U0
  1593. PUNPCKLBW MMX3, MMX7 ; MMX3 = __V3__V2__V1__V0
  1594. ; PSUBW MMX2, mmw0080 ; MMX2 -= 128
  1595. PSUBW MMX2, [ESI+48] ; MMX2 -= 128
  1596. ; PSUBW MMX3, mmw0080 ; MMX3 -= 128
  1597. PSUBW MMX3, [ESI+48] ; MMX3 -= 128
  1598. PSLLW MMX2, 3 ; MMX2 *= 8
  1599. PSLLW MMX3, 3 ; MMX3 *= 8
  1600. MOVQ MMX4, MMX2 ; MMX4 = MMX2 = U
  1601. MOVQ MMX5, MMX3 ; MMX5 = MMX3 = V
  1602. ; PMULHW MMX2, mmwMultUG ; MMX2 *= U GREEN COEFF
  1603. ; PMULHW MMX3, mmwMultVG ; MMX3 *= V GREEN COEFF
  1604. ; PMULHW MMX4, mmwMultUB ; MMX4 = BLUE CHROMA
  1605. ; PMULHW MMX5, mmwMultVR ; MMX5 = RED CHROMA
  1606. PMULHW MMX2, [ESI+8] ; MMX2 *= U GREEN COEFF
  1607. PMULHW MMX3, [ESI+32] ; MMX3 *= V GREEN COEFF
  1608. PMULHW MMX4, [ESI+16] ; MMX4 = BLUE CHROMA
  1609. PMULHW MMX5, [ESI+24] ; MMX5 = RED CHROMA
  1610. PADDSW MMX2, MMX3 ; MMX2 = GREEN CHROMA
  1611. ; convert luma part
  1612. ; PSUBUSB MMX0, mmb10 ; MMX0 -= 16
  1613. ; MOVQ MMX1, mmw00ff
  1614. PSUBUSB MMX0, [ESI+40] ; MMX0 -= 16
  1615. MOVQ MMX6, [ESI+56] ;
  1616. MOVQ MMX1, MMX0
  1617. PSRLW MMX0, 8 ; MMX0 = __Y7__Y5__Y3__Y1 LUMA ODD
  1618. PAND MMX1, MMX6 ; MMX1 = __Y6__Y4__Y2__Y0 LUMA EVEN
  1619. PSLLW MMX0, 3 ; MMX0 *= 8
  1620. PSLLW MMX1, 3 ; MMX1 *= 8
  1621. ; PMULHW MMX0, mmwMultY ; MMX0 LUMA ODD *= LUMA COEFF
  1622. ; PMULHW MMX1, mmwMultY ; MMX1 LUMA EVEN *= LUMA COEFF
  1623. PMULHW MMX0, [ESI] ; MMX0 LUMA ODD *= LUMA COEFF
  1624. PMULHW MMX1, [ESI] ; MMX1 LUMA EVEN *= LUMA COEFF
  1625. ; complete the matrix calc with the additions
  1626. MOVQ MMX3, MMX4 ; COPY BLUE CHROMA
  1627. MOVQ MMX6, MMX5 ; COPY RED CHROMA
  1628. MOVQ MMX7, MMX2 ; COPY GREEN CHROMA
  1629. PADDSW MMX3, MMX0 ; MMX3 = LUMA ODD + BLUE CHROMA
  1630. PADDSW MMX4, MMX1 ; MMX4 = LUMA EVEN + BLUE CHROMA
  1631. PADDSW MMX6, MMX0 ; MMX6 = LUMA ODD + RED CHROMA
  1632. PADDSW MMX5, MMX1 ; MMX5 = LUMA EVEN + RED CHROMA
  1633. PADDSW MMX7, MMX0 ; MMX7 = LUMA ODD + GREEN CHROMA
  1634. PADDSW MMX2, MMX1 ; MMX2 = LUMA EVEN + GREEN CHROMA
  1635. ; clipping
  1636. PACKUSWB MMX3, MMX3
  1637. PACKUSWB MMX4, MMX4
  1638. PACKUSWB MMX6, MMX6
  1639. PACKUSWB MMX5, MMX5
  1640. PACKUSWB MMX7, MMX7
  1641. PACKUSWB MMX2, MMX2
  1642. ; interleave odd and even parts
  1643. PUNPCKLBW MMX4, MMX3 ; MMX4 = B7B6B5B4B3B2B1B0 BLUE
  1644. PUNPCKLBW MMX5, MMX6 ; MMX5 = R7R6R5R4R3R2R1R0 RED
  1645. PUNPCKLBW MMX2, MMX7 ; MMX2 = G7G6G5G4G3G2G1G0 GREEN
  1646. ; mask not needed bits (using 555)
  1647. ; PAND MMX4, mask5
  1648. ; PAND MMX5, mask5
  1649. ; PAND MMX2, mask5
  1650. PAND MMX4, [ESI+88]
  1651. PAND MMX5, [ESI+88]
  1652. PAND MMX2, [ESI+96]
  1653. ; mix colors and write
  1654. PSRLW MMX4, 3 ; MMX4 = RED SHIFTED
  1655. ; PAND MMX4, maskBlue ; MASK THE BLUE AGAIN
  1656. PAND MMX4, [ESI+104] ; MASK THE BLUE AGAIN
  1657. PXOR MMX7, MMX7 ; ZERO MMX7
  1658. MOVQ MMX1, MMX5 ; MMX1 = COPY BLUE
  1659. MOVQ MMX3, MMX4 ; MMX3 = COPY RED
  1660. MOVQ MMX6, MMX2 ; MMX6 = COPY GREEN
  1661. PUNPCKHBW MMX1, MMX7
  1662. PUNPCKHBW MMX3, MMX7
  1663. PUNPCKHBW MMX6, MMX7
  1664. PSLLW MMX6, 3 ; SHIFT GREEN
  1665. PSLLW MMX1, 8 ; SHIFT BLUE
  1666. POR MMX6, MMX3
  1667. POR MMX6, MMX1
  1668. MOVQ [EAX+8], MMX6
  1669. PUNPCKLBW MMX2, MMX7 ; MMX2 = __G3__G2__G1__G0 ALREADY MASKED
  1670. PUNPCKLBW MMX4, MMX7
  1671. PUNPCKLBW MMX5, MMX7
  1672. PSLLW MMX2, 3 ; SHIFT GREEN
  1673. PSLLW MMX5, 8 ; SHIFT BLUE
  1674. POR MMX2, MMX4
  1675. POR MMX2, MMX5
  1676. MOVQ [EAX], MMX2
  1677. ADD EBX, 8 ; PUCY += 8;
  1678. ADD ECX, 4 ; PUCU += 4;
  1679. ADD EDX, 4 ; PUCV += 4;
  1680. ADD EAX, 16 ; PUCOUT += 16 // WROTE 16 BYTES
  1681. INC EDI
  1682. JNE horizLoop
  1683. EMMS
  1684. POP ECX
  1685. END ScanLine565MMX;
  1686. (* Convert picture from YUV -> RGB 565 *)
  1687. PROCEDURE ConvertYUVToRGB565(
  1688. puc: PointerToArrayOfCHAR;
  1689. pucYBaseOffset: LONGINT;
  1690. strideY: LONGINT;
  1691. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT;
  1692. pucOut: Raster.Image;
  1693. widthY, heightY, strideOut: LONGINT );
  1694. VAR
  1695. xCount, yCount, strideDiff: LONGINT;
  1696. pusOut: LONGINT;
  1697. r, g, b: LONGINT;
  1698. y, u, v: LONGINT;
  1699. BEGIN
  1700. strideDiff := (strideOut - widthY)*SIZEOF(INTEGER); (* expressed in bytes *)
  1701. IF heightY < 0 THEN
  1702. (* we are flipping our output upside-down *)
  1703. heightY := -heightY;
  1704. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1705. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1706. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1707. strideY := -strideY;
  1708. strideUV := -strideUV;
  1709. END;
  1710. pusOut := pucOut.adr;
  1711. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1712. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1713. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1714. FOR yCount := 0 TO heightY - 1 DO
  1715. FOR xCount := 0 TO widthY - 1 DO
  1716. y := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucYBaseOffset + xCount ) ) ) - 16;
  1717. u := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucUBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1718. v := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucVBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1719. r := ( 2568H*y + 3343H*u ) DIV 2000H;
  1720. g := ( 2568H*y - 0C92H*v - 1A1EH*u ) DIV 2000H;
  1721. b := ( 2568H*y + 40CFH*v ) DIV 2000H;
  1722. IF r > 255 THEN r := 255; ELSIF r < 0 THEN r := 0 END;
  1723. IF g > 255 THEN g := 255; ELSIF g < 0 THEN g := 0 END;
  1724. IF b > 255 THEN b := 255; ELSIF b < 0 THEN b := 0 END;
  1725. SYSTEM.PUT16( pusOut, SYSTEM.VAL( INTEGER, SYSTEM.VAL( SET, r DIV 8 ) + SYSTEM.VAL( SET, ( g DIV 4 ) * 32 ) +
  1726. SYSTEM.VAL( SET, (b DIV 8 ) * 2048 ) ) );
  1727. pusOut := pusOut + SIZEOF( INTEGER );
  1728. END;
  1729. pucYBaseOffset := pucYBaseOffset + strideY;
  1730. IF yCount MOD 2 > 0 THEN
  1731. pucUBaseOffset := pucUBaseOffset + strideUV;
  1732. pucVBaseOffset := pucVBaseOffset + strideUV
  1733. END;
  1734. pusOut := pusOut + strideDiff;
  1735. END;
  1736. END ConvertYUVToRGB565;
  1737. (* Convert YUV -> RGB 888 *)
  1738. PROCEDURE ConvertYUVToRGB888(
  1739. puc: PointerToArrayOfCHAR;
  1740. pucYBaseOffset: LONGINT;
  1741. strideY: LONGINT;
  1742. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT;
  1743. pucOut: Raster.Image;
  1744. widthY, heightY, strideOut: LONGINT );
  1745. VAR
  1746. xCount, yCount, strideDiff: LONGINT;
  1747. pusOut: LONGINT;
  1748. r, g, b: LONGINT;
  1749. y, u, v: LONGINT;
  1750. BEGIN
  1751. strideDiff := (strideOut - widthY)*3; (* expressed in bytes *)
  1752. IF heightY < 0 THEN
  1753. (* we are flipping our output upside-down *)
  1754. heightY := -heightY;
  1755. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1756. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1757. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1758. strideY := -strideY;
  1759. strideUV := -strideUV;
  1760. END;
  1761. pusOut := pucOut.adr;
  1762. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1763. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1764. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1765. FOR yCount := 0 TO heightY - 1 DO
  1766. FOR xCount := 0 TO widthY - 1 DO
  1767. y := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucYBaseOffset + xCount ) ) ) - 16;
  1768. u := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucUBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1769. v := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucVBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1770. r := ( 2568H*y + 3343H*u ) DIV 2000H;
  1771. g := ( 2568H*y - 0C92H*v - 1A1EH*u ) DIV 2000H;
  1772. b := ( 2568H*y + 40CFH*v ) DIV 2000H;
  1773. IF r > 255 THEN r := 255; ELSIF r < 0 THEN r := 0 END;
  1774. IF g > 255 THEN g := 255; ELSIF g < 0 THEN g := 0 END;
  1775. IF b > 255 THEN b := 255; ELSIF b < 0 THEN b := 0 END;
  1776. SYSTEM.PUT8( pusOut, r );
  1777. INC( pusOut );
  1778. SYSTEM.PUT8( pusOut, g );
  1779. INC( pusOut );
  1780. SYSTEM.PUT8( pusOut, b );
  1781. INC( pusOut );
  1782. END;
  1783. pucYBaseOffset := pucYBaseOffset + strideY;
  1784. IF yCount MOD 2 > 0 THEN
  1785. pucUBaseOffset := pucUBaseOffset + strideUV;
  1786. pucVBaseOffset := pucVBaseOffset + strideUV;
  1787. END;
  1788. pusOut := pusOut + strideDiff;
  1789. END;
  1790. END ConvertYUVToRGB888;
  1791. END ColorSpace;
  1792. (* Procedures to clear, copy and interpolate blocks *)
  1793. (* TransferIDCT* is copied from the DivXPlayer *)
  1794. BlockActions* = OBJECT
  1795. (* clear an 8x8 CHAR block *)
  1796. PROCEDURE ClearBlock*(dest: PointerToArrayOfCHAR; destOffs, incr: LONGINT);
  1797. VAR
  1798. d: LONGINT; (* current address *)
  1799. i: LONGINT; (* loop var *)
  1800. BEGIN
  1801. d := ADDRESSOF(dest[destOffs]);
  1802. FOR i := 0 TO 7 DO
  1803. SYSTEM.PUT32(d, 0); (* wipes 4 CHARs each time *)
  1804. SYSTEM.PUT32(d + 4, 0); (* wipes 4 CHARs each time *)
  1805. INC(d, incr);
  1806. END;
  1807. END ClearBlock;
  1808. (* clear an 8x8 LONGINT array *)
  1809. PROCEDURE ClearBlockLongint*(block: PointerToArrayOfLONGINT);
  1810. BEGIN
  1811. IF EnableMMX THEN
  1812. ClearBlockMMX(ADDRESSOF(block[0]));
  1813. ELSE
  1814. ClearBlockGeneric(block);
  1815. END;
  1816. END ClearBlockLongint;
  1817. (* Reset block to 0 *)
  1818. PROCEDURE ClearBlockGeneric(block: PointerToArrayOfLONGINT );
  1819. VAR
  1820. i: LONGINT;
  1821. adr: LONGINT;
  1822. BEGIN
  1823. adr := ADDRESSOF( block[0] );
  1824. FOR i := 0 TO 63 DO
  1825. SYSTEM.PUT32( adr, 0 );
  1826. INC(adr, SIZEOF(LONGINT));
  1827. END;
  1828. END ClearBlockGeneric;
  1829. PROCEDURE ClearBlockMMX(dst: LONGINT);
  1830. CODE{ SYSTEM.MMX, SYSTEM.PentiumPro }
  1831. MOV EDX, -32 ; clear loop counter
  1832. MOV ESI, [EBP+dst] ; capture block address
  1833. PXOR MMX0, MMX0 ; mm0 = 0
  1834. loop:
  1835. MOVQ [ESI], MMX0 ; clear memory location
  1836. ADD ESI, 8
  1837. INC EDX
  1838. JNZ loop
  1839. EMMS
  1840. END ClearBlockMMX;
  1841. PROCEDURE CopyBlock*(src, dest: PointerToArrayOfCHAR; srcOffs, destOffs, srcIncr, destIncr, lines: LONGINT);
  1842. VAR
  1843. s, d: LONGINT; (* current addresses *)
  1844. i: LONGINT; (* loop var *)
  1845. BEGIN
  1846. s := ADDRESSOF(src[srcOffs]);
  1847. d := ADDRESSOF(dest[destOffs]);
  1848. FOR i := 0 TO (lines-1) DO
  1849. SYSTEM.MOVE(s, d, 8);
  1850. INC(s, srcIncr);
  1851. INC(d, destIncr);
  1852. END;
  1853. END CopyBlock;
  1854. (* move a block by overwriting the destination, motion vectors in half pel precision *)
  1855. PROCEDURE MoveBlockOverwrite*(src, dest: PointerToArrayOfCHAR; destOffs, mvX, mvY, srcIncr, destIncr, lines: LONGINT);
  1856. VAR
  1857. buffer: ARRAY 16 OF CHAR; (* temporary buffer *)
  1858. bufadr: LONGINT; (* address of buffer *)
  1859. index: LONGINT; (* position in buffer *)
  1860. i, j: LONGINT; (* loop vars *)
  1861. s, d: LONGINT; (* addresses of src and dest *)
  1862. tmp1, tmp2: LONGINT; (* temporary var *)
  1863. BEGIN
  1864. s := ADDRESSOF(src[destOffs])+ (mvY DIV 2)*destIncr + (mvX DIV 2);
  1865. d := ADDRESSOF(dest[destOffs]);
  1866. IF (mvX MOD 2) = 0 THEN
  1867. IF (mvY MOD 2) = 0 THEN
  1868. (* simple copy, no interpolation *)
  1869. CopyBlock(src, dest, destOffs + (mvY DIV 2)*destIncr + (mvX DIV 2), destOffs, srcIncr, destIncr, lines);
  1870. ELSE
  1871. (* vertical interpolation only *)
  1872. bufadr := ADDRESSOF(buffer[0]);
  1873. SYSTEM.MOVE(s, bufadr, 8);
  1874. INC(s, srcIncr);
  1875. FOR i := 0 TO (lines-1) DO
  1876. SYSTEM.MOVE(s, bufadr+8-index, 8);
  1877. FOR j := 0 TO 7 DO
  1878. SYSTEM.PUT8(d+j,
  1879. (ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + index + j))) +
  1880. ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + 8 - index + j)))) DIV 2);
  1881. END;
  1882. index := 8 - index;
  1883. INC(s, srcIncr);
  1884. INC(d, destIncr);
  1885. END;
  1886. END;
  1887. ELSE
  1888. IF (mvY MOD 2) = 0 THEN
  1889. (* horizontal interpolation only *)
  1890. bufadr := ADDRESSOF(buffer[0]);
  1891. FOR i := 0 TO (lines-1) DO
  1892. SYSTEM.MOVE(s+1, bufadr, 8);
  1893. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  1894. FOR j := 0 TO 7 DO
  1895. tmp1 := tmp2;
  1896. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+j)));
  1897. SYSTEM.PUT8(d+j, (tmp1 + tmp2) DIV 2);
  1898. END;
  1899. INC(s, srcIncr);
  1900. INC(d, destIncr);
  1901. END;
  1902. ELSE
  1903. (* vertical and horizontal interpolation *)
  1904. bufadr := ADDRESSOF(buffer[0]);
  1905. (* setup *)
  1906. SYSTEM.MOVE(s+1, bufadr, 8);
  1907. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  1908. FOR j := 0 TO 7 DO
  1909. tmp1 := tmp2;
  1910. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+j)));
  1911. SYSTEM.PUT8(bufadr+j, (tmp1 + tmp2) DIV 2);
  1912. END;
  1913. INC(s, srcIncr);
  1914. FOR i := 0 TO (lines-1) DO
  1915. (* part 1: horizontal interpolation *)
  1916. SYSTEM.MOVE(s+1, bufadr+8-index, 8);
  1917. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  1918. FOR j := 0 TO 7 DO
  1919. tmp1 := tmp2;
  1920. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+8-index+j)));
  1921. SYSTEM.PUT8(bufadr+8-index+j, (tmp1 + tmp2) DIV 2);
  1922. END;
  1923. (* part 2: vertical interpolation *)
  1924. FOR j := 0 TO 7 DO
  1925. SYSTEM.PUT8(bufadr+index+j,
  1926. (ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + index + j))) +
  1927. ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + 8 - index + j)))) DIV 2);
  1928. END;
  1929. SYSTEM.MOVE(bufadr+index, d, 8);
  1930. index := 8 - index;
  1931. INC(s, srcIncr);
  1932. INC(d, destIncr);
  1933. END;
  1934. END;
  1935. END;
  1936. END MoveBlockOverwrite;
  1937. (* move a block by interpolating (sum DIV 2) with the destination, motion vectors in half pel precision *)
  1938. PROCEDURE MoveBlockInterp*(src, dest: PointerToArrayOfCHAR; destOffs, mvX, mvY, srcIncr, destIncr, lines: LONGINT);
  1939. VAR
  1940. buffer: ARRAY 16 OF CHAR; (* temporary buffer *)
  1941. bufadr: LONGINT; (* address of buffer *)
  1942. index: LONGINT; (* position in buffer *)
  1943. i, j: LONGINT; (* loop vars *)
  1944. s, d: LONGINT; (* addresses of src and dest *)
  1945. tmp1, tmp2: LONGINT; (* temporary var *)
  1946. BEGIN
  1947. s := ADDRESSOF(src[destOffs])+ (mvY DIV 2)*destIncr + (mvX DIV 2);
  1948. d := ADDRESSOF(dest[destOffs]);
  1949. IF (mvX MOD 2) = 0 THEN
  1950. IF (mvY MOD 2) = 0 THEN
  1951. (* simple copy, no interpolation *)
  1952. FOR i := 0 TO (lines-1) DO
  1953. FOR j := 0 TO 7 DO
  1954. SYSTEM.PUT8(d+j,
  1955. (ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s+j))) +
  1956. ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(d+j)))) DIV 2);
  1957. END;
  1958. INC(s, srcIncr);
  1959. INC(d, destIncr);
  1960. END;
  1961. ELSE
  1962. (* vertical interpolation only *)
  1963. bufadr := ADDRESSOF(buffer[0]);
  1964. SYSTEM.MOVE(s, bufadr, 8);
  1965. INC(s, srcIncr);
  1966. FOR i := 0 TO (lines-1) DO
  1967. SYSTEM.MOVE(s, bufadr+8-index, 8);
  1968. FOR j := 0 TO 7 DO
  1969. tmp1 :=
  1970. (ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + index + j))) +
  1971. ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + 8 - index + j)))) DIV 2;
  1972. SYSTEM.PUT8(d+j, (tmp1 + ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(d + j)))) DIV 2);
  1973. END;
  1974. index := 8 - index;
  1975. INC(s, srcIncr);
  1976. INC(d, destIncr);
  1977. END;
  1978. END;
  1979. ELSE
  1980. IF (mvY MOD 2) = 0 THEN
  1981. (* horizontal interpolation only *)
  1982. bufadr := ADDRESSOF(buffer[0]);
  1983. FOR i := 0 TO (lines-1) DO
  1984. SYSTEM.MOVE(s+1, bufadr, 8);
  1985. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  1986. FOR j := 0 TO 7 DO
  1987. tmp1 := tmp2;
  1988. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+j)));
  1989. tmp1 := (tmp1 + tmp2) DIV 2;
  1990. SYSTEM.PUT8(d+j, (tmp1 + ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(d+j)))) DIV 2);
  1991. END;
  1992. INC(s, srcIncr);
  1993. INC(d, destIncr);
  1994. END;
  1995. ELSE
  1996. (* vertical and horizontal interpolation *)
  1997. bufadr := ADDRESSOF(buffer[0]);
  1998. (* setup *)
  1999. SYSTEM.MOVE(s+1, bufadr, 8);
  2000. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  2001. FOR j := 0 TO 7 DO
  2002. tmp1 := tmp2;
  2003. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+j)));
  2004. SYSTEM.PUT8(bufadr+j, (tmp1 + tmp2) DIV 2);
  2005. END;
  2006. INC(s, srcIncr);
  2007. FOR i := 0 TO (lines-1) DO
  2008. (* part 1: horizontal interpolation *)
  2009. SYSTEM.MOVE(s+1, bufadr+8-index, 8);
  2010. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(s)));
  2011. FOR j := 0 TO 7 DO
  2012. tmp1 := tmp2;
  2013. tmp2 := ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr+8-index+j)));
  2014. SYSTEM.PUT8(bufadr+8-index+j, (tmp1 + tmp2) DIV 2);
  2015. END;
  2016. (* part 2: vertical interpolation *)
  2017. FOR j := 0 TO 7 DO
  2018. tmp1 :=
  2019. (ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + index + j))) +
  2020. ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(bufadr + 8 - index + j)))) DIV 2;
  2021. SYSTEM.PUT8(d+j, (tmp1 + ORD(SYSTEM.VAL(CHAR, SYSTEM.GET8(d + j)))) DIV 2);
  2022. END;
  2023. index := 8 - index;
  2024. INC(s, srcIncr);
  2025. INC(d, destIncr);
  2026. END;
  2027. END;
  2028. END;
  2029. END MoveBlockInterp;
  2030. PROCEDURE TransferIDCTAdd*( source: PointerToArrayOfLONGINT; dest: PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  2031. BEGIN
  2032. IF EnableMMX THEN
  2033. TransferIDCTAddMMX( ADDRESSOF( source[0] ), ADDRESSOF( dest[destOffset] ), stride );
  2034. ELSE
  2035. TransferIDCTAddGeneric( source, dest, destOffset, stride );
  2036. END;
  2037. END TransferIDCTAdd;
  2038. PROCEDURE TransferIDCTCopy*( source: PointerToArrayOfLONGINT; dest: PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  2039. BEGIN
  2040. IF EnableMMX THEN
  2041. TransferIDCTCopyMMX( ADDRESSOF( source[0] ), ADDRESSOF( dest[destOffset] ), stride );
  2042. ELSE
  2043. TransferIDCTCopyGeneric( source, dest, destOffset, stride );
  2044. END;
  2045. END TransferIDCTCopy;
  2046. (* Add macroblock to a block in the actual picture *)
  2047. PROCEDURE TransferIDCTAddGeneric( source: PointerToArrayOfLONGINT; dest: PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  2048. VAR
  2049. x, y, s, d, sum: LONGINT;
  2050. BEGIN
  2051. stride := stride - 8;
  2052. s := ADDRESSOF( source[0] );
  2053. d := ADDRESSOF( dest[destOffset] );
  2054. FOR y := 0 TO 7 DO
  2055. FOR x := 0 TO 7 DO
  2056. sum := ORD( SYSTEM.VAL(CHAR, SYSTEM.GET8( d ) ) ) + SYSTEM.GET32( s );
  2057. IF sum > 255 THEN
  2058. SYSTEM.PUT8( d, 255 )
  2059. ELSIF sum < 0 THEN
  2060. SYSTEM.PUT8( d, 0 )
  2061. ELSE
  2062. SYSTEM.PUT8( d, sum )
  2063. END;
  2064. s := s + SIZEOF( LONGINT );
  2065. d := d + SIZEOF( CHAR );
  2066. END;
  2067. d := d + stride
  2068. END;
  2069. END TransferIDCTAddGeneric;
  2070. PROCEDURE TransferIDCTAddMMX( source, dest, stride: LONGINT );
  2071. CODE{ SYSTEM.MMX, SYSTEM.PentiumPro }
  2072. MOV EAX, [EBP+source] ; PARAMETER 1, *SOURCES32
  2073. MOV EBX, [EBP+dest] ; PARAMETER 2, *DESTU8
  2074. MOV EDI, [EBP+stride] ; PARAMETER 3, STRIDE
  2075. MOV EDX, -8 ; loop counter
  2076. PXOR MMX7, MMX7 ; SET MMX7 = 0
  2077. loop:
  2078. MOVQ MMX0, [EBX] ; eight bytes of destination into mm0
  2079. MOVQ MMX1, MMX0 ; eight bytes of destination into mm1
  2080. PUNPCKLBW MMX0, MMX7 ; unpack first 4 bytes from dest into mm0, no saturation
  2081. PUNPCKHBW MMX1, MMX7 ; unpack next 4 bytes from dest into mm1, no saturation
  2082. MOVQ MMX2, [EAX] ; two source Doublewords into mm2
  2083. PACKSSDW MMX2, [EAX+8] ; pack mm2 with next two source double words into mm2
  2084. MOVQ MMX3, [EAX+16]
  2085. PACKSSDW MMX3, [EAX+24]
  2086. PADDSW MMX0, MMX2 ; add source and destination
  2087. PADDSW MMX1, MMX3 ; add source and destination
  2088. PACKUSWB MMX0, MMX1 ; pack mm0 and mm1 into mm0
  2089. MOVQ [EBX], MMX0 ; copy output to destination
  2090. ADD EBX, EDI ; add +stride to dest ptr
  2091. ADD EAX, 32
  2092. INC EDX
  2093. JNZ loop
  2094. EMMS
  2095. END TransferIDCTAddMMX;
  2096. (* Copy a macroblock to the actual picture *)
  2097. PROCEDURE TransferIDCTCopyGeneric( source: PointerToArrayOfLONGINT; dest: PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  2098. VAR
  2099. x, y, s, d, val: LONGINT;
  2100. BEGIN
  2101. stride := stride - 8;
  2102. s := ADDRESSOF( source[0] );
  2103. d := ADDRESSOF( dest[destOffset] );
  2104. FOR y := 0 TO 7 DO
  2105. FOR x:= 0 TO 7 DO
  2106. val := SYSTEM.GET32( s );
  2107. IF val > 255 THEN
  2108. SYSTEM.PUT8( d, 255 )
  2109. ELSIF val < 0 THEN
  2110. SYSTEM.PUT8( d, 0 )
  2111. ELSE
  2112. SYSTEM.PUT8( d, val )
  2113. END;
  2114. s := s + SIZEOF(LONGINT);
  2115. d := d + SIZEOF( CHAR );
  2116. END;
  2117. d := d + stride
  2118. END;
  2119. END TransferIDCTCopyGeneric;
  2120. PROCEDURE TransferIDCTCopyMMX( source, dest, stride: LONGINT );
  2121. CODE{ SYSTEM.MMX, SYSTEM.PentiumPro }
  2122. MOV EAX, [EBP+source] ; PARAMETER 1, *SOURCES32
  2123. MOV EBX, [EBP+dest] ; PARAMETER 2, *DESTU8
  2124. MOV EDI, [EBP+stride] ; PARAMETER 3, STRIDE
  2125. MOV EDX, -8
  2126. loop:
  2127. MOVQ MMX0, [EAX] ; eight bytes (two LONGINT) of source into mm0
  2128. PACKSSDW MMX0, [EAX+8] ; Pack next 8 bytes (two LONGINT) together with mm0
  2129. MOVQ MMX1, [EAX+16]
  2130. PACKSSDW MMX1, [EAX+24]
  2131. PACKUSWB MMX0, MMX1 ; Pack 4 INTEGER with another 4 INTEGER into mm0
  2132. MOVQ [EBX], MMX0 ; Write mm0 to dest
  2133. ADD EBX, EDI ; Add stride to dest
  2134. ADD EAX, 32 ; next source
  2135. INC EDX
  2136. JNZ loop
  2137. EMMS
  2138. END TransferIDCTCopyMMX;
  2139. END BlockActions;
  2140. BEGIN
  2141. NEW(IdctBorder, 1024 );
  2142. FOR ii := -512 TO 511 DO
  2143. IF ii < -256 THEN
  2144. IdctBorder[ii + 512] := -256
  2145. ELSIF ii > 255 THEN
  2146. IdctBorder[ii + 512] := 255
  2147. ELSE
  2148. IdctBorder[ii + 512] := ii;
  2149. END;
  2150. END;
  2151. END MPEGUtilities.