我用视频采集卡把影像采集到了内存,但不知如何在局域网内的两台机子上传输,有人指点说用winsock,但我是个新手,实现是不会,有没有高手帮帮我,我可以提供我之前的源码,并有详细注解

解决方案 »

  1.   

    UDP 初步
    创建 UDP 应用程序比创建 TCP 应用程序还要简单,因为 UDP 协议不需要显式的连接。在上面的 TCP 应用程序中,一个 Winsock 控件必须显式地进行“监听”,另一个必须使用 Connect 方法初始化连接。UDP 协议不需要显式的连接。要在两个控件中间发送数据,需要完成以下的三步(在连接的双方): 将 RemoteHost 属性设置为另一台计算机的名称。
    将 RemotePort 属性设置为第二个控件的 LocalPort 属性。
    调用 Bind 方法,指定使用的 LocalPort。(下面将详细地讨论该方法。) 
    因为两台计算机的地位可以看成“平等的”,这种应用程序也被称为点到点的。为了具体说明这个问题,下面将创建一个“聊天”应用程序,两个人可以通过它进行实时的交谈。要创建一个 UDP 伙伴,请按照以下步骤执行: 创建一个新的 Standard EXE 工程。
    将缺省的窗体的名称修改为 frmPeerA。
    将窗体的标题修改为“Peer A”。
    在窗体中放入一个 Winsock 控件,并将其命名为 udpPeerA。
    在“属性”页上,单击“协议”并将协议修改为 UDPProtocol。
    在窗体中添加两个 TextBox 控件。将第一个命名为 txtSend,第二个命名为 txtOutput。
    为窗体增加如下的代码。 
    Private Sub Form_Load()
    '控件的名字为 udpPeerA
    With udpPeerA
    '重点:必须将 RemoteHost 的值
    '修改为计算机的名字。
    .RemoteHost= "PeerB" 
    .RemotePort = 1001   '连接的端口号。
    .Bind 1002                '绑定到本地的端口。
    End With
    frmPeerB.Show                 '显示第二个窗体。
    End SubPrivate Sub txtSend_Change()
    '在键入文本时,立即将其发送出去。
    udpPeerA.SendData txtSend.Text
    End SubPrivate Sub udpPeerA_DataArrival _
    (ByVal bytesTotal As Long)
    Dim strData As String
    udpPeerA.GetData strData
    txtOutput.Text = strData
    End Sub要创建第二个 UDP 伙伴,请按照以下步骤执行: 在工程中添加一个标准窗体。
    将窗体的名字修改为 frmPeerB。
    将窗体的标题修改为“Peer B”。
    在窗体中放入一个 Winsock 控件,并将其命名为 udpPeerB。
    在“属性”页上,单击“协议”并将协议修改为“UDPProtocol”。
    在窗体上添加两个 TextBox 控件。将第一个命名为 txtSend,第二个命名为 txtOutput。
    在窗体中添加如下的代码。 
    Private Sub Form_Load()
    '控件的名字为 udpPeerB。
    With udpPeerB
    '重点:必须将 RemoteHost 的值改为
    '计算机的名字。
    .RemoteHost= "PeerA"
    .RemotePort = 1002    '要连接的端口。
    .Bind 1001                '绑定到本地的端口上。
    End With
    End SubPrivate Sub txtSend_Change()
    '在键入后立即发送文本。
    udpPeerB.SendData txtSend.Text
    End SubPrivate Sub udpPeerB_DataArrival _
    (ByVal bytesTotal As Long)
    Dim strData As String
    udpPeerB.GetData strData
    txtOutput.Text = strData
    End Sub如果要试用上面的例子,按 F5 键运行工程,然后在两个窗体的 txtSend TextBox 中分别键入一些文本。键入的文字将出现在另一个窗体的 txtOutput TextBox 中。关于 Bind 方法
    在上面的代码中,在创建 UDP 应用程序时调用了 Bind 方法,这是必须的。Bind 方法的作用是为控件“保留”一个本地端口。例如,如果将控件绑定到 1001 号端口,那么其它应用程序将不能使用该端口进行“监听”。该方法阻止其它应用程序使用同样的端口。Bind 方法的第二个参数是任选的。如果计算机上存在多个网络适配器,可以用 LocalIP 参数来指定使用哪一个适配器。如果忽略该参数,控件使用的将是计算机上“控制面板”设置中“网络”控制面板对话框中列出的第一个适配器。在使用 UDP 协议的时候,可以任意地改变 RemoteHost 和 RemotePort 属性,同时始终保持绑定在同一个 LocalPort 上。TCP 协议与此不同,在改变 RemoteHost 和 RemotePort 属性之前,必须先关闭连接。
      

  2.   

    我的源程序,不包括模块
    Dim hcg As Long     '图像卡句柄Public bSnap As Boolean  '采集状态标志Dim bminfo As BITMAPINFO    'BMP文件信息Dim pBuffer() As Byte       '图像缓冲区
    Private Sub Form_Load()
        Dim status As CGSTATUS
        
        bSnap = False       '设置当前采集状态为‘冻结’
        
        status = BeginCGCard(1, hcg)    '打开图像卡 1
        CG_SUCCESS (status)  '检验函数执行状态,如果失败,则返回错误状态消息框    Call InitCGCard '初始化图像卡硬件状态,用户也可以在其他位置初始化图像卡,但应保证图像卡已经打开
                        '建议用户在应用程序初始化时,同时初始化图像卡硬件。
            
    End SubPrivate Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
        
        If bSnap Then       '如未停止图像采集,出现提示信息
            Cancel = True
            MsgBox "Stop snap"
        End If
        
    End SubPrivate Sub Form_Unload(Cancel As Integer)
        Dim status As CGSTATUS
        
        status = EndCGCard(hcg) '关闭图像卡,释放图像卡内部资源
        CG_SUCCESS (status)
        
    End SubPrivate Sub Frame1_DragDrop(Source As Control, X As Single, Y As Single)End SubPrivate Sub PlayWnd_DragDrop(Source As Control, X As Single, Y As Single)End SubPrivate Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button)
         
        Select Case Button.Index
        Case 1
            If Not bSnap Then
                Snap True        '开始图像卡采集图像至内存
            End If
            
        Case 2
            If bSnap Then
                Snap False       '停止图像卡采集图像至屏幕
            End If
            
        End Select
         
    End Sub
    Public Sub Snap(ByVal bEnable As Boolean)
        Dim status As CGSTATUS
        
        Dim nNum As Long            '采集的总数
        Dim nStatusNum As Long      '当前正在采集的图像状态
        Dim nLastStatusNum As Long  '上一时刻采集的图像状态
        
        Dim handle As Long          '锁定内存句柄
        Dim pLineAddr As Long       '内存线性地址
        
        Dim hdc As Long             '显示设备句柄
        
            If (Not bEnable) Then       '正在采集图像到内存
            status = CGStopSnap(hcg)    '停止采集图像到内存
            If CG_SUCCESS(status) Then
                bSnap = False
            End If
        Else        '否则
            '开始图像卡采集图像到内存
            '指定图像卡将图像采集到静态内存偏移为0的位置,采集缓冲区大小为2幅图像大小
            status = CGStartSnap(hcg, 0, True, 2)
            If CG_SUCCESS(status) Then
                bSnap = True
            
                nStatusNum = -1
                nLastStatusNum = -1
                
                hdc = GetDC(PlayWnd.hWnd)       '得到PlayWnd的DC
                
                '锁定指定位置的静态内存,静态内存偏移为0,锁定大小为两幅图像大小
                status = CGStaticMemLock(0, 2 * bminfo.header.biSizeImage, handle, pLineAddr)
                
                If CG_SUCCESS(status) Then
                    Do
                        '获得当前采集图像的状态,指向正在采集的某场图像
                        '状态字以场为单位,从0开始
                        status = CGGetSnappingNumber(hcg, nStatusNum)
                        If CG_SUCCESS(status) Then
                            If nStatusNum <> nLastStatusNum Then
                                nLastStatusNum = nStatusNum
                                
                                nNum = -1
                                
                                If nStatusNum = 3 Then  '第1帧采集完成,正在采集第2帧
                                    nNum = 1
                                End If
                                
                                If nStatusNum = 1 Then  '第2帧采集完成,正在采集第1帧
                                    nNum = 2
                                End If
                                
                                If nNum > 0 Then
                                    
                                    '将静态内存中的图像传递到用户缓冲区,同时进行格式转换,如果静态内存中图像为15、16、32位,则转换为24位
                                    '由于图像卡采集到静态内存的图像数据是正向存放,而Windows中处理的位图数据需要倒置,因此一般还要将图像倒置
                                    status = CGDataTransform(pBuffer(0), pLineAddr + (nNum - 1) * bminfo.header.biSizeImage, bminfo.header.biWidth, bminfo.header.biHeight, bminfo.header.biBitCount, True)
                                    
                                    If CG_SUCCESS(status) Then
                                        '将图像缓冲区中的数据送至屏幕PlayWnd区域显示
                                        SetDIBitsToDevice hdc, 0, 0, bminfo.header.biWidth, bminfo.header.biHeight, 0, 0, 0, bminfo.header.biHeight, pBuffer(0), bminfo, DIB_RGB_COLORS
                                    End If
                                    
                                End If
                                
                            End If
                        End If
                        
                        DoEvents
                        
                    Loop While bSnap
                    
                    status = CGStaticMemUnlock(handle)  '解除静态内存锁定
                    
                End If
                
                ReleaseDC PlayWnd.hWnd, hdc '释放显示句柄
                
            End If
            
        End If
        
    End Sub
      

  3.   

    Public Sub InitCGCard()
        Dim status As CGSTATUS
        
        Dim format As VIDEO_FORMAT       '视频格式,包括 YUV422、RGB888、RGB565、RGB555、RGB8888、ALL8BIT、LIMITED8BIT
        Dim scan_mode As VIDEO_SCAN      '扫描模式,包括 FRAME、FIELD
        Dim Source As VIDEO_SOURCE       '视频源路,各种图像卡支持的视频源路不尽相同,请参看相应硬件说明
        Dim standard As VIDEO_STANDARD   '视频制式,包括 PAL、NTSC
            
        Dim osc As CRY_OSC      '晶振,包括CRY_OSC_35M(DH-CG300)、CRY_OSC_28M(DH-QP300)
                                '其他类型图像卡没有此硬件设置,但可以调用此接口,并返回CG_NOT_SUPPORT_INTERFACE信息
        
        format = RGB888         '设置视频格式为RGB8888
        status = CGSetVideoFormat(hcg, format)      '在采集图像到屏幕时,需要保证视频格式和当前系统屏幕位深度一致,而采集到内存没有此限制
        
        scan_mode = Frame       '设置扫描模式为FRAME(隔行)
        status = CGSetScanMode(hcg, scan_mode)
        
        Source.source_type = COMPOSITE_VIDEO        '视频类型为复合视频
        Source.nIndex = 0                           '序号为0
        status = CGSetVideoSource(hcg, Source.source_type, Source.nIndex)   '视频源路VIDEO_SOURCE包括视频类型和序号
        
        standard = PAL      '设置视频制式为PAL
        status = CGSetVideoStandard(hcg, standard)
        
        osc = CRY_OSC_35M   '设置晶振为35M
        status = CGSelectCryOSC(hcg, osc)
        
        '设置视频输入窗口,根据视频制式而有所不同
        If standard = PAL Then      '对于视频制式为PAL制
            status = CGSetInputWindow(hcg, 0, 0, 768, 576)  '水平方向为0-768,垂直方向为0-576
        ElseIf standard = NTSC Then '对于视频制式为NTSC制
            status = CGSetInputWindow(hcg, 0, 0, 640, 480)  '水平方向为0-768,垂直方向为0-576
        End If
            
            
        Dim rect As TRect
        Dim nMode As Integer
        Dim nWidth As Long
        Dim nHeight As Long
        
        GetClientRect PlayWnd.hWnd, rect    '获得当前PlayWnd视图状态
        
        nWidth = rect.Right - rect.Left     '视频输出窗口宽度为当前PlayWnd宽度
        nHeight = rect.bottom - rect.Top    '视频输出窗口高度为当前PlayWnd高度
        
        nMode = nWidth Mod 4
        nWidth = nWidth - nMode     '视频输出窗口宽满足4的倍数
        
        nMode = nHeight Mod 2
        nHeight = nHeight - nMode   '视频输出窗口高满足2的倍数
        
        status = CGSetOutputWindow(hcg, 0, 0, nWidth, nHeight)  '设置视频输出窗口
        
        
        '设置BMP文件信息,在保存bmp文件、显示采集图像时使用
        '以下设置如没有特别说明,基本相同
        bminfo.header.biBitCount = 24       '图像位深度,由视频格式确定,如果使用CGDateTransfrom函数,则将15,16,32位数据转换为24位
        bminfo.header.biClrImportant = 0
        bminfo.header.biClrUsed = 0
        bminfo.header.biCompression = BI_RGB
        bminfo.header.biHeight = nHeight    '图像高度,根据扫描模式(FRAME/FIELD)的不同
        bminfo.header.biPlanes = 1
        bminfo.header.biSize = Len(bminfo.header)
        bminfo.header.biSizeImage = nWidth * nHeight * 3    '图像大小,由视频输出窗口和视频格式确定
        bminfo.header.biWidth = nWidth      '图像宽度,一般为输出窗口宽度
        bminfo.header.biXPelsPerMeter = 0
        bminfo.header.biYPelsPerMeter = 0
        
        ReDim pBuffer(0 To (nWidth * nHeight * 3 - 1))  '设置图像缓冲区大小
        
    End Sub