25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.1KB

  1. #include "rtp-over-rtsp.h"
  2. #include "rtp-header.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #define VMIN(x, y) ((x) < (y) ? (x) : (y))
  7. enum rtp_over_tcp_state_t
  8. {
  9. rtp_start = 0,
  10. rtp_channel,
  11. rtp_length_1,
  12. rtp_length_2,
  13. rtp_data,
  14. };
  15. static int rtp_alloc(struct rtp_over_rtsp_t *rtp)
  16. {
  17. void* p;
  18. if (rtp->capacity < rtp->length)
  19. {
  20. p = realloc(rtp->data, rtp->length);
  21. if (!p)
  22. return -1;
  23. rtp->data = (uint8_t*)p;
  24. rtp->capacity = rtp->length;
  25. }
  26. return 0;
  27. }
  28. #if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
  29. // skip missing data, find next start
  30. static const uint8_t* rtp_over_rtsp_try_to_find_next_packet(struct rtp_over_rtsp_t* rtp, const uint8_t* data, const uint8_t* end)
  31. {
  32. const uint8_t* p;
  33. p = (const uint8_t*)memchr(data, '$', end - data);
  34. if (!p)
  35. return end; // not found
  36. rtp->check = 1;
  37. return p;
  38. }
  39. #endif
  40. // 10.12 Embedded (Interleaved) Binary Data
  41. // Stream data such as RTP packets is encapsulated by an ASCII dollar sign(24 hexadecimal),
  42. // followed by a one-byte channel identifier,
  43. // followed by the length of the encapsulated binary data as a binary two-byte integer in network byte order.
  44. const uint8_t* rtp_over_rtsp(struct rtp_over_rtsp_t *rtp, const uint8_t* data, const uint8_t* end)
  45. {
  46. int n;
  47. for (n = 0; data < end; data++)
  48. {
  49. switch (rtp->state)
  50. {
  51. case rtp_start:
  52. if (*data != '$') {
  53. #if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
  54. return rtp_over_rtsp_try_to_find_next_packet(rtp, data, end);
  55. #else
  56. return end;
  57. #endif
  58. }
  59. rtp->bytes = 0;
  60. rtp->state = rtp_channel;
  61. break;
  62. case rtp_channel:
  63. // The channel identifier is defined in the Transport header with
  64. // the interleaved parameter(Section 12.39).
  65. rtp->channel = *data;
  66. rtp->state = rtp_length_1;
  67. break;
  68. case rtp_length_1:
  69. rtp->length = *data << 8;
  70. rtp->state = rtp_length_2;
  71. break;
  72. case rtp_length_2:
  73. rtp->length |= *data;
  74. rtp->state = rtp_data;
  75. break;
  76. case rtp_data:
  77. if (0 == rtp->bytes && 0 != rtp_alloc(rtp))
  78. return end;
  79. n = (int)(end - data);
  80. n = VMIN(rtp->length - rtp->bytes, n);
  81. memcpy(rtp->data + rtp->bytes, data, n);
  82. rtp->bytes += (uint16_t)n;
  83. #if defined(RTP_OVER_RTSP_TRY_TO_FIND_NEXT_PACKET)
  84. if (rtp->bytes >= 12)
  85. {
  86. uint32_t ssrc;
  87. ssrc = *(uint32_t*)(rtp->data + 8);
  88. if (rtp->check)
  89. {
  90. if (rtp->channel >= sizeof(rtp->ssrc) / sizeof(rtp->ssrc[0])
  91. || ssrc != rtp->ssrc[rtp->channel]
  92. || RTP_VERSION != (*rtp->data >> 6))
  93. {
  94. rtp->state = rtp_start;
  95. return rtp_over_rtsp_try_to_find_next_packet(rtp, data, end);
  96. }
  97. rtp->check = 0;
  98. }
  99. else if(rtp->channel < sizeof(rtp->ssrc) / sizeof(rtp->ssrc[0]) && 0 == rtp->ssrc[rtp->channel])
  100. {
  101. assert(RTP_VERSION == (*rtp->data >> 6));
  102. //assert(0 == rtp->ssrc[rtp->channel] || ssrc == rtp->ssrc[rtp->channel]);
  103. rtp->ssrc[rtp->channel] = ssrc;
  104. }
  105. }
  106. #endif
  107. data += n;
  108. if (rtp->bytes == rtp->length)
  109. {
  110. rtp->state = rtp_start;
  111. if(rtp->onrtp)
  112. rtp->onrtp(rtp->param, rtp->channel, rtp->data, rtp->length);
  113. return data;
  114. }
  115. break;
  116. default:
  117. assert(0);
  118. return end;
  119. }
  120. }
  121. return data;
  122. }