Behaviour
←Interoperability - NMOS IS-04 · Index↑ · Upgrade Path→
Start-Up Behaviour
This specification does not define the channel mapping behaviour at start-up, as this may depend on the nature of the Device the API is controlling. However, it is important that the channel mapping behaviour of the underlying Device is reflected in the API at start-up.
Interaction with Other Protocols
If the audio channel mapping behaviour of the Device is changed via another protocol or control interface the Device MUST update the information in the Channel Mapping API to accurately reflect the current behaviour of the Device.
Inputs and Outputs
The inputs
and outputs
resources enumerate the Inputs and Outputs respectively. Each Input and Output resource has a number of child resources.
Identifiers
Inputs and Outputs are represented by a unique identifier. This identifier MUST conform to the following regex pattern:
^[a-zA-Z0-9\-_]+$
All Input and Output identifiers MUST be immutable. Two Inputs MUST NOT share an identifier. Two Outputs MUST NOT share an identifier.
Properties
Inputs and Outputs MUST also provide a human-readable name and description in the properties
resource, intended to be exposed in control systems.
These are distinct from the machine readable unique identifier.
Output and Source Relationship
The sourceid
resource of an Output SHOULD be populated with a Source ID, if:
-
The output audio may be transmitted directly by an NMOS Sender belonging to the Device.
-
The output audio may be transformed by some process to create a new Source and/or Flow.
-
The Output is routed back to an Input of the Channel Mapping API (see Re-entrant Mappings).
Otherwise, the sourceid
MAY be set to null
.
In the case where no audio is currently routed to an Output (i.e all its entries in the active map are null
) then the Output still constitutes a Source, and as such the sourceid
resource for the Output SHOULD still present a Source ID where it would otherwise be required to do so.
Receiver / Source and Input Relationship
Where the audio associated with a Channel Mapping API Input comes directly from an NMOS Receiver, then the parent
resource of the Input is populated in one of two ways:
-
The ID of the originating Source SHOULD appear in the
id
field of theparent
resource if this information is available via some in-stream or out-of-band method. -
However, if information about the Source ID is not available, then the ID of the Receiver SHOULD appear in the
id
field of theparent
resource.
Where the received audio has undergone one or more Source-creating transformations between the Receiver and this Input, the id
field of the parent
resource SHOULD contain the ID of the immediate parent Source.
On the other hand, if the Input does not have an associated NMOS Receiver or Source, the id
field in the parent
resource SHOULD be set to null
.
When the id
contains a Source ID or Receiver ID, the type
field MUST be populated with the string source
or receiver
as appropriate.
When the id
is null
, the type
field MUST also be populated with null
.
For example, the following are all valid:
{
"id": "bdec047b-d161-492a-9496-96da704de2b1",
"type": "source"
}
{
"id": "a7250200-30ae-4866-9aeb-721f3f63f58d",
"type": "receiver"
}
{
"id": null,
"type": null
}
The parent
resource MUST be populated as specified even when the Input is not currently receiving audio from the parent Receiver or Source.
Channels
Inputs and Outputs MUST have at least one channel listed in their channels
resource. For some Devices the number of channels will be fixed - for example where an Input or Output represents a base-band connection to a Device such as analogue audio or AES3.
Other Devices may be capable of dynamically creating or destroying channels, for example where the Input or Output represents an audio stream. The Channel Mapping API does not provide a mechanism for changing the number of channels in an Input or Output resource - this must be done through an out-of-band operation by the user or automatically by the Device.
A change to the number of channels in an Input or Output MUST be represented in the Input’s or Output’s own channels
resource, but also MUST be represented in the global map/active
and map/activations
resources - and in the global io
resource.
Newly created Output channels SHOULD start unrouted, with the input
and channel_index
properties for the channel in the map table being set to null
. The decision as to which channels are deleted when the number of channels are removed is left as a decision to implementers, as it is likely to depend on the application of the Device.
Where a channel is added to or removed from an Output this represents the creation of a new Source.
Input Constraints
Inputs may optionally constrain the way the channels contained in the Input may be routed, using the parameters exposed in the caps
resource.
If a client attempts to create a mapping that would violate these constraints the API SHOULD return an HTTP 400 response. This response SHOULD contain a message informing the client that the request was rejected because it did not respect an input constraint and also provide information about which constraint was broken, and for which channels and Inputs, in order to aid debugging.
To illustrate Input constraints the following examples relate to mapping channels from 64-channel MADI (Multichannel Audio Digital Interface, AES10) Input onto a pair of 8-channel MADI Outputs.
Re-ordering
In some cases Inputs may not be capable of performing a re-ordering operation with their channels. In such cases the Channel Mapping API may be considered as a means of routing multiple channels of audio within a Device, rather than re-ordering channels, as in the following example:
If the Input is constrained in this way, i.e. it cannot perform re-ordering, the reordering
parameter in the Input’s caps
resource MUST be set to false
, and there MUST be a fixed offset for all Input and Output channel indexes in the mapping.
For example, the following two mappings are only permissible if reordering
is set to true
:
However, the following two examples would be permissible if reordering
is set to false
, as the difference in offsets occurs across two different Outputs;
the gap in the channels used from Input does not correspond to a gap within an Output. (However block constraints can make such an example not permitted – see below.)
Channel Block Sizes
Some Devices place a further constraint that channels must be treated as a discrete block from a given Input, where all channels in the block are expected to be routed together from a certain starting point, such that:
- It MUST be that either all Input channels in a block are routed to an Output, or none are routed.
- All Input channels in a block MUST be routed to the same Output when routed.
- An Input channel MUST only be in one block.
- All Input channels MUST be in a block.
- All blocks MUST be the same size.
- All blocks MUST start with an input channel where
channel_index
is zero or a multiple of theblock_size
parameter.
Where an Input is constrained in this way the block_size
parameter in the Input’s caps
resource MUST be an integer indicating the block size that is in use for that Input and the resulting Input Channel start. Otherwise the block_size
parameter MUST be set to 1
.
Consider a case where the specific architecture of a given MADI Card only allows processing of Input channels in blocks. The MADI channel numbers and corresponding Input channel_index
values of these blocks are 0
-7
, or 8
-15
, or 16
-23
, and so on.
The following examples would be permissible, where a block_size
value of 8
is used:
The following examples would not be permissible:
Combining Input Constraints
The block_size
and reordering
parameters may both be used at the same time, to express a constraint where channels must be treated as blocks, and re-ordering in those blocks is not permitted. For example, the following would no longer be permitted when using a block_size
of 8
when the reordering
parameter is set to false
:
Output Routing Constraints
It is recognised that not all Devices allow the routing of channels in any Input to any Output. In order to reflect this limitation, the Output caps
resource presents a list of routable Inputs in the routable_inputs
field. If such restrictions exist then they MUST be populated by the Device, such that if an Input is listed in an Output’s routable input list then channels from that input can be routed to that Output in the Map table, and if the Device allows the Output to have unrouted channels, the list SHOULD also include null
. If no such restrictions exist, the routable_inputs
field MUST be set to null
.
Clients SHOULD NOT attempt to route channels from Inputs to an Output unless that Input is listed in the Output’s routable_inputs
array. If a client attempts to make such a route the API SHOULD respond with an HTTP 400 response. This error message SHOULD inform the client that it attempted to make an illegal route, and which inputs/outputs were involved in the illegal route.
Map
The map
resource has child resources that represent the Active Map and any pending Activations.
The Active Map
The active
resource contain a structure called map
, which looks like the following:
"map":{
"outA":{
"0" :{
"input": "input1",
"channel_index": 0
},
"1":{
"input": "input1",
"channel_index": 1
}
},
"outB":{
"0":{
"input": "input4",
"channel_index": 0
},
"1":{
"input": null,
"channel_index": null
}
}
}
The keys in the map object are the identifiers of all the Outputs in the API. Every Output has an object within the map
object to represent it. Keys within an Output object represent channels in the Output, and are the JSON array index of the channel in the Output’s channels
resource.
Each channel contains two fields - input
and channel_index
. channel_index
is the JSON array index of the Input channel routed to that Output channel, as indicated by the Input’s channels
resource. input
is the identifier of the Input to which the routed channel belongs.
If no Input channel is being routed to an Output channel, both input
and channel_index
MUST be set to null
.
Where an Output does not have a channel routed to it the Device MUST interpret this as silence, and produce a silent signal of appropriate bit depth and bit rate from that output.
Activation Requests
Activations are the mechanism by which changes are made to the active
resource. Activations can either be immediate or scheduled.
In either case an activation is initiated by performing a POST request to the activations
endpoint.
When POSTing to the activations
resource clients MUST use a subset of the map resource, such that only the entries to be updated are included. The API MUST leave values not expressly updated in the POST request unchanged by the activation.
The submission of a scheduled activation MUST NOT result in any changes to the Device audio channel mapping behaviour until the activation time is reached.
The client POST request contains activation
and active
objects that indicate when and what is to be changed respectively.
The Device MUST undertake to apply the parameter changes to the underlying audio processing as close as possible to the time indicated by the mode
property in the activation
object, as follows:
activate_immediate
- on message receiptactivate_scheduled_absolute
- the absolute time indicated by therequested_time
fieldactivate_scheduled_relative
- the relative time after message receipt indicated by therequested_time
field
See the Timestamps section for more details on the required interpretation of the timestamps for scheduled activations.
Once an activation has been completed the resulting changes to the map MUST be reflected in the active
endpoint. The activation
object in the active
endpoint MUST contain the details of the last activation to have taken place.
Activation Responses
Each successful activation request is allocated a unique identifier by the API. This identifier MUST be unique within an API instance and for all time.
Pending scheduled activations, along with their ID, are listed in the activations
resource until they activate. Once activated they MUST be removed from the resource. Immediate activations MUST NOT appear in the activations
list, as they are carried out upon arrival.
The unique identifier is returned as part of the activation response, to allow the client to cancel scheduled activations if required.
Note the presence of the extra activation_time
parameter in the response schema. For immediate activation this SHOULD be the time the activation actually occurred as an absolute TAI timestamp.
An HTTP 200 response MUST be returned when an immediate activation has been successfully requested. For a request with an immediate activation the API SHOULD only return a response once the new map has been applied to the audio.
An HTTP 202 response MUST be returned when a request for a scheduled activation is accepted, to indicate that while the request itself was acceptable it has not yet been acted upon by the device. For scheduled activations activation_time
SHOULD be the absolute TAI time the parameters will actually transition. For absolute scheduled activations, it SHOULD be the same as the requested time, but may differ if the Device is unable to schedule at the requested time.
When there is an error in the request, the API MUST reject the entire request with an appropriate 4xx response. Particular responses MUST be used in the following cases:
Error | HTTP Response |
---|---|
Output is modified by an already scheduled activation. | 423 (Locked) |
Routing request not permitted by Input or Output constraints. | 400 (Bad Request) |
One field of Output channel object is null but other is not. |
400 (Bad Request) |
Canceling Activations
A client cancels an activation by submitting a DELETE request to the resource /map/activations/{activationId}
. If the activation has already been completed the API MUST respond with an HTTP 404 error response, as the activation no longer exists.
Timestamps
Timestamps indicate the absolute or relative time for activation and MUST be string formatted as <seconds>:<nanoseconds>
. Absolute timestamps MUST be based on TAI (which does not apply leap seconds) and must use SMPTE epoch (meaning 1970-01-01 00:00:00 TAI would be represented as 0:0
).
Devices receiving their time references in UTC MUST maintain an up-to-date knowledge of when leap seconds will be applied in order to correctly calculate TAI time. Leap seconds are announced by the International Earth Rotation and Reference System Service (IERS) and the IETF publish an adjustment table.
Re-entrant Mappings
Some Devices have more complex routing requirements. For example, a Device may have a large number of channels on an input, but restrictions in DSP capacity may mean that only a limited sub-set of these channels can be routed at any given time. For example, the Device illustrated below has a 64 channel MADI Input, but a limited number of MADI cards, meaning it can only process 16 of the 64 channels at any one time. Any of the outputs of the MADI cards can then be routed to a two channel AES67 output.
In this example we indicate which inputs can be routed to the AES67 output with /outputs/aes67/caps
as follows:
{
"routable_inputs": [
"madi-a",
"madi-b"
]
}
And the re-entrant mapping is represented with /map/active/aes67
:
{
"aes67":{
"0":{
"input": "madi-b",
"channel_index": 0
},
"1":{
"input": "madi-b",
"channel_index": 2
}
}
}
In this scenario the audio undergoes two distinct routing operations - the first from the MADI input to the MADI card, and then a second from the MADI card to the AES67 output. In order to allow for these kinds of restrictions the Channel Mapping API supports re-entrant mappings, in which audio at an Output may be routed back to an Input. This is signaled to the control system by the same Source ID being present in both the Output’s sourceid
resource and also the Input’s parent
resource.
Where this is done, Output constraints MUST prevent audio being routed back to the Output from which it originated.
Inputs/Outputs View
The io
resource provides a single response detailing all Inputs, Outputs and available mappings between them.
The object returned from this resource contains an inputs
object and an outputs
object. These two objects contain objects representing each of the Inputs and Outputs. Each Input and Output object MUST contain properties corresponding to the child resources described in Inputs and Outputs, with matching values.