【问题标题】:Convert AVI file to WMV in C++ DirectShow; GraphEdit and source code在 C++ DirectShow 中将 AVI 文件转换为 WMV; GraphEdit 和源代码
【发布时间】:2018-09-14 06:51:06
【问题描述】:

我想制作一个工具来获取 AVI 文件作为输入并将其转换为 WMV 文件并将其保存在我的硬盘上。 正如您在 GraphEdit 中看到的那样,我成功地做到了

我开始为同一任务制作 COM C++ 代码以产生相同的效果,但我不知道问题可能出在哪里,导致我无法获得最终转换的文件。 这是我写的代码(有很多内存泄漏)。 我检查了所有返回值,都OKAY,所以调用没有错误。

#include <dshow.h>
#pragma comment(lib,"Strmiids.lib") 
#define AVI_FILE_PATH L"C:\\...\\Desktop\\oo.avi"
#define WMV_FILE_PATH L"C:\\...\\Desktop\\BRGMovie.wmv"

int main() {
    IGraphBuilder* pGraph             = NULL;
    IBaseFilter*   pSource            = NULL;
    IBaseFilter*   pAviSplitter       = NULL;
    IBaseFilter*   pMjpegDecompressor = NULL;
    IBaseFilter*   pSmartTee          = NULL;
    IBaseFilter*   pAviMux            = NULL;
    IBaseFilter*   pFileWriter        = NULL;
    ICaptureGraphBuilder2* pBuild     = NULL;
    IFileSourceFilter*  FileSource    = NULL;

    CoInitialize(NULL);
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph            );
    CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pSource           );
    CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pAviSplitter      );
    CoCreateInstance(CLSID_MjpegDec,    NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pMjpegDecompressor);
    CoCreateInstance(CLSID_SmartTee,    NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pSmartTee         );
    CoCreateInstance(CLSID_AviDest,     NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pAviMux           );
    CoCreateInstance(CLSID_FileWriter,  NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter,   (void**)&pFileWriter       );
    CoCreateInstance(CLSID_FileSource,  NULL, CLSCTX_INPROC_SERVER, IID_IFileSourceFilter, (void**)&FileSource);
    CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);

    pGraph->AddFilter(pSource,            NULL);
    pGraph->AddFilter(pAviSplitter,       NULL);
    pGraph->AddFilter(pMjpegDecompressor, NULL);
    pGraph->AddFilter(pSmartTee,          NULL);
    pGraph->AddFilter(pAviMux,            NULL);
    pGraph->AddFilter(pFileWriter,        NULL);

    pSource->QueryInterface(IID_IFileSourceFilter, (void**)&FileSource);
    FileSource->Load(AVI_FILE_PATH, NULL);

    pBuild->SetOutputFileName(&MEDIASUBTYPE_Asf, WMV_FILE_PATH, &pAviMux, NULL);
    pBuild->RenderStream(NULL, &MEDIATYPE_Video, pSource, 0, pAviMux);

    IEnumPins*  EnumPins = NULL;
    IPin*       OutPin   = NULL;
    IPin*       InPin    = NULL;
    ULONG       fetched  = NULL;
    PIN_INFO    pinfo;

    // find source output
    pSource->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    EnumPins->Release();

    // find AviSplitter input
    pAviSplitter->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    InPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();       
    pGraph->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find AviSplitter upper output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();

    EnumPins->Skip(1);
    EnumPins->Release();

    // find MjpegDecompressor input
    pMjpegDecompressor->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);    

    pGraph->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find MjpegDecompressor output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();
    EnumPins->Release();

    // find SmartTee input
    pSmartTee->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);

    pGraph->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find SmartTee output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();

    EnumPins->Skip(1);

    // find AVIMux input
    pAviMux->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);

    pGraph->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    EnumPins->Skip(1);

    // find AVIMux output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();   

    // find FileWriter input
    pFileWriter->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    EnumPins->Release();
    pGraph->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();
    FileSource->Release();
    CoUninitialize();
    return 0;
}

已编辑:

int main() {
    IGraphBuilder* pGraph = NULL;
    IBaseFilter*   pASFWriter = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;
    ICaptureGraphBuilder2* pBuild = NULL;

    HRESULT hr = CoInitialize(NULL);
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
    hr = CoCreateInstance(CLSID_WMAsfWriter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pASFWriter);
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Asf, WMV_FILE_PATH, &pASFWriter, NULL);
    hr = pGraph->RenderFile(AVI_FILE_PATH, NULL);
    hr = pControl->Run();
    long evCode;
    pEvent->WaitForCompletion(INFINITE, &evCode);

}

【问题讨论】:

    标签: c++ video com directshow


    【解决方案1】:

    提供的过滤器图不会生成 WMV(也称为 ASF)文件。相反,您正在尝试创建扩展名为 .WMV 的 AVI 文件(您正在使用 AVI Mux!)。

    第二个问题是 Smart Tee 过滤器的使用,它不应该在这样的转码图中使用。 Smart Tee 有自己的(并记录在案的)名称。

    要生成 WMV 文件,您需要将 MJPEG 解码器输出连接到 WM ASF Writer Filter 实例的输入。需要配置过滤器并附加配置文件。

    如需了解更多信息,请参阅Creating ASF Files in DirectShow

    另外from MSDN就你的问题:

    【讨论】:

    • 非常感谢您的有用评论。我尝试使用 MSDN 网站上的图表。 link 中有这种方法,他们说最简单的方法是将 WM ASF Writer 添加到过滤器图中,然后使用 IGraphBuilder::RenderFile 方法自动构建图。之后我尝试编写此代码,但仍然无法正常工作。
    • 新代码在上面的编辑部分。在同一 MSDN 链接中也有手动方法,但首先,我想遵循将 AVI 转换为 WMV 的自动方法。如果我需要手动配置 ASF Writer,它没有提示自动方法,请您给我一些小的编码提示如何做?
    • 而不是 SetOutputFileNameRenderFile 我建议使用 CoCreateInstance + AddFilter + IPin.Connect 调用来准确地构建图形并进行精细控制。此外,您需要在连接过滤器引脚之前设置 WM ASF Writer 配置文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多