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

지정된 ACXCIRCUIT와 연결된 WDFDEVICE 개체( WDF - 프레임워크 개체 요약에 설명됨)입니다.

Circuit

새 스트림 instance 연결된 ACXCIRCUIT 개체입니다. ACX 개체에 대한 자세한 내용은 ACX 개체 요약을 참조하세요.

Pin

새 스트림 instance 연결된 ACXPIN ACX 개체입니다.

StreamInit

ACXSTREAM_INIT ACX 개체입니다. 이는 스트림 초기화를 정의하는 데 사용되는 불투명 구조체입니다.

StreamFormat

스트림 데이터 형식을 정의하는 ACXDATAFORMAT ACX 개체입니다.

SignalProcessingMode

새 스트림 회로의 오디오 신호 처리 모드를 식별하는 GUID입니다. 오디오 모드에 대한 자세한 내용은 오디오 신호 처리 모드를 참조하세요.

VarArguments

스트림을 초기화하는 데 사용할 추가 인수를 포함하는 선택적 ACXOBJECTBAG 개체입니다.

반환 값

호출이 성공하면 를 반환합니다 STATUS_SUCCESS . 그렇지 않으면 적절한 오류 코드를 반환합니다. 자세한 내용은 NTSTATUS 값 사용을 참조하세요.

설명

Stream 만들기의 첫 번째 단계는 엔드포인트 오디오 경로의 각 ACXCIRCUIT에 대한 ACXSTREAM instance 만드는 것입니다. ACX는 각 회로의 EvtAcxCircuitCreateStream을 호출합니다. ACX는 헤드 회로로 시작하고 각 회로의 CreateStream을 순서대로 호출하여 꼬리 회로로 끝납니다.

드라이버는 체인의 다음 회로가 호출되기 전이나 후에 초기화를 수행할 수 있습니다. 자세한 내용은 ACXSTREAMBRIDGE 개체를 참조하세요.

Stream 생성 요청은 헤드 회로를 만드는 동안 지정된 EvtAcxCircuitCreateStream을 호출하여 헤드 회로 토폴로지 생성의 일부로 노출된 적절한 ACXPIN으로 전송됩니다.

스트림 만들기 콜백을 수신하는 드라이버는 다음 작업을 수행합니다.

  • ACX 정의 DDI(AcxStreamInit*)를 사용하여 ACXSTREAM_INIT 불투명 구조를 초기화합니다.
  • AcxStreamCreate 또는 AcxRtStreamCREAte ACX DDI를 사용하여 ACXSTREAM 개체를 만듭니다. AcxRtStreamCreate는 상위 사용자 모드 오디오 파이프라인에 연결된 ACXPIN 스트리밍에만 사용되며, 엔드포인트 경로의 다른 모든 회로는 AcxStreamCreate DDI를 대신 사용해야 합니다.
  • 스트림별 요소(예: ACXAUDIOENGINE)를 만듭니다.
  • ACXSTREAM 개체에 요소를 추가합니다.
  • 스트림 만들기 콜백이 성공적으로 완료되었음을 나타내기 위해 STATUS_SUCCESS 반환합니다.

오디오 경로의 회로 간 스트림 통신 채널은 ACXTARGETSTREAM 개체를 사용합니다.

기본 대상 회로가 ACXSTREAM 개체를 만들면 각 회로에 스트림에 대한 회로별 처리를 수행할 수 있는 기회가 제공됩니다. 각 회로는 다음 작업 중 하나 이상을 수행합니다.

  • 스트림 드라이버별 구성 또는 데이터를 사용하여 ACXSTREAM에 Context 개체를 만들고 추가합니다.
  • 제어를 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 버전 개요를 참조하세요.

요구 사항

요구 사항
헤더 acxcircuit.h
IRQL PASSIVE_LEVEL

추가 정보