Condividi tramite


EVT_ACX_CIRCUIT_CREATE_STREAM funzione di callback (acxcircuit.h)

Il driver definisce il callback EVT_ACX_CIRCUIT_CREATE_STREAM per creare istanze del flusso di circuito.

Sintassi

EVT_ACX_CIRCUIT_CREATE_STREAM EvtAcxCircuitCreateStream;

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

Parametri

Device

Oggetto WDFDEVICE (descritto in WDF - Riepilogo degli oggetti framework) associato all'oggetto ACXCIRCUIT specificato.

Circuit

Oggetto ACXCIRCUIT associato alla nuova istanza del flusso. Per altre informazioni sugli oggetti ACX, vedere Riepilogo degli oggetti ACX.

Pin

Oggetto ACXPIN ACX associato alla nuova istanza del flusso.

StreamInit

Oggetto ACX ACXSTREAM_INIT. Si tratta di una struttura opaca, usata per definire l'inizializzazione del flusso.

StreamFormat

Oggetto ACXDATAFORMAT ACX che definisce il formato di dati del flusso.

SignalProcessingMode

GUID che identifica la modalità di elaborazione del segnale audio del nuovo circuito di flusso. Per altre informazioni sulle modalità audio, vedere modalità di elaborazione del segnale audio.

VarArguments

Oggetto ACXOBJECTBAG facoltativo contenente argomenti aggiuntivi da utilizzare per inizializzare il flusso.

Valore restituito

Restituisce STATUS_SUCCESS se la chiamata ha avuto esito positivo. In caso contrario, restituisce un codice di errore appropriato. Per altre informazioni, vedere Uso di valori NTSTATUS.

Osservazioni

Il primo passaggio della creazione di flussi consiste nel creare l'istanza ACXSTREAM per ogni ACXCIRCUIT nel percorso audio dell'endpoint. ACX chiamerà EvtAcxCircuitCreateStream di ogni circuito. ACX inizierà con il circuito head e chiamerà createStream di ogni circuito in ordine, terminando con il circuito di coda.

I driver hanno la possibilità di eseguire qualsiasi inizializzazione prima o dopo che viene richiamato il circuito successivo nella catena, fare riferimento all'oggetto ACXSTREAMBRIDGE per altre informazioni.

La richiesta di creazione del flusso viene inviata all'oggetto ACXPIN appropriato esposto come parte della generazione della topologia del circuito head chiamando evtAcxCircuitCreateStream specificato durante la creazione del circuito head.

Il driver che riceve il callback di creazione del flusso esegue le operazioni seguenti:

  • Inizializza la struttura opaca ACXSTREAM_INIT usando le DDI definite da ACX (AcxStreamInit*)
  • Crea l'oggetto ACXSTREAM usando AcxStreamCreate o AcxRtStreamCreate ACX DDI. AcxRtStreamCreate viene usato solo per lo streaming ACXPIN connesso alla pipeline audio in modalità utente superiore, tutti gli altri circuiti del percorso dell'endpoint devono usare invece acxStreamCreate DDI.
  • Crea tutti gli elementi specifici del flusso, ad esempio ACXAUDIOENGINE.
  • Aggiunge gli elementi all'oggetto ACXSTREAM.
  • Restituisce STATUS_SUCCESS per indicare che il callback di creazione del flusso è stato completato correttamente.

Il canale di comunicazione del flusso tra circuiti in un percorso audio usa oggetti ACXTARGETSTREAM.

Dopo che il circuito di destinazione predefinito crea l'oggetto ACXSTREAM, a ogni circuito verrà data l'opportunità di eseguire la gestione specifica del circuito per il flusso. Ogni circuito a sua volta esegue una o più delle azioni seguenti:

  • Creare e aggiungere un oggetto Context a ACXSTREAM con dati o configurazione specifici del driver di flusso.
  • Tornare al framework ACX, che eseguirà la stessa azione con il circuito successivo nel percorso audio dell'endpoint.

Esempio

Di seguito è riportato un esempio di utilizzo.

    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

Requisiti ACX

versione minima di ACX: 1.0

Per altre informazioni sulle versioni di ACX, vedere panoramica della versione ACX.

Fabbisogno

Requisito Valore
intestazione acxcircuit.h
IRQL PASSIVE_LEVEL

Vedere anche