将流信息添加到 ASF 文件接收器

ASF 文件接收器是 Media Foundation 提供的 IMFMediaSink 的实现,应用程序可用于将 ASF 媒体数据存档到文件中。 有关 ASF 媒体接收器的对象模型和常规用法的信息,请参阅 ASF 媒体接收器

实例化文件接收器后,必须在生成拓扑之前对其进行配置。 文件接收器需要知道输出文件中的流、编码模式信息和元数据。 本主题介绍在文件接收器中添加流的过程。

在 ASF 文件接收器中添加流

文件接收器必须知道输出流及其属性,以便它可以相应地生成输出样本,并将其添加到输出 ASF 文件。 这些设置将写入最终的 ASF 标头对象。

若要设置流信息,必须引用文件接收器的 ASF ContentInfo 对象。 有关详细信息,请参阅 创建 ASF 文件接收器

以下过程总结了使用 ASF 配置文件对象配置流的常规步骤。

在 ASF 文件接收器中配置流信息

  1. 通过调用 MFCreateASFProfile 创建 ASF 配置文件对象。

  2. 对于输出文件中的每个流,请为要添加到文件接收器中的目标流创建媒体类型。 媒体类型必须与 Windows Media 编码器支持的输出类型兼容。

    有关将音频流添加到配置文件的信息,请参阅创建 ASF 编码的音频流。

    有关将视频流添加到配置文件的信息,请参阅创建 ASF 编码的视频流。

  3. 根据步骤 2 中创建的媒体类型创建流,方法是调用 IMFASFProfile::CreateStream

  4. 通过调用步骤 3 中收到的 IMFASFStreamConfig 接口指针为新创建的流分配流号。

  5. (可选)使用以下信息配置流:

  6. (可选)通过设置 MF_ASFPROFILE_MINPACKETSIZEMF_ASFPROFILE_MAXPACKETSIZE 属性来设置配置文件的数据包大小。 ASF 配置文件公开 IMFAttributes 接口,应用程序可以通过调用 IMFASFProfile::QueryInterface 来获取对接口的引用。

  7. 设置文件接收器中流的编码信息。 在 设置文件接收器中的属性中讨论。

  8. 通过调用 IMFASFProfile::SetStream 将流添加到配置文件。

  9. 通过调用 IMFASFContentInfo::SetProfile 将配置文件与 ContentInfo 对象相关联。

若要修改现有流,应用程序可以获取对流的 IMFASFStreamConfig 接口的引用,并根据要求对其进行重新配置。 若要添加或删除流,应用程序必须调用 IMFASFProfile::RemoveStream。 若要应用这些更改、流修改或删除,必须在 ContentInfo 对象中再次设置配置文件。 这会覆盖已与 ContentInfo 对象关联的现有配置文件。

//-------------------------------------------------------------------
//  CreateVideoStream
//  Create an video stream and add it to the profile.
//
//  pProfile: A pointer to the ASF profile.
//  wStreamNumber: Stream number to assign for the new stream.
//    pType: A pointer to the source's video media type.
//-------------------------------------------------------------------

HRESULT CreateVideoStream(IMFASFProfile* pProfile, WORD wStreamNumber, IMFMediaType* pType)
{
    if (!pProfile)
    {
        return E_INVALIDARG;
    }
    if (wStreamNumber < 1 || wStreamNumber > 127 )
    {
        return MF_E_INVALIDSTREAMNUMBER;
    }

    HRESULT hr = S_OK;

    
    IMFMediaType* pVideoType = NULL;
    IMFASFStreamConfig* pVideoStream = NULL;

    UINT32 dwBitRate = 0;
        
    //Create a new video type from the source type
    hr = CreateCompressedVideoType(pType, &pVideoType);
    if (FAILED(hr))
    {
        goto done;
    }

    //Create a new stream with the video type
    hr = pProfile->CreateStream(pVideoType, &pVideoStream);
    if (FAILED(hr))
    {
        goto done;
    }
    

    //Set a valid stream number
    hr = pVideoStream->SetStreamNumber(wStreamNumber);
    if (FAILED(hr))
    {
        goto done;
    }

    //Add the stream to the profile
    hr = pProfile->SetStream(pVideoStream);
    if (FAILED(hr))
    {
        goto done;
    }

    wprintf_s(L"Video Stream created. Stream Number: %d .\n", wStreamNumber);

done:

    SafeRelease(&pVideoStream);
    SafeRelease(&pVideoType);

    return hr;
}

枚举流接收器

对于 ContentInfo 对象感知到的配置文件中的每个流,ASF 文件接收器会创建并添加包含编码流的所有属性的流接收器。 ASF 文件接收器旨在包含固定流。 这意味着不能通过调用 IMFMediaSink::AddStreamSinkIMFMediaSink::RemoveStreamSink 来添加或删除流。 文件接收器上的这些调用失败,并出现MF_E_STREAMSINKS_FIXED错误代码。 在配置文件中添加或删除流不会自动添加或删除文件接收器中的流接收器。 如果配置文件中的流已更改,则必须放弃文件的现有实例,并使用新的流信息重新创建该文件。

以下过程总结了枚举 ASF 文件接收器中的流接收器的常规步骤。

枚举流接收器

  1. 调用 IMFMediaSink::GetStreamSinkCount 以获取 ASF 文件接收器中的流接收器总数。

  2. Loop通过流接收器获取对流接收器的 GetStreamSinkByIndex 接口的引用。

    - 或 -

    通过指定流号调用 IMFMediaSink::GetStreamSinkById 以获取流接收器。 每个流接收器都使用在配置文件中创建流时设置的流号进行标识。

如果要生成部分拓扑来编码媒体文件,则必须将文件接收器作为输出拓扑节点添加到拓扑。 可以通过在文件接收器中指定每个 Steam 接收器或设置文件接收器激活对象和流接收器标识符来执行此操作。 有关详细信息和代码示例,请参阅 创建输出节点

ASF 媒体接收器

媒体基础中的 ASF 支持