版权声明:www.gudianxiaoshuo.com (古典小说网) 今日头条号: 古典古韵古典小说、讨厌编程 https://blog.csdn.net/shuilan0066/article/details/87855789
参考资料:
一 视频回调
1 合成视频回调
Nlss_SetVideoSamplerCB,会通过设置的回调函数返回推流之前的rgb32的buffer给上层用于显示;
1)设置视频回调函数
typedef void(*PFN_NLSS_MERGED_VIDEO_SAMPLER_CB)(_HNLSSERVICE hNLSService, ST_NLSS_VIDEO_SAMPLER *pstSampler);
void LsSession::SetVideoSamplerCB(){
NLS_SDK_GET_FUNC(Nlss_SetVideoSamplerCB)(LsClient, VideoCallback);
}
void LsSession::SetVideoSamplerCB(PFN_NLSS_MERGED_VIDEO_SAMPLER_CB cb)
{
NLS_SDK_GET_FUNC(Nlss_SetVideoSamplerCB)(LsClient, cb);
}
//初始化时,添加视频回调
bool NLSLiveForm::StartPrew(){
ST_NLSS_VIDEOIN_PARAM stChildVInParam;
std::string accid;
//Nlss_InitParam初始化直播对象,直播参数ST_NLSS_PARAM生效
if(!NewInitMediaCapture())//if (!InitMediaCapture())
{
m_errorLog.WriteErrorFuc("InitMediaCapture()");
m_errMsg = L"初始化视频采集设备出错";
ShowMsgBox(this->GetHWND(), m_errMsg, MsgboxCallback(), L"校内外直播间 ", L"确定", L"取消");
return false;
}
//Nlss_Start创建推流实例,开始处理视频(还未开始推流)
if (!m_LiveStreaming.OnStartVideo())
{
m_errorLog.WriteErrorFuc("!m_LiveStreaming.OnStartVideo() - 打开视频采集出错");
m_ChildVideoDisplayList.clear();
m_ChildVideoList.clear();
m_ChildVideoInfoList.clear();
m_errMsg = L"打开视频采集出错";
ShowMsgBox(this->GetHWND(), m_errMsg, MsgboxCallback(), L"校内外直播间 ", L"确定", L"取消");
return false;
}
m_LiveStreaming.SetStatusCB(&OnLiveStreamStatusNty); //直播过程状态改变通知函数 比如,网络不好
if (g_bUseSharedCamera)
{
m_LiveStreaming.SetVideoSamplerCB(VideoCallback_G);
}else
m_LiveStreaming.SetVideoSamplerCB();
2)合成后画面的视频回调
//合成画面后的视频回调
void VideoCallback_G(_HNLSSERVICE hNLSService, ST_NLSS_VIDEO_SAMPLER *sampler)
{
if (sampler)
{
int ret = sampler->iDataSize;
if (ret > 0)
{
int nLen = sampler->iWidth*sampler->iHeight;
nim_nls::LssManange::IsBlackVideo = IsBlack((DWORD*)sampler->puaData, nLen);
timeb time_now;
ftime(&time_now); // 秒数
__int64 cur_timestamp = time_now.time * 1000 + time_now.millitm; // 毫秒
nim_nls::LssManange::GetVideoFrameMng()->AddVideoFrame(true, cur_timestamp, (const char*)sampler->puaData, sampler->iDataSize, \
sampler->iWidth, sampler->iHeight, "", nim_comp::VideoFrameMng::Ft_ARGB);
//capture_video_pic_.ResetData(cur_timestamp, src_buffer, size, width, height/*, subtype*/);
char* pData=m_memMng.getData();
INT32 nFps = g_pLiveForm->m_videoFps;
INT32 nWidth = sampler->iWidth;
INT32 nHeight = sampler->iHeight;
INT32 Info[] = { nFps, nWidth, nHeight };
int len = sizeof(Info) / sizeof(Info[0]);
if (pData)
{
WaitForSingleObject(m_memMng.m_hReadEvent, INFINITE);
ResetEvent(m_memMng.m_hWriteEvent);
memcpy((INT32*)pData, Info, sizeof(INT32)*len);
memcpy(pData + 12, nim_nls::LssManange::GetVideoFrameMng()->capture_video_pic_.pdata_, nim_nls::LssManange::GetVideoFrameMng()->capture_video_pic_.size_);
SetEvent(m_memMng.m_hWriteEvent);
}
}
}
}
2 单个独立子视频回调
Nlss_ChildVideoSetSoloPreviewCB
设置单独预览的视频流buffer回调函数,可用于预览进行显示
Nlss_ChildVideoSwitchSoloPreview
开|关子视频单独预览
void Nlss_ChildVideoSetSoloPreviewCB(_HNLSSCHILDSERVICE hNLSSChild, PFN_NLSS_VIDEOSAMPLER_CB pFunVideoSamplerCB);
void Nlss_ChildVideoSwitchSoloPreview(_HNLSSCHILDSERVICE hNLSSChild, bool bOn);
注意: 遇到奇怪的事情,就是单视频回调,必须在单视频采集后设置才有效,否则,不会返回回调信息。
就是说必须先调用 OnChildVideoStartCapture(accid),在采集这个视频后,
再调用OnChildVideoSetSoloPreviewCB(accid, SoloVideoCallback_G); 才有效。
如果先调用OnChildVideoSetSoloPreviewCB, 后调用OnChildVideoStartCapture,这样即使调用成功了startCapture,也不会有视频回调
1)设置回调
void LsSession::OnChildVideoSetSoloPreviewCB(const std::string& accid, PFN_NLSS_CHILD_VIDEO_SAMPLER_CB pFunVideoSamplerCB)
{
std::map<std::string, _HNLSSCHILDSERVICE>::const_iterator iter = nlss_child_services_.find(accid);
if (iter != nlss_child_services_.end())
NLS_SDK_GET_FUNC(Nlss_ChildVideoSetSoloPreviewCB)(iter->second, pFunVideoSamplerCB);
}
void LsSession::OnChildVideoSwitchSoloPreview(const std::string& accid, bool bOn)
{
std::map<std::string, _HNLSSCHILDSERVICE>::const_iterator iter = nlss_child_services_.find(accid);
if (iter != nlss_child_services_.end())
NLS_SDK_GET_FUNC(Nlss_ChildVideoSwitchSoloPreview)(iter->second, bOn);
}
void NLSLiveForm::SetAllCamerasSoloVideoCB(){
std::string path;
std::string accid;
for (int i = 0; i < m_iVideoDeviceNum; i++)
{
path = m_pVideoDevices[i].paPath;
accid = GetAccidFromPath(path);
m_LiveStreaming.OnChildVideoSetSoloPreviewCB(accid, SoloVideoCallback_G);
SwitchSoloPreview(accid, TRUE);
}
}
2) 回调函数
void SoloVideoCallback_G(_HNLSSERVICE hNLSService, _HNLSSCHILDSERVICE hNLSSChild, ST_NLSS_VIDEO_SAMPLER *sampler)
{
_HNLSSCHILDSERVICE handle = g_pLiveStreaming->GetChildServiceByAccid(g_pLiveForm->GetCurCameraAccid());
if (handle!=hNLSSChild)
{
return;
}
if (sampler)
{
int ret = sampler->iDataSize;
printf("%d\n", sampler->iDataSize);
if (ret > 0)
{
int nLen = sampler->iWidth*sampler->iHeight;
nim_nls::LssManange::IsBlackVideo = IsBlack((DWORD*)sampler->puaData, nLen);
timeb time_now;
ftime(&time_now); // 秒数
__int64 cur_timestamp = time_now.time * 1000 + time_now.millitm; // 毫秒
nim_nls::LssManange::GetSoloVideoFrameMng()->AddVideoFrame(true, cur_timestamp, (const char*)sampler->puaData, sampler->iDataSize, \
sampler->iWidth, sampler->iHeight, "", nim_comp::VideoFrameMng::Ft_ARGB);
}
}
}