//*****************************************伺服器接收代碼*******************************************</p><p>unit Unit1;</p><p>interface</p><p>uses<br /> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br /> Dialogs, ExtCtrls, StdCtrls, IdBaseComponent, IdComponent, IdTCPServer,<br /> DSPack,lib_xvid;</p><p>type<br /> TForm1 = class(TForm)<br /> idtcpsrvr1: TIdTCPServer;<br /> btn1: TButton;<br /> img1: TImage;<br /> mmo1: TMemo;<br /> btn2: TButton;<br /> lbl1: TLabel;<br /> tmr1: TTimer;<br /> procedure btn1Click(Sender: TObject);<br /> procedure idtcpsrvr1Connect(AThread: TIdPeerThread);<br /> procedure idtcpsrvr1Execute(AThread: TIdPeerThread);<br /> procedure FormCreate(Sender: TObject);<br /> procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);<br /> procedure btn2Click(Sender: TObject);<br /> procedure tmr1Timer(Sender: TObject);<br /> procedure idtcpsrvr1Disconnect(AThread: TIdPeerThread);<br /> private<br /> { Private declarations }<br /> xvid_Version:Integer;<br /> xvid_gbl: xvid_gbl_init_t;</p><p> xVid_decode : xvid_dec_create_t;<br /> xvid_decFrame: xvid_dec_frame_t;<br /> public<br /> { Public declarations }</p><p> end;<br /> type<br /> TimgSendBuf = packed record<br /> ImgSize:Word;<br /> Buffer:array [0..352*288*3] of Byte;<br /> end;<br />var<br /> Form1: TForm1;<br /> imgSendBuf:TimgSendBuf;<br /> FrameImg:array [0..352*288*3 ] of Byte;<br /> FrameCount : LongWord = 0;<br /> FrameBytes : LongWord = 0;<br /> PerFrame : LongWord= 0;<br /> PerFrameBytes : LongWord =0;<br />implementation</p><p>{$R *.dfm}</p><p>procedure TForm1.btn1Click(Sender: TObject);<br />begin<br /> idtcpsrvr1.DefaultPort := 9001;<br /> idtcpsrvr1.Active := True;<br /> mmo1.Lines.Add('服務啟動!');<br />end;</p><p>procedure TForm1.idtcpsrvr1Connect(AThread: TIdPeerThread);<br />begin<br /> mmo1.Lines.Add('有用戶端串連!');<br />end;</p><p>procedure TForm1.idtcpsrvr1Execute(AThread: TIdPeerThread);<br />var<br /> SpBmp:TBitmap;<br /> Ret:Integer;<br /> BIInfo: TBitmapInfo;<br /> BitmapHandle: HBitmap;<br /> DIBPtr: Pointer;<br /> DIBSize: LongInt;<br />begin<br /> try<br /> SpBmp := TBitmap.Create;<br /> AThread.Connection.ReadBuffer(imgSendBuf.ImgSize,2);<br /> AThread.Connection.ReadBuffer(imgSendBuf.Buffer,imgSendBuf.ImgSize);</p><p> //初始化解碼資料幀結構<br /> xvid_decFrame.version := xvid_Version;<br /> xvid_decFrame.general := 0;<br /> xvid_decFrame.bitstream := @imgSendBuf.Buffer[0]; //輸入解壓的位流<br /> xvid_decFrame.length := imgSendBuf.ImgSize; //輸入位流長度<br /> xvid_decFrame.output.csp := XVID_CSP_BGR; //色彩空間<br /> xvid_decFrame.output.plane[0] := @FrameImg[0]; //解壓後輸出的緩衝區<br /> xvid_decFrame.output.stride[0] := 320 * 3; //每行位元組數<br /> ret := xvid_decore(xVid_decode.handle , XVID_DEC_DECODE, @xvid_decFrame, nil);<br /> //mmo1.Lines.Add('Img:'+ IntToStr(imgSendBuf.ImgSize) + ' Ret=:' + IntToStr(Ret));<br /> //從視頻緩衝區中取得當前位元影像<br /> BIInfo.bmiHeader.biSize := 40; // SizeOf(TBitmapInfoHeader);<br /> BIInfo.bmiHeader.biWidth := 320;<br /> BIInfo.bmiHeader.biHeight := 240;<br /> BIInfo.bmiHeader.biPlanes := 1;<br /> BIInfo.bmiHeader.biBitCount := 24;<br /> BIInfo.bmiHeader.biCompression := 0;<br /> BIInfo.bmiHeader.biSizeImage := 320 * 240 * 3;<br /> BIInfo.bmiHeader.biXPelsPerMeter := 0;<br /> BIInfo.bmiHeader.biYPelsPerMeter := 0;<br /> BIInfo.bmiHeader.biClrUsed := 0;<br /> BIInfo.bmiHeader.biClrImportant := 0;<br /> BitmapHandle := CreateDIBSection(0, BIInfo,DIB_RGB_COLORS, DIBPtr, 0, 0);<br /> Move(FrameImg, DIBPtr^, BIInfo.bmiHeader.biSizeImage );<br /> SpBmp.Handle := BitmapHandle;<br /> Img1.Canvas.Lock;<br /> Img1.Canvas.Draw(0,0,SpBmp);<br /> Img1.Canvas.Unlock; </p><p> Inc(FrameCount); //接收的幀<br /> FrameBytes := FrameBytes + imgSendBuf.ImgSize + 2; //接收的位元組<br /> finally<br /> DeleteObject(BitmapHandle);<br /> SpBmp.Free;<br /> end;<br />end;</p><p>procedure TForm1.FormCreate(Sender: TObject);<br />begin<br /> //XVID庫初始化操作<br /> xvid_Version :=XVID_MAKE_VERSION(1,1,0);<br /> xvid_gbl.version := xvid_Version; //Version:1.1.0<br /> xvid_gbl.cpu_flags := Word(XVID_CPU_FORCE or XVID_CPU_ASM);//0:自動檢查CPU,XVID_CPU_FORCE or XVID_CPU_ASM:強制使用ASM彙編最佳化<br /> xvid_gbl.debug := 0; //調試層級</p><p> //初始化編解碼<br /> xvid_global(nil, XVID_GBL_INIT, @xvid_gbl, nil);</p><p> xVid_decode.version := xvid_Version;<br /> xVid_decode.width := 320;<br /> xVid_decode.height := 240;<br /> //建立解碼器<br /> xvid_decore(nil,XVID_DEC_CREATE,@xVid_decode, nil);<br />end;</p><p>procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);<br />begin<br /> if Assigned(xVid_decode.handle) then<br /> xvid_decore(xVid_decode.handle,XVID_DEC_DESTROY,@xvid_decode,nil);<br />end;</p><p>procedure TForm1.btn2Click(Sender: TObject);<br />begin<br /> idtcpsrvr1.Active := False;<br />end;</p><p>procedure TForm1.tmr1Timer(Sender: TObject);<br />begin<br /> PerFrame := FrameCount - PerFrame;<br /> PerFrameBytes := (FrameBytes - PerFrameBytes) div 1024;<br /> lbl1.Caption := '當前流量:' + IntToStr(PerFrame) + '幀/秒' + IntToStr(PerFrameBytes) + 'k/秒';<br /> PerFrameBytes := FrameBytes;<br /> PerFrame := FrameCount;<br />end;</p><p>procedure TForm1.idtcpsrvr1Disconnect(AThread: TIdPeerThread);<br />begin<br /> mmo1.Lines.Add('用戶端中斷連線!');<br />end;</p><p>end.</p><p>//*****************************************用戶端發送視頻部分*************************************************</p><p>unit main;</p><p>interface</p><p>uses<br /> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br /> Dialogs, DSUtil, StdCtrls, DSPack, DirectShow9, Menus, ExtCtrls,lib_xvid,<br /> IdBaseComponent, IdComponent, IdTCPServer,IdGlobal, IdTCPConnection,<br /> IdTCPClient, IdThreadMgr, IdThreadMgrDefault, IdAntiFreezeBase,<br /> IdAntiFreeze;</p><p>type<br /> TVideoForm = class(TForm)<br /> FilterGraph: TFilterGraph;<br /> VideoWindow: TVideoWindow;<br /> MainMenu1: TMainMenu;<br /> Devices: TMenuItem;<br /> Filter: TFilter;<br /> Image: TImage;<br /> SampleGrabber: TSampleGrabber;<br /> SnapShot: TButton;<br /> CallBack: TCheckBox;<br /> mmo1: TMemo;<br /> lbl1: TLabel;<br /> idtcpclnt1: TIdTCPClient;<br /> btn1: TButton;<br /> procedure FormCreate(Sender: TObject);<br /> procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);<br /> procedure SnapShotClick(Sender: TObject);<br /> procedure SampleGrabberBuffer(sender: TObject; SampleTime: Double;<br /> pBuffer: Pointer; BufferLen: Integer);</p><p> private<br /> // XVID ENCODER<br /> xvid_gbl: xvid_gbl_init_t;<br /> xvid_enc : xvid_enc_create_t;<br /> xvid_encFrame: xvid_enc_frame_t;<br /> xvid_encStats: xvid_enc_stats_t;</p><p> public<br /> procedure OnSelectDevice(sender: TObject);<br /> end;</p><p> type<br /> TimgSendBuf = packed record<br /> ImgSize:Word;<br /> Buffer:array [0..352*288*3] of Byte;<br /> end;<br />var<br /> VideoForm: TVideoForm;<br /> SysDev: TSysDevEnum;<br /> FrameBuf:array [0..352*288*3 ] of Byte;<br /> FrameImg:array [0..352*288*3 ] of Byte;<br /> FrameSequece : LongWord= 0;<br /> xvid_Version:Integer;<br /> FrameByteCount : LongWord = 0;<br /> CurFrame: LongWord = 0;<br /> Sending:BOOL=False;<br /> imgSendBuf:TimgSendBuf;<br />implementation</p><p>{$R *.dfm}</p><p>procedure TVideoForm.FormCreate(Sender: TObject);<br />var<br /> i: integer;<br /> Device: TMenuItem;<br />begin<br /> xvid_Version :=XVID_MAKE_VERSION(1,1,0);<br /> SysDev:= TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);<br /> if SysDev.CountFilters > 0 then<br /> for i := 0 to SysDev.CountFilters - 1 do<br /> begin<br /> Device := TMenuItem.Create(Devices);<br /> Device.Caption := SysDev.Filters[i].FriendlyName;<br /> Device.Tag := i;<br /> Device.OnClick := OnSelectDevice;<br /> Devices.Add(Device);<br /> end;<br />end;</p><p>procedure TVideoForm.OnSelectDevice(sender: TObject);<br />begin<br /> Self.DoubleBuffered := True;<br /> FilterGraph.ClearGraph;<br /> FilterGraph.Active := false;<br /> Filter.BaseFilter.Moniker := SysDev.GetMoniker(TMenuItem(Sender).tag);<br /> FilterGraph.Active := true;<br /> with FilterGraph as ICaptureGraphBuilder2 do<br /> begin<br /> RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter, SampleGrabber as IBaseFilter, VideoWindow as IbaseFilter);<br /> end;<br /> try<br /> //XVID庫初始化操作<br /> xvid_gbl.version := xvid_Version; //Version:1.1.0<br /> xvid_gbl.cpu_flags := Word(XVID_CPU_FORCE or XVID_CPU_ASM);//0:自動檢查CPU,XVID_CPU_FORCE or XVID_CPU_ASM:強制使用ASM彙編最佳化<br /> xvid_gbl.debug := 0; //調試層級</p><p> //初始化編解碼<br /> xvid_global(nil, XVID_GBL_INIT, @xvid_gbl, nil);</p><p> // XVID編碼器初始化<br /> xvid_enc.version := xvid_Version;<br /> //編碼器參數<br /> xvid_enc.global := XVID_GLOBAL_PACKED; //全域標誌<br /> xvid_enc.width := 320; //壓縮視頻寬度<br /> xvid_enc.height := 240; //壓縮視頻高度<br /> xvid_enc.fbase := 3; //基本幀率/每秒 = fbase * 10 = 30<br /> xvid_enc.fincr := 1; //幀率增長步長,0:可變步長,>1實際增長步長<br /> xvid_enc.profile := XVID_PROFILE_AS_L4; //壓縮層級,MPEG4-ASP最高壓縮層級<br /> xvid_enc.max_key_interval := 0; //最大主要畫面格間隔<br /> xvid_enc.frame_drop_ratio := 0; //丟幀率;0~100<br /> xvid_enc.max_bframes := 0; //是否採用B幀,一般採用I,P幀,如果1=PB幀<br /> xvid_enc.bquant_offset := 0;<br /> xvid_enc.bquant_ratio := 0;</p><p> //建立編碼器<br /> xvid_encore(nil, XVID_ENC_CREATE, @xvid_enc, nil);<br /> //初始化壓縮資料幀結構<br /> xvid_encFrame.version := xvid_Version;<br /> // --- VOL FLAGS<br /> xvid_encFrame.vol_flags := 0;//XVID_VOL_MPEGQUANT OR XVID_VOL_QUARTERPEL OR XVID_VOL_GMC;<br /> // --- VOP FLAGS<br /> xvid_encFrame.vop_flags := 0;//XVID_VOP_HALFPEL or XVID_VOP_INTER4V;</p><p> xvid_encFrame.motion := 0;//XVID_ME_ADVANCEDDIAMOND16 or XVID_ME_HALFPELREFINE16 or<br /> //XVID_ME_ADVANCEDDIAMOND8 or XVID_ME_HALFPELREFINE8; //運動估計<br /> xvid_encFrame.quant := 4; //品質控制=量化參數,0~31,數值越小品質越高和碼率成反比</p><p> xvid_encFrame.coding_type := XVID_TYPE_AUTO; //XVID_TYPE_AUTO=讓編碼器自動決定,I幀編碼是主要畫面格,P幀編碼是幀內預測</p><p> except<br /> Exit;<br /> end;<br /> FilterGraph.Play;<br />end;</p><p>procedure TVideoForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);<br />begin<br /> CallBack.Checked := False;<br /> SysDev.Free;<br /> FilterGraph.ClearGraph;<br /> FilterGraph.Active := false;<br /> //關閉轉碼器<br /> if Assigned(xvid_enc.handle) then<br /> xvid_encore(xvid_enc.handle,XVID_ENC_DESTROY, @xvid_enc, nil);</p><p>end;</p><p>procedure TVideoForm.SnapShotClick(Sender: TObject);<br />begin<br /> idtcpclnt1.Disconnect;<br /> idtcpclnt1.Host:='127.0.0.1';<br /> idtcpclnt1.Port:=9001;<br /> idtcpclnt1.Connect;<br />end;</p><p>procedure TVideoForm.SampleGrabberBuffer(sender: TObject;<br /> SampleTime: Double; pBuffer: Pointer; BufferLen: Integer);<br />var<br /> SpBmp:TBitmap;<br /> Ret:Integer;<br />begin<br /> if CallBack.Checked then<br /> begin</p><p> try<br /> xvid_encFrame.bitstream := @FrameBuf[0];<br /> xvid_encFrame.input.csp := XVID_CSP_BGR; //輸入是rgb位元影像<br /> xvid_encFrame.input.plane[0] := pBuffer; //RGB位元影像資料,每個像素有3個位元組,(R,G,B)<br /> xvid_encFrame.input.stride[0] := 320 * 3; //每行位元組數</p><p> //開始壓縮<br /> //Ret := xvid_encore(xvid_enc.handle, XVID_ENC_ENCODE, @xvid_encFrame,@xvid_encStats); //返回編碼之後的位元組<br /> Ret := xvid_encore(xvid_enc.handle, XVID_ENC_ENCODE, @xvid_encFrame,nil); //返回編碼之後的位元組</p><p> //網路發送<br /> if idtcpclnt1.Connected then<br /> begin<br /> imgSendBuf.ImgSize := Ret;<br /> Move(FrameBuf,imgSendBuf.Buffer,Ret);<br /> idtcpclnt1.WriteBuffer(imgSendBuf,Ret+2,True);<br /> end;<br /> except</p><p> end;<br /> end;<br />end;</p><p>end.</p><p>