实现功能说明:
实现服务端与客户端视频文件实时播放功能即直播功能(注:服务端和客户端有延迟),服务端截图如下:
客户端可以使用vlc播放器通过如下地址播放:mms://127.0.0.1:8041(注:127.0.0.1是本机回环Ip,至于什么是回环IP,自己百度)
其他说明:
1.此流媒体开发是基于windows media encoder SDK开发,而这个sdk又需要依赖windows media encode中的库文件,因此,开发之前,先安装这两个软件,开发过程中只要包含windows media encoder SDK即可,下载地址为(window7亲测可用):http://download.csdn.net/download/zaokang5603/10028002
2.目前上面只支持windows的媒体文件,如果想要支持avi,rmvb视频各种,可以下载个编解码器,例如FinalCodecs,安装即可,无需额外配置
3.如果想要两边支持实时播放,且服务器这边可以有音频输出,那么可以在开始编码之后,可以使用wmPlayer控件,播放此文件,和预览的道理是一样的
4.以下代码是基于vs2013开发,工程下载地址为:http://download.csdn.net/download/zaokang5603/10118016
5.本人也是初次开发,哪里有问题,留言说明,莫喷!
代码片段如下:
#define RELEASE_PTR {\
if (pSrcGrpColl)\
{\
pSrcGrpColl->Release(); \
pSrcGrpColl = NULL; }\
if (pSrcGrp)\
{\
pSrcGrp->Release(); \
pSrcGrp = NULL; \
}\
if (pAudSrc)\
{\
pAudSrc->Release(); \
pAudSrc = NULL; \
}\
if (pVidSrc)\
{\
pVidSrc->Release(); \
pVidSrc = NULL; \
}\
if (pProColl)\
{\
pProColl->Release(); \
pProColl = NULL; \
}\
if (pPro)\
{\
pPro->Release(); \
pPro = NULL; \
}\
if (pPro2)\
{\
pPro2->Release(); \
pPro2 = NULL; \
}\
if (pBrdCst)\
{\
pBrdCst->Release(); \
pBrdCst = NULL; \
}\
if (pPreviewColl)\
{\
pPreviewColl->Release(); \
pPreviewColl = NULL; \
}\
}
void CmsdntestDlg::OnBnClickedButton1()//开启流媒体按钮
{
// TODO: 在此添加控件通知处理程序代码
CComBSTR serverFilePath;
{
CFileDialog dlgFile(TRUE);
if (dlgFile.DoModal() == IDOK)
{
CString file = dlgFile.GetPathName();
serverFilePath = file.AllocSysString();
//m_path = file.AllocSysString();
//m_serverFilePath = WideCharToUTF8(bstr);
}
}
CoUninitialize();//必须先要添加这一坨,可能dlgFile析构没有CoUninitialize造成流媒体广播一段时间就挂掉了
if (!Initencoder(serverFilePath))//搭建mms流媒体服务器
{
AfxMessageBox("encoding file failed!");
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
return;
}
SysFreeString(serverFilePath);
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
}
BOOL CmsdntestDlg::Initencoder(CComBSTR &filePath)
{
IWMEncSourceGroupCollection* pSrcGrpColl = NULL;
IWMEncSourceGroup* pSrcGrp = NULL;
IWMEncSource* pAudSrc = NULL;
IWMEncSource* pVidSrc = NULL;
IWMEncProfileCollection* pProColl = NULL;
IWMEncProfile* pPro = NULL;
IWMEncProfile2* pPro2 = NULL;
IWMEncBroadcast* pBrdCst = NULL;
IWMEncDataViewCollection* pPreviewColl = NULL;
//IWMEncProfile* pPro = NULL;
// Initialize the COM library and retrieve a pointer
// to an IWMEncoder interface.
if (FAILED(CoInitialize(NULL)))
{
return FALSE;
}
if (!m_pEncoder)
{
if (FAILED(CoCreateInstance(CLSID_WMEncoder,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWMEncoder,
(void**)&m_pEncoder)))
{
return FALSE;
}
}
// Retrieve a pointer to an IWMEncSourceGroupCollection
// interface.
if (FAILED(m_pEncoder->get_SourceGroupCollection(&pSrcGrpColl)))//获得解码器集合
{
return FALSE;
}
// Add a new source group to the collection.
if (FAILED(pSrcGrpColl->Add(CComBSTR("SG_1"), &pSrcGrp)))//获得解码器组
{
RELEASE_PTR;
return FALSE;
}
// Add an audio and avideo source to the source group.
if (FAILED(pSrcGrp->AddSource(WMENC_AUDIO, &pAudSrc)))//添加音频资源
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(pSrcGrp->AddSource(WMENC_VIDEO, &pVidSrc)))//添加视频资源
{
RELEASE_PTR;
return FALSE;
}
// Specify an .avi source file and a .wmv output file.
if (FAILED(pAudSrc->SetInput(filePath)))//获得文件音频源
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(pVidSrc->SetInput(filePath)))//获得文件视频源
{
RELEASE_PTR;
return FALSE;
}
// Loop through the profile collection and retrieve a specific
// profile.
if (FAILED(m_pEncoder->get_ProfileCollection(&pProColl)))//获得配置集合
{
RELEASE_PTR;
return FALSE;
}
if (!creatprofile(&pPro2))//创建配置文件
{
AfxMessageBox("creatProfile failed!");
RELEASE_PTR;
return FALSE;
}
if (FAILED(pPro2->QueryInterface(IID_IWMEncProfile, (void**)&pPro)))
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(pSrcGrp->put_Profile(CComVariant(pPro))))//把配置文件配置给资源组,即解码器
{
RELEASE_PTR;
return FALSE;
}
if (!m_pPreview)
{
if (FAILED(CoCreateInstance(CLSID_WMEncPreview,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWMEncDataView,
(void**)&m_pPreview)))//创建预览对象
{
RELEASE_PTR;
return FALSE;
}
}
// Retrieve the preview collection.
if (FAILED(pVidSrc->get_PreviewCollection(&pPreviewColl)))//获取预览集合
{
RELEASE_PTR;
return FALSE;
}
// Add the preview object to the data view collection. If you set the
// cookie to -1, the encoding process automatically generates a unique
// cookie.
if (FAILED(pPreviewColl->Add(m_pPreview, &m_lCookie)))//把预览添加进预览集合
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(m_pEncoder->get_Broadcast(&pBrdCst)))//广播
{
RELEASE_PTR;
return FALSE;
}
;
// Select the 5th profile from the collection and set it into the source group.
if (FAILED(pBrdCst->put_PortNumber(WMENC_PROTOCOL_HTTP, 8401)))//广播端口8401,即客户端通过 mms://127.0.0.1:8041地址即可观看直播,注:127.0.0.1是用当前服务器ip,非此ip
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(m_pEncoder->PrepareToEncode(VARIANT_TRUE)))//准备开始编解码
{
RELEASE_PTR;
return FALSE;
}
HWND hWnd = GetDlgItem(IDC_STATIC)->GetSafeHwnd();
if (FAILED(m_pPreview->SetViewSetting((DWORD)m_lCookie,
sizeof(hWnd),
(BYTE*)&hWnd)))//获得picture control 句柄
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(m_pEncoder->Start()))//开始编解码
{
RELEASE_PTR;
return FALSE;
}
if (FAILED(m_pPreview->Start(m_lCookie)))//开始预览播放
{
RELEASE_PTR;
return FALSE;
}
//IWMEncProfileCollection* pProColl = NULL;
RELEASE_PTR;
return TRUE;
}
BOOL CmsdntestDlg::creatprofile(IWMEncProfile2** pPro2)
{
IWMEncAudienceObj* pAudnc = NULL;
BOOL isOk = TRUE;
//以下各个参数代表什么,可以查看windows media encoder SDk帮助文档,有详细介绍
// Initialize the COM library and retrieve a pointer to an IWMEncProfile2 interface.
if (FAILED(CoCreateInstance(CLSID_WMEncProfile2,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWMEncProfile2,
(void**)pPro2)))
{
return FALSE;
}
// Verify profile settings immediately as they are set.
if (FAILED((*pPro2)->put_ValidateMode(VARIANT_TRUE)))
{
return FALSE;
}
// Provide a name and description.
if (FAILED((*pPro2)->put_ProfileName(CComBSTR("Sample MBR Profile"))))
{
return FALSE;
}
if (FAILED((*pPro2)->put_ProfileDescription(CComBSTR("A video profile with three audiences"))))
{
return FALSE;
}
// specifies the type of content streams that the current profile supports
if (FAILED((*pPro2)->put_ContentType(17)))//每个数字代表不一样文件格式,具体查看Wmencoder SDk帮助文档
{
return FALSE;
}
// Specify constant bit rate (CBR) mode.
if (FAILED((*pPro2)->put_VBRMode(WMENC_VIDEO, 0, WMENC_PVM_UNCONSTRAINED)))
{
return FALSE;
}
// Add audiences for 200, 400, and 600 Kbps.
if (FAILED((*pPro2)->AddAudience(5000000, &pAudnc)))
{
return FALSE;
}
if (FAILED(pAudnc->put_VideoCodec(0, 3)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
// Make the video output size match the input size by setting height and width to 0.
if (FAILED(pAudnc->put_VideoHeight(0, 0)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
if (FAILED(pAudnc->put_VideoWidth(0, 0)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
// Change the buffer size to 5 seconds. By default, the end user's default setting is used.
if (FAILED(pAudnc->put_VideoBufferSize(0, 5000)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
//specifies the video codec quality.
if (FAILED((*pPro2)->get_Audience(0, &pAudnc)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
if (FAILED(pAudnc->put_VideoCompressionQuality(0, 80)))//视频压缩比例
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
// Change the video image sharpness for the first audience only.
if (FAILED(pAudnc->put_VideoImageSharpness(0, 70)))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
// Validate the settings to make sure the profile has no errors.
if (FAILED((*pPro2)->Validate()))
{
pAudnc->Release();
pAudnc = NULL;
return FALSE;
}
// Save the profile to a .prx file.
/*if (FAILED((*pPro2)->SaveToFile(CComBSTR("D:\\test.prx"))))
{
printf("profile error:SaveToFile \n");
}*/
// Release pointers.
if (pAudnc)
{
pAudnc->Release();
pAudnc = NULL;
}
return TRUE;
}
void CmsdntestDlg::OnBnClickedButton2()//关闭流媒体按钮
{
// TODO: 在此添加控件通知处理程序代码
if (m_pPreview)
{
m_pPreview->Stop(m_lCookie);
m_pPreview->Release();
m_pPreview = NULL;
}
if (m_pEncoder)
{
m_pEncoder->Stop();
m_pEncoder->Release();
m_pEncoder = NULL;
}
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
CoUninitialize();
}