Condividi tramite


Sincronizzazione dei comandi DVD

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEnginee Acquisizione audio/video in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che per lo sviluppo di nuovo codice si utilizzi MediaPlayer, IMFMediaEngine e Acquisizione audio/video in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

I comandi DVD non vengono sempre completati immediatamente. Per questo motivo, alcuni dei metodi in IControl2 sono asincroni. Tra questi sono inclusi i metodi di riproduzione, ad esempio PlayTitlee i metodi di spostamento dei menu, ad esempio ShowMenu e ReturnFromSubmenu. Un metodo asincrono restituisce immediatamente, senza attendere il completamento del comando. Al termine del metodo, altri eventi potrebbero impedire il completamento del comando, anche se il metodo ha avuto esito positivo. DirectShow offre diverse opzioni per la sincronizzazione dei comandi, che vanno da nessuna sincronizzazione alla sincronizzazione completa tramite eventi del grafo di filtro.

Tutti i metodi asincroni hanno un parametro dwFlags e un parametro ppCmd. Il parametro dwFlags specifica il comportamento di sincronizzazione e il parametro ppCmd restituisce un puntatore a un oggetto di sincronizzazione facoltativo. Il risultato di comportamenti diversi dipende dai valori specificati per questi parametri.

nessuna sincronizzazione

Per un'applicazione di riproduzione DVD di base, l'opzione migliore può essere semplicemente ignorare i problemi di sincronizzazione. In alcuni casi, un comando potrebbe non riuscire o l'interfaccia utente potrebbe essere leggermente ritardata quando viene aggiornato, ma questi errori saranno nell'ordine di frazioni di secondi.

Per eseguire un comando senza sincronizzazione, impostare il flag di DVD_CMD_FLAG_None nel parametro dwFlags e impostare il parametro ppCmd su NULL:

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, NULL);

blocco

Se si imposta il flag EC_DVD_CMD_FLAG_Block nel parametro dwFlags, il metodo si blocca fino al completamento del comando:

hr = pDVDControl2->PlayTitle(uTitle, EC_DVD_CMD_FLAG_Block, NULL);

In effetti, questo flag trasforma un metodo asincrono in un metodo sincrono. Lo svantaggio è che l'interfaccia utente si blocca se si chiama il metodo dal thread dell'applicazione.

Oggetto di Sincronizzazione

Tutti i metodi asincroni possono restituire un oggetto di sincronizzazione, che è possibile usare per attendere l'avvio o la fine del comando. Per ottenere questo oggetto, passare l'indirizzo di un puntatoreIDeviceCmdnel parametro ppCmd:

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, &pCmdObj);

Se il metodo ha esito positivo, restituisce un nuovo oggetto IConfigurationCmd. Il metodo IDvdCmd::WaitForStart blocca fino all'inizio del comando e il metodo IDvdCmd::WaitForEnd blocca fino al termine del comando. Il valore restituito indica lo stato del comando.

Il codice seguente è funzionalmente equivalente all'impostazione del flag EC_DVD_CMD_FLAG_Block, illustrato in precedenza.

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_None, &pCmdObj);
if (SUCCEEDED(hr))
{
    // Use pCmdObj to wait for the command to complete.
    hr = pCmdObj->WaitToEnd();
    pCmdObj->Release();
}

In questo caso, il metodo PlayTitle non blocca, ma l'applicazione si blocca quando chiama WaitForEnd.

eventi di stato dei comandi

Se si imposta il flag di DVD_CMD_FLAG_SendEvents nel parametro dwFlags, lo strumento di navigazione DVD invia un evento EC_DVD_CMD_START all'avvio del comando e un evento EC_DVD_CMD_END al termine del comando.

Il parametro lParam2 dell'evento è il valore restituito HRESULT per il comando. Il parametro lParam1 dell'evento fornisce un modo per ottenere l'oggetto di sincronizzazione per il comando. Se passi lParam1 al metodo IDvdInfo2::GetCmdFromEvent, il metodo restituisce un puntatore all'interfaccia IDvdCmd dell'oggetto di sincronizzazione. È possibile usare questa interfaccia per attendere il completamento del comando, come descritto in precedenza. Tuttavia, se è stato passato NULL per il parametro ppCmd nel metodo IDvdControl2 originale, lo strumento di navigazione DVD non crea un oggetto di sincronizzazione e GetCmdFromEvent restituisce E_FAIL.

Il codice seguente illustra come usare gli eventi di stato dei comandi senza alcun oggetto di sincronizzazione.

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_SendEvents, NULL);

// In your event handling code:
switch (lEvent)
{
   case EC_DVD_CMD_END:
       HRESULT hr2 = (HRESULT)lParam2;
       /* ... */ 
       break;
}

Si noti che senza un oggetto di sincronizzazione non è possibile indicare quale comando è associato all'evento. Il codice seguente illustra come usare gli eventi con l'oggetto di sincronizzazione. L'idea consiste nell'archiviare gli oggetti di sincronizzazione in un elenco e quindi confrontare i puntatori a oggetti quando si ottiene l'evento EC_DVD_CMD_START o EC_DVD_CMD_END.

IDvdCmd *pCmdObj = NULL;
hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_SendEvents, &pCmdObj);
if (SUCCEEDED(hr)) 
{
    // Store pCmdObj in a list of pending commands.
}

// In your event handling code:
switch (lEvent)
{
case EC_DVD_CMD_END:
   {
       IDvdCmd *pObj = NULL;
       hr = pDvdInfo2->GetCmdFromEvent(lParam, &pObj);
       if (SUCCEEDED(hr)) 
       {
           // Find this object in your list by comparing IUnknown
           // pointers. Assume the following function is defined in 
           // your application:
           IDvdCmd *pPendingObj = GetPendingCommandFromList(pObj); 
           if (pPendingObj)
           {
               // Update UI accordingly (not shown). 
               pPendingObj->Release();
           }
           pObj->Release();
       }
    }
    break;
} 

svuotare i buffer del navigatore DVD

Durante la riproduzione, lo strumento di navigazione DVD memorizza nel buffer i dati video. La quantità di dati memorizzati nel buffer varia. Quando lo strumento di navigazione DVD passa a una nuova parte di video, i dati già presenti nella pipeline non vengono persi, quindi la transizione è facile. Per impostazione predefinita, quando lo strumento di navigazione DVD emette un comando, non scarica i dati già nella pipeline. Di conseguenza, potrebbe esserci una certa latenza prima di poter visualizzare l'effetto del comando, a seconda della quantità di dati memorizzati nel buffer. Per aumentare la velocità di risposta, puoi forzare il DVD Navigator a eseguire il flushing impostando il flag DVD_CMD_FLAG_Flush.

hr = pDVDControl2->PlayTitle(uTitle, DVD_CMD_FLAG_Flush, NULL);

Questo flag può essere combinato con uno qualsiasi dei flag descritti in precedenza, usando un OR bit per bit. Un effetto collaterale dello scaricamento è che alcuni video potrebbero andare persi, quindi non usare questo flag se è necessario garantire che non ci siano lacune nel video.

Applicazioni DVD