发出原始 AV/C 命令

[与此页面关联的功能 DirectShow 是一项旧功能。 它已被 MediaPlayerIMFMediaEngine媒体基金会中的音频/视频捕获取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

IAMExtDeviceIAMExtTransportIAMTimecodeReader 接口的工作原理是将方法调用转换为驱动程序的命令,然后解释驱动程序的响应并通过 HRESULT 或输出参数返回它。 但是,可能无法通过这些方法访问某些设备功能。 因此,MSDV 支持将原始 AV/C 命令发送到设备。

使用此功能时,应记住以下几点:

  • 命令直接传递到设备,无需进行错误检查或参数验证。 因此,仅当 DirectShow 接口未实现所需的功能时,才应发出原始 AV/C 命令。
  • 所有原始 AV/C 命令都是同步的。 发出命令的线程会阻塞,直到命令返回。
  • 一次只能提供一个命令。 在处理命令时,设备将拒绝任何其他命令。
  • UVC 驱动程序不支持原始 AV/C 命令。

若要发送 AV/C 命令,请将命令格式化为字节数组。 然后调用 IAMExtTransport::GetTransportBasicParameters。 传入ED_RAW_EXT_DEV_CMD标志、数组大小和数组。 必须将数组地址强制转换为 LPOLESTR* 类型,因为此参数的原始用途是返回字符串值。

BYTE AvcCmd[] = { ... }; // Contains the AV/C command (not shown)
long cbCmd = sizeof(AvcCmd);
hr = pTransport->GetTransportBasicParameters(
    ED_RAW_EXT_DEV_CMD, 
    &cbCmd,
    (LPOLESTR*) AvcCmd);

数组的内容将直接传递到设备,因此必须注意正确设置其格式。 命令可以将单元 (摄像机) 或子单元 (磁带或相机) 作为目标。 相关标准可从 1394贸易协会网站获得。

  • AV/C 数字接口命令集通用规范
  • AV/C 录音机/播放器子单元规范

前者介绍如何格式化 AV/C 命令并列出单元命令。 后一个规范列出了子单元命令。

GetTransportBasicParameters 方法可能会返回以下错误代码之一:

错误代码 说明
ERROR_TIMEOUT 命令超时。
ERROR_REQ_NOT_ACCEP 设备不接受命令。
ERROR_NOT_SUPPORTED 设备不支持 命令。
ERROR_REQUEST_ABORTED 命令已中止。 假设设备已删除或发生总线重置。

 

注意

这些错误以 Win32 错误代码而不是 HRESULT 的形式返回,因此应直接测试这些值,而不是使用 SUCCEEDEDFAILED 宏。

 

如果方法返回S_OK,则来自设备的响应将复制到 数组中。 响应有效负载可能大于命令,因此必须分配足够大的缓冲区来保存它。 最大有效负载大小为 512 字节。 请注意,S_OK的返回值并不总是意味着设备成功执行了命令。 应用程序必须检查响应有效负载以确定状态。

以下示例演示用于搜索绝对跟踪编号搜索的命令:

// Set up the ATN search command.
BYTE AvcCmd[] = 
{ 
    0x00,   // ctype = "control"
    0x20,   // subunit_type, subunit_id
    0x52,   // opcode (ATN)
    0x20,   // operand 0 = "search"
    0x00,   // operand 1 = ATN
    0x00,   // operand 2 = ATN
    0x00,   // operand 3 = ATN
    0xFF   //  operand 4 = D-VCR medium type.
};
// Specify a track number.
ULONG ulTrackNumber = track_number; // Specify the track number here.
// Shift over by 1 (LSB of operand 1 is a 1-bit blank flag)
ulTrackNumber = ulTrackNumber << 1; 
// Plug this number into operands 1 - 3.
AvcCmd[4] = (BYTE) (ulTrackNumber & 0x000000FF);
AvcCmd[5] = (BYTE)((ulTrackNumber & 0x0000FF00) >> 8);
AvcCmd[6] = (BYTE)((ulTrackNumber & 0x00FF0000) >> 16);

控制 DV 摄像机