⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umain.~pas

📁 基于xvid 视频的捕获压缩传输
💻 ~PAS
字号:
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, DSPack, Menus, StdCtrls,

  DSUtil,lib_xvid, DirectShow9,
  IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient;

type
  Tvideoform = class(TForm)
    FilterGraph: TFilterGraph;
    VideoWindow: TVideoWindow;
    Filter: TFilter;
    SampleGrabber: TSampleGrabber;
    SnapShot: TButton;
    idtcpclnt1: TIdTCPClient;
    Button1: TButton;
    procedure SnapShotClick(Sender: TObject);
    procedure SampleGrabberBuffer(sender: TObject; SampleTime: Double;
      pBuffer: Pointer; BufferLen: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure Button1Click(Sender: TObject);
  private
    // XVID ENCODER
    xvid_gbl      : xvid_gbl_init_t;
    xvid_enc      : xvid_enc_create_t;
    xvid_encFrame : xvid_enc_frame_t;
    xvid_encStats : xvid_enc_stats_t;

  public

  end;

  type
    TimgSendBuf = packed record
    ImgSize:Word;
    Buffer:array [0..352*288*3] of Byte;
  end;

var
  videoform : Tvideoform;
  SysDev    : TSysDevEnum;
  FrameBuf  :array [0..352*288*3 ] of Byte;
  FrameImg  :array [0..352*288*3 ] of Byte;
  FrameSequece    : LongWord= 0;
  xvid_Version    : Integer;
  FrameByteCount  : LongWord = 0;
  CurFrame        : LongWord = 0;
  Sending         : BOOL=False;
  imgSendBuf      : TimgSendBuf;


implementation

{$R *.dfm}

{ TForm1 }



procedure Tvideoform.SnapShotClick(Sender: TObject);
begin
  idtcpclnt1.Disconnect;
  idtcpclnt1.Host:='127.0.0.1';
  idtcpclnt1.Port:=9001;
  idtcpclnt1.Connect;
end;

procedure Tvideoform.SampleGrabberBuffer(sender: TObject; SampleTime: Double;
  pBuffer: Pointer; BufferLen: Integer);
var
  SpBmp:TBitmap;
  Ret:Integer;
begin
  if idtcpclnt1.Connected then
  begin
    try
      xvid_encFrame.bitstream := @FrameBuf[0];
      xvid_encFrame.input.csp := XVID_CSP_BGR;  //输入是rgb位图
      xvid_encFrame.input.plane[0] := pBuffer;  //RGB位图数据,每个像素有3个字节,(R,G,B)
      xvid_encFrame.input.stride[0] := 320 * 3; //每行字节数

      //开始压缩
      Ret := xvid_encore(xvid_enc.handle, XVID_ENC_ENCODE, @xvid_encFrame,nil); //返回编码之后的字节

      //网络发送
      if idtcpclnt1.Connected then
      begin
        imgSendBuf.ImgSize := Ret;
        Move(FrameBuf,imgSendBuf.Buffer,Ret);
        idtcpclnt1.WriteBuffer(imgSendBuf,Ret+2,True);
      end; 
    except
    //
    end;
  end;
end;

procedure Tvideoform.FormCreate(Sender: TObject);
var
  i: integer;
  Device: TMenuItem;
begin
  xvid_Version := XVID_MAKE_VERSION(1,1,0);
  SysDev := TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);
end;

procedure Tvideoform.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  SysDev.Free;
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;

  if  Assigned(xvid_enc.handle) then
    xvid_encore(xvid_enc.handle,XVID_ENC_DESTROY, @xvid_enc, nil);
end;

procedure Tvideoform.Button1Click(Sender: TObject);
begin
 Self.DoubleBuffered := True;
  
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;
  Filter.BaseFilter.Moniker := SysDev.GetMoniker(0);
  FilterGraph.Active := true;
  
  with FilterGraph as ICaptureGraphBuilder2 do
  begin
    RenderStream(@PIN_CATEGORY_PREVIEW, nil, Filter as IBaseFilter, SampleGrabber as IBaseFilter, VideoWindow as IbaseFilter);
  end;

  try
    //XVID库初始化操作
    xvid_gbl.version   := xvid_Version;    //Version:1.1.0
    xvid_gbl.cpu_flags := Word(XVID_CPU_FORCE or XVID_CPU_ASM);
    xvid_gbl.debug     := 0;     //调试级别

    //初始化编解码
    xvid_global(nil, XVID_GBL_INIT, @xvid_gbl, nil);

    // XVID编码器初始化
    xvid_enc.version := xvid_Version;
    //编码器参数
    xvid_enc.global  := XVID_GLOBAL_PACKED;   //全局标志
    xvid_enc.width   := 320;  //压缩视频宽度
    xvid_enc.height  := 240;  //压缩视频高度
    xvid_enc.fbase   := 3;    //基本帧率/每秒  = fbase * 10 = 30
    xvid_enc.fincr   := 1;    //帧率增长步长,0:可变步长,>1实际增长步长
    xvid_enc.profile := XVID_PROFILE_AS_L4; //压缩级别,MPEG4-ASP最高压缩级别
    xvid_enc.max_key_interval := 0; //最大关键帧间隔
    xvid_enc.frame_drop_ratio := 0; //丢帧率;0~100
    xvid_enc.max_bframes      := 1; //是否采用B帧,一般采用I,P帧,如果1=PB帧
    xvid_enc.bquant_offset    := 0;
    xvid_enc.bquant_ratio     := 0;

    //创建编码器
    xvid_encore(nil, XVID_ENC_CREATE, @xvid_enc, nil);
    //初始化压缩数据帧结构
    xvid_encFrame.version := xvid_Version;
    // --- VOL FLAGS
    xvid_encFrame.vol_flags :=  0;//XVID_VOL_MPEGQUANT OR XVID_VOL_QUARTERPEL OR XVID_VOL_GMC;
    // --- VOP FLAGS
    xvid_encFrame.vop_flags := 0; //XVID_VOP_HALFPEL or XVID_VOP_INTER4V;

    xvid_encFrame.motion := 0; //XVID_ME_ADVANCEDDIAMOND16 or XVID_ME_HALFPELREFINE16 or
                               //XVID_ME_ADVANCEDDIAMOND8 or XVID_ME_HALFPELREFINE8;  //运动估计
    xvid_encFrame.quant := 10;  //质量控制=量化参数,0~31,数值越小质量越高和码率成反比

    xvid_encFrame.coding_type := XVID_TYPE_AUTO;  //XVID_TYPE_AUTO=让编码器自动决定,I帧编码是关键帧,P帧编码是帧内预测
  except
    Exit;
  end;

  FilterGraph.Play;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -