EVT_ACX_CIRCUIT_CREATE_STREAM回调函数 (acxcircuit.h)

驱动程序定义 EVT_ACX_CIRCUIT_CREATE_STREAM 回调来创建线路流实例。

语法

EVT_ACX_CIRCUIT_CREATE_STREAM EvtAcxCircuitCreateStream;

NTSTATUS EvtAcxCircuitCreateStream(
  WDFDEVICE Device,
  ACXCIRCUIT Circuit,
  ACXPIN Pin,
  PACXSTREAM_INIT StreamInit,
  ACXDATAFORMAT StreamFormat,
  const GUID *SignalProcessingMode,
  ACXOBJECTBAG VarArguments
)
{...}

参数

Device

WDFDEVICE 对象 (WDF - 与指定 ACXCIRCUIT 关联的框架对象) 摘要中所述。

Circuit

与新流实例关联的 ACXCIRCUIT 对象。 有关 ACX 对象的详细信息,请参阅 ACX 对象的摘要

Pin

与新流实例关联的 ACXPIN ACX 对象。

StreamInit

ACXSTREAM_INIT ACX 对象。 这是一个不透明的结构,用于定义流初始化。

StreamFormat

一个 ACXDATAFORMAT ACX 对象,用于定义流数据格式。

SignalProcessingMode

标识新流线路的音频信号处理模式的 GUID。 有关音频模式的详细信息,请参阅 音频信号处理模式

VarArguments

可选的 ACXOBJECTBAG 对象,其中包含要用于初始化流的附加参数。

返回值

STATUS_SUCCESS如果调用成功,则返回 。 否则,它将返回相应的错误代码。 有关详细信息,请参阅 使用 NTSTATUS 值

注解

Stream创建的第一步是为终结点音频路径中的每个 ACXCIRCUIT 创建 ACXSTREAM 实例。 ACX 将调用每个线路的 EvtAcxCircuitCreateStream。 ACX 将从头电路开始,并按顺序调用每个线路的 CreateStream,以尾部线路结束。

驱动程序有机会在调用链中的下一个线路之前或之后执行任何初始化,有关详细信息,请参阅 ACXSTREAMBRIDGE 对象。

Stream创建请求通过调用头电路创建期间指定的 EvtAcxCircuitCreateStream,发送到作为头电路拓扑生成的一部分公开的相应 ACXPIN。

接收流创建回调的驱动程序执行以下操作:

  • ACXSTREAM_INIT 它通过使用 ACX 定义的 DDI (AcxStreamInit*)
  • 它使用 AcxStreamCreate 或 AcxRtStreamCreate ACX DDI 创建 ACXSTREAM 对象。 AcxRtStreamCreate 仅用于流式处理连接到上层用户模式音频管道的 ACXPIN,终结点路径的所有其他线路必须改用 AcxStreamCreate DDI。
  • 它创建任何特定于流的元素,例如 ACXAUDIOENGINE。
  • 它将元素添加到 ACXSTREAM 对象。
  • 它返回STATUS_SUCCESS指示流创建回调成功完成。

音频路径中线路之间的流通信通道使用 ACXTARGETSTREAM 对象。

默认目标线路创建 ACXSTREAM 对象后,每个线路都有机会对流执行特定于线路的处理。 每个线路依次执行以下一个或多个操作:

  • 使用特定于流驱动程序的配置或数据创建上下文对象并将其添加到 ACXSTREAM。
  • 将控制权返回到 ACX 框架,该框架将对终结点音频路径中的下一个线路执行相同的操作。

示例

示例用法如下所示。

    status = AcxCircuitInitAssignAcxCreateStreamCallback(
                                            circuitInit, 
                                            CodecC_EvtCircuitCreateStream);

NTSTATUS
CodecC_EvtCircuitCreateStream(
    _In_    WDFDEVICE       Device,
    _In_    ACXCIRCUIT      Circuit,
    _In_    ACXPIN          Pin,
    _In_    PACXSTREAM_INIT StreamInit,
    _In_    ACXDATAFORMAT   StreamFormat,
    _In_    const GUID    * SignalProcessingMode,
    _In_    ACXOBJECTBAG    VarArguments
    )
/*++

Routine Description:

    This routine creates a stream for the specified circuit.

Return Value:

    NT status value

--*/
{
    NTSTATUS                        status;
    PCODEC_CAPTURE_DEVICE_CONTEXT   devCtx;
    WDF_OBJECT_ATTRIBUTES           attributes;
    ACXSTREAM                       stream;
    CODEC_STREAM_CONTEXT *          streamCtx;
    ACXELEMENT                      elements[2] = {0};
    ACX_ELEMENT_CONFIG              elementCfg;
    CODEC_ELEMENT_CONTEXT *         elementCtx;
    ACX_STREAM_CALLBACKS            streamCallbacks;
    ACX_RT_STREAM_CALLBACKS         rtCallbacks;
    CCaptureStreamEngine *          streamEngine = NULL;
    CODEC_CAPTURE_CIRCUIT_CONTEXT * circuitCtx;
    CODEC_PIN_CONTEXT *             pinCtx;

    PAGED_CODE();
    UNREFERENCED_PARAMETER(SignalProcessingMode);
    UNREFERENCED_PARAMETER(VarArguments);

    ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW));

    devCtx = GetCaptureDeviceContext(Device);
    ASSERT(devCtx != NULL);

    circuitCtx = GetCaptureCircuitContext(Circuit);
    ASSERT(circuitCtx != NULL);

    pinCtx = GetCodecPinContext(Pin);
    ASSERT(pinCtx != NULL);

    //
    // Set circuit-callbacks.
    //
    status = AcxStreamInitAssignAcxRequestPreprocessCallback(
                                            StreamInit, 
                                            CodecC_EvtStreamRequestPreprocess,
                                            (ACXCONTEXT)AcxRequestTypeAny, // dbg only
                                            AcxRequestTypeAny,
                                            NULL, 
                                            AcxItemIdNone);
    if (!NT_SUCCESS(status)) 
    {
        ASSERT(FALSE);
        goto exit;
    }

    /*
    //
    // Add properties, events and methods.
    //
    status = AcxStreamInitAssignProperties(StreamInit,
                                         StreamProperties,
                                         StreamPropertiesCount);
    */

    //
    // Init streaming callbacks.
    //
    ACX_STREAM_CALLBACKS_INIT(&streamCallbacks);
    streamCallbacks.EvtAcxStreamPrepareHardware     = Codec_EvtStreamPrepareHardware;
    streamCallbacks.EvtAcxStreamReleaseHardware     = Codec_EvtStreamReleaseHardware;
    streamCallbacks.EvtAcxStreamRun                 = Codec_EvtStreamRun;
    streamCallbacks.EvtAcxStreamPause               = Codec_EvtStreamPause;

    status = AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks);
    if (!NT_SUCCESS(status))
    {
        ASSERT(FALSE);
        goto exit;
    } 

    //
    // Init RT streaming callbacks.
    //
    ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks);
    rtCallbacks.EvtAcxStreamGetHwLatency            = Codec_EvtStreamGetHwLatency;
    rtCallbacks.EvtAcxStreamAllocateRtPackets       = Codec_EvtStreamAllocateRtPackets;
    rtCallbacks.EvtAcxStreamFreeRtPackets           = Codec_EvtStreamFreeRtPackets;
    rtCallbacks.EvtAcxStreamGetCapturePacket        = CodecC_EvtStreamGetCapturePacket;
    rtCallbacks.EvtAcxStreamGetCurrentPacket        = Codec_EvtStreamGetCurrentPacket;
    rtCallbacks.EvtAcxStreamGetPresentationPosition = Codec_EvtStreamGetPresentationPosition;

    status = AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks);
    if (!NT_SUCCESS(status))
    {
        ASSERT(FALSE);
        goto exit;
    }
    
    //
    // Buffer notifications are supported.
    //
    AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit);
    
    //
    // Create the stream.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_STREAM_CONTEXT);   

    attributes.EvtDestroyCallback = Codec_EvtStreamDestroy;

    status = AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream);
    if (!NT_SUCCESS(status)) 
    {
        ASSERT(FALSE);
        goto exit;
    }

    streamCtx = GetCodecStreamContext(stream);
    ASSERT(streamCtx);

    if (pinCtx->CodecPinType == CodecPinTypeKeyword)
    {
        PCODEC_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx;

        keywordSpotterCtx = GetCodecKeywordSpotterContext(circuitCtx->KeywordSpotter);

        streamEngine = new(NonPagedPoolNx, DRIVER_TAG) CBufferedCaptureStreamEngine(stream, StreamFormat, (CKeywordDetector *) keywordSpotterCtx->KeywordDetector);
        if (streamEngine == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            ASSERT(FALSE);
            goto exit;
        }
    }
    else
    {
        streamEngine = new(NonPagedPoolNx, DRIVER_TAG) CCaptureStreamEngine(stream, StreamFormat);
        if (streamEngine == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            ASSERT(FALSE);
            goto exit;
        }
    }

    streamCtx->StreamEngine = (PVOID)streamEngine;
    streamEngine = NULL;

    //
    // Post stream creation initialization.
    // Create any custom stream-elements.
    // Add stream elements

ACX 要求

最低 ACX 版本: 1.0

有关 ACX 版本的详细信息,请参阅 ACX 版本概述

要求

要求
Header acxcircuit.h
IRQL PASSIVE_LEVEL

另请参阅