113E博章

       登录 /注册
首页 一算子网 发布
分类 :c++/vc

流媒体学习笔记--编码视频的预览 C+/VC

[ 2008-7-30 22:35:00 | 发表者 : zihe ]

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

 

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

 

要想显示压缩前的和压缩后的视频流要用到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);

      

 &nbs