一个视频聊天程序,我安装了对应的编码器,能成功压缩,能接收到数据但不能成功解压,请大家帮忙修改下
相信需要改的地方不多,不要改变程序的整体模式,
改完测试成功后请发至邮箱[email protected]程序在地址http://e.ys168.com/?slmax
改完后400分相送。地址在http://topic.csdn.net/u/20100909/20/d31df1ac-2321-42bd-8b62-8fb619403423.html
相信需要改的地方不多,不要改变程序的整体模式,
改完测试成功后请发至邮箱[email protected]程序在地址http://e.ys168.com/?slmax
改完后400分相送。地址在http://topic.csdn.net/u/20100909/20/d31df1ac-2321-42bd-8b62-8fb619403423.html
解决方案 »
- 编译安装控件时出现Required package 'rtl' not found
- 请(DELPHI+ADO)高手诊断
- 关于使用VCL Skin 控件后程序出错(请大家帮忙)急!!!!!!!!
- 列举出某应用程序的主窗口以外的其它窗口
- 求一xp界面控件!
- 关于Delphi的WEB开发
- 请问Frame在IntraWeb中是怎样用的?????
- 请指点!!!
- 一个有关wm_DeviceChange中的Wparam和Lparam的问题,是否可以这样用解决RegisterDeviceNotification
- delphi7 小票据基本设置 程序例子 谁有啊?
- IdHttp获得源码、同一个网站为何有时是乱码、有时正常?
- 请教:delphi7 按F9运行报错.
看了你的代碼,程序的關鍵在於視頻的壓縮和解壓縮部分,按照我的方式修改:
以下為視頻解壓關鍵部分代碼:
服務器端解壓視頻數據處理//下面的代碼是Delphi的處理方法: //接著,一起來看看用戶端的圖像顯示過程: //CapVar是COMPVARS物件 C++的定義為 COMPVARS CapVar; //先用取得的CapVar來連接視訊轉碼器 //Capvar.fccHandler是使用用戶端一樣的解碼器 CapVar.hic := ICOpen(CapVar.fccType,CapVar.fccHandler,ICMODE_DECOMPRESS); //成功後,用伺服器傳來的BmpOutInfo當作用戶端的BmpInInfo來取得解壓輸出的圖像頭BmpOutInfo //獲得參數 OutFormatSize:=ICDecompressGetFormatSize(CapVar.hic,@BmpInInfo.bmiHeader); //分配記憶體 GetMem(BmpOutInfo,OutFormatSize); //初始化 zeromemory(BmpOutInfo,OutFormatSize); //設置參數 ICDecompressGetFormat(CapVar.hic, @BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader); //設置參數 OutBufferSize:=BmpOutInfo^.bmiHeader.biSizeImage; //分配記憶體 getmem(OutBuffer,OutBufferSize); //初始化 zeromemory(OutBuffer,OutBufferSize); //解壓縮開始 ICDecompressBegin(CapVar.hic,@BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader); //最後,當然是視頻資料的解壓過程 //如果是關鍵幀 if VIDEO_DATA.bKeyFrame then Result:=ICDecompress(CapVar.hic,0,@BmpInInfo,@VIDEO_DATA.Buf,@BmpOutInfo.bmiHeader,OutBuffer) //如果是普通幀 else Result:=ICDecompress(CapVar.hic,ICDECOMPRESS_NOTKEYFRAME,@BmpInInfo,@VIDEO_DATA.Buf,@BmpOutInfo.bmiHeader,OutBuffer); //如果解壓成功 if (Result=ICERR_OK) then begin //將圖像畫出來 SetDIBitsToDevice(Canvas.Handle,0,0,bmptmp.Width,bmptmp.Height,0,0,0,BmpOutInfo^.bmiHeader.biHeight ,OutBuffer,BmpOutInfo^,DIB_RGB_COLORS); end; //下面的代碼是Delphi的處理方法: //接著,一起來看看用戶端的圖像顯示過程: //CapVar是COMPVARS物件 C++的定義為 COMPVARS CapVar; //先用取得的CapVar來連接視訊轉碼器 //Capvar.fccHandler是使用用戶端一樣的解碼器 CapVar.hic := ICOpen(CapVar.fccType,CapVar.fccHandler,ICMODE_DECOMPRESS); //成功後,用伺服器傳來的BmpOutInfo當作用戶端的BmpInInfo來取得解壓輸出的圖像頭BmpOutInfo //獲得參數 OutFormatSize:=ICDecompressGetFormatSize(CapVar.hic,@BmpInInfo.bmiHeader); //分配記憶體 GetMem(BmpOutInfo,OutFormatSize); //初始化 zeromemory(BmpOutInfo,OutFormatSize); //設置參數 ICDecompressGetFormat(CapVar.hic, @BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader); //設置參數 OutBufferSize:=BmpOutInfo^.bmiHeader.biSizeImage; //分配記憶體 getmem(OutBuffer,OutBufferSize); //初始化 zeromemory(OutBuffer,OutBufferSize); //解壓縮開始 ICDecompressBegin(CapVar.hic,@BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader); //最後,當然是視頻資料的解壓過程 //如果是關鍵幀 if VIDEO_DATA.bKeyFrame then Result:=ICDecompress(CapVar.hic,0,@BmpInInfo,@VIDEO_DATA.Buf,@BmpOutInfo.bmiHeader,OutBuffer) //如果是普通幀 else Result:=ICDecompress(CapVar.hic,ICDECOMPRESS_NOTKEYFRAME,@BmpInInfo,@VIDEO_DATA.Buf,@BmpOutInfo.bmiHeader,OutBuffer); //如果解壓成功 if (Result=ICERR_OK) then begin //將圖像畫出來 SetDIBitsToDevice(Canvas.Handle,0,0,bmptmp.Width,bmptmp.Height,0,0,0,BmpOutInfo^.bmiHeader.biHeight ,OutBuffer,BmpOutInfo^,DIB_RGB_COLORS); end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, ExtCtrls,VFW,IdSocketHandle;type
TForm1 = class(TForm)
Image1: TImage;
VideoReceiver: TIdUDPServer;
procedure FormShow(Sender: TObject);
procedure VideoReceiverUDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
private
{ Private declarations }
public
{ Public declarations }
procedure InitDeCompressor;
procedure FillBitmapStruc;
end;
type VideoData=record buf:array[0..8079] of byte; //压缩后的视频数据 Num:integer;//帧数据过大时,分几个数据包发送,数据包在这一帧中的编号 IsLast:boolean;//是否是这一帧的最后一个数据包end;VarFCV: TCOMPVARS;//帧压缩结构FInInfo: TBitmapInfo;//解压时输入结构FOutInfo: TBitmapInfo;//解压时输出结构FoutActSize: DWORD;//压缩后帧数据的大小OutFormatSize,OutBufferSize:DWORD;Buf: array of Byte;// 未解压时帧数据myout:array[0..230399] of byte;// 解压后帧数据 Form1: TForm1;implementation{$R *.dfm}//填充BMP头结构procedure TForm1.FillBitmapStruc;begin FillChar(FInInfo.bmiHeader, SizeOf(TBitmapInfoHeader), 0); with FInInfo.bmiHeader do begin biBitCount := 24; biCompression := BI_RGB; biHeight := 240; biPlanes := 1; biSize := SizeOf(TBitmapInfoHeader); biWidth := 320; end;end;//初始化压缩引擎procedure TForm1.InitDeCompressor;
var
sResult,a,b:DWORD;
begin FillChar(FCV, SizeOf(FCV), 0); with FCV do begin dwFlags := ICDECOMPRESS_NOTKEYFRAME; cbSize := SizeOf(FCV); cbState := 0; fccHandler := mmioFOURCC('x','v','i','d'); //选择压缩引擎,这里选择divx fccType := ICTYPE_VIDEO; hic := ICOpen(ICTYPE_VIDEO,fccHandler, ICMODE_DECOMPRESS); lDataRate := 780; lKey := 15; lFrame := 0; lKeyCount :=0; lpbiIn :=nil; lpbiOut :=nil; lpBitsPrev :=nil; lpState := nil; lQ :=dword(ICQUALITY_DEFAULT); if hic <> 0 then begin OutFormatSize:=ICCompressGetFormatSize(FCV.hic,@FInInfo.bmiHeader); ShowMessage(IntToStr(OutFormatSize)); FillChar(FOutInfo, SizeOf(FOutInfo), 0); a:=ICCompressGetFormat(hic, @FInInfo, @FOutInfo); ShowMessage(IntToStr(a)); FInInfo.bmiHeader.biCompression:=BI_RGB; FOutInfo.bmiHeader.biCompression:=fccHandler; sResult:=ICDecompressBegin(FCV.hic,@FInInfo.bmiHeader, @FOutInfo.bmiHeader); ShowMessage(IntToStr(sResult));
end; end;end;
procedure TForm1.FormShow(Sender: TObject);
begin
FillBitmapStruc; InitDeCompressor; VideoReceiver.Active:=true;end;
procedure TForm1.VideoReceiverUDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
var RetVal:integer; MyVideo:VideoData; i:integer;begin RetVal:=-1; AData.Position:=0; //读取数据 AData.ReadBuffer(MyVideo,sizeof(MyVideo)); if MyVideo.Num=1 then SetLength(buf,0); SetLength(buf,(MyVideo.Num)*8080); for i:=0 to 8079 do begin buf[(MyVideo.Num-1)*8080+i]:=MyVideo.buf[i]; end; if MyVideo.IsLast then //当前帧最后一个数据包 begin //解压数据 RetVal := ICDeCompress(FCV.hic,0,@FoutInfo.bmiHeader,@Buf,@FOutInfo.bmiHeader,@myout); if RetVal= ICERR_OK then begin //在Image1上画出一帧图像 StretchDIBits(Image1.Canvas.Handle,0,0,Image1.Width,Image1.Height,0,0,FOutInfo.bmiHeader.biWidth,FOutInfo.bmiHeader.biHeight,@myout,FOutInfo,0,SRCCOPY ); Image1.Repaint; end
else
begin
ShowMessage(IntToStr(RetVal));
end; end; end;
end.
unit unVCMVideoProcess;interface
uses
Windows,SysUtils,vfw,unVideoProcess;type
// 压缩
TVCMEncode=class(TInterfacedObject,IVideoProcess)
private
CapVar: TCOMPVARS;
pvdData :PVideoData;
protected public
constructor Create(ch0, ch1, ch2, ch3: AnsiChar);
destructor Destroy; override;
//
function InitProcess(pbiInfo:PBitmapInfo):Integer;stdcall;
procedure EndProcess();stdcall;
function DoProcess(Data :PByte;Len:DWORD; var ReturnData :PByte;var ReturnLen:DWORD
):Integer;stdcall;
end;
//解码
TVCMDecode=class(TInterfacedObject,IVideoProcess)
private
pDeReturn:PByte;
CapVar: TCOMPVARS;
pbiInfoOut:PBitmapInfo;
protected public
constructor Create(ch0, ch1, ch2, ch3: AnsiChar);
destructor Destroy; override;
//
function InitProcess(pbiInfo:PBitmapInfo):Integer;stdcall;
procedure EndProcess();stdcall;
function DoProcess(Data :PByte;Len:DWORD; var ReturnData :PByte;var ReturnLen:DWORD
):Integer;stdcall;
end;
implementation
{ TVideoProcessCompress }constructor TVCMEncode.Create(ch0, ch1, ch2, ch3: AnsiChar);
begin
inherited Create;
pvdData :=nil; Zeromemory(@CapVar,sizeof(TCOMPVARS));
//初始化CapVar CapVar.cbSize:=sizeof(CapVar); //必须指定cbSize为TCOMPVARS结构大小
CapVar.dwFlags:=ICMF_COMPVARS_VALID;
CapVar.cbState:=0;
//fccHandler代表压缩编码类型,我们使用的是DIVX的编码器
CapVar.fccHandler:=mmioFOURCC(ch0,ch1,ch2,ch3);
CapVar.fccType:=ICTYPE_VIDEO;
end;destructor TVCMEncode.Destroy;
begin
EndProcess;
if Assigned(pvdData) then
begin
FreeMemory(pvdData);
pvdData:=nil;
end; inherited;end;function TVCMEncode.DoProcess(Data :PByte;Len:DWORD; var ReturnData :PByte;var ReturnLen:DWORD):Integer;
var
bKeyFrame : BOOL ;
pBuf:PByte;
dwDataLen:DWORD;begin
Result:=0;
ReturnData:=nil; if CapVar.hic=0 then
begin
Result:=-1;
Exit;
end;
pBuf := ICSeqCompressFrame(@CapVar,0,Data,@bKeyFrame,@dwDataLen);
if not Assigned(pBuf) then
begin
Result:=-2;
Exit;
end;
ReturnLen:= dwDataLen+Sizeof(TVideoData);
if Assigned(pvdData) then
begin
FreeMemory(pvdData);
pvdData:=nil;
end;
pvdData:=GetMemory(ReturnLen);
pvdData.KeyFrame:= Byte( bKeyFrame); CopyMemory( @pvdData^.BitmapInfo,CapVar.lpbiOut,SizeOf(TBitmapInfo) );
pvdData^.DataLen:=dwDataLen;
CopyMemory( @pvdData^.Data[0] ,pBuf ,dwDataLen);
ReturnData:=PByte(pvdData);
end;
procedure TVCMEncode.EndProcess;
begin
if (CapVar.hic > 0) then
begin
ICSeqCompressFrameEnd(@CapVar);
ICCompressorFree(@CapVar);
ICClose(CapVar.hic);
CapVar.hic:=0;
end;end;function TVCMEncode.InitProcess(pbiInfo: PBitmapInfo): Integer;
begin
Result :=0;
//正式连接编码器
CapVar.hic:=ICOpen(ICTYPE_VIDEO, CapVar.fccHandler, ICMODE_COMPRESS);
if (CapVar.hic=0) then
begin
Result:=-1;
Exit;
end;// dwOutFormatSize:=ICCompressGetFormatSize(CapVar.hic, pbiInfo);
// pbiInfoOut:=GetMemory(dwOutFormatSize);
// ICCompressGetFormat(CapVar.hic,pbiInfo,pbiInfoOut);
ICSeqCompressFrameStart(@CapVar, pbiInfo);
end;
{ TVideoProcessDeCompress }constructor TVCMDecode.Create(ch0, ch1, ch2, ch3: AnsiChar);
begin
inherited Create;
Zeromemory(@CapVar,sizeof(TCOMPVARS)); //初始化CapVar
pDeReturn:=nil;
CapVar.cbSize:=sizeof(CapVar); //必须指定cbSize为TCOMPVARS结构大小
CapVar.dwFlags:=ICMF_COMPVARS_VALID;
CapVar.cbState:=0;
//fccHandler代表压缩编码类型,我们使用的是DIVX的编码器
CapVar.fccHandler:=mmioFOURCC(ch0,ch1,ch2,ch3);
CapVar.fccType:=ICTYPE_VIDEO;
end;destructor TVCMDecode.Destroy;
begin
EndProcess;
if Assigned(pDeReturn) then
begin
FreeMemory(pDeReturn);
pDeReturn:=nil;
end;
inherited;
end;function TVCMDecode.DoProcess( Data :PByte;Len:DWORD; var ReturnData :PByte;var ReturnLen:DWORD):Integer;
var
dwFlag,dwResult:DWORD;
pvdReceive:PVideoData;begin
Result:=0;
if CapVar.hic=0 then
begin
Result:=-1;
Exit;
end; pvdReceive:=PVideoData(Data);
if pvdReceive^.KeyFrame = 0 then
dwFlag:=ICDECOMPRESS_NOTKEYFRAME
else
dwFlag:=0; ReturnLen:= pbiInfoOut^.bmiHeader.biSizeImage; if Assigned(pDeReturn) then
begin
FreeMemory(pDeReturn);
pDeReturn:=nil;
end;
pDeReturn:=GetMemory(ReturnLen);
dwResult:=ICDecompress(CapVar.hic,dwFlag,@pvdReceive^.BitmapInfo.bmiHeader,
@pvdReceive^.Data[0], @pbiInfoOut^.bmiHeader,pDeReturn); ReturnData:=pDeReturn;
// ReturnLen:= SizeOf(TVideoData)+pbiInfoOut^.bmiHeader.biSizeImage;
// ReturnData:=GetMemory(ReturnLen);
// //ICERR_OK
// CopyMemory(@ReturnData^.BitmapInfo,pbiInfoOut,SizeOf(TBitmapInfo));
// ReturnData^.DataLen:= pbiInfoOut^.bmiHeader.biSizeImage;
// dwResult:=ICDecompress(CapVar.hic,dwFlag,@pvdReceive^.BitmapInfo.bmiHeader,
// @pvdReceive^.Data[0], @pbiInfoOut^.bmiHeader,@ReturnData^.Data[0] );end;procedure TVCMDecode.EndProcess;
begin
if (CapVar.hic > 0) then
begin
ICDeCompressEnd(CapVar.hic);
ICClose(CapVar.hic);
CapVar.hic:=0;
end; if Assigned(pbiInfoOut) then
begin
FreeMemory(pbiInfoOut);
pbiInfoOut:=nil;
end;
end;function TVCMDecode.InitProcess(
pbiInfo: PBitmapInfo): Integer;
var
dwOutFormatSize:DWORD;
begin
Result :=0;
//正式连接编码器
CapVar.hic:=ICOpen(ICTYPE_VIDEO, CapVar.fccHandler, ICMODE_DECOMPRESS);
if (CapVar.hic=0) then
begin
Result:=-1;
Exit;
end; dwOutFormatSize:=ICDecompressGetFormatSize(CapVar.hic, pbiInfo);
pbiInfoOut:=GetMemory(dwOutFormatSize);
ICDeCompressGetFormat(CapVar.hic,pbiInfo,pbiInfoOut); if ICERR_OK<>ICDecompressBegin(CapVar.hic,pbiInfo,pbiInfoOut) then
begin
EndProcess;
end;
end;
end.
这是接口单元
unit unVideoProcess;interfaceuses
Windows;
type
PVideoData=^TVideoData;
TVideoData=packed record
KeyFrame:Byte;
BitmapInfo:TBitmapInfo;
DataLen:DWORD;
Data:array [0..0] of Byte;
end; IVideoProcess=interface
function InitProcess(pbiInfo:PBitmapInfo):Integer;stdcall;
procedure EndProcess();stdcall;
function DoProcess(Data :PByte;Len:DWORD; var ReturnData :PByte;var ReturnLen:DWORD
):Integer;stdcall;
end;implementationend.
好,我正在從之前開發的視頻會議室系統中分離代碼;給您編寫一個視頻傳輸並顯示的demo...
PS,預計晚上將測試demo發給您!