📄 unampglibapi.pas
字号:
result := mpglib_error_noProc;
end
else
result := 0;
end
else begin
//
result := mpglib_error_noLib;
dec(proto.r_refCount);
end;
end
else begin
//
inc(proto.r_refCount);
result := 0;
end;
end;
// -- --
function unloadLib(var proto: mpglib_proto): int;
begin
if (1 = proto.r_refCount) then begin
//
proto.r_module := 0;
proto.r_initMP3 := nil;
proto.r_decodeMP3 := nil;
proto.r_exitMP3 := nil;
//
dec(proto.r_refCount);
end
else
if (0 < proto.r_refCount) then
dec(proto.r_refCount);
//
result := 0;
end;
var
globalLock: unaInProcessGate;
{ unaMpgLibDecoder }
// -- --
procedure unaMpgLibDecoder.afterConstruction();
begin
inherited;
//
f_inStream := unaMemoryStream.create();
f_inStream.maxCacheSize := 128;
//
f_MPSTR := malloc(32*1024); // 32 K
loadLibrary(f_proto.r_libName);
end;
// -- --
procedure unaMpgLibDecoder.beforeDestruction();
begin
inherited;
//
unloadLibrary();
mrealloc(f_MPSTR);
freeAndNil(f_inStream);
end;
// -- --
procedure unaMpgLibDecoder.close();
begin
stop();
end;
// -- --
constructor unaMpgLibDecoder.create(const libName: string);
begin
inherited create();
//
f_proto.r_libName := libName;
end;
// -- --
procedure unaMpgLibDecoder.doWrite(data: pointer; len: unsigned);
begin
f_inStream.write(data, len);
//
wakeUp();
end;
// -- --
function unaMpgLibDecoder.execute(threadIndex: unsigned): int;
var
size: unsigned;
chunk: pArray;
chunkSize: unsigned;
outChunk: array[word] of byte;
res: int;
done: int;
i: unsigned;
entered: bool;
nothing: bool;
giveUp: unsigned;
offset: unsigned;
mpegVer: int;
layer: int;
notUsed: bool;
begin
chunkSize := MAXFRAMESIZE;
chunk := malloc(chunkSize);
res := 0;
mpegVer := -1;
layer := -1;
//
try
while (not shouldStop) do begin
//
f_inStream.waitForData(100);
//
if (0 = f_errorCode) then begin
//
while (not shouldStop and (0 < f_inStream.getFirstChunkSize())) do begin
//
size := f_inStream.read(chunk, chunkSize);
offset := 0;
//
while (0 < size) do begin
//
if (0 = res) then begin
// try to locate FF
i := offset;
repeat
//
while (not shouldStop and
(i < size - 2) and
(
($FF <> chunk[i]) or
($F0 <> (chunk[i + 1] and $F0)) or
($00 = (chunk[i + 1] and $06)) or
($F0 = (chunk[i + 2] and $F0)) or
($0C = (chunk[i + 2] and $0C)) or
((0 <= mpegVer) and (mpegVer <> ((chunk[i + 1] and $08) shr 3))) or
((0 < layer) and (layer <> ((chunk[i + 1] and $06) shr 1)))
)
) do
inc(i);
//
if (i < size - 2) then begin
//
dec(size, i);
move(chunk[i], chunk[0], size);
i := 1;
//
if (0 > mpegVer) then
mpegVer := (chunk[1] and $08) shr 3;
//
if (1 > layer) then
layer := (chunk[1] and $06) shr 1;
//
if (0 < f_ensureLayer) then begin
//
case (f_ensureLayer) of
1: if (3 <> layer) then begin
mpegVer := -1;
layer := -1;
end;
2: if (2 <> layer) then begin
mpegVer := -1;
layer := -1;
end;
3: if (1 <> layer) then begin
mpegVer := -1;
layer := -1;
end;
end;
//
end;
end
else
size := 0; // skip over to next block of data
//
until (shouldStop or (1 > size) or ((0 < layer) and (0 <= mpegVer)));
end;
//
giveUp := 100;
entered := false;
repeat
//
if (globalLock.enter(100)) then begin
//
try
if (0 < size) then begin
//
try
res := f_proto.r_decodeMP3(f_MPSTR, chunk, size, @outChunk, sizeOf(outChunk), done)
except
// ignore all soft errors
res := MP3_ERR;
done := 0;
layer := -1;
mpegVer := -1;
end;
//
end
else
done := 0;
//
finally
globalLock.leave();
end;
//
entered := true;
end
else
dec(giveUp);
//
until (entered or shouldStop or (1 > giveUp));
//
if (1 > giveUp) then
inc(f_enterFails);
//
nothing := (1 > done) and (0 = res);
//
while (not shouldStop and entered and (0 = res) and (0 < done)) do begin
//
notUsed := true; // compatibility with older code
notifyData(@outChunk, done, notUsed);
//
//
giveUp := 100;
entered := false;
repeat
//
if (globalLock.enter(100)) then begin
//
try
//
try
res := f_proto.r_decodeMP3(f_MPSTR, nil, 0, @outChunk, sizeOf(outChunk), done);
except
// ignore all soft errors
res := MP3_ERR;
done := 0;
layer := -1;
mpegVer := -1;
end;
//
finally
globalLock.leave();
end;
//
entered := true;
end
else
dec(giveUp);
//
until (entered or shouldStop or (1 > giveUp));
//
if (1 > giveUp) then
inc(f_enterFails);
end;
//
if (not shouldStop and (nothing or (MP3_ERR = res))) then begin
// broken stream, re-init MP3
f_proto.r_exitMP3(f_MPSTR);
f_errorCode := choice(f_proto.r_initMP3(f_MPSTR), 0, mpglib_error_initFail);
res := 0;
end;
//
if (MP3_NEED_MORE = res) then
size := 0;
//
if (nothing or (0 = res)) then begin
//
inc(offset, 16);
end;
end;
end;
//
end;
end;
//
finally
//
//chunkSize := 0;
mrealloc(chunk);
end;
//
result := 0;
end;
// -- --
function unaMpgLibDecoder.getInDataSize(): unsigned;
begin
result := f_inStream.getSize();
end;
// -- --
procedure unaMpgLibDecoder.loadLibrary(const libName: string);
begin
unloadLibrary();
//
f_errorCode := loadLib(f_proto, libName);
end;
// -- --
procedure unaMpgLibDecoder.notifyData(data: pointer; size: unsigned; var copyToStream: bool);
var
new_rate: unsigned;
new_channels: unsigned;
begin
new_rate := MPSTR.fr.sampling_frequency;
new_channels:= MPSTR.fr.stereo;
//
if ((f_oldPCM_rate <> new_rate) or (f_oldPCM_channels <> new_channels)) then begin
//
notifySamplingChange(freqs[new_rate], 16, new_channels);
//
f_oldPCM_rate := new_rate;
f_oldPCM_channels := new_channels;
end;
//
if (assigned(f_onDataAvail)) then
f_onDataAvail(self, data, size, copyToStream);
end;
// -- --
procedure unaMpgLibDecoder.notifySamplingChange(rate, bits, channels: unsigned);
begin
if (assigned(f_onApplySampling)) then
f_onApplySampling(self, rate, bits, channels);
end;
// -- --
function unaMpgLibDecoder.open(): int;
begin
start();
//
result := 0;
end;
// -- --
procedure unaMpgLibDecoder.startIn();
begin
inherited;
//
f_oldPCM_rate := 0;
f_oldPCM_channels := 0;
f_ensureLayer := -1;
//
if (0 = f_errorCode) then
f_errorCode := choice(f_proto.r_initMP3(f_MPSTR), 0, mpglib_error_initFail);
end;
// -- --
procedure unaMpgLibDecoder.startOut();
begin
inherited;
//
if (0 = f_errorCode) then
f_proto.r_exitMP3(f_MPSTR);
end;
// -- --
procedure unaMpgLibDecoder.unloadLibrary();
begin
unloadLib(f_proto);
end;
// -- --
procedure unaMpgLibDecoder.write(data: pointer; len: unsigned);
begin
doWrite(data, len);
end;
initialization
globalLock := unaInProcessGate.create();
finalization
freeAndNil(globalLock);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -