Quality-Based可变比特率编码

与 CBR) 常 量比特率编码 (不同,在可变比特率 (VBR) 模式下,编码器努力实现编码媒体的最佳质量。 CBR 和 VBR 之间的主要区别在于所使用的缓冲区窗口的大小。 与 CBR 编码的流相比,VBR 编码的流通常具有较大的缓冲区窗口。

编码内容的质量取决于压缩内容时丢失的数据量。 许多因素会影响压缩过程中的数据丢失;但一般来说,原始数据越复杂,压缩率越高,压缩过程中丢失的细节就越大。

在基于质量的 VBR 模式下,不定义编码器必须遵循的比特率或缓冲区窗口。 而是指定数字媒体流的质量级别,而不是比特率。 编码器压缩内容,使所有样本的质量都相当;这可确保质量在整个播放持续时间内保持一致,而不管生成的流的缓冲区要求如何。

基于质量的 VBR 编码倾向于创建大型压缩流。 通常,这种类型的编码非常适合本地播放或高带宽网络连接, (或下载和播放) 。 例如,可以编写一个应用程序,将歌曲从 CD 复制到计算机上的 ASF 文件。 使用基于质量的 VBR 编码可确保复制的所有歌曲都具有相同的质量。 在这些情况下,一致的质量将提供更好的用户体验。

基于质量的 VBR 编码的缺点是,在编码会话之前,实际上无法知道编码媒体的大小或带宽要求,因为编码器使用单个编码传递。 这可能使基于质量的 VBR 编码文件不适用于内存或带宽受限的情况,例如在便携式媒体播放器上播放内容或通过低带宽网络进行流式传输。

为 Quality-Based VBR 编码配置编码器

编码器配置是通过属性值设置的。 这些属性在 wmcodecdsp.h 中定义。 在协商输出媒体类型之前,必须在编码器上设置配置属性。 有关如何在编码器上设置属性的信息,请参阅 配置编码器

以下列表显示了必须为此类型的编码设置的属性:

  • 通过将 MFPKEY_VBRENABLED 属性设置为 VARIANT_TRUE 来指定 VBR 编码模式。
  • MFPKEY_PASSESUSED 设置为 1,因为此 VBR 模式使用一个编码通道。
  • 通过设置 MFPKEY_DESIRED_VBRQUALITY 属性,将所需质量级别 (从 0 设置为 100 ) 。 基于质量的 VBR 不会将内容编码为任何预定义的缓冲区参数。 此质量级别将在整个流中保持,而不考虑由此产生的比特率要求。
  • 对于视频流,请在编码器的输出媒体类型上的 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;
}

ASF 编码类型