Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Graphics
  4. DirectShow - Analyze audio stream from AVI - as fast as possible

DirectShow - Analyze audio stream from AVI - as fast as possible

Scheduled Pinned Locked Moved Graphics
helpdata-structuresannouncement
8 Posts 2 Posters 12 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Claudiu Bucur
    wrote on last edited by
    #1

    I need to create audio peaks for the audio stream from an AVI. For this I intend to use DirectShow by using SampleGrabber. I adapted some of the samples from the SDK. There is only one problem here: I receive the audio samples in real-time (i.e. the same as I would be playing the file), but I need this process to be much faster. I was advised to set the graph SyncSource to NULL and by this the samples will be processed as quickly as possible. Unfortunatelly I get no effect by doing this. I'm attaching here the code I'm using, perhaps I'm doing something wrong and somebody can help me out Thanks alot !

    #include
    #include
    #include
    #include
    #include

    int GrabBitmaps(TCHAR * szFile);
    HRESULT GetPin(IBaseFilter * pFilter, PIN_DIRECTION dirrequired, int iNum, IPin **ppPin);
    IPin * GetInPin ( IBaseFilter *pFilter, int Num );
    IPin * GetOutPin( IBaseFilter *pFilter, int Num );

    class CSampleGrabberCB : public ISampleGrabberCB {

    public:

    STDMETHODIMP\_(ULONG) AddRef() { return 2; }
    STDMETHODIMP\_(ULONG) Release() { return 1; }
    STDMETHODIMP QueryInterface(REFIID riid, void \*\* ppv) {
    	CheckPointer(ppv,E\_POINTER);
    	if( riid == IID\_ISampleGrabberCB || riid == IID\_IUnknown )  {
    		\*ppv = (void \*) static\_cast ( this );
    		return NOERROR;
    	}
    	return E\_NOINTERFACE;
    }
    
    STDMETHODIMP SampleCB( double SampleTime, IMediaSample \* pSample ) {return 0;}
    
    STDMETHODIMP BufferCB( double SampleTime, BYTE \* pBuffer, long BufferSize ) {
    	\_tprintf(TEXT("Found a sample at %f s\\t\[%ld\]\\r\\n"), SampleTime , BufferSize );
    	return 0;
    }
    

    }

    int _tmain(int argc, TCHAR* argv[]) {
    if( argc != 2 || !argv || !argv[1] ) {
    _tprintf( TEXT("GrabBitmaps: You must specify a media filename!\r\n") );
    _tprintf( TEXT("Usage: GrabBitmaps Filename\r\n"));
    return 0;
    }

    CoInitializeEx(NULL, COINIT\_APARTMENTTHREADED);
    
    // Read the filename from the command line      
    TCHAR szFile\[MAX\_PATH\];
    \_tcsncpy(szFile, argv\[1\], MAX\_PATH-1);
    szFile\[MAX\_PATH-1\] = 0;      // Null-terminate
    
    int nSuccess = GrabBitmaps(szFile);
    CoUninitialize();
    return nSuccess;
    

    }

    int GrabBitmaps(TCHAR * szFile ) {
    USES_CONVERSION;
    CComPtr< ISampleGrabber > pGrabber;
    CComPtr< IBaseFilter > pSource;
    CComPtr< IGraphBuilder > pGraph;
    CComPtr< IVideoWindow > pVideoWindow;
    HRESULT hr;

    if (!szFile) return -1;
    \_tprintf(TEXT("Grabbing bitmaps from %s.\\r\\n"), szFile);
    
    // Create the sample grabber
    pGrabber.CoCreateI
    
    M 1 Reply Last reply
    0
    • C Claudiu Bucur

      I need to create audio peaks for the audio stream from an AVI. For this I intend to use DirectShow by using SampleGrabber. I adapted some of the samples from the SDK. There is only one problem here: I receive the audio samples in real-time (i.e. the same as I would be playing the file), but I need this process to be much faster. I was advised to set the graph SyncSource to NULL and by this the samples will be processed as quickly as possible. Unfortunatelly I get no effect by doing this. I'm attaching here the code I'm using, perhaps I'm doing something wrong and somebody can help me out Thanks alot !

      #include
      #include
      #include
      #include
      #include

      int GrabBitmaps(TCHAR * szFile);
      HRESULT GetPin(IBaseFilter * pFilter, PIN_DIRECTION dirrequired, int iNum, IPin **ppPin);
      IPin * GetInPin ( IBaseFilter *pFilter, int Num );
      IPin * GetOutPin( IBaseFilter *pFilter, int Num );

      class CSampleGrabberCB : public ISampleGrabberCB {

      public:

      STDMETHODIMP\_(ULONG) AddRef() { return 2; }
      STDMETHODIMP\_(ULONG) Release() { return 1; }
      STDMETHODIMP QueryInterface(REFIID riid, void \*\* ppv) {
      	CheckPointer(ppv,E\_POINTER);
      	if( riid == IID\_ISampleGrabberCB || riid == IID\_IUnknown )  {
      		\*ppv = (void \*) static\_cast ( this );
      		return NOERROR;
      	}
      	return E\_NOINTERFACE;
      }
      
      STDMETHODIMP SampleCB( double SampleTime, IMediaSample \* pSample ) {return 0;}
      
      STDMETHODIMP BufferCB( double SampleTime, BYTE \* pBuffer, long BufferSize ) {
      	\_tprintf(TEXT("Found a sample at %f s\\t\[%ld\]\\r\\n"), SampleTime , BufferSize );
      	return 0;
      }
      

      }

      int _tmain(int argc, TCHAR* argv[]) {
      if( argc != 2 || !argv || !argv[1] ) {
      _tprintf( TEXT("GrabBitmaps: You must specify a media filename!\r\n") );
      _tprintf( TEXT("Usage: GrabBitmaps Filename\r\n"));
      return 0;
      }

      CoInitializeEx(NULL, COINIT\_APARTMENTTHREADED);
      
      // Read the filename from the command line      
      TCHAR szFile\[MAX\_PATH\];
      \_tcsncpy(szFile, argv\[1\], MAX\_PATH-1);
      szFile\[MAX\_PATH-1\] = 0;      // Null-terminate
      
      int nSuccess = GrabBitmaps(szFile);
      CoUninitialize();
      return nSuccess;
      

      }

      int GrabBitmaps(TCHAR * szFile ) {
      USES_CONVERSION;
      CComPtr< ISampleGrabber > pGrabber;
      CComPtr< IBaseFilter > pSource;
      CComPtr< IGraphBuilder > pGraph;
      CComPtr< IVideoWindow > pVideoWindow;
      HRESULT hr;

      if (!szFile) return -1;
      \_tprintf(TEXT("Grabbing bitmaps from %s.\\r\\n"), szFile);
      
      // Create the sample grabber
      pGrabber.CoCreateI
      
      M Offline
      M Offline
      Mark Salsbery
      wrote on last edited by
      #2

      What do you need to do with the output - does it need to be rendered? Is there a video stream as well as the audio stream? Mark

      "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

      C 1 Reply Last reply
      0
      • M Mark Salsbery

        What do you need to do with the output - does it need to be rendered? Is there a video stream as well as the audio stream? Mark

        "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

        C Offline
        C Offline
        Claudiu Bucur
        wrote on last edited by
        #3

        I don't need to render the output, I just need to analyze it and write the results to another file. Yes, the input media file contains video as well as audio. Claudiu

        M 1 Reply Last reply
        0
        • C Claudiu Bucur

          I don't need to render the output, I just need to analyze it and write the results to another file. Yes, the input media file contains video as well as audio. Claudiu

          M Offline
          M Offline
          Mark Salsbery
          wrote on last edited by
          #4

          By using pGraph->Render(), you're getting the default renderers, right? In your current code, does the audio play when you run the graph? I'm thinking if you use the NULL Renderer filter on the outputs of the grabber and the AVI Splitter (instead of the default renderers) then maybe the graph will run as fast as possible with the sync source set to NULL. I thought the audio renderer was determining the flow rate of samples through the graph, which is why setting the sync source to NULL has no effect. If the AVI splitter is pushing samples at the real-time rate, then you'd probably need a custom grabber filter. Mark

          "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

          C 2 Replies Last reply
          0
          • M Mark Salsbery

            By using pGraph->Render(), you're getting the default renderers, right? In your current code, does the audio play when you run the graph? I'm thinking if you use the NULL Renderer filter on the outputs of the grabber and the AVI Splitter (instead of the default renderers) then maybe the graph will run as fast as possible with the sync source set to NULL. I thought the audio renderer was determining the flow rate of samples through the graph, which is why setting the sync source to NULL has no effect. If the AVI splitter is pushing samples at the real-time rate, then you'd probably need a custom grabber filter. Mark

            "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

            C Offline
            C Offline
            Claudiu Bucur
            wrote on last edited by
            #5

            Exactly, the audio gets played when I run the graph. Can you please show me where to insert those filters in the graph? To make a test and see if it's working ? Claudiu

            M 1 Reply Last reply
            0
            • C Claudiu Bucur

              Exactly, the audio gets played when I run the graph. Can you please show me where to insert those filters in the graph? To make a test and see if it's working ? Claudiu

              M Offline
              M Offline
              Mark Salsbery
              wrote on last edited by
              #6

              After you connect the source filter to the grabber filter, there will be some splitter filter(s) inserted in between by the graph builder. To get an idea of exactly which filter(s) are inserted use GRAPHEDIT.EXE - Add a file source (async) filter, set it's input filename in the dialog, add a grabber filter, and connect the output of the source to the input of the grabber. You'll then see the inserted filter(s). So after you connect the source filter to the grabber filter, You can traverse the partial graph (as described here[^]) starting from the grabber's input pin. Unless an intermediate decoder filter was needed for the audio stream, the next filter upstream should be a splitter filter (it may be AVI, MPEG-1, or other depending on the file format). It should be the first filter you find that has unconnected output pins (see Find an Unconnected Pin on a Filter[^]). For each of the unconnected output pins, create a NULL renderer filter and connect its input pin to the unconnected output pin. Create another NULL Renderer filter and connect it to the grabber filter's output pin. The graph should be complete at this point. You don't need to call pGraph->Render(). You'll still want to call SetSyncSource on the graph builder's IMediaFilter interface to set the sync source to NULL. Mark

              "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

              1 Reply Last reply
              0
              • M Mark Salsbery

                By using pGraph->Render(), you're getting the default renderers, right? In your current code, does the audio play when you run the graph? I'm thinking if you use the NULL Renderer filter on the outputs of the grabber and the AVI Splitter (instead of the default renderers) then maybe the graph will run as fast as possible with the sync source set to NULL. I thought the audio renderer was determining the flow rate of samples through the graph, which is why setting the sync source to NULL has no effect. If the AVI splitter is pushing samples at the real-time rate, then you'd probably need a custom grabber filter. Mark

                "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

                C Offline
                C Offline
                Claudiu Bucur
                wrote on last edited by
                #7

                I managed to create the NULL Renderer and insert it into the graph and it works ! The samples are received as I would expected. Here's the modifications I made:

                CComPtr nullRenderer;
                hr = nullRenderer.CoCreateInstance(CLSID_NullRenderer);
                hr = pGraph->AddFilter(nullRenderer, L"NULL renderer");

                CComPtr nullGrabInPin = GetInPin(nullRenderer, 0);
                CComPtr pGrabOutPin = GetOutPin(pGrabberBase, 0);
                pGraph->Connect(pGrabOutPin, nullGrabInPin);

                Thanks so much for your help ! Now I have to find somewhere the format of the data received on BufferCB for audio PCM and I'm all done. Claudiu

                M 1 Reply Last reply
                0
                • C Claudiu Bucur

                  I managed to create the NULL Renderer and insert it into the graph and it works ! The samples are received as I would expected. Here's the modifications I made:

                  CComPtr nullRenderer;
                  hr = nullRenderer.CoCreateInstance(CLSID_NullRenderer);
                  hr = pGraph->AddFilter(nullRenderer, L"NULL renderer");

                  CComPtr nullGrabInPin = GetInPin(nullRenderer, 0);
                  CComPtr pGrabOutPin = GetOutPin(pGrabberBase, 0);
                  pGraph->Connect(pGrabOutPin, nullGrabInPin);

                  Thanks so much for your help ! Now I have to find somewhere the format of the data received on BufferCB for audio PCM and I'm all done. Claudiu

                  M Offline
                  M Offline
                  Mark Salsbery
                  wrote on last edited by
                  #8

                  Claudiu Bucur wrote:

                  Now I have to find somewhere the format of the data received on BufferCB for audio PCM

                  Maybe pGrabPin->ConnectionMediaType()

                  "Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups