Video Encoder (запись видео с настройками видеокодека)

Великолепный пример записи видео. В начале предоставляется возможность выбора кодека для сжатия, далее с помощью библиотеки OpenGL в окне проигрывается 3D анимация, которая как раз и записывается. Пример маленький, простой и информативный. 
Платформа: Windows.
Автор: D.J. Peters 2009  - Его сайт.

запись и кодирование видео

' AVI Encoder
' Written by D.J. Peters (2009)
' Exported to a single BI file by Kristopher Windsor

#INCLUDE Once "fbgfx.bi"

#INCLUDE "gl/gl.bi"

Const AVIIF_KEYFRAME = &H10


Enum FILEFLAGS
OF_WRITE  = &H0001

OF_CREATE = &H1000

End Enum


Enum AVISAVEFLAGS
ICMF_CHOOSE_KEYFRAME       = (1 Shl 0)
ICMF_CHOOSE_DATARATE       = (1 Shl 1)
ICMF_CHOOSE_PREVIEW        = (1 Shl 2)
ICMF_CHOOSE_ALLCOMPRESSORS = (1 Shl 3)
End Enum


Type AVIFileInfo
    As Uinteger dwMaxBytesPerSec
    As Uinteger dwFlags
    As Uinteger dwCaps
    As Uinteger dwStreams
    As Uinteger dwSuggestedBufferSize
    As Uinteger dwWidth
    As Uinteger dwHeight
    As Uinteger dwScale
    As Uinteger dwRate
    As Uinteger dwLength
    As Uinteger dwEditCount
    As String * 63 szFileType
End Type


Type AVIStreamInfo
    As Uinteger fccType
    As Uinteger fccHandler
    As Uinteger dwFlags
    As Uinteger dwCaps
    As Ushort   wPriority
    As Ushort   wLanguage
    As Uinteger dwScale
    As Uinteger dwRate
    As Uinteger dwStart
    As Uinteger dwLength
    As Uinteger dwInitialFrames
    As Uinteger dwSuggestedBufferSize
    As Uinteger dwQuality
    As Uinteger dwSampleSize
    As Uinteger l,t,w,b
    As Uinteger dwEditCount
    As Uinteger dwFormatChangeCount
    As String * 63 szName
End Type


Type AVICOMPRESSOPTIONS
    As Uinteger fccType
    As Uinteger fccHandler
    As Uinteger dwKeyFrameEvery
    As Uinteger dwQuality
    As Uinteger dwBytesPerSecond
    As Uinteger dwFlags
    As Any Ptr  lpFormat
    As Uinteger cbFormat
    As Any Ptr  lpParms
    As Uinteger cbParms
    As Uinteger dwInterleaveEvery
End Type


Type PAVICOMPRESSOPTIONS As AVICOMPRESSOPTIONS Ptr


Type BITMAPINFOHEADER
    As Integer  biSize
    As Integer  biWidth
    As Integer  biHeight
    As Short    biPlanes
    As Short    biBitCount
    As Integer  biCompression
    As Integer  biSizeImage
    As Integer  biXPelsPerMeter
    As Integer  biYPelsPerMeter
    As Integer  biClrUsed
    As Integer  biClrImportant
End Type


Type AVISaveCallback As Function (Byval nPercent As Integer) As Integer

Type AVIFILE   As Any Ptr

Type AVISTREAM As Any Ptr


Declare Function String2FOURCC       Lib "winmm"    Alias "mmioStringToFOURCCA"  (Byval As String, Byval As UInteger=0) As Uinteger

Declare Sub      AVIFileInit         Lib "avifil32" Alias "AVIFileInit"
Declare Sub      AVIFileExit         Lib "avifil32" Alias "AVIFileExit"
Declare Function AVIFileOpen         Lib "avifil32" Alias "AVIFileOpenA"         (Byval As AVIFILE Ptr, Byval strfile As String, Byval flag As FILEFLAGS, Byval lpClass As Any Ptr) As Integer

Declare Function AVIFileRelease      Lib "avifil32" Alias "AVIFileRelease"       (Byval As AVIFILE) As Integer

Declare Function AVIFileCreateStream Lib "avifil32" Alias "AVIFileCreateStreamA" (Byval As AVIFILE, Byval As AVISTREAM Ptr, Byval As AVIStreamInfo Ptr) As Integer

Declare Function AVIStreamRelease    Lib "avifil32" Alias "AVIStreamRelease"     (Byval As AVISTREAM) As Integer

Declare Function AVIMakeCompressedStream Lib "avifil32" Alias "AVIMakeCompressedStream"(Byval As AVISTREAM Ptr, Byval As AVISTREAM , Byval As AVICOMPRESSOPTIONS Ptr, Byval lpClassHandler As Any Ptr) As Integer

Declare Function AVISaveOptions      Lib "avifil32" Alias "AVISaveOptions"       (Byval hParent  As Integer, Byval As AVISAVEFLAGS, Byval nStreams As Uinteger, Byval As AVISTREAM Ptr, Byval As PAVICOMPRESSOPTIONS Ptr) As Integer

Declare Function AVISaveOptionsFree  Lib "avifil32" Alias "AVISaveOptionsFree"   (Byval nStreams As Integer, Byval As PAVICOMPRESSOPTIONS Ptr) As Integer

Declare Function AVIStreamSetFormat  Lib "avifil32" Alias "AVIStreamSetFormat"   (Byval As AVISTREAM, Byval As Integer, Byval As Any Ptr, Byval As Integer) As Integer

Declare Function AVIStreamWrite      Lib "avifil32" Alias "AVIStreamWrite"       (Byval As AVISTREAM, Byval nPos As Integer, Byval nStream As Integer, Byval lpPixel As Any Ptr, Byval bytes As Integer, Byval flag As Integer, Byval swritten As Integer Ptr, Byval bwritten As Integer Ptr) As Integer


Dim Shared As AVIFILE             file
Dim Shared As AVISTREAM           stream
Dim Shared As AVISTREAM           encoderstream
Dim Shared As AVIStreamInfo       streaminfo
Dim Shared As AVICOMPRESSOPTIONS  compressoptions
Dim Shared As PAVICOMPRESSOPTIONS Ptr ArrayOptions
Dim Shared As BITMAPINFOHEADER    Bitmapformat

' avicapture.bi
' written by d.j.peters (joshy)
Dim Shared As Byte Ptr avi_lpBits, avi_lpScreen
Dim Shared As Integer avi_screen_x, avi_screen_y, avi_frame_rate, avi_frame_count, avi_hWin
Dim Shared As Double avi_timer

ArrayOptions = Callocate(4)
ArrayOptions[0] = @compressoptions

Sub avi_start (file_name  As String, _
    screen_x   As Integer, _
    screen_y   As Integer, _
    frame_rate As Integer)
    Dim As Integer ff = Freefile


    avi_screen_x = screen_x
    avi_screen_y = screen_y
    avi_frame_rate = frame_rate

    Open file_name For Output As ff: Close ff
    Screencontrol fb.GET_WINDOW_HANDLE, avi_hWin
    AVIFileInit

    If AVIFileOpen(@file, file_name, OF_WRITE Or OF_CREATE,0)<>0 Then

        AVIFileExit
        ? "error: AVIFileOpen!"
        Beep: Sleep: End 1

    End If

    With streaminfo
        .fccType = String2FOURCC("vids")
        .dwScale = 1

        .dwRate = avi_frame_rate
        .dwSuggestedBufferSize = avi_screen_x * avi_screen_y * 3 ' RGB
        .l = 0: .t = 0: .w = avi_screen_x:.b = avi_screen_y
    End With

    With BitmapFormat
        .biSize = 40

        .biWidth = avi_screen_x
        .biHeight = avi_screen_y
        .biPlanes = 1

        .biBitCount = 24

        .biCompression = 0 ' raw rgb
        .biSizeImage = avi_screen_x * avi_screen_y * 3 ' rgb
        avi_lpbits = Callocate(.biSizeImage)
    End With

    If AVIFileCreateStream(file, @stream, @streaminfo) Then

        AVIFileRelease(file)
        AVIFileExit
        ? "error: AVIFileCreateStream!": Beep: Sleep: End 1

    End If

    If AVISaveOptions(avi_hWin, &H7, 1, @stream,ArrayOptions) <> 1 Then

        AVIStreamRelease(stream)
        AVIFileRelease(file)
        AVIFileExit
        ? "error: AVISaveOptions!": Beep: Sleep: End 1

    End If

    If AVIMakeCompressedStream(@encoderstream,stream,ArrayOptions[0], 0) Then

        AVISaveOptionsFree(1, ArrayOptions)
        AVIStreamRelease(stream)
        AVIFileRelease(file)
        AVIFileExit
        ? "error: AVIMakeCompressedStream!": Beep: Sleep: End 1

    End If

    If AVIStreamSetFormat(encoderstream, 0, @BitmapFormat, 40) Then

        AVISaveOptionsFree(1, ArrayOptions)
        AVIStreamRelease(encoderstream)
        AVIStreamRelease(stream)
        AVIFileRelease(file)
        AVIFileExit
        ? "error: AVIStreamSetFormat!": Beep: Sleep: End 1

    End If

End Sub


Sub avi_capture
    Static As Integer x, y, d, s

    If avi_frame_count = 0 Then avi_timer = Timer


    avi_lpScreen = Screenptr

    ' from bottom to top
    avi_lpScreen += (avi_screen_y - 1) * (avi_screen_x * 4)
    For y=0 To avi_screen_y-1

        d = y * avi_screen_x * 3: s = 0

        For x = 0 To avi_screen_x - 1

            ' ARGB32 to RGB24
            avi_lpBits[d + 0] = avi_lpScreen[s + 0]
            avi_lpBits[d + 1] = avi_lpScreen[s + 1]
            avi_lpBits[d + 2] = avi_lpScreen[s + 2]
            d += 3: s += 4

        Next

        avi_lpScreen -= (avi_screen_x * 4)
    Next

    AVIStreamWrite(encoderstream, _
    avi_frame_count, _
    1, _
    avi_lpBits, _
    BitmapFormat.biSizeImage, 0, 0, 0)
    avi_frame_count += 1


    While avi_frame_count / (Timer - avi_timer) > avi_frame_rate: Wend 'limit FPS
End Sub


' save OpenGL framebuffer as AVI frame
Sub avi_capture_gl
    Dim As Ubyte tmp
    Dim As Ubyte Ptr lpRGB
    If avi_frame_count = 0 Then avi_timer = Timer

    ' get framebuffer
    glReadPixels(0,0,avi_screen_x,avi_screen_y,GL_RGB,GL_UNSIGNED_BYTE,avi_lpBits)
    ' swap red and blue
    lpRGB=avi_lpBits
    For i As Integer=0 To avi_screen_x*avi_screen_y-1

        tmp=lpRGB[0]
        lpRGB[0]=lpRGB[2]
        lpRGB[2]=tmp
        lpRGB+=3
    Next

    ' write one AVI frame
    AVIStreamWrite(encoderstream, avi_frame_count, 1, avi_lpBits, BitmapFormat.biSizeImage, 0, 0, 0)
    avi_frame_count += 1

    While (avi_frame_count / (Timer - avi_timer)) > avi_frame_rate
        Sleep 3

    Wend
End Sub


Sub avi_end
    ' now free saveoptions,release streams,file and dll
    AVISaveOptionsFree(1,ArrayOptions)
    AVIStreamRelease(EncoderStream)
    AVIStreamRelease(Stream)
    AVIFileRelease(File)
    AVIFileExit
End Sub


'главный файл

#INCLUDE "fbgfx.bi"
#INCLUDE "GL/gl.bi"

#INCLUDE "GL/glu.bi"



'
' main
'
Const scr_w=320

Const scr_h=240


Dim rtri As Single, rquad As Single


avi_start "test.avi", scr_w,scr_h, 20 ' 20 frames per second
Screenres scr_w,scr_h,,32,FB.GFX_OPENGL

glViewport     0,0,scr_w,scr_h
glMatrixMode   GL_PROJECTION
glLoadIdentity

gluPerspective 45, scr_w/scr_h, 0.1, 100

glMatrixMode   GL_MODELVIEW
glLoadIdentity

glShadeModel   GL_SMOOTH
glClearColor   0,0,0,1

glClearDepth   1

glEnable       GL_DEPTH_TEST
glDepthFunc    GL_LEQUAL
glHint         GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST

Do

    glClear        GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
    glLoadIdentity
    glTranslatef   -1.5, 0, -6

    glRotatef      rtri, 0, 1, 0

    glBegin GL_TRIANGLES
    glColor3f 1, 0, 0:glVertex3f  0, 1, 0

    glColor3f 0, 1, 0:glVertex3f -1,-1, 0

    glColor3f 0, 0, 1:glVertex3f  1,-1, 0

    glEnd
    glLoadIdentity
    glTranslatef   1.5, 0  ,-6

    glRotatef      rquad,  1, 0  , 0

    glBegin GL_QUADS
    glColor3f 1, 0, 0:glVertex3f -1, 1, 0

    glColor3f 0, 1, 0:glVertex3f  1, 1, 0

    glColor3f 0, 0, 1:glVertex3f  1,-1, 0

    glColor3f 1, 1, 0:glVertex3f -1,-1, 0

    glEnd
    rtri  += 1

    rquad += 2

    avi_capture_gl
    Flip

Loop While Inkey = ""
avi_end
End