?
Solved

Accessing video frames...

Posted on 2006-04-04
10
Medium Priority
?
1,730 Views
Last Modified: 2010-12-30
Greetings,

Everytime I ask this question, no one is able to answer it, thus I joined Experts-Exchange to get help with the answer.  

I'm using VB.NET 2005 and I would like to access a frame of a video file (AVI for this example) and break it down to macroblocks but I'm not sure how to take a video frame and convert it to bytes (I assume that's what you do).  Here is an excellent pdf file with a really nice diagram explaining what I would like to ultimately do.  Look on page 7 of the pdf.

http://www.xilinx.com/esp/dvt/prof_brdcst/collateral/mpeg.pdf

Thanks!!!
0
Comment
Question by:vilusion
  • 6
  • 2
  • 2
10 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16374243
I have seen a few of these questions, without diving in.  So, here we go!!!

What do you mean by "macroblocks"?  An AVI file is nothing more than a series of bitmaps.

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16374251
You can access an AVI file through the avifil32.dll DLL using p/invoke calls or declares.

Bob
0
 

Author Comment

by:vilusion
ID: 16374300
A Macroblock is an image/frame broken down into 16x16pixel blocks.  Is there anyway you can give a small example code using p/invoke?

Thanks!
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 10

Expert Comment

by:bchoor
ID: 16374535
vilusion,
check this http://www.binary-universe.net/articles/4/english/steganodotnet4.html - it's a C# implementation but uses avifil32.dll as pointed out by Bob. If you need some help with the conversion from C# to VB, there are some online tools that help you do that - or you can post the ones you have problem with and we can help.

See the ExportBitmap function - to retrieve the frame.

HTH
~BC
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16374548
It is not that easy.  I found that reference, and I am having difficulty converting it to VB.NET.  I am working on it.

Bob
0
 
LVL 10

Assisted Solution

by:bchoor
bchoor earned 300 total points
ID: 16374564
also, general concept
1. Initialize avifil32 using AviFileInit
2. Open file using AviFileOpen
3. Get stream using AviFileGetStream
  - 4 streams in an avi file (video, audio, midi and text)
4. To start reading
  -- Get First Frame, count of frames
  -- height/width of the images ==> fill a bitmap info header
5. Extract the images
  -- AviStreamGetFrameOpen
  -- AviStreamGetFrame  ==> you decompress and export at this point
  -- AviStreamGetFrameClose

In my previous post, the web page - has a exportbitmap function - take a look at that.

HTH
~BC
0
 

Author Comment

by:vilusion
ID: 16374616
Thanks Bob and BC for helping me with this.  Yes this is a toughy and GREATLY appreciate your help!  I will work on your suggestions.  Bob, I very much appreciate your efforts in converting to VB.NET.

Thanks!
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 1700 total points
ID: 16374648
Try this:

' Source:
'  Steganography IV - Reading and Writing AVI files
'  http://www.codeproject.com/csharp/steganodotnet4.asp

Imports System.Runtime.InteropServices
Imports System.IO

Public Class AviReader

  Private m_firstFrame As Integer = 0
  Private m_countFrames As Integer = 0
  Private m_aviFile As Integer = 0
  Private m_getFrameObject As Integer
  Private m_aviStream As IntPtr
  Private m_streamInfo As Avi.AVISTREAM_INFO

  Public ReadOnly Property CountFrames() As Integer
    Get
      Return m_countFrames
    End Get
  End Property

  Public ReadOnly Property FrameRate() As Int32
    Get
      Return m_streamInfo.dwRate / m_streamInfo.dwScale
    End Get
  End Property

  Public ReadOnly Property BitmapSize() As Size
    Get
      Return New Size(m_streamInfo.rcFrame.right, m_streamInfo.rcFrame.bottom)
    End Get
  End Property

  Public Sub Open(ByVal fileName As String, ByVal imageBitSize As Int32)
    Avi.AVIFileInit()
    Dim result As Integer = Avi.AVIFileOpen(m_aviFile, fileName, Avi.OF_SHARE_DENY_WRITE, 0)
    If result <> 0 Then
      Throw New Exception("Exception in AVIFileOpen: " & result.ToString)
    End If
    result = Avi.AVIFileGetStream(m_aviFile, m_aviStream, Avi.StreamtypeVIDEO, 0)
    If result <> 0 Then
      Throw New Exception("Exception in AVIFileGetStream: " & result.ToString)
    End If
    m_firstFrame = Avi.AVIStreamStart(m_aviStream.ToInt32)
    m_countFrames = Avi.AVIStreamLength(m_aviStream.ToInt32)
    m_streamInfo = New Avi.AVISTREAM_INFO
    result = Avi.AVIStreamInfo(m_aviStream.ToInt32, m_streamInfo, Marshal.SizeOf(m_streamInfo))
    If result <> 0 Then
      Throw New Exception("Exception in AVIStreamInfo: " & result.ToString)
    End If
    Dim bih As Avi.BITMAPINFOHEADER = New Avi.BITMAPINFOHEADER
    bih.biBitCount = imageBitSize
    bih.biClrImportant = 0
    bih.biClrUsed = 0
    bih.biCompression = 0
    bih.biHeight = m_streamInfo.rcFrame.bottom
    bih.biWidth = m_streamInfo.rcFrame.right
    bih.biPlanes = 1
    bih.biSize = Marshal.SizeOf(bih)
    bih.biXPelsPerMeter = 0
    bih.biYPelsPerMeter = 0
    m_getFrameObject = Avi.AVIStreamGetFrameOpen(m_aviStream, bih)
    If m_getFrameObject = 0 Then
      Throw New Exception("Exception in AVIStreamGetFrameOpen!")
    End If
  End Sub

  Public Sub Close()
    If m_getFrameObject <> 0 Then
      Avi.AVIStreamGetFrameClose(m_getFrameObject)
      m_getFrameObject = 0
    End If
    If Not (m_aviStream.Equals(IntPtr.Zero)) Then
      Avi.AVIStreamRelease(m_aviStream)
      m_aviStream = IntPtr.Zero
    End If
    If m_aviFile <> 0 Then
      Avi.AVIFileRelease(m_aviFile)
      m_aviFile = 0
    End If
    Avi.AVIFileExit()
  End Sub

  Public Sub ExportBitmap(ByVal position As Integer, ByVal dstFileName As String)
    If position > CountFrames Then
      Throw New Exception("Invalid frame position")
    End If
    Dim pDib As Integer = Avi.AVIStreamGetFrame(m_getFrameObject, m_firstFrame + position)
    Dim bih As Avi.BITMAPINFOHEADER = New Avi.BITMAPINFOHEADER
    bih = CType(Marshal.PtrToStructure(New IntPtr(pDib), bih.GetType), Avi.BITMAPINFOHEADER)
    If bih.biSizeImage < 1 Then
      Throw New Exception("Exception in AVIStreamGetFrame: Not bitmap decompressed.")
    End If
    Dim bitmapData(bih.biSizeImage) As Byte
    Dim address As Integer = pDib + Marshal.SizeOf(bih)
    For offset As Integer = 0 To bitmapData.Length - 1
      bitmapData(offset) = Marshal.ReadByte(New IntPtr(address))
      address += 1
    Next offset
    Dim bitmapInfo(Marshal.SizeOf(bih)) As Byte
    Dim ptr As IntPtr = Marshal.AllocHGlobal(bitmapInfo.Length)
    Marshal.StructureToPtr(bih, ptr, False)
    address = ptr.ToInt32
    For offset As Integer = 0 To bitmapInfo.Length - 1
      bitmapInfo(offset) = Marshal.ReadByte(New IntPtr(address))
      address += 1
    Next offset
    Dim bfh As Avi.BITMAPFILEHEADER = New Avi.BITMAPFILEHEADER
    bfh.bfType = Avi.BMP_MAGIC_COOKIE
    bfh.bfSize = 55 + bih.biSizeImage
    bfh.bfReserved1 = 0
    bfh.bfReserved2 = 0
    bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh)

    Dim fs As New FileStream(dstFileName, System.IO.FileMode.Create)
    Dim bw As New BinaryWriter(fs)

    bw.Write(bfh.bfType)
    bw.Write(bfh.bfSize)
    bw.Write(bfh.bfReserved1)
    bw.Write(bfh.bfReserved2)
    bw.Write(bfh.bfOffBits)
    bw.Write(bitmapInfo)
    bw.Write(bitmapData)
    bw.Close()
    fs.Close()

  End Sub
End Class

Public Class Avi
  Public Const StreamtypeVIDEO As Integer = 1935960438
  Public Const OF_SHARE_DENY_WRITE As Integer = 32
  Public Const BMP_MAGIC_COOKIE As Integer = 19778

  <StructLayout(LayoutKind.Sequential, Pack:=1)> _
  Public Structure RECT
    <MarshalAs(UnmanagedType.U4)> Public left As Int32
    <MarshalAs(UnmanagedType.U4)> Public top As Int32
    <MarshalAs(UnmanagedType.U4)> Public right As Int32
    <MarshalAs(UnmanagedType.U4)> Public bottom As Int32
  End Structure

  <StructLayout(LayoutKind.Sequential, Pack:=1)> _
  Public Structure BITMAPINFOHEADER
    <MarshalAs(UnmanagedType.U4)> Public biSize As Int32
    Public biWidth As Int32
    Public biHeight As Int32
    Public biPlanes As Int16
    Public biBitCount As Int16
    <MarshalAs(UnmanagedType.U4)> Public biCompression As Int32
    <MarshalAs(UnmanagedType.U4)> Public biSizeImage As Int32
    Public biXPelsPerMeter As Int32
    Public biYPelsPerMeter As Int32
    <MarshalAs(UnmanagedType.U4)> Public biClrUsed As Int32
    <MarshalAs(UnmanagedType.U4)> Public biClrImportant As Int32
  End Structure

  <StructLayout(LayoutKind.Sequential, Pack:=1)> _
  Public Structure AVISTREAM_INFO
    <MarshalAs(UnmanagedType.U4)> Public fccType As Int32
    <MarshalAs(UnmanagedType.U4)> Public fccHandler As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwFlags As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwCaps As Int32
    <MarshalAs(UnmanagedType.U2)> Public wPriority As Int16
    <MarshalAs(UnmanagedType.U2)> Public wLanguage As Int16
    <MarshalAs(UnmanagedType.U4)> Public dwScale As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwRate As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwStart As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwLength As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwInitialFrames As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwSuggestedBufferSize As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwQuality As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwSampleSize As Int32
    Public rcFrame As RECT
    <MarshalAs(UnmanagedType.U4)> Public dwEditCount As Int32
    <MarshalAs(UnmanagedType.U4)> Public dwFormatChangeCount As Int32
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U2, SizeConst:=64)> _
    Public szName As Int16()
  End Structure

  <StructLayout(LayoutKind.Sequential, Pack:=1)> _
  Public Structure BITMAPFILEHEADER
    Public bfType As Int16
    Public bfSize As Int32
    Public bfReserved1 As Int16
    Public bfReserved2 As Int16
    Public bfOffBits As Int32
  End Structure

  <DllImport("avifil32.dll")> _
  Public Shared Sub AVIFileInit()
  End Sub

  <DllImport("avifil32.dll", PreserveSig:=True)> _
  Public Shared Function AVIFileOpen(ByRef ppfile As Int32, ByVal szFile As String, ByVal uMode As Int32, ByVal pclsidHandler As Int32) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIFileGetStream(ByVal pfile As Int32, ByRef ppavi As IntPtr, ByVal fccType As Int32, ByVal lParam As Int32) As Int32
  End Function

  <DllImport("avifil32.dll", PreserveSig:=True)> _
  Public Shared Function AVIStreamStart(ByVal pavi As Int32) As Int32
  End Function

  <DllImport("avifil32.dll", PreserveSig:=True)> _
  Public Shared Function AVIStreamLength(ByVal pavi As Int32) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamInfo(ByVal pAVIStream As Int32, ByRef psi As AVISTREAM_INFO, ByVal lSize As Int32) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamGetFrameOpen(ByVal pAVIStream As IntPtr, ByRef bih As BITMAPINFOHEADER) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamGetFrame(ByVal pGetFrameObj As Int32, ByVal lPos As Int32) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIFileCreateStream(ByVal pfile As Int32, ByRef ppavi As IntPtr, ByRef ptr_streaminfo As AVISTREAM_INFO) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamSetFormat(ByVal aviStream As IntPtr, ByVal lPos As Int32, ByRef lpFormat As BITMAPINFOHEADER, ByVal cbFormat As Int32) As Int32
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamWrite(ByVal aviStream As IntPtr, ByVal lStart As Int32, ByVal lSamples As Int32, ByVal lpBuffer As IntPtr, ByVal cbBuffer As Int32, ByVal dwFlags As Int32, ByVal dummy1 As Int32, ByVal dummy2 As Int32) As Integer
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamGetFrameClose(ByVal pGetFrameObj As Integer) As Integer
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIStreamRelease(ByVal aviStream As IntPtr) As Integer
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Function AVIFileRelease(ByVal pfile As Integer) As Integer
  End Function

  <DllImport("avifil32.dll")> _
  Public Shared Sub AVIFileExit()
  End Sub

End Class
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16374671
Example:

  Dim reader As New AviReader
  reader.Open("c:\windows\clock.avi", 8)
  Dim frames As Integer = reader.CountFrames
  Dim rate As Single = reader.FrameRate

I had a little problem, so I add the bit size parameter to the Open method, since the only AVI file that I had didn't have 24-bit frames, so the call to AVIStreamGetFrameOpen would fail.

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16374696
Unfortunately, the converters for C# to VB.NET don't convert the remarks, so they are gone from the source code.

Bob
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question