现在的位置: 首页 > 综合 > 正文

流媒体学习笔记———编码视频的预览

2013年10月21日 ⁄ 综合 ⁄ 共 8276字 ⁄ 字号 评论关闭

这篇文章是对以前写过的《显示压缩前的和压缩后的视频》的补充和完善

 

《显示压缩前的和压缩后的视频》原文如下:

 

要想显示压缩前的和压缩后的视频流要用到IWMEncDataView 接口。要使用IWMEncDataViewCollection::Add方法增加一个IWMEncDataView 接口。

显示编码前的窗口

代码如下://一些基本设定省略。

IWMEncDataView* pPreview;

IWMEncDataViewCollection* pPreviewColl;

hr = CoCreateInstance( CLSID_WMEncPreview,

                           NULL,

                           CLSCTX_INPROC_SERVER,

                           IID_IWMEncDataView,

                           (void**)&pPreview);

// Retrieve the preview collection.

hr = pVidSrc->get_PreviewCollection( &pPreviewColl );

long lCookie = -1;//设定为-1,则编码则自动给你加一个唯一的cookie。

hr = pPreviewColl->Add( pPreview, &lCookie);

HWND hWnd;//一个窗口句柄,如果没有设定,则会自动调用一个系统的窗口。

hr = pPreview->SetViewSetting((DWORD) lCookie,                               sizeof(hWnd), 

                              (BYTE*)&hWnd);

hr = pEncoder->Start();

// Start viewing the stream in a pop-up window.

hr = pPreview->Start(lCookie); //开始编码后,显示窗口。

 

显示编码后的窗口

IWMEncDataView* pPostview;

IWMEncDataViewCollection* pPostviewColl;

hr = CoCreateInstance( CLSID_WMEncPreview,

                           NULL,

                           CLSCTX_INPROC_SERVER,

                           IID_IWMEncDataView,

                           (void**)&pPostview);

// Retrieve the preview collection.

hr = pVidSrc->get_PostviewCollection( &pPostviewColl );

long lCookie = -1;//设定为-1,则编码则自动给你加一个唯一的cookie。

hr = pPostviewColl->Add( pPostview, &lCookie);

HWND hWnd;//一个窗口句柄,如果没有设定,则会自动调用一个系统的窗口。

hr = pPostview->SetViewSetting((DWORD) lCookie,                               sizeof(hWnd), 

                              (BYTE*)&hWnd);

hr = pEncoder->Start();

// Start viewing the stream in a pop-up window.

hr = pPostview->Start(lCookie); //开始编码后,显示窗口。

 

上文只是说明了显示窗口的设置,没有文件输入和格式选择等操作,因此每次都要改源码来控制打开文件、存储路径、编码格式,改进了的程序运行界面如下:


 

其中的两个文件路径分别用Cstring m_path,  m_path1

浏览按钮的实现分别如下:

CFileDialog file(true);//true为打开一个文件,false为保存一个文件

  file.DoModal();  //响应点击事件

  m_path=file.GetPathName();  //得到文件的完整路径

  this->UpdateData(false);  //更新数据

  GetDlgItem(IDC_SCREEN)  //使屏幕捕获和视频设备的按钮无效,因为已经选择了文件编码。这样会使程序更健壮一些,否则无意中点了这两个按钮会出现意外的错误。

              ->EnableWindow(FALSE);

  GetDlgItem(IDC_DEVICE)

              ->EnableWindow(FALSE);

 

 

CFileDialog file1(false,".wmv",NULL,OFN_HIDEREADONLY,  //保存一个文件,而且以.wmv为扩展名

                     "WMV Files (*.wmv)|*.wmv|");

   file1.DoModal();

   if(m_path1=file1.GetPathName())

         GetDlgItem(IDC_COMBO)

              ->EnableWindow(TRUE);

this->UpdateData(false);

 

其中得到编码格式是通过在窗口初始化的时候加入的,通过CPreviewsDlg::Choice();调用自定义的函数,Choice()函数的具体实现如下:

void CPreviewsDlg::Choice()

{

      

       HRESULT hr;

    IWMEncoder* pEncoder;

    IWMEncProfileCollection* pProColl;

    IWMEncProfile* pPro;

    long lCount;

    int i;

 

// Initialize the COM library and retrieve a pointer

// to an IWMEncoder interface.

 

    hr = CoInitialize(NULL);

    hr = CoCreateInstance(CLSID_WMEncoder,

                          NULL,

                          CLSCTX_INPROC_SERVER,

                          IID_IWMEncoder,

                          (void**) &pEncoder);

 

// Retrieve a pointer to an IWMEncProfileCollection interface.

 

    hr = pEncoder->get_ProfileCollection(&pProColl);

 

// Loop through the profile collection and retrieve a specific

// profile.

       CString str;

       CComBSTR bstrName(L"");

 

    hr = pProColl->get_Count(&lCount);

    for (i=0; i<lCount; i++)

    {

      

        hr = pProColl->Item(i, &pPro);

        hr = pPro->get_Name(&bstrName);

        str=bstrName.Copy();

              m_choice.InsertString(i,str);

    }

       pEncoder->Release();

}

 

并使用CcomboBox类的OnSelchangeCombo()来得到选择编码的格式

void CPreviewsDlg::OnSelchangeCombo()

{

     j=m_choice.GetCurSel();  //把当前的选择赋值给j

     if(j!=100)  //j的初值为100,如果不等于100说明已经选择了格式

        GetDlgItem(IDC_START)  //使开始编码按钮有效

              ->EnableWindow(TRUE);     

}

 

关于屏幕和设备的区别是通过全局变量h来标志的,h=1是屏幕捕获, h=2是从设备得到视频。程序如下:

void CPreviewsDlg::OnScreen()

{

   h=1;

   GetDlgItem(IDC_DEVICE)

              ->EnableWindow(FALSE);

   GetDlgItem(IDC_BROWER)

              ->EnableWindow(FALSE);

}

 

void CPreviewsDlg::OnDevice()

{

   h=2; 

   GetDlgItem(IDC_SCREEN)

              ->EnableWindow(FALSE);

   GetDlgItem(IDC_BROWER)

              ->EnableWindow(FALSE);

}

 

当配置好后,就可以开始编码了,程序如下:

void CPreviewsDlg::OnStart()

{

  

hwnd=::GetDlgItem(this->GetSafeHwnd(),IDC_VIEW);  //得到预览编码前窗口的句柄

phwnd=::GetDlgItem(this->GetSafeHwnd(),IDC_POSTVIEW); //得到预览编码后窗口的句柄

//    g_MyThread->SetParentWnd(hwnd);  //可以去掉

       g_MyThread->PostThreadMessage(WM_START,0,0 );  //给线程发送消息,开始编码

       GetDlgItem(IDC_WATCH)

              ->EnableWindow(TRUE);

    GetDlgItem(IDC_STOP)

              ->EnableWindow(TRUE);

       GetDlgItem(IDC_START)

              ->EnableWindow(FALSE);

  

}

线程中的开始函数如下:

void CMyThread::OnStart( WPARAM wParam, LPARAM lParam)

{

      

    IWMEncSourceGroupCollection* pSrcGrpColl;

    IWMEncSourceGroup* pSrcGrp;

    IWMEncSource* pAudSrc1;

    IWMEncSource* pSrc1;

    IWMEncVideoSource* pVidSrc1;

//     IWMEncDataView* pPreview;

       IWMEncDataViewCollection* pPostviewColl;

    IWMEncDataViewCollection* pPreviewColl;

    IWMEncProfileCollection* pProColl;

       IWMEncSourcePluginInfoManager* pSrcPlugMgr;

    IWMEncPluginInfo* pPlugInfo;

    IWMEncProfile* pPro;

    IWMEncDisplayInfo* pDispInfo;

    IWMEncAttributes* pAttr;

    IWMEncBroadcast* pBrdcast;

    IWMEncFile* pFile;

       WMENC_ENCODER_STATE enumEncoderState;

       CComBSTR bstrResource(L"");

    long lCount;

    short i;

      

       hr = CoInitialize(NULL);

    hr = CoCreateInstance(CLSID_WMEncoder,  //初始化com

              NULL,

              CLSCTX_INPROC_SERVER,

              IID_IWMEncoder,

              (void**) &pEncoder);

      

       // Retrieve a pointer to an IWMEncSourceGroupCollection

       // interface.

      

    hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);

      

       // Add a source group to the collection. named "SG_1"

      

    hr = pSrcGrpColl->Add(L"SG_1", &pSrcGrp);

      

       // Add a video and audio source to the source group.

      

    hr = pSrcGrp->AddSource(WMENC_VIDEO, &pSrc1);

    hr = pSrcGrp->AddSource(WMENC_AUDIO, &pAudSrc1);

      

       // Retrieve a pointer to an IWMEncVideoSource interface.

      

       hr = pSrc1->QueryInterface(IID_IWMEncVideoSource,

              (void**)&pVidSrc1);

      

   if(h==0)  //h=0说明是编码文件

   {

           CComBSTR bstrInFile("");

              bstrInFile.Append(pThread->m_path);  //CStringCComBSTR的转化

              hr = pAudSrc1->SetInput(bstrInFile);

              hr = pVidSrc1->SetInput(bstrInFile);

   }

   else

   {

          hr = pEncoder->get_SourcePluginInfoManager(&pSrcPlugMgr);

          hr = pSrcPlugMgr->Item(0, &pPlugInfo);

          

          hr = pPlugInfo->Item(1, &bstrResource);   //设置声音的输入

       CComBSTR Aud(L"DEVICE://");

          Aud.Append(bstrResource);

          hr=pAudSrc1->SetInput(Aud);

          if(h==1)

                 hr=pVidSrc1->SetInput(L"ScreenCap://Screen Capture");  //如果h=1,视频来源为屏幕

          else

          {

                   hr = pSrcPlugMgr->Item(1, &pPlugInfo);

               hr = pPlugInfo->Item(1, &bstrResource);

            CComBSTR Vid(L"DEVICE://");    //得到视频设备的输入

               Vid.Append(bstrResource);

               hr=pVidSrc1->SetInput(Vid);

  

         }

   }

 

              // Choose a profile from the collection.

             

              CComBSTR bstrName = NULL;

              CComVariant varProfile;

              varProfile.vt = VT_DISPATCH;

              hr = pEncoder->get_ProfileCollection(&pProColl);

              hr = pProColl->get_Count(&lCount);

              for (i=0; i<lCount; i++)

              {

                     hr = pProColl->Item(i, &pPro);

                     hr = pPro->get_Name(&bstrName);

                     if(i==j)    //选择编码格式

                     {

                            // Set the profile in the source group.

                            varProfile.pdispVal = pPro;

                            hr = pSrcGrp->put_Profile(varProfile);

                            break;

                     }

              }

             

              // Retrieve a pointer to an IWMEncDisplayInfo interface.

             

              hr = pEncoder->get_DisplayInfo(&pDispInfo);

             

              // Describe the encoded content.

             

              CComBSTR bstrAuthor("Let5fly");

              CComBSTR bstrCopyright("Copyright 2000. All rights reserved.");

              CComBSTR bstrDescription("Description of the encoded content.");

              CComBSTR bstrRating("Content rating.");

              CComBSTR bstrTitle("Test the Encoder");

             

              hr = pDispInfo->put_Author(bstrAuthor);         //描述信息

              hr = pDispInfo->put_Copyright(bstrCopyright);

              hr = pDispInfo->put_Description(bstrDescription);

              hr = pDispInfo->put_Rating(bstrRating);

              hr = pDispInfo->put_Title(bstrTitle);

             

              // Retrieve a pointer to an IWMEncAttributes interface.

             

              hr = pEncoder->get_Attributes(&pAttr);<

抱歉!评论已关闭.