织梦CMS - 轻松建站从此开始!

罗索

directshow和vfw采集并转发视频数据的接口

落鹤生 发布于 2011-02-28 15:24 点击:次 
directshow和vfw采集并转发视频数据的接口
TAG:

/********************此文可以被转发,但请转发者保留作者的署名权
****李浩
****msn:lihao_nx@hotmail.com
****
****email:lihaoyxj@gmail.com
****出处:lihaoyxj.cublog.cn
****from:http://blog.csdn.net/lihao_ningxia
*****************/
vfw
//head file

// VideoCapture.h: interface for the VideoCapture class.

#if !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_)

#define AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000
#include<vfw.h>
#include<afxmt.h>
#include<afxole.h>

#include "CommClient.h"

#include "Encoder/libr263.h"
#include "Decoder/tmndec.h"

//  If the parameters below are changed then change following

//  > cdata & cbuffer_size in VideoNetDlg.cpp

//  > rgbdata & buffersize in VideoNetDlg.cpp

//  > update CPARAMS structure before compression

//  > computation of local_wnd_x para in OnInitDialog()

#define QCIF_WIDTH  176

#define QCIF_HEIGHT 144

//#define QCIF_WIDTH  320

//#define QCIF_HEIGHT 240

#define IMAGE_WIDTH       QCIF_WIDTH

#define IMAGE_HEIGHT      QCIF_HEIGHT

// 回调函数定义

typedef LRESULT (*CALLBACKFUNC)(HWND,LPVIDEOHDR);

class VideoCapture

{

public:

   HWND m_capwnd;

    CStdioFile log;

    CAPDRIVERCAPS caps;

    CMutex protectframe;

    int avgaudiosize;

    BOOL isOver;

    CDialog *dlg;

    BITMAPINFOHEADER m_bmpheader;

    BITMAPINFO m_bmpinfo;

    VideoCapture();

    virtual ~VideoCapture();

    BOOL Initialize();

    BOOL  SetCapturePara();

    void Destroy();

    void GetDriverCaps();

    void SetAudioFormat();

    int AllocateMemory(PBITMAPINFO &bmpinfo);

    int getFormatSize(BITMAPINFO bmp);

    int getImageSize(BITMAPINFO bmp);

    // 启动视频捕获

    BOOL StartCapture(HDC BackDC);

    BOOL StopCapture();

    friend LRESULT CALLBACK OnCaptureVideo(HWND hWnd, LPVIDEOHDR lpheader) ;

    void*            m_pParam;

protected:

    void DrawLocalScreen(LPVIDEOHDR lphdr);

    void InitCompressor();

    void CompressFrame(LPVIDEOHDR lphdr);

     CALLBACKFUNC    m_OnCaptureVideo;

 

    // 压缩参数

     COMPVARS        m_CV;

     // 视频回放句柄

     HDC                m_LocalScreenDC;

    HDRAWDIB        m_hdib;

     // 数据通信接口

     CCommClient*    m_pCommClient;

      // Compression parameters....

     CParam cparams;

      // Buffer for storing YUV data....

     unsigned int yuv[ QCIF_WIDTH*QCIF_HEIGHT  + (QCIF_WIDTH*QCIF_HEIGHT)/2 ];

 public:

    void SetCommClient(CCommClient* pClient);

    //

    // 设置采集数据回调接口

    //

    void SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam);

    //

    // 回放远程视频

    //

    void DrawRemoteScreen(char *data, UINT size, HDC hScreenDC);

};

#endif // !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_)

//cpp file

//    Project     : VideoNet version 1.1.

//

//    File description

//    Name    :  VideoCapture.cpp

//    Details :  Captures the frames from webcam.

//

#include "Stdafx.h"

#include "VideoCapture.h"

#include <afxmt.h>

#ifdef _DEBUG

 

#define new DEBUG_NEW

 

#undef THIS_FILE

 

static char THIS_FILE[] = __FILE__;

 

#endif

 

#pragma comment(lib,"vfw32")

 

#pragma comment(lib,"winmm")

 

// Global varialbes...

 

int count=0;

 

unsigned char cdata[10000];

 

int cbuffer_size=10000;

 

unsigned char rgbdata[80000];

 

int buffersize=80000;

 

// Callback function gets invoked during compression...

 

// It returns the compressed data byte by byte...

 

void OwnWriteFunction(int byte)

 

{

 

    if(count<cbuffer_size)

 

        cdata[count]=(unsigned char)byte;

 

   

 

    count++;

 

   

 

}

 

//////////////////////////////////////////////////////////////////////

 

// Construction/Destruction

 

//////////////////////////////////////////////////////////////////////

 

VideoCapture::VideoCapture()

 

{

 

    m_capwnd            = NULL;

 

    isOver                = FALSE;

 

    m_OnCaptureVideo    = NULL;

 

   

 

    log.Open("videocapture.log",CFile::modeCreate | CFile::modeWrite);

 

}

 

VideoCapture::~VideoCapture()

 

{

 

}

 

BOOL VideoCapture::Initialize()

 

{

 

    char devname[100],devversion[100];

 

    char str[200];

 

    int index=0;

 

   

 

    // 初始化压缩编码器

 

    InitCompressor();

 

   

 

    // 创建摄像头句柄

 

    m_capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);

 

    if(m_capwnd==NULL)

 

    {

 

        log.WriteString("\n Unable to create capture window");

 

        return FALSE;

 

    }

 

    // 连接摄像头设备   

 

    capSetUserData( m_capwnd, this );

 

   

 

    // 显示视频设置对话框,进行配置视频的大小、颜色位数等。

 

    capDlgVideoFormat( m_capwnd );

 

    // 取得视频图像数据头,后面压缩时需要用到

 

    capGetVideoFormat( m_capwnd, &m_bmpinfo, sizeof(BITMAPINFO) );

 

   

 

    // 设置回调函数

 

    capSetCallbackOnVideoStream( m_capwnd, OnCaptureVideo );

 

   

 

    capGetDriverDescription(index,devname,100,devversion,100);

 

   

 

    sprintf(str,"\n Driver name = %s version = %s ",devname,devversion);

 

    log.WriteString(str);

 

   

 

    // Connect to webcam driver

 

    if( ! capDriverConnect(m_capwnd,index) )

 

    {

 

       

 

        // Device may be open already or it may not have been

 

        // closed properly last time.

 

        AfxMessageBox("Unable to open Video Capture Device");

 

        log.WriteString("\n Unable to connect driver to the window");

 

        m_capwnd=NULL;

 

        return FALSE;

 

    }

 

   

 

    // Set the capture parameters

 

    if(SetCapturePara()==FALSE)

 

    {

 

        log.WriteString("\n Setting capture parameters failed");

 

        capDriverDisconnect(m_capwnd);

 

        return FALSE;

 

    }

 

    return TRUE;

 

}



/**

 

*   Start capturing frames from webcam

 

*

 

*/

 

BOOL VideoCapture::StartCapture(HDC    BackDC)

 

{

 

    m_LocalScreenDC    = BackDC;

 

   

 

    // 初始化视频回放对象

 

    m_hdib    = ::DrawDibOpen();

 

    if( m_hdib != NULL )

 

    {

 

        ::DrawDibBegin(

 

            m_hdib,

 

            m_LocalScreenDC,

 

            -1,                // don't stretch

 

            -1,                // don't stretch

 

            &m_bmpinfo.bmiHeader,

 

            IMAGE_WIDTH,         // width of image

 

            IMAGE_HEIGHT,        // height of image

 

            0               

 

            );

 

    }

 

   

 

    // 开始视频采集

 

    if(capCaptureSequenceNoFile(m_capwnd)==FALSE)

 

    {

 

        log.WriteString("\n Failed to capture Sequence ..");

 

        return FALSE;

 

    }

 

   

 

    return TRUE;

 

   

 

}




/**

 

*   Stop the capturing process

 

*

 

*/

 

BOOL VideoCapture::StopCapture()

 

{

 

   

 

    capCaptureStop(m_capwnd);

 

    capCaptureAbort(m_capwnd);

 

    Sleep(500);   

 

   

 

    return TRUE;

 

}





/**

 

*   Stop the catpure process and disconnect the driver

 

*

 

*/

 

void VideoCapture::Destroy()

 

{

 

   

 

    if(m_capwnd==NULL) return;

 

   

 

    // Stop the capturing process   

 

    capCaptureAbort(m_capwnd);

 

   

 

    // Disable the callback function..

 

    capSetCallbackOnVideoStream(m_capwnd, NULL);

 

   

 

    Sleep(300);        // This delay is important...

 

   

 

    // Finally disconnect the driver

 

    capDriverDisconnect(m_capwnd);

 

}







/**

 

*

 

*     Set various capture parameters...

 

*

 

*/

 

BOOL  VideoCapture::SetCapturePara()

 

{

 

    CAPTUREPARMS CapParms={0};   

 

   

 

   

 

    capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms));

 

   

 

    CapParms.fAbortLeftMouse = FALSE;

 

    CapParms.fAbortRightMouse = FALSE;

 

    CapParms.fYield = TRUE;

 

    CapParms.fCaptureAudio = FALSE;

 

    CapParms.wPercentDropForError = 50;

 

    CapParms.dwRequestMicroSecPerFrame = (DWORD) ( 1.0e6 / 15.0 );

    if(capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms))==FALSE)

    {

         log.WriteString("\n Failed to set the capture parameters ");

        return FALSE;

    } 

    // Set Video Format

     capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));

    m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH;

     m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT;

    BOOL ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));

   if(ret==TRUE)

        log.WriteString("\n Video parameters set properly");

   return TRUE;

}

/**

*  Allocate Memory for DIB image buffer

*/

int VideoCapture::AllocateMemory(PBITMAPINFO &bmpinfo)

{

    int size1,size2,size;

    BITMAPINFO tbmp;

    char  str[200];

    capGetVideoFormat(m_capwnd,&tbmp,sizeof(tbmp));

    size1 = getFormatSize ( tbmp );

    size2 = getImageSize ( tbmp );

    size = size1 + size2;

    sprintf(str,"\n Formatsize = %d imagesize = %d , fun_size = %d ",

        size1,size2, capGetVideoFormatSize(m_capwnd));

    log.WriteString(str);

    bmpinfo=(BITMAPINFO *) new BYTE[size];

    if(bmpinfo==NULL)

     {

        AfxMessageBox("Unable to allocate memory");

        return -1;

     }

    memset(bmpinfo,0,sizeof(*bmpinfo));

    capGetVideoFormat(m_capwnd,bmpinfo,sizeof(*bmpinfo));

    return size1;

}

/**

*   Calculates the Format Size for DIB image

*/

int VideoCapture::getFormatSize(BITMAPINFO bmp)

{

    int size;

    size=(bmp.bmiHeader.biSize!=0)?bmp.bmiHeader.biSize :sizeof(BITMAPINFOHEADER);

    //return (size+ bmp.bmiHeader.biClrUsed *sizeof(RGBQUAD));

    return size; //RGBQUAD is absent for 24 bit bmp image.

}

/*

*    Calculates the Size of Image

*/

int VideoCapture::getImageSize(BITMAPINFO bmp)

{

    int size;

    BITMAPINFOHEADER head=bmp.bmiHeader;

    if( head.biSizeImage==0 )

    {

        size=( head.biWidth * head.biHeight * head.biBitCount)/8;

    }

    else

        size = head.biSizeImage;  

    return size;

}

// 设置采集数据回调接口 

void VideoCapture::SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam)

{

    m_OnCaptureVideo    = OnCaptureVideo;

    m_pParam            = pParam;

}

/* Invoked when the video frame is captured by the driver*/

LRESULT CALLBACK OnCaptureVideo(HWND mwnd,LPVIDEOHDR lphdr)

{

    VideoCapture *vidcap=(VideoCapture *)capGetUserData(mwnd);

    if( vidcap!=NULL )

    {

        vidcap->DrawLocalScreen( lphdr );

        vidcap->CompressFrame( lphdr ); 

//        if ( vidcap->m_OnCaptureVideo != NULL )

//        {

//            (*vidcap->m_OnCaptureVideo)( mwnd, lphdr );

//            vidcap->DrawLocalScreen( lphdr );

//            vidcap->CompressFrame( lphdr );

//        }

    }

    return TRUE;

}

void VideoCapture::CompressFrame(LPVIDEOHDR lphdr)

{

//    BOOL        bKeyFrame;

//    DWORD        OutActSize;

//    BYTE*        Buf;

//    OutActSize    = m_bmpinfo.bmiHeader.biSizeImage;

//    bKeyFrame    = 0;

//    Buf            = (BYTE*)ICSeqCompressFrame( &m_CV,0,lphdr->lpData,&bKeyFrame,(long*)&OutActSize);

    Bits bits;        // Various count about compression

    //Convert the data from rgb format to YUV format   

    ConvertRGB2YUV( IMAGE_WIDTH,IMAGE_HEIGHT, lphdr->lpData, yuv );

    // Reset the counter

    count=0;

    // 压缩数据

    cparams.format=CPARAM_QCIF;

    cparams.inter = CPARAM_INTRA; 

    cparams.Q_intra = 8;

    cparams.data=yuv;        //  Data in YUV format...

    ::CompressFrame(&cparams, &bits);

    // 传送数据

    m_pCommClient->SendPacket( (char*)cdata, count, PACKET_VIDEO );

}

void VideoCapture::InitCompressor()

{

//    memset( &m_CV,0,sizeof(COMPVARS) );

//    m_CV.cbSize        = sizeof( m_CV );

//    ICCompressorChoose( m_capwnd, 0, NULL, NULL, &m_CV, "Choose a Compressor" );

    // Initialize table for RGB to YUV conversion

    InitLookupTable();

    // Initialize the compressor

    cparams.format = CPARAM_QCIF;

    InitH263Encoder(&cparams);

    // Set up the callback function

    WriteByteFunction = OwnWriteFunction;

    // Initialize decompressor

    InitH263Decoder();

    return;

}

// 回放本地视频

void VideoCapture::DrawLocalScreen(LPVIDEOHDR lphdr) 

{

    ::DrawDibDraw(

        m_hdib,

        m_LocalScreenDC,

        0,        // dest : left pos

        0,        // dest : top pos

        -1,                     // don't zoom x

        -1,                     // don't zoom y

        &m_bmpinfo.bmiHeader,             // bmp header info

        lphdr->lpData,                     // bmp data (lihao_ningxia)

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201102/10982.html]
本文出处:CSDN博客 作者:lihao_ningxia
顶一下
(0)
0%
踩一下
(1)
100%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容