Patrick, while you are at it, have a look at #pragma pack(1) per the example below.
/**
* <pre>
* http://www.ietf.org/rfc/rfc3550.txt
* The RTP header has the following format:
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |V=2|P|X| CC |M| PT | sequence number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | timestamp |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | synchronization source (SSRC) identifier |
* +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
* | contributing source (CSRC) identifiers |
* | .... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* version (V): 2 bits
* This field identifies the version of RTP. The version defined by
* this specification is two (2). (The value 1 is used by the first
* draft version of RTP and the value 0 is used by the protocol
* initially implemented in the "vat" audio tool.)
* padding (P): 1 bit
* If the padding bit is set, the packet contains one or more
* additional padding octets at the end which are not part of the
* payload. The last octet of the padding contains a count of how
* many padding octets should be ignored, including itself. Padding
* may be needed by some encryption algorithms with fixed block sizes
* or for carrying several RTP packets in a lower-layer protocol data
* unit.
* extension (X): 1 bit
* If the extension bit is set, the fixed header MUST be followed by
* exactly one header extension, with a format defined in Section
* 5.3.1.
* CSRC count (CC): 4 bits
* The CSRC count contains the number of CSRC identifiers that follow
* the fixed header.
* marker (M): 1 bit
* The interpretation of the marker is defined by a profile. It is
* intended to allow significant events such as frame boundaries to
* be marked in the packet stream. A profile MAY define additional
* marker bits or specify that there is no marker bit by changing the
* number of bits in the payload type field (see Section 5.3).
* payload type (PT): 7 bits
* This field identifies the format of the RTP payload and determines
* its interpretation by the application. A profile MAY specify a
* default static mapping of payload type codes to payload formats.
* Additional payload type codes MAY be defined dynamically through
* non-RTP means (see Section 3). A set of default mappings for
* audio and video is specified in the companion RFC 3551 [1]. An
* RTP source MAY change the payload type during a session, but this
* field SHOULD NOT be used for multiplexing separate media streams
* (see Section 5.2).
* A receiver MUST ignore packets with payload types that it does not
* understand.
* </pre>
*/
#pragma pack(push, 1)
using RtpHeader = struct RtpHeader final {
enum class Version { vat = 0, v1 = 1, v2 = 2 };
// endian sensitive bit-fields - start - reordered as big endian on network
unsigned csrc_count : 4;
unsigned extension : 1;
unsigned padding : 1;
unsigned version : 2;
unsigned payload_type : 7;
unsigned marker : 1;
// endian sensitive bit-fields - end - reordered as big endian on network
// these fields require hton(ls) to write and ntoh(ls) to read -
// note cannot be regular uing16_t and uint32_s as the alignment gets
// dword aligned if I do that (which might be a compiler bug)
unsigned sequence_number : 16; //!< sequence number
unsigned timestamp : 32; //!< timestamp
unsigned sources : 32; //!< contributing sources
explicit RtpHeader(
const Version aVersion =
RtpHeader::Version::v2,
const bool bExtension = false,
unsigned aCsrc_count = 0u,
const bool bMarker = false,
const uint32_t aPayloadType = 10u,
const uint16_t aSequenceNumber = 0u,
const uint32_t aTimestamp = 0u,
const uint32_t aSSRC = 0u)
: csrc_count{ aCsrc_count }
, extension{ bExtension }
, padding{ 0u }
, version{ static_cast<unsigned>(aVersion) }
, payload_type{ aPayloadType }
, marker{ bMarker ? 1u : 0u }
, sequence_number{ htons(aSequenceNumber) }
, timestamp{ htonl(aTimestamp) }
, sources{ htonl(aSSRC) }
{
// use thread safe very fast random number generator
//static thread_local std::mt19937 generator;
// min-max taken from uint16_t
//std::uniform_int_distribution<uint32_t> distribution;
//sequence_number = 1u; //static_cast<uint16_t>(distribution(generator));
//sources = htonl(distribution(generator));
}