}
Function QueryVideoCodec(InBMH:TBitmapinfoHeader):TBitmapinfoHeader;
Var
i:byte;
tempicinfo:TICINFO;
temphic:hic;
tempbmh,tempbmh1:TBitmapinfoHeader;
begin
tempbmh:=InBMH;
i:=0;
While (VFW.ICInfo(ICTYPE_VIDEO,i,@tempicinfo)=True)do
begin
temphic:=ICOpen(tempicinfo.fccType,tempicinfo.fccHandler,ICMODE_QUERY);
If (temphic<>0) AND (tempicinfo.fccType=ICTYPE_VIDEO)
AND (VFW.ICCompressQuery(temphic,@tempbmh,nil)=ICERR_OK) then
begin
ICGetInfo(temphic, @tempicinfo, sizeof(tempicinfo));
If tempicinfo.szName='DIVXMPG4 V3' then
procedure DropFrame;
function PackFrame(ImageData: Pointer;
var IsKeyFrame: Boolean;
var Size: Cardinal): Pointer;
function UnpackFrame(ImageData: Pointer;
KeyFrame: Boolean;
var Size: Cardinal): Pointer;
function CompressImage(ImageData: Pointer;
Quality: Integer;
var Size: Cardinal): HBITMAP;
function DecompressImage(ImageData: Pointer): HBITMAP;
function PackBitmap(Bitmap: TBitmap;
var IsKeyFrame: Boolean;
var Size: Cardinal): Pointer;
function UnpackBitmap(ImageData: Pointer;
KeyFrame: Boolean;
Bitmap: TBitmap): Boolean;
function GetBitmapInfoIn: TBitmapInfo;
function GetBitmapInfoOut: TBitmapInfo;
ReallocMem(FPrevBuffer, 0);
ReallocMem(FBuffCompOut, 0);
ReallocMem(FBuffDeCompOut, 0);
ReallocMem(pConfigData, 0);
// these could be freed by ICCompressFree
// but Ido
n't know what that function REALLYdo
es !
CloseDrivers;
ClearCompVars(cv);
inherited;
end;
procedure TVideoCoDec.ClearCompVars(var CompVars: TCompVars);
begin
// Retrieve compressor information.
FillChar(info, SizeOf(info), 0);
FLastError:=ICGetInfo(cv.hic, @info, SizeOf(info));
Result:=FLastError <> 0;
if not Result then
// Work around a bug in Huffyuv. Ben tried to save some memory
// and specified a "near-worst-case" bound in the codec instead
// of the actual worst case bound. Unfortunately, it's actually
// not that hard to exceed the codec's estimate with noisy
// captures -- the most common way is accidentally capturing
// static from a non-existent channel.
//
// According to the 2.1.1 comments, Huffyuv uses worst-case
// values of 24-bpp for YUY2/UYVY and 40-bpp for RGB, while the
// actual worst case values are 43 and 51. We'll compute the
// 43/51 value, and use the higher of the two.
if info.fccHandler = MKFOURCC('U', 'Y', 'F', 'H') then
// Save configuration state.
//
// Ordinarily, we wouldn'tdo
this, but there seems to be a bug in
// the Microsoft MPEG-4 compressor that causes it to reset its
// configuration data after a compression session. This occurs
// in all versions from V1 through V3.
//
// Stupid fscking Matrox driver returns -1!!!
cbConfigData:=ICGetStateSize(cv.hic);
if cbConfigData > 0 then
begin
ReallocMem(pConfigData, cbConfigData);
cbConfigData:=ICGetState(cv.hic, pConfigData, cbConfigData);
// As odd as this may seem, if this isn'tdo
ne, then
the Indeo5
// compressor won't allow data rate control until the next
// compression operation!
function TVideoCoDec.StartCompressor: Boolean;
begin
FFrameNum:=0;
FCompressorStarted:=false;
// Start compression process
FLastError:=ICCompressbegin
(cv.hic, @(cv.lpbiIn^.bmiHeader), @(cv.lpbiOut^.bmiHeader));
Result:=FLastError = ICERR_OK;
if not Result then
exit;
// Start decompression process if necessary
if Assigned(FPrevBuffer) then
begin
FLastError:=ICDecompressbegin
(cv.hic, @(cv.lpbiOut^.bmiHeader), @(cv.lpbiIn^.bmiHeader));
Result:=FLastError = ICERR_OK;
if not Result then
begin
ICCompressEnd(cv.hic);
exit;
end;
end;
FCompressorStarted:=true;
end;
function TVideoCoDec.StartDecompressor: Boolean;
begin
Result:=ICCompressorChoose(0, ICMF_CHOOSE_DATARATE or ICMF_CHOOSE_KEYFRAME,
nil {maybe check input format ? @(cv.lpbiIn^.bmiHeader)}, nil, @pc, nil);
// copy the original input format as it will be copied back in SetCompVars
pc.lpbiIn:=AllocMem(SizeOf(TBitmapInfo));
CopyMemory(pc.lpbiIn, cv.lpbiIn, SizeOf(TBitmapInfo));
if Result then
begin
SetCompVars(pc);
InternalInit(pc.hic > 0);
end;
ClearCompVars(pc);
end;
procedure TVideoCoDec.ConfigureCompressor;
begin
if cv.hic > 0 then
FLastError:=ICConfigure(cv.hic, 0);
end;
function TVideoCoDec.CompressImage(ImageData: Pointer;
Quality: Integer;
var Size: Cardinal): HBITMAP;
begin
function TVideoCoDec.PackFrame(ImageData: Pointer;
var IsKeyFrame: Boolean;
var Size: Cardinal): Pointer;
var
dwChunkId: Cardinal;
dwFlags: Cardinal;
dwFlagsIn: Cardinal;
sizeImage: Cardinal;
lAllowableFrameSize: Cardinal;
lKeyRateCounterSave: Cardinal;
bNoOutputProduced: Boolean;
begin
Size:=0;
Result:=nil;
if not FCompressorStarted then
exit;
dwChunkId:=0;
dwFlags:=0;
dwFlagsIn:=ICCOMPRESS_KEYFRAME;
lAllowableFrameSize:=0;//xFFFFFF; // yes, this is illegal according to thedo
cs (see below)
lKeyRateCounterSave:=FKeyRateCounter;
// Figure out if we should force a keyframe. If wedo
n't have any
// keyframe interval, force only the first frame. Otherwise, make
// sure that the key interval is lKeyRate or less. We count from
// the last emitted keyframe, since the compressor can opt to
// make keyframes on its own.
if FForceKeyFrameRate then
begin
if (cv.lKey = 0) then
begin
if (FFrameNum > 0) then
dwFlagsIn:=0;
end
else
begin
Dec(FKeyRateCounter);
if (FKeyRateCounter > 0) then
dwFlagsIn:=0
else
FKeyRateCounter:=cv.lKey;
end;
end
else
dwFlagsIn:=0;
// Figure out how much space to give the compressor, if we are using
// data rate stricting. If the compressor takes up less than quota
// on a frame, save the space for later frames. If the compressor
// uses too much, reduce the quota for successive frames, butdo
not
// reduce below half datarate.
if (FMaxFrameSize > 0) then
begin
lAllowableFrameSize:=FMaxFrameSize + (FSlopSpace shr 2);
if (lAllowableFrameSize < (FMaxFrameSize shr 1)) then
lAllowableFrameSize:=FMaxFrameSize shr 1;
end;
// A couple of notes:
//
// o ICSeqCompressFrame() passes 0x7FFFFFFF when data rate control
// is inactive. do
cs say 0. We pass 0x7FFFFFFF here to avoid
// a bug in the Indeo 5 QC driver, which page faults if
// keyframe interval=0 and max frame size = 0.
// If we're using a compressor with a stupid algorithm (Microsoft Video 1),
// we have to decompress the frame again to compress the next one....
if (FLastError = ICERR_OK) and Assigned(FPrevBuffer) and
((cv.lKey = 0) or (FKeyRateCounter > 1)) then
function TVideoCoDec.UnpackBitmap(ImageData: Pointer;
KeyFrame: Boolean;
Bitmap: TBitmap): Boolean;
var Size: Cardinal;
lpData: Pointer;
bmi: TBitmapInfo;
bmih: TBitmapInfoHeader;
usage, paintmode: Integer;
begin
Result:=Assigned(ImageData) and Assigned(Bitmap);
if not Result then
exit;
try
bmi:=BIInput;
bmih:=bmi.bmiHeader;
lpData:=UnpackFrame(ImageData, KeyFrame, Size);
Result:=Assigned(lpData) and (Size > 0);
if not Result then
exit;
usage:=IIF(bmih.biClrUsed = 0, DIB_RGB_COLORS, DIB_PAL_COLORS);
PaintMode:=IIF(KeyFrame, SRCCOPY, MERGECOPY);
with Bitmapdo
// typecast the List.Objects as Cardinal to get the fccHandler code !
function TVideoCoDec.EnumCodecs(List: TStrings): Integer;
var pII: TICINFO;
c: Integer;
ok: Boolean;
fccType: TFourCC;
hIC: Cardinal;
begin
c:=0;
List.Clear;
fccType.AsString:='vidc';
ZeroMemory(@pII, SizeOf(pII));
repeat
ok:=ICInfo(fccType.AsCardinal, c, @pII);
if ok then
begin
Inc(c);
// open the compressor ..
// should get all the info with ICInfo but itdo
esn't ?!?!
// this slows the whole thing quite a bit .. about 0.5 - 1 sec !
hIC:=ICOpen(fccType.AsCardinal, pII.fccHandler, ICMODE_COMPRESS);
if hIC > 0 then
function WriteSample(Index: Integer;
cbSize: Cardinal;
lpData: Pointer;
Flags: Cardinal): Boolean;
function AddSample(cbSize: Cardinal;
lpData: Pointer;
Flags: Cardinal): Boolean;
function ReadSample(Index: Integer;
cbSize: Cardinal;
lpData: Pointer): Boolean;
function DeleteSamples(Index, Count: Cardinal): Integer;
procedure SetName(Value: string);
// returns the FOURCC code of the type
function GetStreamType: Cardinal;
property Name: string read FName write SetName;
// streams name ... just to eat more memory
property Stream: IAVIStream read FStream;
// direct acces to the stream object if needed
property StreamType: Cardinal read GetStreamType;
// the streams type (streamtypeVIDEO/AUDIO, ...)
property Samples: Cardinal read FSamples;
// number of samples in the stream
end;