[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 942
  • Last Modified:

Record avi with sound

Hi Experts,
I have record a video file(avi) and audio file(wav) as separate files, now I want to combine these into a avi file that can play with video and audio.

Please help me with this.

Thank in advance!
0
CongUan
Asked:
CongUan
  • 5
  • 5
1 Solution
 
mrblueCommented:
You can use graph editor from DirectX SDK and mount DirectShow graph with two input streams - video & audio using AVI Mux filter.
Or you could build own, more sophisticated application based od DirectShow.
Or maybe locate some shareware in Internet.
0
 
CongUanAuthor Commented:
I had not used DirectShow, Please help me for some link or example code about this.

Thanks agian!
0
 
mrblueCommented:
Here sample how to join AVI with WAVE (add strmiids.lib to link list):

You can also start Graph Editor & connect to created graph:
File->Connect to Remote Graph...

// TEST_EE_AVIwSound.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <dshow.h>
#include <comdef.h>
#include <initguid.h>

_COM_SMARTPTR_TYPEDEF(IGraphBuilder, IID_IGraphBuilder);
_COM_SMARTPTR_TYPEDEF(ICaptureGraphBuilder2, IID_ICaptureGraphBuilder2);
_COM_SMARTPTR_TYPEDEF(IMediaControl, IID_IMediaControl);
_COM_SMARTPTR_TYPEDEF(IMediaEvent, IID_IMediaEvent);
_COM_SMARTPTR_TYPEDEF(IBaseFilter, IID_IBaseFilter);
_COM_SMARTPTR_TYPEDEF(IFileSinkFilter2, IID_IFileSinkFilter2);

DEFINE_GUID(CLSID_WAVEParser,
0xD51BD5A1, 0x7548, 0x11CF, 0xA5, 0x20, 0x00, 0x80, 0xC7, 0x7E, 0xF5, 0x8A);


HRESULT AddToRot(IUnknownPtr pUnkGraph, DWORD *pdwRegister)
{
    IMonikerPtr pMoniker;
    IRunningObjectTablePtr pROT;

    if(FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL;

    WCHAR wsz[256];
    wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
    HRESULT hRes = CreateItemMoniker(L"!", wsz, &pMoniker);

    if(SUCCEEDED(hRes)) {
        hRes = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister);
    }

    return hRes;
}

void RemoveFromRot(DWORD pdwRegister)
{
    IRunningObjectTablePtr pROT;

    if(SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
        pROT->Revoke(pdwRegister);
    };
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
      HRESULT hRes;

       hRes = CoInitialize(NULL);

      if(SUCCEEDED(hRes)) {
            IGraphBuilderPtr pGraph;

            hRes = pGraph.CreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);

            if(SUCCEEDED(hRes)) {
                  DWORD dwRegister;
                  ICaptureGraphBuilder2Ptr pICaptureGraphBuilder2;

                  hRes = AddToRot(pGraph, &dwRegister);

                  hRes = pICaptureGraphBuilder2.CreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER);

                  if(SUCCEEDED(hRes)) {
                        IMediaControlPtr pControl;
                        IMediaEventPtr pEvent;
                        IBaseFilterPtr pAVISource, pWAVESource, pAVISplitter, pWAVEParser, pAVIMux, pFileWriter;
                        IFileSinkFilter2Ptr pIFileSinkFilter2;

                        pICaptureGraphBuilder2->SetFiltergraph(pGraph);
                        hRes = pGraph.QueryInterface(IID_IMediaControl, &pControl);
                        hRes = pGraph.QueryInterface(IID_IMediaEvent, &pEvent);

                        hRes = pGraph->AddSourceFilter(L"C:\\DXSDK9\\Samples\\Media\\highway.avi", L"AVI File", &pAVISource);
                        hRes = pGraph->AddSourceFilter(L"C:\\DXSDK9\\Samples\\Media\\audiopath3.wav", L"WAVE File", &pWAVESource);

                        hRes = pAVISplitter.CreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER);
                        hRes = pGraph->AddFilter(pAVISplitter, L"AVI Splitter");

                        hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVISource, NULL, pAVISplitter);

                        hRes = pWAVEParser.CreateInstance(CLSID_WAVEParser, NULL, CLSCTX_INPROC_SERVER);
                        hRes = pGraph->AddFilter(pWAVEParser, L"WAVE Parser");

                        hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pWAVESource, NULL, pWAVEParser);

                        hRes = pAVIMux.CreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC_SERVER);
                        hRes = pGraph->AddFilter(pAVIMux, L"AVI Mux");

                        hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVISplitter, NULL, pAVIMux);
                        hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pWAVEParser, NULL, pAVIMux);

                        hRes = pFileWriter.CreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER);
                        hRes = pGraph->AddFilter(pFileWriter, L"File Writer");

                        hRes = pFileWriter.QueryInterface(IID_IFileSinkFilter2, &pIFileSinkFilter2);
                        hRes = pIFileSinkFilter2->SetFileName(L"c:\\result.avi", NULL);

                        hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVIMux, NULL, pFileWriter);

                        hRes = MessageBox(NULL, TEXT("Test"), TEXT("Check #1"), MB_OK);

                        hRes = pControl->Run();

                        long evCode = 0;
                        pEvent->WaitForCompletion(INFINITE, &evCode);
                  };


                  RemoveFromRot(dwRegister);
            };

            CoUninitialize();
      };

      return 0;
}





0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
CongUanAuthor Commented:
I tested this, it work but the sound some time interrupted (not the same original sound)
Do you have any suggestion for this?

For more question, if the lenght of wav file is not the same the length of AVIs file (for example: wav: 24s AVis: 25s)then what happent with final avi file?

Many thank again!
0
 
CongUanAuthor Commented:
Hi mrblue,
How can I set the param with my source file with the follow comment

Instead of harding-code as L"C:\\DXSDK9\\Samples\\Media\\highway.avi" I want to send my param source file to this,
so, How can I do this, I used WCHAR* but it is not work.

I want to write a function as AddWavToAVI(const WCHAR* wavFile, const WCHAR* aviFile, const WCHAR* rsAVIFile)
But when I used
hRes = pGraph->AddSourceFilter(aviFile, L"AVI File", &pAVISource);
hRes = pGraph->AddSourceFilter(wavFile, L"WAVE File", &pWAVESource);
and
hRes = pIFileSinkFilter2->SetFileName(rsAVIFile, NULL);

I don't see any result for this, it seem to can not write.

Please give me more suggestion

Tx,
0
 
mrblueCommented:
"I tested this, it work but the sound some time interrupted (not the same original sound)
Do you have any suggestion for this?"

Try this (add pointed code):

_COM_SMARTPTR_TYPEDEF(IFileSinkFilter2, IID_IFileSinkFilter2);
_COM_SMARTPTR_TYPEDEF(IConfigAviMux, IID_IConfigAviMux);    // <---

IFileSinkFilter2Ptr pIFileSinkFilter2;
IConfigAviMuxPtr pIConfigAviMux;        // <---

hRes = pAVIMux.CreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC_SERVER);
hRes = pGraph->AddFilter(pAVIMux, L"AVI Mux");

"For more question, if the lenght of wav file is not the same the length of AVIs file (for example: wav: 24s AVis: 25s)then what happent with final avi file?"

If I remember well:
1.If video is longer the rest of movie will be without sound
2.If sound is longer the last frame will be "repeated" (actually shown longer)


hRes = pAVIMux.QueryInterface(IID_IConfigAviMux, &pIConfigAviMux); // <---
hRes = pIConfigAviMux->SetMasterStream(1);  // <---

It simply selects master (more important) stream for synchronization.

In your case it should be:
-1 - none is master
0 - video
1 - sound

From Doc:
"It is recomended to use the audio stream as the master stream, because minor adjustment to the video playback rate are less noticable than changes to the audio playback rate"


0
 
mrblueCommented:
I have used literally the following code and it works:

============
#include "stdafx.h"
#include <dshow.h>
#include <comdef.h>
#include <initguid.h>

_COM_SMARTPTR_TYPEDEF(IGraphBuilder, IID_IGraphBuilder);
_COM_SMARTPTR_TYPEDEF(ICaptureGraphBuilder2, IID_ICaptureGraphBuilder2);
_COM_SMARTPTR_TYPEDEF(IMediaControl, IID_IMediaControl);
_COM_SMARTPTR_TYPEDEF(IMediaEvent, IID_IMediaEvent);
_COM_SMARTPTR_TYPEDEF(IBaseFilter, IID_IBaseFilter);
_COM_SMARTPTR_TYPEDEF(IFileSinkFilter2, IID_IFileSinkFilter2);
_COM_SMARTPTR_TYPEDEF(IConfigAviMux, IID_IConfigAviMux);

DEFINE_GUID(CLSID_WAVEParser,
0xD51BD5A1, 0x7548, 0x11CF, 0xA5, 0x20, 0x00, 0x80, 0xC7, 0x7E, 0xF5, 0x8A);


HRESULT AddToRot(IUnknownPtr pUnkGraph, DWORD *pdwRegister)
{
    IMonikerPtr pMoniker;
    IRunningObjectTablePtr pROT;

    if(FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL;

    WCHAR wsz[256];
    wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
    HRESULT hRes = CreateItemMoniker(L"!", wsz, &pMoniker);

    if(SUCCEEDED(hRes)) {
        hRes = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister);
    }

    return hRes;
}

void RemoveFromRot(DWORD pdwRegister)
{
    IRunningObjectTablePtr pROT;

    if(SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
        pROT->Revoke(pdwRegister);
    };
}

VOID AddWavToAVI(const WCHAR *wavFile, const WCHAR *aviFile, const WCHAR *rsAVIFile)
{
      HRESULT hRes;
      IGraphBuilderPtr pGraph;

      hRes = pGraph.CreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);

      if(SUCCEEDED(hRes)) {
            DWORD dwRegister;
            ICaptureGraphBuilder2Ptr pICaptureGraphBuilder2;

            hRes = AddToRot(pGraph, &dwRegister);

            hRes = pICaptureGraphBuilder2.CreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER);

            if(SUCCEEDED(hRes)) {
                  IMediaControlPtr pControl;
                  IMediaEventPtr pEvent;
                  IBaseFilterPtr pAVISource, pWAVESource, pAVISplitter, pWAVEParser, pAVIMux, pFileWriter;
                  IFileSinkFilter2Ptr pIFileSinkFilter2;
                  IConfigAviMuxPtr pIConfigAviMux;

                  pICaptureGraphBuilder2->SetFiltergraph(pGraph);
                  hRes = pGraph.QueryInterface(IID_IMediaControl, &pControl);
                  hRes = pGraph.QueryInterface(IID_IMediaEvent, &pEvent);

                  hRes = pGraph->AddSourceFilter(aviFile, L"AVI File", &pAVISource);
                  hRes = pGraph->AddSourceFilter(wavFile, L"WAVE File", &pWAVESource);

                  hRes = pAVISplitter.CreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER);
                  hRes = pGraph->AddFilter(pAVISplitter, L"AVI Splitter");

                  hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVISource, NULL, pAVISplitter);

                  hRes = pWAVEParser.CreateInstance(CLSID_WAVEParser, NULL, CLSCTX_INPROC_SERVER);
                  hRes = pGraph->AddFilter(pWAVEParser, L"WAVE Parser");

                  hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pWAVESource, NULL, pWAVEParser);

                  hRes = pAVIMux.CreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC_SERVER);
                  hRes = pGraph->AddFilter(pAVIMux, L"AVI Mux");


                  hRes = pAVIMux.QueryInterface(IID_IConfigAviMux, &pIConfigAviMux);
                  hRes = pIConfigAviMux->SetMasterStream(1);


                  hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVISplitter, NULL, pAVIMux);
                  hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pWAVEParser, NULL, pAVIMux);

                  hRes = pFileWriter.CreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER);
                  hRes = pGraph->AddFilter(pFileWriter, L"File Writer");

                  hRes = pFileWriter.QueryInterface(IID_IFileSinkFilter2, &pIFileSinkFilter2);
                  hRes = pIFileSinkFilter2->SetFileName(rsAVIFile, NULL);

                  hRes = pICaptureGraphBuilder2->RenderStream(NULL, NULL, pAVIMux, NULL, pFileWriter);

                  hRes = MessageBox(NULL, TEXT("Test"), TEXT("Check #1"), MB_OK);

                  hRes = pControl->Run();

                  long evCode = 0;
                  pEvent->WaitForCompletion(INFINITE, &evCode);
            };

            RemoveFromRot(dwRegister);
      };
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
      HRESULT hRes;

       hRes = CoInitialize(NULL);

      if(SUCCEEDED(hRes)) {
            AddWavToAVI(L"C:\\DXSDK9\\Samples\\Media\\audiopath3.wav", L"C:\\DXSDK9\\Samples\\Media\\highway.avi", L"c:\\result.avi");
            CoUninitialize();
      };

      return 0;
}
0
 
CongUanAuthor Commented:
Thank you very much for your help.
I resolved my problem.
AddWavToAVI(L"C:\\DXSDK9\\Samples\\Media\\audiopath3.wav", L"C:\\DXSDK9\\Samples\\Media\\highway.avi", L"c:\\result.avi");
This is still a hard-code, I try to write a function to convert a char* to WCHAR*
It work now.

Thank you again.

0
 
mrblueCommented:
You can use:
MultiByteToWideChar()
WideCharToMultuByte()

In MFC there are even macros that use these functions

W2T() ot T2W()


0
 
CongUanAuthor Commented:
Yah, Many thank again, I used this with im my code before!

0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now