The AudioVideoFlowclass has no public constructors, but instead relies on settings in an AudioVideoFlowTemplateinstance to initialize or modify an AudioVideoFlowinstance.

After an AudioVideoFlowTemplateinstance has been created, its settings can be copied to an AudioVideoFlowinstance by a call to the Initializemethod on the AudioVideoFlowclass. This initialization must occur within the body of a handler for the AudioVideoFlowConfigurationRequestedevent. Alternatively, an AudioVideoFlowTemplateinstance can be set and then passed in a call to the BeginApplyChangesmethod on the AudioVideoFlowclass.

AudioVideoFlowTemplateand AudioVideoFlowinstances are independent of one another. A new AudioVideoFlowTemplateinstance can be created each time an AudioVideoFlowinstance is to be set or modified, or a single AudioVideoFlowTemplateinstance can be used to set or modify multiple AudioVideoFlowinstances.

Initializing an AudioVideoFlow Instance

The technique of calling Initializeto initialize an AudioVideoFlowinstance can be used only when the AudioVideoFlowis in the Idlestate, and only within the body of a handler for the AudioVideoFlowConfigurationRequestedevent.

Copy Code
AudioVideoFlow _audioVideoFlow;
...

public void audioVideoCall_FlowConfigurationRequested(object
sender, AudioVideoFlowConfigurationRequestedEventArgs e)
{
  _audioVideoFlow = e.Flow;
  
  // Register an event handler for the StateChanged event.
  // When the flow becomes Active, as indicated by the StateChanged
event, the program will perform media-related actions.
  _audioVideoFlow.StateChanged += new
EventHandler<MediaFlowStateChangedEventArgs>(audioVideoFlow_StateChanged);

  // Change the default behavior before the negotiation is
completed.
  
  // Create a template based on the current AudioVideoFlow.
  AudioVideoFlowTemplate template = new
AudioVideoFlowTemplate(_audioVideoFlow);
		
  // Accept only 8Khz audio sampling rate codecs.
  template.Audio.Channels[ChannelLabel.AudioMono].SamplingRate =
AudioSamplingRate.EightKhz;
  // Change _audioVideoFlow settings according to the template.
  _audioVideoFlow.Initialize(template);
}

// Very simple handler for the StateChanged event.
void audioVideoCall_StateChanged(object sender,
CallStateChangedEventArgs e)
{
  Console.WriteLine("Call has changed state. The previous call
state was: " + e.PreviousState + " and the current state is: " +
e.State);
}
Important:
The AudioVideoFlowTemplateconstructor throws InvalidOperationExceptionif the state of its AudioVideoFlowparameter is in the Terminatedstate.

Modifying an AudioVideoFlowTemplate Instance

The settings of an AudioVideoFlowinstance can also be changed by a call to BeginApplyChanges.

In the following code example, which is shown only for purposes of illustration, it is assumed that AVCall, an AudioVideoCallinstance, previously has been created, and that the state of _audioVideoFlowis Active.

Copy Code
AudioVideoFlow _audioVideoFlow;
...

AudioVideoFlowTemplate AVFTemplate = new
AudioVideoFlowTemplate(AVCall.Flow);
AVFTemplate.EncryptionPolicy = MediaEncryption.Supported;
AVFTemplate.Audio.GetChannels()[ChannelLabel.AudioMono].AllowedDirection
= MediaChannelDirection.SendOnly;
_audioVideoFlow.BeginApplyChanges(AVFTemplate,
ApplyChangesCallback, null);

...

void ApplyChangesCallback(IAsyncResult asyncResult)
{
  try
  {
	_audioVideoFlow.EndApplyChanges(asyncResult);
  }
  catch
  {
	// handle exceptions
  }
}

Negotiation Between Local and Remote Endpoints

After an AudioVideoFlowinstance has been initialized or modified, negotiation with the remote participant is carried out. Settings such as HoldStatusand AllowedDirectionon the remote endpoint can affect the resulting AudioVideoFlowsettings. For example, if the application sets AllowedDirectionto MediaChannelDirection. SendReceive, but the remote has previously set AllowedDirectionto MediaChannelDirection. SendOnly, the Directionsetting on the local endpoint will become MediaChannelDirection. ReceiveOnly.

The following steps show the values of AllowedDirection, Direction, and HoldStatusafter negotiations have finished.

  1. The local endpoint sets AllowedDirectionto MediaChannelDirection. SendReceive, and HoldStatusis HoldType. None. On the remote endpoint, AllowedDirection= MediaChannelDirection. SendOnly.

    Result: Directionon the local endpoint will be set to MediaChannelDirection. ReceiveOnly.

  2. The local endpoint applies a hold to both ends, using a call to BeginHold( HoldType. BothEndpoints, , ).

    Results: AllowedDirectionis MediaChannelDirection. SendReceive, HoldStatusis set to HoldType. BothEndpoints, and Directionon the local endpoint will be set to MediaChannelDirection. Inactive.

  3. The local endpoint removes the hold, using a call to BeginRetrieve.

    Results: AllowedDirectionis MediaChannelDirection. SendReceive, HoldStatusis set to HoldType. None, and Directionon the local endpoint will depend on the response from the remote endpoint. If the remote endpoint responds with MediaChannelDirection. SendReceive, then Directionwill be set to MediaChannelDirection. SendReceive. If the remote endpoint responds with MediaChannelDirection. SendOnly(as in step 1), then Directionon the local endpoint will be set to MediaChannelDirection. ReceiveOnly.

In negotiation with a remote endpoint, if the local endpoint sends an offer that places a restriction on the media flow by a change in the direction or by placing a hold, it does not matter if the remote endpoint rejects the offer. On the other hand, if the local endpoint sends an offer that removes existing restrictions, it waits for the remote endpoint to accept or reject the offer.

Operations that mute a media flow do not require negotiation.