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.

200 lines
4.3KB

  1. #include "ps-file-source.h"
  2. #include "cstringext.h"
  3. #include "rtp-profile.h"
  4. #include "rtp-payload.h"
  5. #include <assert.h>
  6. extern "C" uint32_t rtp_ssrc(void);
  7. PSFileSource::PSFileSource(const char *file)
  8. :m_reader(file)
  9. {
  10. m_speed = 1.0;
  11. m_status = 0;
  12. m_ps_clock = 0;
  13. m_rtp_clock = 0;
  14. m_rtcp_clock = 0;
  15. uint32_t ssrc = rtp_ssrc();
  16. struct ps_muxer_func_t func;
  17. func.alloc = Alloc;
  18. func.free = Free;
  19. func.write = Packet;
  20. m_ps = ps_muxer_create(&func, this);
  21. m_ps_stream = ps_muxer_add_stream(m_ps, PSI_STREAM_H264, NULL, 0);
  22. static struct rtp_payload_t s_psfunc = {
  23. PSFileSource::RTPAlloc,
  24. PSFileSource::RTPFree,
  25. PSFileSource::RTPPacket,
  26. };
  27. m_pspacker = rtp_payload_encode_create(RTP_PAYLOAD_MP2P, "MP2P", (uint16_t)ssrc, ssrc, &s_psfunc, this);
  28. struct rtp_event_t event;
  29. event.on_rtcp = OnRTCPEvent;
  30. m_rtp = rtp_create(&event, this, ssrc, ssrc, 90000, 4*1024, 1);
  31. rtp_set_info(m_rtp, "RTSPServer", "szj.h264");
  32. }
  33. PSFileSource::~PSFileSource()
  34. {
  35. if(m_rtp)
  36. rtp_destroy(m_rtp);
  37. if(m_pspacker)
  38. rtp_payload_encode_destroy(m_pspacker);
  39. ps_muxer_destroy(m_ps);
  40. }
  41. int PSFileSource::SetTransport(const char* /*track*/, std::shared_ptr<IRTPTransport> transport)
  42. {
  43. m_transport = transport;
  44. return 0;
  45. }
  46. int PSFileSource::Play()
  47. {
  48. m_status = 1;
  49. time64_t clock = time64_now();
  50. if(0 == m_rtp_clock || m_rtp_clock + 40 < (clock - m_ps_clock))
  51. {
  52. size_t bytes;
  53. const uint8_t* ptr;
  54. if(0 == m_reader.GetNextFrame(m_pos, ptr, bytes))
  55. {
  56. if(0 == m_ps_clock)
  57. m_ps_clock = clock;
  58. ps_muxer_input(m_ps, m_ps_stream, 0, (clock-m_ps_clock)*90, (clock-m_ps_clock)*90, ptr, bytes);
  59. m_rtp_clock += 40;
  60. SendRTCP();
  61. return 1;
  62. }
  63. }
  64. return 0;
  65. }
  66. int PSFileSource::Pause()
  67. {
  68. m_status = 2;
  69. m_rtp_clock = 0;
  70. return 0;
  71. }
  72. int PSFileSource::Seek(int64_t pos)
  73. {
  74. m_rtp_clock = 0;
  75. return m_reader.Seek(pos);
  76. }
  77. int PSFileSource::SetSpeed(double speed)
  78. {
  79. m_speed = speed;
  80. return 0;
  81. }
  82. int PSFileSource::GetDuration(int64_t& duration) const
  83. {
  84. return m_reader.GetDuration(duration);
  85. }
  86. int PSFileSource::GetSDPMedia(std::string& sdp) const
  87. {
  88. static const char* pattern =
  89. "m=video 0 RTP/AVP %d\n"
  90. "a=rtpmap:%d MP2P/90000\n";
  91. char media[64];
  92. snprintf(media, sizeof(media), pattern, RTP_PAYLOAD_MP2P, RTP_PAYLOAD_MP2P);
  93. sdp = media;
  94. return 0;
  95. }
  96. int PSFileSource::GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const
  97. {
  98. uint16_t seq;
  99. uint32_t timestamp;
  100. rtp_payload_encode_getinfo(m_pspacker, &seq, &timestamp);
  101. // url=rtsp://video.example.com/twister/video;seq=12312232;rtptime=78712811
  102. snprintf(rtpinfo, bytes, "url=%s;seq=%hu;rtptime=%u", uri, seq, timestamp);
  103. return 0;
  104. }
  105. void PSFileSource::OnRTCPEvent(const struct rtcp_msg_t* msg)
  106. {
  107. msg;
  108. }
  109. void PSFileSource::OnRTCPEvent(void* param, const struct rtcp_msg_t* msg)
  110. {
  111. PSFileSource *self = (PSFileSource *)param;
  112. self->OnRTCPEvent(msg);
  113. }
  114. int PSFileSource::SendRTCP()
  115. {
  116. // make sure have sent RTP packet
  117. time64_t clock = time64_now();
  118. int interval = rtp_rtcp_interval(m_rtp);
  119. if(0 == m_rtcp_clock || m_rtcp_clock + interval < clock)
  120. {
  121. char rtcp[1024] = {0};
  122. size_t n = rtp_rtcp_report(m_rtp, rtcp, sizeof(rtcp));
  123. // send RTCP packet
  124. m_transport->Send(true, rtcp, n);
  125. m_rtcp_clock = clock;
  126. }
  127. return 0;
  128. }
  129. void* PSFileSource::Alloc(void* /*param*/, size_t bytes)
  130. {
  131. // PSFileSource* self = (PSFileSource*)param;
  132. return malloc(bytes);
  133. }
  134. void PSFileSource::Free(void* /*param*/, void* packet)
  135. {
  136. // PSFileSource* self = (PSFileSource*)param;
  137. return free(packet);
  138. }
  139. int PSFileSource::Packet(void* param, int /*avtype*/, void* pes, size_t bytes)
  140. {
  141. PSFileSource* self = (PSFileSource*)param;
  142. time64_t clock = time64_now();
  143. return rtp_payload_encode_input(self->m_pspacker, pes, (int)bytes, (uint32_t)(clock * 90 /*kHz*/));
  144. }
  145. void* PSFileSource::RTPAlloc(void* param, int bytes)
  146. {
  147. PSFileSource *self = (PSFileSource*)param;
  148. assert(bytes <= sizeof(self->m_packet));
  149. return self->m_packet;
  150. }
  151. void PSFileSource::RTPFree(void* param, void *packet)
  152. {
  153. PSFileSource *self = (PSFileSource*)param;
  154. assert(self->m_packet == packet);
  155. }
  156. int PSFileSource::RTPPacket(void* param, const void *packet, int bytes, uint32_t /*timestamp*/, int /*flags*/)
  157. {
  158. PSFileSource *self = (PSFileSource*)param;
  159. assert(self->m_packet == packet);
  160. int r = self->m_transport->Send(false, packet, bytes);
  161. if (r != bytes)
  162. return -1;
  163. return rtp_onsend(self->m_rtp, packet, bytes/*, time*/);
  164. }