热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于录制WMV视频时的问题

最近在做个录制WMV格式的音视频的问题,录制完回放的时候,画面不连续,下面是我的源码,肯定有经验的朋友帮帮忙看看哪里出了问题?WMVRecorderDlg.cpp:implement
最近在做个录制WMV格式的音视频的问题,录制完回放的时候,画面不连续,下面是我的源码,肯定有经验的朋友帮帮忙看看哪里出了问题?

// WMVRecorderDlg.cpp : implementation file

BOOL CWMVRecorderDlg::Run()
{
HRESULT hr;
CString s;

IBaseFilter *pWriter = NULL;
    IFileSinkFilter2 *pSink = NULL;
IBaseFilter *pAviDest = NULL;
IConfigAviMux *pAviCfg = NULL;
IBaseFilter *pReader = NULL;
IFileSourceFilter *pSink2 = NULL;

// create the graph
hr = CoCreateInstance( CLSID_FilterGraph,
   NULL,
   CLSCTX_INPROC_SERVER,
   IID_IGraphBuilder,
   (void**)&(pGraph) );

if( FAILED( hr ) )
{
s.Format( "不能生成FilterGraph,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
AfxMessageBox( s );
return FALSE;
}

// add file writer
hr = AddFilterByClsid(pGraph, L"File Writer", CLSID_FileWriter, &pWriter);
if( FAILED( hr ) )
{
s.Format( "不能生成FileWriter,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}


pWriter->QueryInterface(IID_IFileSinkFilter2, (void**)&pSink);
if( pSink != NULL )
{
// pSink->SetFileName( MultiByte2WideChar( m_fname ), NULL );
pSink->SetFileName( MultiByte2WideChar(_T("E:\\dest.wmv"))/*录制后的文件*/, NULL );
// pSink->SetFileName( L"mms://192.168.1.2:9000", NULL );
pSink->SetMode( AM_FILE_OVERWRITE );
SAFE_RELEASE( pSink );
}


// add avi mux 
hr = AddFilterByClsid(pGraph, L"Avi Mux", CLSID_AviDest, &pAviDest);
if( FAILED( hr ) )
{
s.Format( "不能生成AviDest,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}


pAviDest->QueryInterface(IID_IConfigAviMux, (void**)&pAviCfg);
if( pAviCfg != NULL )
{
SAFE_RELEASE( pAviCfg );
}


// connect avi mux to file writer
hr = ConnectTwoFilters( pGraph, pAviDest, pWriter );
if( FAILED( hr ) )
{
s.Format( "连接avi mux到file writer,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

hr = AddFilterByClsid(pGraph, L"Asf Reader1", CLSID_WMAsfReader, &pReader);
if( FAILED( hr ) ) 
{
s.Format( "不能生成流读取filter,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}


hr = pReader->QueryInterface(IID_IFileSourceFilter, (void**)&(pSink2) );
if( FAILED( hr ) ) 
{
s.Format( "无法设定流,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}



//hr = pSink2->Load( MultiByte2WideChar( m_address1 ), NULL );

hr = pSink2->Load(MultiByte2WideChar(_T("E:\\source.wmv"))/*需要录制的源媒体文件*/, NULL );
// hr = pSink2->Load( L"mms://192.168.1.2:9000", NULL );
SAFE_RELEASE( pSink2 );
if( FAILED( hr ) ) 
{
s.Format( "无法设定流参数,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

hr = RenderOutputPins( pGraph, pReader );
if( FAILED( hr ) ) 
{
s.Format( "无法连接流,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

//第二个码流

int bUse2 = GetConfigInt("双码流", "是否采用", 0);
if(bUse2)
{
hr = AddFilterByClsid(pGraph, L"Asf Reader2", CLSID_WMAsfReader, &pReader);
if( FAILED( hr ) ) 
{
s.Format( "不能生成流读取filter,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

hr = pReader->QueryInterface(IID_IFileSourceFilter, (void**)&(pSink2) );
if( FAILED( hr ) ) 
{
s.Format( "无法设定流,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

hr = pSink2->Load( MultiByte2WideChar( m_address2 ), NULL );
SAFE_RELEASE( pSink2 );
if( FAILED( hr ) ) 
{
s.Format( "无法设定流参数,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

hr = RenderOutputPins( pGraph, pReader );
if( FAILED( hr ) ) 
{
s.Format( "无法连接流,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}


}


hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&(pControl) );
if( FAILED( hr ) ) 
{
s.Format( "不能获得视频控制,错误码:%X,说明:%s\n", hr, ErrMsgLib( hr ) );
ERRMSG0( s );
// AfxMessageBox( s );
return FALSE;
}

pControl->Run();
AfxMessageBox(_T("run return"));

return TRUE;
}

4 个解决方案

#1



//      Filename: WmvRec.h
//       Version: 0.0


#ifndef __WMVREC_H
#define __WMVREC_H

char* WideChar2MultiByte( WCHAR* p );
WCHAR* MultiByte2WideChar( const char* p );
IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest);
ULONG EnumAllPins( IBaseFilter* pFilter, IPin* Pins[], ULONG nMaxNumber );
HRESULT ConnectTwoFilters(IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest);
HRESULT AddFilterByClsid(IGraphBuilder *pGraph, LPCWSTR wszName, const GUID& clsid, IBaseFilter **ppF);
ULONG EnumCaptureDeviceName( REFCLSID clsidDeviceClass, CString* pStrArray, ULONG nMaxNumber );
void FindAudioCapture( IBaseFilter** pSrc, const char* name );
ULONG EnumAudioInputName( IBaseFilter* pSrc, CString* pStrArray, ULONG nMaxNumber );
void EnableAudioInput( IBaseFilter* pSrc, const char* strName, bool bEnable );
HRESULT RenderOutputPins(IGraphBuilder *pGB, IBaseFilter *pFilter);

#endif // __WMVREC_H

//   Filename:WmvRec.cpp
//   Version: 0.0
//

#include "stdafx.h"
#include "Report.h"
#include "Config.h"
#include 
#include "Wmsysprf.h"
#include 
#include 
#include "WmvRec.h"

// 将宽字符转换成多字节串,返回静态对象,无需删除,必须立刻使用
char* WideChar2MultiByte( WCHAR* p )
{
static char buffer[ 1024 ];
WideCharToMultiByte( CP_ACP, 0, p, -1, buffer, 1024, NULL, NULL );
return buffer;
}

// 将多字节串转换成宽字符,返回静态对象,无需删除,必须立刻使用
WCHAR* MultiByte2WideChar( const char* p )
{
static WCHAR buffer[ 1024 ];
MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, 1024 );
return buffer;
}

// 取得filter指定方向的第一个pin
IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest)
{
IPin * foundPin = NULL;
if( pFilter != NULL )
{
IEnumPins* pEnum = NULL;
HRESULT hr = pFilter->EnumPins(&pEnum);
if (SUCCEEDED(hr)) 
{
IPin* pPin = NULL;
while (!foundPin && pEnum->Next(1, &pPin, 0) == S_OK) 
{
PIN_DIRECTION dir;
pPin->QueryDirection(&dir);
if (dir == dirRequest) 
{
foundPin = pPin;
}
else
{
pPin->Release();
}
}
pEnum->Release();
}
}
    return foundPin;
}

// 找出filter全部的pin
ULONG EnumAllPins( IBaseFilter* pFilter, IPin* Pins[], ULONG nMaxNumber )
{
ULONG nCount = 0;
if( pFilter != NULL )
{
IEnumPins* pEnum = NULL;
HRESULT hr = pFilter->EnumPins( &pEnum );
if( SUCCEEDED(hr) ) 
{
pEnum->Next( nMaxNumber, Pins, &nCount ); 
pEnum->Release();
}
}
    return nCount;
}

// ConnectTwoFilters: Connects two filters using the first pin on each.
HRESULT ConnectTwoFilters(IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest)
{
    IPin *pOut = GetPin( pSrc, PINDIR_OUTPUT ); 
    if( !pOut ) return E_FAIL;
    IPin *pIn = GetPin( pDest, PINDIR_INPUT );
    if( !pOut ) 
{
        pIn->Release();
        return E_FAIL;
    }
    HRESULT hr = pGraph->ConnectDirect( pOut, pIn, NULL );
    pIn->Release();
    pOut->Release();
    return hr;
}

//  根据指定的CLSID, 把filter加入到graph中并返回filter 
HRESULT AddFilterByClsid(IGraphBuilder *pGraph, LPCWSTR wszName, 
    const GUID& clsid, IBaseFilter **ppF)
{
    *ppF = NULL;
    HRESULT hr = CoCreateInstance( clsid, 
   NULL,
   CLSCTX_INPROC_SERVER,
   IID_IBaseFilter, 
   (void**)ppF );
    if( SUCCEEDED( hr ) )
    {
        hr = pGraph->AddFilter( (*ppF), wszName );
    }
    return hr;
}

ULONG EnumCaptureDeviceName( REFCLSID clsidDeviceClass, CString* pStrArray, ULONG nMaxNumber )
{
HRESULT hr;
ULONG nCount = 0;

// Create the system device enumerator.
ICreateDevEnum *pDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum, 
 NULL, 
 CLSCTX_INPROC, 
 IID_ICreateDevEnum, 
 (void **)&pDevEnum);

// Create an enumerator for video capture devices.
IEnumMoniker *pClassEnum = NULL;
pDevEnum->CreateClassEnumerator( clsidDeviceClass, &pClassEnum, 0 );

ULONG cFetched;
IMoniker *pMoniker = NULL;
while( pClassEnum->Next( 1, &pMoniker, &cFetched ) == S_OK )
{
IPropertyBag *pPropBag;
        pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);

        // To retrieve the friendly name of the filter, do the following:
        VARIANT varName;
        VariantInit(&varName);
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
        if (SUCCEEDED(hr))
        {
if( varName.vt == VT_BSTR )
{
pStrArray[ nCount ++ ] = WideChar2MultiByte( varName.bstrVal );
}
        }
        VariantClear(&varName);

pMoniker->Release();
if( nCount >= nMaxNumber ) break;
}

pClassEnum->Release();
pDevEnum->Release();

return nCount;
}


void  FindAudioCapture( IBaseFilter** pSrc, const char* name )
{
HRESULT hr;
*pSrc = NULL;

// Create the system device enumerator.
ICreateDevEnum *pDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum, 
 NULL, 
 CLSCTX_INPROC, 
 IID_ICreateDevEnum, 
 (void **)&pDevEnum);

// Create an enumerator for video capture devices.
IEnumMoniker *pClassEnum = NULL;
pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pClassEnum, 0);

ULONG cFetched;
IMoniker *pMoniker = NULL;
while( pClassEnum->Next( 1, &pMoniker, &cFetched ) == S_OK )
{
IPropertyBag *pPropBag;
        pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);

        // To retrieve the friendly name of the filter, do the following:
        VARIANT varName;
        VariantInit(&varName);
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
        if (SUCCEEDED(hr))
        {
            // Display the name in your UI somehow.
if( varName.vt == VT_BSTR )
{
if( strcmp( WideChar2MultiByte( varName.bstrVal ), name ) == 0 )
{
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)pSrc);
VariantClear(&varName);
break;
}
}
        }
        VariantClear(&varName);

// Bind the first moniker to a filter object.
pMoniker->Release();
}

pClassEnum->Release();
pDevEnum->Release();
}

ULONG EnumAudioInputName( IBaseFilter* pSrc, CString* pStrArray, ULONG nMaxNumber )
{
HRESULT hr;
ULONG nCount = 0;
if( pSrc != NULL )
{
IEnumPins* pEnum = NULL;
IBaseFilter* pFilter = pSrc;
hr = pFilter->EnumPins(&pEnum);
if (SUCCEEDED(hr)) 
{
IPin* pPin = NULL;
while(pEnum->Next(1, &pPin, 0) == S_OK) 
{
PIN_DIRECTION dir;
pPin->QueryDirection(&dir);
if (dir == PINDIR_INPUT ) 
{
PIN_INFO info;
pPin->QueryPinInfo( &info );
pStrArray[ nCount ++ ] = WideChar2MultiByte( info.achName );
}
pPin->Release();
}
pEnum->Release();
}
}
return nCount;
}

void EnableAudioInput( IBaseFilter* pSrc, const char* strName, bool bEnable )
{
HRESULT hr;
ULONG nCount = 0;
if( pSrc != NULL )
{
IEnumPins* pEnum = NULL;
IBaseFilter* pFilter = pSrc;
hr = pFilter->EnumPins(&pEnum);
if (SUCCEEDED(hr)) 
{
IPin* pPin = NULL;
while(pEnum->Next(1, &pPin, 0) == S_OK) 
{
PIN_DIRECTION dir;
pPin->QueryDirection(&dir);
if (dir == PINDIR_INPUT ) 
{
PIN_INFO info;
pPin->QueryPinInfo( &info );

IAMAudioInputMixer* pPinCfg;
pPin->QueryInterface( IID_IAMAudioInputMixer, (void**)&pPinCfg );

if( strcmp( WideChar2MultiByte( info.achName ), strName ) == 0 )
{
if( pPinCfg )
{
pPinCfg->put_Enable( bEnable );
pPinCfg->Release();
}
}
}
pPin->Release();
}
pEnum->Release();
}
}
}

//------------------------------------------------------------------------------
// Name: RenderOutputPins()
// Desc: Renders every output pin on a specified filter. 
//
// pGB:     Pointer to the Filter Graph Manager.
// pFilter: Pointer to the filter.
//------------------------------------------------------------------------------
HRESULT RenderOutputPins(IGraphBuilder *pGB, IBaseFilter *pFilter)
{
    HRESULT         hr = S_OK;
    IEnumPins *     pEnumPin = NULL;
    IPin *          pConnectedPin = NULL, * pPin;
    PIN_DIRECTION   PinDirection;
    ULONG           ulFetched;

    // Enumerate all the pins on the filter.
    hr = pFilter->EnumPins( &pEnumPin );

    if(SUCCEEDED(hr))
    {
        // Step through every pin, looking for the output pins.
        while (S_OK == (hr = pEnumPin->Next( 1L, &pPin, &ulFetched)))
        {
            // Check whether this pin is already connected. If so, ignore it.
            hr = pPin->ConnectedTo(&pConnectedPin);
            if (pConnectedPin)
            {
                // Release the IPin interface on the connected pin.
                pConnectedPin->Release();
                pConnectedPin = NULL;
            }

            if (VFW_E_NOT_CONNECTED == hr)
            {
                // This pin is not connected to another filter yet. Check 
                // whether it is an output pin. If so, use the Filter Graph
                // Manager's Render() method to render the pin.

                hr = pPin->QueryDirection( &PinDirection );
                if ( ( S_OK == hr ) && ( PinDirection == PINDIR_OUTPUT ) )
                {
                    hr = pGB->Render(pPin);
                }
            }
            pPin->Release();

            // If there was an error, stop enumerating.
            if (FAILED(hr))                      
                break;
        }
    }

    // Release the pin enumerator object.
    pEnumPin->Release();
    return hr;
}

#2


没人指点下么?

#3


该回复于2010-09-07 14:47:37被版主删除

#4


Encoder ??

推荐阅读
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 本文介绍了如何清除Eclipse中SVN用户的设置。首先需要查看使用的SVN接口,然后根据接口类型找到相应的目录并删除相关文件。最后使用SVN更新或提交来应用更改。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • Struts2+Sring+Hibernate简单配置
    2019独角兽企业重金招聘Python工程师标准Struts2SpringHibernate搭建全解!Struts2SpringHibernate是J2EE的最 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • Annotation的大材小用
    为什么80%的码农都做不了架构师?最近在开发一些通用的excel数据导入的功能,由于涉及到导入的模块很多,所以开发了一个比较通用的e ... [详细]
  • ZABBIX 3.0 配置监控NGINX性能【OK】
    1.在agent端查看配置:nginx-V查看编辑时是否加入状态监控模块:--with-http_stub_status_module--with-http_gzip_stat ... [详细]
author-avatar
我和你2602883283
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有