AVI.Mod 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. MODULE AVI;
  2. (* Procedures to read an .avi file *)
  3. (* Written by Thomas Trachsel, ttrachsel@web.de, 18.9.2003 *)
  4. (* Extended with indexfunctionality and adaptation on Codecs by Urs Müller, October 2004 *)
  5. (* Cleaned by PL, March 2005 *)
  6. IMPORT
  7. SYSTEM, Machine, Streams, KernelLog, AOC := Codecs;
  8. CONST
  9. Debug = FALSE;
  10. DefaultReaderSize = 4096;
  11. WriteError = 2907;
  12. (* Steht jetzt einmal hier, kann man vielleicht in AVIDemux reinpacken, mal schauen *)
  13. TYPE
  14. (* Structure that contains the main informations of the .avi file *)
  15. MainAVIHeaderDesc* = OBJECT
  16. VAR
  17. microSecsPerFrame*: LONGINT;
  18. maxBytesPerSec*: LONGINT;
  19. reserved1*: LONGINT;
  20. flags*: LONGINT;
  21. totalFrames*: LONGINT;
  22. initialFrames*: LONGINT;
  23. streams*: LONGINT;
  24. suggestedBufferSize*: LONGINT;
  25. width*: LONGINT;
  26. height*: LONGINT;
  27. reserved*: ARRAY 4 OF LONGINT;
  28. END MainAVIHeaderDesc;
  29. (* Structure that contains the main Info of a stream in a .avi file *)
  30. AVIStreamHeader* = OBJECT
  31. VAR
  32. fccType*: ARRAY 4 OF CHAR;
  33. fccHandler*: ARRAY 4 OF CHAR;
  34. flags*: LONGINT;
  35. priority*: LONGINT;
  36. initialFrames*: LONGINT;
  37. scale*: LONGINT;
  38. rate*: LONGINT;
  39. start*: LONGINT;
  40. length*: LONGINT;
  41. suggestedBufferSize*: LONGINT;
  42. quality*: LONGINT;
  43. sampleSize*: LONGINT;
  44. left*: LONGINT;
  45. top*: LONGINT;
  46. right*: LONGINT;
  47. bottom*: LONGINT;
  48. streamIdentifier*: ARRAY 4 OF CHAR;
  49. bitMapInfo*: BitMapInfo;
  50. waveFormatEx*: WAVEFormatEx;
  51. END AVIStreamHeader;
  52. (* video stream specific infos *)
  53. BitMapInfo = OBJECT
  54. VAR
  55. size*: LONGINT;
  56. width*: LONGINT;
  57. height*: LONGINT;
  58. planes*: LONGINT;
  59. bitCount*: LONGINT;
  60. compression*: LONGINT;
  61. sizeImage*: LONGINT;
  62. xPelsPerMeter*: LONGINT;
  63. yPelsPerMeter*: LONGINT;
  64. clrUsed*: LONGINT;
  65. clrImportant*: LONGINT;
  66. END BitMapInfo;
  67. (* audio stream specific infos *)
  68. WAVEFormatEx* = OBJECT
  69. VAR
  70. formatTag*: LONGINT;
  71. channels*: LONGINT;
  72. samplesPerSec*: LONGINT;
  73. avgBytesPerSec*: LONGINT;
  74. blockAlign*: LONGINT;
  75. bitsPerSample*: LONGINT;
  76. cbSize*: LONGINT;
  77. END WAVEFormatEx;
  78. (* IndexChunk infos *)
  79. AVIIndexEntry* = RECORD
  80. ckid*: LONGINT;
  81. flags*: LONGINT;
  82. offset*: LONGINT;
  83. length*: LONGINT;
  84. tot*: LONGINT;
  85. END;
  86. TYPE IndexArrayPointer* = POINTER TO ARRAY OF AVIIndexEntry;
  87. (* Stream for reading a Stream of an .avi file *)
  88. TYPE AVIStream* = OBJECT(AOC.DemuxStream)
  89. VAR
  90. bufAdr: LONGINT;
  91. r : Streams.Reader;
  92. chunkSize*: LONGINT; (* Bytes in actual AVI Chunk *)
  93. streamHeader: AVIStreamHeader;
  94. stuffByte*: LONGINT;
  95. eof*: BOOLEAN; (* End of File *)
  96. (* Constructor *)
  97. PROCEDURE & Init*( r: Streams.Reader; streamHdr: AVIStreamHeader);
  98. BEGIN
  99. bufAdr := 0;
  100. chunkSize := 0;
  101. streamHeader := streamHdr;
  102. SELF.r := r;
  103. ASSERT(SELF.r # NIL);
  104. stuffByte := 0;
  105. eof := FALSE;
  106. END Init;
  107. (* Returns TRUE if the underlying reader supports seeking. *)
  108. PROCEDURE CanSetPos*() : BOOLEAN;
  109. BEGIN
  110. RETURN r.CanSetPos();
  111. END CanSetPos;
  112. (* Compare two array up to len bytes *)
  113. PROCEDURE CompareCharArrays(ar1,ar2 : ARRAY OF CHAR; len: LONGINT ): BOOLEAN;
  114. VAR
  115. i: LONGINT;
  116. BEGIN
  117. IF ( len > LEN( ar1 ) ) OR ( len > LEN( ar2 ) ) THEN
  118. RETURN FALSE
  119. END;
  120. FOR i := 0 TO len-1 DO
  121. IF ar1[i] # ar2[i] THEN
  122. RETURN FALSE
  123. END;
  124. END;
  125. RETURN TRUE
  126. END CompareCharArrays;
  127. (* Seek the next chunk of our stream in the avi file and read it *)
  128. PROCEDURE ReadNextChunk(VAR buf: ARRAY OF CHAR);
  129. VAR
  130. tempBuf: ARRAY 4 OF CHAR;
  131. len: LONGINT;
  132. done: BOOLEAN;
  133. BEGIN
  134. IF Debug THEN KernelLog.String("Read next Chunk"); KernelLog.Ln; END;
  135. done := FALSE;
  136. eof := FALSE;
  137. (* Undocument in .avi docu; if the size of a chunk is odd, we have to skip one byte *)
  138. IF stuffByte > 0 THEN
  139. r.SkipBytes( 1 );
  140. stuffByte := 0
  141. END;
  142. REPEAT
  143. r.Bytes(tempBuf, 0, 4, len );
  144. IF r.res = Streams.Ok THEN
  145. r.RawLInt(len);
  146. stuffByte := len MOD 2;
  147. IF r.res = Streams.Ok THEN
  148. IF Debug THEN
  149. KernelLog.String( "AVIStream: Found Chunk : " );
  150. KernelLog.Hex( ORD( tempBuf[0] ), 0 ); KernelLog.Hex( ORD( tempBuf[1] ), 0 );
  151. KernelLog.Hex( ORD( tempBuf[2] ), 0 ); KernelLog.Hex( ORD( tempBuf[3] ), 0 ); KernelLog.String(" ");
  152. KernelLog.Char( tempBuf[0] ); KernelLog.Char( tempBuf[1] ); KernelLog.Char( tempBuf[2] );
  153. KernelLog.Char( tempBuf[3] ); KernelLog.String( "@Pos: "); KernelLog.Int( r.Pos() - 8, 0 );
  154. KernelLog.String( " SkipBytes: " ); KernelLog.Int( len, 0 ); KernelLog.Ln();
  155. END;
  156. IF CompareCharArrays( tempBuf, streamHeader.streamIdentifier, 4 ) THEN
  157. (* We found the correct chunk *)
  158. IF len > 0 THEN
  159. done := TRUE;
  160. bufAdr := ADDRESSOF( buf[0] );
  161. r.Bytes( buf, 0, len, chunkSize );
  162. buf[len] := CHR( 0 ); buf[len+1] := CHR( 0 ); buf[len+2] := CHR( 0 ); buf[len+3] := CHR( 0 );
  163. ASSERT( len = chunkSize );
  164. END;
  165. ELSE
  166. r.SkipBytes( len + stuffByte )
  167. END;
  168. ELSE
  169. eof := TRUE;
  170. res := Streams.EOF;
  171. KernelLog.String("ENDE");
  172. END;
  173. ELSE
  174. eof := TRUE;
  175. res := Streams.EOF;
  176. KernelLog.String("ENDE");
  177. END;
  178. UNTIL ( done OR eof );
  179. END ReadNextChunk;
  180. (* Go to the beginnig of the next frame -> Read next chunk *)
  181. PROCEDURE Resynch*(VAR buf: ARRAY OF CHAR): BOOLEAN;
  182. BEGIN
  183. ReadNextChunk(buf);
  184. RETURN ~eof
  185. END Resynch;
  186. (* Return Pos in Avi File, relativ to the beginning of the stream data *)
  187. PROCEDURE Pos*(): Streams.Position;
  188. BEGIN
  189. RETURN r.Pos()
  190. END Pos;
  191. (* Set the Position of the AVIReader. If frame flag is set, position is interpreted as a framenumber *)
  192. PROCEDURE SetAVIPos*(pos: LONGINT; VAR retPos: LONGINT);
  193. BEGIN
  194. IF Debug THEN KernelLog.String("DemuxStream.SetAVIPos"); KernelLog.Ln; END;
  195. r.SetPos(pos);
  196. stuffByte := 0;
  197. retPos := r.Pos();
  198. Reset;
  199. END SetAVIPos;
  200. PROCEDURE Bytes*(VAR x: ARRAY OF CHAR; ofs, size: LONGINT; VAR len: LONGINT);
  201. VAR
  202. min, res: LONGINT;
  203. BEGIN
  204. IF Debug THEN KernelLog.String("Bytes"); KernelLog.Ln; END;
  205. demultiplexer.GetData(streamNr, x, ofs, size, min, len, res);
  206. END Bytes;
  207. (* Set Byte Position *)
  208. PROCEDURE SetPos*(pos : Streams.Position);
  209. VAR seekType, itemSize, res : LONGINT;
  210. BEGIN
  211. IF Debug THEN KernelLog.String("DemuxStream.SetPos"); KernelLog.Ln; END;
  212. seekType := AOC.SeekByte;
  213. demultiplexer.SetStreamPos(streamNr, seekType, pos, itemSize, res);
  214. Reset;
  215. END SetPos;
  216. END AVIStream;
  217. (* The .avi File Demultiplexer *)
  218. AVIDemux* = OBJECT(AOC.AVDemultiplexer)
  219. VAR
  220. r : Streams.Reader;
  221. filename* : ARRAY 256 OF CHAR;
  222. (* We need just these 3 Headers *)
  223. aviHeader: MainAVIHeaderDesc;
  224. audioStreamHeader: AVIStreamHeader;
  225. videoStreamHeader: AVIStreamHeader;
  226. riffLength: LONGINT;
  227. movieBeginPos: LONGINT;
  228. indexStart: LONGINT;
  229. videoFrames: LONGINT;
  230. audioChunks: LONGINT;
  231. videoIndex: IndexArrayPointer;
  232. audioIndex: IndexArrayPointer;
  233. audioBytes: LONGINT;
  234. videoBufferIndex: LONGINT;
  235. audioChunkSize: LONGINT;
  236. audioStream: AVIStream;
  237. videoStream: AVIStream;
  238. videoFramePos: LONGINT;
  239. audioFramePos: LONGINT;
  240. PROCEDURE Open*(in : Streams.Reader; VAR res : WORD);
  241. BEGIN
  242. r := in;
  243. res := AOC.ResFailed;
  244. IF in IS AOC.FileInputStream THEN
  245. in(AOC.FileInputStream).f.GetName(filename);
  246. IF ReadHeader() THEN res := AOC.ResOk END
  247. ELSE RETURN END; (* bad bad bad *)
  248. END Open;
  249. PROCEDURE GetAVIHeader*(): MainAVIHeaderDesc;
  250. BEGIN
  251. RETURN aviHeader
  252. END GetAVIHeader;
  253. (* Compare two arrays up to len bytes *)
  254. PROCEDURE CompareCharArrays( ar1,ar2 : ARRAY OF CHAR; len: LONGINT ): BOOLEAN;
  255. VAR
  256. i: LONGINT;
  257. BEGIN
  258. IF ( len > LEN( ar1 ) ) OR ( len > LEN( ar2 ) ) THEN
  259. RETURN FALSE
  260. END;
  261. FOR i := 0 TO len-1 DO
  262. IF ar1[i] # ar2[i] THEN
  263. RETURN FALSE
  264. END;
  265. END;
  266. RETURN TRUE
  267. END CompareCharArrays;
  268. (* Read .avi FIle Header *)
  269. PROCEDURE ReadHeader*(): BOOLEAN;
  270. VAR
  271. buf : ARRAY 8 OF CHAR;
  272. len: LONGINT;
  273. done: BOOLEAN;
  274. headerLength: LONGINT;
  275. headerBeginPos: LONGINT;
  276. tempHeader: AVIStreamHeader;
  277. streamNumber: SHORTINT;
  278. BEGIN
  279. done := FALSE;
  280. streamNumber := 0;
  281. riffLength := 0;
  282. aviHeader := NIL;
  283. audioStreamHeader := NIL;
  284. videoStreamHeader := NIL;
  285. ASSERT(r # NIL);
  286. (* Check, if we have a valid avi file *)
  287. r.Bytes( buf,0,4,len );
  288. IF CompareCharArrays( buf, "RIFF" ,4 ) # TRUE THEN
  289. KernelLog.String( "Not a valid .avi File!" ); KernelLog.Ln;
  290. RETURN FALSE
  291. END;
  292. r.RawLInt(riffLength);
  293. r.Bytes( buf,0,4, len );
  294. IF CompareCharArrays( buf, "AVI ",4 ) # TRUE THEN
  295. KernelLog.String( "Only .avi Files that contain a video stream are allowed" ); KernelLog.Ln();
  296. RETURN FALSE
  297. END;
  298. (* Read AVI Headers *)
  299. REPEAT
  300. r.Bytes( buf,0,4, len );
  301. IF CompareCharArrays( buf, "LIST",4 ) THEN
  302. (* We found an additional Header *)
  303. (* Store Infos about header *)
  304. r.RawLInt(headerLength);
  305. headerLength := headerLength + headerLength MOD 2;
  306. headerBeginPos := r.Pos();
  307. r.Bytes( buf,0,4, len );
  308. (* Main AVI Header *)
  309. IF CompareCharArrays(buf, "hdrl",4) THEN
  310. r.Bytes( buf,0,4, len );
  311. IF CompareCharArrays(buf, "avih",4) THEN
  312. aviHeader := ReadMainAVIHeader()
  313. ELSE
  314. SkipHeader()
  315. END;
  316. (* Stream Header *)
  317. ELSIF CompareCharArrays( buf, "strl",4 ) THEN
  318. r.Bytes( buf,0,4, len );
  319. IF CompareCharArrays( buf, "strh",4 ) THEN
  320. tempHeader := ReadAVIStreamHeader();
  321. IF CompareCharArrays(tempHeader.fccType, "vids",4) THEN
  322. r.SkipBytes(4); (* Skip "strf" *)
  323. IF videoStreamHeader = NIL THEN
  324. videoStreamHeader := tempHeader;
  325. videoStreamHeader.streamIdentifier[0] := "0";
  326. videoStreamHeader.streamIdentifier[1] := CHR( ORD( '0' ) + streamNumber );
  327. videoStreamHeader.streamIdentifier[2] := "d";
  328. videoStreamHeader.streamIdentifier[3] := "c";
  329. INC(streamNumber)
  330. END;
  331. tempHeader := NIL;
  332. IF videoStreamHeader.bitMapInfo = NIL THEN
  333. videoStreamHeader.bitMapInfo := ReadBitMapInfo();
  334. videoStreamHeader.waveFormatEx := NIL
  335. ELSE
  336. SkipHeader()
  337. END;
  338. ELSIF CompareCharArrays(tempHeader.fccType, "auds",4) THEN
  339. r.SkipBytes(4);
  340. IF audioStreamHeader = NIL THEN
  341. audioStreamHeader := tempHeader;
  342. audioStreamHeader.streamIdentifier[0] := "0";
  343. audioStreamHeader.streamIdentifier[1] := CHR( ORD('0') + streamNumber );
  344. audioStreamHeader.streamIdentifier[2] := "w";
  345. audioStreamHeader.streamIdentifier[3] := "b";
  346. INC(streamNumber)
  347. END;
  348. tempHeader := NIL;
  349. IF audioStreamHeader.waveFormatEx = NIL THEN
  350. audioStreamHeader.waveFormatEx := ReadWaveFormatEx();
  351. audioStreamHeader.bitMapInfo := NIL
  352. ELSE
  353. SkipHeader()
  354. END;
  355. ELSE
  356. IF Debug THEN
  357. KernelLog.String( "AVIDemux: Unknown AviStream found; " ); KernelLog.String(tempHeader.fccType);
  358. KernelLog.Ln()
  359. END;
  360. END;
  361. END;
  362. ELSIF CompareCharArrays(buf, "movi",4) THEN
  363. (* movie data begin, including movi Tag *)
  364. movieBeginPos := r.Pos()-4;
  365. (* this could be improved... *)
  366. r.SetPos(headerLength+movieBeginPos); (* headerLength); *)
  367. r.Bytes(buf,0,4,len);
  368. IF CompareCharArrays(buf, "idx1",4) THEN
  369. (* There is an index *)
  370. (* Start of Index including idx1 Tag *)
  371. indexStart := r.Pos()-4;
  372. ReadIndex();
  373. IF Debug THEN
  374. KernelLog.String("AVIDemux: Start of movie stream found " ); KernelLog.Ln()
  375. END;
  376. ELSE
  377. videoIndex := NIL;
  378. audioIndex := NIL;
  379. END;
  380. r.SetPos(movieBeginPos+4);
  381. done := TRUE;
  382. ELSE
  383. IF Debug THEN
  384. KernelLog.String("AVIDemux: Unknown StreamHeader found: " ); KernelLog.String(buf); KernelLog.Ln()
  385. END;
  386. r.SkipBytes( headerLength - ( r.Pos() - headerBeginPos ) )
  387. END;
  388. ELSE
  389. (* Unknown Header -> Skip *)
  390. IF Debug THEN
  391. KernelLog.String("AVIDemux: Unknown Header found: " ); KernelLog.Buffer(buf,0,4); KernelLog.Ln()
  392. END;
  393. SkipHeader();
  394. END;
  395. UNTIL done;
  396. IF Debug THEN
  397. DumpHeaders();
  398. END;
  399. RETURN TRUE
  400. END ReadHeader;
  401. (* Noch ueberlegen: BOOLEAN Rueckgabe, wenn kein Index dann False *)
  402. PROCEDURE ReadIndex*;
  403. VAR
  404. buf : ARRAY 8 OF CHAR;
  405. buf2 : ARRAY 8 OF CHAR;
  406. indexLength: LONGINT;
  407. nidx: LONGINT;
  408. idxType: INTEGER;
  409. i: LONGINT;
  410. pos: LONGINT;
  411. length: LONGINT;
  412. len: LONGINT;
  413. temp: LONGINT;
  414. nai: LONGINT;
  415. nvi: LONGINT;
  416. tot: LONGINT;
  417. ioff: LONGINT;
  418. BEGIN
  419. r.RawLInt(indexLength);
  420. nidx := indexLength DIV 16;
  421. idxType := 0;
  422. i := 0;
  423. LOOP
  424. r.Bytes(buf, 0, 4, len);
  425. IF CompareCharArrays(buf, videoStreamHeader.streamIdentifier, 3) THEN
  426. i := i+1;
  427. (* Not shure, wether this is necessary - but everything works fine with it *)
  428. indexStart := r.Pos()-4;
  429. EXIT;
  430. END;
  431. IF i >= nidx THEN
  432. KernelLog.String("No Index found"); KernelLog.Ln();
  433. EXIT;
  434. END;
  435. END;
  436. r.SkipBytes(4);
  437. r.RawLInt(pos);
  438. r.RawLInt(length);
  439. r.SetPos(pos);
  440. (* Index from start of File*)
  441. IF CompareCharArrays(buf2, buf, 4) THEN
  442. r.RawLInt(temp);
  443. IF (temp = length) THEN
  444. idxType := 1;
  445. END;
  446. ELSE
  447. r.SetPos(pos + movieBeginPos);
  448. r.Bytes(buf2, 0, 4, len);
  449. IF CompareCharArrays(buf2, buf, 4) THEN
  450. r.RawLInt(temp);
  451. IF (temp = length) THEN
  452. idxType := 2;
  453. END;
  454. END;
  455. END;
  456. (* now go on according to indexType *)
  457. IF idxType = 0 THEN
  458. KernelLog.String("File without index: Not supported yet");
  459. (* And trap here ... *)
  460. END;
  461. (* The 0 case: no index. It is possible to generate an index b y traversing the whole file *)
  462. (* For now we simply declare the file as not seekable *)
  463. IF idxType # 0 THEN
  464. nai := 0;
  465. nvi := 0;
  466. r.SetPos(indexStart);
  467. i := 0;
  468. (* Count, how many entries there are (the number would also be in the header, *)
  469. (* but if there is no index, you have to do this anyway) *)
  470. REPEAT
  471. r.Bytes(buf, 0, 4, len);
  472. IF CompareCharArrays(buf, videoStreamHeader.streamIdentifier, 3) THEN
  473. nvi := nvi+1;
  474. ELSE
  475. IF audioStreamHeader # NIL THEN
  476. IF CompareCharArrays(buf, audioStreamHeader.streamIdentifier, 4) THEN
  477. nai := nai+1;
  478. END;
  479. END;
  480. END;
  481. r.SkipBytes(12);
  482. i := i+1;
  483. UNTIL (i = nidx-1);
  484. videoFrames := nvi;
  485. audioChunks := nai;
  486. NEW(videoIndex, nvi);
  487. (* Vielleicht haben wir ja nur Bilder... *)
  488. IF (audioChunks > 0) THEN
  489. NEW(audioIndex, nai);
  490. END;
  491. (* So, und jetzt die Arrays fuellen *)
  492. nvi := 0;
  493. nai := 0;
  494. tot := 0;
  495. r.SetPos(indexStart);
  496. IF (idxType = 1) THEN
  497. ioff := 8;
  498. ELSE
  499. ioff := movieBeginPos;
  500. END;
  501. i := 0;
  502. REPEAT
  503. r.Bytes(buf, 0, 4, len);
  504. IF CompareCharArrays(buf, videoStreamHeader.streamIdentifier, 3) THEN
  505. r.RawLInt(videoIndex[nvi].flags);
  506. r.RawLInt(videoIndex[nvi].offset);
  507. videoIndex[nvi].offset := videoIndex[nvi].offset + ioff;
  508. r.RawLInt(videoIndex[nvi].length);
  509. nvi := nvi+1;
  510. ELSE
  511. IF CompareCharArrays(buf, audioStreamHeader.streamIdentifier, 4) THEN
  512. r.SkipBytes(4);
  513. r.RawLInt(audioIndex[nai].offset);
  514. audioIndex[nai].offset := audioIndex[nai].offset + ioff;
  515. r.RawLInt(audioIndex[nai].length);
  516. audioIndex[nai].tot := tot;
  517. tot := tot + audioIndex[nai].length;
  518. nai := nai+1;
  519. END;
  520. END;
  521. i := i+1;
  522. UNTIL (i = nidx-1);
  523. audioBytes := tot;
  524. END;
  525. END ReadIndex;
  526. (* Skip chunk *)
  527. PROCEDURE SkipHeader*;
  528. VAR
  529. length: LONGINT;
  530. BEGIN
  531. r.RawLInt(length);
  532. r.SkipBytes( length + length MOD 2)
  533. END SkipHeader;
  534. (* Read Main AVI Header *)
  535. PROCEDURE ReadMainAVIHeader(): MainAVIHeaderDesc;
  536. VAR
  537. aviHeader: MainAVIHeaderDesc;
  538. headerLength: LONGINT;
  539. startPos: LONGINT;
  540. BEGIN
  541. NEW( aviHeader );
  542. r.RawLInt(headerLength);
  543. startPos := r.Pos();
  544. r.RawLInt( aviHeader.microSecsPerFrame );
  545. r.RawLInt( aviHeader.maxBytesPerSec );
  546. r.RawLInt( aviHeader.reserved1 );
  547. r.RawLInt( aviHeader.flags );
  548. r.RawLInt( aviHeader.totalFrames );
  549. r.RawLInt( aviHeader.initialFrames );
  550. r.RawLInt( aviHeader.streams );
  551. r.RawLInt( aviHeader.suggestedBufferSize );
  552. r.RawLInt( aviHeader.width );
  553. r.RawLInt( aviHeader.height );
  554. r.RawLInt( aviHeader.reserved[0] );
  555. r.RawLInt( aviHeader.reserved[1] );
  556. r.RawLInt( aviHeader.reserved[2] );
  557. r.RawLInt( aviHeader.reserved[3] );
  558. (* Skip Bytes if we have still available *)
  559. IF r.Pos() - startPos < headerLength THEN
  560. r.SkipBytes( headerLength - ( r.Pos() - startPos ) )
  561. END;
  562. RETURN aviHeader;
  563. END ReadMainAVIHeader;
  564. (* Read Header of this avi Stream *)
  565. PROCEDURE ReadAVIStreamHeader(): AVIStreamHeader;
  566. VAR
  567. header: AVIStreamHeader;
  568. headerLength: LONGINT;
  569. startPos: LONGINT;
  570. len: LONGINT;
  571. temp: INTEGER;
  572. BEGIN
  573. NEW(header);
  574. r.RawLInt(headerLength);
  575. startPos := r.Pos();
  576. r.Bytes( header.fccType,0,4, len );
  577. r.Bytes( header.fccHandler,0,4, len );
  578. r.RawLInt( header.flags );
  579. r.RawLInt( header.priority );
  580. r.RawLInt( header.initialFrames );
  581. r.RawLInt( header.scale );
  582. r.RawLInt( header.rate );
  583. r.RawLInt( header.start );
  584. r.RawLInt( header.length );
  585. r.RawLInt( header.suggestedBufferSize );
  586. r.RawLInt( header.quality );
  587. r.RawLInt( header.sampleSize );
  588. r.RawInt( temp ); header.left := temp;
  589. r.RawInt( temp ); header.top := temp;
  590. r.RawInt( temp ); header.right := temp;
  591. r.RawInt( temp ); header.bottom := temp;
  592. (* Skio Bytes if we have still available *)
  593. IF r.Pos() - startPos < headerLength THEN
  594. r.SkipBytes( headerLength - ( r.Pos() - startPos ) )
  595. END;
  596. RETURN header
  597. END ReadAVIStreamHeader;
  598. (* Read BitMapInfo Structure *)
  599. PROCEDURE ReadBitMapInfo(): BitMapInfo;
  600. VAR
  601. header: BitMapInfo;
  602. headerLength: LONGINT;
  603. startPos: LONGINT;
  604. temp: INTEGER;
  605. BEGIN
  606. NEW(header);
  607. r.RawLInt(headerLength);
  608. startPos := r.Pos();
  609. r.RawLInt( header.size );
  610. r.RawLInt( header.width );
  611. r.RawLInt( header.height );
  612. r.RawInt( temp ); header.planes := temp;
  613. r.RawInt( temp ); header.bitCount := temp;
  614. r.RawLInt( header.compression );
  615. r.RawLInt( header.sizeImage );
  616. r.RawLInt( header.xPelsPerMeter );
  617. r.RawLInt( header.yPelsPerMeter );
  618. r.RawLInt( header.clrUsed );
  619. r.RawLInt( header.clrImportant );
  620. IF r.Pos() - startPos < headerLength THEN
  621. r.SkipBytes( headerLength - ( r.Pos() - startPos ) )
  622. END;
  623. RETURN header
  624. END ReadBitMapInfo;
  625. (* Read WaveFormatEX Structure *)
  626. PROCEDURE ReadWaveFormatEx(): WAVEFormatEx;
  627. VAR
  628. header: WAVEFormatEx;
  629. headerLength: LONGINT;
  630. startPos: LONGINT;
  631. temp: INTEGER;
  632. BEGIN
  633. NEW(header);
  634. r.RawLInt(headerLength);
  635. startPos := r.Pos();
  636. r.RawInt( temp ); header.formatTag := temp;
  637. r.RawInt( temp ); header.channels := temp;
  638. r.RawLInt( header.samplesPerSec );
  639. r.RawLInt( header.avgBytesPerSec );
  640. r.RawInt( temp ); header.blockAlign := temp;
  641. r.RawInt( temp ); header.bitsPerSample := temp;
  642. r.RawInt( temp ); header.cbSize := temp;
  643. IF r.Pos() - startPos < headerLength THEN
  644. r.SkipBytes( headerLength - ( r.Pos() - startPos ) )
  645. END;
  646. RETURN header
  647. END ReadWaveFormatEx;
  648. (* Write Avi Headers to KernelLog *)
  649. PROCEDURE DumpHeaders*;
  650. BEGIN
  651. KernelLog.String("AviDemux: Dump of Avi Headers: "); KernelLog.Ln();
  652. IF aviHeader # NIL THEN
  653. KernelLog.String( "aviHeader.microSecsPerFrame = " ); KernelLog.Int( aviHeader.microSecsPerFrame, 0 ); KernelLog.Ln();
  654. KernelLog.String( "aviHeader.maxBytesPerSec = " ); KernelLog.Int( aviHeader.maxBytesPerSec, 0 ); KernelLog.Ln();
  655. KernelLog.String( "aviHeader.reserved1 = " ); KernelLog.Int( aviHeader.reserved1, 0 ); KernelLog.Ln();
  656. KernelLog.String( "aviHeader.flags = " ); KernelLog.Int( aviHeader.flags, 0 ); KernelLog.Ln();
  657. KernelLog.String( "aviHeader.totalFrames = " ); KernelLog.Int( aviHeader.totalFrames, 0 ); KernelLog.Ln();
  658. KernelLog.String( "aviHeader.initialFrames = " ); KernelLog.Int( aviHeader.initialFrames, 0 ); KernelLog.Ln();
  659. KernelLog.String( "aviHeader.streams = " ); KernelLog.Int( aviHeader.streams, 0 ); KernelLog.Ln();
  660. KernelLog.String( "aviHeader.suggestedBufferSize = " ); KernelLog.Int( aviHeader.suggestedBufferSize, 0 ); KernelLog.Ln();
  661. KernelLog.String( "aviHeader.width = " ); KernelLog.Int( aviHeader.width, 0 ); KernelLog.Ln();
  662. KernelLog.String( "aviHeader.height = " ); KernelLog.Int( aviHeader.height, 0 ); KernelLog.Ln();
  663. KernelLog.String( "aviHeader.reserved[0] = " ); KernelLog.Int( aviHeader.reserved[0],0 ); KernelLog.Ln();
  664. KernelLog.String( "aviHeader.reserved[1] = " ); KernelLog.Int( aviHeader.reserved[1],0 ); KernelLog.Ln();
  665. KernelLog.String( "aviHeader.reserved[2] = " ); KernelLog.Int( aviHeader.reserved[2],0 ); KernelLog.Ln();
  666. KernelLog.String( "aviHeader.reserved[3] = " ); KernelLog.Int( aviHeader.reserved[3],0 ); KernelLog.Ln()
  667. ELSE
  668. KernelLog.String("AVIDemux.aviHeader = NIL"); KernelLog.Ln()
  669. END;
  670. IF audioStreamHeader # NIL THEN
  671. KernelLog.String( "audioStreamHeader.fccType = " ); KernelLog.String( audioStreamHeader.fccType ); KernelLog.Ln();
  672. KernelLog.String( "audioStreamHeader.fccHandler = " ); KernelLog.String( audioStreamHeader.fccHandler );
  673. KernelLog.Ln();
  674. KernelLog.String( "audioStreamHeader.flags = " ); KernelLog.Int( audioStreamHeader.flags, 0 ); KernelLog.Ln();
  675. KernelLog.String( "audioStreamHeader.priority = " ); KernelLog.Int( audioStreamHeader.priority, 0 ); KernelLog.Ln();
  676. KernelLog.String( "audioStreamHeader.initialFrames = " ); KernelLog.Int( audioStreamHeader.initialFrames, 0 );
  677. KernelLog.Ln();
  678. KernelLog.String( "audioStreamHeader.scale = " ); KernelLog.Int( audioStreamHeader.scale, 0 ); KernelLog.Ln();
  679. KernelLog.String( "audioStreamHeader.rate = " ); KernelLog.Int( audioStreamHeader.rate, 0 ); KernelLog.Ln();
  680. KernelLog.String( "audioStreamHeader.start = " ); KernelLog.Int( audioStreamHeader.start, 0 ); KernelLog.Ln();
  681. KernelLog.String( "audioStreamHeader.length = " ); KernelLog.Int( audioStreamHeader.length, 0 ); KernelLog.Ln();
  682. KernelLog.String( "audioStreamHeader.suggestedBufferSize = " );
  683. KernelLog.Int( audioStreamHeader.suggestedBufferSize, 0 ); KernelLog.Ln();
  684. KernelLog.String( "audioStreamHeader.quality = " ); KernelLog.Int( audioStreamHeader.quality, 0 ); KernelLog.Ln();
  685. KernelLog.String( "audioStreamHeader.sampleSize = " ); KernelLog.Int( audioStreamHeader.sampleSize, 0 );
  686. KernelLog.Ln();
  687. KernelLog.String( "audioStreamHeader.left = " ); KernelLog.Int( audioStreamHeader.left, 0 ); KernelLog.Ln();
  688. KernelLog.String( "audioStreamHeader.top = " ); KernelLog.Int( audioStreamHeader.top, 0 ); KernelLog.Ln();
  689. KernelLog.String( "audioStreamHeader.right = " ); KernelLog.Int( audioStreamHeader.right, 0 ); KernelLog.Ln();
  690. KernelLog.String( "audioStreamHeader.bottom = " ); KernelLog.Int( audioStreamHeader.bottom, 0 ); KernelLog.Ln();
  691. KernelLog.String( "audioStreamHeader.streamIdentifier = " );
  692. KernelLog.Buffer( audioStreamHeader.streamIdentifier, 0, 4 ); KernelLog.Ln()
  693. ELSE
  694. KernelLog.String("AVIDemux.audioStreamHeader = NIL"); KernelLog.Ln()
  695. END;
  696. IF videoStreamHeader # NIL THEN
  697. KernelLog.String( "videoStreamHeader.fccType = " ); KernelLog.String( videoStreamHeader.fccType ); KernelLog.Ln();
  698. KernelLog.String( "videoStreamHeader.fccHandler = " ); KernelLog.String( videoStreamHeader.fccHandler );
  699. KernelLog.Ln();
  700. KernelLog.String( "videoStreamHeader.flags = " ); KernelLog.Int( videoStreamHeader.flags, 0 ); KernelLog.Ln();
  701. KernelLog.String( "videoStreamHeader.priority = " ); KernelLog.Int( videoStreamHeader.priority, 0 ); KernelLog.Ln();
  702. KernelLog.String( "videoStreamHeader.initialFrames = " ); KernelLog.Int( videoStreamHeader.initialFrames, 0 );
  703. KernelLog.Ln();
  704. KernelLog.String( "videoStreamHeader.scale = " ); KernelLog.Int( videoStreamHeader.scale, 0 ); KernelLog.Ln();
  705. KernelLog.String( "videoStreamHeader.rate = " ); KernelLog.Int( videoStreamHeader.rate, 0 ); KernelLog.Ln();
  706. KernelLog.String( "videoStreamHeader.start = " ); KernelLog.Int( videoStreamHeader.start, 0 ); KernelLog.Ln();
  707. KernelLog.String( "videoStreamHeader.length = " ); KernelLog.Int( videoStreamHeader.length, 0 ); KernelLog.Ln();
  708. KernelLog.String( "videoStreamHeader.suggestedBufferSize = " );
  709. KernelLog.Int( videoStreamHeader.suggestedBufferSize, 0 ); KernelLog.Ln();
  710. KernelLog.String( "videoStreamHeader.quality = " ); KernelLog.Int( videoStreamHeader.quality, 0 ); KernelLog.Ln();
  711. KernelLog.String( "videoStreamHeader.sampleSize = " ); KernelLog.Int( videoStreamHeader.sampleSize, 0 );
  712. KernelLog.Ln();
  713. KernelLog.String( "videoStreamHeader.streamIdentifier = " );
  714. KernelLog.Buffer( videoStreamHeader.streamIdentifier, 0, 4 ); KernelLog.Ln()
  715. ELSE
  716. KernelLog.String("AVIDemux.videoStreamHeader = NIL"); KernelLog.Ln()
  717. END;
  718. IF videoStreamHeader.bitMapInfo # NIL THEN
  719. KernelLog.String( "bitMapInfo.size = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.size ,0 ); KernelLog.Ln();
  720. KernelLog.String( "bitMapInfo.width = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.width ,0 ); KernelLog.Ln();
  721. KernelLog.String( "bitMapInfo.height = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.height ,0 ); KernelLog.Ln();
  722. KernelLog.String( "bitMapInfo.planes = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.planes ,0 ); KernelLog.Ln();
  723. KernelLog.String( "bitMapInfo.bitCount = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.bitCount ,0 ); KernelLog.Ln();
  724. KernelLog.String( "bitMapInfo.compression = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.compression ,0 ); KernelLog.Ln();
  725. KernelLog.String( "bitMapInfo.sizeImage = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.sizeImage ,0 ); KernelLog.Ln();
  726. KernelLog.String( "bitMapInfo.xPelsPerMeter = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.xPelsPerMeter ,0 ); KernelLog.Ln();
  727. KernelLog.String( "bitMapInfo.yelsPerMeter = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.yPelsPerMeter ,0 ); KernelLog.Ln();
  728. KernelLog.String( "bitMapInfo.clrUsed = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.clrUsed ,0 ); KernelLog.Ln();
  729. KernelLog.String( "bitMapInfo.clrImportant = " ); KernelLog.Int( videoStreamHeader.bitMapInfo.clrImportant ,0 ); KernelLog.Ln()
  730. ELSE
  731. KernelLog.String("AVIDemux.bitMapInfo = NIL"); KernelLog.Ln()
  732. END;
  733. IF (audioStreamHeader # NIL) & (audioStreamHeader.waveFormatEx # NIL) THEN
  734. KernelLog.String( "waveFormat.formatTag = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.formatTag ,0 ); KernelLog.Ln();
  735. KernelLog.String( "waveFormat.channel = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.channels ,0 ); KernelLog.Ln();
  736. KernelLog.String( "waveFormat.samplesPerSec = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.samplesPerSec ,0 ); KernelLog.Ln();
  737. KernelLog.String( "waveFormat.avgBytesPerSec = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.avgBytesPerSec ,0 ); KernelLog.Ln();
  738. KernelLog.String( "waveFormat.blockAlign = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.blockAlign ,0 ); KernelLog.Ln();
  739. KernelLog.String( "waveFormat.bitsPerSample = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.bitsPerSample ,0 ); KernelLog.Ln();
  740. KernelLog.String( "waveFormat.cbSize = " ); KernelLog.Int( audioStreamHeader.waveFormatEx.cbSize ,0 ); KernelLog.Ln()
  741. ELSE
  742. KernelLog.String("AVIDemux.waveFormat = NIL"); KernelLog.Ln()
  743. END;
  744. KernelLog.Ln()
  745. END DumpHeaders;
  746. (* Write AVI video index to Kernel Log *)
  747. PROCEDURE DumpVideoIndex*;
  748. VAR i : LONGINT;
  749. BEGIN
  750. KernelLog.String("AviDemux: Dump of Video-Index: "); KernelLog.Ln();
  751. IF videoIndex = NIL THEN KernelLog.String("no index in AVI"); KernelLog.Ln; RETURN END;
  752. FOR i := 0 TO LEN(videoIndex)-1 DO
  753. KernelLog.String("Index: "); KernelLog.Int(i, 0);
  754. KernelLog.String(" ckid= "); KernelLog.Int(videoIndex[i].ckid, 0);
  755. KernelLog.String(" flags= "); KernelLog.Int(videoIndex[i].flags, 0);
  756. KernelLog.String(" offset= "); KernelLog.Int(videoIndex[i].offset, 0);
  757. KernelLog.String(" length= "); KernelLog.Int(videoIndex[i].length, 0);
  758. KernelLog.String(" tot= "); KernelLog.Int(videoIndex[i].tot, 0);
  759. IF (i > 0) THEN KernelLog.String(" deltaOFF= "); KernelLog.Int(videoIndex[i].offset - videoIndex[i-1].offset, 0); END;
  760. KernelLog.Ln;
  761. END
  762. END DumpVideoIndex;
  763. (* Write AVI audio index to Kernel Log *)
  764. PROCEDURE DumpAudioIndex*;
  765. VAR i : LONGINT;
  766. BEGIN
  767. KernelLog.String("AviDemux: Dump of Audio-Index: "); KernelLog.Ln();
  768. IF audioIndex = NIL THEN KernelLog.String("no index in AVI"); KernelLog.Ln; RETURN END;
  769. FOR i := 0 TO LEN(audioIndex)-1 DO
  770. KernelLog.String("Index: "); KernelLog.Int(i, 0);
  771. KernelLog.String(" ckid= "); KernelLog.Int(audioIndex[i].ckid, 0);
  772. KernelLog.String(" flags= "); KernelLog.Int(audioIndex[i].flags, 0);
  773. KernelLog.String(" offset= "); KernelLog.Int(audioIndex[i].offset, 0);
  774. KernelLog.String(" length= "); KernelLog.Int(audioIndex[i].length, 0);
  775. KernelLog.String(" tot= "); KernelLog.Int(audioIndex[i].tot, 0);
  776. IF (i > 0) THEN KernelLog.String(" deltaOFF= "); KernelLog.Int(audioIndex[i].offset - audioIndex[i-1].offset, 0); END;
  777. KernelLog.Ln;
  778. END
  779. END DumpAudioIndex;
  780. (* Return AudioStreamHeader *)
  781. PROCEDURE GetAudioStreamHeader*(): AVIStreamHeader;
  782. BEGIN
  783. RETURN audioStreamHeader
  784. END GetAudioStreamHeader;
  785. (* Return VideoStreamHeader *)
  786. PROCEDURE GetVideoStreamHeader*():AVIStreamHeader;
  787. BEGIN
  788. RETURN videoStreamHeader
  789. END GetVideoStreamHeader;
  790. (* Muss noch generischer werden *)
  791. PROCEDURE GetStream*(streamNr: LONGINT): AOC.DemuxStream;
  792. VAR
  793. (* reader : AVIReader; *)
  794. (* reader: AOC.FileInputStream; *)
  795. reader : Streams.Reader;
  796. i: LONGINT;
  797. streamInfo : AOC.AVStreamInfo;
  798. tag : ARRAY 4 OF CHAR;
  799. BEGIN
  800. reader := AOC.OpenInputStream(filename); (* should be only one reader ideally... *)
  801. reader.SetPos(r.Pos());
  802. IF streamNr = 0 THEN
  803. NEW(videoStream, reader, videoStreamHeader);
  804. videoFramePos := 0;
  805. (* Add streamInfo to Stream *)
  806. streamInfo.streamType := AOC.STVideo;
  807. FOR i := 0 TO 3 DO streamInfo.contentType[i] := videoStreamHeader.fccHandler[i] END;
  808. IF videoIndex = NIL THEN streamInfo.seekability := {};
  809. ELSE streamInfo.seekability := {3,4}; END;
  810. streamInfo.length := videoFrames;
  811. streamInfo.frames := videoFrames;
  812. streamInfo.rate := videoStreamHeader.rate;
  813. videoStream.streamInfo := streamInfo;
  814. RETURN videoStream;
  815. ELSE
  816. NEW(audioStream, reader, audioStreamHeader);
  817. audioFramePos := 0;
  818. (* Add streamInfo to Stream *)
  819. streamInfo.streamType := AOC.STAudio;
  820. IF (audioStreamHeader.waveFormatEx # NIL) THEN
  821. CASE audioStreamHeader.waveFormatEx.formatTag OF
  822. 1 : COPY("PCM", tag);
  823. | 85: COPY("MP3", tag);
  824. ELSE
  825. END;
  826. FOR i := 0 TO 3 DO streamInfo.contentType[i] := tag[i]; END;
  827. END;
  828. IF audioIndex = NIL THEN streamInfo.seekability := {};
  829. ELSE streamInfo.seekability := {1,2}; END;
  830. streamInfo.length := audioStreamHeader.length*GetSampleSize();
  831. streamInfo.frames := audioChunks;
  832. streamInfo.rate := audioStreamHeader.rate;
  833. audioStream.streamInfo := streamInfo;
  834. RETURN audioStream;
  835. END;
  836. END GetStream;
  837. PROCEDURE GetMilliSecondsPerFrame*(): LONGINT;
  838. BEGIN
  839. RETURN aviHeader.microSecsPerFrame DIV 1000;
  840. END GetMilliSecondsPerFrame;
  841. PROCEDURE GetNofChannels*(): LONGINT;
  842. BEGIN
  843. RETURN audioStreamHeader.waveFormatEx.channels;
  844. END GetNofChannels;
  845. PROCEDURE GetSamplesPerSecond*(): LONGINT;
  846. BEGIN
  847. RETURN audioStreamHeader.waveFormatEx.samplesPerSec;
  848. END GetSamplesPerSecond;
  849. PROCEDURE GetBitsPerSample*(): LONGINT;
  850. BEGIN
  851. RETURN audioStreamHeader.waveFormatEx.bitsPerSample;
  852. END GetBitsPerSample;
  853. PROCEDURE GetVideoIndex*(): IndexArrayPointer;
  854. BEGIN
  855. RETURN videoIndex;
  856. END GetVideoIndex;
  857. PROCEDURE GetAudioIndex*(): IndexArrayPointer;
  858. BEGIN
  859. RETURN audioIndex;
  860. END GetAudioIndex;
  861. PROCEDURE GetAudioChunks*(): LONGINT;
  862. BEGIN
  863. RETURN audioChunks;
  864. END GetAudioChunks;
  865. PROCEDURE GetAudioBytes*(): LONGINT;
  866. BEGIN
  867. RETURN audioBytes;
  868. END GetAudioBytes;
  869. PROCEDURE GetVideoFrames*(): LONGINT;
  870. BEGIN
  871. RETURN videoFrames;
  872. END GetVideoFrames;
  873. PROCEDURE GetNumberOfStreams*(): LONGINT;
  874. BEGIN
  875. RETURN aviHeader.streams;
  876. END GetNumberOfStreams;
  877. (* Could be optimized, as we assume videostream beeing at index 0 and that there is only one *)
  878. PROCEDURE GetStreamInfo*(streamNr: LONGINT): AOC.AVStreamInfo;
  879. VAR streamInfo : AOC.AVStreamInfo;
  880. i: INTEGER;
  881. tag : ARRAY 4 OF CHAR;
  882. BEGIN
  883. IF streamNr = 0 THEN (* Video *)
  884. streamInfo.streamType := AOC.STVideo;
  885. FOR i := 0 TO 3 DO
  886. streamInfo.contentType[i] := videoStreamHeader.fccHandler[i];
  887. END;
  888. IF videoIndex = NIL THEN
  889. streamInfo.seekability := {};
  890. ELSE
  891. streamInfo.seekability := {3,4};
  892. END;
  893. streamInfo.length := videoFrames;
  894. streamInfo.frames := videoFrames;
  895. streamInfo.rate := videoStreamHeader.rate;
  896. ELSE (* Audio *)
  897. streamInfo.streamType := AOC.STAudio;
  898. IF (audioStreamHeader.waveFormatEx # NIL) THEN
  899. CASE audioStreamHeader.waveFormatEx.formatTag OF
  900. 1 : COPY("PCM", tag);
  901. | 85: COPY("MP3", tag);
  902. ELSE
  903. END;
  904. FOR i := 0 TO 3 DO
  905. streamInfo.contentType[i] := tag[i];
  906. END;
  907. END;
  908. IF audioIndex = NIL THEN
  909. streamInfo.seekability := {};
  910. ELSE
  911. streamInfo.seekability := {1,2};
  912. END;
  913. streamInfo.length := audioStreamHeader.length*GetSampleSize();
  914. streamInfo.frames := audioChunks;
  915. streamInfo.rate := audioStreamHeader.rate;
  916. END;
  917. RETURN streamInfo
  918. END GetStreamInfo;
  919. PROCEDURE GetStreamType*(streamNr : LONGINT): LONGINT;
  920. VAR type : LONGINT;
  921. BEGIN
  922. IF streamNr = 0 THEN type := AOC.STVideo;
  923. ELSIF streamNr = 1 THEN type := AOC.STAudio;
  924. ELSE type := AOC.STUnknown;
  925. END;
  926. RETURN type
  927. END GetStreamType;
  928. (* Returns Information, which can be read out from file and which is useful/needed *)
  929. PROCEDURE GetInfo*(VAR vl, vf, vr, mspf, al, af, ar : LONGINT);
  930. BEGIN
  931. vl := videoFrames;
  932. vf := videoFrames;
  933. vr := videoStreamHeader.rate;
  934. mspf := aviHeader.microSecsPerFrame;
  935. IF audioStreamHeader # NIL THEN
  936. al := audioStreamHeader.length*GetSampleSize();
  937. af := audioChunks;
  938. ar := audioStreamHeader.rate;
  939. END;
  940. END GetInfo;
  941. PROCEDURE GetData*(streamNr: LONGINT; VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
  942. VAR
  943. rres: BOOLEAN;
  944. BEGIN
  945. IF streamNr = 0 THEN
  946. IF videoIndex # NIL THEN
  947. IF videoFramePos < videoFrames THEN
  948. len := videoIndex[videoFramePos].length;
  949. IF (len > (size-4)) THEN
  950. len := len+4;
  951. res := AOC.ResFailed;
  952. RETURN;
  953. END;
  954. rres := videoStream.Resynch(buf);
  955. INC(videoFramePos);
  956. IF rres THEN
  957. videoStream.res := Streams.Ok;
  958. res := AOC.ResOk;
  959. ELSE
  960. res := AOC.ResFailed;
  961. videoStream.res := Streams.EOF;
  962. END
  963. ELSE
  964. res := AOC.ResFailed;
  965. videoStream.res := Streams.EOF;
  966. len := 0;
  967. END;
  968. END;
  969. ELSE
  970. IF audioIndex # NIL THEN
  971. IF audioFramePos < audioChunks THEN
  972. len := audioIndex[audioFramePos].length;
  973. IF (LEN(buf) < len+4) THEN
  974. len := len+4;
  975. res := AOC.ResFailed;
  976. audioStream.res := Streams.EOF;
  977. RETURN;
  978. END;
  979. len := audioIndex[audioFramePos].length;
  980. rres := audioStream.Resynch(buf);
  981. INC(audioFramePos);
  982. IF rres THEN
  983. audioStream.res := Streams.Ok;
  984. res := AOC.ResOk;
  985. ELSE
  986. (* res := AOC.ResFailed; *)
  987. audioStream.res := Streams.EOF;
  988. END
  989. ELSE
  990. res := AOC.ResFailed;
  991. audioStream.res := Streams.EOF;
  992. len := 0;
  993. END;
  994. END;
  995. END;
  996. END GetData;
  997. PROCEDURE SetStreamPos*(streamNr: LONGINT; seekType: LONGINT; pos: LONGINT; VAR itemSize: LONGINT; VAR res: WORD);
  998. (* PROCEDURE SetStreamPos*(streamNr, pos : LONGINT; VAR res: WORD); *)
  999. VAR
  1000. n0, n1, n, spos: LONGINT;
  1001. (* seekType, itemSize : LONGINT; *)
  1002. BEGIN
  1003. IF Debug THEN KernelLog.String("AVIDemux.SetStreamPos: "); KernelLog.Int(pos, 0); KernelLog.Ln; END;
  1004. IF streamNr = 0 THEN
  1005. IF videoIndex # NIL THEN
  1006. IF seekType = AOC.SeekKeyFrame THEN
  1007. IF pos > itemSize THEN
  1008. IF pos >= videoStreamHeader.length-1 THEN
  1009. pos := videoStreamHeader.length-1;
  1010. ELSE
  1011. WHILE ((pos < videoFrames-1) & (videoIndex[pos].flags # 16)) DO
  1012. INC(pos);
  1013. END;
  1014. END;
  1015. ELSE
  1016. IF(pos > 0) THEN
  1017. DEC(pos);
  1018. END;
  1019. WHILE ((videoIndex[pos].flags # 16) & (pos > 0)) DO
  1020. DEC(pos);
  1021. END;
  1022. END;
  1023. END;
  1024. IF ((seekType = AOC.SeekFrame) OR (seekType = AOC.SeekKeyFrame)) THEN
  1025. IF pos < LEN(videoIndex) THEN
  1026. videoStream.SetAVIPos(videoIndex[pos].offset, itemSize);
  1027. itemSize := pos;
  1028. videoFramePos := pos;
  1029. END
  1030. ELSE
  1031. videoStream.SetAVIPos(pos, itemSize);
  1032. END;
  1033. END;
  1034. ELSE
  1035. IF audioIndex # NIL THEN
  1036. IF seekType = AOC.SeekSample THEN
  1037. IF pos < 0 THEN
  1038. pos := 0;
  1039. END;
  1040. IF pos = 0 THEN
  1041. n0 := 0;
  1042. ELSE
  1043. n0 := 0;
  1044. n1 := audioChunks;
  1045. WHILE (n0 < n1 - 1) DO
  1046. n := (n0 + n1) DIV 2;
  1047. IF (audioIndex[n].tot > pos) THEN
  1048. n1 := n;
  1049. ELSE
  1050. n0 := n;
  1051. END;
  1052. END;
  1053. END;
  1054. audioStream.SetAVIPos(audioIndex[n0].offset, itemSize);
  1055. audioFramePos := n0;
  1056. ELSIF seekType = AOC.SeekByte THEN
  1057. (* spos := ENTIER(pos * 8 * audioStreamHeader.waveFormatEx.samplesPerSec/audioStreamHeader.rate / 1000); *)
  1058. spos := ENTIER(pos / audioStreamHeader.rate * audioStreamHeader.waveFormatEx.samplesPerSec);
  1059. IF Debug THEN KernelLog.String("spos= "); KernelLog.Int(spos, 0); KernelLog.Ln; END;
  1060. IF spos < 0 THEN spos := 0 END;
  1061. IF spos = 0 THEN n0 := 0
  1062. ELSE
  1063. n0 := 0;
  1064. n1 := audioChunks;
  1065. WHILE (n0 < n1 - 1) DO
  1066. n := (n0 + n1) DIV 2;
  1067. IF (audioIndex[n].tot > spos) THEN
  1068. n1 := n;
  1069. ELSE
  1070. n0 := n;
  1071. END;
  1072. END;
  1073. END;
  1074. audioStream.SetAVIPos(audioIndex[n0].offset, itemSize);
  1075. audioFramePos := n0;
  1076. IF Debug THEN
  1077. KernelLog.String("audioIndex[n].tot= "); KernelLog.Int(audioIndex[n].tot, 0);
  1078. KernelLog.String("audioIndex[n0].offset= "); KernelLog.Int(audioIndex[n0].offset, 0);
  1079. KernelLog.String("audioFramePos= "); KernelLog.Int(audioFramePos, 0);
  1080. KernelLog.String("itemSize= "); KernelLog.Int(itemSize, 0); KernelLog.Ln;
  1081. END
  1082. ELSE
  1083. audioStream.SetAVIPos(pos, itemSize);
  1084. END;
  1085. END;
  1086. END;
  1087. END SetStreamPos;
  1088. PROCEDURE GetVideoWidth*(): LONGINT;
  1089. BEGIN
  1090. RETURN videoStreamHeader.bitMapInfo.width;
  1091. END GetVideoWidth;
  1092. PROCEDURE GetVideoHeight*(): LONGINT;
  1093. BEGIN
  1094. RETURN videoStreamHeader.bitMapInfo.height;
  1095. END GetVideoHeight;
  1096. PROCEDURE GetNextFrameSize*(streamNr: LONGINT): LONGINT;
  1097. BEGIN
  1098. IF streamNr = 0 THEN
  1099. IF videoFramePos < videoFrames THEN
  1100. RETURN videoIndex[videoFramePos].length;
  1101. ELSE
  1102. RETURN AOC.ResFailed;
  1103. END;
  1104. ELSE
  1105. IF audioFramePos < audioChunks THEN
  1106. RETURN audioIndex[audioFramePos].length;
  1107. ELSE
  1108. RETURN AOC.ResFailed;
  1109. END;
  1110. END;
  1111. END GetNextFrameSize;
  1112. PROCEDURE GetSampleSize*(): LONGINT;
  1113. VAR
  1114. s: LONGINT;
  1115. BEGIN
  1116. s := ((audioStreamHeader.waveFormatEx.bitsPerSample+7) DIV 8)*audioStreamHeader.waveFormatEx.channels;
  1117. IF s = 0 THEN
  1118. s := 1;
  1119. END;
  1120. RETURN s;
  1121. END GetSampleSize;
  1122. END AVIDemux;
  1123. (* -- Helper Procedures -- *)
  1124. (* Align stream to next Byte *)
  1125. PROCEDURE Align*(VAR index: LONGINT);
  1126. BEGIN
  1127. IF ( index MOD 8 ) # 0 THEN
  1128. index := index - ( index MOD 8 ) + 8
  1129. END;
  1130. END Align;
  1131. (* True if actual position is on byte boundary *)
  1132. PROCEDURE IsAligned*(index: LONGINT): BOOLEAN;
  1133. BEGIN
  1134. IF ( index MOD 8 ) = 0 THEN
  1135. RETURN TRUE;
  1136. ELSE
  1137. RETURN FALSE;
  1138. END;
  1139. END IsAligned;
  1140. (* Read next n Bits (max 32), without advancing in stream. Max 32 Bits are allowed *)
  1141. (* Very slow but portable *)
  1142. PROCEDURE ShowBitsSlow*( n: LONGINT; VAR buf: ARRAY OF CHAR; VAR index: LONGINT): LONGINT;
  1143. VAR
  1144. ret: LONGINT;
  1145. count: LONGINT;
  1146. BEGIN
  1147. ret := 0;
  1148. count := 0;
  1149. WHILE count < n DO
  1150. ret := ret * 2;
  1151. IF ( 7 - ( index MOD 8 ) ) IN SYSTEM.VAL( SET, buf[index DIV 8] ) THEN
  1152. INC(ret)
  1153. END;
  1154. INC( index );
  1155. INC( count )
  1156. END;
  1157. index := index - count;
  1158. RETURN ret
  1159. END ShowBitsSlow;
  1160. (* Read next n Bits (max 32), without advancing in stream. Max 32 Bits are allowed *)
  1161. (* Fast, but im not sure if it's portable *)
  1162. PROCEDURE ShowBits*( n: LONGINT; VAR buf: ARRAY OF CHAR; VAR index: LONGINT): LONGINT;
  1163. VAR
  1164. nbit: LONGINT;
  1165. posInLONGINT: LONGINT;
  1166. bufa, bufb: LONGINT;
  1167. temp: LONGINT;
  1168. bufAdr: LONGINT;
  1169. BEGIN
  1170. bufAdr := ADDRESSOF( buf[0] );
  1171. posInLONGINT := index MOD 32;
  1172. nbit := ( posInLONGINT+ n ) - 32;
  1173. IF nbit > 0 THEN
  1174. (* We have to read two 32 bit values *)
  1175. temp := LSH( index - posInLONGINT , -3 ) + bufAdr;
  1176. bufa := Machine.ChangeByteOrder( SYSTEM.GET32( temp ) );
  1177. bufb := Machine.ChangeByteOrder( SYSTEM.GET32( temp + 4 ) );
  1178. temp := LSH( LSH( bufa, posInLONGINT ), nbit - posInLONGINT );
  1179. RETURN SYSTEM.VAL( LONGINT, SYSTEM.VAL( SET, LSH( bufb, nbit - 32 ) ) + SYSTEM.VAL( SET, temp ) )
  1180. ELSE
  1181. (* Reading one 32 value is sufficient *)
  1182. bufa := Machine.ChangeByteOrder( SYSTEM.GET32( LSH( index - posInLONGINT, -3 ) + bufAdr ) );
  1183. RETURN LSH( LSH( bufa, posInLONGINT ), n - 32 )
  1184. END;
  1185. END ShowBits;
  1186. (* Show n bits, byte aligned without advancing in bit stream *)
  1187. PROCEDURE ShowBitsByteAligned*(n: LONGINT; VAR buf: ARRAY OF CHAR; VAR index: LONGINT): LONGINT;
  1188. VAR
  1189. count: LONGINT;
  1190. ret: LONGINT;
  1191. BEGIN
  1192. count := 8 - ( index MOD 8 );
  1193. IF count = 8 THEN
  1194. IF ShowBits(8, buf, index) = 7FH THEN (* Spezial case: see iso spec *)
  1195. count := 8
  1196. ELSE
  1197. count := 0
  1198. END;
  1199. END;
  1200. index := index + count;
  1201. ret := ShowBits(n, buf, index);
  1202. index := index - count;
  1203. RETURN ret
  1204. END ShowBitsByteAligned;
  1205. (* Read next n Bits and advance in Bit Stream. Max 32 Bits are allowed *)
  1206. PROCEDURE GetBits*( n: LONGINT; VAR buf: ARRAY OF CHAR; VAR index: LONGINT): LONGINT;
  1207. VAR
  1208. ret: LONGINT;
  1209. BEGIN
  1210. ret := ShowBits(n, buf, index);
  1211. SkipBits(n, index);
  1212. RETURN ret
  1213. END GetBits;
  1214. (* Skip Next n Bits *)
  1215. PROCEDURE SkipBits*(n: LONGINT; VAR index: LONGINT );
  1216. BEGIN
  1217. index := index + n
  1218. END SkipBits;
  1219. PROCEDURE Factory*() : AOC.AVDemultiplexer;
  1220. VAR p: AVIDemux;
  1221. BEGIN
  1222. NEW(p);
  1223. RETURN p
  1224. END Factory;
  1225. END AVI.