Erstellen von Wiedergabetopologien
In diesem Thema wird beschrieben, wie Sie eine Topologie für die Audio- oder Videowiedergabe erstellen. Für die einfache Wiedergabe können Sie eine Teiltopologie erstellen, in der die Quellknoten direkt mit den Ausgabeknoten verbunden sind. Sie müssen keine Knoten für die Zwischentransformationen einfügen, z. B. Decoder oder Farbkonverter. Die Mediensitzung verwendet das Topologieladeprogramm, um die Topologie aufzulösen, und das Topologieladeprogramm fügt die erforderlichen Transformationen ein.
- Erstellen der Topologie
- Verbinden von Streams mit Mediensenken
- Erstellen der Mediensenke
- Next Steps
- Zugehörige Themen
Erstellen der Topologie
Im Folgenden finden Sie die allgemeinen Schritte zum Erstellen einer partiellen Wiedergabetopologie aus einer Medienquelle:
- Erstellen Sie die Medienquelle. In den meisten Fällen verwenden Sie den Quell resolver, um die Medienquelle zu erstellen. Weitere Informationen finden Sie unter Quell resolver.
- Abrufen des Präsentationsdeskriptors der Medienquelle.
- Erstellen Sie eine leere Topologie.
- Verwenden Sie den Präsentationsdeskriptor, um die Streamdeskriptoren aufzuzählen. Für jeden Streamdeskriptor:
- Abrufen des Hauptmedientyps des Streams, z. B. Audio oder Video.
- Überprüfen Sie, ob der Stream derzeit ausgewählt ist. (Optional können Sie einen Stream basierend auf dem Medientyp auswählen oder die Auswahl aufheben.)
- Wenn der Stream ausgewählt ist, erstellen Sie basierend auf dem Medientyp des Streams ein Aktivierungsobjekt für die Mediensenke.
- Fügen Sie einen Quellknoten für den Stream und einen Ausgabeknoten für die Mediensenke hinzu.
- Verbinden den Quellknoten an den Ausgabeknoten.
Um diesen Prozess zu vereinfachen, ist der Beispielcode in diesem Thema in mehrere Funktionen unterteilt. Die Funktion der obersten Ebene heißt CreatePlaybackTopology . Es werden drei Parameter verwendet:
- Ein Zeiger auf eine INTERFACESMediaSource-Schnittstelle der Medienquelle.
- Ein Zeiger auf die INTERFACESPresentationDescriptor-Schnittstelle des Präsentationsdeskriptors. Rufen Sie diesen Zeiger ab, indem Sie DENKMediaSource::CreatePresentationDescriptoraufrufen. Für Quellen mit mehreren Präsentationen werden die Präsentationsdeskriptoren für nachfolgende Präsentationen im MENewPresentation-Ereignis bereitgestellt.
- Ein Handle für ein Anwendungsfenster. Wenn die Quelle über einen Videostream verfügt, wird das Video in diesem Fenster angezeigt.
Die Funktion gibt einen Zeiger auf eine partielle Wiedergabetopologie im ppTopology-Parameter zurück.
// Create a playback topology from a media source.
HRESULT CreatePlaybackTopology(
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
HWND hVideoWnd, // Video window.
IMFTopology **ppTopology) // Receives a pointer to the topology.
{
IMFTopology *pTopology = NULL;
DWORD cSourceStreams = 0;
// Create a new topology.
HRESULT hr = MFCreateTopology(&pTopology);
if (FAILED(hr))
{
goto done;
}
// Get the number of streams in the media source.
hr = pPD->GetStreamDescriptorCount(&cSourceStreams);
if (FAILED(hr))
{
goto done;
}
// For each stream, create the topology nodes and add them to the topology.
for (DWORD i = 0; i < cSourceStreams; i++)
{
hr = AddBranchToPartialTopology(pTopology, pSource, pPD, i, hVideoWnd);
if (FAILED(hr))
{
goto done;
}
}
// Return the IMFTopology pointer to the caller.
*ppTopology = pTopology;
(*ppTopology)->AddRef();
done:
SafeRelease(&pTopology);
return hr;
}
Diese Funktion führt folgende Schritte aus:
- Rufen Sie MFCreateTopology auf, um die Topologie zu erstellen. Anfänglich enthält die Topologie keine Knoten.
- Rufen Sie DEN AUFRUF VONPRESENTATIONDescriptor::GetStreamDescriptorCount auf, um die Anzahl der Streams in der Präsentation abzurufen.
- Rufen Sie für jeden Stream die anwendungsdefinierte
AddBranchToPartialTopologyFunktion zu einem Branch in der Topologie auf. Diese Funktion wird im nächsten Abschnitt gezeigt.
Verbinden von Streams mit Mediensenken
Fügen Sie für jeden ausgewählten Stream einen Quellknoten und einen Ausgabeknoten hinzu, und verbinden Sie dann die beiden Knoten. Der Quellknoten stellt den Stream dar. Der Ausgabeknoten stellt entweder den Enhanced Video Renderer (EVR) oder den Streaming Audio Renderer (SAR) dar.
Die AddBranchToPartialTopology im nächsten Beispiel gezeigte Funktion verwendet die folgenden Parameter:
- Ein Zeiger auf die INTERFACESTopology-Schnittstelle der Topologie.
- Ein Zeiger auf die INTERFACESMediaSource-Schnittstelle der Medienquelle.
- Ein Zeiger auf die INTERFACESPresentationDescriptor-Schnittstelle des Präsentationsdeskriptors.
- Der nullbasierte Index des Streams.
- Ein Handle für das Videofenster. Dieses Handle wird nur für den Videostream verwendet.
// Add a topology branch for one stream.
//
// For each stream, this function does the following:
//
// 1. Creates a source node associated with the stream.
// 2. Creates an output node for the renderer.
// 3. Connects the two nodes.
//
// The media session will add any decoders that are needed.
HRESULT AddBranchToPartialTopology(
IMFTopology *pTopology, // Topology.
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
DWORD iStream, // Stream index.
HWND hVideoWnd) // Window for video playback.
{
IMFStreamDescriptor *pSD = NULL;
IMFActivate *pSinkActivate = NULL;
IMFTopologyNode *pSourceNode = NULL;
IMFTopologyNode *pOutputNode = NULL;
BOOL fSelected = FALSE;
HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
if (fSelected)
{
// Create the media sink activation object.
hr = CreateMediaSinkActivate(pSD, hVideoWnd, &pSinkActivate);
if (FAILED(hr))
{
goto done;
}
// Add a source node for this stream.
hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode);
if (FAILED(hr))
{
goto done;
}
// Create the output node for the renderer.
hr = AddOutputNode(pTopology, pSinkActivate, 0, &pOutputNode);
if (FAILED(hr))
{
goto done;
}
// Connect the source node to the output node.
hr = pSourceNode->ConnectOutput(0, pOutputNode, 0);
}
// else: If not selected, don't add the branch.
done:
SafeRelease(&pSD);
SafeRelease(&pSinkActivate);
SafeRelease(&pSourceNode);
SafeRelease(&pOutputNode);
return hr;
}
Die Funktion führt Folgendes aus:
- Ruft DIE VerzeichnisseSEscriptor::GetStreamDescriptorByIndex auf und übergibt den Streamindex. Diese Methode gibt einen Zeiger auf den Streamdeskriptor für diesen Stream zusammen mit einem booleschen Wert zurück, der angibt, ob der Stream ausgewählt ist.
- Wenn der Stream nicht ausgewählt ist, wird die Funktion beendet und gibt S _ OK zurück, da die Anwendung keinen Topologiezweig für einen Stream erstellen muss, es sei denn, er ist ausgewählt.
- Wenn der Stream ausgewählt ist, schließt die Funktion die Topologieverzweigung wie folgt ab:
- Erstellt ein Aktivierungsobjekt für die Senke, indem die anwendungsdefinierte CreateMediaSinkActivate-Funktion aufgerufen wird. Diese Funktion wird im nächsten Abschnitt gezeigt.
- Fügt der Topologie einen Quellknoten hinzu. Der Code für diesen Schritt wird im Thema Erstellen von Quellknotengezeigt.
- Fügt der Topologie einen Ausgabeknoten hinzu. Der Code für diesen Schritt wird im Thema Erstellen von Ausgabeknotengezeigt.
- Verbindet die beiden Knoten durch Aufrufen von NODESTopologyNode::ConnectOutput auf dem Quellknoten. Durch verbinden der Knoten gibt die Anwendung an, dass der Upstreamknoten Daten an den Downstreamknoten übermitteln soll. Ein Quellknoten verfügt über eine Ausgabe und ein Ausgabeknoten über eine Eingabe, sodass beide Streamindizes 0 (null) sind.
Erweiterte Anwendungen können Streams auswählen oder deaktivieren, anstatt die Standardkonfiguration der Quelle zu verwenden. Eine Quelle kann über mehrere Streams verfügen, und jeder von ihnen kann standardmäßig ausgewählt werden. Der Präsentationsdeskriptor der Medienquelle verfügt über einen Standardsatz von Datenstromauswahlen. In einer einfachen Videodatei mit einem einzelnen Audio- und Videostream wählt die Medienquelle in der Regel beide Streams standardmäßig aus. Eine Datei kann jedoch mehrere Audiostreams für verschiedene Sprachen oder mehrere Videostreams enthalten, die mit unterschiedlichen Bitraten codiert sind. In diesem Fall wird die Auswahl einiger Streams standardmäßig aufgehoben. Die Anwendung kann die Auswahl ändern, indem SIE IM Präsentationsdeskriptor DIE OPTIONEN "PRESENTPresentationDescriptor::SelectStream" und "CSVPresentationDescriptor::D eselectStream" aufrufen.
Erstellen der Mediensenke
Die nächste Funktion erstellt ein Aktivierungsobjekt für die EVR- oder SAR-Mediensenke.
// Create an activation object for a renderer, based on the stream media type.
HRESULT CreateMediaSinkActivate(
IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor.
HWND hVideoWindow, // Handle to the video clipping window.
IMFActivate **ppActivate
)
{
IMFMediaTypeHandler *pHandler = NULL;
IMFActivate *pActivate = NULL;
// Get the media type handler for the stream.
HRESULT hr = pSourceSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
// Get the major media type.
GUID guidMajorType;
hr = pHandler->GetMajorType(&guidMajorType);
if (FAILED(hr))
{
goto done;
}
// Create an IMFActivate object for the renderer, based on the media type.
if (MFMediaType_Audio == guidMajorType)
{
// Create the audio renderer.
hr = MFCreateAudioRendererActivate(&pActivate);
}
else if (MFMediaType_Video == guidMajorType)
{
// Create the video renderer.
hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate);
}
else
{
// Unknown stream type.
hr = E_FAIL;
// Optionally, you could deselect this stream instead of failing.
}
if (FAILED(hr))
{
goto done;
}
// Return IMFActivate pointer to caller.
*ppActivate = pActivate;
(*ppActivate)->AddRef();
done:
SafeRelease(&pHandler);
SafeRelease(&pActivate);
return hr;
}
Diese Funktion führt folgende Schritte aus:
Ruft IM STREAM-Deskriptor DENSTREAMDESCRIPTOR::GetMediaTypeHandler auf. Diese Methode gibt einen POINTERMediaTypeHandler-Schnittstellenzeiger zurück.
Ruft DENMEDIATypeHandler::GetMajorType auf. Diese Methode gibt die Haupttyp-GUID für den Stream zurück.
Wenn der Streamtyp Audio ist, ruft die Funktion MFCreateAudioRendererActivate auf, um das Aktivierungsobjekt des Audiorenderers zu erstellen. Wenn der Streamtyp video ist, ruft die Funktion MFCreateVideoRendererActivate auf, um das Aktivierungsobjekt des Videorenderers zu erstellen. Beide Funktionen geben einen Zeiger auf die SCHNITTSTELLE "POINTERActivate" zurück. Dieser Zeiger wird verwendet, um den Ausgabeknoten für die Senke zu initialisieren, wie zuvor gezeigt.
Für jeden anderen Streamtyp gibt dieses Beispiel einen Fehlercode zurück. Alternativ können Sie einfach die Auswahl des Streams aufheben.
Nächste Schritte
Um jeweils eine Mediendatei wiederzuspielen, stellen Sie die Topologie in der Mediensitzung in die Warteschlange, indem Sie DEN AUFRUF VONMEDIASESSION::SetTopologyaufrufen. Die Mediensitzung verwendet das Topologieladeprogramm, um die Topologie aufzulösen. Ein vollständiges Beispiel finden Sie unter Wiedergeben von Mediendateien mit Media Foundation.