MODULE Codecs;
IMPORT
Streams, Commands, Files, SoundDevices, Raster, Modules, Strings, Configuration, Unzip, Texts, Archives;
CONST
ResFailed* = -1;
ResOk* = 0;
ResSeekInexact* = 1;
ImgFmtBW* = 0;
ImgFmtGrey* = 1;
ImgFmtRGB* = 2;
ImgFmtRGBA* = 3;
STError* = -1;
STUnknown* = 0;
STAudio* = 1;
STVideo* = 2;
STImage* = 3;
SeekByte* = 0;
SeekSample* = 1;
SeekKeySample* = 2;
SeekFrame* = 3;
SeekKeyFrame* = 4;
TYPE
AVStreamInfo* = RECORD
streamType* : LONGINT;
seekability* : SET;
contentType* : ARRAY 16 OF CHAR;
length* : LONGINT;
frames* : LONGINT;
rate*: LONGINT;
END;
FileInputStream* = OBJECT(Streams.Reader)
VAR
r : Files.Rider;
f* : Files.File;
streamInfo*: AVStreamInfo;
PROCEDURE Receive(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
BEGIN
f.ReadBytes(r, buf, ofs, size);
len := size - r.res;
IF len >= min THEN res := Streams.Ok ELSE res := Streams.EOF END
END Receive;
PROCEDURE &InitFileReader*(f : Files.File; pos: LONGINT);
BEGIN
InitReader(SELF.Receive, 4096);
SELF.f := f;
f.Set(r, pos);
streamInfo.seekability := {SeekByte};
END InitFileReader;
PROCEDURE CanSetPos*(): BOOLEAN;
BEGIN
RETURN TRUE;
END CanSetPos;
PROCEDURE SetPos*(pos : LONGINT);
BEGIN
f.Set(r, pos);
Reset;
received := pos;
END SetPos;
END FileInputStream;
AVDemultiplexer* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE GetNumberOfStreams*() : LONGINT;
BEGIN
RETURN 0
END GetNumberOfStreams;
PROCEDURE GetStreamType*(streamNr : LONGINT): LONGINT;
BEGIN
RETURN -1;
END GetStreamType;
PROCEDURE GetStreamInfo*(streamNr : LONGINT): AVStreamInfo;
END GetStreamInfo;
PROCEDURE GetStream*(streamNr: LONGINT): DemuxStream;
END GetStream;
PROCEDURE GetData*(streamNr : LONGINT; VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
END GetData;
PROCEDURE SetStreamPos*(streamNr : LONGINT; seekType : LONGINT; pos : LONGINT; VAR itemSize : LONGINT; VAR res : LONGINT);
END SetStreamPos;
END AVDemultiplexer;
DemuxStream* = OBJECT(Streams.Reader)
VAR
demultiplexer* : AVDemultiplexer;
streamNr* : LONGINT;
streamInfo* : AVStreamInfo;
PROCEDURE& Open*(demultiplexer : AVDemultiplexer; streamNr : LONGINT);
BEGIN
SELF.demultiplexer := demultiplexer;
SELF.streamNr := streamNr;
InitReader(Receive, 4096)
END Open;
PROCEDURE Receive(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
BEGIN
demultiplexer.GetData(streamNr, buf, ofs, size, min, len, res)
END Receive;
PROCEDURE SetPos*(pos : LONGINT);
VAR seekType, itemSize, res: LONGINT;
BEGIN
seekType := SeekByte;
demultiplexer.SetStreamPos(streamNr, seekType, pos, itemSize, res);
Reset
END SetPos;
PROCEDURE SetPosX*(seekType : LONGINT; pos : LONGINT; VAR itemSize : LONGINT; VAR res : LONGINT);
BEGIN
demultiplexer.SetStreamPos(streamNr, seekType, pos, itemSize, res);
Reset
END SetPosX;
END DemuxStream;
AudioDecoder* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE HasMoreData*():BOOLEAN;
END HasMoreData;
PROCEDURE GetAudioInfo*(VAR nofChannels, samplesPerSecond, bitsPerSample : LONGINT);
END GetAudioInfo;
PROCEDURE SetAudioInfo*(nofChannels, samplesPerSecond, bitsPerSample : LONGINT);
END SetAudioInfo;
PROCEDURE CanSeek*() : BOOLEAN;
BEGIN RETURN FALSE
END CanSeek;
PROCEDURE GetCurrentSample*() : LONGINT;
BEGIN HALT(301); RETURN 0
END GetCurrentSample;
PROCEDURE GetTotalSamples*() : LONGINT;
BEGIN HALT(301); RETURN 0
END GetTotalSamples;
PROCEDURE GetCurrentTime*() : LONGINT;
BEGIN HALT(301); RETURN 0
END GetCurrentTime;
PROCEDURE SetStreamLength*(length : LONGINT);
END SetStreamLength;
PROCEDURE SeekSample*(sample: LONGINT; goKeySample : BOOLEAN; VAR res : LONGINT);
END SeekSample;
PROCEDURE SeekMillisecond*(millisecond : LONGINT; goKeySample : BOOLEAN; VAR res : LONGINT);
END SeekMillisecond;
PROCEDURE Next*;
END Next;
PROCEDURE FillBuffer*(buffer : SoundDevices.Buffer);
END FillBuffer;
END AudioDecoder;
AudioEncoder* = OBJECT
PROCEDURE Open*(out : Streams.Writer; sRate, sRes, nofCh: LONGINT; VAR res : LONGINT);
END Open;
PROCEDURE Write*(buffer : SoundDevices.Buffer; VAR res : LONGINT);
END Write;
PROCEDURE Close*(VAR res : LONGINT);
END Close;
END AudioEncoder;
VideoDecoder* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE HasMoreData*():BOOLEAN;
END HasMoreData;
PROCEDURE GetVideoInfo*(VAR width, height, millisecondsPerFrame : LONGINT);
END GetVideoInfo;
PROCEDURE CanSeek*() : BOOLEAN;
BEGIN RETURN FALSE
END CanSeek;
PROCEDURE GetCurrentFrame*() : LONGINT;
END GetCurrentFrame;
PROCEDURE GetCurrentTime*() : LONGINT;
END GetCurrentTime;
PROCEDURE SeekFrame*(frame : LONGINT; goKeyFrame : BOOLEAN; VAR res : LONGINT);
END SeekFrame;
PROCEDURE SeekMillisecond*(millisecond : LONGINT; goKeyFrame : BOOLEAN; VAR res : LONGINT);
END SeekMillisecond;
PROCEDURE Next*;
END Next;
PROCEDURE Render*(img : Raster.Image);
END Render;
END VideoDecoder;
ImageDecoder* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE GetImageInfo*(VAR width, height, format, maxProgressionLevel : LONGINT);
END GetImageInfo;
PROCEDURE SetProgressionLevel*(progressionLevel: LONGINT);
END SetProgressionLevel;
PROCEDURE GetNativeImage*(VAR img : Raster.Image);
END GetNativeImage;
PROCEDURE Render*(img : Raster.Image);
END Render;
END ImageDecoder;
ImageEncoder* = OBJECT
PROCEDURE Open*(out : Streams.Writer);
END Open;
PROCEDURE SetQuality*(quality : LONGINT);
END SetQuality;
PROCEDURE WriteImage*(img : Raster.Image; VAR res : LONGINT);
END WriteImage;
END ImageEncoder;
TextDecoder* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE GetText*() : Texts.Text;
BEGIN
HALT(301); RETURN NIL
END GetText;
END TextDecoder;
TextEncoder* = OBJECT
PROCEDURE Open*(out : Streams.Writer);
END Open;
PROCEDURE WriteText*(text : Texts.Text; VAR res : LONGINT);
END WriteText;
END TextEncoder;
CryptoDecoder* = OBJECT
PROCEDURE Open*(in: Streams.Reader; VAR res: LONGINT);
END Open;
PROCEDURE GetReader*(): Streams.Reader;
END GetReader;
END CryptoDecoder;
CryptoEncoder* = OBJECT
PROCEDURE Open*(out: Streams.Writer);
END Open;
PROCEDURE GetWriter*(): Streams.Writer;
END GetWriter;
END CryptoEncoder;
CONST
Unspecified* = 0;
DoNotDispose* = 1;
RestoreToBackground* = 2;
RestoreToPrevious* = 3;
WaitForUserInput* = 0;
TYPE
ImageDescriptor* = OBJECT
VAR
left*, top*, width*, height* : LONGINT;
image* : Raster.Image;
delayTime* : LONGINT;
disposeMode* : LONGINT;
flags* : SET;
previous*, next* : ImageDescriptor;
PROCEDURE &Init*;
BEGIN
left := 0; top := 0; width := 0; height := 0;
image := NIL;
delayTime := 20; disposeMode := Unspecified;
flags := {};
previous := NIL; next := NIL;
END Init;
END ImageDescriptor;
ImageSequence* = RECORD
width*, height* : LONGINT;
bgColor* : LONGINT;
images* : ImageDescriptor;
END;
AnimationDecoder* = OBJECT
PROCEDURE Open*(in : Streams.Reader; VAR res : LONGINT);
END Open;
PROCEDURE GetImageSequence*(VAR sequence : ImageSequence; VAR res : LONGINT);
END GetImageSequence;
END AnimationDecoder;
TYPE
DemuxFactory = PROCEDURE () : AVDemultiplexer;
AudioDecoderFactory = PROCEDURE () : AudioDecoder;
AudioEncoderFactory = PROCEDURE () : AudioEncoder;
VideoDecoderFactory = PROCEDURE () : VideoDecoder;
ImageDecoderFactory = PROCEDURE () : ImageDecoder;
ImageEncoderFactory = PROCEDURE () : ImageEncoder;
TextDecoderFactory = PROCEDURE () : TextDecoder;
TextEncoderFactory = PROCEDURE () : TextEncoder;
CryptoDecoderFactory = PROCEDURE () : CryptoDecoder;
CryptoEncoderFactory = PROCEDURE () : CryptoEncoder;
AnimationDecoderFactory = PROCEDURE () : AnimationDecoder;
PROCEDURE GetDemuxFactoryName(CONST name : ARRAY OF CHAR; VAR module , procedure : Modules.Name; VAR res : LONGINT);
VAR config, factoryName, msg : ARRAY 128 OF CHAR;
BEGIN
res := ResFailed;
config := "Codecs.Demultiplexer."; Strings.Append(config, name);
Configuration.Get(config, factoryName, res);
IF (res = Configuration.Ok) THEN
Commands.Split(factoryName, module, procedure, res, msg);
END
END GetDemuxFactoryName;
PROCEDURE GetDecoderFactoryName(CONST type, name : ARRAY OF CHAR; VAR module, procedure : Modules.Name; VAR res : LONGINT);
VAR config, factoryName, msg : ARRAY 128 OF CHAR;
BEGIN
res := ResFailed;
config := "Codecs.Decoder."; Strings.Append(config, type); Strings.Append(config, ".");
Strings.Append(config, name);
Configuration.Get(config, factoryName, res);
IF (res = Configuration.Ok) THEN
Commands.Split(factoryName, module, procedure, res, msg);
END
END GetDecoderFactoryName;
PROCEDURE GetEncoderFactoryName(CONST type, name : ARRAY OF CHAR; VAR module, procedure : Modules.Name; VAR res : LONGINT);
VAR config, factoryName, msg : ARRAY 128 OF CHAR;
BEGIN
res := ResFailed;
config := "Codecs.Encoder."; Strings.Append(config, type); Strings.Append(config, ".");
Strings.Append(config, name);
Configuration.Get(config, factoryName, res);
IF (res = Configuration.Ok) THEN
Commands.Split(factoryName, module, procedure, res, msg);
END
END GetEncoderFactoryName;
PROCEDURE GetDemultiplexer*(CONST name : ARRAY OF CHAR) : AVDemultiplexer;
VAR
demux : AVDemultiplexer; factory : DemuxFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
demux := NIL;
GetDemuxFactoryName(name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
demux := factory();
END;
END;
RETURN demux;
END GetDemultiplexer;
PROCEDURE GetImageDecoder*(CONST name : ARRAY OF CHAR) : ImageDecoder;
VAR
decoder : ImageDecoder; factory : ImageDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Image", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetImageDecoder;
PROCEDURE GetImageEncoder*(CONST name : ARRAY OF CHAR) : ImageEncoder;
VAR
encoder : ImageEncoder; factory : ImageEncoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
encoder := NIL;
GetEncoderFactoryName("Image", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
encoder := factory();
END;
END;
RETURN encoder;
END GetImageEncoder;
PROCEDURE GetVideoDecoder*(CONST name : ARRAY OF CHAR) : VideoDecoder;
VAR
decoder : VideoDecoder; factory : VideoDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Video", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetVideoDecoder;
PROCEDURE GetAudioDecoder*(CONST name : ARRAY OF CHAR) : AudioDecoder;
VAR
decoder : AudioDecoder; factory : AudioDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Audio", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetAudioDecoder;
PROCEDURE GetAudioEncoder*(CONST name : ARRAY OF CHAR) : AudioEncoder;
VAR
encoder : AudioEncoder; factory : AudioEncoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
encoder := NIL;
GetEncoderFactoryName("Audio", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
encoder := factory();
END;
END;
RETURN encoder;
END GetAudioEncoder;
PROCEDURE GetTextDecoder*(CONST name : ARRAY OF CHAR) : TextDecoder;
VAR
decoder : TextDecoder; factory : TextDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Text", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetTextDecoder;
PROCEDURE GetTextEncoder*(CONST name : ARRAY OF CHAR) : TextEncoder;
VAR
encoder : TextEncoder; factory : TextEncoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
encoder := NIL;
GetEncoderFactoryName("Text", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
encoder := factory();
END;
END;
RETURN encoder;
END GetTextEncoder;
PROCEDURE GetCryptoDecoder*(CONST name : ARRAY OF CHAR) : CryptoDecoder;
VAR
decoder : CryptoDecoder; factory : CryptoDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Crypto", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetCryptoDecoder;
PROCEDURE GetCryptoEncoder*(CONST name : ARRAY OF CHAR) : CryptoEncoder;
VAR
encoder : CryptoEncoder; factory : CryptoEncoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
encoder := NIL;
GetEncoderFactoryName("Crypto", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
encoder := factory();
END;
END;
RETURN encoder;
END GetCryptoEncoder;
PROCEDURE GetAnimationDecoder*(CONST name : ARRAY OF CHAR) : AnimationDecoder;
VAR
decoder : AnimationDecoder; factory : AnimationDecoderFactory;
moduleName, procedureName : Modules.Name; res : LONGINT;
BEGIN
decoder := NIL;
GetDecoderFactoryName("Animation", name, moduleName, procedureName, res);
IF (res = ResOk) THEN
GETPROCEDURE(moduleName, procedureName, factory);
IF (factory # NIL) THEN
decoder := factory();
END;
END;
RETURN decoder;
END GetAnimationDecoder;
PROCEDURE SplitName*(CONST name : ARRAY OF CHAR; VAR protocol, filename : ARRAY OF CHAR);
VAR pos, i : LONGINT;
BEGIN
pos := Strings.Pos("://", name);
IF pos >= 0 THEN
FOR i := 0 TO pos - 1 DO protocol[i] := name[i] END;
protocol[pos] := 0X;
INC(pos, 3); i := 0; WHILE name[pos] # 0X DO filename[i] := name[pos]; INC(pos); INC(i) END;
filename[i] := 0X
ELSE
COPY("", protocol);
COPY(name, filename)
END
END SplitName;
PROCEDURE JoinName*(CONST protocol, filename : ARRAY OF CHAR; VAR name : ARRAY OF CHAR);
BEGIN
IF (protocol # "") THEN
Strings.Concat(protocol, "://", name); Strings.Concat(name, filename, name);
ELSE
COPY(filename, name);
END;
END JoinName;
PROCEDURE OpenInputStream*(CONST name : ARRAY OF CHAR) : Streams.Reader;
VAR f : Files.File;
is : FileInputStream;
inpStream : Streams.Reader;
r : Streams.Receiver;
tp, protocol, filename : ARRAY 1024 OF CHAR;
zf : Unzip.ZipFile;
entry : Unzip.Entry;
archive : Archives.Archive;
res : LONGINT;
BEGIN
SplitName(name, protocol, filename);
COPY(protocol, tp); Strings.LowerCase(tp);
IF protocol = "" THEN
f := Files.Old(filename);
IF f = NIL THEN RETURN NIL END;
NEW(is, f, 0);
RETURN is
ELSIF Strings.Match("*.zip", tp) THEN
f := Files.Old(protocol);
IF f = NIL THEN RETURN NIL END;
NEW(zf, f, res);
IF res = 0 THEN
entry := zf.FindEntry(filename);
IF entry # NIL THEN
zf.OpenReceiver(r, entry, res);
IF res = 0 THEN
NEW(inpStream, r, 1024);
RETURN inpStream
ELSE RETURN NIL
END
ELSE RETURN NIL
END
ELSE RETURN NIL
END
ELSIF Strings.Match("*.skin", tp) THEN
archive := Archives.Old(protocol, "skin");
IF archive = NIL THEN
RETURN NIL
ELSE
archive.Acquire; r := archive.OpenReceiver(filename); archive.Release;
IF r = NIL THEN
RETURN NIL
ELSE
NEW(inpStream, r, 1024);
RETURN inpStream
END
END
ELSIF Strings.Match("*.tar", tp) OR Strings.Match("*.rep", tp) THEN
archive := Archives.Old(protocol, "tar");
IF archive = NIL THEN
RETURN NIL
ELSE
archive.Acquire; r := archive.OpenReceiver(filename); archive.Release;
IF r = NIL THEN
RETURN NIL
ELSE
NEW(inpStream, r, 1024);
RETURN inpStream
END
END
END;
RETURN NIL
END OpenInputStream;
PROCEDURE OpenOutputStream*(CONST name : ARRAY OF CHAR) : Streams.Writer;
VAR
file : Files.File; w : Files.Writer;
writer : Streams.Writer;
sender : Streams.Sender;
tp, protocol, filename : ARRAY 1024 OF CHAR;
archive : Archives.Archive;
BEGIN
writer := NIL;
SplitName(name, protocol, filename);
COPY(protocol, tp); Strings.LowerCase(tp);
IF protocol = "" THEN
file := Files.New(filename);
IF file # NIL THEN
Files.Register(file);
NEW(w, file, 0); writer := w;
END
ELSIF Strings.Match("*.skin", tp) THEN
archive := Archives.Old(protocol, "skin");
IF archive = NIL THEN archive := Archives.New(protocol, "skin"); END;
IF archive # NIL THEN
archive.Acquire; sender := archive.OpenSender(filename); archive.Release;
IF sender # NIL THEN
NEW(writer, sender, 1024);
END
END
ELSIF Strings.Match("*.tar", tp) OR Strings.Match("*.rep", tp) THEN
archive := Archives.Old(protocol, "tar");
IF archive = NIL THEN archive := Archives.New(protocol, "tar"); END;
IF archive # NIL THEN
archive.Acquire; sender := archive.OpenSender(filename); archive.Release;
IF sender # NIL THEN
NEW(writer, sender, 1024);
END
END
END;
RETURN writer;
END OpenOutputStream;
END Codecs.
--------------------------
SystemTools.Free Codecs~