Splitting an AVI File into Multiple Bitmaps Using ltmmSampleTarget Example for Visual Basic

The following code utilizes ltmmSampleTarget and ltmmConvertCtrl to generate multiple device independent bitmaps from an AVI file.

' declarations
Private Type BITMAPINFOHEADER '40 bytes
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
End Type

Private Type BITMAPFILEHEADER   ' 14 bytes
' just leave off bfType, it messes up the alignment
'        bfType As Integer
        bfSize As Long          ' 12 bytes from here
        bfReserved1 As Integer
        bfReserved2 As Integer
        bfOffBits As Long
End Type

Private Type RECT    ' 16 bytes
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Private Type REFERENCE_TIME  ' 8 bytes
    lowpart As Long
    highpart As Long
End Type

Private Type VIDEOINFOHEADER ' 88 bytes
    rcSource As RECT
    rcTarget As RECT
    dwBitRate As Long
    dwBitErrorRate As Long
    AvgTimePerFrame As REFERENCE_TIME
    bmiHeader As BITMAPINFOHEADER
End Type

Const FILE_SHARE_READ = &H1
Const OPEN_EXISTING = 3
Const INVALID_HANDLE_VALUE = -1
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Const CREATE_ALWAYS = 2
Const FILE_ATTRIBUTE_NORMAL = &H80

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) 


'
' SaveBMP24
' saves a bitmap to a file (supports only 24 BPP) 
' strFile - output file name
' bih - BITMAPINFOHEADER
' Bits - bitmap image data
'
Private Sub SaveBMP24(strFile As String, bih As BITMAPINFOHEADER, Bits() As Byte) 
    Dim hFile As Long
    Dim bfh As BITMAPFILEHEADER
    Dim nWritten As Long
    Dim bfType As Integer
    hFile = CreateFile(strFile, GENERIC_READ + GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0) 
    
    If hFile = INVALID_HANDLE_VALUE Then
        Exit Sub
    End If

    bfType = &H4D42
    bfh.bfOffBits = 14 + bih.biSize
    bfh.bfSize = bfh.bfOffBits + bih.biSizeImage
    bfh.bfReserved1 = 0
    bfh.bfReserved2 = 0

    
    If (WriteFile(hFile, bfType, 2, nWritten, 0) = 0 Or nWritten <> 2) Then
        CloseHandle hFile
        Exit Sub
    End If

    If (WriteFile(hFile, bfh, 12, nWritten, 0) = 0 Or nWritten <> 12) Then
        CloseHandle hFile
        Exit Sub
    End If
    
    If (WriteFile(hFile, bih, bih.biSize, nWritten, 0) = 0 Or nWritten <> bih.biSize) Then
        CloseHandle hFile
        Exit Sub
    End If
    
    
    If (WriteFile(hFile, Bits(0), bih.biSizeImage, nWritten, 0) = 0 Or nWritten <> bih.biSizeImage) Then
        CloseHandle hFile
        Exit Sub
    End If
    

    CloseHandle hFile
End Sub
'
' Copy VideoInfoHeader
' copys an array to a video info header
' vih - destination video info header
' viharr - source array
'
Private Sub CopyVideoInfoHeader(vih As VIDEOINFOHEADER, viharr() As Byte) 
    CopyMemory vih, viharr(0), 88
End Sub

'
' SplitAvi
' splits an avi file into individual BMP files
' strAviFile - source file name
' strOutputDir - directory of output BMP files (split?.bmp) 
' MaxFrames - maximum number of BMP files (frames) to generate
'
Sub SplitAvi(strAviFile As String, strOutputDir As String, MaxFrames As Integer) 

    Dim SampleTarget As ltmmSampleTarget
    Dim MediaType As ltmmMediaType
    Dim MediaSample As ltmmMediaSample
    Dim strFile As String
    Dim n As Integer
    Dim vih As VIDEOINFOHEADER
    
    ' create sample target
    Set SampleTarget = New ltmmSampleTarget
    
    ' create the media type object
    Set MediaType = New ltmmMediaType
    
    
    ' set type to MEDIATYPE_Video
    MediaType.Type = "{73646976-0000-0010-8000-00AA00389B71}"
    
    ' set subtype to MEDIASUBTYPE_RGB24
    MediaType.Subtype = "{e436eb7d-524f-11ce-9f53-0020af0ba770}"
    
    '  set the accepted media type
    SampleTarget.SetAcceptedMediaType MediaType
    
    
    ' get it back for debugging
    Set MediaType = SampleTarget.GetAcceptedMediaType ()
    
    
    '  set the convert input file name
    ltmmConvertCtrl1.SourceFile = strAviFile
    
    '  set the convert object target
    ltmmConvertCtrl1.TargetObject = SampleTarget
    
    ' start the conversion
    ltmmConvertCtrl1.StartConvert

    ' get the connected media type
    Set MediaType = SampleTarget.GetConnectedMediaType ()
    

    ' get the VIDEOINFOHEADER
    CopyVideoInfoHeader vih, MediaType.Format
    
   
    For n = 0 To (MaxFrames - 1) 
        ' fetch a sample
        On Error GoTo Done
        Set MediaSample = SampleTarget.GetSample (1000) 
        ' save the image
        strFile = strOutputDir & "split" & CStr(n + 1) & ".bmp"
        SaveBMP24 strFile, vih.bmiHeader, MediaSample.Buffer
        Set MediaSample = Nothing
    Next
Done: 
    ' stop
    ltmmConvertCtrl1.StopConvert
    
End Sub

Private Sub Form_Load()
    SplitAvi "c:\count.avi", "c:\", 10
End Sub