From OpenHome

(Difference between revisions)
Jump to: navigation, search
(Message Format)
 
(107 intermediate revisions not shown)
Line 5: Line 5:
OHM and OHU, together with [[Av:Developer:Songcast:Ohz|OHZ]], form the Songcast family of OpenHome protocols for transporting audio around a home network.
OHM and OHU, together with [[Av:Developer:Songcast:Ohz|OHZ]], form the Songcast family of OpenHome protocols for transporting audio around a home network.
-
* OHM provides large scale one to many communication using multicast UDP.  
+
* OHM provides large scale one to many communication using Multicast UDP.  
-
* OHU provides small scale one to many communication using unicast UDP.
+
* OHU provides small scale one to many communication using Unicast UDP.
-
OHU can be used to deliver Songcast functionality to networks that do not control multicast UDP to the level required by OHM.
+
OHU can be used to deliver Songcast functionality to networks that do not handle Multicast UDP as thoroughly as OHM requires.
-
== Message Format ==
+
== General ==
 +
=== Message Format ===
The OHM and OHU protocols share the same message format.
The OHM and OHU protocols share the same message format.
-
{| border="1"  
+
{| border="1" cellpadding="3" style="background-color:#ffffcc;"  
! Bytes
! Bytes
! Name
! Name
! Description
! Description
 +
|- align="left" style="color:#ffffff; background-color:#008833;"
 +
| Header
 +
|
 +
|
|-
|-
-
|| Header
+
| 4
 +
| Signature
 +
| 0x6f, 0x68, 0x6d, 0x20 ('ohm ')
|-
|-
-
|| 4
+
| 1
-
|| Signature
+
| Version
-
|| 0x6f, 0x68, 0x6d, 0x20 ('ohm ')
+
| 1
|-
|-
-
|| 1
+
| 1
-
|| Version
+
| Type
-
|| 1
+
| The type of message
|-
|-
-
|| 1
+
|
-
|| Type
+
|  
-
|| The type of message
+
| 0 - Join
|-
|-
-
|| Join
+
|
-
|| 0
+
|
 +
| 1 - Listen
|-
|-
-
|| Listen
+
|
-
|| 1
+
|
 +
| 2 - Leave
|-
|-
-
|| Leave
+
|
-
|| 2
+
|
 +
| 3 - Audio (details below)
|-
|-
-
|| Audio
+
|
-
|| 3
+
|
 +
| 4 - Track  (details below)
|-
|-
-
|| Track
+
|
-
|| 4
+
|
 +
| 5 - Metatext  (details below)
|-
|-
-
|| Metatext
+
|
-
|| 5
+
|
 +
| 6 - Slave  (details below)
|-
|-
-
|| Slave
+
| 2
-
|| 6
+
| Length
 +
| The length in bytes of the whole message including this header
|-
|-
-
|| 2
+
|
-
|| Length
+
| Minimum
-
|| The length in bytes of the whole message including the header
+
| 8
|-
|-
-
|| Minimum
+
|
-
|| 8
+
| Maximum
 +
| 16392
 +
|- align="left" style="color:#ffffff; background-color:#008833;"
 +
| Audio
 +
|
 +
|
|-
|-
-
|| Maximum
+
| 1
-
|| 16392
+
| AudioHeaderLength
 +
| 50
|-
|-
-
|| Audio
+
| 1
 +
| Flags
 +
| Bit 0 - halt
|-
|-
-
|| 1
+
|  
-
|| AudioHeaderLength
+
|  
-
|| 50
+
| Bit 1 - lossless
|-
|-
-
|| 1
+
|  
-
|| Flags
+
|  
-
|| Bit 0 - halt
+
| Bit 2 - timestamped
|-
|-
-
||  
+
|  
-
||  
+
|  
-
|| Bit 1 - lossless
+
| Bit 3 - resent
|-
|-
-
||  
+
|  
-
||  
+
|  
-
|| Bit 2 - timestamped
+
| Bit 4 - 0
|-
|-
-
||  
+
|  
-
||  
+
|  
-
|| Bit 3 - 0
+
| Bit 5 - 0
|-
|-
-
||  
+
|  
-
||  
+
|  
-
|| Bit 4 - 0
+
| Bit 6 - 0
|-
|-
-
||  
+
|  
-
||  
+
|  
-
|| Bit 5 - 0
+
| Bit 7 - 0
|-
|-
-
||
+
| 2
-
||
+
| SampleCount
-
|| Bit 6 - 0
+
| The number of samples in this frame
|-
|-
-
||
+
| 4
-
||
+
| Frame
-
|| Bit 7 - 0
+
| The frame number
|-
|-
-
|| 2
+
| 4
-
|| SampleCount
+
| NetworkTimestamp
-
|| The number of samples in this frame
+
| The time when the previous frame was sent over the network (if the timestamped flag is on)
|-
|-
-
|| 4
+
| 4
-
|| Frame
+
| MediaLatency
-
|| The frame number
+
| The duration of the Sender's audio buffer
|-
|-
-
|| 4
+
| 4
-
|| NetworkTimestamp
+
| MediaTimestamp
-
|| The time when the previous frame was sent over the network (if the timestamped flag is on)
+
| The time when this frame was placed into an audio buffer of duration <tt>MediaLatency</tt> on the Sender (if the timestamped flag is on)
|-
|-
-
|| 4
+
| 8
-
|| MediaLatency
+
| StartSample
-
|| The length in milliseconds of the audio buffer
+
| The sample number within the current track of the first sample in this frame
|-
|-
-
|| 4
+
| 8
-
|| MediaTimestamp
+
| TotalSamples
-
|| The time when this frame was placed into the audio buffer {if the timestamp flag is on)
+
| The total number of samples in the current track
|-
|-
-
|| 8
+
| 4
-
|| StartSample
+
| SampleRate
-
|| The sample number within the current track of the first sample in this frame
+
| The sample rate in samples per second
|-
|-
-
|| 8
+
| 4
-
|| TotalSamples
+
| BitRate
-
|| The total number of samples in the current track
+
| The bit rate in bits per second
|-
|-
-
|| 4
+
| 2
-
|| SampleRate
+
| VolumeOffset
-
|| The sample rate in samples per second
+
| The volume offset in signed binary milli-dB (+/- 32dB)
|-
|-
-
|| 4
+
| 1
-
|| BitRate
+
| BItDepth
-
|| The bit rate in bits per second
+
| The bit depth (8, 16, or 24)
|-
|-
-
|| 2
+
| 1
-
|| VolumeOffset
+
| Channels
-
|| The volume offset in signed binary milli-dB (+/- 32dB)
+
| The number of interleaved audio channels
|-
|-
-
|| 1
+
| 1
-
|| BItDepth
+
| AudioReserved
-
|| The bit depth (8, 16, or 24)
+
| 0
|-
|-
-
|| 1
+
| 1
-
|| Channels
+
| CodecNameLength
-
|| The number of interleaved audio channels
+
| The number of bytes in the name of the codec
|-
|-
-
|| 1
+
| m
-
|| AudioReserved
+
| CodecName
-
|| 0
+
| The codec name (in UTF-8), where m = CodecNameLength
|-
|-
-
|| 1
+
| n
-
|| CodecNameLength
+
| Pcm
-
|| The number of bytes in the name of the codec
+
| Pcm samples, where n = Channels * BitDepth * SampleCount / 8
 +
|- align="left" style="color:#ffffff; background-color:#008833;"
 +
| Track
 +
|
 +
|
|-
|-
-
|| m
+
| 4
-
|| CodecName
+
| TrackSequence
-
|| The codec name (in UTF-8), where m = AudioCodecLength
+
| Sequence number for this track.
|-
|-
-
|| n
+
| 4
-
|| Pcm
+
| TrackUriLength
-
|| Pcm samples, where n = AudioChannels * AudioBitDepth * AudioSampleCount / 8
+
| The length in bytes of the track URI
|-
|-
-
|| Track
+
| 4
 +
| TrackMetadataLength
 +
| The length in bytes of the track metadata
|-
|-
-
|| 4
+
| p
-
|| TrackUriLength
+
| TrackUri
-
|| The length in bytes of the track uri.
+
| The track URI, where p = TrackUriLength
|-
|-
-
|| 4
+
| q
-
|| TrackMetadataLength
+
| TrackMetadata
-
|| The length in bytes of the track metadata
+
| The track metadata in DIDL-Lite format, where q = TrackMetadataLength
 +
|- align="left" style="color:#ffffff; background-color:#008833;"
 +
| Metatext
 +
|
 +
|
|-
|-
-
|| p
+
| 4
-
|| TrackUri
+
| MetatextSequence
-
|| The track uri, where p = TrackUriLength
+
| Sequence number for this metatext.
|-
|-
-
|| q
+
| 4
-
|| TrackMetadata
+
| MetatextLength
-
|| The track metadata in DIDL-Lite format, where q = TrackMetadataLength
+
| The length in bytes of the metatext
|-
|-
-
|| Metatext
+
| r
 +
| Metatext
 +
| The metatext in DIDL-Lite format, where r = MetatextLength
 +
|- align="left" style="color:#ffffff; background-color:#008833;"
 +
| Slave
 +
|
 +
|
|-
|-
-
|| 4
+
| 4
-
|| MetatextLength
+
| SlaveCount
-
|| The length in bytes of the metatext
+
| The number of slaves
|-
|-
-
|| r
+
| s
-
|| Metatext
+
| SlaveList
-
|| The metatext in DIDL-Lite format, where r = MetatextLength
+
| The list of slave endpoints, where s = 6 * SlaveCount
-
|-
+
-
| colspan="4" | Slave
+
-
|-
+
-
|| 4
+
-
|| SlaveCount
+
-
|| The number of slaves
+
-
|-
+
-
|| s
+
-
|| SlaveList
+
-
|| The list of slave endpoints, where s = 6 * SlaveCount
+
|}
|}
-
== Control Messages ==
+
=== Control Messages ===
-
The Join and Listen messages are used for OHM control. The Join, Listen, Leave, and Slave messages are used for OHU control.
+
The Join and Listen messages are used by OHM. The Join, Listen, Leave, and Slave messages are used by OHU.
-
== Audio Messages ==
+
=== Audio Messages ===
Audio is transmitted as a timely and continuous stream of Audio messages.
Audio is transmitted as a timely and continuous stream of Audio messages.
-
It is typical to send audio messages every 5ms - 10ms with the length of each message dependent on the format of the audio being played.
+
It is typical to send Audio messages every 5ms - 10ms with the length of each message dependent on the format of the audio being played.
-
It is also typical at a track boundary to send a shorter audio message so that a single audio message does not span two tracks.
+
It is also typical at a track boundary to send a shorter Audio message so that a single Audio message does not span two tracks.
-
If no audio material is to be played because, for instance, the user has told the sender to pause playback, then the sender should not send silence. Rather, the sender should adorn the last audio message with the 'halt' flag to indicate that this continuous stream of audio has completed and that the next continuous stream of audio will start at an arbitrary time in the future.
+
If no audio material is to be played because, for instance, the user has told the sender to pause playback, then the sender should not send silence. Rather, the sender should adorn the last Audio message with the 'halt' flag to indicate that this continuous stream of audio has completed and that the next continuous stream of audio will start at an arbitrary time in the future.
-
Note that AudioCodecName should represent the codec that was used to decode the PCM payload. If no appropriate codec name is available AudioCodecName should be set to “PCM”.
+
Note that CodecName should represent the codec that was used to decode the PCM payload. If no appropriate codec name is available then CodecName should be set to "PCM".
-
== Timestamps ==
+
=== Timestamps ===
-
Accurate timestamps provide appropriately equipped Songcast Receivers with the ability to achieve high quality audio synchronisation. But timestamps should only be used where high accuracy is achievable. Timestamps should use an audio MCLK that is 256 * 44K1, or 256 * 48K.
+
Accurate timestamps allow appropriately equipped Songcast Receivers to achieve close audio synchronisation. But timestamps should only be used when high accuracy is achievable. The timestamps and the media latency are measured according to an audio MCLK that is 256 * 44K1, or 256 * 48K.
-
== Track Messages ==
+
=== Track Messages ===
-
Track messages are transmitted to provide Songcast Receivers with in-band information concerning the currently playing track. They should be sent shortly after a Receiver sends a Join message, and whenever the track changes.
+
Track messages are transmitted to provide Songcast Receivers with in-band information concerning the currently playing track. They should be sent when a Receiver sends a Join message, and whenever the track changes. The incrementing sequence number can be used by Receivers to distinguish between Track messages sent at the start of a new track (increment) and those sent when a new Receiver joins (no increment).
-
== Metatext Messages ==
+
=== Metatext Messages ===
-
Metatext messages are used to convey dynamic textual information concerning the currently playing audio material. This is typically information broadcast by internet radio stations.
+
Metatext messages are used to convey dynamic textual information concerning the currently playing audio material. This is typically information broadcast by internet radio stations. The incrementing sequence number can be used by Receivers to distinguish between Metatext messages sent when the dynamic information changes (increment) and those sent when a new Receiver joins (no increment).
-
== Slave Messages ==
+
=== Slave Messages ===
-
OHU uses Slave messages to deliver one-to-many communication using unicast UDP. The message contains a list of endpoints arranged as 6-byte ordered pairs of ip-address and port.
+
OHU uses Slave messages to deliver one-to-many communication using Unicast UDP. The message contains a list of endpoints arranged as 6-byte ordered pairs of ip-address and port.
-
== OHM ==
+
== Multicast ==
=== OHM Sender Channel ===
=== OHM Sender Channel ===
-
OHM is used to stream audio from a single sender to multiple receivers using multicast UDP.
+
OHM is used to stream audio from a single sender to multiple receivers using Multicast UDP.
-
Each OHM Sender within a single multicast networking domain has a unique 16 bit OHM Channel, which must be configurable by the user to avoid conflicts. And each OHM Channel has an equivalent URI as follows:
+
Each Multicast Sender within a network has a unique 16 bit Multicast Channel, which must be configurable by the user to avoid conflicts. And each Multicast Channel has an equivalent URI as follows:
-
 
+
{| border="1" cellpadding="5" style="background-color:#ffffcc;"
-
{|
+
! colspan="2" | Multicast Sender Channel
-
|| Channel
+
|- align="left" style="color:#ffffff; background-color:#008833;"
-
|| Uri
+
| Channel
 +
| Uri
|-
|-
-
|| 0
+
| 0
-
|| ohm://239.253.0.0:51972
+
| ohm://239.253.0.0:51972
|-
|-
-
|| 1
+
| 1
-
|| ohm://239.253.0.1:51972
+
| ohm://239.253.0.1:51972
|-
|-
-
|| 2
+
| 2
-
|| ohm://239.253.0.2:51972
+
| ohm://239.253.0.2:51972
|-
|-
-
|| 3
+
| 3
-
|| ohm://239.253.0.3:51972
+
| ohm://239.253.0.3:51972
|-
|-
|| ...
|| ...
|| ...
|| ...
|-
|-
-
|| 65535
+
| 65535
-
|| ohm://239.253.255.255:51972
+
| ohm://239.253.255.255:51972
|}
|}
-
An OHM Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for an OHM Sender to publish its URI by some other mechanism.
+
A Multicast Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for Multicast Sender to publish its URI by some other mechanism.
-
An OHM Receiver engages with an OHM Sender by exchanging messages with the multicast endpoint indicated by the OHM Sender's URI.
+
A Receiver engages with an Multicast Sender by exchanging messages with the Multicast endpoint indicated by this OHM URI.
 +
 
 +
=== OHM NULL URI ===
 +
The URI <tt>ohm://0.0.0.0:0</tt> is the OHM NULL URI.
 +
 
 +
If requested to play this URI, a Receiver should clear any Track Uri, Track Metadata, and Track Metatext, and be silent.
=== OHM Control ===
=== OHM Control ===
-
The OHM Sender and OHM Receivers implement the following state machines to reduce unnecessary multicast network traffic.
 
-
One Receiver tends to become the Primary Receiver, which sends Listen messages to keep the Sender producing audio messages. If the Primary Receiver ever stops listening then one of the remaining Secondary Receivers is automatically promoted to the role of Primary Receiver.
+
In general a Receiver is required to send a Join message to the Sender when it starts listening and a Listen message every second or so after that. However, when using Multicast UDP it is not necessary for a Receiver to send a Listen message if it has detected that some other Receiver has already sent one. This is because the only purpose of the Listen message is to ensure that the Sender continues sending Audio messages, and any Listen message from any Receiver will serve this purpose.
-
The OHM Sender stops producing audio messages T seconds after the last Receiver has stopped listening. Ts and Tp are arranged so that for a Sender to erroneously stop producing audio messages in the presence of active Receivers it would have to miss 4 consecutive Listen messages.
+
A Multicast Sender and a listening Receiver implement the following state machines to reduce unnecessary Multicast network traffic.
-
== ==
+
[[File:Songcast Sender Multicast State Transition Diagram.png]]
 +
 
 +
'''MULTICAST SENDER STATE TRANSITION DIAGRAM'''
 +
 
 +
[[File:Songcast Receiver Multicast State Transition Diagram.png]]
 +
 
 +
'''MULTICAST RECEIVER STATE TRANSITION DIAGRAM'''
 +
 
 +
 
 +
Using this scheme one Receiver tends to become the Primary Receiver, which sends Listen messages to keep the Sender producing audio messages. If the Primary Receiver ever stops listening then one of the remaining Secondary Receivers is automatically promoted to the role of Primary Receiver.
 +
 
 +
The OHM Sender stops producing Audio messages T seconds after the last Receiver has stopped sending Listen messages. Ts and Tp are arranged so that for a Sender to erroneously stop producing Audio messages in the presence of active Receivers it would have to miss 4 consecutive Listen messages.
 +
 
 +
The Sender Blocked states should only occur in a misconfigured system with more than one Sender on the same channel.
 +
 
 +
== Unicast ==
-
== OHU ==
 
=== OHU Basics ===
=== OHU Basics ===
The OHU protocol is arranged so that the OHU Sender need send audio to only one OHU Receiver. This is to reduce the processing overhead on those OHU Senders that have constrained processing resources.
The OHU protocol is arranged so that the OHU Sender need send audio to only one OHU Receiver. This is to reduce the processing overhead on those OHU Senders that have constrained processing resources.
Line 290: Line 337:
An OHU Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for an OHU Sender to publish its URI by some other mechanism.
An OHU Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for an OHU Sender to publish its URI by some other mechanism.
-
An OHU Receiver engages with an OHU Sender by exchanging udp messages with the unicast endpoint indicated by the OHU Sender's URI.
+
An OHU Receiver engages with an OHU Sender by exchanging UDP messages with the Unicast endpoint indicated by the OHU Sender's URI.
=== OHU Control ===
=== OHU Control ===
As well as the Join and Listen messages, OHU also uses the Leave message. This gives the OHU Sender instantaneous information concerning its OHU Listeners and enables it to quickly reorganise its OHU Primary Receiver and OHU Slave Receivers in a way that ensures uninterrupted audio.
As well as the Join and Listen messages, OHU also uses the Leave message. This gives the OHU Sender instantaneous information concerning its OHU Listeners and enables it to quickly reorganise its OHU Primary Receiver and OHU Slave Receivers in a way that ensures uninterrupted audio.
-
The periodic Listen message from all receivers is still present as a fallback mechanism for detecting OHU Receivers that became disconnected in a way that prevented them from successfully informing the OHU Sender.
+
The periodic Listen message from all receivers is still present as a fallback mechanism for detecting OHU Receivers that become disconnected in a way that prevents them from successfully informing the OHU Sender with a Leave message.
 +
 
 +
The Unicast Sender is difficult to express in a traditional State Transition Diagram. But the following description should serve as a reasonable specification.
 +
 
 +
* When a Join message is received
 +
** If this is the first Receiver, set the Primary Receiver and move to the Alive state
 +
** If this is not the first Receiver, add to the Slave Receiver list and send a Slave message with this updated list to the Primary Receiver
 +
** In all cases send a Track and Metatext message to the Primary Receiver
 +
 
 +
* When a Listen message is received
 +
** Identify the sending Primary or Slave Receiver and refresh their Alive timer
 +
** Check for expired Alive timers and modify the Primary or Slave list accordingly, possibly sending a Slave message with this updated list to the Primary Receiver
 +
 
 +
* When a Leave message is received
 +
** Identify the sending Primary or Slave Receiver modify the Primary or Slave list accordingly, possibly sending a Slave message with this updated list to the Primary Receiver
 +
 
 +
* If no more Receivers are listening, return the Waiting state
 +
 
 +
* In the Alive state send all necessary  Audio, Track, and Metatext messages to the Primary Receiver
 +
 
 +
A Receiver connected to a Unicast Sender implements the following state machine. It contains a mechanism for synchronizing the sending of a Leave message with the reception of an Audio message. This mechanism is designed to give the OHU Sender as much time as possible to reorganise its Slaves.
 +
 
 +
[[File:Songcast Receiver Unicast State Transition Diagram.png]]
 +
 
 +
'''UNICAST RECEIVER STATE TRANSITION DIAGRAM'''
 +
 
 +
== UPnP Services ==
 +
 
 +
The usual way of publishing a Songcast Sender Uri is through the Metadata state variable in the [[Av:Developer:SenderService|Sender service]]. This should cause a Songcast Sender to be listed by those Control Points compliant with the OpenHome AV standard.
 +
 
 +
A Songcast Receiver should publish itself using the [[Av:Developer:ReceiverService|Receiver service]] in conjunction with the [[Av:Developer:ReceiverService|Product service]]
 +
 
 +
== Source Code ==
 +
 
 +
A reference implementation of a Songcast Sender and Songcast Receiver will shortly be published, together with a complete open source UPnP stack.
-
There are a number of ways in which an OHU Sender can be implemented, but an OHU Receiver is expected to operate the following state machine.
+
== Glossary ==
-
The state machine contains a mechanism for attempting to synchronise the sending of a Leave message with the reception of an Audio message. This mechanism is designed to give the OHU Sender as much time as possible to reorganise.
+
* Binary milli-dB  - 1/1024 dB
 +
* Endpoint  - an ip-address and port combination that specifies a particular application running on a networked machine.
 +
* Multicast - one-to-many ip-based networking using a specially reserved set of addresses
 +
* Unicast - basic point-to-point ip-based networking

Latest revision as of 14:42, 19 August 2015

Contents

Songcast OHM/OHU Protocol Specification (Version 1.0)

Introduction

OHM and OHU, together with OHZ, form the Songcast family of OpenHome protocols for transporting audio around a home network.

  • OHM provides large scale one to many communication using Multicast UDP.
  • OHU provides small scale one to many communication using Unicast UDP.

OHU can be used to deliver Songcast functionality to networks that do not handle Multicast UDP as thoroughly as OHM requires.

General

Message Format

The OHM and OHU protocols share the same message format.


Bytes Name Description
Header
4 Signature 0x6f, 0x68, 0x6d, 0x20 ('ohm ')
1 Version 1
1 Type The type of message
0 - Join
1 - Listen
2 - Leave
3 - Audio (details below)
4 - Track (details below)
5 - Metatext (details below)
6 - Slave (details below)
2 Length The length in bytes of the whole message including this header
Minimum 8
Maximum 16392
Audio
1 AudioHeaderLength 50
1 Flags Bit 0 - halt
Bit 1 - lossless
Bit 2 - timestamped
Bit 3 - resent
Bit 4 - 0
Bit 5 - 0
Bit 6 - 0
Bit 7 - 0
2 SampleCount The number of samples in this frame
4 Frame The frame number
4 NetworkTimestamp The time when the previous frame was sent over the network (if the timestamped flag is on)
4 MediaLatency The duration of the Sender's audio buffer
4 MediaTimestamp The time when this frame was placed into an audio buffer of duration MediaLatency on the Sender (if the timestamped flag is on)
8 StartSample The sample number within the current track of the first sample in this frame
8 TotalSamples The total number of samples in the current track
4 SampleRate The sample rate in samples per second
4 BitRate The bit rate in bits per second
2 VolumeOffset The volume offset in signed binary milli-dB (+/- 32dB)
1 BItDepth The bit depth (8, 16, or 24)
1 Channels The number of interleaved audio channels
1 AudioReserved 0
1 CodecNameLength The number of bytes in the name of the codec
m CodecName The codec name (in UTF-8), where m = CodecNameLength
n Pcm Pcm samples, where n = Channels * BitDepth * SampleCount / 8
Track
4 TrackSequence Sequence number for this track.
4 TrackUriLength The length in bytes of the track URI
4 TrackMetadataLength The length in bytes of the track metadata
p TrackUri The track URI, where p = TrackUriLength
q TrackMetadata The track metadata in DIDL-Lite format, where q = TrackMetadataLength
Metatext
4 MetatextSequence Sequence number for this metatext.
4 MetatextLength The length in bytes of the metatext
r Metatext The metatext in DIDL-Lite format, where r = MetatextLength
Slave
4 SlaveCount The number of slaves
s SlaveList The list of slave endpoints, where s = 6 * SlaveCount

Control Messages

The Join and Listen messages are used by OHM. The Join, Listen, Leave, and Slave messages are used by OHU.

Audio Messages

Audio is transmitted as a timely and continuous stream of Audio messages.

It is typical to send Audio messages every 5ms - 10ms with the length of each message dependent on the format of the audio being played.

It is also typical at a track boundary to send a shorter Audio message so that a single Audio message does not span two tracks.

If no audio material is to be played because, for instance, the user has told the sender to pause playback, then the sender should not send silence. Rather, the sender should adorn the last Audio message with the 'halt' flag to indicate that this continuous stream of audio has completed and that the next continuous stream of audio will start at an arbitrary time in the future.

Note that CodecName should represent the codec that was used to decode the PCM payload. If no appropriate codec name is available then CodecName should be set to "PCM".

Timestamps

Accurate timestamps allow appropriately equipped Songcast Receivers to achieve close audio synchronisation. But timestamps should only be used when high accuracy is achievable. The timestamps and the media latency are measured according to an audio MCLK that is 256 * 44K1, or 256 * 48K.

Track Messages

Track messages are transmitted to provide Songcast Receivers with in-band information concerning the currently playing track. They should be sent when a Receiver sends a Join message, and whenever the track changes. The incrementing sequence number can be used by Receivers to distinguish between Track messages sent at the start of a new track (increment) and those sent when a new Receiver joins (no increment).

Metatext Messages

Metatext messages are used to convey dynamic textual information concerning the currently playing audio material. This is typically information broadcast by internet radio stations. The incrementing sequence number can be used by Receivers to distinguish between Metatext messages sent when the dynamic information changes (increment) and those sent when a new Receiver joins (no increment).

Slave Messages

OHU uses Slave messages to deliver one-to-many communication using Unicast UDP. The message contains a list of endpoints arranged as 6-byte ordered pairs of ip-address and port.

Multicast

OHM Sender Channel

OHM is used to stream audio from a single sender to multiple receivers using Multicast UDP.

Each Multicast Sender within a network has a unique 16 bit Multicast Channel, which must be configurable by the user to avoid conflicts. And each Multicast Channel has an equivalent URI as follows:

Multicast Sender Channel
Channel Uri
0 ohm://239.253.0.0:51972
1 ohm://239.253.0.1:51972
2 ohm://239.253.0.2:51972
3 ohm://239.253.0.3:51972
... ...
65535 ohm://239.253.255.255:51972

A Multicast Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for Multicast Sender to publish its URI by some other mechanism.

A Receiver engages with an Multicast Sender by exchanging messages with the Multicast endpoint indicated by this OHM URI.

OHM NULL URI

The URI ohm://0.0.0.0:0 is the OHM NULL URI.

If requested to play this URI, a Receiver should clear any Track Uri, Track Metadata, and Track Metatext, and be silent.

OHM Control

In general a Receiver is required to send a Join message to the Sender when it starts listening and a Listen message every second or so after that. However, when using Multicast UDP it is not necessary for a Receiver to send a Listen message if it has detected that some other Receiver has already sent one. This is because the only purpose of the Listen message is to ensure that the Sender continues sending Audio messages, and any Listen message from any Receiver will serve this purpose.

A Multicast Sender and a listening Receiver implement the following state machines to reduce unnecessary Multicast network traffic.

Songcast Sender Multicast State Transition Diagram.png

MULTICAST SENDER STATE TRANSITION DIAGRAM

Songcast Receiver Multicast State Transition Diagram.png

MULTICAST RECEIVER STATE TRANSITION DIAGRAM


Using this scheme one Receiver tends to become the Primary Receiver, which sends Listen messages to keep the Sender producing audio messages. If the Primary Receiver ever stops listening then one of the remaining Secondary Receivers is automatically promoted to the role of Primary Receiver.

The OHM Sender stops producing Audio messages T seconds after the last Receiver has stopped sending Listen messages. Ts and Tp are arranged so that for a Sender to erroneously stop producing Audio messages in the presence of active Receivers it would have to miss 4 consecutive Listen messages.

The Sender Blocked states should only occur in a misconfigured system with more than one Sender on the same channel.

Unicast

OHU Basics

The OHU protocol is arranged so that the OHU Sender need send audio to only one OHU Receiver. This is to reduce the processing overhead on those OHU Senders that have constrained processing resources.

If the OHU Sender is using this feature of the OHU protocol then it nominates one of its OHU Receivers to be the Primary OHU Receiver and sends it a Slave message, which contains a list of Slave OHU Receiver endpoints. The Primary OHU Receiver must forward any subsequent Audio, Track, or Metatext messages to this list.

As OHU Receivers come and go, the OHU Sender is responsible for nominating its OHU Primary Receiver and updating the list of OHU Slave Receivers appropriately.

If an OHU Sender has the processing power necessary to send to multiple OHU Receivers it may ignore the Slave feature or may adopt a hybrid approach, which would multiply the maximum number of OHU Receivers that that OHU Sender could support.

OHU Sender Uri

An OHU Sender URI, such as ohu://192.168.1.23:51973, represents an ip endpoint.

An OHU Sender usually publishes its URI using the OpenHome Sender service over UPnP. However, it is also possible for an OHU Sender to publish its URI by some other mechanism.

An OHU Receiver engages with an OHU Sender by exchanging UDP messages with the Unicast endpoint indicated by the OHU Sender's URI.

OHU Control

As well as the Join and Listen messages, OHU also uses the Leave message. This gives the OHU Sender instantaneous information concerning its OHU Listeners and enables it to quickly reorganise its OHU Primary Receiver and OHU Slave Receivers in a way that ensures uninterrupted audio.

The periodic Listen message from all receivers is still present as a fallback mechanism for detecting OHU Receivers that become disconnected in a way that prevents them from successfully informing the OHU Sender with a Leave message.

The Unicast Sender is difficult to express in a traditional State Transition Diagram. But the following description should serve as a reasonable specification.

  • When a Join message is received
    • If this is the first Receiver, set the Primary Receiver and move to the Alive state
    • If this is not the first Receiver, add to the Slave Receiver list and send a Slave message with this updated list to the Primary Receiver
    • In all cases send a Track and Metatext message to the Primary Receiver
  • When a Listen message is received
    • Identify the sending Primary or Slave Receiver and refresh their Alive timer
    • Check for expired Alive timers and modify the Primary or Slave list accordingly, possibly sending a Slave message with this updated list to the Primary Receiver
  • When a Leave message is received
    • Identify the sending Primary or Slave Receiver modify the Primary or Slave list accordingly, possibly sending a Slave message with this updated list to the Primary Receiver
  • If no more Receivers are listening, return the Waiting state
  • In the Alive state send all necessary Audio, Track, and Metatext messages to the Primary Receiver

A Receiver connected to a Unicast Sender implements the following state machine. It contains a mechanism for synchronizing the sending of a Leave message with the reception of an Audio message. This mechanism is designed to give the OHU Sender as much time as possible to reorganise its Slaves.

Songcast Receiver Unicast State Transition Diagram.png

UNICAST RECEIVER STATE TRANSITION DIAGRAM

UPnP Services

The usual way of publishing a Songcast Sender Uri is through the Metadata state variable in the Sender service. This should cause a Songcast Sender to be listed by those Control Points compliant with the OpenHome AV standard.

A Songcast Receiver should publish itself using the Receiver service in conjunction with the Product service

Source Code

A reference implementation of a Songcast Sender and Songcast Receiver will shortly be published, together with a complete open source UPnP stack.

Glossary

  • Binary milli-dB - 1/1024 dB
  • Endpoint - an ip-address and port combination that specifies a particular application running on a networked machine.
  • Multicast - one-to-many ip-based networking using a specially reserved set of addresses
  • Unicast - basic point-to-point ip-based networking