MPEGVideoDecoder.Mod 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548
  1. (** AUTHOR "Yves Weber";
  2. PURPOSE "MPEG System Demultiplexer and MPEG Video Decoder";
  3. *)
  4. MODULE MPEGVideoDecoder;
  5. IMPORT
  6. SYSTEM, Codec := Codecs, Raster, Streams, KernelLog, Files, WMGraphics, MPEGTables,
  7. WM := WMWindowManager, Rectangles := WMRectangles, Kernel, Commands,
  8. Util := MPEGUtilities;
  9. CONST
  10. (* Video start codes in numeric order *)
  11. SCPicture* = CHR(000H);
  12. (* CHR(001H)
  13. :
  14. CHR(0AFH) are slice start codes
  15. CHR(0B0H) and
  16. CHR(0B1H) are reserved *)
  17. SCUserData* = CHR(0B2H);
  18. SCSequenceHeader* = CHR(0B3H);
  19. SCSequenceError* = CHR(0B4H);
  20. SCExtension* = CHR(0B5H);
  21. (* CHR(0B6H) is reserved *)
  22. SCSequenceEnd* = CHR(0B7H);
  23. SCGOP* = CHR(0B8H);
  24. (* System start codes in numeric order *)
  25. SCSystemEnd* = CHR(0B9H);
  26. SCPack* = CHR(0BAH);
  27. SCSystemHeader* = CHR(0BBH);
  28. SCReservedStream* = CHR(0BCH);
  29. SCPrivateStream* = CHR(0BDH);
  30. SCPaddingStream* = CHR(0BEH);
  31. SCPrivateStream2* = CHR(0BFH);
  32. (* CHR(0C0H)
  33. :
  34. CHR(0DFH) are audio streams 0..31
  35. CHR(0E0H)
  36. :
  37. CHR(0EFH) are video streams 0..15
  38. CHR(0F0H)
  39. :
  40. CHR(0FFH) are reserved streams 0..15 *)
  41. (* Picture Structures (MPEG-2 only) *)
  42. PicStructReserved* = 0;
  43. PicStructTopField* = 1;
  44. PicStructBottomField* = 2;
  45. PicStructFrame* = 3;
  46. (* Frame Motion Types *)
  47. FMTReserved* = 0;
  48. FMTField* = 1;
  49. FMTFrame* = 2;
  50. FMTDualPrime* = 3;
  51. (* index in MotionVectorInfos *)
  52. forward = 0;
  53. backward = 1;
  54. horizontal = 0;
  55. vertical = 1;
  56. mv1 = 0; (* first motion vector *)
  57. mv2 = 1; (* second motion vector (MPEG-1 always uses just the first one) *)
  58. TYPE
  59. (* required by the demultiplexer to keep track of its streams *)
  60. StreamType = RECORD
  61. stream*: Codec.DemuxStream;
  62. idByte*: CHAR;
  63. pos: LONGINT;
  64. bytesLeftInPacket: LONGINT;
  65. eos: BOOLEAN; (* end of stream *)
  66. END;
  67. (* Window of a very (!) simple stand-alone player *)
  68. TYPE PW* = OBJECT(WM.DoubleBufferWindow)
  69. PROCEDURE & InitNew*(w, h:LONGINT; alpha:BOOLEAN);
  70. BEGIN
  71. Init(w, h, alpha);
  72. manager := WM.GetDefaultManager();
  73. WM.DefaultAddWindow(SELF);
  74. END InitNew;
  75. (* Overwrite draw procedure because we do not want any interpolation *)
  76. PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
  77. BEGIN
  78. Draw^(canvas, w, h, 0)
  79. END Draw;
  80. PROCEDURE Close*;
  81. BEGIN
  82. Close^;
  83. END Close;
  84. END PW;
  85. (* Decoder for an MPEG Video Sequence *)
  86. MPEGVideoDecoder* = OBJECT(Codec.VideoDecoder)
  87. VAR
  88. (* Video Information *)
  89. videoWidth, videoHeight: LONGINT;
  90. videoWidthDiv2, videoHeightDiv2: LONGINT;
  91. videoWidthDiv16, videoHeightDiv16: LONGINT;
  92. aspectRatioIndex, frameRateIndex: LONGINT;
  93. bitRate: LONGINT;
  94. stream*: Util.BitStream; (* the stream we read from *)
  95. reader: Util.StreamReader; (* allows to read VLCs and other information from the stream *)
  96. idct: Util.IDCT; (* performs the iDCT *)
  97. yuv2rgb: Util.ColorSpace; (* performs the colorspace transformation YUV -> RGB *)
  98. dequantizer: Util.Dequantizer; (* performs the dequantization of intra and non-intra quantizer matrices *)
  99. blocks: Util.BlockActions; (* required for motion compensation *)
  100. intraQM: Util.PointerToArrayOfLONGINT; (* intra quantizer matrix *)
  101. nonintraQM: Util.PointerToArrayOfLONGINT; (* non-intra quantizer matrix *)
  102. curFrame: Util.Frame; (* the dequantized and iDCT'ed YUV values *)
  103. prevRef, nextRef: Util.Frame; (* previous and next reference picture *)
  104. nextFrameToRender: Util.Frame; (* the next frame ready to be rendered *)
  105. mvinfos: Util.MotionVectorInfos; (* everything that is somehow connected to motion vectors *)
  106. frameNr: LONGINT; (* number of the current frame (restarts for each GOP) *)
  107. realFrameNr: LONGINT; (* number of the current frame (restarts at the beginning of the movie) *)
  108. time: LONGINT; (* current time in milliseconds *)
  109. mspf: LONGINT; (* milliseconds per frame *)
  110. hasMoreFrames: BOOLEAN; (* FALSE at the end of a video sequence *)
  111. (* MPEG-2 stuff *)
  112. MPEG2: BOOLEAN; (* TRUE -> MPEG-2; FALSE -> MPEG-1 *)
  113. MainProfile: BOOLEAN; (* TRUE -> Main Profile; FALSE -> Simple Profile *)
  114. LevelID: LONGINT; (* 1 -> Low, 2 -> Main, 3 -> High1440, 4 -> High *)
  115. ChromaFormat: LONGINT; (* 1 -> 4:2:0, 2 -> 4:2:2, 3-> 4:4:4 *)
  116. picExt: Util.PicCodingExt; (* some infos about the picture *)
  117. (* less important VARs *)
  118. mbSkipped: BOOLEAN; (* TRUE if last macroblock was skipped (required for DC prediction) *)
  119. dcY, dcCb, dcCr: LONGINT; (* DC coefficient prediction for Y, Cb and Cr blocks *)
  120. mbMotionForwOld, mbMotionBackOld: BOOLEAN; (* required for skipped macroblocks of B-Frames *)
  121. mbIntraOld: BOOLEAN;
  122. (* local in picture *)
  123. mbAddress: LONGINT; (* Address of the current macroblock *)
  124. mbAddressLast: LONGINT; (* Address of the last coded macroblock *)
  125. mbAddressLastIntra: LONGINT;
  126. macroblockNr: INTEGER; (* number of the macroblock currently decoded (in slice) *)
  127. (* local in macroblock *)
  128. frameMotionType: LONGINT;
  129. dctType: BOOLEAN;
  130. block: Util.PointerToArrayOfLONGINT; (* current block of a macroblock *)
  131. frametype: LONGINT;
  132. (* Constructor *)
  133. PROCEDURE &Init*;
  134. VAR
  135. i: SHORTINT;
  136. BEGIN
  137. NEW(idct);
  138. NEW(yuv2rgb);
  139. NEW(dequantizer);
  140. NEW(picExt);
  141. NEW(mvinfos);
  142. NEW(blocks);
  143. NEW(block, 64);
  144. hasMoreFrames := TRUE;
  145. realFrameNr := -1;
  146. (* init QMs with default values *)
  147. NEW(intraQM, 64);
  148. NEW(nonintraQM, 64);
  149. FOR i := 0 TO 63 DO
  150. intraQM[i] := MPEGTables.IQM[i];
  151. nonintraQM[i] := 16;
  152. END;
  153. END Init;
  154. (* Open a video stream by reading the sequence header *)
  155. PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
  156. VAR
  157. marker: CHAR;
  158. BEGIN
  159. res := Codec.ResFailed;
  160. IF ~(in IS Codec.DemuxStream) THEN RETURN END;
  161. NEW(stream, in(Codec.DemuxStream));
  162. NEW(reader, stream);
  163. frameNr := -1;
  164. (* read (next) start code *)
  165. IF ~GotoNextMarker(stream, marker) THEN
  166. (* stream does not start with a startcode *)
  167. KernelLog.String("this is not a legal MPEG video stream (no startcode found)"); KernelLog.Ln;
  168. RETURN;
  169. END;
  170. (* check if startcode is legal *)
  171. IF marker # SCSequenceHeader THEN
  172. IF marker = CHR(0BAH) THEN
  173. KernelLog.String("This is a multiplexed (audio & video) MPEG stream. Use the demultiplexer."); KernelLog.Ln;
  174. ELSE
  175. (* video sequence must start with 00 00 01 B3 *)
  176. KernelLog.String("This is not a valid Video Stream (Marker="); KernelLog.Hex(ORD(marker), -1);
  177. KernelLog.String(")"); KernelLog.Ln;
  178. END;
  179. RETURN;
  180. END;
  181. (* skip the startcode *)
  182. stream.SkipBits(32);
  183. IF ParseSequenceHeader() THEN
  184. (* create image buffers *)
  185. videoWidthDiv2 := videoWidth DIV 2;
  186. videoHeightDiv2 := videoHeight DIV 2;
  187. videoWidthDiv16 := videoWidth DIV 16;
  188. videoHeightDiv16 := videoHeight DIV 16;
  189. NEW(curFrame);
  190. NEW(curFrame.buffer, videoHeight * videoWidth + 2 * (videoHeightDiv2 * videoWidthDiv2));
  191. curFrame.cbOffset := videoHeight * videoWidth;
  192. curFrame.crOffset := videoHeight * videoWidth + videoHeightDiv2 * videoWidthDiv2;
  193. curFrame.frameNr := -1;
  194. NEW(prevRef);
  195. NEW(prevRef.buffer, videoHeight * videoWidth + 2 * (videoHeightDiv2 * videoWidthDiv2));
  196. prevRef.cbOffset := videoHeight * videoWidth;
  197. prevRef.crOffset := videoHeight * videoWidth + videoHeightDiv2 * videoWidthDiv2;
  198. prevRef.frameNr := -1;
  199. NEW(nextRef);
  200. NEW(nextRef.buffer, videoHeight * videoWidth + 2 * (videoHeightDiv2 * videoWidthDiv2));
  201. nextRef.cbOffset := videoHeight * videoWidth;
  202. nextRef.crOffset := videoHeight * videoWidth + videoHeightDiv2 * videoWidthDiv2;
  203. nextRef.frameNr := -1;
  204. res := Codec.ResOk;
  205. RETURN;
  206. ELSE
  207. KernelLog.String("Failed parsing (first) Sequence Header"); KernelLog.Ln;
  208. END;
  209. END Open;
  210. PROCEDURE HasMoreData*(): BOOLEAN;
  211. BEGIN
  212. RETURN hasMoreFrames;
  213. END HasMoreData;
  214. PROCEDURE ParseSequenceHeader(): BOOLEAN;
  215. VAR
  216. marker: CHAR;
  217. BEGIN
  218. videoWidth := stream.GetBits(12);
  219. videoHeight := stream.GetBits(12);
  220. (* we just extend the video to a multiple of 16. not perfect, but it works... *)
  221. IF videoWidth MOD 16 # 0 THEN
  222. videoWidth := ((videoWidth DIV 16) + 1) * 16;
  223. END;
  224. IF videoHeight MOD 16 # 0 THEN
  225. videoHeight := ((videoHeight DIV 16) + 1) * 16;
  226. END;
  227. aspectRatioIndex := stream.GetBits(4);
  228. frameRateIndex := stream.GetBits(4);
  229. CASE frameRateIndex OF
  230. 1: mspf := 42 (* 23.976 fps -> 41.70837... *)
  231. | 2: mspf := 42 (* 24 fps -> 41.66666... *)
  232. | 3: mspf := 40 (* 25 fps -> 40.00000... *)
  233. | 4: mspf := 33 (* 29.97 fps -> 33.36670... *)
  234. | 5: mspf := 33 (* 30 fps -> 33.33333... *)
  235. | 6: mspf := 20 (* 50 fps -> 20.00000... *)
  236. | 7: mspf := 17 (* 59.94 fps -> 16.68335... *)
  237. | 8: mspf := 17 (* 60 fps -> 16.66666... *)
  238. ELSE
  239. mspf := 40; (* illegal framerate, just assume something *)
  240. KernelLog.String("Unknown Framerate Index: "); KernelLog.Int(frameRateIndex, 0); KernelLog.Ln;
  241. END;
  242. bitRate := stream.GetBits(18);
  243. stream.SkipBits(1); (* marker bit *)
  244. stream.SkipBits(10); (* vbv buffer size *)
  245. stream.SkipBits(1); (* constrained bit *)
  246. IF stream.GetBits(1) = 1 THEN
  247. (* intra quantizer matrix coming... *)
  248. reader.ReadQuantizerMatrix(intraQM);
  249. IF reader.eof THEN RETURN FALSE END;
  250. END;
  251. IF stream.GetBits(1) = 1 THEN
  252. (* non-intra quantizer matrix coming *)
  253. reader.ReadQuantizerMatrix(nonintraQM);
  254. IF reader.eof THEN RETURN FALSE END;
  255. END;
  256. IF ~stream.HasMoreData() THEN hasMoreFrames := FALSE; RETURN FALSE END;
  257. IF ~GotoNextMarker(stream, marker) THEN
  258. RETURN FALSE;
  259. END;
  260. (* read extension block(s) if present *)
  261. IF marker = SCExtension THEN
  262. (* This is an MPEG-2 stream! *)
  263. MPEG2 := TRUE;
  264. REPEAT
  265. IF marker = SCExtension THEN
  266. stream.SkipBits(32);
  267. IF ~ReadExtension() THEN RETURN FALSE END;
  268. IF ~GotoNextMarker(stream, marker) THEN RETURN FALSE END;
  269. ELSE
  270. (* skip user data - they are unimportant for the decoder *)
  271. stream.SkipBits(32);
  272. IF ~GotoNextMarker(stream, marker) THEN RETURN FALSE END;
  273. END;
  274. UNTIL (marker # SCExtension) & (marker # SCUserData);
  275. ELSE
  276. (* This is an MPEG-1 stream! *)
  277. MPEG2 := FALSE;
  278. WHILE marker = SCUserData DO
  279. stream.SkipBits(32);
  280. IF ~GotoNextMarker(stream, marker) THEN
  281. RETURN FALSE;
  282. END;
  283. END;
  284. END;
  285. RETURN TRUE;
  286. END ParseSequenceHeader;
  287. (* Read an extension. It is assumed that the stream is currently at the end of an extension start code *)
  288. PROCEDURE ReadExtension(): BOOLEAN;
  289. VAR
  290. fourbits: LONGINT;
  291. tmp: BOOLEAN;
  292. BEGIN
  293. fourbits := stream.GetBits(4);
  294. CASE fourbits OF
  295. 0, 5, 6, 9..15:
  296. (* not supported by MP@ML or not defined by the standard *)
  297. KernelLog.String("Extension not supported: "); KernelLog.Int(stream.ShowBits(4), 0); KernelLog.Ln;
  298. RETURN FALSE;
  299. | 1: (* sequence extension *)
  300. tmp := reader.ReadSequenceExtension(MainProfile, LevelID, ChromaFormat, videoWidth, videoHeight);
  301. IF reader.eof THEN
  302. RETURN FALSE;
  303. ELSE
  304. RETURN tmp;
  305. END;
  306. | 2: (* sequence display extension *)
  307. tmp := reader.ReadSequenceDisplayExtension();
  308. IF reader.eof THEN
  309. RETURN FALSE;
  310. ELSE
  311. RETURN tmp;
  312. END;
  313. | 3: (* quant matrix extension *)
  314. tmp := reader.ReadQuantMatrixExtension();
  315. IF reader.eof THEN
  316. RETURN FALSE;
  317. ELSE
  318. RETURN tmp;
  319. END;
  320. | 4: (* copyright extension *)
  321. tmp := reader.ReadCopyrightExtension();
  322. IF reader.eof THEN
  323. RETURN FALSE;
  324. ELSE
  325. RETURN tmp;
  326. END;
  327. | 7: (* picture display extension *)
  328. tmp := reader.ReadPictureDisplayExtension();
  329. IF reader.eof THEN
  330. RETURN FALSE;
  331. ELSE
  332. RETURN tmp;
  333. END;
  334. | 8: (* picture coding extension *)
  335. tmp := reader.ReadPictureCodingExtension(picExt, mvinfos);
  336. IF reader.eof THEN
  337. RETURN FALSE;
  338. ELSE
  339. RETURN tmp;
  340. END;
  341. ELSE
  342. hasMoreFrames := FALSE;
  343. RETURN FALSE;
  344. END;
  345. (* we can't come here... *)
  346. RETURN FALSE;
  347. END ReadExtension;
  348. (* parse an SMTPE timecode (25 bits) *)
  349. PROCEDURE ReadTimecode;
  350. VAR
  351. h, min, sec, frames: LONGINT;
  352. BEGIN
  353. stream.SkipBits(1);
  354. h := stream.GetBits(5);
  355. min := stream.GetBits(6);
  356. stream.SkipBits(1);
  357. sec := stream.GetBits(6);
  358. frames := stream.GetBits(6);
  359. (* the timecode may not be used for seeking because it does not
  360. always start at 0:00:00.00 for all movies *)
  361. (*
  362. KernelLog.String("Timecode: ");
  363. KernelLog.Int(h, 0); KernelLog.String(":");
  364. KernelLog.Int(min, 0); KernelLog.String(":");
  365. KernelLog.Int(sec, 0); KernelLog.String(".");
  366. KernelLog.Int(frames, 0); KernelLog.Ln;
  367. *)
  368. IF ~stream.HasMoreData() THEN
  369. hasMoreFrames := FALSE;
  370. END;
  371. END ReadTimecode;
  372. (* return some information about the video stream *)
  373. PROCEDURE GetVideoInfo*(VAR width, height, millisecondsPerFrame : LONGINT);
  374. BEGIN
  375. width := videoWidth;
  376. height := videoHeight;
  377. millisecondsPerFrame := mspf;
  378. END GetVideoInfo;
  379. PROCEDURE CanSeek*() : BOOLEAN;
  380. BEGIN
  381. RETURN TRUE
  382. END CanSeek;
  383. PROCEDURE GetCurrentFrame*() : LONGINT;
  384. BEGIN
  385. RETURN realFrameNr;
  386. END GetCurrentFrame;
  387. PROCEDURE GetCurrentTime*() : LONGINT;
  388. BEGIN
  389. RETURN time;
  390. END GetCurrentTime;
  391. PROCEDURE SeekFrame*(frame : LONGINT; goKeyFrame : BOOLEAN; VAR res : LONGINT);
  392. VAR
  393. i: LONGINT;
  394. code: CHAR;
  395. lastIntraPosOld, lastIntraNrOld, lastIntraPos, lastIntraNr, lastFramePos: LONGINT;
  396. nrB, nrBOld: LONGINT;
  397. countB: BOOLEAN;
  398. type: LONGINT;
  399. BEGIN
  400. res := Codec.ResFailed;
  401. (* start at the beginning *)
  402. stream.Reset;
  403. IF ~GotoNextMarker(stream, code) THEN RETURN END;
  404. stream.SkipBits(32);
  405. IF ~ParseSequenceHeader() THEN RETURN END;
  406. lastIntraPos := stream.Pos();
  407. lastFramePos := stream.Pos();
  408. (* to be sure, we need to decode the last 2 i-frames. consider (decoding!) order IBBPBBIB *)
  409. FOR i := 0 TO frame DO
  410. (* skip frame i *)
  411. type := SkipNext();
  412. IF type = 1 THEN
  413. (* skipped frame was an I-frame *)
  414. lastIntraPosOld := lastIntraPos;
  415. lastIntraNrOld := lastIntraNr;
  416. lastIntraPos := lastFramePos;
  417. lastIntraNr := i;
  418. countB := TRUE;
  419. nrBOld := nrB;
  420. nrB := 0;
  421. ELSE
  422. IF countB THEN
  423. IF type = 3 THEN
  424. INC(nrB);
  425. ELSE
  426. countB := FALSE;
  427. END;
  428. END;
  429. END;
  430. lastFramePos := stream.Pos();
  431. END;
  432. (* jump to the second last I-frame *)
  433. stream.SetPos(lastIntraPosOld);
  434. realFrameNr := lastIntraNrOld;
  435. frameNr := 10000; (* expected frameNr > tempRef => frameNr gets adjusted *)
  436. Next();
  437. FOR i := 1 TO nrBOld DO
  438. type := SkipNext();
  439. END;
  440. DEC(frameNr, nrBOld);
  441. FOR i := lastIntraNrOld+1 TO lastIntraNr-1 DO
  442. Next();
  443. END;
  444. IF ~goKeyFrame THEN
  445. FOR i := lastIntraNr TO frame DO
  446. Next();
  447. END;
  448. END;
  449. res := Codec.ResOk;
  450. END SeekFrame;
  451. PROCEDURE SeekMillisecond*(millisecond : LONGINT; goKeyFrame : BOOLEAN; VAR res : LONGINT);
  452. VAR
  453. newframe: LONGINT;
  454. BEGIN
  455. newframe := millisecond DIV mspf;
  456. SeekFrame(newframe, goKeyFrame, res);
  457. time := newframe * mspf;
  458. END SeekMillisecond;
  459. (* skips one frame *)
  460. PROCEDURE SkipNext(): LONGINT;
  461. VAR
  462. marker: CHAR;
  463. picType: LONGINT; (* 1=I-, 2=P-, 3=B-, 4=D-Picture, other values are illegal *)
  464. tempRef: LONGINT; (* temporal reference *)
  465. nextCode: LONGINT;
  466. tmpFrame: Util.Frame; (* required to switch two frames *)
  467. BEGIN
  468. IF ~hasMoreFrames THEN RETURN -1 END;
  469. INC(frameNr);
  470. INC(realFrameNr);
  471. IF frameNr = nextRef.frameNr THEN
  472. (* we have already decoded this frame, just take it from the nextRef buffer *)
  473. tmpFrame := curFrame;
  474. curFrame := nextRef;
  475. nextRef := tmpFrame;
  476. ELSE
  477. (* decode one or two frames *)
  478. REPEAT
  479. mbAddress := -1;
  480. mbAddressLast := -1;
  481. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  482. WHILE marker # SCPicture DO
  483. IF marker = SCSequenceHeader THEN
  484. stream.SkipBits(32);
  485. IF ~ParseSequenceHeader() THEN
  486. hasMoreFrames := FALSE;
  487. RETURN -1;
  488. END;
  489. ELSIF marker = SCGOP THEN
  490. stream.SkipBits(32);
  491. ReadTimecode; (* SMPTE Timecode *)
  492. stream.SkipBits(1); (* closed GOP -> if closed wipe out prev and next buffer (black) *)
  493. stream.SkipBits(1); (* broken link *)
  494. stream.SkipBits(5); (* not used, should be 0... *)
  495. (* temporal reference restarts at zero *)
  496. frameNr := 0;
  497. prevRef.frameNr := -1; (* make sure they are at most used as reference *)
  498. nextRef.frameNr := -1; (* make sure they are at most used as reference *)
  499. ELSE
  500. KernelLog.String("Unexpected marker found: "); KernelLog.Hex(ORD(marker), -1); KernelLog.Ln;
  501. RETURN -1;
  502. END;
  503. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  504. END;
  505. (* parse picture header *)
  506. stream.SkipBits(32);
  507. tempRef := stream.GetBits(10); (* temporal reference *)
  508. curFrame.frameNr := tempRef;
  509. picType := stream.GetBits(3); (* the picture type (I, P, B or D) *)
  510. frametype := picType;
  511. curFrame.picType := picType;
  512. stream.SkipBits(16); (* vbv buffer delay -> not relevant for us *)
  513. IF (picType = 2) OR (picType = 3) THEN
  514. stream.SkipBits(4);
  515. END;
  516. IF picType = 3 THEN
  517. stream.SkipBits(4);
  518. END;
  519. WHILE stream.ShowBits(1) = 1 DO
  520. stream.SkipBits(1); (* extra information follows *)
  521. stream.SkipBits(8); (* undefined by the standard *)
  522. END;
  523. stream.SkipBits(1); (* skip '0' marker bit *)
  524. IF ~stream.HasMoreData() THEN
  525. hasMoreFrames := FALSE;
  526. RETURN -1;
  527. END;
  528. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  529. (* read extension data if present *)
  530. IF marker = SCExtension THEN
  531. IF ~MPEG2 THEN
  532. HALT(1234);
  533. END;
  534. stream.SkipBits(32);
  535. IF stream.ShowBits(4) # 8 THEN
  536. RETURN -1;
  537. ELSE
  538. stream.SkipBits(4);
  539. END;
  540. IF ~reader.ReadPictureCodingExtension(picExt, mvinfos) THEN RETURN -1 END;
  541. IF reader.eof THEN hasMoreFrames := FALSE; RETURN 0 END;
  542. IF picExt.framePredFrameDct THEN frameMotionType := FMTFrame END;
  543. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  544. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  545. ELSIF MPEG2 THEN
  546. (* MPEG-2 requires a picture extension ! *)
  547. KernelLog.String("MPEG-2 picture extension not found"); KernelLog.Ln;
  548. HALT(1234);
  549. END;
  550. (* read user data if present *)
  551. IF marker = SCUserData THEN
  552. stream.SkipBits(32);
  553. WHILE stream.ShowBits(24) # 1 DO
  554. stream.SkipBits(8);
  555. END;
  556. IF ~GotoNextMarker(stream, marker) THEN RETURN -1 END;
  557. END;
  558. (* now we are really ready to decode the picture *)
  559. IF (picType = 1) OR (picType = 2) OR (picType = 3) THEN
  560. REPEAT
  561. (* Skip Slice *)
  562. stream.SkipBits(32);
  563. WHILE stream.ShowBits(24) # 1 DO
  564. stream.SkipBits(8);
  565. END;
  566. nextCode := stream.ShowBits(32);
  567. UNTIL ~(nextCode > 100H) & (nextCode <= 1AFH);
  568. ELSIF picType = 4 THEN
  569. (* D-Picture *)
  570. RETURN -1; (* D-Pictures not supported *)
  571. ELSE
  572. (* illegal or reserved value *)
  573. RETURN -1;
  574. END;
  575. IF tempRef > frameNr THEN
  576. (* dont display the frame yet - it is a future reference for upcoming B-Pics *)
  577. tmpFrame := nextRef;
  578. nextRef := curFrame;
  579. curFrame := tmpFrame;
  580. END;
  581. UNTIL tempRef <= frameNr;
  582. END;
  583. (* now we are sure that the correct frame is in the curFrame buffer *)
  584. (* store I- and P-Pictures as prediction for further pics *)
  585. IF (curFrame.picType = 1) OR (curFrame.picType = 2) THEN
  586. tmpFrame := prevRef;
  587. prevRef := curFrame;
  588. curFrame := tmpFrame;
  589. nextFrameToRender := prevRef;
  590. ELSE
  591. nextFrameToRender := curFrame;
  592. END;
  593. RETURN picType;
  594. END SkipNext;
  595. (* Prepare the next frame *)
  596. PROCEDURE Next*;
  597. VAR
  598. marker: CHAR;
  599. picType: LONGINT; (* 1=I-, 2=P-, 3=B-, 4=D-Picture, other values are illegal *)
  600. tempRef: LONGINT; (* temporal reference *)
  601. res: BOOLEAN;
  602. nextCode: LONGINT;
  603. tmpFrame: Util.Frame; (* required to switch two frames *)
  604. BEGIN
  605. IF ~hasMoreFrames THEN RETURN END;
  606. INC(frameNr);
  607. INC(realFrameNr);
  608. INC(time, mspf);
  609. IF frameNr = nextRef.frameNr THEN
  610. (* we have already decoded this frame, just take it from the nextRef buffer *)
  611. tmpFrame := curFrame;
  612. curFrame := nextRef;
  613. nextRef := tmpFrame;
  614. ELSE
  615. (* decode one or two frames *)
  616. REPEAT
  617. mbAddress := -1;
  618. mbAddressLast := -1;
  619. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  620. WHILE marker # SCPicture DO
  621. IF marker = SCSequenceHeader THEN
  622. stream.SkipBits(32);
  623. IF ~ParseSequenceHeader() THEN
  624. hasMoreFrames := FALSE;
  625. RETURN END;
  626. ELSIF marker = SCGOP THEN
  627. stream.SkipBits(32);
  628. ReadTimecode; (* SMPTE Timecode *)
  629. stream.SkipBits(1); (* closed GOP -> if closed wipe out prev and next buffer (black) *)
  630. stream.SkipBits(1); (* broken link *)
  631. stream.SkipBits(5); (* not used, should be 0... *)
  632. (* temporal reference restarts at zero *)
  633. frameNr := 0;
  634. prevRef.frameNr := -1; (* make sure they are at most used as reference *)
  635. nextRef.frameNr := -1; (* make sure they are at most used as reference *)
  636. ELSIF marker = SCSequenceEnd THEN
  637. (* video sequence finished - there are no more frames to be decoded *)
  638. hasMoreFrames := FALSE;
  639. RETURN;
  640. ELSE
  641. KernelLog.String("Unexpected marker found: "); KernelLog.Hex(ORD(marker), -1); KernelLog.Ln;
  642. RETURN;
  643. END;
  644. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  645. END;
  646. (* parse picture header *)
  647. stream.SkipBits(32);
  648. tempRef := stream.GetBits(10); (* temporal reference *)
  649. curFrame.frameNr := tempRef;
  650. picType := stream.GetBits(3); (* the picture type (I, P, B or D) *)
  651. frametype := picType;
  652. curFrame.picType := picType;
  653. stream.SkipBits(16); (* vbv buffer delay -> not relevant for us *)
  654. IF tempRef < frameNr THEN
  655. frameNr := tempRef;
  656. END;
  657. IF (picType = 2) OR (picType = 3) THEN
  658. IF stream.ShowBits(1) = 1 THEN
  659. mvinfos.fullPel[mv1][forward] := TRUE;
  660. ELSE
  661. mvinfos.fullPel[mv1][forward] := FALSE;
  662. END;
  663. stream.SkipBits(1);
  664. mvinfos.fCode[mv1][forward] := stream.GetBits(3);
  665. mvinfos.rSize[mv1][forward] := mvinfos.fCode[mv1][forward] - 1;
  666. mvinfos.f[mv1][forward] := SYSTEM.VAL(LONGINT, {mvinfos.rSize[mv1][forward]}); (* 2 ^ rSize *)
  667. END;
  668. IF picType = 3 THEN
  669. IF stream.ShowBits(1) = 1 THEN
  670. mvinfos.fullPel[mv1][backward] := TRUE;
  671. ELSE
  672. mvinfos.fullPel[mv1][backward] := FALSE;
  673. END;
  674. stream.SkipBits(1);
  675. mvinfos.fCode[mv1][backward] := stream.GetBits(3);
  676. mvinfos.rSize[mv1][backward] := mvinfos.fCode[mv1][backward] - 1;
  677. mvinfos.f[mv1][backward] := SYSTEM.VAL(LONGINT, {mvinfos.rSize[mv1][backward]}); (* 2 ^ rSize *)
  678. END;
  679. WHILE stream.ShowBits(1) = 1 DO
  680. stream.SkipBits(1); (* extra information follows *)
  681. stream.SkipBits(8); (* undefined by the standard *)
  682. END;
  683. stream.SkipBits(1); (* skip '0' marker bit *)
  684. IF ~stream.HasMoreData() OR reader.eof THEN
  685. hasMoreFrames := FALSE;
  686. RETURN;
  687. END;
  688. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  689. (* read extension data if present *)
  690. IF marker = SCExtension THEN
  691. IF ~MPEG2 THEN
  692. HALT(1234);
  693. END;
  694. stream.SkipBits(32);
  695. IF stream.ShowBits(4) # 8 THEN
  696. RETURN;
  697. ELSE
  698. stream.SkipBits(4);
  699. END;
  700. IF ~reader.ReadPictureCodingExtension(picExt, mvinfos) THEN RETURN END;
  701. IF reader.eof THEN hasMoreFrames := FALSE; RETURN END;
  702. IF picExt.framePredFrameDct THEN frameMotionType := FMTFrame END;
  703. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  704. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  705. ELSIF MPEG2 THEN
  706. (* MPEG-2 requires a picture extension ! *)
  707. KernelLog.String("MPEG-2 picture extension not found"); KernelLog.Ln;
  708. HALT(1234);
  709. END;
  710. (* read user data if present *)
  711. IF marker = SCUserData THEN
  712. stream.SkipBits(32);
  713. WHILE stream.ShowBits(24) # 1 DO
  714. stream.SkipBits(8);
  715. END;
  716. IF ~GotoNextMarker(stream, marker) THEN RETURN END;
  717. END;
  718. (* now we are really ready to decode the picture *)
  719. IF (picType = 1) OR (picType = 2) OR (picType = 3) THEN
  720. REPEAT
  721. res := DecodeSlice(picType);
  722. IF ~res THEN hasMoreFrames := FALSE; RETURN END;
  723. nextCode := stream.ShowBits(32);
  724. UNTIL ~(res & (nextCode > 100H) & (nextCode <= 1AFH));
  725. ELSIF picType = 4 THEN
  726. (* D-Picture *)
  727. RETURN; (* D-Pictures not supported *)
  728. ELSE
  729. (* illegal or reserved value *)
  730. RETURN;
  731. END;
  732. IF tempRef > frameNr THEN
  733. (* dont display the frame yet - it is a future reference for upcoming B-Pics *)
  734. tmpFrame := nextRef;
  735. nextRef := curFrame;
  736. curFrame := tmpFrame;
  737. END;
  738. UNTIL tempRef <= frameNr;
  739. END;
  740. (* now we are sure that the correct frame is in the curFrame buffer *)
  741. (* store I- and P-Pictures as prediction for further pics *)
  742. IF (curFrame.picType = 1) OR (curFrame.picType = 2) THEN
  743. tmpFrame := prevRef;
  744. prevRef := curFrame;
  745. curFrame := tmpFrame;
  746. nextFrameToRender := prevRef;
  747. ELSE
  748. nextFrameToRender := curFrame;
  749. END;
  750. END Next;
  751. (* Decode one slice. Precondition: stream is positioned at the beginning of a slice *)
  752. PROCEDURE DecodeSlice(type: LONGINT):BOOLEAN;
  753. VAR
  754. quantScale: LONGINT;
  755. marker: CHAR;
  756. BEGIN
  757. (* re-init DC prediction *)
  758. IF MPEG2 THEN
  759. dcY := MPEGTables.DCP[picExt.dcPrecision];
  760. dcCb := MPEGTables.DCP[picExt.dcPrecision];
  761. dcCr := MPEGTables.DCP[picExt.dcPrecision];
  762. ELSE
  763. dcY := 8 * 128;
  764. dcCb := 8 * 128;
  765. dcCr := 8 * 128;
  766. END;
  767. (* re-init motion vector prediction *)
  768. mvinfos.pmv[mv1][forward][horizontal] := 0;
  769. mvinfos.pmv[mv1][forward][vertical] := 0;
  770. mvinfos.pmv[mv1][backward][horizontal] := 0;
  771. mvinfos.pmv[mv1][backward][vertical] := 0;
  772. mvinfos.pmv[mv2][forward][horizontal] := 0;
  773. mvinfos.pmv[mv2][forward][vertical] := 0;
  774. mvinfos.pmv[mv2][backward][horizontal] := 0;
  775. mvinfos.pmv[mv2][backward][vertical] := 0;
  776. mvinfos.motionVerticalFieldSelect[mv1][forward] := FALSE;
  777. mvinfos.motionVerticalFieldSelect[mv1][backward] := FALSE;
  778. mvinfos.motionVerticalFieldSelect[mv2][forward] := TRUE;
  779. mvinfos.motionVerticalFieldSelect[mv2][backward] := TRUE;
  780. macroblockNr := 0;
  781. stream.SkipBits(24);
  782. mbAddress := ((stream.GetBits(8)-1) * videoWidthDiv16) - 1;
  783. mbAddressLast := mbAddress;
  784. quantScale := stream.GetBits(5);
  785. IF quantScale < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  786. IF MPEG2 THEN
  787. (* translate qscalecode to qscale *)
  788. IF picExt.qScaleType THEN
  789. (* take from table 1 *)
  790. quantScale := MPEGTables.QS1[quantScale];
  791. ELSE
  792. (* take from table 0 *)
  793. quantScale := MPEGTables.QS0[quantScale];
  794. END;
  795. END;
  796. (* extra slice information, not yet defined by the standard *)
  797. WHILE stream.ShowBits(1) = 1 DO
  798. stream.SkipBits(9);
  799. END;
  800. stream.SkipBits(1);
  801. (* decode all macroblocks in this slice *)
  802. WHILE stream.ShowBits(23) # 0 DO
  803. IF ~DecodeMacroBlock(type, quantScale) THEN hasMoreFrames := FALSE; RETURN FALSE END;
  804. END;
  805. RETURN GotoNextMarker(stream, marker);
  806. END DecodeSlice;
  807. (* Decode one macroblock *)
  808. PROCEDURE DecodeMacroBlock(type: LONGINT; VAR quantScale: LONGINT):BOOLEAN;
  809. VAR
  810. tmp: LONGINT;
  811. cbp: LONGINT;
  812. cbpBits: LONGINT;
  813. mbIntra, mbPattern, mbMotionBack, mbMotionForw, mbQuant: BOOLEAN;
  814. i: LONGINT;
  815. offsetX, offsetY, offsetXDiv2, offsetYDiv2: LONGINT;
  816. first: BOOLEAN; (* whether or not a block is the first one coded in a macroblock *)
  817. fpmf, fpmb: LONGINT; (* full pel multiplier forward & backward *)
  818. yoffs, yincr: LONGINT; (* parameters for CopyBlock - different for interlaced/non-interlaced blocks *)
  819. BEGIN
  820. INC(macroblockNr);
  821. (* skip stuffing *)
  822. WHILE stream.ShowBits(11) = 15 DO
  823. stream.SkipBits(11);
  824. END;
  825. (* read the macroblock address *)
  826. WHILE stream.ShowBits(11) = 8 DO
  827. stream.SkipBits(11);
  828. INC(mbAddress, 33);
  829. END;
  830. tmp := reader.ReadAddressIncrement();
  831. IF reader.eof THEN hasMoreFrames := FALSE END;
  832. IF tmp # -1 THEN
  833. INC(mbAddress, tmp);
  834. ELSE
  835. RETURN FALSE;
  836. END;
  837. mbSkipped := (mbAddress - mbAddressLast) > 1;
  838. (* fill in prediction for all skipped macroblocks *)
  839. IF mbSkipped THEN
  840. CASE type OF
  841. 1: (* I-Frame *)
  842. (* I-Frames are not allowed to skip MBs *)
  843. HALT(1234);
  844. | 2: (* P-Frame *)
  845. FOR i := mbAddressLast + 1 TO (mbAddress - 1) DO
  846. (* motion vector reset to zero, just copy prediction *)
  847. InsertPrediction(TRUE, FALSE, i, 0, 0, 0, 0);
  848. END;
  849. | 3: (* B-Frame *)
  850. IF mvinfos.fullPel[mv1][forward] THEN
  851. fpmf := 2;
  852. ELSE
  853. fpmf := 1;
  854. END;
  855. IF mvinfos.fullPel[mv1][backward] THEN
  856. fpmb := 2;
  857. ELSE
  858. fpmb := 1;
  859. END;
  860. FOR i := mbAddressLast + 1 TO (mbAddress - 1) DO
  861. (* use motion vector and prediction type (forward, backward, both) from last mb *)
  862. InsertPrediction(
  863. mbMotionForwOld,
  864. mbMotionBackOld,
  865. i,
  866. mvinfos.mv[mv1][forward][horizontal] * fpmf,
  867. mvinfos.mv[mv1][forward][vertical] * fpmf,
  868. mvinfos.mv[mv1][backward][horizontal] * fpmb,
  869. mvinfos.mv[mv1][backward][vertical] * fpmb);
  870. END;
  871. END;
  872. END;
  873. (* read macroblock type *)
  874. IF ~reader.ReadMacroBlockType(type, mbIntra, mbPattern, mbMotionBack, mbMotionForw, mbQuant) THEN
  875. RETURN FALSE;
  876. END;
  877. IF reader.eof THEN
  878. RETURN FALSE;
  879. END;
  880. IF MPEG2 THEN
  881. (* read additional macroblock info *)
  882. IF mbMotionForw OR mbMotionBack THEN
  883. IF picExt.picStructure = PicStructFrame THEN
  884. IF ~picExt.framePredFrameDct THEN
  885. frameMotionType := stream.GetBits(2);
  886. END;
  887. ELSE
  888. (* read field motion type -> interlaced video not supported atm *)
  889. HALT(1234);
  890. END;
  891. END;
  892. IF (picExt.picStructure = PicStructFrame) & (~picExt.framePredFrameDct) & (mbIntra OR mbPattern) THEN
  893. dctType := (stream.GetBits(1) = 1);
  894. ELSE
  895. dctType := FALSE;
  896. END;
  897. END;
  898. (* concealment vectors in MPEG-2 -> not supported atm *)
  899. IF picExt.concealmentMV THEN
  900. HALT(1234);
  901. END;
  902. (* reset motion prediction if required *)
  903. IF mbIntraOld OR
  904. ((type = 2) & mbSkipped) OR
  905. ((type = 2) & ~mbMotionForw) THEN
  906. mvinfos.pmv[0][0][0] := 0;
  907. mvinfos.pmv[0][0][1] := 0;
  908. mvinfos.pmv[0][1][0] := 0;
  909. mvinfos.pmv[0][1][1] := 0;
  910. mvinfos.pmv[1][0][0] := 0;
  911. mvinfos.pmv[1][0][1] := 0;
  912. mvinfos.pmv[1][1][0] := 0;
  913. mvinfos.pmv[1][1][1] := 0;
  914. mvinfos.mv[0][0][0] := 0;
  915. mvinfos.mv[0][0][1] := 0;
  916. mvinfos.mv[0][1][0] := 0;
  917. mvinfos.mv[0][1][1] := 0;
  918. mvinfos.mv[1][0][0] := 0;
  919. mvinfos.mv[1][0][1] := 0;
  920. mvinfos.mv[1][1][0] := 0;
  921. mvinfos.mv[1][1][1] := 0;
  922. mvinfos.motionVerticalFieldSelect[mv1][forward] := FALSE;
  923. mvinfos.motionVerticalFieldSelect[mv1][backward] := FALSE;
  924. mvinfos.motionVerticalFieldSelect[mv2][forward] := TRUE;
  925. mvinfos.motionVerticalFieldSelect[mv2][backward] := TRUE;
  926. END;
  927. IF ~stream.HasMoreData() THEN
  928. hasMoreFrames := FALSE;
  929. RETURN FALSE;
  930. END;
  931. (* read new quantizer scale *)
  932. IF mbQuant THEN
  933. quantScale := stream.GetBits(5);
  934. IF quantScale < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  935. IF MPEG2 THEN
  936. (* translate qscalecode to qscale *)
  937. IF picExt.qScaleType THEN
  938. (* take from table 1 *)
  939. quantScale := MPEGTables.QS1[quantScale];
  940. ELSE
  941. (* take from table 0 *)
  942. quantScale := MPEGTables.QS0[quantScale];
  943. END;
  944. END;
  945. END;
  946. (* read forward motion vector *)
  947. IF mbMotionForw OR (MPEG2 & mbIntra & picExt.concealmentMV) THEN
  948. IF ~MPEG2 THEN
  949. mvinfos.motionCode[mv1][forward][horizontal] := reader.ReadMotionCode();
  950. IF (mvinfos.fCode[mv1][forward] # 1) & (mvinfos.motionCode[mv1][forward][horizontal] # 0) THEN
  951. mvinfos.motionResidual[mv1][forward][horizontal] := stream.GetBits(mvinfos.fCode[mv1][forward]-1);
  952. END;
  953. mvinfos.motionCode[mv1][forward][vertical] := reader.ReadMotionCode();
  954. IF (mvinfos.fCode[mv1][forward] # 1) & (mvinfos.motionCode[mv1][forward][vertical] # 0) THEN
  955. mvinfos.motionResidual[mv1][forward][vertical] := stream.GetBits(mvinfos.fCode[mv1][forward]-1);
  956. END;
  957. ELSE
  958. (* MPEG-2 *)
  959. reader.ReadMotionVectors(0, mvinfos, frameMotionType);
  960. END;
  961. END;
  962. (* read backward motion vector *)
  963. IF mbMotionBack OR (MPEG2 & mbIntra & picExt.concealmentMV) THEN
  964. IF ~MPEG2 THEN
  965. mvinfos.motionCode[mv1][backward][horizontal] := reader.ReadMotionCode();
  966. IF (mvinfos.fCode[mv1][backward] # 1) & (mvinfos.motionCode[mv1][backward][horizontal] # 0) THEN
  967. mvinfos.motionResidual[mv1][backward][horizontal] := stream.GetBits(mvinfos.fCode[mv1][backward]-1);
  968. END;
  969. mvinfos.motionCode[mv1][backward][vertical] := reader.ReadMotionCode();
  970. IF (mvinfos.fCode[mv1][backward] # 1) & (mvinfos.motionCode[mv1][backward][vertical] # 0) THEN
  971. mvinfos.motionResidual[mv1][backward][vertical] := stream.GetBits(mvinfos.fCode[mv1][backward]-1);
  972. END;
  973. ELSE
  974. (* MPEG-2 *)
  975. reader.ReadMotionVectors(1, mvinfos, frameMotionType);
  976. END;
  977. END;
  978. IF reader.eof OR ~stream.HasMoreData() THEN
  979. hasMoreFrames := FALSE;
  980. RETURN FALSE;
  981. END;
  982. (* read pattern of coded blocks (CBP) *)
  983. IF mbPattern THEN
  984. IF stream.ShowBits(3) = 0 THEN
  985. (* code is 8 or 9 bits long, use table CBP9 *)
  986. cbpBits := stream.ShowBits(9);
  987. cbp := MPEGTables.CBP9[cbpBits][0];
  988. stream.SkipBits(MPEGTables.CBP9[cbpBits][1]);
  989. ELSE
  990. (* code is at most 7 bits long, use table CBP7 *)
  991. cbpBits := stream.ShowBits(7)-16;
  992. cbp := MPEGTables.CBP7[cbpBits][0];
  993. stream.SkipBits(MPEGTables.CBP7[cbpBits][1]);
  994. END;
  995. ELSE
  996. IF mbIntra THEN
  997. (* intra-blocks: all blocks are coded *)
  998. cbp := 63;
  999. ELSE
  1000. (* inter-block: no blocks are coded if no pattern is specified *)
  1001. cbp := 0;
  1002. END;
  1003. END;
  1004. (* calculate motion vectors *)
  1005. IF ~MPEG2 THEN
  1006. IF mbMotionForw THEN
  1007. MotionDisplacement(forward, horizontal);
  1008. MotionDisplacement(forward, vertical);
  1009. END;
  1010. IF mbMotionBack THEN
  1011. MotionDisplacement(backward, horizontal);
  1012. MotionDisplacement(backward, vertical);
  1013. END;
  1014. ELSE
  1015. (* MPEG-2 *)
  1016. (* decode all required motion vectors *)
  1017. IF mbMotionForw THEN
  1018. DecodeMotionVectors(mv1, forward, horizontal);
  1019. DecodeMotionVectors(mv1, forward, vertical);
  1020. END;
  1021. IF mbMotionBack THEN
  1022. DecodeMotionVectors(mv1, backward, horizontal);
  1023. DecodeMotionVectors(mv1, backward, vertical);
  1024. END;
  1025. IF frameMotionType = FMTField THEN
  1026. (* decode second pair of motion vectors *)
  1027. IF mbMotionForw THEN
  1028. DecodeMotionVectors(mv2, forward, horizontal);
  1029. DecodeMotionVectors(mv2, forward, vertical);
  1030. END;
  1031. IF mbMotionBack THEN
  1032. DecodeMotionVectors(mv2, backward, horizontal);
  1033. DecodeMotionVectors(mv2, backward, vertical);
  1034. END;
  1035. END;
  1036. (* adjust predictions of non-used MVs *)
  1037. IF frameMotionType = FMTFrame THEN
  1038. IF mbMotionForw THEN
  1039. mvinfos.pmv[mv2][forward][horizontal] := mvinfos.pmv[mv1][forward][horizontal];
  1040. mvinfos.pmv[mv2][forward][vertical] := mvinfos.pmv[mv1][forward][vertical];
  1041. END;
  1042. IF mbMotionBack THEN
  1043. mvinfos.pmv[mv2][backward][horizontal] := mvinfos.pmv[mv1][backward][horizontal];
  1044. mvinfos.pmv[mv2][backward][vertical] := mvinfos.pmv[mv1][backward][vertical];
  1045. END;
  1046. END;
  1047. END;
  1048. IF MPEG2 THEN
  1049. mvinfos.fullPel[mv1][forward] := FALSE;
  1050. mvinfos.fullPel[mv1][backward] := FALSE;
  1051. END;
  1052. IF (type # 1) & ~mbIntra THEN
  1053. (* P- or B-Frame *)
  1054. IF frameMotionType = FMTField THEN
  1055. (* MPEG2 interlaced block *)
  1056. InsertInterlacedPrediction(
  1057. (type = 2) OR ((type = 3) & mbMotionForw),
  1058. mbMotionBack,
  1059. mbAddress,
  1060. mvinfos);
  1061. ELSE
  1062. (* MPEG1 or MPEG2 *)
  1063. IF mvinfos.fullPel[mv1][forward] THEN
  1064. fpmf := 2;
  1065. ELSE
  1066. fpmf := 1;
  1067. END;
  1068. IF mvinfos.fullPel[mv1][backward] THEN
  1069. fpmb := 2;
  1070. ELSE
  1071. fpmb := 1;
  1072. END;
  1073. InsertPrediction(
  1074. (type = 2) OR ((type = 3) & mbMotionForw),
  1075. mbMotionBack,
  1076. mbAddress,
  1077. mvinfos.mv[mv1][forward][horizontal] * fpmf,
  1078. mvinfos.mv[mv1][forward][vertical] * fpmf,
  1079. mvinfos.mv[mv1][backward][horizontal] * fpmb,
  1080. mvinfos.mv[mv1][backward][vertical] * fpmb);
  1081. END;
  1082. END;
  1083. (* calculate offset of the macroblock in the current frame *)
  1084. offsetX := (mbAddress MOD (videoWidthDiv16)) * 16;
  1085. offsetY := (mbAddress DIV (videoWidthDiv16)) * 16;
  1086. offsetXDiv2 := offsetX DIV 2;
  1087. offsetYDiv2 := offsetY DIV 2;
  1088. (* decode all coded blocks *)
  1089. IF ~MPEG2 THEN
  1090. first := TRUE;
  1091. (* Y0 *)
  1092. IF 5 IN SYSTEM.VAL(SET, cbp) THEN
  1093. IF ~DecodeBlock(0, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1094. IF mbIntra THEN
  1095. blocks.TransferIDCTCopy(block, curFrame.buffer, offsetY*videoWidth + offsetX, videoWidth);
  1096. ELSE
  1097. blocks.TransferIDCTAdd(block, curFrame.buffer, offsetY*videoWidth + offsetX, videoWidth);
  1098. END;
  1099. first := FALSE;
  1100. END;
  1101. (* Y1 *)
  1102. IF 4 IN SYSTEM.VAL(SET, cbp) THEN
  1103. IF ~DecodeBlock(1, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1104. IF mbIntra THEN
  1105. blocks.TransferIDCTCopy(block, curFrame.buffer, offsetY*videoWidth + offsetX + 8, videoWidth);
  1106. ELSE
  1107. blocks.TransferIDCTAdd(block, curFrame.buffer, offsetY*videoWidth + offsetX + 8, videoWidth);
  1108. END;
  1109. first := FALSE;
  1110. END;
  1111. (* Y2 *)
  1112. IF 3 IN SYSTEM.VAL(SET, cbp) THEN
  1113. IF ~DecodeBlock(2, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1114. IF mbIntra THEN
  1115. blocks.TransferIDCTCopy(block, curFrame.buffer, (offsetY+8)*videoWidth + offsetX, videoWidth);
  1116. ELSE
  1117. blocks.TransferIDCTAdd(block, curFrame.buffer, (offsetY+8)*videoWidth + offsetX, videoWidth);
  1118. END;
  1119. first := FALSE;
  1120. END;
  1121. (* Y3 *)
  1122. IF 2 IN SYSTEM.VAL(SET, cbp) THEN
  1123. IF ~DecodeBlock(3, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1124. IF mbIntra THEN
  1125. blocks.TransferIDCTCopy(block, curFrame.buffer, (offsetY+8)*videoWidth + offsetX+8, videoWidth);
  1126. ELSE
  1127. blocks.TransferIDCTAdd(block, curFrame.buffer, (offsetY+8)*videoWidth + offsetX+8, videoWidth);
  1128. END;
  1129. first := FALSE;
  1130. END;
  1131. (* Cb *)
  1132. IF 1 IN SYSTEM.VAL(SET, cbp) THEN
  1133. IF ~DecodeBlock(4, block, mbIntra, quantScale, TRUE, type) THEN RETURN FALSE END;
  1134. IF mbIntra THEN
  1135. blocks.TransferIDCTCopy(block, curFrame.buffer, videoWidth*videoHeight + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1136. ELSE
  1137. blocks.TransferIDCTAdd(block, curFrame.buffer, videoWidth*videoHeight + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1138. END;
  1139. END;
  1140. (* Cr *)
  1141. IF 0 IN SYSTEM.VAL(SET, cbp) THEN
  1142. IF ~DecodeBlock(5, block, mbIntra, quantScale, TRUE, type) THEN RETURN FALSE END;
  1143. IF mbIntra THEN
  1144. blocks.TransferIDCTCopy(block, curFrame.buffer, videoWidth*videoHeight + videoWidthDiv2*videoHeightDiv2 + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1145. ELSE
  1146. blocks.TransferIDCTAdd(block, curFrame.buffer, videoWidth*videoHeight + videoWidthDiv2*videoHeightDiv2 + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1147. END;
  1148. END;
  1149. ELSE
  1150. (* MPEG-2 *)
  1151. IF dctType THEN
  1152. (* interlaced block *)
  1153. yincr := 2;
  1154. yoffs := 1;
  1155. ELSE
  1156. (* progressive block *)
  1157. yincr := 1;
  1158. yoffs := 8;
  1159. END;
  1160. first := TRUE;
  1161. (* Y0 *)
  1162. IF 5 IN SYSTEM.VAL(SET, cbp) THEN
  1163. IF ~DecodeBlock2(0, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1164. IF mbIntra THEN
  1165. blocks.TransferIDCTCopy(block, curFrame.buffer, offsetY*videoWidth + offsetX, videoWidth * yincr);
  1166. ELSE
  1167. blocks.TransferIDCTAdd(block, curFrame.buffer, offsetY*videoWidth + offsetX, videoWidth * yincr);
  1168. END;
  1169. first := FALSE;
  1170. END;
  1171. (* Y1 *)
  1172. IF 4 IN SYSTEM.VAL(SET, cbp) THEN
  1173. IF ~DecodeBlock2(1, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1174. IF mbIntra THEN
  1175. blocks.TransferIDCTCopy(block, curFrame.buffer, offsetY*videoWidth + offsetX + 8, videoWidth * yincr);
  1176. ELSE
  1177. blocks.TransferIDCTAdd(block, curFrame.buffer, offsetY*videoWidth + offsetX + 8, videoWidth * yincr);
  1178. END;
  1179. first := FALSE;
  1180. END;
  1181. (* Y2 *)
  1182. IF 3 IN SYSTEM.VAL(SET, cbp) THEN
  1183. IF ~DecodeBlock2(2, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1184. IF mbIntra THEN
  1185. blocks.TransferIDCTCopy(block, curFrame.buffer, (offsetY+yoffs)*videoWidth + offsetX, videoWidth * yincr);
  1186. ELSE
  1187. blocks.TransferIDCTAdd(block, curFrame.buffer, (offsetY+yoffs)*videoWidth + offsetX, videoWidth * yincr);
  1188. END;
  1189. first := FALSE;
  1190. END;
  1191. (* Y3 *)
  1192. IF 2 IN SYSTEM.VAL(SET, cbp) THEN
  1193. IF ~DecodeBlock2(3, block, mbIntra, quantScale, first, type) THEN RETURN FALSE END;
  1194. IF mbIntra THEN
  1195. blocks.TransferIDCTCopy(block, curFrame.buffer, (offsetY+yoffs)*videoWidth + offsetX + 8, videoWidth * yincr);
  1196. ELSE
  1197. blocks.TransferIDCTAdd(block, curFrame.buffer, (offsetY+yoffs)*videoWidth + offsetX + 8, videoWidth * yincr);
  1198. END;
  1199. END;
  1200. (* Cb *)
  1201. IF 1 IN SYSTEM.VAL(SET, cbp) THEN
  1202. IF ~DecodeBlock2(4, block, mbIntra, quantScale, TRUE, type) THEN RETURN FALSE END;
  1203. IF mbIntra THEN
  1204. blocks.TransferIDCTCopy(block, curFrame.buffer, videoWidth*videoHeight + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1205. ELSE
  1206. blocks.TransferIDCTAdd(block, curFrame.buffer, videoWidth*videoHeight + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1207. END;
  1208. END;
  1209. IF 0 IN SYSTEM.VAL(SET, cbp) THEN
  1210. IF ~DecodeBlock2(5, block, mbIntra, quantScale, TRUE, type) THEN RETURN FALSE END;
  1211. IF mbIntra THEN
  1212. blocks.TransferIDCTCopy(block, curFrame.buffer, videoWidth*videoHeight + videoWidthDiv2*videoHeightDiv2 + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1213. ELSE
  1214. blocks.TransferIDCTAdd(block, curFrame.buffer, videoWidth*videoHeight + videoWidthDiv2*videoHeightDiv2 + offsetYDiv2*videoWidthDiv2 + offsetXDiv2, videoWidthDiv2);
  1215. END;
  1216. END;
  1217. END;
  1218. (* skip "end of macroblock"-bit of a D-Picture *)
  1219. IF type = 4 THEN
  1220. IF stream.ShowBits(1) # 1 THEN
  1221. RETURN FALSE;
  1222. ELSE
  1223. stream.SkipBits(1);
  1224. END;
  1225. END;
  1226. mbMotionForwOld := mbMotionForw;
  1227. mbMotionBackOld := mbMotionBack;
  1228. mbIntraOld := mbIntra;
  1229. mbAddressLast := mbAddress;
  1230. IF mbIntra THEN
  1231. mbAddressLastIntra := mbAddress;
  1232. END;
  1233. RETURN TRUE;
  1234. END DecodeMacroBlock;
  1235. PROCEDURE InsertInterlacedPrediction(forw, back: BOOLEAN; address: LONGINT; VAR mvi: Util.MotionVectorInfos);
  1236. VAR
  1237. yOffs, cbOffs, crOffs: LONGINT; (* offsets in the Frame.buffer array *)
  1238. mvfx1, mvfy1, mvbx1, mvby1: LONGINT; (* luminance motion vectors, first set *)
  1239. mvfx2, mvfy2, mvbx2, mvby2: LONGINT; (* luminance motion vectors, second set *)
  1240. mvfx1c, mvfy1c, mvbx1c, mvby1c: LONGINT; (* chrominance motion vectors, first set *)
  1241. mvfx2c, mvfy2c, mvbx2c, mvby2c: LONGINT; (* chrominance motion vectors, second set *)
  1242. BEGIN
  1243. (* calculate position of the destination macroblock *)
  1244. yOffs := (address DIV videoWidthDiv16) * videoWidth * 16 + (address MOD videoWidthDiv16) * 16;
  1245. cbOffs := videoWidth * videoHeight + (address DIV videoWidthDiv16) * videoWidthDiv2 * 8 + (address MOD videoWidthDiv16) * 8;
  1246. crOffs := cbOffs + videoHeightDiv2 * videoWidthDiv2;
  1247. (* set motion vectors (vertical components are field-based, so they are handled differently) *)
  1248. mvfx1 := mvi.mv[mv1][forward][horizontal];
  1249. mvfy1 := mvi.mv[mv1][forward][vertical];
  1250. mvbx1 := mvi.mv[mv1][backward][horizontal];
  1251. mvby1 := mvi.mv[mv1][backward][vertical];
  1252. mvfx2 := mvi.mv[mv2][forward][horizontal];
  1253. mvfy2 := mvi.mv[mv2][forward][vertical];
  1254. mvbx2 := mvi.mv[mv2][backward][horizontal];
  1255. mvby2 := mvi.mv[mv2][backward][vertical];
  1256. mvfx1c := mvfx1 DIV 2;
  1257. mvfy1c := mvfy1 DIV 2;
  1258. mvbx1c := mvbx1 DIV 2;
  1259. mvby1c := mvby1 DIV 2;
  1260. mvfx2c := mvfx2 DIV 2;
  1261. mvfy2c := mvfy2 DIV 2;
  1262. mvbx2c := mvbx2 DIV 2;
  1263. mvby2c := mvby2 DIV 2;
  1264. IF mvi.motionVerticalFieldSelect[mv1][forward] THEN INC(mvfy1); INC(mvfy1c) END;
  1265. IF mvi.motionVerticalFieldSelect[mv1][backward] THEN INC(mvby1); INC(mvby1c) END;
  1266. IF ~mvi.motionVerticalFieldSelect[mv2][forward] THEN DEC(mvfy2); DEC(mvfy2c) END;
  1267. IF ~mvi.motionVerticalFieldSelect[mv2][backward] THEN DEC(mvby2); DEC(mvby2c) END;
  1268. IF forw THEN
  1269. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs, mvfx1, mvfy1, 2*videoWidth, 2*videoWidth, 8);
  1270. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs+8, mvfx1, mvfy1, 2*videoWidth, 2*videoWidth, 8);
  1271. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs+videoWidth, mvfx2, mvfy2, 2*videoWidth, 2*videoWidth, 8);
  1272. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs+videoWidth+8, mvfx2, mvfy2, 2*videoWidth, 2*videoWidth, 8);
  1273. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, cbOffs, mvfx1c, mvfy1c, videoWidth, videoWidth, 4);
  1274. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, cbOffs+videoWidthDiv2, mvfx2c, mvfy2c, videoWidth, videoWidth, 4);
  1275. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, crOffs, mvfx1c, mvfy1c, videoWidth, videoWidth, 4);
  1276. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, crOffs+videoWidthDiv2, mvfx2c, mvfy2c, videoWidth, videoWidth, 4);
  1277. END;
  1278. IF back THEN
  1279. IF forw THEN
  1280. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs, mvbx1, mvby1, 2*videoWidth, 2*videoWidth, 8);
  1281. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs+8, mvbx1, mvby1, 2*videoWidth, 2*videoWidth, 8);
  1282. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs+videoWidth, mvbx2, mvby2, 2*videoWidth, 2*videoWidth, 8);
  1283. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs+videoWidth+8, mvbx2, mvby2, 2*videoWidth, 2*videoWidth, 8);
  1284. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, cbOffs, mvbx1c, mvby1c, videoWidth, videoWidth, 4);
  1285. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, cbOffs+videoWidthDiv2, mvbx2c, mvby2c, videoWidth, videoWidth, 4);
  1286. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, crOffs, mvbx1c, mvby1c, videoWidth, videoWidth, 4);
  1287. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, crOffs+videoWidthDiv2, mvbx2c, mvby2c, videoWidth, videoWidth, 4);
  1288. ELSE
  1289. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs, mvbx1, mvby1, 2*videoWidth, 2*videoWidth, 8);
  1290. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs+8, mvbx1, mvby1, 2*videoWidth, 2*videoWidth, 8);
  1291. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs+videoWidth, mvbx2, mvby2, 2*videoWidth, 2*videoWidth, 8);
  1292. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs+videoWidth+8, mvbx2, mvby2, 2*videoWidth, 2*videoWidth, 8);
  1293. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, cbOffs, mvbx1c, mvby1c, videoWidth, videoWidth, 4);
  1294. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, cbOffs+videoWidthDiv2, mvbx2c, mvby2c, videoWidth, videoWidth, 4);
  1295. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, crOffs, mvbx1c, mvby1c, videoWidth, videoWidth, 4);
  1296. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, crOffs+videoWidthDiv2, mvbx2c, mvby2c, videoWidth, videoWidth, 4);
  1297. END;
  1298. END;
  1299. END InsertInterlacedPrediction;
  1300. (* copy the prediction into a macroblock *)
  1301. (* param names (capitals): MotionVector, Forward, Backward *)
  1302. PROCEDURE InsertPrediction(forward, backward: BOOLEAN; address, mvfx, mvfy, mvbx, mvby: LONGINT);
  1303. VAR
  1304. yOffs, cbOffs, crOffs: LONGINT; (* offsets in the Frame.buffer array *)
  1305. BEGIN
  1306. (* calculate position of the destination macroblock *)
  1307. yOffs := (address DIV videoWidthDiv16) * videoWidth * 16 + (address MOD videoWidthDiv16) * 16;
  1308. cbOffs := videoWidth * videoHeight + (address DIV videoWidthDiv16) * videoWidthDiv2 * 8 + (address MOD videoWidthDiv16) * 8;
  1309. crOffs := cbOffs + videoHeightDiv2 * videoWidthDiv2;
  1310. IF forward THEN
  1311. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs, mvfx, mvfy, videoWidth, videoWidth, 16);
  1312. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, yOffs+8, mvfx, mvfy, videoWidth, videoWidth, 16);
  1313. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, cbOffs, mvfx DIV 2, mvfy DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1314. blocks.MoveBlockOverwrite(prevRef.buffer, curFrame.buffer, crOffs, mvfx DIV 2, mvfy DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1315. END;
  1316. IF backward THEN
  1317. IF forward THEN
  1318. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs, mvbx, mvby, videoWidth, videoWidth, 16);
  1319. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, yOffs+8, mvbx, mvby, videoWidth, videoWidth, 16);
  1320. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, cbOffs, mvbx DIV 2, mvby DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1321. blocks.MoveBlockInterp(nextRef.buffer, curFrame.buffer, crOffs, mvbx DIV 2, mvby DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1322. ELSE
  1323. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs, mvbx, mvby, videoWidth, videoWidth, 16);
  1324. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, yOffs+8, mvbx, mvby, videoWidth, videoWidth, 16);
  1325. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, cbOffs, mvbx DIV 2, mvby DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1326. blocks.MoveBlockOverwrite(nextRef.buffer, curFrame.buffer, crOffs, mvbx DIV 2, mvby DIV 2, videoWidthDiv2, videoWidthDiv2, 8);
  1327. END;
  1328. END;
  1329. END InsertPrediction;
  1330. PROCEDURE DecodeMotionVectors(r, s, t: LONGINT);
  1331. VAR
  1332. rSize: LONGINT;
  1333. f: LONGINT;
  1334. high, low, range: LONGINT;
  1335. delta: LONGINT;
  1336. prediction: LONGINT;
  1337. DEBUG: BOOLEAN;
  1338. BEGIN
  1339. DEBUG := (realFrameNr = -1) & (mbAddress > 1155) & (mbAddress < 1159);
  1340. IF DEBUG THEN
  1341. KernelLog.String("Macroblock "); KernelLog.Int(mbAddress, 0); KernelLog.Ln;
  1342. KernelLog.String("+++ INPUT +++"); KernelLog.Ln;
  1343. mvinfos.Dump(r, s, t);
  1344. END;
  1345. rSize := mvinfos.fCode[s][t] - 1;
  1346. f := SYSTEM.VAL(LONGINT, {rSize}); (* 2 ^ rSize *)
  1347. high := 16 * f - 1;
  1348. low := (-16) * f ;
  1349. range := 32 * f;
  1350. IF (f = 1) OR (mvinfos.motionCode[r][s][t] = 0) THEN
  1351. delta := mvinfos.motionCode[r][s][t];
  1352. ELSE
  1353. IF mvinfos.motionCode[r][s][t] > 0 THEN
  1354. delta := (mvinfos.motionCode[r][s][t] - 1) * f + mvinfos.motionResidual[r][s][t] + 1;
  1355. ELSE
  1356. delta := - ((- mvinfos.motionCode[r][s][t] - 1) * f + mvinfos.motionResidual[r][s][t] + 1);
  1357. END;
  1358. END;
  1359. IF (frameMotionType # FMTFrame) & (t = 1) & (picExt.picStructure = PicStructFrame) THEN
  1360. prediction := mvinfos.pmv[r][s][t] DIV 2;
  1361. ELSE
  1362. prediction := mvinfos.pmv[r][s][t];
  1363. END;
  1364. mvinfos.mv[r][s][t] := prediction + delta;
  1365. IF mvinfos.mv[r][s][t] < low THEN
  1366. INC(mvinfos.mv[r][s][t], range);
  1367. ELSIF mvinfos.mv[r][s][t] > high THEN
  1368. DEC(mvinfos.mv[r][s][t], range);
  1369. END;
  1370. IF (frameMotionType # FMTFrame) & (t = 1) & (picExt.picStructure = PicStructFrame) THEN
  1371. mvinfos.pmv[r][s][t] := mvinfos.mv[r][s][t] * 2;
  1372. ELSE
  1373. mvinfos.pmv[r][s][t] := mvinfos.mv[r][s][t];
  1374. END;
  1375. END DecodeMotionVectors;
  1376. PROCEDURE MotionDisplacement(fb, hv: LONGINT);
  1377. VAR
  1378. delta: LONGINT;
  1379. range: LONGINT;
  1380. motionCode, motionResidual, f, prediction: LONGINT;
  1381. BEGIN
  1382. motionCode := mvinfos.motionCode[mv1][fb][hv];
  1383. motionResidual := mvinfos.motionResidual[mv1][fb][hv];
  1384. f := mvinfos.f[mv1][fb];
  1385. prediction := mvinfos.pmv[mv1][fb][hv];
  1386. IF (f = 1) OR (motionCode = 0) THEN
  1387. delta := motionCode;
  1388. ELSE
  1389. delta := 1 + f * (motionCode * Sign(motionCode) - 1) + motionResidual;
  1390. IF motionCode < 0 THEN
  1391. delta := -delta;
  1392. END;
  1393. END;
  1394. INC(prediction, delta);
  1395. range := f * 32;
  1396. IF prediction > (f * 16 - 1) THEN
  1397. DEC(prediction, range);
  1398. ELSIF prediction < -(f * 16) THEN
  1399. INC(prediction, range);
  1400. END;
  1401. mvinfos.mv[mv1][fb][hv] := prediction;
  1402. mvinfos.pmv[mv1][fb][hv] := prediction;
  1403. END MotionDisplacement;
  1404. (* MPEG-1 only !! *)
  1405. PROCEDURE DecodeBlock(
  1406. nr: SHORTINT;
  1407. coeffs: Util.PointerToArrayOfLONGINT;
  1408. intra: BOOLEAN;
  1409. VAR qScale: LONGINT;
  1410. first: BOOLEAN;
  1411. type: LONGINT): BOOLEAN;
  1412. VAR
  1413. bits: LONGINT;
  1414. size: LONGINT;
  1415. dcDiff: LONGINT;
  1416. tmp: LONGINT;
  1417. cur: LONGINT; (* current position in coeffs *)
  1418. dummy: BOOLEAN;
  1419. i: LONGINT;
  1420. intraSkipped: BOOLEAN;
  1421. BEGIN
  1422. FOR i := 0 TO 63 DO
  1423. coeffs[i] := 0;
  1424. END;
  1425. cur := 0;
  1426. IF intra THEN
  1427. (* read DC coefficient *)
  1428. bits := stream.ShowBits(3);
  1429. IF nr < 4 THEN
  1430. (* intra coded luminance block *)
  1431. IF bits = 7 THEN
  1432. stream.SkipBits(3);
  1433. size := 4;
  1434. WHILE stream.ShowBits(1) = 1 DO
  1435. INC(size);
  1436. stream.SkipBits(1);
  1437. END;
  1438. INC(size);
  1439. stream.SkipBits(1);
  1440. ELSE
  1441. size := MPEGTables.DCL3[bits][0];
  1442. stream.SkipBits(MPEGTables.DCL3[bits][1]);
  1443. END;
  1444. ELSE
  1445. (* intra coded chrominance block *)
  1446. IF bits = 7 THEN
  1447. stream.SkipBits(3);
  1448. size := 3;
  1449. WHILE stream.ShowBits(1) = 1 DO
  1450. INC(size);
  1451. stream.SkipBits(1);
  1452. END;
  1453. INC(size);
  1454. stream.SkipBits(1);
  1455. ELSE
  1456. size := MPEGTables.DCC3[bits][0];
  1457. stream.SkipBits(MPEGTables.DCC3[bits][1]);
  1458. END;
  1459. END;
  1460. IF size # 0 THEN
  1461. IF stream.ShowBits(1) = 0 THEN
  1462. (* negative difference: invert all bits and make number negative *)
  1463. tmp := stream.GetBits(size);
  1464. IF tmp < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1465. dcDiff := -(SYSTEM.VAL(INTEGER, ((-SYSTEM.VAL(SET, tmp)) * {0..(size-1)})));
  1466. ELSE
  1467. (* positive difference *)
  1468. dcDiff := stream.GetBits(size);
  1469. IF dcDiff < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1470. END;
  1471. END;
  1472. coeffs[0] := dcDiff;
  1473. cur := 1;
  1474. ELSE
  1475. (* read first DCT coefficient *)
  1476. IF stream.ShowBits(1) = 1 THEN
  1477. IF stream.ShowBits(2) = 2 THEN
  1478. coeffs[0] := 1;
  1479. ELSE
  1480. coeffs[0] := -1;
  1481. END;
  1482. stream.SkipBits(2);
  1483. INC(cur);
  1484. ELSE
  1485. dummy := reader.ReadRunLevelCode(coeffs, cur, MPEG2); (* cannot return FALSE! *)
  1486. IF reader.eof THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1487. END;
  1488. END;
  1489. (* MPEG-1 always uses first table. MPEG-2 chooses using the intraVlcFormat flag (for intra blocks only) *)
  1490. IF (~MPEG2) OR (~picExt.intraVlcFormat OR ~intra) THEN
  1491. WHILE ~reader.ReadRunLevelCode(coeffs, cur, MPEG2) DO END;
  1492. ELSE
  1493. WHILE ~reader.ReadRunLevelCode2(coeffs, cur) DO END;
  1494. END;
  1495. IF reader.eof THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1496. intraSkipped := (mbAddress - mbAddressLastIntra) > 1;
  1497. (* dequantize the coefficients *)
  1498. IF intra THEN
  1499. CASE nr OF
  1500. 0..3:
  1501. (* Y block *)
  1502. IF ~dequantizer.DequantizeIntraCoeffs(coeffs, intraQM, qScale, dcY, first, intraSkipped) THEN RETURN FALSE END;
  1503. | 4:
  1504. (* Cb block *)
  1505. IF ~dequantizer.DequantizeIntraCoeffs(coeffs, intraQM, qScale, dcCb, first, intraSkipped) THEN RETURN FALSE END;
  1506. | 5:
  1507. (* Cr block *)
  1508. IF ~dequantizer.DequantizeIntraCoeffs(coeffs, intraQM, qScale, dcCr, first, intraSkipped) THEN RETURN FALSE END;
  1509. END;
  1510. ELSE
  1511. IF ~dequantizer.DequantizeNonintraCoeffs(coeffs, nonintraQM, qScale) THEN RETURN FALSE END;
  1512. END;
  1513. idct.PerformIDCT(coeffs);
  1514. IF macroblockNr = -1 THEN KernelLog.String("Block decoded"); KernelLog.Ln; END;
  1515. RETURN TRUE;
  1516. END DecodeBlock;
  1517. PROCEDURE DecodeBlock2(
  1518. nr: SHORTINT;
  1519. coeffs:Util.PointerToArrayOfLONGINT;
  1520. intra: BOOLEAN;
  1521. VAR qScale: LONGINT;
  1522. first: BOOLEAN;
  1523. type: LONGINT): BOOLEAN;
  1524. VAR
  1525. bits: LONGINT; (* temp variable for reading some bits off the stream *)
  1526. size: LONGINT; (* amount of bits in the stream for dcDiff *)
  1527. dcDiff: LONGINT; (* DC difference decoded from stream *)
  1528. dcPrediction: LONGINT; (* DC prediction *)
  1529. coeffsPos: LONGINT; (* current position in the coeffs array *)
  1530. dummy: BOOLEAN; (* dummy variable *)
  1531. BEGIN
  1532. blocks.ClearBlockLongint(coeffs);
  1533. IF intra THEN
  1534. (* special treatment of the first coefficient -> DC *)
  1535. bits := stream.ShowBits(3);
  1536. IF nr < 4 THEN
  1537. (* intra coded Y block -> DCL table *)
  1538. IF bits = 7 THEN
  1539. stream.SkipBits(3);
  1540. size := 4;
  1541. WHILE stream.ShowBits(1) = 1 DO
  1542. INC(size);
  1543. stream.SkipBits(1);
  1544. END;
  1545. INC(size);
  1546. stream.SkipBits(1);
  1547. ELSE
  1548. size := MPEGTables.DCL3[bits][0];
  1549. stream.SkipBits(MPEGTables.DCL3[bits][1]);
  1550. END;
  1551. ELSE
  1552. (* intra coded Cb or Cr block -> DCC table*)
  1553. IF bits = 7 THEN
  1554. stream.SkipBits(3);
  1555. size := 3;
  1556. WHILE stream.ShowBits(1) = 1 DO
  1557. INC(size);
  1558. stream.SkipBits(1);
  1559. END;
  1560. INC(size);
  1561. stream.SkipBits(1);
  1562. ELSE
  1563. size := MPEGTables.DCC3[bits][0];
  1564. stream.SkipBits(MPEGTables.DCC3[bits][1]);
  1565. END;
  1566. END;
  1567. IF size = 0 THEN
  1568. dcDiff := 0;
  1569. ELSE
  1570. IF stream.ShowBits(1) = 0 THEN
  1571. (* negative difference: invert all bits and make number negative *)
  1572. bits := stream.GetBits(size);
  1573. IF bits < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1574. dcDiff := -(SYSTEM.VAL(INTEGER, ((-SYSTEM.VAL(SET, bits)) * {0..(size-1)})));
  1575. ELSE
  1576. (* positive difference *)
  1577. dcDiff := stream.GetBits(size);
  1578. IF dcDiff < 0 THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1579. END;
  1580. END;
  1581. (* set up DC prediction *)
  1582. IF (mbSkipped OR ((mbAddress - mbAddressLastIntra) > 1)) & first THEN
  1583. (* reset prediction *)
  1584. (* besser auf macroblock ebene? *)
  1585. CASE nr OF
  1586. 0..3:
  1587. dcY := MPEGTables.DCP[picExt.dcPrecision];
  1588. | 4:
  1589. dcCb := MPEGTables.DCP[picExt.dcPrecision];
  1590. | 5:
  1591. dcCr := MPEGTables.DCP[picExt.dcPrecision];
  1592. END;
  1593. END;
  1594. CASE nr OF
  1595. 0..3:
  1596. (* Y block *)
  1597. dcPrediction := dcY;
  1598. | 4:
  1599. (* Cb block *)
  1600. dcPrediction := dcCb;
  1601. | 5:
  1602. (* Cr block *)
  1603. dcPrediction := dcCr;
  1604. END;
  1605. coeffs[0] := dcPrediction + dcDiff;
  1606. CASE nr OF
  1607. 0..3:
  1608. dcY := coeffs[0];
  1609. | 4:
  1610. dcCb := coeffs[0];
  1611. | 5:
  1612. dcCr := coeffs[0];
  1613. END;
  1614. coeffsPos := 1;
  1615. ELSE
  1616. (* read first DCT coefficient, no special treatment *)
  1617. IF stream.ShowBits(1) = 1 THEN
  1618. IF stream.ShowBits(2) = 2 THEN
  1619. coeffs[0] := 1;
  1620. ELSE
  1621. coeffs[0] := -1;
  1622. END;
  1623. stream.SkipBits(2);
  1624. coeffsPos := 1;
  1625. ELSE
  1626. dummy := reader.ReadRunLevelCode(coeffs, coeffsPos, MPEG2); (* cannot return FALSE! *)
  1627. IF reader.eof THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1628. END;
  1629. END;
  1630. (* read the remaining coefficients *)
  1631. IF ~picExt.intraVlcFormat OR ~intra THEN
  1632. WHILE ~reader.ReadRunLevelCode(coeffs, coeffsPos, MPEG2) DO END;
  1633. ELSE
  1634. WHILE ~reader.ReadRunLevelCode2(coeffs, coeffsPos) DO END;
  1635. END;
  1636. IF reader.eof THEN hasMoreFrames := FALSE; RETURN FALSE END;
  1637. IF picExt.alternateScan THEN
  1638. (* interlaced movie: not supported yet *)
  1639. HALT(1234);
  1640. END;
  1641. (* do the dequantisation *)
  1642. IF intra THEN
  1643. dequantizer.DequantizeIntraCoeffs2(coeffs, intraQM, qScale, picExt.dcPrecision);
  1644. ELSE
  1645. dequantizer.DequantizeNonintraCoeffs2(coeffs, nonintraQM, qScale);
  1646. END;
  1647. (* perform iDCT *)
  1648. idct.PerformIDCT(coeffs);
  1649. RETURN TRUE;
  1650. END DecodeBlock2;
  1651. (* Render the current picture to img *)
  1652. PROCEDURE Render*(img : Raster.Image);
  1653. BEGIN
  1654. yuv2rgb.Convert(
  1655. nextFrameToRender.buffer, 0, videoWidth, videoWidth * videoHeight,
  1656. videoWidth * videoHeight + videoWidthDiv2 * videoHeightDiv2, videoWidthDiv2, img, videoWidth, videoHeight,
  1657. videoWidth);
  1658. END Render;
  1659. END MPEGVideoDecoder;
  1660. MPEGDemultiplexer* = OBJECT(Codec.AVDemultiplexer);
  1661. VAR
  1662. input: Streams.Reader;
  1663. bytesRead: LONGINT;
  1664. streams: ARRAY 64 OF POINTER TO StreamType;
  1665. nextStreamNr: LONGINT;
  1666. singleStream: BOOLEAN; (* TRUE if there is just one unpacked (video) stream -> no need to demux *)
  1667. PROCEDURE &Init*;
  1668. BEGIN
  1669. nextStreamNr := 0;
  1670. END Init;
  1671. (** open the demultiplexer on an input stream *)
  1672. PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
  1673. VAR
  1674. oldPos, i: LONGINT;
  1675. startCode: CHAR;
  1676. BEGIN
  1677. input := in;
  1678. res := Codec.ResFailed;
  1679. (* only seekable streams are supported *)
  1680. IF ~in.CanSetPos() THEN RETURN END;
  1681. IF ~GotoNextStartCode() THEN RETURN END;
  1682. startCode := input.Get();
  1683. IF startCode = SCSequenceHeader THEN
  1684. singleStream := TRUE;
  1685. NEW(streams[0]);
  1686. NEW(streams[0].stream, SELF, 0);
  1687. streams[0].idByte := startCode;
  1688. streams[0].pos := 0;
  1689. streams[0].bytesLeftInPacket := -1; (* one stream -> no packets -> no bytes to read *)
  1690. streams[0].eos := FALSE;
  1691. nextStreamNr := -1; (* nextStreamNr should not be accessed - it's the only stream! *)
  1692. input.SetPos(0); (* reset because we already read a startcode *)
  1693. res := Codec.ResOk;
  1694. RETURN;
  1695. ELSIF startCode # SCPack THEN
  1696. RETURN;
  1697. END;
  1698. (* startCode = SCPack *)
  1699. IF ~ReadPackHeader() THEN RETURN END;
  1700. IF ~GotoNextStartCode() OR (input.Get() # SCSystemHeader) THEN RETURN END;
  1701. IF ~ReadSystemHeader() THEN RETURN END;
  1702. (* search for some more streams *)
  1703. oldPos := input.Pos();
  1704. FOR i := 0 TO 20 DO
  1705. (* read chunk header *)
  1706. IF ~GotoNextStartCode() THEN HALT(1234) END;
  1707. startCode := input.Get();
  1708. IF startCode = SCSystemHeader THEN
  1709. IF ~ReadSystemHeader() THEN HALT(1234) END;
  1710. ELSIF startCode = SCPack THEN
  1711. IF ~ReadPackHeader() THEN HALT(1234) END;
  1712. ELSIF ((ORD(startCode) >= 0BCH) & (ORD(startCode) <= 0FFH)) THEN
  1713. input.SkipBytes(ORD(input.Get()) * 100H + ORD(input.Get()));
  1714. ELSE
  1715. (* we're lost... *)
  1716. HALT(1234);
  1717. END;
  1718. END;
  1719. input.SetPos(oldPos);
  1720. res := Codec.ResOk;
  1721. END Open;
  1722. PROCEDURE GotoNextStartCode(): BOOLEAN;
  1723. BEGIN
  1724. IF SkipZeros() < 2 THEN RETURN FALSE END;
  1725. RETURN input.Get() = CHR(1);
  1726. END GotoNextStartCode;
  1727. PROCEDURE SkipZeros(): LONGINT;
  1728. VAR
  1729. count: LONGINT;
  1730. BEGIN
  1731. WHILE (input.Peek() = CHR(0)) & ~(input.res = Streams.EOF) DO
  1732. input.SkipBytes(1);
  1733. INC(count);
  1734. END;
  1735. IF input.res = Streams.EOF THEN
  1736. RETURN -1;
  1737. ELSE
  1738. RETURN count;
  1739. END;
  1740. END SkipZeros;
  1741. (* Reads a pack header *)
  1742. PROCEDURE ReadPackHeader(): BOOLEAN;
  1743. VAR
  1744. peek: LONGINT;
  1745. stuffBytes: LONGINT;
  1746. buffer: ARRAY 8 OF CHAR;
  1747. BEGIN
  1748. peek := ORD(input.Peek());
  1749. IF (peek >= 32) & (peek < 48) THEN
  1750. (* 0010 xxxx -> MPEG-1 System *)
  1751. input.Bytes(buffer, 0, 8, bytesRead);
  1752. IF (input.res # Streams.Ok) OR (bytesRead < 8) THEN RETURN FALSE END;
  1753. (* we don't care about SCR and MuxRate, so we ignore the rest *)
  1754. RETURN TRUE;
  1755. ELSIF (peek >= 64) & (peek < 128) THEN
  1756. (* 01xx xxxx -> MPEG-2 System *)
  1757. input.SkipBytes(9);
  1758. stuffBytes := ORD(input.Get()) MOD 8;
  1759. input.SkipBytes(stuffBytes);
  1760. RETURN (input.res = Streams.Ok);
  1761. ELSE
  1762. (* unknown system *)
  1763. RETURN FALSE;
  1764. END;
  1765. END ReadPackHeader;
  1766. (* Reads a system header *)
  1767. PROCEDURE ReadSystemHeader(): BOOLEAN;
  1768. VAR
  1769. headerLength: LONGINT;
  1770. buffer: ARRAY 8 OF CHAR;
  1771. BEGIN
  1772. input.Bytes(buffer, 0, 8, bytesRead);
  1773. IF (input.res # Streams.Ok) OR (bytesRead < 8) THEN RETURN FALSE END;
  1774. headerLength := ORD(buffer[0]) * 256 + ORD(buffer[1]) - 6;
  1775. (* we don't care about rateBound, audioBound, CSPS-, AudioLock- and VideoLock-Flags and videoBound *)
  1776. (* read stream infos *)
  1777. WHILE ORD(input.Peek()) > 127 DO
  1778. input.Bytes(buffer, 0, 3, bytesRead);
  1779. IF (input.res # Streams.Ok) OR (bytesRead < 3) THEN RETURN FALSE END;
  1780. IF isNewStream(buffer[0]) THEN
  1781. (* we found infos about a new stream *)
  1782. NEW(streams[nextStreamNr]);
  1783. NEW(streams[nextStreamNr].stream, SELF, nextStreamNr);
  1784. streams[nextStreamNr].idByte := buffer[0];
  1785. streams[nextStreamNr].pos := -1;
  1786. streams[nextStreamNr].eos := FALSE;
  1787. INC(nextStreamNr);
  1788. END;
  1789. END;
  1790. RETURN TRUE;
  1791. END ReadSystemHeader;
  1792. PROCEDURE isNewStream(id: CHAR): BOOLEAN;
  1793. VAR
  1794. i: LONGINT;
  1795. BEGIN
  1796. FOR i := 0 TO (nextStreamNr-1) DO
  1797. IF streams[i].idByte = id THEN RETURN FALSE END;
  1798. END;
  1799. RETURN TRUE;
  1800. END isNewStream;
  1801. PROCEDURE GetNumberOfStreams*() : LONGINT;
  1802. BEGIN
  1803. IF singleStream THEN
  1804. RETURN 1;
  1805. ELSE
  1806. RETURN nextStreamNr;
  1807. END;
  1808. END GetNumberOfStreams;
  1809. PROCEDURE GetStreamType*(streamNr : LONGINT): LONGINT;
  1810. VAR
  1811. streamid: LONGINT;
  1812. BEGIN
  1813. IF streams[streamNr] # NIL THEN
  1814. streamid := ORD(streams[streamNr].idByte);
  1815. CASE streamid OF
  1816. 0BCH..0BFH:
  1817. (* reserved stream, private stream, padding stream, private stream 2 *)
  1818. RETURN Codec.STUnknown;
  1819. | 0C0H..0DFH:
  1820. (* audio stream 0..31 *)
  1821. RETURN Codec.STAudio;
  1822. | 0E0H..0EFH:
  1823. (* video stream 0..15 *)
  1824. RETURN Codec.STVideo;
  1825. | 0F0H..0FFH:
  1826. (* reserved streams *)
  1827. KernelLog.String("Stream-ID: "); KernelLog.Hex(streamid, 0); KernelLog.Ln;
  1828. RETURN Codec.STUnknown;
  1829. ELSE
  1830. KernelLog.String("Stream-ID: "); KernelLog.Hex(streamid, 0); KernelLog.Ln;
  1831. RETURN Codec.STUnknown;
  1832. END;
  1833. ELSE
  1834. (* no such stream... *)
  1835. RETURN Codec.STError;
  1836. END;
  1837. END GetStreamType;
  1838. PROCEDURE GetStream*(streamNr: LONGINT): Codec.DemuxStream;
  1839. BEGIN
  1840. IF streams[streamNr] # NIL THEN
  1841. RETURN streams[streamNr].stream;
  1842. ELSE
  1843. RETURN NIL;
  1844. END;
  1845. END GetStream;
  1846. PROCEDURE GetStreamInfo*(streamNr : LONGINT): Codec.AVStreamInfo;
  1847. VAR si : Codec.AVStreamInfo;
  1848. BEGIN
  1849. CASE GetStreamType(streamNr) OF
  1850. Codec.STAudio: COPY("MPEGAUDIO", si.contentType);
  1851. | Codec.STVideo: COPY("MPEG", si.contentType);
  1852. | Codec.STUnknown: COPY("UNKNOWN", si.contentType);
  1853. ELSE COPY("UNKNOWN", si.contentType);
  1854. END;
  1855. RETURN si
  1856. END GetStreamInfo;
  1857. (* read data from streamNr, store it into buffer buf starting at offset ofs, store size bytes if possible, block if not read min bytes at least. Return number of read bytes in len and return code res *)
  1858. PROCEDURE GetData*(streamNr : LONGINT; VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
  1859. VAR
  1860. cur: POINTER TO StreamType;
  1861. length: LONGINT;
  1862. offset: LONGINT;
  1863. BEGIN
  1864. IF singleStream THEN
  1865. IF streams[0].eos = TRUE THEN
  1866. (* what else should we do - even when min > 0 ?? *)
  1867. RETURN;
  1868. END;
  1869. input.Bytes(buf, ofs, size, len);
  1870. res := input.res;
  1871. IF input.res = Streams.EOF THEN
  1872. streams[0].eos := TRUE;
  1873. END;
  1874. INC(streams[0].pos, len);
  1875. RETURN;
  1876. END;
  1877. cur := streams[streamNr];
  1878. len := size;
  1879. offset := ofs;
  1880. IF cur.eos = TRUE THEN
  1881. (* what else should we do - even when min > 0 ?? *)
  1882. RETURN;
  1883. END;
  1884. IF cur.pos = -1 THEN
  1885. (* search for the beginning of the stream *)
  1886. input.SetPos(-1);
  1887. IF ~GotoNextPacket(cur^) THEN res := Codec.ResFailed; RETURN END;
  1888. END;
  1889. input.SetPos(cur.pos);
  1890. WHILE (cur.bytesLeftInPacket < size) & ~cur.eos DO
  1891. (* copy bytes left from current packet *)
  1892. input.Bytes(buf, offset, cur.bytesLeftInPacket, length);
  1893. INC(cur.pos, length);
  1894. DEC(size, cur.bytesLeftInPacket);
  1895. INC(offset, cur.bytesLeftInPacket);
  1896. (* jump to next packet of this stream *)
  1897. IF ~GotoNextPacket(cur^) THEN
  1898. (* end of stream ! *)
  1899. cur.eos := TRUE;
  1900. DEC(len, size);
  1901. RETURN;
  1902. END;
  1903. END;
  1904. res := Codec.ResOk;
  1905. IF cur.eos THEN
  1906. (* we couldn't get enough bytes... *)
  1907. DEC(len, size);
  1908. ELSE
  1909. (* copy required bytes *)
  1910. input.Bytes(buf, offset, size, length);
  1911. cur.pos := input.Pos();
  1912. DEC(cur.bytesLeftInPacket, length);
  1913. END;
  1914. END GetData;
  1915. PROCEDURE SkipData(streamNr : LONGINT; size: LONGINT; VAR len, res: LONGINT);
  1916. VAR
  1917. cur: POINTER TO StreamType;
  1918. BEGIN
  1919. IF singleStream THEN
  1920. input.SkipBytes(size);
  1921. res := Codec.ResOk; (* shouldn't we return input.res? *)
  1922. INC(streams[0].pos, len);
  1923. RETURN;
  1924. END;
  1925. cur := streams[streamNr];
  1926. len := size;
  1927. IF cur.pos = -1 THEN
  1928. (* search for the beginning of the stream *)
  1929. input.SetPos(cur.pos);
  1930. IF ~GotoNextPacket(cur^) THEN res := Codec.ResFailed; RETURN END;
  1931. END;
  1932. input.SetPos(cur.pos);
  1933. WHILE cur.bytesLeftInPacket < size DO
  1934. (* skip bytes left in the current packet *)
  1935. input.SkipBytes(cur.bytesLeftInPacket);
  1936. INC(cur.pos, cur.bytesLeftInPacket);
  1937. DEC(size, cur.bytesLeftInPacket);
  1938. (* jump to next packet of this stream *)
  1939. IF ~GotoNextPacket(cur^) THEN
  1940. res := Codec.ResFailed;
  1941. RETURN;
  1942. END;
  1943. END;
  1944. (* skip required bytes *)
  1945. input.SkipBytes(size);
  1946. cur.pos := input.Pos();
  1947. DEC(cur.bytesLeftInPacket, size);
  1948. END SkipData;
  1949. PROCEDURE GetPosInMuxedStream*(streamNr: LONGINT): LONGINT;
  1950. BEGIN
  1951. RETURN streams[streamNr].pos;
  1952. END GetPosInMuxedStream;
  1953. (* jump to the next packet of the stream with identifier id, starting at the current position of the input-stream *)
  1954. (* assumption: position is at the beginning of a packet (or pack or system header) *)
  1955. PROCEDURE GotoNextPacket(VAR stream: StreamType): BOOLEAN;
  1956. VAR
  1957. nextStartCode: CHAR;
  1958. length: LONGINT;
  1959. peekByte: CHAR;
  1960. flags: LONGINT;
  1961. optionsLength: LONGINT;
  1962. BEGIN
  1963. IF ~GotoNextStartCode() THEN RETURN FALSE END;
  1964. nextStartCode := input.Get();
  1965. WHILE (nextStartCode # stream.idByte) & (input.res # Streams.EOF) DO
  1966. IF nextStartCode = SCPack THEN
  1967. IF ~ReadPackHeader() THEN RETURN FALSE END;
  1968. ELSIF nextStartCode = SCSystemHeader THEN
  1969. IF ~ReadSystemHeader() THEN RETURN FALSE END;
  1970. ELSE
  1971. (* read length field and skip the packet *)
  1972. length := ORD(input.Get()) * 100H + ORD(input.Get());
  1973. input.SkipBytes(length);
  1974. END;
  1975. (* read startcode of next chunk *)
  1976. IF ~GotoNextStartCode() THEN RETURN FALSE END;
  1977. nextStartCode := input.Get();
  1978. END;
  1979. IF input.res = Streams.EOF THEN
  1980. RETURN FALSE;
  1981. END;
  1982. (* read packet header *)
  1983. length := ORD(input.Get()) * 100H + ORD(input.Get());
  1984. IF nextStartCode # SCPrivateStream2 THEN
  1985. IF (ORD(input.Peek()) >= 128) & (ORD(input.Peek()) < 192) THEN
  1986. (* MPEG-2 System *)
  1987. input.SkipBytes(1);
  1988. flags := ORD(input.Get());
  1989. (* the simple way: skip all additional stuff *)
  1990. optionsLength := ORD(input.Get());
  1991. input.SkipBytes(optionsLength);
  1992. DEC(length, optionsLength + 3);
  1993. ELSE
  1994. (* MPEG-1 System *)
  1995. WHILE ORD(input.Peek()) = 0FFH DO
  1996. (* skip padding *)
  1997. input.SkipBytes(1);
  1998. DEC(length);
  1999. END;
  2000. peekByte := input.Peek();
  2001. IF (ORD(peekByte) > 63) & (ORD(peekByte) <128) THEN
  2002. (* 01xx xxxx *)
  2003. input.SkipBytes(2);
  2004. DEC(length, 2);
  2005. peekByte := input.Peek();
  2006. END;
  2007. IF (ORD(peekByte) > 31) & (ORD(peekByte) < 48) THEN
  2008. (* 0010 xxxx *)
  2009. input.SkipBytes(5);
  2010. DEC(length, 5);
  2011. peekByte := input.Peek();
  2012. ELSIF (ORD(peekByte) > 47) & (ORD(peekByte) < 64) THEN
  2013. (* 0011 xxxx *)
  2014. input.SkipBytes(10);
  2015. DEC(length, 10);
  2016. ELSE
  2017. (* skip 0000 1111 fixed pattern *)
  2018. input.SkipBytes(1);
  2019. DEC(length);
  2020. END;
  2021. END;
  2022. END;
  2023. (* finally we reached the next data bytes of the requested stream *)
  2024. stream.pos := input.Pos() + 1; (* next byte is first byte of the stream *)
  2025. stream.bytesLeftInPacket := length;
  2026. RETURN TRUE;
  2027. END GotoNextPacket;
  2028. (* seek the streamNr to position pos with seekType. itemSize contains the size of the element seeked to, if known and applicable; res = 0 if Ok, otherwise an error number *)
  2029. PROCEDURE SetStreamPos*(streamNr : LONGINT; seekType : LONGINT; pos : LONGINT; VAR itemSize : LONGINT; VAR res : LONGINT);
  2030. VAR
  2031. cur: POINTER TO StreamType;
  2032. len: LONGINT;
  2033. BEGIN
  2034. res := Codec.ResFailed;
  2035. IF seekType # Codec.SeekByte THEN
  2036. (* we can only seek for bytes here. seeking for frames can be done directly in the decoder *)
  2037. RETURN;
  2038. END;
  2039. itemSize := 1; (* does this make sense? one byte has always size one...*)
  2040. IF singleStream THEN
  2041. IF streamNr # 0 THEN RETURN END;
  2042. input.SetPos(pos);
  2043. streams[0].pos := pos;
  2044. res := Codec.ResOk;
  2045. RETURN;
  2046. END;
  2047. IF streamNr >= nextStreamNr THEN
  2048. RETURN
  2049. END;
  2050. cur := streams[streamNr];
  2051. IF (cur.stream.Pos()+cur.stream.Available()) > pos THEN
  2052. (* reset stream and start searching at the beginning *)
  2053. input.SetPos(-1);
  2054. IF ~GotoNextPacket(cur^) THEN HALT(1234); res := Codec.ResFailed; RETURN END;
  2055. (* skip some data *)
  2056. SkipData(streamNr, pos, len, res);
  2057. ELSE
  2058. (* skip some data *)
  2059. SkipData(streamNr, pos - (cur.stream.Pos()+cur.stream.Available()), len, res);
  2060. END;
  2061. END SetStreamPos;
  2062. PROCEDURE HasMoreData(streamNr: LONGINT): BOOLEAN;
  2063. BEGIN
  2064. RETURN ~streams[streamNr].eos;
  2065. END HasMoreData;
  2066. END MPEGDemultiplexer;
  2067. PROCEDURE GotoNextMarker(VAR stream: Util.BitStream; VAR marker: CHAR): BOOLEAN;
  2068. VAR
  2069. i: INTEGER;
  2070. DEBUG: BOOLEAN;
  2071. BEGIN
  2072. DEBUG := FALSE;
  2073. i := 0;
  2074. stream.ByteAlign();
  2075. (* skip stuffing zeros *)
  2076. WHILE (stream.ShowBits(24) # 1) DO
  2077. stream.SkipBits(8);
  2078. INC(i);
  2079. END;
  2080. marker := CHR(stream.ShowBits(32) MOD 256);
  2081. RETURN TRUE;
  2082. END GotoNextMarker;
  2083. PROCEDURE Sign(value: LONGINT): LONGINT;
  2084. BEGIN
  2085. IF value > 0 THEN
  2086. RETURN 1;
  2087. ELSIF value < 0 THEN
  2088. RETURN -1;
  2089. ELSE
  2090. RETURN 0;
  2091. END;
  2092. END Sign;
  2093. PROCEDURE DecoderFactory*() : Codec.VideoDecoder;
  2094. VAR p: MPEGVideoDecoder;
  2095. BEGIN
  2096. NEW(p);
  2097. RETURN p;
  2098. END DecoderFactory;
  2099. PROCEDURE DemuxFactory*() : Codec.AVDemultiplexer;
  2100. VAR d: MPEGDemultiplexer;
  2101. BEGIN
  2102. NEW(d);
  2103. RETURN d
  2104. END DemuxFactory;
  2105. PROCEDURE Test*(context : Commands.Context);
  2106. VAR
  2107. demux: MPEGDemultiplexer;
  2108. decoder: MPEGVideoDecoder;
  2109. file: Files.File;
  2110. fileinputstream: Codec.FileInputStream;
  2111. vstream: Codec.DemuxStream;
  2112. result: LONGINT;
  2113. i: LONGINT;
  2114. w, h, ms: LONGINT;
  2115. (* Player stuff *)
  2116. wnd: PW;
  2117. timer: Kernel.Timer;
  2118. milliTimer : Kernel.MilliTimer;
  2119. ticks: LONGINT;
  2120. filename:ARRAY 100 OF CHAR;
  2121. min, max, total: LONGINT;
  2122. minFrame, maxFrame: LONGINT;
  2123. BEGIN
  2124. (* parse parameter: filename *)
  2125. context.arg.SkipWhitespace; context.arg.String(filename);
  2126. file := Files.Old(filename);
  2127. IF file = NIL THEN
  2128. context.error.String("Couldn't open File "); context.error.String(filename);
  2129. context.error.Ln();
  2130. RETURN;
  2131. END;
  2132. NEW(timer);
  2133. NEW(fileinputstream, file, 0);
  2134. NEW(demux);
  2135. demux.Open(fileinputstream, result);
  2136. IF result # Codec.ResOk THEN
  2137. context.error.String("error opening the demultiplexer"); context.error.Ln;
  2138. END;
  2139. vstream := demux.GetStream(0);
  2140. NEW(decoder);
  2141. decoder.Open(vstream, result);
  2142. IF result = Codec.ResOk THEN
  2143. (* get information *)
  2144. decoder.GetVideoInfo(w, h, ms);
  2145. (* open the window *)
  2146. NEW(wnd, w, h, FALSE);
  2147. wnd.SetTitle(WM.NewString("Simple MPEG Player"));
  2148. (* decode some frames ... *)
  2149. (* decoder.SeekFrame(100, FALSE, result); *)
  2150. (* decoder.SeekMillisecond(5000, FALSE, result); *)
  2151. FOR i := 0 TO 50 DO
  2152. Kernel.SetTimer(milliTimer, 0);
  2153. decoder.Next();
  2154. decoder.Render(wnd.backImg);
  2155. wnd.Swap();
  2156. wnd.Invalidate(Rectangles.MakeRect( 0, 0, wnd.backImg.width, wnd.backImg.height ) );
  2157. ticks := Kernel.Elapsed(milliTimer);
  2158. (* context.out.String("Time required: "); context.out.Int(ticks, 0); context.out.Ln; *)
  2159. IF ticks < min THEN
  2160. min := ticks;
  2161. minFrame := i;
  2162. ELSIF ticks > max THEN
  2163. max := ticks;
  2164. maxFrame := i;
  2165. END;
  2166. INC(total, ticks);
  2167. (* timer.Sleep(100); *)
  2168. END;
  2169. context.out.String("Finished decoding "); context.out.Int(i, 0); context.out.String(" Frames (min/avg/max): ");
  2170. context.out.Int(min, 0); context.out.String(" (Frame "); context.out.Int(minFrame, 0); context.out.String(") / ");
  2171. context.out.Int(total DIV i, 0); context.out.String(" /"); context.out.Int(max, 0); context.out.String(" (Frame "); context.out.Int(maxFrame, 0);
  2172. context.out.String(")"); context.out.Ln;
  2173. END;
  2174. END Test;
  2175. END MPEGVideoDecoder.
  2176. SystemTools.Free MPEGVideoDecoder ~
  2177. MPEGVideoDecoder.Test beauty.mpg~
  2178. (* end of file *)