Freigeben über


Schreiben der Datei

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation abgelöst. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code mediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, so umgeschrieben wird, dass nach Möglichkeit die neuen APIs verwendet werden.]

Um die Datei zu schreiben, führen Sie einfach das Filterdiagramm aus, indem Sie die IMediaControl::Run-Methode aufrufen. Warten Sie, bis die Wiedergabe abgeschlossen ist, und beenden Sie das Diagramm explizit, indem Sie IMediaControl::Stop aufrufen. Andernfalls wird die Datei nicht ordnungsgemäß geschrieben.

Um den Fortschritt des Dateischreibvorgangs anzuzeigen, fragen Sie den Mux-Filter für die IMediaSeeking-Schnittstelle ab . Rufen Sie die IMediaSeeking::GetDuration-Methode auf, um die Dauer der Datei abzurufen. Rufen Sie während der Ausführung des Graphen in regelmäßigen Abständen die IMediaSeeking::GetCurrentPosition-Methode auf, um die aktuelle Position des Graphen im Stream abzurufen. Die aktuelle Position dividiert durch dauer ergibt den prozentsatz abgeschlossen.

Hinweis

Eine Anwendung fragt in der Regel den Filter Graph-Manager für IMediaSeeking ab, aber das Schreiben von Dateien ist eine Ausnahme von dieser Regel. Der Filtergraph-Manager berechnet die aktuelle Position von der Startposition und wie lange der Graph ausgeführt wurde. Dies ist für die Dateiwiedergabe, aber nicht für das Schreiben von Dateien genau. Daher sollten Sie die Position aus dem MUX-Filter abrufen, um ein genaues Ergebnis zu erhalten.

 

Der folgende Code ruft die Dauer der Datei ab, startet einen Timer zum Aktualisieren der Anwendungsbenutzeroberfläche und führt das Filterdiagramm aus. (Fehlerüberprüfung wird aus Gründen der Übersichtlichkeit weggelassen.)

IMediaSeeking *pSeek = NULL;
IMediaEventEx *pEvent = NULL;
IMediaControl *pControl = NULL;
REFERENCE_TIME rtTotal;

// Query for interfaces. Remember to release them later.
hr = pMux->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
hr = pGraph->QueryInterface(IID_IMediaEventEx, (void**)&pEvent);
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);

// Error checking is omitted for clarity.

// Set the DirectShow event notification window.
hr = pEvent->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0);

// Set the range of the progress bar to the file length (in seconds).
hr = pSeek->GetDuration(&rtTotal);
SendDlgItemMessage(hwnd, IDC_PROGRESS1, PBM_SETRANGE, 0, 
   MAKELPARAM(0, rtTotal / 10000000));
// Start the timer.
UINT_PTR res = SetTimer(hwnd, nIDEvent, 100, NULL);
// Run the graph.
pControl->Run();

Wenn die Anwendung ein Timerereignis empfängt, kann sie die Benutzeroberfläche mit der aktuellen Position aktualisieren:

void OnTimer(HWND hDlg, IMediaSeeking *pSeek)
{
    REFERENCE_TIME rtNow;
    HRESULT hr = pSeek->GetCurrentPosition(&rtNow);
    if (SUCCEEDED(hr))
    {
        SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, rtNow/10000000, 0);
    }
}

Wenn die Anwendung ein DirectShow-Abschlussereignis empfängt, sollte sie das Diagramm beenden, wie im folgenden Code gezeigt:

// Application window procedure
LRESULT CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    /*  ...  */
    case WM_GRAPHNOTIFY:
        DoHandleEvent();
        break;
    /*  ...  */
    }
}

void DoHandleEvent()
{
    long evCode, param1, param2;
    bool bComplete = false;
    if (!pEvent) return;

    // Get all the events, and see we're done.
    while (SUCCEEDED(pEvent->GetEvent(&evCode, &param1, &param2, 0))
    {
        pEvent->FreeEventParams(evCode, param1, param2);
        switch(evCode)
        {
            case EC_USERABORT:
            case EC_ERRORABORT:
            case EC_COMPLETE:
                bComplete = true;
                break;
        }
    }
    if (bComplete)
    {
        pControl->Stop(); // Important! You must stop the graph!

        // Turn off event notification.
        pEvent->SetNotifyWindow(NULL, 0, 0);
        pEvent->Release();
        pEvent = NULL;
        // Reset the progress bar to zero and get rid of the timer.
        SendDlgItemMessage(IDC_PROGRESS1, PBM_SETPOS, 0, 0);
        KillTimer(hwnd, nIDEvent);
    }
}