通过 IWMDMDevice3 获取格式功能

IWMDMDevice3::GetFormatCapability 是询问设备支持哪些格式的首选方法。 以下步骤演示如何使用此方法查询设备的格式功能:

  1. 应用程序必须确定设备支持的格式以及感兴趣的格式。 为此,应用程序可以通过调用 IWMDMDevice3::GetProperty 请求设备支持的格式列表。
  2. 应用程序循环访问所有支持的格式,并通过调用 IWMDMDevice3::GetFormatCapability 并使用 WMDM_FORMATCODE 枚举指定格式,请求设备针对特定格式 (( 例如 WMA 或 WMV) )的格式功能。 此方法检索 WMDM_FORMAT_CAPABILITY 结构。
  3. 循环访问检索到 WMDM_FORMAT_CAPABILITY 结构中的所有 WMDM_PROP_CONFIG 结构。 每个 WMDM_PROP_CONFIG 结构都包含一组具有支持值的属性,表示该格式的一个配置。 每个配置都有一个首选项编号,其中较小的数字表示设备具有更大的首选项。
  4. 循环访问检索到 WMDM_PROP_CONFIG 中的所有 WMDM_PROP_DESC结构。 每个 WMDM_PROP_DESC 都包含受支持的属性/值对的列表。
  5. WMDM_PROP_DESC 结构中检索属性名称和值。 属性包括比特率、编解码器和帧大小。 属性名称在 mswmdm.h 头文件中定义;元数据常量中提供了其中大多数 常量的列表。 可以使用三种类型的属性值:
    • 单个值WMDM_ENUM_PROP_VALID_VALUES_ANY,指示支持此属性的任何值。
    • 值范围,由最大值、最小值和间隔定义。
    • 离散值的列表。
  6. 清除存储的值。 这些值的内存由 Windows Media 设备管理器 分配;你的设备负责释放内存。 本主题末尾介绍了如何执行此操作。

响应 GetFormatCapability 时,设备可以报告WMDM_FORMAT_CAPABILITY WMDM_ENUM_PROP_VALID_VALUES_ANY。WMDM_PROP_CONFIG。WMDM_PROP_DESC。ValidValuesForm 声明对比特率、通道等任何值的支持。 但是,应谨慎对待此声明,因为设备有时可能报告对任何值的支持,而实际上它们不支持所有比特率或图像大小。 在将应用程序发送到打算播放这些文件的设备时,可以考虑让应用程序将极大型或高比特率文件转码到较小的版本或内存密集型和 CPU 密集型版本。

以下 C++ 函数演示如何请求对特定格式的设备格式支持。

HRESULT GetFormatCaps(WMDM_FORMATCODE formatCode, IWMDMDevice3* pDevice)
{
    HRESULT hr = S_OK;

    // Get a list of supported configurations for the format.
    WMDM_FORMAT_CAPABILITY formatCapList;
    hr = pDevice->GetFormatCapability(formatCode, &formatCapList);
    if (FAILED(hr)) return E_FAIL;

    // TODO: Display the format name.
    // Loop through the configurations and examine each one.
    for (UINT iConfig = 0; iConfig < formatCapList.nPropConfig; iConfig++)
    {
        WMDM_PROP_CONFIG formatConfig = formatCapList.pConfigs[iConfig];

        // Preference level for this configuration (lower number means more preferred).
        // TODO: Display the preference level for this format configuration.

        // Loop through all properties for this configuration and get supported
        // values for the property. Values can be a single value, a range, 
        // or a list of enumerated values.
        for (UINT iDesc = 0; iDesc < formatConfig.nPropDesc; iDesc++)
        {
            WMDM_PROP_DESC propDesc = formatConfig.pPropDesc[iDesc];
            // TODO: Display the property name.

            // Three ways a value can be represented: any, a range, or a list.
            switch (propDesc.ValidValuesForm)
            {
                case WMDM_ENUM_PROP_VALID_VALUES_ANY:
                    // TODO: Display a message indicating that all values are valid.
                    break;
                case WMDM_ENUM_PROP_VALID_VALUES_RANGE:
                    {
                        // List these in the docs as the propvariants set.
                        WMDM_PROP_VALUES_RANGE rng = 
                            propDesc.ValidValues.ValidValuesRange;
                        // TODO: Display the min, max, and step values.
                    }
                    break;
                case WMDM_ENUM_PROP_VALID_VALUES_ENUM:
                    {
                        // TODO: Display a banner for the list of valid values.
                        WMDM_PROP_VALUES_ENUM list = propDesc.ValidValues.EnumeratedValidValues;
                        PROPVARIANT pVal;
                        for (UINT iValue = 0; iValue < list.cEnumValues; iValue++)
                        {
                            pVal = list.pValues[iValue];
                            // TODO: Display each valid value.
                            PropVariantClear(&pVal);
                            PropVariantInit(&pVal);
                        }
                    }

                    break;
                default:
                    return E_FAIL,
                    break;
            }
        }
    }
    // Now clear the memory used by WMDM_FORMAT_CAPABILITY.
    FreeFormatCapability(formatCapList);
    return hr;
}

清除分配的内存

从设备检索格式功能后,应用程序必须释放分配用于保存说明的内存。 GetFormatSupportGetFormatSupport2 具有简单结构的数组,只需使用 数组调用 CoTaskMemFree 即可清除这些结构。 但是, GetFormatCapability 具有更复杂的数据结构,其中包含动态分配的内存,必须通过循环访问所有元素并单独释放它们来清除这些内存。

以下 C++ 代码演示应用程序如何释放为 WMDM_FORMAT_CAPABILITY 结构分配的内存。

void CWMDMController::FreeFormatCapability(WMDM_FORMAT_CAPABILITY formatCap)
{
    // Loop through all configurations.
    for (UINT i = 0; i < formatCap.nPropConfig; i++) 
    {
        // Loop through all descriptions of a configuration and delete
        // the values particular to that description type.
        for (UINT j=0; j < formatCap.pConfigs[i].nPropDesc; j++) 
        {
            switch (formatCap.pConfigs[i].pPropDesc[j].ValidValuesForm)
            {
                case WMDM_ENUM_PROP_VALID_VALUES_ENUM:
                    for (UINT k=0; k < formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.cEnumValues; k++)
                    {
                        PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.pValues[k]));
                    }
                    CoTaskMemFree(formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.pValues);
                    break;
                case WMDM_ENUM_PROP_VALID_VALUES_RANGE:
                    PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeMin));
                    PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeMax));
                    PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeStep));
                    break;
                case WMDM_ENUM_PROP_VALID_VALUES_ANY:
                    // No dynamically allocated memory for this value.
                default:
                    break;
            }

            // Free the memory for the description name.
            CoTaskMemFree(formatCap.pConfigs[i].pPropDesc[j].pwszPropName);
        }
        // Free the memory holding the array of description items for this configuration.
        CoTaskMemFree(formatCap.pConfigs[i].pPropDesc);
    }

    // Free the memory pointing to the array of configurations.
    CoTaskMemFree(formatCap.pConfigs);
    formatCap.nPropConfig = 0;
}

查询所有支持的格式

通常,应用程序会查询设备以查找特定格式,因为它有兴趣将特定文件发送到设备。 但是,如果要查询应用程序的所有支持格式,可以调用 IWMDMDevice3::GetProperty 并传入g_wszWMDMFormatsSupported以检索完整列表。

如果设备仅返回一个元素(WMDM_FORMATCODE_UNDEFINED),这通常意味着设备不支持格式代码。 使用 WMDM_FORMATCODE_UNDEFINED 调用 GetFormatCapability 可能会检索功能,但这些属性可能是相当通用的 (,例如名称、文件大小、上次修改日期等) 。

以下步骤演示如何查询所有受支持格式的列表:

  1. 请求通过调用 IWMDMDevice3::GetProperty 并传入 g_wszWMDMFormatsSupported 支持的所有格式代码的列表。 这会返回一个 PROPVARIANT, 其中包含受支持格式的 SAFEARRAY
  2. 通过调用 SafeArrayGetElement 遍历元素。 每个元素都是 一个WMDM_FORMATCODE 枚举。
  3. 请求每种格式的功能,并释放每个 WMDM_FORMAT_CAPABILITY 元素的内存。
  4. 通过调用 PropVariantClear 清除在步骤 1 中检索到 的 PROPVARIANT

以下 C++ 示例代码检索设备支持的格式列表。

// Query a device for supported configurations for each media or format type. 
HRESULT CWMDMController::GetCaps(IWMDMDevice3* pDevice)
{
    HRESULT hr = S_OK;

    // Request the "formats supported" property to get a list of supported formats.
    PROPVARIANT pvFormatsSupported;
    PropVariantInit(&pvFormatsSupported);
    hr = pDevice->GetProperty(g_wszWMDMFormatsSupported, &pvFormatsSupported);
    HANDLE_HR(hr, "Got a property list in GetCaps", "Couldn't get a property list in GetCaps.");

    // Loop through the retrieved format list.
    // For each format, get a list of format configurations.
    SAFEARRAY* formatList = pvFormatsSupported.parray;
    WMDM_FORMATCODE formatCode = WMDM_FORMATCODE_NOTUSED;
    for (LONG iCap = 0; iCap < formatList->rgsabound[0].cElements; iCap++)
    { 
        // Get a format from the SAFEARRAY of retrieved formats.
        SafeArrayGetElement(formatList, &iCap, &formatCode);

        // Call a custom function to request the format capabilities.
        if (formatCode != WMDM_FORMATCODE_NOTUSED)
            myGetFormatCaps(formatCode, pDevice);
    }

e_Exit:
    // Clear out the memory we used.
    PropVariantClear(&pvFormatsSupported);
    return hr;
}

发现设备格式功能