热门标签 | 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 ??

推荐阅读
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • 本文介绍如何使用线段树解决洛谷 P1531 我讨厌它问题,重点在于单点更新和区间查询最大值。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • Android 自定义 RecycleView 左滑上下分层示例代码
    为了满足项目需求,需要在多个场景中实现左滑删除功能,并且后续可能在列表项中增加其他功能。虽然网络上有很多左滑删除的示例,但大多数封装不够完善。因此,我们尝试自己封装一个更加灵活和通用的解决方案。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 开发日志:高效图片压缩与上传技术解析 ... [详细]
  • 本文详细解析了Autofac在高级应用场景中的具体实现,特别是如何通过注册泛型接口的类来优化依赖注入。示例代码展示了如何使用 `builder.RegisterAssemblyTypes` 方法,结合 `typeof(IEventHandler).Assembly` 和 `Where` 过滤条件,动态注册所有符合条件的类,从而简化配置并提高代码的可维护性。此外,文章还探讨了这一方法在复杂系统中的实际应用及其优势。 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
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社区 版权所有