unit avi;interface
{$I config.inc}
uses
  Windows, SysUtils,Classes, Graphics, Dialogs,MMSystem,ACMWaveIn,ACMWaveOut, Controls,Forms,
{$IFDEF VER90}
  ole2;
{$ELSE}
  ActiveX;
{$ENDIF}type
  TAVIStreamInfoA = record
    fccType,
    fccHandler,
    dwFlags, // Contains AVITF_* flags
    dwCaps: DWORD;
    wPriority,
    wLanguage: WORD;
    dwScale,
    dwRate, // dwRate / dwScale == samples/second
    dwStart,
    dwLength, // In units above...
    dwInitialFrames,
    dwSuggestedBufferSize,
    dwQuality,
    dwSampleSize: DWORD;
    rcFrame: TRect;
    dwEditCount,
    dwFormatChangeCount: DWORD;
    szName: array[0..63] of AnsiChar;
  end;  WAVEFORMATEX = record
    wFormatTag : WORD  ;
    nChannels  : WORD  ;
    nSamplesPerSec : DWORD ;
    nAvgBytesPerSec : DWORD ;
    nBlockAlign : WORD  ;
    wBitsPerSample : WORD  ;
    cbSize : WORD  ;
  end;  Tmpeglayer3waveformat_tag = record
    wfx               : WAVEFORMATEX ;
    wID               : WORD         ;
    fdwFlags          : DWORD        ;
    nBlockSize        : WORD         ;
    nFramesPerBlock   : WORD         ;
    nCodecDelay       : WORD         ;
  end;
  TAVIStreamInfo = TAVIStreamInfoA;
  PAVIStreamInfo = ^TAVIStreamInfo;  TWavHeader   =   record
    rId   :   longint;
    rLen   :   longint;
    wId   :   longint;
    fId   :   longint;
    fLen   :   longint;
    wFormatTag   :   word;
    nChannels   :   word;
    nSamplesPerSec   :   longint;
    nAvgBytesPerSec   :   longint;
    nBlockAlign   :   word;
    wBitsPerSample   :   word;
    dId   :   longint;
    wSampleLength   :   longint;
  end;
  PTWavHeader = ^TWavHeader;  TAVICOMPRESSOPTIONS = record
    fccType ,
    fccHandler ,
    dwKeyFrameEvery,
    dwQuality ,
    dwBytesPerSecond ,
    dwFlags : DWORD  ;
    lpFormat : Pointer ;
    cbFormat : DWORD  ;
    lpParms : Pointer ;
    cbParms : DWORD  ;
    dwInterleaveEvery :DWORD  ;
  end;
  PAVICOMPRESSOPTIONS = ^TAVICOMPRESSOPTIONS;  TFmtChunk = packed record
    id : array[0..3] of Char;       //="fmt "
    size : ULONG;  //=16
    wFormatTag : Word ;   //=WAVE_FORMAT_PCM=1
    wChannels :  Word;       //=1 or 2 for mono or stereo
    dwSamplesPerSec : ULONG ;  //=11025 or 22050 or 44100
    dwAvgBytesPerSec : ULONG ; //=wBlockAlign * dwSamplesPerSec
    wBlockAlign : Word;      //=wChannels * (wBitsPerSample==8?1:2)
    wBitsPerSample : Word ;  //=8 or 16, for bits per sample
  end;  TDataChunk = packed record
    id : array[0..3] of Char;           //="data"
    size : ULONG;     //=datsize, size of the following array
    data : PByte; //=the raw data goes here
  end;  TWavChunk = packed record
    id : array[0..3] of Char;       //="RIFF"
    size : ULONG;                   //=datsize+8+16+4
    itype : array[0..3] of Char;        //="WAVE"
    fmt : TFmtChunk ;
    dat : TDataChunk ;
  end;
  PWavChunk = ^TWavChunk;  pRGBArray = ^TRGBArray;
  TRGBArray = array[0..32767] of TRGBTriple;  Tbuffer = array of char;  TAVISaveCallback = function(nPercent: integer): LONGint; stdcall;
function  AVIFileOpen(var ppfile: pointer; szFile: PChar; uMode: UINT; lpHandler: pointer): HResult; stdcall;
procedure AVIFileInit; stdcall;
procedure AVIFileExit; stdcall;
function  AVIFileCreateStream(pfile: pointer; var ppavi: pointer; var psi: TAVIStreamInfo): HResult; stdcall;
function  AVIStreamSetFormat(pavi: pointer; lPos: LONGint; lpFormat: pointer; cbFormat: LONGint): HResult; stdcall;
function  AVIFileGetStream(pfile: pointer; var ppavi: pointer; streamtype : DWORD;cbFormat: LONGint): HResult; stdcall;
function  AVIStreamWrite(pavi: pointer; lStart, lSamples: LONGint; lpBuffer: pointer; cbBuffer: LONGint; dwFlags: DWORD; var plSampWritten: LONGint; var plBytesWritten: LONGint): HResult; stdcall;
function  AVIStreamRelease(pavi: pointer): ULONG; stdcall;
function  AVIFileRelease(pfile: pointer): ULONG; stdcall;
function  CreateEditableStream(var ppsEditable: pointer; psSource: pointer): HResult; stdcall;
function  AVIStreamInfo(pAVIStream : Pointer; var psi : TAVIStreamInfo; lSize : LongInt) : HRESULT; stdcall;
function  AVIStreamStart(pavi : LongInt) : HRESULT; stdcall;
function  AVIStreamLength(pavi : LongInt) : HRESULT; stdcall;
function  AVIStreamGetFrameOpen(pAVIStream : Pointer; var bih : TBitmapInfoHeader) : HRESULT; stdcall;
function  AVIStreamReadFormat(aviStream : Pointer; lPos : LongInt; var lpFormat : tWAVEFORMATEX; var cbFormat : LongInt): HRESULT; stdcall;
function  AVISaveOptions(handle : HWND;uiFlags : ULONG;nStreams : Integer;var ppavi : Pointer;  plpOptions : PAVICOMPRESSOPTIONS): HRESULT; stdcall;
function  AVISaveOptionsFree(nStreams : Integer; var plpOptions : TAVICOMPRESSOPTIONS): HRESULT; stdcall;
function  AVIMakeCompressedStream(var ppsCompressed : Pointer; psSource : Pointer; var lpOptions : TAVICOMPRESSOPTIONS; var dummy : Integer): HRESULT; stdcall;
procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: Integer; var ImageSize: longInt; PixelFormat: TPixelFormat);
procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var Info: TBitmapInfoHeader;PixelFormat: TPixelFormat);
function  AlignBit(Bits, BitsPerPixel, Alignment: Cardinal): Cardinal;
function  InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE; var BitmapInfo; var Bits; PixelFormat: TPixelFormat): Boolean;
function  CreateAviFile(fname : string ; dwWidth , dwHeight,idwRate  : Integer ;pf : TPixelFormat; var pFile : Pointer; var pStream : Pointer ) : Boolean;
function  WriteAviFile(pvideo : Pointer; var istep : Integer;pData : Pointer ;iw,ih : Integer; bufsize : Cardinal;bVertical : Boolean = False) : HRESULT;
function  CloseAViFile(var pFile,pStream : Pointer) : Boolean ;
procedure CreateWav(channels, resolution: word; rate: Integer;fn: string);
procedure StartWave(parent : TWinControl; bufsize : LongInt; onData : TOnData);
procedure CloseWave;
function  AddWave( avifile, audiofile:string):boolean;

解决方案 »

  1.   


    const
      streamtypeAUDIO  = byte('a') or (byte('u') shl 8) or (byte('d') shl 16) or (byte('s') shl 24);//$73647561;
      streamtypeVIDEO  = byte('v') or (byte('i') shl 8) or (byte('d') shl 16) or (byte('s') shl 24);//$73646976;
      streamtypeDIVX   = byte('D') or (byte('i') shl 8) or (byte('v') shl 16) or (byte('x') shl 24);
      streamIV32       = byte('i') or (byte('v') shl 8) or (byte('3') shl 16) or (byte('2') shl 24);
      AVIIF_KEYFRAME   = $10;
      MPEGLAYER3_FLAG_PADDING_ISO = 0;
      MPEGLAYER3_FLAG_PADDING_ON  = 1;
      MPEGLAYER3_FLAG_PADDING_OFF = 2;
      MPEGLAYER3_WFX_EXTRA_BYTES  = 12 ;
      WAVE_FORMAT_MPEGLAYER3      = $0055;
      ICMF_CHOOSE_KEYFRAME        = $0001; // show KeyFrame Every box
      ICMF_CHOOSE_DATARATE        = $0002; // show DataRate box
      ICMF_CHOOSE_PREVIEW         = $0004;
      AVICOMPRESSF_INTERLEAVE     = $00000001;    // interleave
    AVICOMPRESSF_DATARATE       = $00000002;    // use a data rate
    AVICOMPRESSF_KEYFRAMES      = $00000004;    // use keyframes
    AVICOMPRESSF_VALID          = $00000008;
    var
      AcmWaveIn : TACMWaveIn;
      bStartWave : Boolean = False;
      GWaveStep : Integer = 0;
      WaveBuff : array of Byte;
      WaveBuffsize : Integer;
    implementationprocedure AVIFileInit; stdcall; external 'avifil32.dll' name 'AVIFileInit';
    procedure AVIFileExit; stdcall; external 'avifil32.dll' name 'AVIFileExit';
    function AVIFileOpen; external 'avifil32.dll' name 'AVIFileOpenA';
    function AVIFileCreateStream; external 'avifil32.dll' name 'AVIFileCreateStreamA';
    function AVIStreamSetFormat; external 'avifil32.dll' name 'AVIStreamSetFormat';
    function AVIFileGetStream; external 'avifil32.dll' name 'AVIFileGetStream';
    function AVIStreamWrite; external 'avifil32.dll' name 'AVIStreamWrite';
    function AVIStreamRelease; external 'avifil32.dll' name 'AVIStreamRelease';
    function AVIFileRelease; external 'avifil32.dll' name 'AVIFileRelease';
    function CreateEditableStream; external 'avifil32.dll' name 'CreateEditableStream';
    function AVIStreamInfo; external 'avifil32.dll' name 'AVIStreamInfo';
    function AVIStreamStart; external  'avifil32.dll' name 'AVIStreamStart';
    function AVIStreamLength; external  'avifil32.dll' name 'AVIStreamLength';
    function AVIStreamGetFrameOpen; external  'avifil32.dll' name 'AVIStreamGetFrameOpen';
    function AVIStreamReadFormat; external  'avifil32.dll' name 'AVIStreamReadFormat';
    function AVISaveOptions; external  'avifil32.dll' name 'AVISaveOptions';
    function AVISaveOptionsFree; external  'avifil32.dll' name 'AVISaveOptionsFree';
    function AVIMakeCompressedStream; external  'avifil32.dll' name 'AVIMakeCompressedStream';
    function AddWave( avifile, audiofile:string):boolean;    
    var buf:array of Byte;
        WavChunk:pTWavheader;
        hdr:Thandle;
        size:dword; 
        read:dword;
        numbytes,numsamps:integer; 
        StreamInfoW:TAVIStreamInfo; 
        Dummy : Integer;
        wfx:tWAVEFORMATEX;
        pavi , pStreamW: Pointer;
        wav : PWavChunk;
    label Error;
    begin 
      Result := False;
      if not FileExists(avifile) or (not FileExists(audiofile)) then Exit;
      AVIFileInit;
      if AVIFileOpen(pavi,PChar(avifile), OF_READWRITE , nil) <> 0 then Exit;
      hdr:=FileOpen(audiofile,fmOpenRead);
      size:=getfilesize(hdr,nil);
      setlength(buf,size);
      FileRead(hdr,buf[0],size);
      FileClose(hdr);
      wav := PWavChunk(buf);  //ÉèÖÃÒôƵÁ÷  
      wfx.wFormatTag := wav.fmt.wFormatTag;
      wfx.nAvgBytesperSec := wav.fmt.dwAvgBytesPerSec;
      wfx.nBlockAlign := wav.fmt.wBlockAlign;
      wfx.nSamplesPerSec := wav.fmt.dwSamplesPerSec;
      wfx.wBitsPerSample := wav.fmt.wBitsPerSample;
      wfx.nChannels := WAV.fmt.wChannels;
      FillChar(StreamInfow, sizeof(StreamInfow), 0);  streamInfow.fccType := streamtypeAUDIO;
      streamInfow.dwScale := wav.fmt.wBlockAlign;
      streamInfow.dwRate := wav.fmt.dwSamplesPerSec*wav.fmt.wBlockAlign;
      streamInfow.dwSampleSize := wav.fmt.wBlockAlign;
      streamInfow.dwQuality:=dword(-1);  if (aviFileCreateStream(pavi,pStreamW,StreamInfoW) <>0) then
        goto Error;  if (AVIStreamSetFormat(pStreamW, 0, @wfx, sizeof(tWAVEFORMATEX)) <> 0) then
        goto Error;
      //ÏÂÃæдÒôƵÁ÷Êý¾Ý
      numbytes:= wav.dat.size;
      numsamps:= (numbytes*8) div (wav.fmt.wBitsPerSample);
                                                //size - wav.dat.size
      if AVIStreamWrite(pStreamw, 0, numsamps,@buf[0] , numbytes, AVIIF_KEYFRAME,Dummy, Dummy) <> 0 then
        goto Error;
    Error :
      if pStreamW <> nil then
        AVIStreamRelease(pStreamW);
      if pavi <> nil then
        AVIFileRelease(pavi);
      AVIFileExit;
      buf := nil;
      result:=True;
    end;procedure StartWave(parent : TWinControl;bufsize : LongInt; onData : TOnData);
      var format:TWaveFormatEx;
    begin
      if Assigned(AcmWaveIn) then
        AcmWaveIn.Close
      else AcmWaveIn := TACMWaveIn.Create(parent);
      with format do
      begin
        wFormatTag := WAVE_FORMAT_PCM;
        nChannels := 1;
        nSamplesPerSec := 16000;
        wBitsPerSample := 8;
        nBlockAlign := nChannels * (wBitsPerSample div 8 );
        nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
        cbSize := 0;
      end;
      AcmWaveIn.Parent := parent;
      AcmWaveIn.OnData := onData;
      ACMWaveIn.BufferSize := bufsize;
      ACMWaveIn.Open(@format);
      bStartWave := True;
      SetLength(WaveBuff,bufsize);
      GWaveStep := 0;
      WaveBuffsize := bufsize;
    end;procedure CloseWave;
    begin
      if Assigned(AcmWaveIn) then
      begin
        AcmWaveIn.Close;
        FreeAndNil(AcmWaveIn);
      end;
      bStartWave := False;
      WaveBuff := nil;
    end;
    { 1(µ¥Éù)»òÕß2(Á¢ÌåÉù)  ,  { 8»òÕß16,´ú±í8λ»ò16λÉùÒô }   { ÉùÒôƵÂÊ,Èç11025,22050, 44100}
    procedure CreateWav(channels, resolution: word; rate: Integer;fn: string);
     var
       wf : file of TWavHeader;
       wh : TWavHeader;
    begin
      wh.rId := $46464952;
      wh.rLen := 36;
      wh.wId := $45564157;
      wh.fId := $20746d66;
      wh.fLen := 16;
      wh.wFormatTag := 1;
      wh.nChannels := channels;
      wh.nSamplesPerSec := rate;
      wh.nAvgBytesPerSec := channels*rate*(resolution div 8);
      wh.nBlockAlign := channels*(resolution div 8);
      wh.wBitsPerSample := resolution;
      wh.dId := $61746164;
      wh.wSampleLength := 0;
      system.assignfile(wf,fn); {´ò¿ª¶ÔÓ¦Îļþ }
      rewrite(wf); {Òƶ¯Ö¸Õëµ½ÎļþÍ·}
      write(wf,wh); {д½øÎļþÍ· }
      closefile(wf); {¹Ø±ÕÎļþ }
    end;function CreateAviFile(fname : string ; dwWidth , dwHeight ,idwRate : Integer ; pf : TPixelFormat; var pFile : Pointer; var pStream : Pointer) : Boolean;
      var VideoInfo,AudioInfo: TAVIStreamInfo;
          BitmapInfo: TBitmapInfoHeader;
          BitmapInfoSize : Cardinal;
          bitCount : Integer;
          waveFormat : tWAVEFORMATEX ;
          myopts : TAVICOMPRESSOPTIONS;
          aopts : array[0..1] of TAVICOMPRESSOPTIONS;
          ppsCompressed : Pointer;
          dummy : Integer;
          hr : HRESULT;
    begin
      Result := False;
      if FileExists(fname) then DeleteFile(fname);
      AVIFileInit;
      try
        case pf of
          pf1bit: bitCount := 1;
          pf4bit: bitCount := 4;
          pf8bit: bitCount := 8;
          pf15bit: bitCount := 15;
          pf16bit: bitCount := 16;
          pf24bit: bitCount := 24;
        end;
        if AVIFileOpen(pFile, PChar(fname), OF_WRITE or OF_CREATE , nil) <> 0 then Exit;
        FillChar(VideoInfo, sizeof(VideoInfo), 0);
        with VideoInfo do
        begin
          fccType := streamtypeVIDEO;
          fccHandler := streamtypeDIVX;
          dwFlags := 0;
          dwSuggestedBufferSize := AlignBit(dwWidth, bitCount, 32) * Cardinal(abs(dwHeight));;
          rcFrame.Right := dwWidth;
          rcFrame.Bottom := dwHeight;
          dwScale := 1;
          dwRate := idwRate;    
          dwSampleSize :=  0;
        end;
        if (AVIFileCreateStream(pFile, pStream, VideoInfo) <> 0) then Exit;
        if hr <> 0 then hr := GetLastError;
        FillChar(BitmapInfo, sizeof(TBitmapInfoHeader), 0);
        with BitmapInfo do
        begin
          biSize := SizeOf(TBitmapInfoHeader);
          biBitCount := bitCount;
          biWidth := dwWidth;
          biHeight := dwHeight;
          biPlanes := 1;
          biCompression := BI_RGB; // Always return data in RGB format
          biSizeImage := AlignBit(biWidth, biBitCount, 32) * Cardinal(abs(biHeight));
        end;
        if (AVIStreamSetFormat(pStream, 0, @BitmapInfo, sizeof(TBitmapInfoHeader)) <> 0) then  Exit;
      finally  end;
      Result := True;
    end;function WriteAviFile(pvideo : Pointer; var istep : Integer;pData : Pointer ; iw,ih : Integer; bufsize : Cardinal;bVertical : Boolean = False) : HRESULT;
      var Dummy : Integer;
          i,j,Fcurx,FDstx : Integer;
          puf : PByte;
          hmem : Cardinal;
          psrc : pRGBArray;
          pDst :  pRGBArray;
    begin
      if bVertical then
      begin
        hmem := GlobalAlloc(GHND,iw * ih * 3);
        puf := GlobalLock(hmem);
        psrc := pRGBArray(pData) ;
        pDst := pRGBArray(puf);
        for i := 0 to ih  - 1 do
        begin
          for j := 0 to iw  - 1 do
          begin
            Fcurx := i * iw + j;
            FDstx := (ih - 1 - i) * iw + j;
            pDst[FDstx].rgbtBlue := psrc[Fcurx].rgbtBlue;
            pDst[FDstx].rgbtGreen := psrc[Fcurx].rgbtGreen;
            pDst[FDstx].rgbtRed := psrc[Fcurx].rgbtRed;
          end;
        end;
      end;
      if bVertical then
        Result := AVIStreamWrite(pvideo, istep, 1, pDst, bufsize, AVIIF_KEYFRAME, Dummy, Dummy)
      else
        Result := AVIStreamWrite(pvideo, istep, 1, pData, bufsize, AVIIF_KEYFRAME, Dummy, Dummy);
      Inc(istep);
      if bVertical then
      begin
        GlobalUnlock(hmem);
        GlobalFree(hmem);
      end;
    end;function CloseAViFile(var pFile,pStream : Pointer) : Boolean;
    begin
      if pStream <> nil then
        AVIStreamRelease(pStream);
      if pFile <> nil then
        AVIFileRelease(pFile);
      AVIFileExit;
      pStream := nil;
      pFile := nil;
    end;
      

  2.   

    上面是avi单元文件,使用方法:
    procedure Tfrmmain.StartRecord;
      var dwRate : Integer;
    begin
      if (FVideoWidth = 0) or (FVideoHeight = 0) then Exit;
      FRecordFile := FSaveFolder + FCombineFile;
      if (mpMusic.Mode = mpPlaying) or (mpMusic.Mode = mpRecording) then  mpMusic.Pause;
      //创建音频文件
      CreateWav(2,16,48000, ChangeFileExt(FRecordFile,'.wav'));
      mpMusic.DeviceType := dtAutoSelect;
      mpMusic.FileName := ChangeFileExt(FRecordFile,'.wav');
      mpMusic.Open;
      /开始录音
      mpMusic.StartRecording;
      //设置视频帧数
      if FCamera is TPRCamera then
      begin
        {$IFDEF Large_Screen}
        dwRate := 15;
        FVideoDelay := 10;
        {$else}
        dwRate := 20;
        FVideoDelay := 10;
        {$ENDIF}
      end
      else if FCamera is TEDCamera then
      begin
        FVideoDelay := 0;
        if FCamera.DeviceName = 'Canon EOS 600D' then
          dwRate := 5
        else if FCamera.DeviceName = 'Canon EOS 500D' then
          dwRate := 7
        else dwRate := 6;
      end;
      //创建AVI文件
      CreateAviFile(FRecordFile,FVideoWidth,FVideoHeight,dwRate,pf24bit,PAVIFile,PAVIStream);
      Start := True;
      istep := 0;
      FRecordTime := 0;
      {$ENDIF}
    end;
    var 
      PAVIFile : Pointer;
      PAVIStream : Pointer;
      istep : Integer;
      Start : Boolean;
      FVideoDelay : Integer = 10;
      FVideoWidth,FVideoHeight : Integer;//在视频预览回调函数中写入图像数据
      if (PAVIFile <> nil) and (PAVIStream <> nil) and Start then
      begin
        WriteAviFile(PAVIStream,istep,bd.Scan0,bd.Width,bd.Height,bd.Height * bd.Stride,True);
        Delay(FVideoDelay);
      end;
    //结束录制
      Start := False;
      CloseAViFile(PAVIFile,PAVIStream);
      mpMusic.Stop;
      mpMusic.Save;
      mpMusic.Close;
    //合并音频视频文件,音频和视频很难完全同步
      AddWave(FRecordFile,ChangeFileExt(FRecordFile,'.wav'));
      SysUtils.DeleteFile(ChangeFileExt(FRecordFile,'.wav'));
      

  3.   

    to mdejtod
    (稻草人)
    谢谢你 这么多代码哦 学习一下先 我用的directdraw捕捉视频的  不懂的还请教你哦 非常感激 
      

  4.   

    function AlignBit(Bits, BitsPerPixel, Alignment: Cardinal): Cardinal;
    begin
      Dec(Alignment);
      Result := ((Bits * BitsPerPixel) + Alignment) and not Alignment;
      Result := Result shr 3;
    end;
      

  5.   

    保存为avi需要相关写avi文件的接口,directshow有这样的filter,也可以自己使用网上找的接口写。注意avi是否支持你保存的数据的编码方式
      

  6.   

    to mdejtod
    (稻草人)
    看到美女了,这么热心,,lz最好是真的美女哦
      

  7.   

    美女谈不上 至少还OK 凑合吧 大家都是普通人 呵呵O(∩_∩)O~
      

  8.   

    请教你用directdraw怎么写录视频的,和你一样我的是将图像处理过显示在Image上的。
      

  9.   

    Delphi XE5 +Win764, avifil32.dll没办法通过。