Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » DirectX » Audiosamples mit ISampleGrabberCB

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
18.06.2005, 14:39 Uhr
sonetta



Hallo,

seit einiger Zeit versuche ich audiodaten aus einem avi oder mpeg-videostream herauszubekommen. Ich nutze DirectShow dafür.
Abspielen usw funzt ganz gut, nur das Grabben von AudioSamples aus dem laufenden Video macht mich irre. Ich möchte diese für einen VU-meter nutzen. Zum Grabben nehme ich die Methode BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ) der ISampleGrabber-Klasse. Und ich bekomme auch eine Ausgabe!
Aber: ich bekomme auch Wert ausgegeben, wenn das Video definitiv keinen Ton hat, habs mit GraphEdit überprüft. ( Jetzt bin ich mir schon nicht mehr sicher, ob das, was ich da bekomme, wirklich Audiodaten sind (heul)
Bei der Codemenge ist das wirklich schwer für dritte darzustellen.Versuchs trotzdem mal:

Hier die Klasse mit der Callback-Methode, hier geb ich die Samples auch testweise aus.

C++:
class CFakeCallback : public ISampleGrabberCB
    {
    public:
        BYTE *m_Buffer;
        STDMETHODIMP_(ULONG) AddRef()  { return 2; }
        STDMETHODIMP_(ULONG) Release() { return 1; }

STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
    {
    if (riid == IID_ISampleGrabberCB || riid == IID_IUnknown)
        {
        *ppv = (void *) static_cast<ISampleGrabberCB *>(this);
        return NOERROR;
        }
    return E_NOINTERFACE;
    }

STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
    {
    static long counter = 0;

    return 0;
    }
//Grabben, kopieren in glob. Struktur und Ausgabe
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize )
{
    CString out = _T("");
    CString complete = _T("");
        
    if (!pBuffer)
        return E_POINTER;
    
    if( cbInfo.lBufferSize < lBufferSize )
        {
        delete [] cbInfo.pBuffer;
        cbInfo.pBuffer = NULL;
        cbInfo.lBufferSize = 0;
        }

    cbInfo.dblSampleTime = dblSampleTime;
    
    if (!cbInfo.pBuffer)
        {
        cbInfo.pBuffer = new BYTE[lBufferSize];
        cbInfo.lBufferSize = lBufferSize;
        }
    
    memcpy(cbInfo.pBuffer, pBuffer, cbInfo.lBufferSize);
    
            //liefert immer 1492 oder 19812 Werte
            //Zahlen zwischen 0 und 255, sieht plausibel aus
    for(int n=0; n<cbInfo.lBufferSize; n++)     {
       out.Format("%d",(short)cbInfo.pBuffer[n]);
       AfxMessageBox(out);
    }
    return 0;
}
};

CFakeCallback pCallbackA; //globales Object



Hier die globale Struktur um die Sample-Daten irgendwie in der App weiter zu verarbeiten:

C++:
typedef struct _callbackinfo
    {
    double dblSampleTime;
    long lBufferSize;
    BYTE *pBuffer;
    } CALLBACKINFO;

CALLBACKINFO cbInfo={0};






Die Struktur der DirectShow-Interfaces:

C++:
struct STREAM
{
    IGraphBuilder *GB;    //Rendern
    IMediaControl *MC;    //Play/Stop
    IBasicAudio   *BA;    //Audiointerface
    IMediaSeeking *MS;    //Position
    IVideoWindow *VW;   //Video Window
    IMediaEventEx *ME; //MediaEvent
    IBaseFilter *pGrabberF;
    ISampleGrabber *pGrabber;
};





Die Methode meiner MainFrame-Klasse die das Video lädt, initialisiert usw, wo der mittlere Teil wohl interessant ist:

C++:
STREAM* CMainFrame::Load(CString name) // name = filename des videos
{
    ms = new STREAM; //member-Streamobjekt
    HRESULT hres;
    WCHAR wFile[MAX_PATH];
    RECT rc;
    int width;
    int height;
    MediaDlg = new CDSWindow();
    BOOL ret = MediaDlg->Create(IDD_DIALOG5,this); //Dialogfenster für Video
    ModifyStyle(MediaDlg->GetSafeHwnd(), NULL, WS_THICKFRAME, NULL);
    MultiByteToWideChar(CP_ACP,0,name,-1,wFile,MAX_PATH);

            //Init interfaces and graphs
    hres = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&ms->pGrabberF);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not create the Sample Grabber.");

    hres =ms->pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&ms->pGrabber);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not create ISampleGrabber interface.");

    hres = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&ms->GB);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not create the Filter Graph Manager.");

    hres = ms->GB->AddFilter(ms->pGrabberF, L"Sample Grabber");
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not add Sample Grabber filter to graph.");

    hres = ms->GB->RenderFile(wFile,NULL);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->GB->QueryInterface(IID_IMediaControl,(void **)&ms->MC);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->GB->QueryInterface(IID_IMediaSeeking,(void **)&ms->MS);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->GB->QueryInterface(IID_IBasicAudio,(void **)&ms->BA);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->GB->QueryInterface(IID_IVideoWindow,   (void **)&ms->VW);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->GB->QueryInterface(IID_IMediaEventEx, (void**)&ms->ME);
    if (FAILED(hres))
        AfxMessageBox("ERROR");
    
    hres = ms->pGrabber->SetOneShot(FALSE);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not set one shot for pSampleGrabber.");

    hres = ms->pGrabber->SetBufferSamples(FALSE);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not set buffer samples for pSampleGrabber.");
    
    AM_MEDIA_TYPE smt;
    ZeroMemory(&smt, sizeof(AM_MEDIA_TYPE));
    smt.majortype = MEDIATYPE_Audio;
    smt.formattype = FORMAT_WaveFormatEx;
    smt.subtype = MEDIASUBTYPE_PCM;
    hres = ms->pGrabber->SetMediaType(&smt);

    CComQIPtr< ISampleGrabberCB, &IID_ISampleGrabberCB > pCBa( &pCallbackA );
    hres = ms->pGrabber->SetCallback(pCBa, 1);
    if (FAILED(hres))
        AfxMessageBox("ERROR - Could not set Callback");

    //Fensterstyles und Notity
    ms->VW->put_AutoShow(OAFALSE);
    ms->VW->put_Owner((OAHWND)MediaDlg->GetSafeHwnd());
    ms->VW->put_WindowStyle(WS_CHILD);
    hres=ms->ME->SetNotifyWindow((OAHWND)GetSafeHwnd(), WM_GRAPHNOTIFY, 0);
    if(hres!=S_OK)
        return NULL;

    //Anfangsfenster einpassen
    MediaDlg->GetClientRect(&rc);
    width =  rc.right - rc.left;
    height = rc.bottom - rc.top;
    ms->VW->SetWindowPosition(rc.left, rc.top+50, width, height);
    ms->VW->put_Visible(OATRUE);
    ms->VW->SetWindowForeground(OATRUE);

    //Videodialog anzeigen
    MediaDlg->ShowWindow(SW_SHOW);
    MediaDlg->RedrawWindow(NULL, NULL, RDW_UPDATENOW);
            
             //init sliders
    pSlider2->SetRange( 0, (int)GetEndPos() ); //Seeking
    HWND hWnd = m_DlgBarAuswahl.GetSafeHwnd();
    CWnd *pBar = CWnd::FromHandle(hWnd);
    CProgressCtrl *pProgress = (CProgressCtrl*)pBar->GetDlgItem(IDC_PROGRESS1);
    pProgress->SetRange32( 0, (int)GetEndPos() ); //Progressing
    pProgress1->SetRange( 0, 100 ); //Volume

    return ms;
}



Der Graph wird dann mit Run() in einer anderen Methode gestartet, das Event-Management von Directshow ist auch ausgelagert und funzt einwandfrei.

Sowie einige globale Hilfsmethoden wie GetUnconnectedPin, ConnectFilters, ConnectFilters
MyFreeMediaType, die aber funzen sollten, sonst bekäme ich ja Fehler oder gar keine Ausgabe.

Mir ist klar, dass das nicht unbedingt trivial ist - aber darum bin ich ja hier.
Wenn mir hier keiner helfen kann, geb ichs wohl auf ;((
In netz gibt es ne menge beispiele, um bitmaps aus video zu grabben - aber Audiodaten?
leider sehr dürftig ! Hab mir deshalb die Videobeispiele für Audio angepasst, aber irgendwie ...


Bitte lasst Hirn regnen. Wäre Klasse wenn mir jemand auf die Sprünge helfen könnte.

Liebe Grüsse
sonetta
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ DirectX ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: