广播 ASF 数据

本主题介绍如何使用 HTTP 协议跨网络发送 ASF 数据。 通过网络发送文件需要使用编写器对象,因此在阅读本主题之前,应大致了解此对象。 有关详细信息,请参阅 编写 ASF 文件

如果从未压缩的数据开始,请执行以下操作:

  1. 通过调用 WMCreateWriter 函数创建编写器对象。 此函数返回 IWMWriter 指针。

    IWMWriter *pWriter;
    hr = WMCreateWriter(NULL, &pWriter);
    
  2. 通过调用 WMCreateWriterNetworkSink 函数创建网络接收器对象,该函数返回 IWMWriterNetworkSink 指针。

    IWMWriterNetworkSink *pNetSink;
    hr = WMCreateWriterNetworkSink(&pNetSink);
    
  3. 在网络接收器上调用 IWMWriterNetworkSink::Open ,并指定要打开的端口号;例如 8080。 (可选)调用 IWMWriterNetworkSink::GetHostURL 以获取主机的 URL。 客户端将从此 URL 访问内容。 还可以调用 IWMWriterNetworkSink::SetMaximumClients 来限制客户端数。

    DWORD dwPortNum = 8080;
    hr = pNetSink->Open( &dwPortNum)
    
  4. 通过在编写器上调用 IWMWriterAdvanced::AddSink ,使用指向网络接收器的 IWMWriterNetworkSink 接口的指针,将网络接收器附加到编写器。

    IWMWriterAdvanced *pWriterAdvanced;
    hr = pWriter->QueryInterface(IID_IWMWriterAdvanced, ( void** ) pWriterAdvanced );
    if (SUCCEEDED(hr))
    {
        pWriterAdvanced->AddSink(pNetSink);
    }
    
  5. 通过使用 IWMProfile 指针在编写器对象上调用 IWMWriter::SetProfile 方法来设置 ASF 配置文件。 有关创建配置文件的信息,请参阅 使用配置文件

  6. (可选)使用编写器上的 IWMHeaderInfo 接口指定元数据。

  7. 在编写器上调用 IWMWriter::BeginWriting

    hr = pWriter->BeginWriting();
    
  8. 对于每个示例,调用 IWMWriter::WriteSample 方法。 指定流编号、演示时间、样本持续时间和指向示例缓冲区的指针。 WriteSample 方法压缩示例。

  9. 完成后,请在编写器上调用 IWMWriter::EndWriting

    hr = pWriter->EndWriting();
    
  10. 在编写器上调用 IWMWriterAdvanced::RemoveSink 以分离网络接收器对象。

    hr = pWriterAdvanced->RemoveSink(pNetSink);
    
  11. 在网络接收器上调用 IWMWriterNetworkSink::Close 以释放端口。

    hr = pNetSink->Close();
    

通过网络流式传输 ASF 内容的另一种方法是从现有 ASF 文件读取 ASF 内容。 SDK 中提供的 WMVNetWrite 示例演示了此方法。 除了前面列出的步骤外,请执行以下操作:

  1. 创建读取器对象,并使用文件名调用 Open 方法。

  2. 在读取器对象上调用 IWMReaderAdvanced::SetManualStreamSelection ,其值为 TRUE。 这使应用程序能够读取文件中的每个流,包括相互排除的流。

  3. 查询 IWMProfile 接口的读取器。 在上一过程) (步骤 5 调用编写器对象上的 IWMWriter::SetProfile 时使用此指针。

  4. 对于配置文件中定义的每个流,调用 IWMProfile::GetStream 以获取流编号。 将此流编号传递给读取器的 IWMReaderAdvanced::SetReceiveStreamSamples 方法。 此方法通知读取器提供压缩样本,而不是对其进行解码。 这些示例将通过应用程序的 IWMReaderCallbackAdvanced::OnStreamSample 回调方法传递到应用程序。

    必须获取未压缩读取的每个流的编解码器信息,并在广播之前将其添加到标头。 若要获取编解码器信息,请调用 IWMHeaderInfo2::GetCodecInfoCountIWMHeaderInfo2::GetCodecInfo 以枚举与读取器中的文件关联的编解码器。 选择与流配置匹配的编解码器信息。 然后,通过调用 IWMHeaderInfo3::AddCodecInfo,传递从读取器获取的信息,在编写器中设置编解码器信息。

  5. 在编写器上设置配置文件后,调用编写 器上的 IWMWriter::GetInputCount 以获取输入数。 对于每个输入,请调用值为 NULLIWMWriter::SetInputProps。 这向编写器对象指示应用程序将提供压缩的示例,因此编写器不必使用任何编解码器来压缩数据。 在调用 BeginWriting 之前,请确保调用 SetInputProps

  6. (可选)将元数据属性从读取器复制到编写器

  7. 由于读取器中的示例已压缩,因此使用 IWMWriterAdvanced::WriteStreamSample 方法编写示例,而不是 WriteSample 方法。 WriteStreamSample 方法绕过编写器对象的常规压缩过程。

  8. 当读取器到达文件末尾时,它会向应用程序发送WMT_EOF通知。

此外,应用程序应驱动读取器对象的时钟,以便读取器尽快从文件拉取数据。 为此,请在读取器上调用 IWMReaderAdvanced::SetUserProvidedClock 方法,值为 TRUE。 读取器发送WMT_STARTED通知后,调用 IWMReaderAdvanced::D eliverTime 并指定读取器应提供的时间间隔。 读取器完成读取此时间间隔后,它会调用应用程序的 IWMReaderCallbackAdvanced::OnTime 回调方法。 应用程序应再次调用 DeliverTime 以读取下一个时间间隔。 例如,若要以一秒的间隔从文件读取数据,请执行以下操作:

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

通过网络发送 ASF 数据

使用编写器接收器