Udostępnij za pośrednictwem


Nadawanie danych ASF

[Funkcja skojarzona z tą stroną, windows Media Format 11 SDK, jest starszą funkcją. Został zastąpiony przez Source Reader i Sink Writer. Czytnik Źródeł i Rejestrator Ujścia zostały zoptymalizowane pod kątem systemów Windows 10 i Windows 11. Firma Microsoft zdecydowanie zaleca, aby nowy kod używał czytnika źródeł i modułu zapisywania ujścia zamiast zestawu SDK windows Media Format 11, jeśli jest to możliwe. Firma Microsoft sugeruje, że istniejący kod, który używa starszych interfejsów API, należy przepisać go do korzystania z nowych interfejsów API, jeśli to możliwe.]

W tym temacie opisano sposób wysyłania danych ASF przez sieć przy użyciu protokołu HTTP. Wysyłanie plików za pośrednictwem sieci wymaga użycia obiektu zapisywania, dlatego przed przeczytaniem tego tematu należy zapoznać się z ogólnym zrozumieniem tego obiektu. Aby uzyskać więcej informacji, zobacz Zapisywanie plików ASF.

Jeśli zaczynasz od nieskompresowanych danych, wykonaj następujące czynności:

  1. Utwórz obiekt zapisywania, wywołując funkcję WMCreateWriter. Ta funkcja zwraca wskaźnik IWMWriter.

    IWMWriter *pWriter;
    hr = WMCreateWriter(NULL, &pWriter);
    
  2. Utwórz obiekt ujścia sieci, wywołując funkcję WMCreateWriterNetworkSink, która zwraca wskaźnik IWMWriterNetworkSink.

    IWMWriterNetworkSink *pNetSink;
    hr = WMCreateWriterNetworkSink(&pNetSink);
    
  3. Wywołaj metodę IWMWriterNetworkSink::Open na ujściu sieciowym i ustaw numer portu do otwarcia, na przykład 8080. Opcjonalnie wywołaj IWMWriterNetworkSink::GetHostURL, aby uzyskać adres URL hosta. Klienci będą uzyskiwać dostęp do zawartości z tego adresu URL. Możesz również wywołać IWMWriterNetworkSink::SetMaximumClients, aby ograniczyć liczbę klientów.

    DWORD dwPortNum = 8080;
    hr = pNetSink->Open( &dwPortNum)
    
  4. Podłącz sieć jako ujście do zapisywarki, wywołując IWMWriterAdvanced::AddSink na zapisywarce, ze wskaźnikiem do interfejsu IWMWriterNetworkSink.

    IWMWriterAdvanced *pWriterAdvanced;
    hr = pWriter->QueryInterface(IID_IWMWriterAdvanced, ( void** ) pWriterAdvanced );
    if (SUCCEEDED(hr))
    {
        pWriterAdvanced->AddSink(pNetSink);
    }
    
  5. Ustaw profil ASF, wywołując metodę IWMWriter::SetProfile dla obiektu zapisywania, używając wskaźnika IWMProfile. Aby uzyskać informacje na temat tworzenia profilu, zobacz Praca z profilami.

  6. Opcjonalnie określ metadane przy użyciu interfejsu IWMHeaderInfo modułu zapisywania.

  7. Wywołaj IWMWriter::BeginWriting na zapisującym.

    hr = pWriter->BeginWriting();
    
  8. Dla każdego przykładu wywołaj metodę IWMWriter::WriteSample. Określ numer strumienia, czas prezentacji, czas trwania próbki i wskaźnik do próbkowego buforu. Metoda WriteSample kompresuje przykłady.

  9. Gdy skończysz, wywołaj IWMWriter::EndWriting na zapisywarce.

    hr = pWriter->EndWriting();
    
  10. Wywołaj IWMWriterAdvanced::RemoveSink na składniku zapisywania, aby odłączyć obiekt ujścia sieci.

    hr = pWriterAdvanced->RemoveSink(pNetSink);
    
  11. Wywołaj IWMWriterNetworkSink::Zamknij ujścia sieci, aby zwolnić port.

    hr = pNetSink->Close();
    

Innym sposobem przesyłania strumieniowego zawartości ASF za pośrednictwem sieci jest odczytywanie jej z istniejącego pliku ASF. Przykładowa aplikacja WMVNetWrite zawarta w zestawie SDK demonstruje to podejście. Oprócz wymienionych wcześniej kroków wykonaj następujące czynności:

  1. Utwórz obiekt czytelnika i wywołaj metodę Open o nazwie pliku.

  2. Wywołaj IWMReaderAdvanced::SetManualStreamSelection w obiekcie czytnika z wartością TRUE. Dzięki temu aplikacja może odczytywać każdy strumień w pliku, w tym strumienie z wzajemnym wykluczeniem.

  3. Zapytaj czytelnika o interfejs IWMProfile. Użyj tego wskaźnika podczas wywoływania IWMWriter::SetProfile obiektu zapisywania (krok 5 w poprzedniej procedurze).

  4. Dla każdego strumienia zdefiniowanego w profilu wywołaj IWMProfile::GetStream, aby pobrać numer strumienia. Przekaż ten numer strumienia do metody IWMReaderAdvanced::SetReceiveStreamSamples. Ta metoda informuje czytelnika o dostarczaniu skompresowanych próbek, a nie dekodowaniu ich. Przykłady zostaną dostarczone do aplikacji za pośrednictwem IWMReaderCallbackAdvanced::OnStreamSample metody wywołania zwrotnego.

    Należy uzyskać informacje o kodeku dla każdego strumienia odczytywanego nieskompresowanego i dodać je do nagłówka przed emisją. Aby uzyskać informacje kodera, wywołaj IWMHeaderInfo2::GetCodecInfoCount i IWMHeaderInfo2::GetCodecInfo, aby wyliczyć kodery skojarzone z plikiem w czytniku. Wybierz informacje o kodeku zgodne z konfiguracją strumienia. Następnie ustaw informacje kodeka w składniku zapisywania, wywołując IWMHeaderInfo3::AddCodecInfo, przekazując informacje uzyskane od czytnika.

  5. Po skonfigurowaniu profilu zapisywacza, wywołaj funkcję IWMWriter::GetInputCount na zapisywaczu, aby pozyskać liczbę wejść. Dla każdych danych wejściowych wywołaj IWMWriter::SetInputProps z wartością NULL. Wskazuje to na obiekt zapisywania, że aplikacja dostarczy skompresowane próbki, więc moduł zapisywania nie musi używać żadnych koderów do kompresowania danych. Przed wywołaniem BeginWritingnależy wywołać SetInputProps.

  6. Opcjonalnie skopiuj atrybuty metadanych z czytnika do modułu zapisywania

  7. Ponieważ próbki z czytnika są już skompresowane, użyj metody IWMWriterAdvanced::WriteStreamSample, aby napisać przykłady, zamiast metody WriteSample. Metoda WriteStreamSample pomija zwykłe procedury kompresji obiektu zapisywania.

  8. Gdy czytelnik osiągnie koniec pliku, wysyła powiadomienie WMT_EOF do aplikacji.

Ponadto aplikacja powinna prowadzić zegar na obiekcie czytnika, aby czytnik pobierał dane z pliku tak szybko, jak to możliwe. W tym celu wywołaj metodę IWMReaderAdvanced::SetUserProvidedClock na czytniku z wartością TRUE. Gdy odtwarzacz wyśle powiadomienie WMT_STARTED, wywołaj IWMReaderAdvanced::DeliverTime i określ interwał czasu, który ma dostarczyć odtwarzacz. Po zakończeniu odczytywania tego interwału czasu czytnik wywołuje IWMReaderCallbackAdvanced::OnTime metodę wywołania zwrotnego. Aplikacja powinna wywołać DeliverTime ponownie, aby odczytać następny interwał czasu. Aby na przykład odczytywać z pliku w odstępach jednej sekundy:

// Initial call to DeliverTime.
QWORD m_qwTime = 10000000; // 1 second.
hr = m_pReaderAdvanced->DeliverTime(m_qwTime);

// In the callback:
HRESULT CNetWrite::OnTime(QWORD cnsCurrentTime, void *pvContext)
{
    HRESULT hr = S_OK;
    // Continue calling DeliverTime until the end of the file.
    if(!m_bEOF)
    {
        m_qwTime += 10000000; // 1 second.
        hr = m_pReaderAdvanced->DeliverTime(m_qwTime);
    }
    return S_OK;
}

Wysyłanie danych ASF przez sieć

praca z ujściami składnika zapisywania