乐趣区

关于c++:SkeyeLive中DShow本地采集视频参数设置及可能出现的错误提示详解

在近期公布的 SkeyeLive 多窗口版本中,因为界面的局限性,选择性的将本地采集的音视频参数设置在界面上剔除掉了(临时还没想好放在哪里,后续版本会在界面调整后增加),大家能够查看 SkeyeLive 源码中的 StartDSCapture 函数的参数设置代码进行相应设置;也应近期 SkeyeSMS 流媒体服务器群(QQ 群:102644504,欢送大家进群交换,任何技术问题,在所知的范畴内都能给予解答)中大家提到的参数设置的谬误提醒以及参数该如何设置的问题,上面我将就参数设置的具体细节和代码关联做具体介绍。

一、查看设施属性

在 Windows 零碎中大多数音视频采集设施都能反对通过 DirecShow 进行捕捉,在捕捉之前,咱们首先应该理解设施的性能参数,如:视频采集设施的长,宽,色调格局,图像格式等,以及音频设备的采样率,采样位宽,声道数等;要理解这些,咱们能够简略的通过一款微软提供的 DShow 设施采集小工具“amcap.exe”查看,如下图所示:

在“设施”菜单栏中能够查看到枚举的以后零碎中所有的音视频采集设施(包含虚构设施),抉择一个设施即可进行捕捉,而后在“选项”一栏中能够进行“预览”或者相应的参数设置,如下图所示:

其中,“视频捕捉接口”项是咱们常常用到的查看视频的长,宽,色调格局,图像格式等参数的设施信息,如下图所示:

此外,还有其余一些图像参数的设置,有趣味的也能够理解下;当然,咱们齐全能够通过代码来实现这个小工具的性能,在我的另一片文章“SkeyLive 中 DirectShow 采集音视频流程及几种采集形式介绍”中有具体的阐明,这里就不做过多赘述。

二、DShow 采集参数设置

参数设置咱们定义了一个构造,其原型如下:

// 设施捕捉参数信息
typedef struct tagDEVICE_CONFIG_INFO
{
    int nVideoId;// 视频    ID -1== 不必,0-n == id
    int nAudioId;// 音频 id -1== 不必,0-n == id
    int  nDeviceId;// 设施序号 1,2,3,4,5....
    struct tagVideoInfo
    {
        int nWidth;// 视频高度
        int nHeight;// 视频宽度
        int nVideoWndId;// 视频关联窗口 ID
        int nFrameRate;// 视频帧率
        char strDataType[64];// 标识 色调格局 数据类型,如 "YUY2" "YUYV" "UYVY 等"
        int nRenderType;// 出现形式
        int nPinType;// 捕捉口
    }VideoInfo;

    struct tagAudioInfo
    {
        int nChannaels;// 通道数
        int nBytesPerSample;// 采样位数
        int nSampleRate;// 采样率
        DWORD nAudioBufferType;// 音频缓存区的大小
        int nPinType;// 捕捉口
    }AudioInfo;

}DEVICE_CONFIG_INFO;

构造中参数均有具体阐明,这里就比拟重要的色调格局进行举例说明:
-> 色调格局(strDataType)
色调格局是指 DShow 捕捉输入的图像数据的色调格局,次要是 RGB 和 YUV 两种,这个参数很重要,在显示和编码时咱们都会用到,设置不当可能导致色调显示不对甚至未知的程序解体(个别是指针越界),在 SkeyeStreamPusher 中反对两种罕用的格局 YUY2 和 RGB24,次要是编码时须要进行格局转换或者分支解决。

咱们在程序中中进行了简略的设施配置:

        //1. 咱们来简略配置一个设施信息
        m_sDevConfigInfo.nDeviceId = 1;
        m_sDevConfigInfo.nVideoId = nCamId;// 摄像机视频捕捉 ID
        m_sDevConfigInfo.nAudioId = nAudioId;// 音频捕捉 ID
        m_sDevConfigInfo.VideoInfo.nFrameRate = nFps;
        m_sDevConfigInfo.VideoInfo.nWidth = nVideoWidth;
        m_sDevConfigInfo.VideoInfo.nHeight = nVideoHeight;
        strcpy_s(m_sDevConfigInfo.VideoInfo.strDataType, 64, "YUY2");
        m_sDevConfigInfo.VideoInfo.nRenderType = 1;
        m_sDevConfigInfo.VideoInfo.nPinType = 1;
        m_sDevConfigInfo.VideoInfo.nVideoWndId = 0;

        m_sDevConfigInfo.AudioInfo.nAudioBufferType = 4096;
        m_sDevConfigInfo.AudioInfo.nBytesPerSample = 16;
        m_sDevConfigInfo.AudioInfo.nSampleRate = 16000;//44100;
        m_sDevConfigInfo.AudioInfo.nChannaels = 2;
        m_sDevConfigInfo.AudioInfo.nPinType = 2;

        // 初始化 Pusher 构造信息
        memset(&m_mediainfo, 0x00, sizeof(Skeye_MEDIA_INFO_T));
        m_mediainfo.u32VideoCodec =  Skeye_SDK_VIDEO_CODEC_H264;//0x1C;
        m_mediainfo.u32VideoFps = nFps;
        m_mediainfo.u32AudioCodec = Skeye_SDK_AUDIO_CODEC_AAC;
        m_mediainfo.u32AudioChannel = 2;
        m_mediainfo.u32AudioSamplerate = 16000;//44100;

如果参数设置不胜利,将会呈现谬误(或者正告)提醒,有一种提醒是设施不反对外部显示 (经测试某些虚构设施可能呈现),这在 DShow 采集库底层代码中曾经做过解决,进行内部关上窗口显示,不影响采集;另有一种提醒为“应用默认参数”,这种提醒就表明咱们设置的参数失败了,可能是设施不反对这种色调格局或者分辨率;当然,捕捉设施通常是胜利的,然而,要留神默认的色调格局和分辨率将有可能和咱们的设置参数不统一,这时候就要理解设施的具体参数,而后在编码时进行相应解决,否则可能导致编码失败,或者编码后推送进去的视频色调不对。
参数设置代码如下:

        // 失去视频格式大小
    AM_MEDIA_TYPE *pmt;
    pAMStreamConfig->GetFormat(&pmt);

    // 设置视频格式
    pmt->majortype = MEDIATYPE_Video;

    GUID defaultSubType = pmt->subtype;
    pmt->subtype  = GetMediaTypeGuid(strRGBBytes);


    VIDEOINFOHEADER *pvih = reinterpret_cast<VIDEOINFOHEADER *>(pmt->pbFormat);
    // 设置回去
    int nDefualWidth = pvih->bmiHeader.biWidth;
    int nDefualHeight = pvih->bmiHeader.biHeight;

    pvih->bmiHeader.biWidth = iWidth; 
    pvih->bmiHeader.biHeight = iHeight;
     pvih->bmiHeader.biSizeImage = pmt->lSampleSize = iWidth*iHeight*pvih->bmiHeader.biPlanes*pvih->bmiHeader.biBitCount/8;
     pvih->AvgTimePerFrame = (LONGLONG)(10000000/nFrameRate);

    hr = pAMStreamConfig->SetFormat(pmt);
    if(FAILED(hr))
    {
        // 如果设置失败能够选用默认的, 但使用之后, 小屏幕初始化时会呈现闪动的状况        
//         pvih->bmiHeader.biWidth = nDefualWidth; 
//         pvih->bmiHeader.biHeight = nDefualHeight;
//         pvih->bmiHeader.biSizeImage = pmt->lSampleSize = nDefualWidth*nDefualHeight*pvih->bmiHeader.biPlanes*pvih->bmiHeader.biBitCount/8;
        
        pmt->subtype  = defaultSubType;

        hr = pAMStreamConfig->SetFormat(pmt);

        CSourceManager* pManager = CSourceManager::Instance();
        if (pManager)
        {pManager->LogErr(_T("应用默认参数。"));
        }
        //AfxMessageBox(_T("应用默认参数。"));

        if(FAILED(hr))
        {SAFE_RELEASE(pAMStreamConfig);
            FreeMediaType(*pmt);
            //ERR_DEBUG("初始化设置视频格式失败");
            return hr;
        }

一开始,咱们就失去了设施的参数,如果参数设置失败后,将色调格局设置回去,而后提醒“应用默认参数。”;实践上来说,咱们应该将这个设施的参数保留下来,在设置失败时一成不变的设置回去,而后在外层函数中对其进行容错解决,然而,咱们不可能解决所有可能呈现的未知的色调格局或者其余的未知参数类型,为了程序的稳定性,咱们通常只解决罕用的可管制的参数类型,如果有其余色调格局的须要,大家应该本人在设置好后,在编码前做相应的色调格局转换解决,或者把这种格局通知我,我将会将其增加进 SkeyeLive 进行兼容。

退出移动版