Results 1 to 9 of 9

Thread: 2 web cameras and .net

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2011
    Location
    Sydney, Australia
    Posts
    756

    2 web cameras and .net

    Hi All,

    I need help once again, I have tried searching all day with no luck.

    Im making a camera/video capture app for my shinny new windows tablet (win 7 ultimate). I have tried a few apps but all are really crap and not what im after.

    From searching I found the avicap32.dll method which on my dev computer works perfect, on my tablet however it doesnt.

    The reason for this is the tablet has 2 webcams, front and back, both use the very same driver so show as 1 source on the tablet. when i select the source it gives me the option of picking abc usb cam or cba usb cam but still doesnt work.

    I have no idea how to get around this

    also skype can list the name of the webcams and display perfectly as can the trialed apps.

    Please see below code

    Code:
        Const WM_CAP_START = &H400S
        Const WS_CHILD = &H40000000
        Const WS_VISIBLE = &H10000000
    
        Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
        Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
        Const WM_CAP_EDIT_COPY = WM_CAP_START + 30
        Const WM_CAP_SEQUENCE = WM_CAP_START + 62
        Const WM_CAP_FILE_SAVEAS = WM_CAP_START + 23
    
        Const WM_CAP_SET_SCALE = WM_CAP_START + 53
        Const WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
        Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
    
        Const SWP_NOMOVE = &H2S
        Const SWP_NOSIZE = 1
        Const SWP_NOZORDER = &H4S
        Const HWND_BOTTOM = 1
        '--The capGetDriverDescription function retrieves the version 
        ' description of the capture driver--
        Declare Function capGetDriverDescriptionA Lib "avicap32.dll" _
           (ByVal wDriverIndex As Short, _
            ByVal lpszName As String, ByVal cbName As Integer, _
            ByVal lpszVer As String, _
            ByVal cbVer As Integer) As Boolean
    
        '--The capCreateCaptureWindow function creates a capture window--
        Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
           (ByVal lpszWindowName As String, ByVal dwStyle As Integer, _
            ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
            ByVal nHeight As Short, ByVal hWnd As Integer, _
            ByVal nID As Integer) As Integer
    
        '--This function sends the specified message to a window or windows--
        Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
           (ByVal hwnd As Integer, ByVal Msg As Integer, _
            ByVal wParam As Integer, _
           <MarshalAs(UnmanagedType.AsAny)> ByVal lParam As Object) As Integer
    
        '--Sets the position of the window relative to the screen buffer--
        Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" _
           (ByVal hwnd As Integer, _
            ByVal hWndInsertAfter As Integer, ByVal x As Integer, _
            ByVal y As Integer, _
            ByVal cx As Integer, ByVal cy As Integer, _
            ByVal wFlags As Integer) As Integer
    
        '--This function destroys the specified window--
        Declare Function DestroyWindow Lib "user32" _
           (ByVal hndw As Integer) As Boolean
        '---used to identify the video source---
        Dim VideoSource As Integer
        '---used as a window handle---
        Dim hWnd As Integer
    
    
        Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
            Dim path As String
            path = "C:\data\"
            Dim number As Integer
            number = System.IO.Directory.GetFiles(path).Length
            SendMessage(hWnd, WM_CAP_EDIT_COPY, 0, 0)
            Dim loData As IDataObject = Clipboard.GetDataObject()
            If loData.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
                Using loBitmap As Image = CType(loData.GetData(GetType(System.Drawing.Bitmap)), Image)
                    loBitmap.Save(path & "image" & number & ".jpg", Imaging.ImageFormat.Jpeg)
                    PictureBox2.Image = Image.FromFile(path & "image" & number & ".jpg")
                    PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage
                End Using
            End If
            
    
        End Sub
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            System.IO.Directory.CreateDirectory("C:\data")
            ListVideoSources()
    
        End Sub
        '---list all the various video sources---
        Private Sub ListVideoSources()
            Dim DriverName As String = Space(80)
            Dim DriverVersion As String = Space(80)
            For i As Integer = 0 To 9
                If capGetDriverDescriptionA(i, DriverName, 80, _
                   DriverVersion, 80) Then
                    lstVideoSources.Items.Add(DriverName.Trim)
    
                End If
            Next
        End Sub
    
        '---list all the video sources---
        Private Sub lstVideoSources_SelectedIndexChanged( _
           ByVal sender As System.Object, ByVal e As System.EventArgs) _
           Handles lstVideoSources.SelectedIndexChanged
            '---check which video source is selected---
            VideoSource = lstVideoSources.SelectedIndex
            '---preview the selected video source
            PreviewVideo(picCapture)
        End Sub
        '---preview the selected video source---
        Private Sub PreviewVideo(ByVal pbCtrl As PictureBox)
            hWnd = capCreateCaptureWindowA(VideoSource, _
                WS_VISIBLE Or WS_CHILD, 0, 0, 0, _
                0, pbCtrl.Handle.ToInt32, 0)
            If SendMessage( _
               hWnd, WM_CAP_DRIVER_CONNECT, _
               VideoSource, 0) Then
                '---set the preview scale---
                SendMessage(hWnd, WM_CAP_SET_SCALE, True, 0)
                '---set the preview rate (ms)---
                SendMessage(hWnd, WM_CAP_SET_PREVIEWRATE, 30, 0)
                '---start previewing the image---
                SendMessage(hWnd, WM_CAP_SET_PREVIEW, True, 0)
                '---resize window to fit in PictureBox control---
                SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, _
                   pbCtrl.Width, pbCtrl.Height, _
                   SWP_NOMOVE Or SWP_NOZORDER)
            Else
                '--error connecting to video source---
                DestroyWindow(hWnd)
            End If
        End Sub
        '---stop the preview window---
        Private Sub btnStopCamera_Click( _
           ByVal sender As System.Object, _
           ByVal e As System.EventArgs)
    
            StopPreviewWindow()
        End Sub
        '--disconnect from video source---
        Private Sub StopPreviewWindow()
            SendMessage(hWnd, WM_CAP_DRIVER_DISCONNECT, VideoSource, 0)
            DestroyWindow(hWnd)
        End Sub
        '---Start recording the video---
        Private Sub btnStartRecording_Click( _
           ByVal sender As System.Object, _
           ByVal e As System.EventArgs) _
           Handles btnStartRecording.Click
            btnStartRecording.Enabled = False
            btnStopRecording.Enabled = True
            '---start recording---
            SendMessage(hWnd, WM_CAP_SEQUENCE, 0, 0)
        End Sub
        '---stop recording and save it on file---
        Private Sub btnStopRecording_Click( _
           ByVal sender As System.Object, _
           ByVal e As System.EventArgs) _
           Handles btnStopRecording.Click
            btnStartRecording.Enabled = True
            btnStopRecording.Enabled = False
            '---save the recording to file---
            SendMessage(hWnd, WM_CAP_FILE_SAVEAS, 0, _
               "C:\RecordedVideo.avi")
        End Sub
    so basically the listbox on the form fills with driver details, i would then select it and the preview would appear in the picture box, on the tablet this doesnt happen, both webcams are listed under same driver, select it and windows asks which camera but never loads the preview (ideally i would like that windows pop up to not show as well i have the camera names if that helps).

    I did look into some other options like directshow.net and even webcamlib.dll (which looks simple but cant even load the dll).


    EDIT**** I added a msgbox to the area that errors on connecting and it ran so it seems like a connection error, seeing as it connects using driver and both have same driver it must not know which one to use. stil any help appriciated**

    any and all help is appriciated, i thought this would be easy and is was, until 2 webcams came into it
    Last edited by bensonsearch; Dec 26th, 2012 at 02:09 AM.

  2. #2
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,242

    Re: 2 web cameras and .net

    avicap32.dll is almost certainly (actually, scrap 'almost') NOT the method used by any of the applications that work with the tablet. It is, like, so last century. You'll need something considerably more sophisticated such as DirectShow
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2011
    Location
    Sydney, Australia
    Posts
    756

    Re: 2 web cameras and .net

    Thanx dunfiddlin
    I have gone down the directshow road and have hit a wall, the only thing left is to be able to select which camera to use, the code I have below will always bring up the first video device. I have tried playing around with things in the findcapturedevice sub but to no avail. Any ideas how I could select which camera to use?

    cheers for the help

    Code:
    Imports DirectShowLib
    Imports System
    Imports System.Diagnostics
    Imports System.Drawing
    Imports System.Runtime.InteropServices
    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices.ComTypes
    
    Public Class Form1
    
        Dim D As Integer = Convert.ToInt32("0X8000", 16)
        Public WM_GRAPHNOTIFY As Integer = D + 1
    
        Dim VideoWindow As IVideoWindow = Nothing
        Dim MediaControl As IMediaControl = Nothing
        Dim MediaEventEx As IMediaEventEx = Nothing
        Dim GraphBuilder As IGraphBuilder = Nothing
        Dim CaptureGraphBuilder As ICaptureGraphBuilder2 = Nothing
    
        Enum PlayState
            Stopped
            Paused
            Running
            Init
        End Enum
        Dim CurrentState As PlayState = PlayState.Stopped
    
        Dim rot As DsROTEntry = Nothing
    
       
    
        Private Sub CaptureVideo()
            Dim hr As Integer = 0
            Dim sourceFilter As IBaseFilter = Nothing
            Try
                GetInterfaces()
    
                hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder) 'Specifies filter graph "graphbuilder" for the capture graph builder "captureGraphBuilder" to use.
    
                sourceFilter = FindCaptureDevice()
    
                hr = GraphBuilder.AddFilter(sourceFilter, "Video Capture")
    
                hr = CaptureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, Nothing, Nothing)
    
                Marshal.ReleaseComObject(sourceFilter)
    
                SetupVideoWindow()
    
                rot = New DsROTEntry(GraphBuilder)
    
                hr = MediaControl.Run()
    
                CurrentState = PlayState.Running
    
            Catch ex As Exception
                MessageBox.Show("An unrecoverable error has occurred.With error : " & ex.ToString)
            End Try
        End Sub
    
        Private Sub GetInterfaces()
            Dim hr As Integer = 0
            GraphBuilder = CType(New FilterGraph, IGraphBuilder)
            CaptureGraphBuilder = CType(New CaptureGraphBuilder2, ICaptureGraphBuilder2)
            MediaControl = CType(GraphBuilder, IMediaControl)
            VideoWindow = CType(GraphBuilder, IVideoWindow)
            MediaEventEx = CType(GraphBuilder, IMediaEventEx)
            hr = MediaEventEx.SetNotifyWindow(Me.Handle, WM_GRAPHNOTIFY, IntPtr.Zero) 'This method designates a window as the recipient of messages generated by or sent to the current DirectShow object
        End Sub
    
        Public Function FindCaptureDevice() As IBaseFilter
            Dim hr As Integer = 0
            Dim classEnum As IEnumMoniker = Nothing
            Dim moniker As IMoniker() = New IMoniker(0) {}
            Dim source As Object = Nothing
            Dim devEnum As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum)
            hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, classEnum, 0)
            Marshal.ReleaseComObject(devEnum)
            If classEnum Is Nothing Then
                Throw New ApplicationException("No video capture device was detected.\r\n\r\n" & _
                               "This sample requires a video capture device, such as a USB WebCam,\r\n" & _
                               "to be installed and working properly.  The sample will now close.")
            End If
            If classEnum.Next(moniker.Length, moniker, IntPtr.Zero) = 0 Then
                Dim iid As Guid = GetType(IBaseFilter).GUID
                moniker(0).BindToObject(Nothing, Nothing, iid, source)
            Else
                Throw New ApplicationException("Unable to access video capture device!")
            End If
            Marshal.ReleaseComObject(moniker(0))
            Marshal.ReleaseComObject(classEnum)
            Return CType(source, IBaseFilter)
        End Function
    
        Public Sub SetupVideoWindow()
            Dim hr As Integer = 0
            'set the video window to be a child of the main window
            'putowner : Sets the owning parent window for the video playback window. 
            hr = VideoWindow.put_Owner(PictureBox1.Handle)
            hr = VideoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren)
    
            'Use helper function to position video window in client rect of main application window
            ResizeVideoWindow()
    
            'Make the video window visible, now that it is properly positioned
            'put_visible : This method changes the visibility of the video window. 
            hr = VideoWindow.put_Visible(OABool.True)
    
        End Sub
    
        Public Sub ResizeVideoWindow()
            'Resize the video preview window to match owner window size
            'left , top , width , height
            If Not (VideoWindow Is Nothing) Then 'if the videopreview is not nothing
                VideoWindow.SetWindowPosition(0, 0, Me.Width, Me.ClientSize.Height)
            End If
        End Sub
    
        Public Sub closeinterfaces()
            '//stop previewing data
            If Not (Me.MediaControl Is Nothing) Then
                Me.MediaControl.StopWhenReady()
            End If
    
            Me.CurrentState = PlayState.Stopped
    
            '//stop recieving events
            If Not (Me.MediaEventEx Is Nothing) Then
                Me.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero)
            End If
    
            '// Relinquish ownership (IMPORTANT!) of the video window.
            '// Failing to call put_Owner can lead to assert failures within
            '// the video renderer, as it still assumes that it has a valid
            '// parent window.
            If Not (Me.VideoWindow Is Nothing) Then
                Me.VideoWindow.put_Visible(OABool.False)
                Me.VideoWindow.put_Owner(IntPtr.Zero)
            End If
    
            ' // Remove filter graph from the running object table
            If Not (rot Is Nothing) Then
                rot.Dispose()
                rot = Nothing
            End If
    
            '// Release DirectShow interfaces
            Marshal.ReleaseComObject(Me.MediaControl) : Me.MediaControl = Nothing
            Marshal.ReleaseComObject(Me.MediaEventEx) : Me.MediaEventEx = Nothing
            Marshal.ReleaseComObject(Me.VideoWindow) : Me.VideoWindow = Nothing
            Marshal.ReleaseComObject(Me.GraphBuilder) : Me.GraphBuilder = Nothing
            Marshal.ReleaseComObject(Me.CaptureGraphBuilder) : Me.CaptureGraphBuilder = Nothing
    
        End Sub

  4. #4
    Fanatic Member
    Join Date
    Aug 2004
    Location
    Essex, UK
    Posts
    653

    Re: 2 web cameras and .net

    Just in case you want to try a different approach, I can recommend the Aforge.Net library - http://www.aforgenet.com/aforge/framework/

    I too gave up on avicap32.dll because I wanted better support for multiple webcams.

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Oct 2011
    Location
    Sydney, Australia
    Posts
    756

    Re: 2 web cameras and .net

    thanx paulg4ije, worked like a charm and effortlessly. THANKYOU EVERYONE

  6. #6
    New Member
    Join Date
    Dec 2015
    Posts
    2

    Re: 2 web cameras and .net

    Hello,
    Could one of you send me a sample VB.Net code showing how to use the AForge.Net lib to select an imaging device as a source for capture ?
    Bensonsearch, how did you do exactly ?
    Thanks.

  7. #7
    Fanatic Member
    Join Date
    Aug 2004
    Location
    Essex, UK
    Posts
    653

    Re: 2 web cameras and .net

    This is some of my code:

    Code:
    Imports AForge.Video
    Imports AForge.Video.DirectShow
    
    Module modCameras
    
        Public videoDevices As FilterInfoCollection
        'Private cam As VideoCaptureDevice
    
        Sub Get_Camera_List(cmb As ComboBox)
    
            ' Get list of available video capture devices (webcams) using AForge library
            Try
    
                videoDevices = New FilterInfoCollection(FilterCategory.VideoInputDevice)
    
                Dim iCamCount As Integer = videoDevices.Count
    
                If iCamCount > 0 Then
                    For i As Integer = 0 To iCamCount - 1
                        cmb.items.add(videoDevices(i).Name)
                    Next
                End If
    
            Catch ex As Exception
                MsgBox(ex.Message, MsgBoxStyle.Information)
            End Try
    
        End Sub
    
    End Module
    Code:
        Private Sub cmbCams_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbCams.SelectedIndexChanged
            GsCamName = cmbCams.SelectedItem.ToString
            GiCamID = cmbCams.SelectedIndex
        End Sub
    
        Private Sub Camera_On()
            Try
                Dim videoSource As VideoCaptureDevice = New VideoCaptureDevice(videoDevices(GiCamID).MonikerString)
                vsp1.VideoSource = videoSource
                videoSource.DesiredFrameRate = 10
                videoSource.DesiredFrameSize = New Size(640, 480)
                vsp1.Start()
                cmdGrab.Enabled = True
                vsp1.Visible = True
                bCameraOn = True
            Catch ex As Exception
                MsgBox("Failed to connect to chosen webcam.", MsgBoxStyle.Information)
                Call Camera_Off()
            End Try
        End Sub
    
        Private Sub Camera_Off()
            Try
                chkPreview.Checked = False
                cmdGrab.Enabled = False
                vsp1.SignalToStop()
                vsp1.WaitForStop()
                vsp1.Visible = False
                bCameraOn = False
            Catch
            End Try
        End Sub
    
        Private Sub cmdGrab_Click(sender As System.Object, e As System.EventArgs) Handles cmdGrab.Click
            Call Grab_Image()
        End Sub
    
        Private Sub Grab_Image()
            If fnGrab_Image() Then
                vsp1.Visible = False
                vsp1.SignalToStop()
                chkPreview.Checked = False
            End If
        End Sub
    You need an Aforge Video Source Player on your form (vsp1 in my code).

    Hopefully you can adapt this code to suit your requirements.

  8. #8
    Fanatic Member
    Join Date
    Aug 2004
    Location
    Essex, UK
    Posts
    653

    Re: 2 web cameras and .net

    Forgot this bit:

    Code:
        Private Function fnGrab_Image() As Boolean
    
            ' Grab an image from webcam - Aforge Video Source Player must be running
    
            Try
                Dim bm As Bitmap = New Bitmap(640, 480)
                bm = vsp1.GetCurrentVideoFrame
    
                If bm.Width <> 640 Or bm.Height <> 480 Then
                    bm = New Bitmap(bm, New Size(640, 480))
                End If
    
                Dim bm2 As Bitmap = New Bitmap(640, 512)
                Dim g As Graphics = Graphics.FromImage(bm2)
                g.DrawImage(bm, 0, 32)
                g.Dispose()
                pbTX.Image = fnAdd_Header(bm2, "Greyscale") ' Add 16 line greyscale header
                Gbm = CType(bm2.Clone, Bitmap)
                If chkStamp.Checked Then pbTX.Image = fnAdd_Date_Time_Stamp(CType(pbTX.Image, Bitmap))
                If chkLive.Checked Then pbTX.Image = fnAdd_Live_Webcam_Stamp(CType(pbTX.Image, Bitmap))
                If chkCallsign.Checked Then pbTX.Image = fnAdd_Callsign(CType(pbTX.Image, Bitmap))
                Return True
            Catch
                MsgBox("Aforge Video Source Player (webcam) not ready.")
                Return False
            End Try
    
        End Function
    Ignore the "stamps" and "header" - you should be able to adapt this code to do what you want.

    Paul.

  9. #9
    New Member
    Join Date
    Dec 2015
    Posts
    2

    Re: 2 web cameras and .net

    Thank you, Paul.
    It's so simple compared to what it could have been with avicap.

    popeau

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width