You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.8KB

  1. #include "rtp-packet.h"
  2. #include "rtp-util.h"
  3. #include <string.h>
  4. #include <assert.h>
  5. // RFC3550 RTP: A Transport Protocol for Real-Time Applications
  6. // 5.1 RTP Fixed Header Fields (p12)
  7. /*
  8. 0 1 2 3
  9. 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
  10. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  11. |V=2|P|X| CC |M| PT | sequence number |
  12. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  13. | timestamp |
  14. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  15. | synchronization source (SSRC) identifier |
  16. +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  17. | contributing source (CSRC) identifiers |
  18. | .... |
  19. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  20. */
  21. int rtp_packet_deserialize(struct rtp_packet_t *pkt, const void* data, int bytes)
  22. {
  23. uint32_t i, v;
  24. int hdrlen;
  25. const uint8_t *ptr;
  26. if (bytes < RTP_FIXED_HEADER) // RFC3550 5.1 RTP Fixed Header Fields(p12)
  27. return -1;
  28. ptr = (const unsigned char *)data;
  29. memset(pkt, 0, sizeof(struct rtp_packet_t));
  30. // pkt header
  31. v = nbo_r32(ptr);
  32. pkt->rtp.v = RTP_V(v);
  33. pkt->rtp.p = RTP_P(v);
  34. pkt->rtp.x = RTP_X(v);
  35. pkt->rtp.cc = RTP_CC(v);
  36. pkt->rtp.m = RTP_M(v);
  37. pkt->rtp.pt = RTP_PT(v);
  38. pkt->rtp.seq = RTP_SEQ(v);
  39. pkt->rtp.timestamp = nbo_r32(ptr + 4);
  40. pkt->rtp.ssrc = nbo_r32(ptr + 8);
  41. assert(RTP_VERSION == pkt->rtp.v);
  42. hdrlen = RTP_FIXED_HEADER + pkt->rtp.cc * 4;
  43. if (RTP_VERSION != pkt->rtp.v || bytes < hdrlen + (pkt->rtp.x ? 4 : 0) + (pkt->rtp.p ? 1 : 0))
  44. return -1;
  45. // pkt contributing source
  46. for (i = 0; i < pkt->rtp.cc; i++)
  47. {
  48. pkt->csrc[i] = nbo_r32(ptr + 12 + i * 4);
  49. }
  50. assert(bytes >= hdrlen);
  51. pkt->payload = (uint8_t*)ptr + hdrlen;
  52. pkt->payloadlen = bytes - hdrlen;
  53. // pkt header extension
  54. if (1 == pkt->rtp.x)
  55. {
  56. const uint8_t *rtpext = ptr + hdrlen;
  57. assert(pkt->payloadlen >= 4);
  58. pkt->extension = rtpext + 4;
  59. pkt->extprofile = nbo_r16(rtpext);
  60. pkt->extlen = nbo_r16(rtpext + 2) * 4;
  61. if (pkt->extlen + 4 > pkt->payloadlen)
  62. {
  63. assert(0);
  64. return -1;
  65. }
  66. else
  67. {
  68. pkt->payload = rtpext + pkt->extlen + 4;
  69. pkt->payloadlen -= pkt->extlen + 4;
  70. }
  71. }
  72. // padding
  73. if (1 == pkt->rtp.p)
  74. {
  75. uint8_t padding = ptr[bytes - 1];
  76. if (pkt->payloadlen < padding)
  77. {
  78. assert(0);
  79. return -1;
  80. }
  81. else
  82. {
  83. pkt->payloadlen -= padding;
  84. }
  85. }
  86. return 0;
  87. }
  88. int rtp_packet_serialize_header(const struct rtp_packet_t *pkt, void* data, int bytes)
  89. {
  90. int hdrlen;
  91. uint32_t i;
  92. uint8_t* ptr;
  93. if (RTP_VERSION != pkt->rtp.v || 0 != (pkt->extlen % 4))
  94. {
  95. assert(0); // RTP version field must equal 2 (p66)
  96. return -1;
  97. }
  98. // RFC3550 5.1 RTP Fixed Header Fields(p12)
  99. hdrlen = RTP_FIXED_HEADER + pkt->rtp.cc * 4 + (pkt->rtp.x ? 4 : 0);
  100. if (bytes < hdrlen + pkt->extlen)
  101. return -1;
  102. ptr = (uint8_t *)data;
  103. nbo_write_rtp_header(ptr, &pkt->rtp);
  104. ptr += RTP_FIXED_HEADER;
  105. // pkt contributing source
  106. for (i = 0; i < pkt->rtp.cc; i++, ptr += 4)
  107. {
  108. nbo_w32(ptr, pkt->csrc[i]);
  109. }
  110. // pkt header extension
  111. if (1 == pkt->rtp.x)
  112. {
  113. // 5.3.1 RTP Header Extension
  114. assert(0 == (pkt->extlen % 4));
  115. nbo_w16(ptr, pkt->extprofile);
  116. nbo_w16(ptr + 2, pkt->extlen / 4);
  117. memcpy(ptr + 4, pkt->extension, pkt->extlen);
  118. ptr += pkt->extlen + 4;
  119. }
  120. return hdrlen + pkt->extlen;
  121. }
  122. int rtp_packet_serialize(const struct rtp_packet_t *pkt, void* data, int bytes)
  123. {
  124. int hdrlen;
  125. hdrlen = rtp_packet_serialize_header(pkt, data, bytes);
  126. if (hdrlen < RTP_FIXED_HEADER || hdrlen + pkt->payloadlen > bytes)
  127. return -1;
  128. memcpy(((uint8_t*)data) + hdrlen, pkt->payload, pkt->payloadlen);
  129. return hdrlen + pkt->payloadlen;
  130. }