Using an AudioVideoFlowTemplate

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

The AudioVideoFlow class has no public constructors, but instead relies on settings in an AudioVideoFlowTemplate instance to initialize or modify an AudioVideoFlow instance.

After an AudioVideoFlowTemplate instance has been created, its settings can be copied to an AudioVideoFlow instance by a call to the Initialize() method on the AudioVideoFlow class. This initialization must occur within the body of a handler for the AudioVideoFlowConfigurationRequested event. Alternatively, an AudioVideoFlowTemplate instance can be set and then passed in a call to the BeginApplyChanges() method on the AudioVideoFlow class.

AudioVideoFlowTemplate and AudioVideoFlow instances are independent of one another. A new AudioVideoFlowTemplate instance can be created each time an AudioVideoFlow instance is to be set or modified, or a single AudioVideoFlowTemplate instance can be used to set or modify multiple AudioVideoFlow instances.

Initializing an AudioVideoFlow Instance

The technique of calling Initialize() to initialize an AudioVideoFlow instance can be used only when the AudioVideoFlow is in the Idle state, and only within the body of a handler for the AudioVideoFlowConfigurationRequested event.

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 AudioVideoFlowTemplate constructor throws InvalidOperationException if the state of its AudioVideoFlow parameter is in the Terminated state.

Modifying an AudioVideoFlowTemplate Instance

The settings of an AudioVideoFlow instance 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 AudioVideoCall instance, previously has been created, and that the state of _audioVideoFlow is Active.

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 AudioVideoFlow instance has been initialized or modified, negotiation with the remote participant is carried out. Settings such as HoldStatus and AllowedDirection on the remote endpoint can affect the resulting AudioVideoFlow settings. For example, if the application sets AllowedDirection to MediaChannelDirection.SendReceive, but the remote has previously set AllowedDirection to MediaChannelDirection.SendOnly, the Direction setting on the local endpoint will become MediaChannelDirection.ReceiveOnly.

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

  1. The local endpoint sets AllowedDirection to MediaChannelDirection.SendReceive, and HoldStatus is HoldType.None. On the remote endpoint, AllowedDirection = MediaChannelDirection.SendOnly.

    Result: Direction on 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: AllowedDirection is MediaChannelDirection.SendReceive, HoldStatus is set to HoldType.BothEndpoints, and Direction on the local endpoint will be set to MediaChannelDirection.Inactive.

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

    Results: AllowedDirection is MediaChannelDirection.SendReceive, HoldStatus is set to HoldType.None, and Direction on the local endpoint will depend on the response from the remote endpoint. If the remote endpoint responds with MediaChannelDirection.SendReceive, then Direction will be set to MediaChannelDirection.SendReceive. If the remote endpoint responds with MediaChannelDirection.SendOnly (as in step 1), then Direction on 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.