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

📄 main.pas.bak

📁 xvid库调用来压缩视频编码实例
💻 BAK
字号:
unit main;

interface

uses   
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DSUtil, StdCtrls, DSPack, DirectShow9, Menus, ExtCtrls,lib_xvid;

type
  TVideoForm = class(TForm)
    FilterGraph: TFilterGraph;
    VideoWindow: TVideoWindow;
    MainMenu1: TMainMenu;
    Devices: TMenuItem;
    Filter: TFilter;
    Image: TImage;
    SampleGrabber: TSampleGrabber;
    SnapShot: TButton;
    CallBack: TCheckBox;
    mmo1: TMemo;
    lbl1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure SnapShotClick(Sender: TObject);
    procedure SampleGrabberBuffer(sender: TObject; SampleTime: Double;
      pBuffer: Pointer; BufferLen: Integer);
  private
    // XVID ENCODER
    xvid_gbl: xvid_gbl_init_t;
    xvid_enc: xvid_enc_create_t;
    xvid_encFrame: xvid_enc_frame_t;
    xvid_encStats: xvid_dec_stats_t;

    xVid_decode: xvid_dec_create_t;
    xvid_decFrame:xvid_dec_frame_t;
    xvid_decStats:xvid_dec_stats_t;    
  public
    procedure OnSelectDevice(sender: TObject);
  end;

const
   MaxPixelCount = 65536;
type
   //Pf24bit真彩色位图像素数据结构体
   pRGBTripleArray = ^TRGBTripleArray;
   TRGBTripleArray = array[0..MaxPixelCount - 1] of TRGBTriple;
var
  VideoForm: TVideoForm;
  SysDev: TSysDevEnum;
  FrameBuf:array [0..320*240*3 - 1] of Byte;
  FrameSequece : LongWord= 0;
implementation

{$R *.dfm}

procedure TVideoForm.FormCreate(Sender: TObject);
var
  i: integer;
  Device: TMenuItem;
begin
  SysDev:= TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);
  if SysDev.CountFilters > 0 then
    for i := 0 to SysDev.CountFilters - 1 do
    begin
      Device := TMenuItem.Create(Devices);
      Device.Caption := SysDev.Filters[i].FriendlyName;
      Device.Tag := i;
      Device.OnClick := OnSelectDevice;
      Devices.Add(Device);
    end;
end;

procedure TVideoForm.OnSelectDevice(sender: TObject);
begin
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;
  Filter.BaseFilter.Moniker := SysDev.GetMoniker(TMenuItem(Sender).tag);
  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 := 1 SHL 16 + 1 SHL 8 + 0;    //Version:1.1.0
      xvid_gbl.cpu_flags := 0; //0:自动检查CPU,XVID_CPU_FORCE:强制使用XVID指定特征的CPU 
      xvid_gbl.debug := 0;     //调试级别

      //初始化编码器,得到编码器句柄
      xvid_global(xvid_enc.handle, XVID_GBL_INIT, @xvid_gbl, nil);

      //初始化解码器
      xvid_global(xVid_decode.handle, XVID_GBL_INIT, @xvid_gbl, nil);

      // XVID编码器初始化
      xvid_enc.version := 1 SHL 16 + 1 SHL 8 + 0;
      //编码器参数
      xvid_enc.global := 0;   //全局标志
      xvid_enc.width := 320;  //压缩视频宽度
      xvid_enc.height := 240; //压缩视频高度
      xvid_enc.fbase := 25;   //基本帧率/每秒
      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 := 0; //是否采用B帧,一般采用I,P帧,如果1=PB帧

      //创建编码器
      xvid_encore(xvid_enc.handle, XVID_ENC_CREATE, @xvid_enc, nil);

      //初始化压缩数据帧结构
      xvid_encFrame.version := 1 SHL 16 + 1 SHL 8 + 0;

      // --- VOL FLAGS
      xvid_encFrame.vol_flags := 0;
      xvid_encFrame.vol_flags := xvid_encFrame.vol_flags OR XVID_VOL_MPEGQUANT;  //允许MPEG量化
      xvid_encFrame.vol_flags := xvid_encFrame.vol_flags OR XVID_VOL_GMC;        //允许GMC
      xvid_encFrame.vol_flags := xvid_encFrame.vol_flags OR XVID_VOL_QUARTERPEL; //采用1/4像素运算
      // --- VOP FLAGS
      xvid_encFrame.vop_flags := xvid_encFrame.vop_flags OR XVID_VOP_CHROMAOPT;  //允许色彩优化
      //xvid_encFrame.vop_flags := xvid_encFrame.vop_flags OR XVID_VOP_HALFPEL;    //允许半像素
      xvid_encFrame.motion := 0;  //运动标识
      xvid_encFrame.quant := 8; //质量控制=量化参数,1~31,数值越小质量越高
      //输入图像初始化
      xvid_encFrame.input.csp := XVID_CSP_BGR OR XVID_CSP_VFLIP; //24bit真彩色位图编码
      xvid_encFrame.input.stride[0] := xvid_enc.width; //每行多少个字节,一般为Width*3

      // XVID解码器初始化
      xVid_decode.version := 1 SHL 16 + 1 SHL 8 + 0;
      xVid_decode.width := 320;
      xVid_decode.height := 240;

      //创建解码器
      xvid_decore(xVid_decode.handle,XVID_DEC_CREATE,@xVid_decode, nil);
      //初始化解码数据帧结构
      xvid_decFrame.version := 1 SHL 16 + 1 SHL 8 + 0;
      xvid_decFrame.brightness := 0;     //亮度偏移
      xvid_decFrame.general := XVID_LOWDELAY; //低延时
      xvid_decFrame.output.csp := XVID_CSP_BGR OR XVID_CSP_VFLIP;
      xvid_decFrame.output.stride[0] := 320 * 240 * 3;
      xvid_decFrame.length := 0;
      // DECSTATS STRUCTURE INIT
      xvid_decStats.version := 1 SHL 16 + 1 SHL 8 + 0;
  except
    Exit;
  end;
  FilterGraph.Play;
end;

procedure TVideoForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CallBack.Checked := False;
  SysDev.Free;
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;
  //关闭编解码器
  xvid_encore(xvid_enc.handle,XVID_ENC_DESTROY, @xvid_enc, nil);
end;

procedure TVideoForm.SnapShotClick(Sender: TObject);
begin
  SampleGrabber.GetBitmap(Image.Picture.Bitmap);
end;

procedure TVideoForm.SampleGrabberBuffer(sender: TObject;
  SampleTime: Double; pBuffer: Pointer; BufferLen: Integer);
var
  SpBmp:TBitmap;
  BmpLineData:prgbtriplearray;
  yp,up,vp:array [0..88800] of Byte;
  yCount,uCount,vCount:Integer;
  Row,Col:Integer;
  Ret:Integer;
begin
  if CallBack.Checked then
  begin
    //Image.Canvas.Lock;
    try
      SpBmp := TBitmap.Create;
      SpBmp.PixelFormat := pf24bit;
      SampleGrabber.GetBitmap(SpBmp, pBuffer, BufferLen); //捕获原始bmp位图
      //如果要直接显示 
      //Image.Picture.Graphic := SpBmp;
      yCount:=0;
      uCount:=0;
      vCount:=0;
      //转换RGB像素的位图矩阵,为YUV420格式的矩阵
      for Row := 0 to SpBmp.Height - 1 do
      begin
         BmpLineData := Spbmp.ScanLine[Row]; //获取每行像素数据指针
         for Col:= 0 to SpBmp.Width -1 do
         begin
           YP[yCount] := Round(BmpLineData[Col].rgbtRed * 0.3 + BmpLineData[Col].rgbtGreen * 0.6 + BmpLineData[Col].rgbtBlue * 0.1);
           if Odd(Col) then //如果是偶数
           begin
             UP[uCount]:= Round(BmpLineData[Col].rgbtBlue * 0.4 - BmpLineData[Col].rgbtRed * 0.1 - BmpLineData[Col].rgbtGreen * 0.3);
             VP[vCount]:= Round(BmpLineData[Col].rgbtBlue * 0.6 - BmpLineData[Col].rgbtRed * 0.5 - BmpLineData[Col].rgbtGreen * 0.1);
             Inc(uCount,1);
             Inc(vCount,1);
           end;
           Inc(yCount,1);
         end;
      end;

      //图像压缩编码
      xvid_encStats.version := 1 SHL 16 + 1 SHL 8 + 0;
      FillChar(FrameBuf,SizeOf(FrameBuf),0);
      xvid_encFrame.bitstream := @FrameBuf[0];

      xvid_encFrame.input.plane[0] := @yp; //Y色度矩阵
      //xvid_encFrame.input.plane[1] := @up; //U色差Cr矩阵
      //xvid_encFrame.input.plane[2] := @vp; //V色差Cb矩阵
      xvid_encFrame.input.stride[0] := SpBmp.Width; //Y矩阵每行字节数
      //xvid_encFrame.input.stride[1] := SpBmp.Width div 2; //U矩阵每行字节数
      //xvid_encFrame.input.stride[2] := SpBmp.Width div 2; //V矩阵每行字节数

      xvid_encFrame.bframe_threshold :=0;


      xvid_encFrame.coding_type := XVID_TYPE_IVOP;  //I帧编码是关键帧,P帧编码是帧内预测

      //开始压缩
      Ret := xvid_encore(xvid_enc.handle, XVID_ENC_ENCODE, @xvid_encFrame, @xvid_encStats); //返回编码之后的字节
      if Ret > 0 then
      begin
        //FrameBuf的数组中存在Ret个数据就是编码的数据
        xvid_decFrame.bitstream := @FrameBuf;
        xvid_decFrame.length := Ret;
        xvid_decore(xVid_decode.handle , XVID_DEC_DECODE, @xvid_decFrame, @xvid_decStats);
        //xvid_decFrame.output.plane[0]
        //xvid_decFrame.output.plane[1]
        //xvid_decFrame.output.plane[2]
        //xvid_decStats.
        lbl1.Caption := '';

      end else begin
        mmo1.Lines.Add('编码失败');
      end;

    finally
      //Image.Canvas.Unlock;
      SpBmp.Free;
    end;
  end;
end;

end.

⌨️ 快捷键说明

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