Запись видео в AVI

В данном примере записывается видео с окна, в котором происходит некая анимация. Пример примечателен тем, что в нем не используются никакие сторонние библиотеки, только средствами FreeBasic.
Платформы: Windows , Linux. 
Автор:  D.J.Peters (Joshy) 2005.

запись видео

' AVI File Creator
' Copyright by D.J.Peters (Joshy)
' 8/2005 FreeBASICForum.de

' vour caractercode to string
#DEFINE cc4_to_Str(c) Chr$(c And &h000000FF,(c And &h0000FF00) Shr 8,(c And &h00FF0000) Shr 16,(c And &hFF000000) Shr 24)

Const AVIF_HASINDEX       As Uinteger = &H10      ' Index at end of file?
Const AVIF_MUSTUSEINDEX   As Uinteger = &H20

Const AVIF_ISINTERLEAVED  As Uinteger = &H100

Const AVIF_TRUSTCKTYPE    As Uinteger = &H800     ' Use CKType to find key frames?
Const AVIF_WASCAPTUREFILE As Uinteger = &H10000

Const AVIF_COPYRIGHTED    As Uinteger = &H20000


'!!! string * 4 don't work in binary mode !!!
Const RIFF As Uinteger = &H46464952 '"RIFF"
Const AVI_ As Uinteger = &H20495641 '"AVI "
Const LIST As Uinteger = &H5453494c '"LIST"
Const hdrl As Uinteger = &H6c726468 '"hdrl" Headerlist
Const avih As Uinteger = &H68697661 '"avih" AVIheader
Const strl As Uinteger = &H6c727473 '"strl" Streamlist
Const strh As Uinteger = &H68727473 '"strh" Streamheader
Const vids As Uinteger = &H73646976 '"vids" Videostream
Const auds As Uinteger = &H73647561 '"auds" Audiostream
Const DIB_ As Uinteger = &H20424944 '"DIB " Device independent bitmap
Const strf As Uinteger = &H66727473 '"strf" Streamformat
Const movi As Uinteger = &H69766f6d '"movi" on filepos 2036 LIST size "movie"
Const nndb As Uinteger = &H62643030 '"00db" Stream 00 DIB bytes
Const nndc As Uinteger = &H62643030 '"00dc" Stream 00 DIB compressed
Const nnwb As Uinteger = &H62773030 '"01wb" Stream 01 Wave bytes

Const idx1 As Uinteger = &H31786469 '"idx1" 'Indexlist
Const JUNK As Uinteger = &H4b4e554a '"JUNK"

Type AVIRGB
    r As Byte

    g As Byte

    b As Byte

    a As Byte

End Type


Type AVIFILE
    RIFFChunk             As Uinteger '0 "RIFF"
    RIFFSize              As Uinteger '4 '2048 +  n * (imagesize+8+16)
    AVI_Chunk             As Uinteger '8 "AVI "

    AVILISTChunk             As Uinteger '12 "LIST"
    AVILISTSize              As Uinteger '16 (192)

    hdrlChunk             As Uinteger '20 "hdrl"
    avihChunk             As Uinteger '24 "avih"
    avihSize              As Uinteger '28 (56)
    aviMicroSecPerFrame    As Uinteger '32 4  (0) frame display rate (or 0L)
    aviMaxBytesPerSec      As Uinteger '36 8  (0) max. transfer rate
    aviPaddingGranularity  As Uinteger '40 12 (0) pad to multiples of this size as long normally 2K.
    aviFlag               As Uinteger '44 16 (&H810)
    aviTotalFrames         As Uinteger '48 20 (number of frames)
    aviInitFrames          As Uinteger '52 24 (0)
    aviStreams             As Uinteger '56 28 (1)
    aviSuggestedBufferSize As Uinteger '60 32 (w*h*3)
    aviWidth             As Uinteger '64 36 (w)
    aviHeight             As Uinteger '68 40 (h)
    aviReserved1           As Uinteger '72 44 (0)
    aviReserved2           As Uinteger '76 48 (0)
    aviReserved3           As Uinteger '80 52 (0)
    aviReserved4           As Uinteger '84 56 (0)

    STREAMLISTChunk             As Uinteger '88 "LIST"
    STREAMLISTSize              As Uinteger '92 (116)

    strlChunk             As Uinteger '96  "strl"
    strhChunk             As Uinteger '100 "strh"
    strhSize              As Uinteger '104 (56)
    fccType               As Uinteger '108 4 "vids"
    fccHandler            As Uinteger '112 8 "DIB "
    dwAVITF_              As Uinteger '116 12 (0)
    wPriority             As Ushort   '120 14 (0)
    wLanguage             As Ushort   '122 16 (0)
    dwInitFrames          As Uinteger '124 20 (0)
    dwScale               As Uinteger '128 24 (1)
    dwRate                As Uinteger '132 28 (frames per second) dwRate / dwScale = samples/second
    dwStart               As Uinteger '136 32 (0)
    dwLength              As Uinteger '140 36 (number of frames)
    dwSuggestedBufferSize As Uinteger '144 40 (ImageSize)
    dwQuality             As Uinteger '148 44 (10000)=100%
    dwSampleSize          As Uinteger '152 48 (0)
    wLeft                 As Ushort   '156 50 !!!(0)
    wTop                  As Ushort   '158 52 (0)
    wRight                As Ushort   '160 54 (width)
    wBottom               As Ushort   '162 56 (height)

    strfChunk             As Uinteger '164 "strf" Streamformat
    strfSize              As Uinteger '168 (40)
    FormatSize            As Uinteger '172 4  (40)
    dwWidth               As Uinteger '176 8  (width)
    dwHeight              As Uinteger '180 12 (height)
    wPlanes               As Ushort   '184 14 (1)
    wBitcount             As Ushort   '186 16 (24)
    compression           As Uinteger '188 20 (0)
    Imagesize             As Uinteger '192 24  (w * h * 3)
    xpels                 As Uinteger '196 28 (0)
    ypels                 As Uinteger '200 32 (0)
    ColorsUsed            As Uinteger '204 36 (0)
    ColorsImportent       As Uinteger '208 40 (0)

    JUNK                  As Uinteger '212  "JUNK"
    JUNKSize              As Uinteger '216-220 (1816)=2036 ok
End Type


Type AVI_MOVI_LIST 'at 2036
    LISTChunk             As Uinteger '2036 "LIST"
    LISTSize              As Uinteger '2040
    moviChunk             As Uinteger '2044 "movi"
End Type

Type AVI_MOVI_LIST_ENTRY 'at 2048
    ChunkId               As Uinteger '2048  "00db" "00dc" or "01wb"
    ChunkSize             As Uinteger '2052  (w*h*3) Bitmap or wave datasize
End Type

Type AVI_INDEX_LIST                 ' at 2048 + (num_of_frames * (8+Imagesize))
    idx1Chunk             As Uinteger ' "idx1"
    idx1Size              As Uinteger ' num_of_entry * 16 = Sizeof(index_entry)
End Type

Type AVI_INDEX_ENTRY
    chunkid               As Uinteger ' "00db" "00dc" or "01wb"
    dwAVIIF_              As Uinteger ' (&H10) Keyframe
    dwChunkOffset         As Uinteger ' Position of chunk
    dwChunkLength         As Uinteger ' Length of chunk
End Type



Dim Shared avi As avifile

Function PrepareAVIFile(strFile As String,Byval w As Uinteger,Byval h As Uinteger,Byval FramesPerSecond As Uinteger) As Integer

    Dim As Integer hFile
    Dim As String  pad
    Dim As AVI_MOVI_LIST aml
    With avi
        .RIFFChunk = RIFF
        .RIFFSize  = 2040

        .AVI_Chunk = AVI_
        .AVILISTChunk =LIST
        .AVILISTSize  =192


        .hdrlChunk =hdrl
        .avihChunk =avih
        .avihSize  =56
        .aviFlag   =&h810
        .aviTotalFrames=0
        .aviStreams=1
        .aviSuggestedBufferSize=w*h*3

        .aviWidth=w
        .aviHeight=h

        .STREAMLISTChunk=LIST
        .STREAMLISTSize =116

        .strlChunk=strl
        .strhChunk=strh
        .strhSize=56

        .fccType=vids
        .fccHandler=DIB_
        .dwScale=1
        .dwRate=framespersecond
        .dwLength=0

        .dwSuggestedBufferSize=w*h*3

        .dwQuality=10000
        .wRight=w
        .wBottom=h

        .strfChunk=strf
        .strfSize=40

        .FormatSize=40

        .dwWidth=w
        .dwHeight=h
        .wPlanes=1
        .wBitcount=24

        .compression=0

        .Imagesize=w*h*3


        .JUNK=JUNK
        .JUNKSize=1816


    End With

    With aml
        .LISTChunk = LIST
        .moviChunk  = movi
    End With

    hfile=FreeFile

    Open strfile For Binary As #hfile
    Put #hfile,,avi
    pad=Space$(1816)
    Put #hfile,,pad 'now 2036 bytes are written
    Put #hfile,,aml 'now 2048 bytes are written

    Function=hfile
End Function


Sub WriteInAVIFile(Byval hfile As Integer)
    Dim As Byte r,g,b
    Dim rgbptr As AVIRGB Ptr

    Dim As Integer i,l,n,c

    n=avi.aviTotalframes
    l=(avi.aviWidth * avi.aviHeight)-1

    c=nndb
    Seek #hfile,2049+((8+avi.ImageSize)*n)
    Put #hfile,,c
    Put #hfile,,avi.ImageSize

    Screenlock

    rgbptr=ScreenPtr

    For i=l To 0 Step -1

        r=rgbptr[i].r
        g=rgbptr[i].g
        b=rgbptr[i].b
        Put #hfile,,r
        Put #hfile,,g
        Put #hfile,,b
    Next

    Screenunlock

    avi.aviTotalframes+=1

End Sub


Sub CloseAVIFile(Byval hFile As Integer)
    Dim As AVI_INDEX_LIST ail
    Dim As AVI_INDEX_ENTRY aie
    Dim As Integer l,n,s,i
    l=avi.ImageSize
    n=avi.aviTotalFrames

    'update number of total frames
    Seek #hfile,49

    Put #hfile,,avi.aviTotalFrames
    Seek #hfile,141

    Put #hfile,,avi.aviTotalFrames

    s=4+n*(l+8)
    'LIST xxxx movi xxxx= sizeoff(movi) + n*(8+imagesize)
    Seek #hfile,2041

    Put #hfile,,s

    s=n*(l+8) '= n*(imagesize+sizeoff(dd00,imagesize))
    Seek #hfile,2049+s
    'idx1 xxxx      xxxx=n*sizeoff(indexentry)
    ail.idx1Chunk=idx1
    ail.idx1Size =n*16

    Put #hFile,,ail

    'db00 flag offset size
    aie.chunkid=nndb     ' "00db"
    aie.dwAVIIF_=&H10    ' Keyframe
    aie.dwChunkLength=l  ' imagesize
    For i=0 To n-1
        aie.dwChunkOffset=4+i*(l+8)
        Put #hfile,,aie
    Next


    'RIFF xxxx "AVI "
    '      (idx1xxxx) imagesize+00dbxxxx+(00dd flag offset size)
    s=2040 + 8 + n * (avi.imagesize+8+16)
    Seek #hfile,5

    Put #hfile,,s
    Close #hFile
End Sub


'''
''' main
'''
Const scr_width As UInteger=640

Const scr_height As UInteger=480

Dim As Integer myfile,i
Screenres scr_width,scr_height,32

myfile=PrepareAVIFile("test1.avi",scr_width,scr_height,15)

For i=1 To 150

    Line (Rnd*scr_width,Rnd*scr_height)-(Rnd*320,Rnd*200),Rgb(Rnd*255,Rnd*255,Rnd*255),bf
    WriteInAVIFile myfile
Next

CloseAVIFile myfile
Sleep

End