I386.DivXDecoder.Mod 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266
  1. (* OpendivX Decoder based on the VideoDecoder Interface of Codecs, cleaned by PL *)
  2. MODULE DivXDecoder;
  3. IMPORT
  4. SYSTEM, Files,Streams, Raster, KernelLog,
  5. Math, Reals, DivXHelper, DT := DivXTypes, Codecs, AVI;
  6. TYPE MacroBlock *= OBJECT
  7. VAR
  8. mp4State: DT.MP4State;
  9. mv: MotionCompensation;
  10. (* Macroblock ModeMap *)
  11. mbWidth*, mbHeight*: LONGINT;
  12. DQTab: ARRAY 4 OF LONGINT;
  13. MCBPCTabIntra: ARRAY 32 OF DT.TabType;
  14. MCBPCTabInter: ARRAY 256 OF DT.TabType;
  15. CBPYTab: ARRAY 48 OF DT.TabType;
  16. log:Streams.Writer;
  17. texture: DivXHelper.TextureDecoding;
  18. PROCEDURE &init*( state: DT.MP4State; VAR reader: DT.VideoBuffer; logWriter: Streams.Writer );
  19. VAR
  20. i: LONGINT;
  21. BEGIN
  22. log := logWriter;
  23. mp4State := state;
  24. NEW( mv, state, log);
  25. NEW( texture, mp4State, log);
  26. mbWidth := mp4State.horizontalSize DIV 16;
  27. mbHeight := mp4State.verticalSize DIV 16;
  28. DQTab[0] := -1; DQTab[1] := -2; DQTab[2] := 1; DQTab[3] := 2;
  29. MCBPCTabIntra[0].val := -1; MCBPCTabIntra[0].len := 0; MCBPCTabIntra[1].val := 20; MCBPCTabIntra[1].len := 6;
  30. MCBPCTabIntra[2].val := 36; MCBPCTabIntra[2].len := 6; MCBPCTabIntra[3].val := 52; MCBPCTabIntra[3].len := 6;
  31. MCBPCTabIntra[4].val := 4; MCBPCTabIntra[4].len := 4; MCBPCTabIntra[5].val := 4; MCBPCTabIntra[5].len := 4;
  32. MCBPCTabIntra[6].val := 4; MCBPCTabIntra[6].len := 4; MCBPCTabIntra[7].val := 4; MCBPCTabIntra[7].len := 4;
  33. MCBPCTabIntra[8].val := 19; MCBPCTabIntra[8].len := 3; MCBPCTabIntra[9].val := 19; MCBPCTabIntra[9].len := 3;
  34. MCBPCTabIntra[10].val := 19; MCBPCTabIntra[10].len := 3; MCBPCTabIntra[11].val := 19; MCBPCTabIntra[11].len := 3;
  35. MCBPCTabIntra[12].val := 19; MCBPCTabIntra[12].len := 3; MCBPCTabIntra[13].val := 19; MCBPCTabIntra[13].len := 3;
  36. MCBPCTabIntra[14].val := 19; MCBPCTabIntra[14].len := 3; MCBPCTabIntra[15].val := 19; MCBPCTabIntra[15].len := 3;
  37. MCBPCTabIntra[16].val := 35; MCBPCTabIntra[16].len := 3; MCBPCTabIntra[17].val := 35; MCBPCTabIntra[17].len := 3;
  38. MCBPCTabIntra[18].val := 35; MCBPCTabIntra[18].len := 3; MCBPCTabIntra[19].val := 35; MCBPCTabIntra[19].len := 3;
  39. MCBPCTabIntra[20].val := 35; MCBPCTabIntra[20].len := 3; MCBPCTabIntra[21].val := 35; MCBPCTabIntra[21].len := 3;
  40. MCBPCTabIntra[22].val := 35; MCBPCTabIntra[22].len := 3; MCBPCTabIntra[23].val := 35; MCBPCTabIntra[23].len := 3;
  41. MCBPCTabIntra[24].val := 51; MCBPCTabIntra[24].len := 3; MCBPCTabIntra[25].val := 51; MCBPCTabIntra[25].len := 3;
  42. MCBPCTabIntra[26].val := 51; MCBPCTabIntra[26].len := 3; MCBPCTabIntra[27].val := 51; MCBPCTabIntra[27].len := 3;
  43. MCBPCTabIntra[28].val := 51; MCBPCTabIntra[28].len := 3; MCBPCTabIntra[29].val := 51; MCBPCTabIntra[29].len := 3;
  44. MCBPCTabIntra[30].val := 51; MCBPCTabIntra[30].len := 3; MCBPCTabIntra[31].val := 51; MCBPCTabIntra[31].len := 3;
  45. MCBPCTabInter[0].val := -1; MCBPCTabInter[0].len := 0;
  46. MCBPCTabInter[1].val := 255; MCBPCTabInter[1].len := 9;
  47. MCBPCTabInter[2].val := 52; MCBPCTabInter[2].len := 9;
  48. MCBPCTabInter[3].val := 36; MCBPCTabInter[3].len := 9;
  49. MCBPCTabInter[4].val := 20; MCBPCTabInter[4].len := 9;
  50. MCBPCTabInter[5].val := 49; MCBPCTabInter[5].len := 9;
  51. MCBPCTabInter[6].val := 35; MCBPCTabInter[6].len := 8;
  52. MCBPCTabInter[7].val := 35; MCBPCTabInter[7].len := 8;
  53. MCBPCTabInter[8].val := 19; MCBPCTabInter[8].len := 8;
  54. MCBPCTabInter[9].val := 19; MCBPCTabInter[9].len := 8;
  55. MCBPCTabInter[10].val := 50; MCBPCTabInter[10].len := 8;
  56. MCBPCTabInter[11].val := 50; MCBPCTabInter[11].len := 8;
  57. MCBPCTabInter[12].val := 51; MCBPCTabInter[12].len := 7;
  58. MCBPCTabInter[13].val := 51; MCBPCTabInter[13].len := 7;
  59. MCBPCTabInter[14].val := 51; MCBPCTabInter[14].len := 7;
  60. MCBPCTabInter[15].val := 51; MCBPCTabInter[15].len := 7;
  61. MCBPCTabInter[16].val := 34; MCBPCTabInter[16].len := 7;
  62. MCBPCTabInter[17].val := 34; MCBPCTabInter[17].len := 7;
  63. MCBPCTabInter[18].val := 34; MCBPCTabInter[18].len := 7;
  64. MCBPCTabInter[19].val := 34; MCBPCTabInter[19].len := 7;
  65. MCBPCTabInter[20].val := 18; MCBPCTabInter[20].len := 7;
  66. MCBPCTabInter[21].val := 18; MCBPCTabInter[21].len := 7;
  67. MCBPCTabInter[22].val := 18; MCBPCTabInter[22].len := 7;
  68. MCBPCTabInter[23].val := 18; MCBPCTabInter[23].len := 7;
  69. MCBPCTabInter[24].val := 33; MCBPCTabInter[24].len := 7;
  70. MCBPCTabInter[25].val := 33; MCBPCTabInter[25].len := 7;
  71. MCBPCTabInter[26].val := 33; MCBPCTabInter[26].len := 7;
  72. MCBPCTabInter[27].val := 33; MCBPCTabInter[27].len := 7;
  73. MCBPCTabInter[28].val := 17; MCBPCTabInter[28].len := 7;
  74. MCBPCTabInter[29].val := 17; MCBPCTabInter[29].len := 7;
  75. MCBPCTabInter[30].val := 17; MCBPCTabInter[30].len := 7;
  76. MCBPCTabInter[31].val := 17; MCBPCTabInter[31].len := 7;
  77. MCBPCTabInter[32].val := 4; MCBPCTabInter[32].len := 6;
  78. MCBPCTabInter[33].val := 4; MCBPCTabInter[33].len := 6;
  79. MCBPCTabInter[34].val := 4; MCBPCTabInter[34].len := 6;
  80. MCBPCTabInter[35].val := 4; MCBPCTabInter[35].len := 6;
  81. MCBPCTabInter[36].val := 4; MCBPCTabInter[36].len := 6;
  82. MCBPCTabInter[37].val := 4; MCBPCTabInter[37].len := 6;
  83. MCBPCTabInter[38].val := 4; MCBPCTabInter[38].len := 6;
  84. MCBPCTabInter[39].val := 4; MCBPCTabInter[39].len := 6;
  85. MCBPCTabInter[40].val := 48; MCBPCTabInter[40].len := 6;
  86. MCBPCTabInter[41].val := 48; MCBPCTabInter[41].len := 6;
  87. MCBPCTabInter[42].val := 48; MCBPCTabInter[42].len := 6;
  88. MCBPCTabInter[43].val := 48; MCBPCTabInter[43].len := 6;
  89. MCBPCTabInter[44].val := 48; MCBPCTabInter[44].len := 6;
  90. MCBPCTabInter[45].val := 48; MCBPCTabInter[45].len := 6;
  91. MCBPCTabInter[46].val := 48; MCBPCTabInter[46].len := 6;
  92. MCBPCTabInter[47].val := 48; MCBPCTabInter[47].len := 6;
  93. FOR i := 48 TO 63 DO MCBPCTabInter[i].val := 3; MCBPCTabInter[i].len := 5 END;
  94. FOR i := 64 TO 95 DO MCBPCTabInter[i].val := 32; MCBPCTabInter[i].len := 4 END;
  95. FOR i := 96 TO 127 DO MCBPCTabInter[i].val := 16; MCBPCTabInter[i].len := 4 END;
  96. FOR i := 128 TO 191 DO MCBPCTabInter[i].val := 2; MCBPCTabInter[i].len := 3 END;
  97. FOR i := 192 TO 255 DO MCBPCTabInter[i].val := 1; MCBPCTabInter[i].len := 3 END;
  98. CBPYTab[0].val := -1; CBPYTab[0].len := 0;
  99. CBPYTab[1].val := -1; CBPYTab[1].len := 0;
  100. CBPYTab[2].val := 6; CBPYTab[2].len := 6;
  101. CBPYTab[3].val := 9; CBPYTab[3].len := 6;
  102. CBPYTab[4].val := 8; CBPYTab[4].len := 5;
  103. CBPYTab[5].val := 8; CBPYTab[5].len := 5;
  104. CBPYTab[6].val := 4; CBPYTab[6].len := 5;
  105. CBPYTab[7].val := 4; CBPYTab[7].len := 5;
  106. CBPYTab[8].val := 2; CBPYTab[8].len := 5;
  107. CBPYTab[9].val := 2; CBPYTab[9].len := 5;
  108. CBPYTab[10].val := 1; CBPYTab[10].len := 5;
  109. CBPYTab[11].val := 1; CBPYTab[11].len := 5;
  110. CBPYTab[12].val := 0; CBPYTab[12].len := 4;
  111. CBPYTab[13].val := 0; CBPYTab[13].len := 4;
  112. CBPYTab[14].val := 0; CBPYTab[14].len := 4;
  113. CBPYTab[15].val := 0; CBPYTab[15].len := 4;
  114. CBPYTab[16].val := 12; CBPYTab[16].len := 4;
  115. CBPYTab[17].val := 12; CBPYTab[17].len := 4;
  116. CBPYTab[18].val := 12; CBPYTab[18].len := 4;
  117. CBPYTab[19].val := 12; CBPYTab[19].len := 4;
  118. CBPYTab[20].val := 10; CBPYTab[20].len := 4;
  119. CBPYTab[21].val := 10; CBPYTab[21].len := 4;
  120. CBPYTab[22].val := 10; CBPYTab[22].len := 4;
  121. CBPYTab[23].val := 10; CBPYTab[23].len := 4;
  122. CBPYTab[24].val := 14; CBPYTab[24].len := 4;
  123. CBPYTab[25].val := 14; CBPYTab[25].len := 4;
  124. CBPYTab[26].val := 14; CBPYTab[26].len := 4;
  125. CBPYTab[27].val := 14; CBPYTab[27].len := 4;
  126. CBPYTab[28].val := 5; CBPYTab[28].len := 4;
  127. CBPYTab[29].val := 5; CBPYTab[29].len := 4;
  128. CBPYTab[30].val := 5; CBPYTab[30].len := 4;
  129. CBPYTab[31].val := 5; CBPYTab[31].len := 4;
  130. CBPYTab[32].val := 13; CBPYTab[32].len := 4;
  131. CBPYTab[33].val := 13; CBPYTab[33].len := 4;
  132. CBPYTab[34].val := 13; CBPYTab[34].len := 4;
  133. CBPYTab[35].val := 13; CBPYTab[35].len := 4;
  134. CBPYTab[36].val := 3; CBPYTab[36].len := 4;
  135. CBPYTab[37].val := 3; CBPYTab[37].len := 4;
  136. CBPYTab[38].val := 3; CBPYTab[38].len := 4;
  137. CBPYTab[39].val := 3; CBPYTab[39].len := 4;
  138. CBPYTab[40].val := 11; CBPYTab[40].len := 4;
  139. CBPYTab[41].val := 11; CBPYTab[41].len := 4;
  140. CBPYTab[42].val := 11; CBPYTab[42].len := 4;
  141. CBPYTab[43].val := 11; CBPYTab[43].len := 4;
  142. CBPYTab[44].val := 7; CBPYTab[44].len := 4;
  143. CBPYTab[45].val := 7; CBPYTab[45].len := 4;
  144. CBPYTab[46].val := 7; CBPYTab[46].len := 4;
  145. CBPYTab[47].val := 7; CBPYTab[47].len := 4
  146. END init;
  147. (* Decode next macroblock *)
  148. PROCEDURE Decode(VAR s: DT.VideoBuffer ): BOOLEAN;
  149. VAR
  150. j, temp: LONGINT;
  151. intraFlag,interFlag, res, coded: BOOLEAN;
  152. BEGIN
  153. IF mp4State.hdr.predictionType # DT.IVOP THEN
  154. mp4State.hdr.notCoded := AVI.GetBits(1, s.data^, s.index)
  155. END;
  156. (* coded macroblock or I-VOP *)
  157. IF ( mp4State.hdr.notCoded = 0 ) OR ( mp4State.hdr.predictionType = DT.IVOP ) THEN
  158. mp4State.hdr.mcbpc := GetMCBPC(s); (* mcbpc *)
  159. mp4State.hdr.derivedMbType := mp4State.hdr.mcbpc MOD 8;
  160. mp4State.hdr.cbpc := ( mp4State.hdr.mcbpc DIV 16 ) MOD 4;
  161. (* Used only in P-VOP *)
  162. mp4State.modeMap[mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mp4State.hdr.derivedMbType;
  163. IF ( mp4State.hdr.derivedMbType = DT.Intra ) OR ( mp4State.hdr.derivedMbType = DT.IntraQ ) THEN
  164. intraFlag := TRUE
  165. ELSE
  166. intraFlag := FALSE
  167. END;
  168. interFlag := ~intraFlag;
  169. IF intraFlag THEN
  170. mp4State.hdr.acPredFlag := AVI.GetBits(1, s.data^, s.index)
  171. END;
  172. IF mp4State.hdr.derivedMbType # DT.Stuffing THEN
  173. mp4State.hdr.cbpy := GetCBPY(s); (* cbpy *)
  174. mp4State.hdr.cbp := SYSTEM.VAL( LONGINT, SYSTEM.VAL( SET, ( mp4State.hdr.cbpy * 4 ) ) +
  175. SYSTEM.VAL( SET, mp4State.hdr.cbpc ) );
  176. ELSE
  177. RETURN FALSE
  178. END;
  179. IF ( mp4State.hdr.derivedMbType = DT.InterQ ) OR ( mp4State.hdr.derivedMbType = DT.IntraQ ) THEN
  180. mp4State.hdr.dQuant := AVI.GetBits(2, s.data^, s.index);
  181. mp4State.hdr.quantizer := mp4State.hdr.quantizer + DQTab[mp4State.hdr.dQuant];
  182. IF ( mp4State.hdr.quantizer > 31 ) THEN
  183. mp4State.hdr.quantizer := 31
  184. ELSIF mp4State.hdr.quantizer < 1 THEN
  185. mp4State.hdr.quantizer := 1
  186. END;
  187. END;
  188. (* Set MotionVector *)
  189. IF ( mp4State.hdr.derivedMbType = DT.Inter ) OR ( mp4State.hdr.derivedMbType = DT.InterQ ) THEN
  190. res := mv.SetMV( -1, s )
  191. ELSIF mp4State.hdr.derivedMbType = DT.Inter4V THEN
  192. FOR j := 0 TO 3 DO
  193. res := mv.SetMV( j, s )
  194. END;
  195. ELSE (* Intra *)
  196. IF mp4State.hdr.predictionType = DT.PVOP THEN
  197. mv.ResetIntraMV(mp4State.hdr.mbYPos + 1, mp4State.hdr.mbXPos + 1 )
  198. END;
  199. END;
  200. (* motion compensation *)
  201. IF interFlag THEN
  202. mv.Reconstruct(mp4State.hdr.mbXPos, mp4State.hdr.mbYPos, mp4State.hdr.derivedMbType);
  203. (* texture decoding add *)
  204. FOR j := 0 TO 5 DO
  205. coded := 5 - j IN SYSTEM.VAL(SET, mp4State.hdr.cbp );
  206. IF coded THEN
  207. temp := texture.BlockInter( j, coded, s );
  208. AddBlockInter(j, mp4State.hdr.mbXPos, mp4State.hdr.mbYPos)
  209. END;
  210. END;
  211. ELSE
  212. (* texture decoding add *)
  213. FOR j := 0 TO 5 DO
  214. coded := 5 - j IN SYSTEM.VAL(SET, mp4State.hdr.cbp );
  215. temp := texture.BlockIntra( j, coded, s );
  216. AddBlockIntra(j, mp4State.hdr.mbXPos, mp4State.hdr.mbYPos)
  217. END;
  218. END;
  219. ELSE (* not coded macroblock *)
  220. mv.ResetNotCodedMV( mp4State.hdr.mbYPos + 1, mp4State.hdr.mbXPos + 1);
  221. mp4State.modeMap[mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := DT.NotCoded;
  222. mv.Reconstruct(mp4State.hdr.mbXPos, mp4State.hdr.mbYPos, mp4State.hdr.derivedMbType)
  223. END;
  224. mp4State.quantStore[mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mp4State.hdr.quantizer;
  225. IF mp4State.hdr.mbXPos < ( mbWidth - 1 ) THEN
  226. INC( mp4State.hdr.mbXPos );
  227. ELSE
  228. INC( mp4State.hdr.mbYPos );
  229. mp4State.hdr.mbXPos := 0
  230. END;
  231. RETURN TRUE;
  232. END Decode;
  233. (* Add an IntraBlock to the Picture *)
  234. PROCEDURE AddBlockIntra( comp, bx, by: LONGINT );
  235. VAR
  236. cc, iincr, offset: LONGINT;
  237. BEGIN
  238. (* color component index *)
  239. IF comp < 4 THEN cc := 0
  240. ELSE cc := ( comp MOD 2 ) + 1
  241. END;
  242. IF ( cc = 0 ) THEN (* luminance *)
  243. bx := bx * 16; (* pixel coordinates *)
  244. by := by * 16;
  245. (* frame DCT coding; *)
  246. offset := mp4State.frameRefBaseOffset[cc] +
  247. ( mp4State.codedPictureWidth * ( by + ( ( ( comp MOD 4 ) DIV 2 ) * 8 ) ) + bx + ( ( comp MOD 2 ) * 8 ) );
  248. iincr := mp4State.codedPictureWidth
  249. ELSE (* chrominance *)
  250. bx := bx * 8; (* pixel coordinates *)
  251. by := by * 8;
  252. (* frame DCT coding *)
  253. offset := mp4State.frameRefBaseOffset[cc] + mp4State.chromWidth * by + bx;
  254. iincr := mp4State.chromWidth
  255. END;
  256. IF DT.Debug THEN
  257. log.String( "TransferIDCTCopy: "); log.Int( offset - mp4State.frameRefBaseOffset[cc], 0 ); log.Char( ' ' );
  258. log.Int( iincr, 0 ); log.Ln()
  259. END;
  260. TransferIDCTCopy( ADDRESSOF(texture.dstBlock[4]), mp4State.frameRef, offset, iincr );
  261. END AddBlockIntra;
  262. (* Add an interblock to the current picture *)
  263. PROCEDURE AddBlockInter( comp, bx, by: LONGINT );
  264. VAR
  265. cc, iincr, offset: LONGINT;
  266. BEGIN
  267. IF comp < 4 THEN cc := 0
  268. ELSE cc := ( comp MOD 2 ) + 1
  269. END;
  270. IF cc = 0 THEN (* luminance *)
  271. bx := bx * 16; (* pixel coordinates *)
  272. by := by * 16;
  273. (* frame DCT coding *)
  274. offset := mp4State.frameRefBaseOffset[cc]
  275. + mp4State.codedPictureWidth * ( by + ( ( ( comp MOD 4 ) DIV 2 ) * 8 ) ) + bx + ( ( comp MOD 2 ) * 8 );
  276. iincr := mp4State.codedPictureWidth
  277. ELSE (* chrominance *)
  278. bx := bx * 8; (* pixel coordinates *)
  279. by := by * 8;
  280. (* frame DCT coding *)
  281. offset := mp4State.frameRefBaseOffset[cc] + mp4State.chromWidth * by + bx;
  282. iincr := mp4State.chromWidth
  283. END;
  284. IF DT.Debug THEN
  285. log.String( "TransferIDCTAdd: "); log.Int( offset - mp4State.frameRefBaseOffset[cc], 0 ); log.Char( ' ' );
  286. log.Int( iincr, 0 ); log.Ln()
  287. END;
  288. TransferIDCTAdd( ADDRESSOF(texture.dstBlock[4]), mp4State.frameRef, offset, iincr );
  289. END AddBlockInter;
  290. PROCEDURE TransferIDCTAdd( source: LONGINT; dest: DT.PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  291. BEGIN
  292. IF DT.EnableMMX THEN
  293. TransferIDCTAddMMX( source, ADDRESSOF( dest[destOffset] ), stride );
  294. ELSE
  295. TransferIDCTAddGeneric( source, dest, destOffset, stride );
  296. END;
  297. END TransferIDCTAdd;
  298. PROCEDURE TransferIDCTCopy( source: LONGINT; dest: DT.PointerToArrayOfCHAR;
  299. destOffset, stride: LONGINT );
  300. BEGIN
  301. IF DT.EnableMMX THEN
  302. TransferIDCTCopyMMX( source, ADDRESSOF( dest[destOffset] ), stride );
  303. ELSE
  304. TransferIDCTCopyGeneric( source, dest, destOffset, stride );
  305. END;
  306. END TransferIDCTCopy;
  307. (* Add macroblock to a block in the actual picture *)
  308. PROCEDURE TransferIDCTAddGeneric( source: LONGINT; dest: DT.PointerToArrayOfCHAR;
  309. destOffset, stride: LONGINT );
  310. VAR
  311. x, y, s, d, sum: LONGINT;
  312. BEGIN
  313. stride := stride - 8;
  314. s := source;
  315. d := ADDRESSOF( dest[destOffset] );
  316. IF DT.Debug THEN
  317. log.String( "TransferIDCTAdd: " )
  318. END;
  319. FOR y := 0 TO 7 DO
  320. FOR x := 0 TO 7 DO
  321. sum := ORD( SYSTEM.VAL(CHAR, SYSTEM.GET8( d ) ) ) + SYSTEM.GET16( s );
  322. IF sum > 255 THEN
  323. SYSTEM.PUT8( d, 255 )
  324. ELSIF sum < 0 THEN
  325. SYSTEM.PUT8( d, 0 )
  326. ELSE
  327. SYSTEM.PUT8( d, sum )
  328. END;
  329. s := s + SIZEOF( INTEGER);
  330. d := d + SIZEOF( CHAR );
  331. IF DT.Debug THEN
  332. log.Int( ORD( SYSTEM.VAL(CHAR, SYSTEM.GET8( d-1 ) ) ), 0 ); log.Char( ' ' )
  333. END;
  334. END;
  335. d := d + stride
  336. END;
  337. IF DT.Debug THEN
  338. log.Ln()
  339. END;
  340. END TransferIDCTAddGeneric;
  341. PROCEDURE TransferIDCTAddMMX( source, dest, stride: LONGINT );
  342. CODE{ SYSTEM.MMX, SYSTEM.PentiumPro }
  343. MOV EAX, [EBP+source] ; PARAMETER 1, *SOURCES32
  344. MOV EBX, [EBP+dest] ; PARAMETER 2, *DESTU8
  345. MOV EDI, [EBP+stride] ; PARAMETER 3, STRIDE
  346. MOV EDX, -8 ; loop counter
  347. PXOR MMX7, MMX7 ; SET MMX7 = 0
  348. loop:
  349. MOVQ MMX0, [EBX] ; eight bytes of destination into mm0
  350. MOVQ MMX1, MMX0 ; eight bytes of destination into mm1
  351. PUNPCKLBW MMX0, MMX7 ; unpack first 4 bytes from dest into mm0, no saturation
  352. PUNPCKHBW MMX1, MMX7 ; unpack next 4 bytes from dest into mm1, no saturation
  353. MOVQ MMX2, [EAX] ; four source words into mm2
  354. ; PACKSSDW MMX2, [EAX+8] ; pack mm2 with next two source double words into mm2
  355. MOVQ MMX3, [EAX+8]
  356. ; PACKSSDW MMX3, [EAX+24]
  357. PADDSW MMX0, MMX2 ; add source and destination
  358. PADDSW MMX1, MMX3 ; add source and destination
  359. PACKUSWB MMX0, MMX1 ; pack mm0 and mm1 into mm0
  360. MOVQ [EBX], MMX0 ; copy output to destination
  361. ADD EBX, EDI ; add +stride to dest ptr
  362. ADD EAX, 16
  363. INC EDX
  364. JNZ loop
  365. EMMS
  366. END TransferIDCTAddMMX;
  367. (* Copy a macroblock to the actual picture *)
  368. PROCEDURE TransferIDCTCopyGeneric( source: LONGINT; dest: DT.PointerToArrayOfCHAR; destOffset, stride: LONGINT );
  369. VAR
  370. x, y, s, d, val: LONGINT;
  371. BEGIN
  372. stride := stride - 8;
  373. s := source;
  374. d := ADDRESSOF( dest[destOffset] );
  375. IF DT.Debug THEN
  376. log.String( "Transferp: " )
  377. END;
  378. FOR y := 0 TO 7 DO
  379. FOR x:= 0 TO 7 DO
  380. val := LONG(SYSTEM.GET16( s ));
  381. IF val > 255 THEN SYSTEM.PUT8( d, 255 )
  382. ELSIF val < 0 THEN SYSTEM.PUT8( d, 0 )
  383. ELSE SYSTEM.PUT8( d, val )
  384. END;
  385. s := s + SIZEOF(INTEGER);
  386. d := d + SIZEOF( CHAR );
  387. IF DT.Debug THEN
  388. log.Int( ORD( SYSTEM.VAL(CHAR, SYSTEM.GET8( d -1) ) ), 0 ); log.Char( ' ' )
  389. END;
  390. END;
  391. d := d + stride
  392. END;
  393. IF DT.Debug THEN
  394. log.Ln()
  395. END;
  396. END TransferIDCTCopyGeneric;
  397. PROCEDURE TransferIDCTCopyMMX( source, dest, stride: LONGINT );
  398. CODE{ SYSTEM.MMX, SYSTEM.PentiumPro }
  399. MOV EAX, [EBP+source] ; PARAMETER 1, *SOURCES32
  400. MOV EBX, [EBP+dest] ; PARAMETER 2, *DESTU8
  401. MOV EDI, [EBP+stride] ; PARAMETER 3, STRIDE
  402. MOV EDX, -8
  403. loop:
  404. MOVQ MMX0, [EAX] ; eight bytes (four INTEGER) of source into mm0
  405. ; PACKSSDW MMX0, 8[EAX] ; Pack next 8 bytes (two LONGINT) together with mm0
  406. MOVQ MMX1, [EAX+8]
  407. ; PACKSSDW MMX1, 24[EAX]
  408. PACKUSWB MMX0, MMX1 ; Pack 4 INTEGER with another 4 INTEGER into mm0
  409. MOVQ [EBX], MMX0 ; Write mm0 to dest
  410. ADD EBX, EDI ; Add stride to dest
  411. ADD EAX, 16 ; next source
  412. INC EDX
  413. JNZ loop
  414. EMMS
  415. END TransferIDCTCopyMMX;
  416. (* Used to derive macroblock type and pattern for luminance *)
  417. PROCEDURE GetCBPY(VAR s: DT.VideoBuffer): LONGINT;
  418. VAR
  419. cbpy: LONGINT;
  420. code: LONGINT;
  421. BEGIN
  422. code := AVI.ShowBits( 6, s.data^, s.index );
  423. IF code < 2 THEN
  424. RETURN -1
  425. END;
  426. IF code >= 48 THEN
  427. AVI.SkipBits( 2, s.index );
  428. cbpy := 15
  429. ELSE
  430. AVI.SkipBits( CBPYTab[code].len, s.index );
  431. cbpy := CBPYTab[code].val
  432. END;
  433. IF ( ~( (mp4State.hdr.derivedMbType = 3 ) OR ( mp4State.hdr.derivedMbType = 4 ) ) ) THEN
  434. cbpy := 15 - cbpy
  435. END;
  436. RETURN cbpy;
  437. END GetCBPY;
  438. (* Used to derive macroblock type and pattern for chrominance *)
  439. PROCEDURE GetMCBPC(VAR s: DT.VideoBuffer): LONGINT;
  440. VAR
  441. code: LONGINT;
  442. BEGIN
  443. IF mp4State.hdr.predictionType = DT.IVOP THEN
  444. code := AVI.ShowBits( 9, s.data^, s.index );
  445. IF code = 1 THEN
  446. AVI.SkipBits( 9, s.index ); (* stuffing *)
  447. RETURN 0
  448. ELSIF code < 8 THEN
  449. RETURN -1
  450. END;
  451. code := code DIV 8;
  452. IF code >= 32 THEN
  453. AVI.SkipBits( 1, s.index );
  454. RETURN 3
  455. END;
  456. AVI.SkipBits( MCBPCTabIntra[code].len, s.index );
  457. RETURN MCBPCTabIntra[code].val
  458. ELSE
  459. code := AVI.ShowBits( 9, s.data^, s.index );
  460. IF code = 1 THEN
  461. AVI.SkipBits( 9, s.index ); (* stuffing *)
  462. RETURN 0
  463. ELSIF code = 0 THEN
  464. RETURN -1
  465. END;
  466. IF code >= 256 THEN
  467. AVI.SkipBits( 1, s.index );
  468. RETURN 0;
  469. END;
  470. AVI.SkipBits( MCBPCTabInter[code].len, s.index );
  471. RETURN MCBPCTabInter[code].val
  472. END;
  473. END GetMCBPC;
  474. END MacroBlock;
  475. TYPE MotionCompensation = OBJECT
  476. VAR
  477. MVTab0: ARRAY 14 OF DT.TabType;
  478. MVTab1: ARRAY 96 OF DT.TabType;
  479. MVTab2: ARRAY 124 OF DT.TabType;
  480. MV: ARRAY 2 OF ARRAY 6 OF ARRAY ( DT.DecMbr+1 ) OF ARRAY ( DT.DecMbc+2 ) OF LONGINT;
  481. RoundTab: ARRAY 16 OF LONGINT;
  482. mp4State: DT.MP4State;
  483. log: Streams.Writer;
  484. PROCEDURE &init*( state: DT.MP4State; logWriter: Streams.Writer);
  485. VAR
  486. i, j, index: LONGINT;
  487. BEGIN
  488. log := logWriter;
  489. mp4State := state;
  490. RoundTab[0] := 0; RoundTab[1] := 0; RoundTab[2] := 0; RoundTab[3] := 1; RoundTab[4] := 1; RoundTab[5] := 1;
  491. RoundTab[6] := 1; RoundTab[7] := 1; RoundTab[8] := 1; RoundTab[9] := 1; RoundTab[10] := 1; RoundTab[11] := 1;
  492. RoundTab[12] := 1; RoundTab[13] := 1; RoundTab[14] := 2; RoundTab[15] := 2;
  493. MVTab0[0].val := 3; MVTab0[0].len := 4;
  494. MVTab0[1].val := -3; MVTab0[1].len := 4;
  495. MVTab0[2].val := 2; MVTab0[2].len := 3;
  496. MVTab0[3].val := 2; MVTab0[3].len := 3;
  497. MVTab0[4].val := -2; MVTab0[4].len := 3;
  498. MVTab0[5].val := -2; MVTab0[5].len := 3;
  499. MVTab0[6].val := 1; MVTab0[6].len := 2;
  500. MVTab0[7].val := 1; MVTab0[7].len := 2;
  501. MVTab0[8].val := 1; MVTab0[8].len := 2;
  502. MVTab0[9].val := 1; MVTab0[9].len := 2;
  503. MVTab0[10].val := -1; MVTab0[10].len := 2;
  504. MVTab0[11].val := -1; MVTab0[11].len := 2;
  505. MVTab0[12].val := -1; MVTab0[12].len := 2;
  506. MVTab0[13].val := -1; MVTab0[13].len := 2;
  507. MVTab1[0].val := 12; MVTab1[0].len := 10;
  508. MVTab1[1].val := -12; MVTab1[1].len := 10;
  509. MVTab1[2].val := 11; MVTab1[2].len := 10;
  510. MVTab1[3].val := -11; MVTab1[3].len := 10;
  511. MVTab1[4].val := 10; MVTab1[4].len := 9;
  512. MVTab1[5].val := 10; MVTab1[5].len := 9;
  513. MVTab1[6].val := -10; MVTab1[6].len := 9;
  514. MVTab1[7].val := -10; MVTab1[7].len := 9;
  515. MVTab1[8].val := 9; MVTab1[8].len := 9;
  516. MVTab1[9].val := 9; MVTab1[9].len := 9;
  517. MVTab1[10].val := -9; MVTab1[10].len := 9;
  518. MVTab1[11].val := -9; MVTab1[11].len := 9;
  519. MVTab1[12].val := 8; MVTab1[12].len := 9;
  520. MVTab1[13].val := 8; MVTab1[13].len := 9;
  521. MVTab1[14].val := -8; MVTab1[14].len := 9;
  522. MVTab1[15].val := -8; MVTab1[15].len := 9;
  523. FOR i := 16 TO 23 DO MVTab1[i].val := 7; MVTab1[i].len := 7 END;
  524. FOR i := 24 TO 31 DO MVTab1[i].val := -7; MVTab1[i].len := 7 END;
  525. FOR i := 32 TO 39 DO MVTab1[i].val := 6; MVTab1[i].len := 7 END;
  526. FOR i := 40 TO 47 DO MVTab1[i].val := -6; MVTab1[i].len := 7 END;
  527. FOR i := 48 TO 56 DO MVTab1[i].val := 5; MVTab1[i].len := 7 END;
  528. FOR i := 56 TO 63 DO MVTab1[i].val := -5; MVTab1[i].len := 7 END;
  529. FOR i := 64 TO 79 DO MVTab1[i].val := 4; MVTab1[i].len := 6 END;
  530. FOR i := 80 TO 95 DO MVTab1[i].val := -4; MVTab1[i].len := 6 END;
  531. MVTab2[0].val := 32; MVTab2[0].len := 12;
  532. MVTab2[1].val := -32; MVTab2[1].len := 12;
  533. MVTab2[2].val := 31; MVTab2[2].len := 12;
  534. MVTab2[3].val := -31; MVTab2[3].len := 12;
  535. MVTab2[4].val := 30; MVTab2[4].len := 11;
  536. MVTab2[5].val := 30; MVTab2[5].len := 11;
  537. MVTab2[6].val := -30; MVTab2[6].len := 11;
  538. MVTab2[7].val := -30; MVTab2[7].len := 11;
  539. MVTab2[8].val := 29; MVTab2[8].len := 11;
  540. MVTab2[9].val := 29; MVTab2[9].len := 11;
  541. MVTab2[10].val := -29; MVTab2[10].len := 11;
  542. MVTab2[11].val := -29; MVTab2[11].len := 11;
  543. MVTab2[12].val := 28; MVTab2[12].len := 11;
  544. MVTab2[13].val := 28; MVTab2[13].len := 11;
  545. MVTab2[14].val := -28; MVTab2[14].len := 11;
  546. MVTab2[15].val := -28; MVTab2[15].len := 11;
  547. MVTab2[16].val := 27; MVTab2[16].len := 11;
  548. MVTab2[17].val := 27; MVTab2[17].len := 11;
  549. MVTab2[18].val := -27; MVTab2[18].len := 11;
  550. MVTab2[19].val := -27; MVTab2[19].len := 11;
  551. MVTab2[20].val := 26; MVTab2[20].len := 11;
  552. MVTab2[21].val := 26; MVTab2[21].len := 11;
  553. MVTab2[22].val := -26; MVTab2[22].len := 11;
  554. MVTab2[23].val := -26; MVTab2[23].len := 11;
  555. MVTab2[24].val := 25; MVTab2[24].len := 11;
  556. MVTab2[25].val := 25; MVTab2[25].len := 11;
  557. MVTab2[26].val := -25; MVTab2[26].len := 11;
  558. MVTab2[27].val := -25; MVTab2[27].len := 11;
  559. index := 28;
  560. FOR i:= 24 TO 13 BY -1 DO
  561. FOR j := 0 TO 3 DO
  562. MVTab2[index].val := i; MVTab2[index].len := 10;
  563. INC( index )
  564. END;
  565. FOR j := 0 TO 3 DO
  566. MVTab2[index].val := -i; MVTab2[index].len := 10;
  567. INC( index )
  568. END;
  569. END;
  570. END init;
  571. (* compute motion vector prediction *)
  572. PROCEDURE FindPMV ( block, comp: LONGINT ): LONGINT;
  573. VAR
  574. p1, p2, p3, xin1, xin2, xin3, yin1, yin2, yin3, vec1, vec2, vec3, x, y: LONGINT;
  575. BEGIN
  576. x := mp4State.hdr.mbXPos;
  577. y := mp4State.hdr.mbYPos;
  578. IF ( y = 0 ) & ( ( block = 0 ) OR ( block = 1 ) ) THEN
  579. IF (x = 0 ) & (block = 0 ) THEN
  580. RETURN 0;
  581. ELSIF ( block = 1 ) THEN
  582. RETURN MV[comp][0][y + 1][x + 1]
  583. ELSE (* block == 0 *)
  584. RETURN MV[comp][1][y + 1][x]
  585. END;
  586. ELSE
  587. (* considerate border (avoid increment inside each single array index) *)
  588. INC( x );
  589. INC( y );
  590. CASE block OF
  591. 0:
  592. vec1 := 1; yin1 := y; xin1 := x - 1;
  593. vec2 := 2; yin2 := y - 1; xin2 := x;
  594. vec3 := 2; yin3 := y - 1; xin3 := x + 1;
  595. | 1:
  596. vec1 := 0; yin1 := y; xin1 := x;
  597. vec2 := 3; yin2 := y - 1; xin2 := x;
  598. vec3 := 2; yin3 := y - 1; xin3 := x + 1;
  599. | 2:
  600. vec1 := 3; yin1 := y; xin1 := x - 1;
  601. vec2 := 0; yin2 := y; xin2 := x;
  602. vec3 := 1; yin3 := y; xin3 := x;
  603. ELSE
  604. vec1 := 2; yin1 := y; xin1 := x;
  605. vec2 := 0; yin2 := y; xin2 := x;
  606. vec3 := 1; yin3 := y; xin3 := x;
  607. END;
  608. p1 := MV[comp][vec1][yin1][xin1];
  609. p2 := MV[comp][vec2][yin2][xin2];
  610. p3 := MV[comp][vec3][yin3][xin3];
  611. RETURN Mmin( Mmax( p1, p2 ), Mmin( Mmax( p2, p3 ),Mmax( p1, p3 ) ) )
  612. END;
  613. END FindPMV;
  614. PROCEDURE Mmin( a, b: LONGINT ): LONGINT;
  615. BEGIN
  616. IF a < b THEN RETURN a ELSE RETURN b END;
  617. END Mmin;
  618. PROCEDURE Mmax( a, b: LONGINT ): LONGINT;
  619. BEGIN
  620. IF a > b THEN RETURN a ELSE RETURN b END;
  621. END Mmax;
  622. (* Set current motion vector *)
  623. PROCEDURE SetMV( blockNum: LONGINT; VAR s: DT.VideoBuffer ): BOOLEAN;
  624. VAR
  625. tempSet: SET;
  626. horMvData, verMvData, horMvRes, verMvRes, i: LONGINT;
  627. scaleFac, high, low, range: LONGINT;
  628. mvdx, mvdy, pmvx, pmvy, mvx, mvy: LONGINT;
  629. BEGIN
  630. tempSet := { mp4State.hdr.fCodeFor - 1 };
  631. scaleFac := SYSTEM.VAL( LONGINT, tempSet );
  632. high := ( 32 * scaleFac ) - 1;
  633. low := ( ( -32 ) * scaleFac );
  634. range := ( 64 * scaleFac );
  635. horMvData := GetMVData(s); (* mv data *)
  636. IF ( scaleFac = 1 ) OR ( horMvData = 0 ) THEN
  637. mvdx := horMvData
  638. ELSE
  639. horMvRes := AVI.GetBits( mp4State.hdr.fCodeFor - 1, s.data^, s.index ); (* mv residual *)
  640. mvdx := ( ( ABS( horMvData ) - 1 ) * scaleFac ) + horMvRes + 1;
  641. IF ( horMvData < 0 ) THEN
  642. mvdx := -mvdx
  643. END;
  644. END;
  645. verMvData := GetMVData(s);
  646. IF ( scaleFac = 1 ) OR ( verMvData = 0 ) THEN
  647. mvdy := verMvData
  648. ELSE
  649. verMvRes := AVI.GetBits( mp4State.hdr.fCodeFor - 1, s.data^, s.index );
  650. mvdy := ( ( ABS( verMvData) - 1 ) * scaleFac ) + verMvRes + 1;
  651. IF ( verMvData < 0 ) THEN
  652. mvdy := -mvdy
  653. END;
  654. END;
  655. IF blockNum = -1 THEN
  656. pmvx := FindPMV( 0, 0 );
  657. pmvy := FindPMV( 0, 1 );
  658. ELSE
  659. pmvx := FindPMV( blockNum, 0 );
  660. pmvy := FindPMV( blockNum, 1 );
  661. END;
  662. IF DT.Debug THEN
  663. log.String("Hor MotV Pred: "); log.Int( pmvx, 0 ); log.Ln();
  664. log.String("Ver MotV Pred: "); log.Int( pmvy, 0 ); log.Ln();
  665. log.String("MVD Hor: "); log.Int( mvdx, 0 ); log.Ln();
  666. log.String("MVD Ver: "); log.Int( mvdy, 0 ); log.Ln()
  667. END;
  668. mvx := pmvx + mvdx;
  669. IF mvx < low THEN
  670. mvx := mvx + range
  671. END;
  672. IF mvx > high THEN
  673. mvx := mvx - range
  674. END;
  675. mvy := pmvy + mvdy;
  676. IF mvy < low THEN
  677. mvy := mvy + range
  678. END;
  679. IF mvy > high THEN
  680. mvy := mvy - range
  681. END;
  682. (* put [mv_x, mv_y] in MV struct *)
  683. IF blockNum = -1 THEN
  684. FOR i := 0 TO 3 DO
  685. MV[0][i][mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mvx;
  686. MV[1][i][mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mvy
  687. END;
  688. ELSE
  689. MV[0][blockNum][mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mvx;
  690. MV[1][blockNum][mp4State.hdr.mbYPos + 1][mp4State.hdr.mbXPos + 1] := mvy
  691. END;
  692. IF DT.Debug THEN
  693. log.String("Hor MotV: "); log.Int( mvx, 0 ); log.Ln();
  694. log.String("Ver MotV: "); log.Int( mvy, 0 ); log.Ln()
  695. END;
  696. RETURN TRUE;
  697. END SetMV;
  698. PROCEDURE GetMVData(VAR s: DT.VideoBuffer ): LONGINT;
  699. VAR
  700. code: LONGINT;
  701. BEGIN
  702. IF AVI.GetBits( 1, s.data^, s.index ) > 0 THEN
  703. RETURN 0; (* hor_mv_data = 0 *)
  704. END;
  705. code := AVI.ShowBits( 12, s.data^, s.index );
  706. IF code >= 512 THEN
  707. code := ( code DIV 256 ) - 2;
  708. AVI.SkipBits( MVTab0[code].len, s.index );
  709. RETURN MVTab0[code].val;
  710. END;
  711. IF code >= 128 THEN
  712. code := ( code DIV 4 ) - 32;
  713. AVI.SkipBits( MVTab1[code].len, s.index );
  714. RETURN MVTab1[code].val;
  715. END;
  716. code := code - 4;
  717. ASSERT( code >= 0 );
  718. AVI.SkipBits( MVTab2[code].len, s.index);
  719. RETURN MVTab2[code].val;
  720. END GetMVData;
  721. (* Reset Intra motion vectors *)
  722. PROCEDURE ResetIntraMV( yPos, xPos: LONGINT );
  723. VAR
  724. j: LONGINT;
  725. BEGIN
  726. FOR j := 0 TO 3 DO
  727. MV[0][j][yPos][xPos] := 0;
  728. MV[1][j][yPos][xPos] := 0
  729. END;
  730. END ResetIntraMV;
  731. (* Reset single MV *)
  732. PROCEDURE ResetNotCodedMV( yPos, xPos: LONGINT );
  733. BEGIN
  734. MV[0][0][yPos][xPos] := 0;
  735. MV[0][1][yPos][xPos] := 0;
  736. MV[0][2][yPos][xPos] := 0;
  737. MV[0][3][yPos][xPos] := 0;
  738. MV[1][0][yPos][xPos] := 0;
  739. MV[1][1][yPos][xPos] := 0;
  740. MV[1][2][yPos][xPos] := 0;
  741. MV[1][3][yPos][xPos] := 0
  742. END ResetNotCodedMV;
  743. (* Reconstruct the current picture ( apply prediction ) *)
  744. PROCEDURE Reconstruct( bx, by, mode: LONGINT );
  745. VAR
  746. w, h, lx, dx, dy, xp, yp, comp, sum, x, y, px, py: LONGINT;
  747. src: DT.PointerToArrayOfCHAR;
  748. srcBaseOffset: ARRAY 3 OF LONGINT;
  749. BEGIN
  750. x := bx + 1;
  751. y := by + 1;
  752. lx := mp4State.codedPictureWidth;
  753. src := mp4State.frameFor;
  754. srcBaseOffset[0] := mp4State.frameForBaseOffset[0];
  755. srcBaseOffset[1] := mp4State.frameForBaseOffset[1];
  756. srcBaseOffset[2] := mp4State.frameForBaseOffset[2];
  757. w := 8;
  758. h := 8;
  759. (* Luma *)
  760. px := bx * 16;
  761. py := by * 16;
  762. IF mode = DT.Inter4V THEN
  763. FOR comp := 0 TO 3 DO
  764. dx := MV[0][comp][y][x];
  765. dy := MV[1][comp][y][x];
  766. xp := px + ( comp MOD 2 ) * 8;
  767. yp := py + ( ( comp MOD 4 ) DIV 2 ) * 8;
  768. IF DT.Debug THEN
  769. log.String( "reconComp: src[0] "); log.Int( lx, 0 ); log.Char( ' ' ); log.Int( w, 0 ); log.Char( ' ' ); log.Int( h, 0 );
  770. log.Char( ' ' ); log.Int( xp, 0 ); log.Char( ' ' ); log.Int( yp, 0 ); log.Char( ' ' ); log.Int( dx, 0 ); log.Char( ' ' ); log.Int( dy, 0 );
  771. log.Char( ' ' ); log.Int( 0, 0 ); log.Ln()
  772. END;
  773. ReconComp (src, srcBaseOffset[0], mp4State.frameRef, mp4State.frameRefBaseOffset[0], lx, w, h, xp, yp, dx, dy, 0);
  774. END;
  775. ELSE
  776. dx := MV[0][0][y][x];
  777. dy := MV[1][0][y][x];
  778. IF DT.Debug THEN
  779. log.String( "reconComp: src[0] "); log.Int( lx, 0 ); log.Char( ' ' ); log.Int( w, 0 ); log.Char( ' ' ); log.Int( h, 0 );
  780. log.Char( ' ' ); log.Int( px, 0 ); log.Char( ' ' ); log.Int( py, 0 ); log.Char( ' ' ); log.Int( dx, 0 ); log.Char( ' ' ); log.Int( dy, 0 );
  781. log.Char( ' ' ); log.Int( 0, 0 ); log.Ln()
  782. END;
  783. ReconComp (src, srcBaseOffset[0], mp4State.frameRef, mp4State.frameRefBaseOffset[0], lx, w*2, h*2, px, py, dx, dy, 0);
  784. END;
  785. (* Chr *)
  786. px := bx*8;
  787. py := by*8;
  788. IF mode = DT.Inter4V THEN
  789. sum := MV[0][0][y][x] + MV[0][1][y][x] + MV[0][2][y][x] + MV[0][3][y][x];
  790. IF sum = 0 THEN
  791. dx := 0
  792. ELSE
  793. IF sum >= 0 THEN
  794. dx := RoundTab[ABS( sum ) MOD 16] + (ABS( sum ) DIV 16) * 2
  795. ELSE
  796. dx := -(RoundTab[ ABS( sum ) MOD 16] + ( ABS( sum ) DIV 16 ) * 2)
  797. END;
  798. END;
  799. sum := MV[1][0][y][x] + MV[1][1][y][x] + MV[1][2][y][x] + MV[1][3][y][x];
  800. IF sum = 0 THEN
  801. dy := 0
  802. ELSE
  803. IF sum >= 0 THEN
  804. dy := RoundTab[ABS( sum ) MOD 16] + (ABS(sum) DIV 16) * 2
  805. ELSE
  806. dy := -(RoundTab[ABS( sum ) MOD 16] + (ABS(sum) DIV 16) * 2)
  807. END;
  808. END;
  809. ELSE
  810. dx := MV[0][0][y][x];
  811. dy := MV[1][0][y][x];
  812. (* chroma rounding *)
  813. IF dx MOD 4 = 0 THEN
  814. dx := dx DIV 2;
  815. ELSE
  816. dx := SYSTEM.VAL( LONGINT, SYSTEM.VAL( SET, dx DIV 2 ) + {0} )
  817. END;
  818. IF dy MOD 4 = 0 THEN
  819. dy := dy DIV 2;
  820. ELSE
  821. dy := SYSTEM.VAL( LONGINT, SYSTEM.VAL( SET, dy DIV 2 ) + {0} )
  822. END;
  823. END;
  824. lx := lx DIV 2;
  825. IF DT.Debug THEN
  826. log.String( "reconComp: src[1] "); log.Int( lx, 0 ); log.Char( ' ' ); log.Int( w, 0 ); log.Char( ' ' ); log.Int( h, 0 );
  827. log.Char( ' ' ); log.Int( px, 0 ); log.Char( ' ' ); log.Int( py, 0 ); log.Char( ' ' ); log.Int( dx, 0 ); log.Char( ' ' ); log.Int( dy, 0 );
  828. log.Char( ' ' ); log.Int( 1, 0 ); log.Ln()
  829. END;
  830. ReconComp ( src, srcBaseOffset[1], mp4State.frameRef, mp4State.frameRefBaseOffset[1], lx, w, h, px, py, dx, dy, 1 );
  831. IF DT.Debug THEN
  832. log.String( "reconComp: src[2] "); log.Int( lx, 0 ); log.Char( ' ' ); log.Int( w, 0 ); log.Char( ' ' ); log.Int( h, 0 );
  833. log.Char( ' ' ); log.Int( px, 0 ); log.Char( ' ' ); log.Int( py, 0 ); log.Char( ' ' ); log.Int( dx, 0 ); log.Char( ' ' ); log.Int( dy, 0 );
  834. log.Char( ' ' ); log.Int( 2, 0 ); log.Ln()
  835. END;
  836. ReconComp ( src, srcBaseOffset[2], mp4State.frameRef, mp4State.frameRefBaseOffset[2], lx, w, h, px, py, dx, dy, 2 );
  837. END Reconstruct;
  838. (* Copy block in old picture to actual picture *)
  839. PROCEDURE ReconComp( s: DT.PointerToArrayOfCHAR; sBaseOffset: LONGINT; d: DT.PointerToArrayOfCHAR;
  840. dBaseOffset, lx, w, h, x, y, dx, dy, chroma: LONGINT );
  841. VAR
  842. xint, xh, yint, yh: LONGINT;
  843. sIndex, dIndex: LONGINT;
  844. mcDriver, i: LONGINT;
  845. BEGIN
  846. xint := dx DIV 2;
  847. xh := dx MOD 2;
  848. yint := dy DIV 2;
  849. yh := dy MOD 2;
  850. IF w # 8 THEN i := 8;
  851. ELSE i := 0;
  852. END;
  853. (* origins *)
  854. sIndex := sBaseOffset + lx * (y + yint) + x + xint;
  855. dIndex := dBaseOffset + lx * y + x;
  856. (* mcDriver := ( ( w != 8 ) << 3 ) | ( mp4State.hdr.roundingType <<2 ) | ( yh << 1) | ( xh ); *)
  857. mcDriver := SYSTEM.VAL( LONGINT, SYSTEM.VAL( SET, i )+ SYSTEM.VAL( SET, mp4State.hdr.roundingType*4 )
  858. + SYSTEM.VAL( SET, yh*2 ) + SYSTEM.VAL( SET, xh ) );
  859. IF DT.Debug THEN
  860. log.String("mcDriver: "); log.Int( mcDriver, 0 ); log.Ln();
  861. END;
  862. CASE mcDriver OF
  863. (* block *)
  864. (* no round *)
  865. 0: CopyBlock(s, d, sIndex, dIndex, lx);
  866. | 1: CopyBlockHor(s, d, sIndex, dIndex, lx);
  867. | 2: CopyBlockVer(s, d, sIndex, dIndex, lx);
  868. | 3: CopyBlockHorVer(s, d, sIndex, dIndex, lx);
  869. | 4: CopyBlock(s, d, sIndex, dIndex, lx);
  870. (* round *)
  871. | 5: CopyBlockHorRound(s, d, sIndex, dIndex, lx);
  872. | 6: CopyBlockVerRound(s, d, sIndex, dIndex, lx);
  873. | 7: CopyBlockHorVerRound(s, d, sIndex, dIndex, lx);
  874. (* macroblock *)
  875. (* no round *)
  876. | 8: CopyMBlock(s, d, sIndex, dIndex, lx);
  877. | 9: CopyMBlockHor(s, d, sIndex, dIndex, lx);
  878. | 10: CopyMBlockVer(s, d, sIndex, dIndex, lx);
  879. | 11: CopyMBlockHorVer(s, d, sIndex, dIndex, lx);
  880. | 12: CopyMBlock(s, d, sIndex, dIndex, lx);
  881. (* round *)
  882. | 13: CopyMBlockHorRound(s, d, sIndex, dIndex, lx);
  883. | 14: CopyMBlockVerRound(s, d, sIndex, dIndex, lx);
  884. | 15: CopyMBlockHorVerRound(s, d, sIndex, dIndex, lx)
  885. END;
  886. END ReconComp;
  887. (* specialized basic motion compensation routines *)
  888. PROCEDURE CopyBlock( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  889. VAR
  890. dy,d,s : LONGINT;
  891. BEGIN
  892. s := ADDRESSOF( src[sIndex] );
  893. d := ADDRESSOF( dst[dIndex] );
  894. FOR dy := 0 TO 7 DO
  895. SYSTEM.MOVE( s, d, 8 );
  896. s := s + stride;
  897. d := d + stride;
  898. END;
  899. END CopyBlock;
  900. PROCEDURE CopyBlockHor( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  901. VAR
  902. dx, dy, d, s, temp: LONGINT;
  903. BEGIN
  904. s := ADDRESSOF( src[sIndex] );
  905. d := ADDRESSOF( dst[dIndex] );
  906. FOR dy := 0 TO 7 DO
  907. FOR dx := 0 TO 7 DO
  908. (* Dst[dx] = (Src[dx] + Src[dx+1]+1) >> 1; hor interpolation with rounding *)
  909. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  910. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1 ) ) );
  911. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 2 );
  912. END;
  913. s := s + stride;
  914. d := d + stride
  915. END;
  916. END CopyBlockHor;
  917. PROCEDURE CopyBlockVer( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  918. VAR
  919. dy, dx, d, s, temp: LONGINT;
  920. BEGIN
  921. s := ADDRESSOF( src[sIndex] );
  922. d := ADDRESSOF( dst[dIndex] );
  923. FOR dy := 0 TO 7 DO
  924. FOR dx := 0 TO 7 DO
  925. (* Dst[dx] = (Src[dx] + Src[dx+Stride] +1) >> 1; // ver interpolation with rounding *)
  926. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  927. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) );
  928. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 2 )
  929. END;
  930. s := s + stride;
  931. d := d + stride
  932. END;
  933. END CopyBlockVer;
  934. PROCEDURE CopyBlockHorVer( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  935. VAR
  936. dy, dx, d, s, temp: LONGINT;
  937. BEGIN
  938. s := ADDRESSOF( src[sIndex] );
  939. d := ADDRESSOF( dst[dIndex] );
  940. FOR dy := 0 TO 7 DO
  941. FOR dx := 0 TO 7 DO
  942. (* Dst[dx] = (Src[dx] + Src[dx+1] + Src[dx+Stride] + Src[dx+Stride+1] +2) >> 2; // horver interpolation with rounding *)
  943. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  944. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1) ) );
  945. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) ) +
  946. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride + 1 ) ) );
  947. SYSTEM.PUT8( d + dx, ( temp + 2 ) DIV 4 )
  948. END;
  949. s := s + stride;
  950. d := d + stride;
  951. END;
  952. END CopyBlockHorVer;
  953. PROCEDURE CopyBlockHorRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  954. VAR
  955. dy, dx, d, s, temp: LONGINT;
  956. BEGIN
  957. s := ADDRESSOF( src[sIndex] );
  958. d := ADDRESSOF( dst[dIndex] );
  959. FOR dy := 0 TO 7 DO
  960. FOR dx := 0 TO 7 DO
  961. (* Dst[dx] = (Src[dx] + Src[dx+1]) >> 1; // hor interpolation with rounding *)
  962. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  963. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1 ) ) );
  964. SYSTEM.PUT8( d + dx, temp DIV 2 )
  965. END;
  966. s := s + stride;
  967. d := d + stride
  968. END;
  969. END CopyBlockHorRound;
  970. PROCEDURE CopyBlockVerRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  971. VAR
  972. dy, dx, d, s, temp: LONGINT;
  973. BEGIN
  974. s := ADDRESSOF( src[sIndex] );
  975. d := ADDRESSOF( dst[dIndex] );
  976. FOR dy := 0 TO 7 DO
  977. FOR dx := 0 TO 7 DO
  978. (* Dst[dx] = (Src[dx] + Src[dx+Stride]) >> 1; // ver interpolation with rounding *)
  979. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  980. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) );
  981. SYSTEM.PUT8( d+ dx, temp DIV 2 );
  982. END;
  983. s := s + stride;
  984. d := d + stride
  985. END;
  986. END CopyBlockVerRound;
  987. PROCEDURE CopyBlockHorVerRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  988. VAR
  989. dy, dx, d, s, temp: LONGINT;
  990. BEGIN
  991. s := ADDRESSOF( src[sIndex] );
  992. d := ADDRESSOF( dst[dIndex] );
  993. FOR dy := 0 TO 7 DO
  994. FOR dx := 0 TO 7 DO
  995. (* Dst[dx] = (Src[dx] + Src[dx+1] + Src[dx+Stride] + Src[dx+Stride+1] +1) >> 2; // horver interpolation with rounding *)
  996. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1 ) ) ) ;
  997. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) ) +
  998. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride + 1 ) ) );
  999. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 4 );
  1000. END;
  1001. s := s + stride;
  1002. d := d + stride
  1003. END;
  1004. END CopyBlockHorVerRound;
  1005. PROCEDURE CopyMBlock( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  1006. VAR
  1007. dy, s, d: LONGINT;
  1008. BEGIN
  1009. s := ADDRESSOF( src[sIndex] );
  1010. d := ADDRESSOF( dst[dIndex] );
  1011. FOR dy := 0 TO 15 DO
  1012. SYSTEM.MOVE( s, d, 16 );
  1013. s := s + stride;
  1014. d := d + stride;
  1015. END;
  1016. END CopyMBlock;
  1017. PROCEDURE CopyMBlockHor(src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT);
  1018. VAR
  1019. dy, dx, s, d, temp: LONGINT;
  1020. BEGIN
  1021. s := ADDRESSOF( src[sIndex] );
  1022. d := ADDRESSOF( dst[dIndex] );
  1023. FOR dy := 0 TO 15 DO
  1024. FOR dx := 0 TO 15 DO
  1025. (* Dst[dx] = (Src[dx] + Src[dx+1]+1) >> 1; // hor interpolation with rounding *)
  1026. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) );
  1027. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1) ) );
  1028. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 2 )
  1029. END;
  1030. s := s + stride;
  1031. d := d + stride
  1032. END;
  1033. END CopyMBlockHor;
  1034. PROCEDURE CopyMBlockVer(src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT);
  1035. VAR
  1036. dy, dx, s, d, temp: LONGINT;
  1037. BEGIN
  1038. s := ADDRESSOF( src[sIndex] );
  1039. d := ADDRESSOF( dst[dIndex] );
  1040. FOR dy := 0 TO 15 DO
  1041. FOR dx := 0 TO 15 DO
  1042. (* Dst[dx] = (Src[dx] + Src[dx+Stride] +1) >> 1; // ver interpolation with rounding *)
  1043. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) );
  1044. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) );
  1045. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 2 );
  1046. END;
  1047. s := s + stride;
  1048. d := d + stride;
  1049. END;
  1050. END CopyMBlockVer;
  1051. PROCEDURE CopyMBlockHorVer(src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT);
  1052. VAR
  1053. dy, dx, s, d, temp: LONGINT;
  1054. BEGIN
  1055. s := ADDRESSOF( src[sIndex] );
  1056. d := ADDRESSOF( dst[dIndex] );
  1057. FOR dy := 0 TO 15 DO
  1058. FOR dx := 0 TO 15 DO
  1059. (* Dst[dx] = (Src[dx] + Src[dx+1] + Src[dx+Stride] + Src[dx+Stride+1] +2) >> 2; // horver interpolation with rounding *)
  1060. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx +1 ) ) );
  1061. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) ) +
  1062. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride + 1 ) ) );
  1063. SYSTEM.PUT8( d + dx, ( temp + 2 ) DIV 4 );
  1064. END;
  1065. s := s + stride;
  1066. d := d + stride;
  1067. END;
  1068. END CopyMBlockHorVer;
  1069. PROCEDURE CopyMBlockHorRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  1070. VAR
  1071. dy, dx, d, s, temp: LONGINT;
  1072. BEGIN
  1073. s := ADDRESSOF( src[sIndex] );
  1074. d := ADDRESSOF( dst[dIndex] );
  1075. FOR dy := 0 TO 15 DO
  1076. FOR dx := 0 TO 15 DO
  1077. (* Dst[dx] = (Src[dx] + Src[dx+1]) >> 1; // hor interpolation with rounding *)
  1078. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  1079. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1 ) ) );
  1080. SYSTEM.PUT8( d + dx, temp DIV 2 )
  1081. END;
  1082. s := s + stride;
  1083. d := d + stride
  1084. END;
  1085. END CopyMBlockHorRound;
  1086. PROCEDURE CopyMBlockVerRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  1087. VAR
  1088. dy, dx, d, s, temp: LONGINT;
  1089. BEGIN
  1090. s := ADDRESSOF( src[sIndex] );
  1091. d := ADDRESSOF( dst[dIndex] );
  1092. FOR dy := 0 TO 15 DO
  1093. FOR dx := 0 TO 15 DO
  1094. (* Dst[dx] = (Src[dx] + Src[dx+Stride]) >> 1; // ver interpolation with rounding *)
  1095. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) );
  1096. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) );
  1097. SYSTEM.PUT8( d+ dx, temp DIV 2 );
  1098. END;
  1099. s := s + stride;
  1100. d := d + stride
  1101. END;
  1102. END CopyMBlockVerRound;
  1103. PROCEDURE CopyMBlockHorVerRound( src, dst: DT.PointerToArrayOfCHAR; sIndex, dIndex, stride: LONGINT );
  1104. VAR
  1105. dy, dx, d, s, temp: LONGINT;
  1106. BEGIN
  1107. s := ADDRESSOF( src[0] ) + sIndex;
  1108. d := ADDRESSOF( dst[0] ) + dIndex;
  1109. FOR dy := 0 TO 15 DO
  1110. FOR dx := 0 TO 15 DO
  1111. (* Dst[dx] = (Src[dx] + Src[dx+1] + Src[dx+Stride] + Src[dx+Stride+1] +1) >> 2; // horver interpolation with rounding *)
  1112. temp := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx ) ) ) +
  1113. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + 1) ) );
  1114. temp := temp + ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride ) ) ) +
  1115. ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( s + dx + stride + 1 ) ) );
  1116. SYSTEM.PUT8( d + dx, ( temp + 1 ) DIV 4 );
  1117. END;
  1118. s := s + stride;
  1119. d := d + stride
  1120. END;
  1121. END CopyMBlockHorVerRound;
  1122. END MotionCompensation;
  1123. TYPE MMXConsts = POINTER TO MMXConstsDesc;
  1124. TYPE MMXConstsDesc = RECORD
  1125. mmwMultY, mmwMultUG, mmwMultUB, mmwMultVR, mmwMultVG: HUGEINT;
  1126. (* various masks and other constants *)
  1127. mmb10, mmw0080, mmw00ff, mmwCutRed, mmwCutGreen, mmwCutBlue: HUGEINT;
  1128. mask5, mask6, maskBlue: HUGEINT;
  1129. END;
  1130. (* Convert colorspace *)
  1131. TYPE ColorSpace = OBJECT
  1132. VAR
  1133. mmxConsts: MMXConsts;
  1134. (* initialize rgb lookup tables *)
  1135. PROCEDURE &Init*;
  1136. BEGIN
  1137. NEW( mmxConsts );
  1138. mmxConsts.mmwMultY := 2568256825682568H;
  1139. mmxConsts.mmwMultUG := 0F36EF36EF36EF36EH;
  1140. mmxConsts.mmwMultUB := 40CF40CF40CF40CFH;
  1141. mmxConsts.mmwMultVR := 3343334333433343H;
  1142. mmxConsts.mmwMultVG := 0E5E2E5E2E5E2E5E2H;
  1143. (* various masks and other constants *)
  1144. mmxConsts.mmb10 := 1010101010101010H;
  1145. mmxConsts.mmw0080 := 0080008000800080H;
  1146. mmxConsts.mmw00ff := 00FF00FF00FF00FFH;
  1147. mmxConsts.mmwCutRed := 7C007C007C007C00H;
  1148. mmxConsts.mmwCutGreen := 03E003E003E003E0H;
  1149. mmxConsts.mmwCutBlue := 001F001F001F001FH;
  1150. mmxConsts.mask5 := 0F8F8F8F8F8F8F8F8H;
  1151. mmxConsts.mask6 := 0FCFCFCFCFCFCFCFCH;
  1152. mmxConsts.maskBlue := 1F1F1F1F1F1F1F1FH;
  1153. END Init;
  1154. (* Convert picture from one colorspace to an another *)
  1155. PROCEDURE Convert(src: DT.PointerToArrayOfCHAR; srcYBaseOffset: LONGINT; yStride: LONGINT;
  1156. srcUBaseOffset, srcVBaseOffset,uvStride: LONGINT; img: Raster.Image; width, height, dstStride: LONGINT );
  1157. BEGIN
  1158. IF img.fmt.code = Raster.BGR888.code THEN
  1159. ConvertYUVToRGB888( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1160. dstStride );
  1161. ELSIF img.fmt.code = Raster.BGR565.code THEN
  1162. IF DT.EnableMMX THEN
  1163. ConvertYUVToRGB565MMX( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1164. dstStride );
  1165. ELSE
  1166. ConvertYUVToRGB565( src, srcYBaseOffset, yStride, srcUBaseOffset, srcVBaseOffset, uvStride, img, width, height,
  1167. dstStride );
  1168. END;
  1169. END;
  1170. END Convert;
  1171. (* Convert picture from YUV -> RGB 565, mmx version *)
  1172. PROCEDURE ConvertYUVToRGB565MMX(puc: DT.PointerToArrayOfCHAR; pucYBaseOffset: LONGINT; strideY: LONGINT;
  1173. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT; pucOut: Raster.Image;
  1174. widthY, heightY, strideOut: LONGINT );
  1175. VAR
  1176. y, horizCount: LONGINT;
  1177. pusOut: LONGINT;
  1178. BEGIN
  1179. strideOut := widthY*2;
  1180. IF heightY < 0 THEN
  1181. (* we are flipping our output upside-down *)
  1182. heightY := -heightY;
  1183. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1184. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1185. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1186. strideY := -strideY;
  1187. strideUV := -strideUV;
  1188. END;
  1189. pusOut := pucOut.adr;
  1190. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1191. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1192. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1193. horizCount := -(widthY DIV 8);
  1194. FOR y := 0 TO heightY-1 DO
  1195. ScanLine565MMX(horizCount, pucVBaseOffset, pucUBaseOffset, pucYBaseOffset, pusOut,
  1196. ADDRESSOF( mmxConsts.mmwMultY ) );
  1197. pucYBaseOffset := pucYBaseOffset + strideY;
  1198. IF ( y MOD 2 ) > 0 THEN
  1199. pucUBaseOffset := pucUBaseOffset + strideUV;
  1200. pucVBaseOffset := pucVBaseOffset + strideUV
  1201. END;
  1202. pusOut := pusOut + strideOut;
  1203. END;
  1204. END ConvertYUVToRGB565MMX;
  1205. PROCEDURE ScanLine565MMX( horizCount, pucV, pucU, pucY, pucOut: LONGINT; mmxConsts: LONGINT);
  1206. CODE { SYSTEM.MMX, SYSTEM.PentiumPro }
  1207. PUSH ECX
  1208. MOV EAX, [EBP+pucOut]
  1209. MOV EBX, [EBP+pucY]
  1210. MOV ECX, [EBP+pucU]
  1211. MOV EDX, [EBP+pucV]
  1212. MOV EDI, [EBP+horizCount]
  1213. MOV ESI, [EBP+mmxConsts]
  1214. horizLoop:
  1215. ; load data
  1216. MOVD MMX2, [ECX] ; mm2 = ________u3u2u1u0
  1217. MOVD MMX3, [EDX] ; mm3 = ________v3v2v1v0
  1218. MOVQ MMX0, [EBX] ; mm0 = y7y6y5y4y3y2y1y0
  1219. PXOR MMX7, MMX7 ; zero mm7
  1220. ; convert chroma part
  1221. PUNPCKLBW MMX2, MMX7 ; MMX2 = __U3__U2__U1__U0
  1222. PUNPCKLBW MMX3, MMX7 ; MMX3 = __V3__V2__V1__V0
  1223. ; PSUBW MMX2, mmw0080 ; MMX2 -= 128
  1224. PSUBW MMX2, [ESI+48] ; MMX2 -= 128
  1225. ; PSUBW MMX3, mmw0080 ; MMX3 -= 128
  1226. PSUBW MMX3, [ESI+48] ; MMX3 -= 128
  1227. PSLLW MMX2, 3 ; MMX2 *= 8
  1228. PSLLW MMX3, 3 ; MMX3 *= 8
  1229. MOVQ MMX4, MMX2 ; MMX4 = MMX2 = U
  1230. MOVQ MMX5, MMX3 ; MMX5 = MMX3 = V
  1231. ; PMULHW MMX2, mmwMultUG ; MMX2 *= U GREEN COEFF
  1232. ; PMULHW MMX3, mmwMultVG ; MMX3 *= V GREEN COEFF
  1233. ; PMULHW MMX4, mmwMultUB ; MMX4 = BLUE CHROMA
  1234. ; PMULHW MMX5, mmwMultVR ; MMX5 = RED CHROMA
  1235. PMULHW MMX2, [ESI+8] ; MMX2 *= U GREEN COEFF
  1236. PMULHW MMX3, [ESI+32] ; MMX3 *= V GREEN COEFF
  1237. PMULHW MMX4, [ESI+16] ; MMX4 = BLUE CHROMA
  1238. PMULHW MMX5, [ESI+24] ; MMX5 = RED CHROMA
  1239. PADDSW MMX2, MMX3 ; MMX2 = GREEN CHROMA
  1240. ; convert luma part
  1241. ; PSUBUSB MMX0, mmb10 ; MMX0 -= 16
  1242. ; MOVQ MMX1, mmw00ff
  1243. PSUBUSB MMX0, [ESI+40] ; MMX0 -= 16
  1244. MOVQ MMX6, [ESI+56]
  1245. MOVQ MMX1, MMX0
  1246. PSRLW MMX0, 8 ; MMX0 = __Y7__Y5__Y3__Y1 LUMA ODD
  1247. PAND MMX1, MMX6 ; MMX1 = __Y6__Y4__Y2__Y0 LUMA EVEN
  1248. PSLLW MMX0, 3 ; MMX0 *= 8
  1249. PSLLW MMX1, 3 ; MMX1 *= 8
  1250. ; PMULHW MMX0, mmwMultY ; MMX0 LUMA ODD *= LUMA COEFF
  1251. ; PMULHW MMX1, mmwMultY ; MMX1 LUMA EVEN *= LUMA COEFF
  1252. PMULHW MMX0, [ESI] ; MMX0 LUMA ODD *= LUMA COEFF
  1253. PMULHW MMX1, [ESI] ; MMX1 LUMA EVEN *= LUMA COEFF
  1254. ; complete the matrix calc with the additions
  1255. MOVQ MMX3, MMX4 ; COPY BLUE CHROMA
  1256. MOVQ MMX6, MMX5 ; COPY RED CHROMA
  1257. MOVQ MMX7, MMX2 ; COPY GREEN CHROMA
  1258. PADDSW MMX3, MMX0 ; MMX3 = LUMA ODD + BLUE CHROMA
  1259. PADDSW MMX4, MMX1 ; MMX4 = LUMA EVEN + BLUE CHROMA
  1260. PADDSW MMX6, MMX0 ; MMX6 = LUMA ODD + RED CHROMA
  1261. PADDSW MMX5, MMX1 ; MMX5 = LUMA EVEN + RED CHROMA
  1262. PADDSW MMX7, MMX0 ; MMX7 = LUMA ODD + GREEN CHROMA
  1263. PADDSW MMX2, MMX1 ; MMX2 = LUMA EVEN + GREEN CHROMA
  1264. ; clipping
  1265. PACKUSWB MMX3, MMX3
  1266. PACKUSWB MMX4, MMX4
  1267. PACKUSWB MMX6, MMX6
  1268. PACKUSWB MMX5, MMX5
  1269. PACKUSWB MMX7, MMX7
  1270. PACKUSWB MMX2, MMX2
  1271. ; interleave odd and even parts
  1272. PUNPCKLBW MMX4, MMX3 ; MMX4 = B7B6B5B4B3B2B1B0 BLUE
  1273. PUNPCKLBW MMX5, MMX6 ; MMX5 = R7R6R5R4R3R2R1R0 RED
  1274. PUNPCKLBW MMX2, MMX7 ; MMX2 = G7G6G5G4G3G2G1G0 GREEN
  1275. ; mask not needed bits (using 555)
  1276. ; PAND MMX4, mask5
  1277. ; PAND MMX5, mask5
  1278. ; PAND MMX2, mask5
  1279. PAND MMX4, [ESI+88]
  1280. PAND MMX5, [ESI+88]
  1281. PAND MMX2, [ESI+96]
  1282. ; mix colors and write
  1283. PSRLW MMX4, 3 ; MMX4 = RED SHIFTED
  1284. ; PAND MMX4, maskBlue ; MASK THE BLUE AGAIN
  1285. PAND MMX4, [ESI+104] ; MASK THE BLUE AGAIN
  1286. PXOR MMX7, MMX7 ; ZERO MMX7
  1287. MOVQ MMX1, MMX5 ; MMX1 = COPY BLUE
  1288. MOVQ MMX3, MMX4 ; MMX3 = COPY RED
  1289. MOVQ MMX6, MMX2 ; MMX6 = COPY GREEN
  1290. PUNPCKHBW MMX1, MMX7
  1291. PUNPCKHBW MMX3, MMX7
  1292. PUNPCKHBW MMX6, MMX7
  1293. PSLLW MMX6, 3 ; SHIFT GREEN
  1294. PSLLW MMX1, 8 ; SHIFT BLUE
  1295. POR MMX6, MMX3
  1296. POR MMX6, MMX1
  1297. MOVQ [EAX+8], MMX6
  1298. PUNPCKLBW MMX2, MMX7 ; MMX2 = __G3__G2__G1__G0 ALREADY MASKED
  1299. PUNPCKLBW MMX4, MMX7
  1300. PUNPCKLBW MMX5, MMX7
  1301. PSLLW MMX2, 3 ; SHIFT GREEN
  1302. PSLLW MMX5, 8 ; SHIFT BLUE
  1303. POR MMX2, MMX4
  1304. POR MMX2, MMX5
  1305. MOVQ [EAX], MMX2
  1306. ADD EBX, 8 ; PUCY += 8;
  1307. ADD ECX, 4 ; PUCU += 4;
  1308. ADD EDX, 4 ; PUCV += 4;
  1309. ADD EAX, 16 ; PUCOUT += 16 // WROTE 16 BYTES
  1310. INC EDI
  1311. JNE horizLoop
  1312. EMMS
  1313. POP ECX
  1314. END ScanLine565MMX;
  1315. (* Convert picture from YUV -> RGB 565 *)
  1316. PROCEDURE ConvertYUVToRGB565(puc: DT.PointerToArrayOfCHAR; pucYBaseOffset: LONGINT; strideY: LONGINT;
  1317. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT; pucOut: Raster.Image;
  1318. widthY, heightY, strideOut: LONGINT );
  1319. VAR
  1320. xCount, yCount, strideDiff: LONGINT;
  1321. pusOut: LONGINT;
  1322. r, g, b: LONGINT;
  1323. y, u, v: LONGINT;
  1324. BEGIN
  1325. strideDiff := (strideOut - widthY)*SIZEOF(INTEGER); (* expressed in bytes *)
  1326. IF heightY < 0 THEN
  1327. (* we are flipping our output upside-down *)
  1328. heightY := -heightY;
  1329. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1330. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1331. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1332. strideY := -strideY;
  1333. strideUV := -strideUV;
  1334. END;
  1335. pusOut := pucOut.adr;
  1336. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1337. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1338. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1339. FOR yCount := 0 TO heightY - 1 DO
  1340. FOR xCount := 0 TO widthY - 1 DO
  1341. y := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucYBaseOffset + xCount ) ) ) - 16;
  1342. u := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucUBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1343. v := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucVBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1344. r := ( 2568H*y + 3343H*u ) DIV 2000H;
  1345. g := ( 2568H*y - 0C92H*v - 1A1EH*u ) DIV 2000H;
  1346. b := ( 2568H*y + 40CFH*v ) DIV 2000H;
  1347. IF r > 255 THEN r := 255; ELSIF r < 0 THEN r := 0 END;
  1348. IF g > 255 THEN g := 255; ELSIF g < 0 THEN g := 0 END;
  1349. IF b > 255 THEN b := 255; ELSIF b < 0 THEN b := 0 END;
  1350. (* SYSTEM.PUT16( pusOut, SYSTEM.VAL( INTEGER,
  1351. ( SYSTEM.VAL( SET, LSH( b, 8 ) ) * SYSTEM.VAL( SET, 0F800H ) ) +
  1352. ( SYSTEM.VAL( SET, LSH( g, 3 ) ) * SYSTEM.VAL( SET, 07E0H ) ) +
  1353. ( SYSTEM.VAL( SET, LSH( r, -3 ) ) * SYSTEM.VAL( SET, 001FH ) ) ) );
  1354. *)
  1355. SYSTEM.PUT16( pusOut, SYSTEM.VAL( INTEGER, SYSTEM.VAL( SET, r DIV 8 ) + SYSTEM.VAL( SET, ( g DIV 4 ) * 32 ) +
  1356. SYSTEM.VAL( SET, (b DIV 8 ) * 2048 ) ) );
  1357. pusOut := pusOut + SIZEOF( INTEGER );
  1358. END;
  1359. pucYBaseOffset := pucYBaseOffset + strideY;
  1360. IF yCount MOD 2 > 0 THEN
  1361. pucUBaseOffset := pucUBaseOffset + strideUV;
  1362. pucVBaseOffset := pucVBaseOffset + strideUV
  1363. END;
  1364. pusOut := pusOut + strideDiff;
  1365. END;
  1366. END ConvertYUVToRGB565;
  1367. (* Convert YUV -> RGB 888 *)
  1368. PROCEDURE ConvertYUVToRGB888(puc: DT.PointerToArrayOfCHAR; pucYBaseOffset: LONGINT; strideY: LONGINT;
  1369. pucUBaseOffset, pucVBaseOffset, strideUV: LONGINT; pucOut: Raster.Image;
  1370. widthY, heightY, strideOut: LONGINT );
  1371. VAR
  1372. xCount, yCount, strideDiff: LONGINT;
  1373. pusOut: LONGINT;
  1374. r, g, b: LONGINT;
  1375. y, u, v: LONGINT;
  1376. BEGIN
  1377. strideDiff := (strideOut - widthY)*3; (* expressed in bytes *)
  1378. IF heightY < 0 THEN
  1379. (* we are flipping our output upside-down *)
  1380. heightY := -heightY;
  1381. pucYBaseOffset := pucYBaseOffset + ( heightY - 1 ) * strideY ;
  1382. pucUBaseOffset := pucUBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1383. pucVBaseOffset := pucVBaseOffset + ( heightY DIV 2 - 1 ) * strideUV;
  1384. strideY := -strideY;
  1385. strideUV := -strideUV;
  1386. END;
  1387. pusOut := pucOut.adr;
  1388. pucYBaseOffset := ADDRESSOF( puc[0] )+ pucYBaseOffset;
  1389. pucUBaseOffset := ADDRESSOF ( puc[0] ) + pucUBaseOffset;
  1390. pucVBaseOffset := ADDRESSOF( puc[0] ) + pucVBaseOffset;
  1391. FOR yCount := 0 TO heightY - 1 DO
  1392. FOR xCount := 0 TO widthY - 1 DO
  1393. y := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucYBaseOffset + xCount ) ) ) - 16;
  1394. u := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucUBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1395. v := ORD( SYSTEM.VAL( CHAR, SYSTEM.GET8( pucVBaseOffset + ( xCount DIV 2 ) ) ) ) - 128;
  1396. r := ( 2568H*y + 3343H*u ) DIV 2000H;
  1397. g := ( 2568H*y - 0C92H*v - 1A1EH*u ) DIV 2000H;
  1398. b := ( 2568H*y + 40CFH*v ) DIV 2000H;
  1399. IF r > 255 THEN r := 255; ELSIF r < 0 THEN r := 0 END;
  1400. IF g > 255 THEN g := 255; ELSIF g < 0 THEN g := 0 END;
  1401. IF b > 255 THEN b := 255; ELSIF b < 0 THEN b := 0 END;
  1402. SYSTEM.PUT8( pusOut, r );
  1403. INC( pusOut );
  1404. SYSTEM.PUT8( pusOut, g );
  1405. INC( pusOut );
  1406. SYSTEM.PUT8( pusOut, b );
  1407. INC( pusOut );
  1408. END;
  1409. pucYBaseOffset := pucYBaseOffset + strideY;
  1410. IF yCount MOD 2 > 0 THEN
  1411. pucUBaseOffset := pucUBaseOffset + strideUV;
  1412. pucVBaseOffset := pucVBaseOffset + strideUV;
  1413. END;
  1414. pusOut := pusOut + strideDiff;
  1415. END;
  1416. END ConvertYUVToRGB888;
  1417. END ColorSpace;
  1418. (* The OpenDivXDecoder *)
  1419. TYPE DivXDecoder* = OBJECT(Codecs.VideoDecoder)
  1420. VAR
  1421. s: Streams.Reader;
  1422. mp4State: DT.MP4State;
  1423. mp4StateBefore: DT.MP4State;
  1424. mp4Buffers: DT.MP4Buffers;
  1425. macroBlock: MacroBlock;
  1426. col: ColorSpace;
  1427. opt: DT.DecoderOptions; (* Between 0 and 10 *)
  1428. stride: LONGINT;
  1429. util: DT.MyUtils;
  1430. log: Files.Writer;
  1431. debugFile: Files.File;
  1432. img: Raster.Image;
  1433. frameCounter: LONGINT; (* The absolut position in the file *)
  1434. buffer: DT.VideoBuffer;
  1435. videoWidth: LONGINT;
  1436. videoHeight: LONGINT;
  1437. frameRate* : LONGINT;
  1438. init: BOOLEAN;
  1439. firstFrame: BOOLEAN;
  1440. hasMoreBytes : BOOLEAN;
  1441. (* Read Headers of the next frame and decode it *)
  1442. PROCEDURE Next*;
  1443. VAR
  1444. ret: BOOLEAN;
  1445. done: BOOLEAN;
  1446. temp: LONGINT;
  1447. ofs, size: LONGINT;
  1448. len: LONGINT;
  1449. i: LONGINT;
  1450. tmp: LONGINT;
  1451. tmpPtr: DT.PointerToArrayOfCHAR;
  1452. BEGIN
  1453. IF firstFrame = FALSE THEN
  1454. IF DT.Debug THEN
  1455. log.String( "Decoding picture number: "); log.Int( mp4State.hdr.picNum, 0 ); log.Ln()
  1456. END;
  1457. IF buffer.data = NIL THEN
  1458. NEW(buffer.data, 10240);
  1459. buffer.size := 10240;
  1460. END;
  1461. buffer.index := 0;
  1462. s.Bytes(buffer.data^, ofs, buffer.size, len);
  1463. IF len > buffer.size THEN
  1464. buffer.size := len;
  1465. NEW(buffer.data, buffer.size);
  1466. s.Bytes(buffer.data^, ofs, buffer.size, len);
  1467. ELSE
  1468. buffer.size := len;
  1469. END;
  1470. IF s.res = Streams.EOF THEN
  1471. hasMoreBytes := FALSE;
  1472. RETURN;
  1473. END;
  1474. REPEAT
  1475. NextStartCode();
  1476. IF AVI.ShowBitsSlow(27, buffer.data^, buffer.index) = DT.VideoObjectStartCode THEN
  1477. ret := GetVisualObjectHeader();
  1478. ELSIF AVI.ShowBitsSlow(32, buffer.data^, buffer.index) = DT.GroupOfVopStartCode THEN
  1479. ret := GetGOPHeader();
  1480. ELSIF AVI.ShowBitsSlow(32, buffer.data^, buffer.index) = DT.VideoObjectPlaneStartCode THEN
  1481. IF GetVideoObjectPlaneHeader() = FALSE THEN
  1482. KernelLog.String( "DivXPlayer: Reading VideoObjectPlane Header failed, Pos in Stream: ");
  1483. KernelLog.Int( s.Pos(), 0 ); KernelLog.String(" Next 32 Bits: "); (* KernelLog.Hex( s.ShowBits(32), 0 ); *) KernelLog.Ln();
  1484. END;
  1485. DecodeVOP();
  1486. done := TRUE;
  1487. ELSIF AVI.ShowBits(32, buffer.data^, buffer.index ) = DT.UserDataStartCode THEN
  1488. temp := AVI.GetBits(32, buffer.data^, buffer.index);
  1489. WHILE AVI.ShowBits(24, buffer.data^, buffer.index) # 1 DO
  1490. AVI.SkipBits(8, buffer.index);
  1491. END;
  1492. ELSE
  1493. AVI.SkipBits(8, buffer.index);
  1494. END;
  1495. UNTIL ( done OR ( ( buffer.index DIV 32 ) >= buffer.size - 4 ) OR (s.res = Streams.EOF) );
  1496. INC(frameCounter);
  1497. IF ~done THEN
  1498. END;
  1499. INC( mp4State.hdr.picNum );
  1500. IF DT.Debug THEN
  1501. debugFile.Update()
  1502. END;
  1503. END;
  1504. mp4StateBefore := mp4State;
  1505. (* Adjust mp4 state *)
  1506. FOR i := 0 TO 2 DO
  1507. tmp := mp4State.frameRefBaseOffset[i];
  1508. mp4State.frameRefBaseOffset[i] := mp4State.frameForBaseOffset[i];
  1509. mp4State.frameForBaseOffset[i] := tmp
  1510. END;
  1511. tmpPtr := mp4State.frameRef;
  1512. mp4State.frameRef := mp4State.frameFor;
  1513. mp4State.frameFor := tmpPtr;
  1514. IF firstFrame THEN
  1515. mp4StateBefore := mp4State;
  1516. firstFrame := FALSE;
  1517. END;
  1518. END Next;
  1519. PROCEDURE Render*(img : Raster.Image);
  1520. BEGIN
  1521. SELF.img := img;
  1522. IF ( img # NIL ) THEN
  1523. (* Postprocessing could be added here *)
  1524. col.Convert( mp4StateBefore.frameRef, mp4StateBefore.frameRefBaseOffset[0], mp4StateBefore.codedPictureWidth,
  1525. mp4StateBefore.frameRefBaseOffset[1], mp4StateBefore.frameRefBaseOffset[2], ( mp4StateBefore.codedPictureWidth DIV 2 ),
  1526. img, mp4StateBefore.hdr.width, mp4StateBefore.hdr.height, stride );
  1527. END;
  1528. END Render;
  1529. (* returns false if the stream has ended *)
  1530. PROCEDURE HasMoreData*(): BOOLEAN;
  1531. BEGIN
  1532. RETURN hasMoreBytes
  1533. END HasMoreData;
  1534. (* Decodes a Frame *)
  1535. PROCEDURE DecodeVOP;
  1536. VAR
  1537. res: BOOLEAN;
  1538. BEGIN
  1539. mp4State.hdr.mba := 0;
  1540. mp4State.hdr.mbXPos := 0;
  1541. mp4State.hdr.mbYPos := 0;
  1542. REPEAT
  1543. res := macroBlock.Decode(buffer);
  1544. INC( mp4State.hdr.mba )
  1545. UNTIL ( mp4State.hdr.mba >= mp4State.hdr.mbASize ) OR ( AVI.ShowBitsByteAligned(23, buffer.data^, buffer.index ) = 0 );
  1546. (* add edge to decoded frame *)
  1547. MakeEdge( mp4State.frameRef, mp4State.frameRefBaseOffset[0],
  1548. mp4State.codedPictureWidth, mp4State.codedPictureHeight, 32 );
  1549. MakeEdge( mp4State.frameRef, mp4State.frameRefBaseOffset[1], mp4State.chromWidth, mp4State.chromHeight, 16 );
  1550. MakeEdge( mp4State.frameRef, mp4State.frameRefBaseOffset[2], mp4State.chromWidth, mp4State.chromHeight, 16 );
  1551. END DecodeVOP;
  1552. (* Sets the the stream on which to read *)
  1553. PROCEDURE Open*(in: Streams.Reader; VAR res: WORD );
  1554. BEGIN
  1555. SELF.s := in;
  1556. NEW( mp4State);
  1557. NEW( mp4StateBefore );
  1558. frameCounter := 0;
  1559. NEW( util );
  1560. NEW( col );
  1561. firstFrame := FALSE;
  1562. frameRate := -1;
  1563. init := TRUE;
  1564. hasMoreBytes := TRUE;
  1565. Next();
  1566. END Open;
  1567. (* Sets the necessary videoInfo, which is needed to decode frames *)
  1568. PROCEDURE GetVideoInfo*(VAR width, height, milliSecondsPerFrame: LONGINT);
  1569. VAR si : Codecs.AVStreamInfo;
  1570. BEGIN
  1571. height := SELF.videoHeight;
  1572. width := SELF.videoWidth;
  1573. IF (frameRate = -1) THEN
  1574. si := s(Codecs.DemuxStream).streamInfo;
  1575. IF si.rate # 0 THEN milliSecondsPerFrame := 1000 DIV si.rate
  1576. ELSE milliSecondsPerFrame := 40 END
  1577. ELSE
  1578. milliSecondsPerFrame := 1000 DIV frameRate
  1579. END
  1580. END GetVideoInfo;
  1581. PROCEDURE CanSeek*(): BOOLEAN;
  1582. BEGIN
  1583. RETURN TRUE;
  1584. END CanSeek;
  1585. PROCEDURE GetCurrentFrame*() : LONGINT;
  1586. BEGIN
  1587. RETURN frameCounter;
  1588. END GetCurrentFrame;
  1589. PROCEDURE SeekFrame*(frame : LONGINT; goKeyFrame : BOOLEAN; VAR res : WORD);
  1590. VAR
  1591. seekType: LONGINT;
  1592. dummy: LONGINT;
  1593. BEGIN
  1594. IF goKeyFrame THEN
  1595. seekType := Codecs.SeekKeyFrame;
  1596. ELSE
  1597. seekType := Codecs.SeekFrame;
  1598. END;
  1599. frameCounter := res;
  1600. (* is it always a demuxStream?? *)
  1601. s(Codecs.DemuxStream).SetPosX(seekType, frame, frameCounter, dummy);
  1602. res := frameCounter;
  1603. IF (s # NIL) & (s.Available() > 0) THEN hasMoreBytes := TRUE; ELSE hasMoreBytes := FALSE; END;
  1604. END SeekFrame;
  1605. (* Seeks a position based on timevalue. If gokeyframe is set, the next following keyframe is searched *)
  1606. PROCEDURE SeekMillisecond*(millisecond: LONGINT; goKeyFrame : BOOLEAN; VAR res : WORD);
  1607. VAR
  1608. frame: LONGINT;
  1609. dummy: LONGINT;
  1610. seekType: LONGINT;
  1611. BEGIN
  1612. (* Now, this is wrong: we cannot assume, that microsecsperframe is always 40000 *)
  1613. frame := millisecond DIV 40;
  1614. IF goKeyFrame THEN
  1615. seekType := Codecs.SeekKeyFrame;
  1616. ELSE
  1617. seekType := Codecs.SeekFrame;
  1618. END;
  1619. s(Codecs.DemuxStream).SetPosX(seekType, frame, frameCounter, dummy);
  1620. res := frameCounter;
  1621. IF (s # NIL) & (s.Available() > 0) THEN hasMoreBytes := TRUE; ELSE hasMoreBytes := FALSE; END;
  1622. END SeekMillisecond;
  1623. (* Add edges to the picture *)
  1624. PROCEDURE MakeEdge( framePic: DT.PointerToArrayOfCHAR; framePicBaseOffset, edgedWidth, edgedHeight, edge: LONGINT );
  1625. VAR
  1626. j, width, height: LONGINT;
  1627. pBorder, pBorderTop, pBorderBottom, pBorderTopRef, pBorderBottomRef: LONGINT;
  1628. borderLeft, borderRight: CHAR;
  1629. pLeftCornerTop, pRightCornerTop, pLeftCornerBottom, pRightCornerBottom: LONGINT;
  1630. leftCornerTop, rightCornerTop, leftCornerBottom, rightCornerBottom: CHAR;
  1631. BEGIN
  1632. width := edgedWidth - ( 2*edge );
  1633. height := edgedHeight - ( 2*edge );
  1634. (* left and right edges *)
  1635. pBorder := framePicBaseOffset;
  1636. FOR j := 1 TO height DO
  1637. borderLeft := framePic[pBorder];
  1638. borderRight := framePic[pBorder + (width-1)];
  1639. util.MemSet( framePic, pBorder - edge, borderLeft, edge );
  1640. util.MemSet( framePic, pBorder + width, borderRight, edge );
  1641. pBorder := pBorder + edgedWidth
  1642. END;
  1643. (* top and bottom edges *)
  1644. pBorderTopRef := framePicBaseOffset;
  1645. pBorderBottomRef := framePicBaseOffset + ( edgedWidth*( height -1 ) );
  1646. pBorderTop := pBorderTopRef - ( edge*edgedWidth );
  1647. pBorderBottom := pBorderBottomRef + edgedWidth;
  1648. FOR j := 1 TO edge DO
  1649. SYSTEM.MOVE( ADDRESSOF( framePic[pBorderTopRef] ), ADDRESSOF( framePic[pBorderTop] ), width );
  1650. SYSTEM.MOVE( ADDRESSOF( framePic[pBorderBottomRef] ), ADDRESSOF( framePic[pBorderBottom] ), width );
  1651. pBorderTop := pBorderTop + edgedWidth;
  1652. pBorderBottom := pBorderBottom + edgedWidth
  1653. END;
  1654. (* corners *)
  1655. pLeftCornerTop := framePicBaseOffset - edge - ( edge * edgedWidth );
  1656. pRightCornerTop := pLeftCornerTop + edge + width;
  1657. pLeftCornerBottom := framePicBaseOffset + (edgedWidth * height) - edge;
  1658. pRightCornerBottom := pLeftCornerBottom + edge + width;
  1659. leftCornerTop := framePic[framePicBaseOffset];
  1660. rightCornerTop := framePic[ framePicBaseOffset + width - 1];
  1661. leftCornerBottom := framePic[framePicBaseOffset + ( edgedWidth * ( height - 1 ) )];
  1662. rightCornerBottom := framePic[ framePicBaseOffset + (edgedWidth * ( height - 1 ) ) + ( width - 1 )];
  1663. FOR j := 1 TO edge DO
  1664. util.MemSet( framePic, pLeftCornerTop, leftCornerTop, edge );
  1665. util.MemSet( framePic, pRightCornerTop, rightCornerTop, edge );
  1666. util.MemSet( framePic, pLeftCornerBottom, leftCornerBottom, edge );
  1667. util.MemSet( framePic, pRightCornerBottom, rightCornerBottom, edge );
  1668. pLeftCornerTop := pLeftCornerTop + edgedWidth;
  1669. pRightCornerTop := pRightCornerTop + edgedWidth;
  1670. pLeftCornerBottom := pLeftCornerBottom + edgedWidth;
  1671. pRightCornerBottom := pRightCornerBottom + edgedWidth
  1672. END;
  1673. END MakeEdge;
  1674. (* Read Headers *)
  1675. PROCEDURE GetVisualObjectHeader(): BOOLEAN;
  1676. VAR
  1677. temp, i, k: LONGINT;
  1678. tempReal: REAL;
  1679. BEGIN
  1680. IF AVI.ShowBits(27, buffer.data^, buffer.index ) = DT.VideoObjectStartCode THEN
  1681. temp := AVI.GetBits(27, buffer.data^, buffer.index);
  1682. temp := AVI.GetBits(5, buffer.data^, buffer.index); (* VideoObject ID *)
  1683. temp := AVI.GetBits(28, buffer.data^, buffer.index);
  1684. IF temp # DT.VisualObjectLayerStartCode THEN
  1685. IF DT.Debug THEN
  1686. log.String( "VideoObjectLayerStartCode expected but found: " ); log.Int( temp, 0 ); log.Ln()
  1687. END;
  1688. RETURN FALSE
  1689. END;
  1690. mp4State.hdr.ident := AVI.GetBits(4, buffer.data^, buffer.index); (* vol_id *)
  1691. mp4State.hdr.randomAccessibleVol := AVI.GetBits(1, buffer.data^, buffer.index);
  1692. mp4State.hdr.typeIndication := AVI.GetBits(8, buffer.data^, buffer.index);
  1693. mp4State.hdr.isObjectLayerIdentifier := AVI.GetBits(1, buffer.data^, buffer.index);
  1694. IF mp4State.hdr.isObjectLayerIdentifier > 0 THEN
  1695. mp4State.hdr.visualObjectLayerVerId := AVI.GetBits(4, buffer.data^, buffer.index);
  1696. mp4State.hdr.visualObjectLayerPriority := AVI.GetBits(3, buffer.data^, buffer.index)
  1697. ELSE
  1698. mp4State.hdr.visualObjectLayerVerId := 1;
  1699. mp4State.hdr.visualObjectLayerPriority := 1
  1700. END;
  1701. mp4State.hdr.aspectRatioInfo := AVI.GetBits(4, buffer.data^, buffer.index);
  1702. ASSERT( mp4State.hdr.aspectRatioInfo # 0FH );
  1703. (* IF mp4State.hdr.aspectRatioInfo = 0FH THEN
  1704. mp4State.hdr.parWidth := AVI.GetBits(8, buffer.data^, buffer.index);
  1705. mp4State.hdr.parHeight := AVI.GetBits(8, buffer.data^, buffer.index)
  1706. END; *)
  1707. mp4State.hdr.volControlParameters := AVI.GetBits(1, buffer.data^, buffer.index);
  1708. IF mp4State.hdr.volControlParameters > 0 THEN
  1709. mp4State.hdr.chromaFormat := AVI.GetBits(2, buffer.data^, buffer.index);
  1710. mp4State.hdr.lowDelay := AVI.GetBits(1, buffer.data^, buffer.index);
  1711. mp4State.hdr.vbvParameters := AVI.GetBits(1, buffer.data^, buffer.index);
  1712. IF mp4State.hdr.vbvParameters > 0 THEN
  1713. mp4State.hdr.firstHalfBitRate := AVI.GetBits(15, buffer.data^, buffer.index);
  1714. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* marker *)
  1715. mp4State.hdr.latterHalfBitRate := AVI.GetBits(15, buffer.data^, buffer.index);
  1716. temp :=AVI.GetBits(1, buffer.data^, buffer.index); (* marker *)
  1717. mp4State.hdr.firstHalfvbvBufferSize := AVI.GetBits(15, buffer.data^, buffer.index);
  1718. temp :=AVI.GetBits(1, buffer.data^, buffer.index); (* marker *)
  1719. mp4State.hdr.latterHalfvbvBufferSize := AVI.GetBits(3, buffer.data^, buffer.index);
  1720. mp4State.hdr.firstHalfvbvOccupancy := AVI.GetBits(11, buffer.data^, buffer.index);
  1721. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* marker *)
  1722. mp4State.hdr.latterHalfvbvOccupancy := AVI.GetBits(15, buffer.data^, buffer.index);
  1723. temp := AVI.GetBits(1, buffer.data^, buffer.index) (* marker *)
  1724. END;
  1725. END;
  1726. mp4State.hdr.shape := AVI.GetBits(2, buffer.data^, buffer.index);
  1727. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1728. mp4State.hdr.timeIncrementResolution := AVI.GetBits(16, buffer.data^, buffer.index);
  1729. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1730. mp4State.hdr.fixedVopRate := AVI.GetBits(1, buffer.data^, buffer.index);
  1731. IF mp4State.hdr.fixedVopRate > 0 THEN
  1732. tempReal := Math.ln( mp4State.hdr.timeIncrementResolution) / Math.ln( 2.0 );
  1733. temp := ENTIER( tempReal );
  1734. IF tempReal / Reals.Real( temp ) > 1.0 THEN
  1735. INC( temp )
  1736. END;
  1737. IF temp < 1 THEN
  1738. temp := 1
  1739. END;
  1740. mp4State.hdr.fixedVopTimeIncrement := AVI.GetBits(temp, buffer.data^, buffer.index)
  1741. END;
  1742. IF mp4State.hdr.shape # DT.BinaryShapeOnly THEN
  1743. IF mp4State.hdr.shape = 0 THEN
  1744. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1745. mp4State.hdr.width := AVI.GetBits(13, buffer.data^, buffer.index);
  1746. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1747. mp4State.hdr.height := AVI.GetBits(13, buffer.data^, buffer.index);
  1748. temp := AVI.GetBits(1, buffer.data^, buffer.index) (* Marker *)
  1749. END;
  1750. IF init THEN
  1751. videoWidth := mp4State.hdr.width;
  1752. videoHeight := mp4State.hdr.height;
  1753. END;
  1754. mp4State.hdr.interlaced := AVI.GetBits(1, buffer.data^, buffer.index);
  1755. mp4State.hdr.obmcDisable := AVI.GetBits(1, buffer.data^, buffer.index);
  1756. IF mp4State.hdr.visualObjectLayerVerId = 1 THEN
  1757. mp4State.hdr.spriteUsage := AVI.GetBits(1, buffer.data^, buffer.index)
  1758. ELSE
  1759. mp4State.hdr.spriteUsage := AVI.GetBits(2, buffer.data^, buffer.index)
  1760. END;
  1761. mp4State.hdr.not8Bit := AVI.GetBits(1, buffer.data^, buffer.index);
  1762. IF mp4State.hdr.not8Bit > 0THEN
  1763. mp4State.hdr.quantPrecision := AVI.GetBits(4, buffer.data^, buffer.index);
  1764. mp4State.hdr.bitsPerPixel := AVI.GetBits(4, buffer.data^, buffer.index)
  1765. ELSE
  1766. mp4State.hdr.quantPrecision := 5;
  1767. mp4State.hdr.bitsPerPixel := 8
  1768. END;
  1769. IF mp4State.hdr.shape = DT.GrayScaleOnly THEN
  1770. KernelLog.String("GreyScale not supported"); log.Ln();
  1771. RETURN FALSE
  1772. END;
  1773. mp4State.hdr.quantType := AVI.GetBits(1, buffer.data^, buffer.index);
  1774. IF mp4State.hdr.quantType > 0 THEN
  1775. mp4State.hdr.loadIntraQuantMatrix := AVI.GetBits(1, buffer.data^, buffer.index);
  1776. IF mp4State.hdr.loadIntraQuantMatrix > 0 THEN
  1777. (* load intra quant matrix *)
  1778. k := 0;
  1779. REPEAT
  1780. INC( k );
  1781. temp := AVI.GetBits(8, buffer.data^, buffer.index);
  1782. mp4State.mp4Tables.intraQuantMatrix[mp4State.mp4Tables.zigZagScan[k]] := temp
  1783. UNTIL ( ( k >= 64 ) OR ( temp = 0 ) );
  1784. FOR i := k TO 63 DO
  1785. mp4State.mp4Tables.intraQuantMatrix[mp4State.mp4Tables.zigZagScan[i]] :=
  1786. mp4State.mp4Tables.intraQuantMatrix[mp4State.mp4Tables.zigZagScan[k-1]]
  1787. END;
  1788. END;
  1789. mp4State.hdr.loadNonIntraQuantMatrix := AVI.GetBits(1, buffer.data^, buffer.index);
  1790. IF mp4State.hdr.loadNonIntraQuantMatrix > 0 THEN
  1791. (* load nonintra quant matrix *)
  1792. k := 0;
  1793. REPEAT
  1794. INC(k);
  1795. temp := AVI.GetBits(8, buffer.data^, buffer.index);
  1796. mp4State.mp4Tables.nonIntraQuantMatrix[mp4State.mp4Tables.zigZagScan[k]] := temp
  1797. UNTIL ( ( k >= 64 ) OR ( temp = 0 ) );
  1798. FOR i := k TO 63 DO
  1799. mp4State.mp4Tables.nonIntraQuantMatrix[mp4State.mp4Tables.zigZagScan[i]] :=
  1800. mp4State.mp4Tables.nonIntraQuantMatrix[mp4State.mp4Tables.zigZagScan[k-1]]
  1801. END;
  1802. END;
  1803. END;
  1804. IF mp4State.hdr.visualObjectLayerVerId # 1 THEN (* ident *)
  1805. mp4State.hdr.quarterPixel := AVI.GetBits(1, buffer.data^, buffer.index)
  1806. ELSE
  1807. mp4State.hdr.quarterPixel := 0
  1808. END;
  1809. mp4State.hdr.complexityEstimationDisable := AVI.GetBits(1, buffer.data^, buffer.index);
  1810. mp4State.hdr.errorResDisable := AVI.GetBits(1, buffer.data^, buffer.index);
  1811. mp4State.hdr.dataPartitioning := AVI.GetBits(1, buffer.data^, buffer.index);
  1812. IF mp4State.hdr.dataPartitioning > 0 THEN
  1813. KernelLog.String( "Data partitioning not supported" ); KernelLog.Ln();
  1814. RETURN FALSE
  1815. ELSE
  1816. mp4State.hdr.errorResDisable := 1
  1817. END;
  1818. mp4State.hdr.intraacdcPredDisable := 0;
  1819. mp4State.hdr.scalability := AVI.GetBits(1, buffer.data^, buffer.index);
  1820. IF mp4State.hdr.scalability > 0 THEN
  1821. KernelLog.String( "Scalability not supported" ); KernelLog.Ln();
  1822. RETURN FALSE
  1823. END;
  1824. IF AVI.ShowBits( 32, buffer.data^, buffer.index ) = DT.UserDataStartCode THEN
  1825. KernelLog.String("No user data in video object Layer supported")
  1826. END;
  1827. END;
  1828. IF init THEN
  1829. mp4State.hdr.FinishHeader();
  1830. NEW( opt, mp4State.hdr.width, mp4State.hdr.height);
  1831. NEW( mp4Buffers, opt );
  1832. mp4State.SetUpState(mp4Buffers);
  1833. NEW( macroBlock, mp4State, buffer, log);
  1834. firstFrame := TRUE;
  1835. (* Perhaps someone finds out the correct way with mpeg4, so assume 40 *)
  1836. stride := opt.xDim;
  1837. init := FALSE;
  1838. END;
  1839. RETURN TRUE
  1840. ELSE
  1841. END;
  1842. RETURN FALSE
  1843. END GetVisualObjectHeader;
  1844. PROCEDURE GetGOPHeader(): BOOLEAN;
  1845. VAR
  1846. temp: LONGINT;
  1847. BEGIN
  1848. IF AVI.ShowBits(32, buffer.data^, buffer.index) = DT.GroupOfVopStartCode THEN
  1849. temp := AVI.GetBits(32, buffer.data^, buffer.index);
  1850. mp4State.hdr.timeCode := AVI.GetBits(18, buffer.data^, buffer.index);
  1851. mp4State.hdr.closedGov := AVI.GetBits(1, buffer.data^, buffer.index);
  1852. mp4State.hdr.brokenLink := AVI.GetBits(1, buffer.data^, buffer.index);
  1853. ELSE
  1854. END;
  1855. RETURN TRUE
  1856. END GetGOPHeader;
  1857. PROCEDURE NextStartCode;
  1858. VAR
  1859. temp: LONGINT;
  1860. BEGIN
  1861. IF AVI.IsAligned(buffer.index) = FALSE THEN
  1862. temp := AVI.GetBits( 1, buffer.data^, buffer.index );
  1863. WHILE AVI.IsAligned(buffer.index) = FALSE DO
  1864. AVI.SkipBits(1, buffer.index);
  1865. END;
  1866. END;
  1867. END NextStartCode;
  1868. PROCEDURE GetVideoObjectPlaneHeader(): BOOLEAN;
  1869. VAR
  1870. temp: LONGINT;
  1871. tempReal: REAL;
  1872. BEGIN
  1873. IF AVI.GetBits(32, buffer.data^, buffer.index) # DT.VideoObjectPlaneStartCode THEN
  1874. RETURN FALSE
  1875. END;
  1876. mp4State.hdr.predictionType := AVI.GetBits(2, buffer.data^, buffer.index);
  1877. mp4State.hdr.timeBase := 0;
  1878. WHILE AVI.GetBits(1, buffer.data^, buffer.index) # 0 DO (* temporal time base *)
  1879. INC( mp4State.hdr.timeBase )
  1880. END;
  1881. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* marker bit *)
  1882. tempReal := Math.ln( mp4State.hdr.timeIncrementResolution )/Math.ln( 2.0 );
  1883. temp := ENTIER( tempReal );
  1884. IF ( tempReal / Reals.Real( temp ) ) > 1.0 THEN
  1885. INC( temp )
  1886. END;
  1887. IF temp < 1 THEN
  1888. temp := 1
  1889. END;
  1890. mp4State.hdr.timeInc := AVI.GetBits(temp, buffer.data^, buffer.index); (* vop_time_increment (1-16 bits) *)
  1891. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* marker bit *)
  1892. mp4State.hdr.vopCoded := AVI.GetBits(1, buffer.data^, buffer.index);
  1893. IF mp4State.hdr.vopCoded = 0 THEN
  1894. NextStartCode();
  1895. RETURN TRUE
  1896. END;
  1897. IF ( mp4State.hdr.shape # DT.BinaryShapeOnly ) & ( mp4State.hdr.predictionType = DT.PVOP ) THEN
  1898. mp4State.hdr.roundingType := AVI.GetBits(1, buffer.data^, buffer.index)
  1899. ELSE
  1900. mp4State.hdr.roundingType := 0
  1901. END;
  1902. IF mp4State.hdr.shape # DT.Rectangular THEN
  1903. IF ~( (mp4State.hdr.spriteUsage = DT.StaticSprite) & (mp4State.hdr.predictionType = DT.IVOP) ) THEN
  1904. mp4State.hdr.width := AVI.GetBits(13, buffer.data^, buffer.index);
  1905. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1906. mp4State.hdr.height := AVI.GetBits(13, buffer.data^, buffer.index);
  1907. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1908. mp4State.hdr.horSpatRef := AVI.GetBits(13, buffer.data^, buffer.index);
  1909. temp := AVI.GetBits(1, buffer.data^, buffer.index); (* Marker *)
  1910. mp4State.hdr.verSpatRef := AVI.GetBits(13, buffer.data^, buffer.index);
  1911. temp := AVI.GetBits(1, buffer.data^, buffer.index) (* Marker *)
  1912. END;
  1913. mp4State.hdr.changeCRDisable := AVI.GetBits(1, buffer.data^, buffer.index);
  1914. mp4State.hdr.constantAlpha := AVI.GetBits(1, buffer.data^, buffer.index);
  1915. IF mp4State.hdr.constantAlpha > 0THEN
  1916. mp4State.hdr.constantAlphaValue := AVI.GetBits(8, buffer.data^, buffer.index)
  1917. END;
  1918. END;
  1919. IF mp4State.hdr.complexityEstimationDisable = 0 THEN
  1920. KernelLog.String("ComplexityEstimationDisable must be enabled"); KernelLog.Ln();
  1921. RETURN FALSE
  1922. END;
  1923. IF mp4State.hdr.shape # DT.BinaryShapeOnly THEN
  1924. mp4State.hdr.intradcvlcthr := AVI.GetBits(3, buffer.data^, buffer.index );
  1925. IF mp4State.hdr.interlaced > 0 THEN
  1926. KernelLog.String("Interlaced movies not supported"); KernelLog.Ln();
  1927. RETURN FALSE
  1928. END;
  1929. END;
  1930. IF mp4State.hdr.shape # DT.BinaryShapeOnly THEN
  1931. mp4State.hdr.quantizer := AVI.GetBits( mp4State.hdr.quantPrecision, buffer.data^, buffer.index );
  1932. IF mp4State.hdr.predictionType # DT.IVOP THEN
  1933. mp4State.hdr.fCodeFor := AVI.GetBits(3, buffer.data^, buffer.index)
  1934. END;
  1935. IF mp4State.hdr.scalability = 0 THEN
  1936. IF ( mp4State.hdr.shape > 0 ) & ( mp4State.hdr.predictionType # DT.IVOP ) THEN
  1937. mp4State.hdr.shapeCodingType := AVI.GetBits(1, buffer.data^, buffer.index)
  1938. END;
  1939. END;
  1940. END;
  1941. RETURN TRUE
  1942. END GetVideoObjectPlaneHeader;
  1943. END DivXDecoder;
  1944. PROCEDURE Factory*() : Codecs.VideoDecoder;
  1945. VAR p: DivXDecoder;
  1946. BEGIN
  1947. NEW(p);
  1948. RETURN p
  1949. END Factory;
  1950. END DivXDecoder.
  1951. SystemTools.Free DivXDecoder ~