Share via


Synchronisation des commandes DVD

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture in Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement que le nouveau code utilise MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation au lieu de DirectShow, si possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Les commandes DVD ne se terminent pas toujours instantanément. Pour cette raison, certaines des méthodes dans IDvdControl2 sont asynchrones. Il s’agit notamment des méthodes de lecture, telles que PlayTitle, et des méthodes de navigation dans les menus, telles que ShowMenu et ReturnFromSubmenu. Une méthode asynchrone retourne immédiatement, sans attendre la fin de la commande. Une fois la méthode retournée, d’autres événements peuvent empêcher la fin de la commande, même si la méthode a réussi. DirectShow fournit plusieurs options pour la synchronisation des commandes, allant de l’absence de synchronisation à la synchronisation complète à l’aide d’événements de graphe de filtre.

Toutes les méthodes asynchrones ont un paramètre dwFlags et un paramètre ppCmd . Le paramètre dwFlags spécifie le comportement de synchronisation, et le paramètre ppCmd retourne un pointeur vers un objet de synchronisation facultatif. Des comportements différents se traduisent en fonction des valeurs que vous donnez pour ces paramètres.

Aucune synchronisation

Pour une application de lecture de DVD de base, la meilleure option peut consister simplement à ignorer les problèmes de synchronisation. Parfois, une commande peut échouer ou l’interface utilisateur peut légèrement être en retard lors de sa mise à jour, mais ces erreurs sont de l’ordre de fractions de secondes.

Pour émettre une commande sans synchronisation, définissez l’indicateur DVD_CMD_FLAG_None dans le paramètre dwFlags et définissez le paramètre ppCmd sur NULL :

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

Blocage

Si vous définissez l’indicateur EC_DVD_CMD_FLAG_Block dans le paramètre dwFlags , la méthode se bloque jusqu’à ce que la commande se termine :

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

En effet, cet indicateur transforme une méthode asynchrone en méthode synchrone. L’inconvénient est que votre interface utilisateur se bloque si vous appelez la méthode à partir du thread d’application.

Objet Synchronization

Toutes les méthodes asynchrones peuvent retourner un objet de synchronisation, que vous pouvez utiliser pour attendre le début ou la fin de la commande. Pour obtenir cet objet, passez l’adresse d’un pointeur IDvdCmd dans le paramètre ppCmd :

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

Si la méthode réussit, elle retourne un nouvel objet IDvdCmd . La méthode IDvdCmd::WaitForStart se bloque jusqu’à ce que la commande commence, et la méthode IDvdCmd::WaitForEnd se bloque jusqu’à ce que la commande se termine. La valeur de retour indique le status de la commande.

Le code suivant est fonctionnellement équivalent à la définition de l’indicateur EC_DVD_CMD_FLAG_Block, indiqué précédemment.

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();
}

Dans ce cas, la méthode PlayTitle ne bloque pas, mais l’application bloque en appelant WaitForEnd.

Événements d’état de la commande

Si vous définissez l’indicateur DVD_CMD_FLAG_SendEvents dans le paramètre dwFlags , le Navigateur de DVD envoie un événement EC_DVD_CMD_START au début de la commande et un événement EC_DVD_CMD_END à la fin de la commande.

Le paramètre lParam2 de l’événement est la valeur de retour HRESULT de la commande . Le paramètre lParam1 de l’événement fournit un moyen d’obtenir l’objet de synchronisation pour la commande . Si vous passez lParam1 à la méthode IDvdInfo2::GetCmdFromEvent , la méthode retourne un pointeur vers l’interface IDvdCmd de l’objet de synchronisation. Vous pouvez utiliser cette interface pour attendre la fin de la commande, comme décrit précédemment. Toutefois, si vous avez transmis NULL pour le paramètre ppCmd dans la méthode IDvdControl2 d’origine, le Navigateur de DVD ne crée pas d’objet de synchronisation et GetCmdFromEvent retourne E_FAIL.

Le code suivant montre comment utiliser des événements de status de commande sans objet de synchronisation.

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;
}

Notez que sans objet de synchronisation, vous ne pouvez pas déterminer quelle commande est associée à l’événement. Le code suivant montre comment utiliser des événements avec l’objet de synchronisation. L’idée est de stocker les objets de synchronisation dans une liste, puis de comparer les pointeurs d’objets lorsque vous obtenez l’événement EC_DVD_CMD_START ou 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;
} 

Vidage des mémoires tampons du navigateur de DVD

Pendant la lecture, le Navigateur de DVD met en mémoire tampon les données vidéo. La quantité de données mises en mémoire tampon varie. Lorsque le navigateur de DVD bascule vers une nouvelle vidéo, les données déjà dans le pipeline ne sont pas perdues, de sorte que la transition est transparente. Par défaut, lorsque le Navigateur de DVD émet une commande, il ne vide pas les données déjà dans le pipeline. Par conséquent, il peut y avoir une certaine latence avant que vous puissiez voir l’effet de la commande, en fonction de la quantité de données mises en mémoire tampon. Pour augmenter la réactivité, vous pouvez forcer le vidage du Dvd Navigator en définissant l’indicateur DVD_CMD_FLAG_Flush.

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

Cet indicateur peut être combiné avec l’un des indicateurs décrits précédemment, à l’aide d’un or au niveau du bit. Un effet secondaire du vidage est qu’une partie de la vidéo peut être perdue. N’utilisez donc pas cet indicateur si vous devez garantir qu’il n’y a pas de lacunes dans la vidéo.

DVD Applications