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

ASF 文件接收器是媒体基础提供的 IMFMediaSink 的实现,应用程序可以使用该实现将 ASF 媒体数据存档到文件中。 有关 ASF 媒体接收器的对象模型和一般用法的信息,请参阅 ASF 媒体接收器

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

在 ASF 文件接收器中添加流

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

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

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

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

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

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

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

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

  3. 通过调用 IMFASFProfile::CreateStream,基于步骤 2 中创建的媒体类型创建流。

  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. 循环访问流接收器,获取对流接收器的 GetStreamSinkByIndex 接口的引用。

    -或-

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

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

ASF 媒体接收器

媒体基础中的 ASF 支持