Scrittura del file
[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.
Per scrivere il file, è sufficiente eseguire il grafico del filtro chiamando il metodo IMediaControl::Run . Attendere il completamento della riproduzione e arrestare esplicitamente il grafico chiamando IMediaControl::Stop; in caso contrario, il file non è scritto correttamente.
Per visualizzare lo stato di avanzamento dell'operazione di scrittura dei file, eseguire una query sul filtro Mux per l'interfaccia IMediaSeeking . Chiamare il metodo IMediaSeeking::GetDuration per recuperare la durata del file. Periodicamente mentre il grafico è in esecuzione, chiamare il metodo IMediaSeeking::GetCurrentPosition per recuperare la posizione corrente del grafico nel flusso. La posizione corrente divisa per durata fornisce la percentuale di completamento.
Nota
Un'applicazione in genere esegue una query su Filter Graph Manager per IMediaSeeking, ma la scrittura di file è un'eccezione a questa regola. Filter Graph Manager calcola la posizione corrente dalla posizione iniziale e la durata dell'esecuzione del grafico, che è accurata per la riproduzione dei file, ma non per la scrittura di file. Pertanto, per ottenere un risultato accurato, è necessario recuperare la posizione dal filtro MUX.
Il codice seguente ottiene la durata del file, avvia un timer per aggiornare l'interfaccia utente dell'applicazione ed esegue il grafico del filtro. Il controllo degli errori viene omesso per maggiore chiarezza.
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();
Quando l'applicazione riceve un evento timer, può aggiornare l'interfaccia utente con la posizione corrente:
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);
}
}
Quando l'applicazione riceve un evento di completamento DirectShow, deve arrestare il grafico, come illustrato nel codice seguente:
// 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, ¶m1, ¶m2, 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);
}
}