aes67_rtp.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * SPDX-FileCopyrightText: 2026 DatanoiseTV
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. * RTP audio streaming engine.
  8. *
  9. * Handles RTP packet construction, parsing, transmission and reception
  10. * for AES67 audio streams. Manages per-stream jitter buffers allocated
  11. * in PSRAM when available.
  12. */
  13. #pragma once
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include "esp_err.h"
  17. #include "aes67_config.h"
  18. #ifdef __cplusplus
  19. extern "C" {
  20. #endif
  21. /* RTP header as defined in RFC 3550, packed for network wire format */
  22. typedef struct __attribute__((packed)) {
  23. uint8_t flags; /* V=2, P, X, CC */
  24. uint8_t pt; /* M bit + payload type */
  25. uint16_t seq; /* Sequence number (network byte order) */
  26. uint32_t timestamp; /* RTP timestamp (network byte order) */
  27. uint32_t ssrc; /* Synchronization source (network byte order) */
  28. } aes67_rtp_header_t;
  29. /* Stream direction */
  30. typedef enum {
  31. AES67_STREAM_SOURCE = 0, /* TX: capture audio, send RTP */
  32. AES67_STREAM_SINK = 1, /* RX: receive RTP, play audio */
  33. } aes67_stream_dir_t;
  34. /* Stream status flags (bitmask) */
  35. #define AES67_RTP_STATUS_SEQ_ERROR (1 << 0)
  36. #define AES67_RTP_STATUS_SSRC_ERROR (1 << 1)
  37. #define AES67_RTP_STATUS_PT_ERROR (1 << 2)
  38. #define AES67_RTP_STATUS_TIMESTAMP_ERR (1 << 3)
  39. #define AES67_RTP_STATUS_RECEIVING (1 << 4)
  40. #define AES67_RTP_STATUS_MUTED (1 << 5)
  41. #define AES67_RTP_STATUS_OVERFLOW (1 << 6)
  42. #define AES67_RTP_STATUS_UNDERFLOW (1 << 7)
  43. /* Configuration for a single RTP stream */
  44. typedef struct {
  45. aes67_stream_dir_t direction;
  46. uint32_t dest_ip; /* Multicast destination IP (network order) */
  47. uint16_t dest_port; /* Destination port (host order) */
  48. uint16_t src_port; /* Source port (host order) */
  49. uint8_t payload_type; /* RTP payload type (e.g. 98) */
  50. uint32_t ssrc; /* SSRC identifier */
  51. uint32_t sample_rate; /* Sample rate in Hz */
  52. uint8_t channels; /* Number of audio channels */
  53. uint8_t word_length; /* Bytes per sample (2, 3, or 4) */
  54. aes67_codec_t codec; /* Audio codec */
  55. uint16_t packet_time_us; /* Packet time in microseconds */
  56. uint32_t playout_delay_us; /* Playout delay for sinks */
  57. uint8_t dscp; /* DSCP marking */
  58. uint8_t ttl; /* Multicast TTL */
  59. /* Channel routing: maps RTP channel index to local audio channel */
  60. uint8_t routing[CONFIG_AES67_MAX_CHANNELS_PER_STREAM];
  61. } aes67_rtp_stream_config_t;
  62. /* Runtime stream status */
  63. typedef struct {
  64. uint32_t status_flags; /* Bitmask of AES67_RTP_STATUS_* */
  65. uint32_t packets_sent; /* Total packets transmitted */
  66. uint32_t packets_received; /* Total packets received */
  67. uint32_t packets_lost; /* Detected packet loss count */
  68. uint32_t packets_late; /* Packets arriving after playout */
  69. uint32_t seq_errors; /* Sequence discontinuity count */
  70. int32_t jitter_us; /* Estimated jitter in microseconds */
  71. uint32_t last_rtp_timestamp; /* Last RTP timestamp processed */
  72. uint16_t last_seq; /* Last sequence number */
  73. } aes67_rtp_stream_status_t;
  74. /* Opaque stream handle */
  75. typedef struct aes67_rtp_stream *aes67_rtp_stream_handle_t;
  76. /* Opaque RTP engine handle */
  77. typedef struct aes67_rtp_engine *aes67_rtp_engine_handle_t;
  78. /**
  79. * Initialize the RTP engine. Creates the network sockets and processing tasks.
  80. */
  81. esp_err_t aes67_rtp_engine_init(const aes67_net_config_t *net_config,
  82. bool use_psram,
  83. aes67_rtp_engine_handle_t *handle);
  84. /**
  85. * Start the RTP engine (begins packet processing).
  86. */
  87. esp_err_t aes67_rtp_engine_start(aes67_rtp_engine_handle_t handle);
  88. /**
  89. * Stop the RTP engine.
  90. */
  91. esp_err_t aes67_rtp_engine_stop(aes67_rtp_engine_handle_t handle);
  92. /**
  93. * Destroy the RTP engine and all streams.
  94. */
  95. esp_err_t aes67_rtp_engine_destroy(aes67_rtp_engine_handle_t handle);
  96. /**
  97. * Add an RTP stream (source or sink). Returns a stream handle.
  98. */
  99. esp_err_t aes67_rtp_stream_add(aes67_rtp_engine_handle_t engine,
  100. const aes67_rtp_stream_config_t *config,
  101. aes67_rtp_stream_handle_t *stream);
  102. /**
  103. * Remove an RTP stream.
  104. */
  105. esp_err_t aes67_rtp_stream_remove(aes67_rtp_engine_handle_t engine,
  106. aes67_rtp_stream_handle_t stream);
  107. /**
  108. * Get stream status.
  109. */
  110. esp_err_t aes67_rtp_stream_get_status(aes67_rtp_stream_handle_t stream,
  111. aes67_rtp_stream_status_t *status);
  112. /**
  113. * Write audio samples to a source stream's buffer (called by audio driver).
  114. * Samples are interleaved, in native byte order, at the stream's word length.
  115. *
  116. * @param stream Source stream handle
  117. * @param samples Pointer to interleaved sample data
  118. * @param frame_count Number of audio frames (one sample per channel = one frame)
  119. * @return ESP_OK on success
  120. */
  121. esp_err_t aes67_rtp_source_write(aes67_rtp_stream_handle_t stream,
  122. const void *samples, uint32_t frame_count);
  123. /**
  124. * Read audio samples from a sink stream's jitter buffer (called by audio driver).
  125. * Returns silence if the jitter buffer is empty or the stream is muted.
  126. *
  127. * @param stream Sink stream handle
  128. * @param samples Output buffer for interleaved sample data
  129. * @param frame_count Number of frames to read
  130. * @return ESP_OK on success, ESP_ERR_NOT_FOUND if no data available
  131. */
  132. esp_err_t aes67_rtp_sink_read(aes67_rtp_stream_handle_t stream,
  133. void *samples, uint32_t frame_count);
  134. /**
  135. * Called by the audio frame timer (TIC) to trigger RTP packet transmission
  136. * for all active source streams.
  137. */
  138. esp_err_t aes67_rtp_engine_process_tx(aes67_rtp_engine_handle_t handle,
  139. uint32_t rtp_timestamp);
  140. /**
  141. * Get the stream buffer used for RTP RX -> playback decoupling.
  142. */
  143. #include "freertos/stream_buffer.h"
  144. StreamBufferHandle_t aes67_rtp_engine_get_stream_buf(aes67_rtp_engine_handle_t handle);
  145. /**
  146. * Set the task to notify when new sink data arrives.
  147. */
  148. #include "freertos/task.h"
  149. void aes67_rtp_engine_set_notify_task(aes67_rtp_engine_handle_t handle,
  150. TaskHandle_t task);
  151. /**
  152. * Enable/disable direct I2S playback from the RTP RX path.
  153. */
  154. void aes67_rtp_engine_set_playback(aes67_rtp_engine_handle_t handle,
  155. void *audio_handle);
  156. /**
  157. * Get available frames in a sink stream's jitter buffer.
  158. */
  159. uint32_t aes67_rtp_sink_available(aes67_rtp_stream_handle_t stream);
  160. #ifdef __cplusplus
  161. }
  162. #endif