常量比特率编码

在固定比特率 (CBR) 编码中,编码器知道输出媒体样本的比特率和缓冲区窗口 (编码会话开始前) 泄漏的存储桶参数。 编码器在整个文件持续时间内使用相同位数对样本的每一秒进行编码,以实现流的目标比特率。 这限制了流样本大小的变化。 此外,在编码会话期间,比特率并不完全达到指定值,而是保持接近目标比特率。

当你希望在不解析整个文件的情况下了解文件的比特率或大致持续时间时,CBR 编码会很有用。 在实时流式处理中,这是必需的,因为此时需要以可预测的比特率并保持不变的带宽使用率来对媒体内容进行流式处理。

CBR 编码的缺点是编码内容的质量不会保持不变。 由于某些内容更难压缩,因此 CBR 流的某些部分的质量会比其他内容低。 例如,典型的电影具有一些相当静态的场景和一些充满动作的场景。 如果使用 CBR 对电影进行编码,则静态且因此易于高效编码的场景的质量将高于动作场景,因为动作场景需要更高的样本大小才能保持相同的质量。

通常,CBR 文件质量的变化在较低的比特率下更为明显。 在较高的比特率下,CBR 编码文件的质量仍会有所不同,但质量问题对用户不太明显。 使用 CBR 编码时,应将带宽设置为交付方案允许的上限。

CBR 配置设置

必须在编码会话之前通过指定编码类型和各种流特定的设置来配置编码器。

为 CBR 编码配置编码器

  1. 指定 CBR 编码模式。

    默认情况下,编码器配置为使用 CBR 编码。 编码器配置是通过属性值设置的。 这些属性在 wmcodecdsp.h 中定义。 可以通过将 MFPKEY_VBRENABLED 属性设置为 VARIANT_FALSE 来显式指定此模式。 有关如何在编码器上设置属性的信息,请参阅 配置编码器

  2. 选择编码比特率。

    对于 CBR 编码,在编码会话开始之前,必须知道要对流进行编码的比特率。 在配置编码器期间,必须设置比特率。 为此,在执行媒体类型协商时,检查音频流的MF_MT_AUDIO_AVG_BYTES_PER_SECOND属性 () 或视频流的MF_MT_AVG_BITRATE属性 () 可用输出媒体类型,并选择平均比特率最接近目标比特率的输出媒体类型。 有关详细信息,请参阅 编码器上的媒体类型协商

下面的代码示例演示 SetEncodingProperties 的实现。 此函数设置 CBR 和 VBR 的流级别编码属性。

//-------------------------------------------------------------------
//  SetEncodingProperties
//  Create a media source from a URL.
//
//  guidMT:  Major type of the stream, audio or video
//  pProps:  A pointer to the property store in which 
//           to set the required encoding properties.
//-------------------------------------------------------------------

HRESULT SetEncodingProperties (const GUID guidMT, IPropertyStore* pProps)
{
    if (!pProps)
    {
        return E_INVALIDARG;
    }

    if (EncodingMode == NONE)
    {
        return MF_E_NOT_INITIALIZED;
    }
   
    HRESULT hr = S_OK;

    PROPVARIANT var;

    switch (EncodingMode)
    {
        case CBR:
            // Set VBR to false.
            hr = InitPropVariantFromBoolean(FALSE, &var);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = pProps->SetValue(MFPKEY_VBRENABLED, var);
            if (FAILED(hr))
            {
                goto done;
            }

            // Set the video buffer window.
            if (guidMT == MFMediaType_Video)
            {
                hr = InitPropVariantFromInt32(VIDEO_WINDOW_MSEC, &var);
                if (FAILED(hr))
                {
                    goto done;
                }

                hr = pProps->SetValue(MFPKEY_VIDEOWINDOW, var);    
                if (FAILED(hr))
                {
                    goto done;
                }
            }
            break;

        case VBR:
            //Set VBR to true.
            hr = InitPropVariantFromBoolean(TRUE, &var);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = pProps->SetValue(MFPKEY_VBRENABLED, var);
            if (FAILED(hr))
            {
                goto done;
            }

            // Number of encoding passes is 1.

            hr = InitPropVariantFromInt32(1, &var);
            if (FAILED(hr))
            {
                goto done;
            }

            hr = pProps->SetValue(MFPKEY_PASSESUSED, var);
            if (FAILED(hr))
            {
                goto done;
            }

            // Set the quality level.

            if (guidMT == MFMediaType_Audio)
            {
                hr = InitPropVariantFromUInt32(98, &var);
                if (FAILED(hr))
                {
                    goto done;
                }

                hr = pProps->SetValue(MFPKEY_DESIRED_VBRQUALITY, var);    
                if (FAILED(hr))
                {
                    goto done;
                }
            }
            else if (guidMT == MFMediaType_Video)
            {
                hr = InitPropVariantFromUInt32(95, &var);
                if (FAILED(hr))
                {
                    goto done;
                }

                hr = pProps->SetValue(MFPKEY_VBRQUALITY, var);    
                if (FAILED(hr))
                {
                    goto done;
                }
            }
            break;

        default:
            hr = E_UNEXPECTED;
            break;
    }    

done:
    PropVariantClear(&var);
    return hr;
}

漏水桶设置

对于 CBR 编码,流的平均值和最大泄漏桶值相同。 有关这些参数的详细信息,请参阅 漏水桶缓冲区模型

若要对音频流进行 CBR 编码,需要在编码器上协商输出媒体类型后设置泄漏的存储桶值。 编码器根据输出媒体类型上设置的平均比特率在内部计算缓冲区窗口。

若要设置泄漏的存储桶值,请创建 DWORD 数组,可以在媒体接收器的属性存储中的 MFPKEY_ASFSTREAMSINK_CORRECTED_LEAKYBUCKET 属性中设置以下值。 有关详细信息,请参阅 在文件接收器中设置属性

ASF 编码类型

教程:1-Pass Windows Media Encoding

教程:使用 CBR 编码编写 WMA 文件