Sincronizzazione dei comandi DVD

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine 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, FMMediaEngine e Audio/Video Capture 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 I MdfControl2 sono asincroni. Questi includono metodi di riproduzione, ad esempio PlayTitle e metodi di spostamento dei menu, ad esempio ShowMenu e ReturnFromSubmenu. Un metodo asincrono restituisce immediatamente, senza attendere il completamento del comando. Dopo che il metodo restituisce, altri eventi possono 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 grafico 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. Risultati di comportamenti diversi a seconda dei valori che si assegnano per questi parametri.

Nessuna sincronizzazione

Per un'applicazione di riproduzione DVD di base, l'opzione migliore può essere semplicemente ignorare i problemi di sincronizzazione. Occasionalmente un comando potrebbe non riuscire o l'interfaccia utente potrebbe ritardare leggermente 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);

Processi bloccati

Se si imposta il flag EC_DVD_CMD_FLAG_Block nel parametro dwFlags , il metodo 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 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 puntatore IDeviceCmd nel parametro ppCmd :

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

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

Il codice seguente equivale in modo funzionale all'impostazione del flag di 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 blocca chiamando WaitForEnd.

Eventi di stato comando

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 quando il comando inizia 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 si passa lParam1 al metodo IDeviceInfo2::GetCmdFromEvent , il metodo restituisce un puntatore all'interfaccia IDeviceCmd 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 I MdfControl2 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 oggetti 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 è 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;
} 

Scaricamento dei buffer del navigatore DVD

Durante la riproduzione, il navigatore DVD memorizza i dati video. La quantità di dati memorizzati nel buffer varia. Quando il navigatore DVD passa a una nuova parte di video, i dati già nella pipeline non vengono persi, quindi la transizione è facile. Per impostazione predefinita, quando lo strumento di navigazione DVD genera un comando, non scarica i dati già nella pipeline. Di conseguenza, potrebbe esserci una latenza prima di poter visualizzare l'effetto del comando, a seconda della quantità di dati memorizzata nel buffer. Per aumentare la velocità di risposta, è possibile forzare lo scaricamento del navigatore DVD impostando il flag di 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 essere persi, quindi non usare questo flag se è necessario garantire che non ci siano lacune nel video.

Applicazioni DVD