Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

300 wiersze
8.3KB

  1. #if defined(_DEBUG) || defined(DEBUG)
  2. #include "sockutil.h"
  3. #include "rtsp-client.h"
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include "sockpair.h"
  7. #include "cstringext.h"
  8. #include "sys/system.h"
  9. #include "cpm/unuse.h"
  10. #include "sdp.h"
  11. #include "ntp-time.h"
  12. #include "rtp-profile.h"
  13. #include "media/ps-file-source.h"
  14. #include "media/h264-file-source.h"
  15. #include "media/h265-file-source.h"
  16. #include "media/mp4-file-source.h"
  17. #include "rtp-udp-transport.h"
  18. #include <map>
  19. #include <memory>
  20. #include <string>
  21. #include "cpm/shared_ptr.h"
  22. #if defined(_HAVE_FFMPEG_)
  23. #include "media/ffmpeg-file-source.h"
  24. #include "media/ffmpeg-live-source.h"
  25. #endif
  26. //#define UDP_MULTICAST_ADDR "239.0.0.2"
  27. extern "C" int rtsp_addr_is_multicast(const char* ip);
  28. struct rtsp_client_push_test_t
  29. {
  30. std::shared_ptr<IMediaSource> source;
  31. rtsp_client_t* rtsp;
  32. socket_t socket;
  33. char sdp[2 * 1024];
  34. std::string peer;
  35. int mode;
  36. int status;
  37. socket_t rtp[5][2];
  38. unsigned short port[5][2];
  39. std::shared_ptr<IRTPTransport> transport[5];
  40. };
  41. static int rtsp_client_sdp(struct rtsp_client_push_test_t* ctx, const char* file)
  42. {
  43. static const char* pattern_vod =
  44. "v=0\n"
  45. "o=- %llu %llu IN IP4 %s\n"
  46. "s=rtsp-client-push-test\n"
  47. "c=IN IP4 0.0.0.0\n"
  48. "t=0 0\n"
  49. "a=range:npt=0-%.1f\n"
  50. "a=recvonly\n"
  51. "a=control:*\n"; // aggregate control
  52. static const char* pattern_live =
  53. "v=0\n"
  54. "o=- %llu %llu IN IP4 %s\n"
  55. "s=rtsp-client-push-test\n"
  56. "c=IN IP4 0.0.0.0\n"
  57. "t=0 0\n"
  58. "a=range:npt=now-\n" // live
  59. "a=recvonly\n"
  60. "a=control:*\n"; // aggregate control
  61. int offset = 0;
  62. if (0 == strcmp(file, "camera"))
  63. {
  64. #if defined(_HAVE_FFMPEG_)
  65. ctx->source.reset(new FFLiveSource("video=Integrated Webcam"));
  66. #endif
  67. offset = snprintf(ctx->sdp, sizeof(ctx->sdp), pattern_live, ntp64_now(), ntp64_now(), "0.0.0.0");
  68. assert(offset > 0 && offset + 1 < sizeof(ctx->sdp));
  69. }
  70. else
  71. {
  72. if (strendswith(file, ".ps"))
  73. ctx->source.reset(new PSFileSource(file));
  74. else if (strendswith(file, ".h264"))
  75. ctx->source.reset(new H264FileSource(file));
  76. else if (strendswith(file, ".h265"))
  77. ctx->source.reset(new H265FileSource(file));
  78. else
  79. {
  80. #if defined(_HAVE_FFMPEG_)
  81. ctx->source.reset(new FFFileSource(file));
  82. #else
  83. ctx->source.reset(new MP4FileSource(file));
  84. #endif
  85. }
  86. int64_t duration;
  87. ctx->source->GetDuration(duration);
  88. offset = snprintf(ctx->sdp, sizeof(ctx->sdp), pattern_vod, ntp64_now(), ntp64_now(), "0.0.0.0", duration / 1000.0);
  89. assert(offset > 0 && offset + 1 < sizeof(ctx->sdp));
  90. }
  91. std::string sdpmedia;
  92. ctx->source->GetSDPMedia(sdpmedia);
  93. return offset + snprintf(ctx->sdp + offset, sizeof(ctx->sdp) - offset, "%s", sdpmedia.c_str());
  94. }
  95. static int rtsp_client_send(void* param, const char* uri, const void* req, size_t bytes)
  96. {
  97. //TODO: check uri and make socket
  98. //1. uri != rtsp describe uri(user input)
  99. //2. multi-uri if media_count > 1
  100. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  101. return socket_send_all_by_time(ctx->socket, req, bytes, 0, 2000);
  102. }
  103. static int rtpport(void* param, int media, const char* source, unsigned short rtp[2], char* ip, int len)
  104. {
  105. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  106. int m = rtsp_client_get_media_type(ctx->rtsp, media);
  107. if (SDP_M_MEDIA_AUDIO != m && SDP_M_MEDIA_VIDEO != m)
  108. return 0; // ignore
  109. switch (ctx->mode)
  110. {
  111. case RTSP_TRANSPORT_RTP_UDP:
  112. // TODO: ipv6
  113. assert(0 == sockpair_create("0.0.0.0", ctx->rtp[media], ctx->port[media]));
  114. rtp[0] = ctx->port[media][0];
  115. rtp[1] = ctx->port[media][1];
  116. if (rtsp_addr_is_multicast(ip))
  117. {
  118. if (0 != socket_udp_multicast(ctx->rtp[media][0], ip, source, 16) || 0 != socket_udp_multicast(ctx->rtp[media][1], ip, source, 16))
  119. return -1;
  120. }
  121. #if defined(UDP_MULTICAST_ADDR)
  122. else
  123. {
  124. if (0 != socket_udp_multicast(ctx->rtp[media][0], UDP_MULTICAST_ADDR, source, 16) || 0 != socket_udp_multicast(ctx->rtp[media][1], UDP_MULTICAST_ADDR, source, 16))
  125. return -1;
  126. snprintf(ip, len, "%s", UDP_MULTICAST_ADDR);
  127. }
  128. #endif
  129. break;
  130. case RTSP_TRANSPORT_RTP_TCP:
  131. rtp[0] = 2 * media;
  132. rtp[1] = 2 * media + 1;
  133. break;
  134. default:
  135. assert(0);
  136. return -1;
  137. }
  138. return ctx->mode;
  139. }
  140. int rtsp_client_options(rtsp_client_t* rtsp, const char* commands);
  141. static void onrtp(void* param, uint8_t channel, const void* data, uint16_t bytes)
  142. {
  143. static int keepalive = 0;
  144. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  145. //rtp_receiver_tcp_input(channel, data, bytes);
  146. //if (++keepalive % 1000 == 0)
  147. //{
  148. // rtsp_client_play(ctx->rtsp, NULL, NULL);
  149. //}
  150. }
  151. static int onannounce(void* param)
  152. {
  153. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  154. return rtsp_client_setup(ctx->rtsp, ctx->sdp, strlen(ctx->sdp));
  155. }
  156. static int onsetup(void* param, int timeout, int64_t duration)
  157. {
  158. int i;
  159. uint64_t npt = 0;
  160. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  161. for (i = 0; i < rtsp_client_media_count(ctx->rtsp); i++)
  162. {
  163. int payload;
  164. unsigned short port[2];
  165. const char* encoding;
  166. const struct rtsp_header_transport_t* transport;
  167. char track[16] = { 0 };
  168. #if defined(_HAVE_FFMPEG_)
  169. snprintf(track, sizeof(track) - 1, "track%d", i);
  170. #else
  171. snprintf(track, sizeof(track) - 1, "track%d", i + 1); // mp4 track base 1
  172. #endif
  173. transport = rtsp_client_get_media_transport(ctx->rtsp, i);
  174. encoding = rtsp_client_get_media_encoding(ctx->rtsp, i);
  175. payload = rtsp_client_get_media_payload(ctx->rtsp, i);
  176. if (RTSP_TRANSPORT_RTP_UDP == transport->transport)
  177. {
  178. //assert(RTSP_TRANSPORT_RTP_UDP == transport->transport); // udp only
  179. assert(0 == transport->multicast); // unicast only
  180. assert(transport->rtp.u.client_port1 == ctx->port[i][0]);
  181. assert(transport->rtp.u.client_port2 == ctx->port[i][1]);
  182. port[0] = transport->rtp.u.server_port1;
  183. port[1] = transport->rtp.u.server_port2;
  184. ctx->transport[i] = std::make_shared<RTPUdpTransport>();
  185. assert(transport->rtp.u.server_port1 && transport->rtp.u.server_port2);
  186. const char* ip = transport->destination[0] ? transport->destination : ctx->peer.c_str();
  187. assert(0 == ((RTPUdpTransport*)ctx->transport[i].get())->Init(ctx->rtp[i], ip, port));
  188. ctx->source->SetTransport(track, ctx->transport[i]);
  189. }
  190. else if (RTSP_TRANSPORT_RTP_TCP == transport->transport)
  191. {
  192. //assert(transport->rtp.u.client_port1 == transport->interleaved1);
  193. //assert(transport->rtp.u.client_port2 == transport->interleaved2);
  194. assert(0); // todo
  195. }
  196. else
  197. {
  198. assert(0); // TODO
  199. }
  200. }
  201. assert(0 == rtsp_client_record(ctx->rtsp, &npt, NULL));
  202. return 0;
  203. }
  204. static int onteardown(void* param)
  205. {
  206. return 0;
  207. }
  208. static int onrecord(void* param, int media, const uint64_t* nptbegin, const uint64_t* nptend, const double* scale, const struct rtsp_rtp_info_t* rtpinfo, int count)
  209. {
  210. struct rtsp_client_push_test_t* ctx = (struct rtsp_client_push_test_t*)param;
  211. ctx->status = 1;
  212. return 0;
  213. }
  214. void rtsp_client_push_test(const char* host, const char* file)
  215. {
  216. int r;
  217. struct rtsp_client_push_test_t ctx;
  218. struct rtsp_client_handler_t handler;
  219. static char packet[2 * 1024 * 1024];
  220. memset(&ctx, 0, sizeof(ctx));
  221. handler.send = rtsp_client_send;
  222. handler.rtpport = rtpport;
  223. handler.onannounce = onannounce;
  224. handler.onsetup = onsetup;
  225. handler.onrecord = onrecord;
  226. handler.onteardown = onteardown;
  227. handler.onrtp = onrtp;
  228. ctx.status = 0;
  229. ctx.peer = std::string(host);
  230. ctx.mode = RTSP_TRANSPORT_RTP_UDP; // RTSP_TRANSPORT_RTP_TCP
  231. snprintf(packet, sizeof(packet), "rtsp://%s/live/push", host); // url
  232. socket_init();
  233. ctx.socket = socket_connect_host(host, 554, 2000);
  234. assert(socket_invalid != ctx.socket);
  235. //ctx.rtsp = rtsp_client_create(NULL, NULL, &handler, &ctx);
  236. ctx.rtsp = rtsp_client_create(packet, "username1", "password1", &handler, &ctx);
  237. assert(ctx.rtsp);
  238. assert(rtsp_client_sdp(&ctx, file) > 0);
  239. assert(0 == rtsp_client_announce(ctx.rtsp, ctx.sdp));
  240. socket_setnonblock(ctx.socket, 0);
  241. r = socket_recv(ctx.socket, packet, sizeof(packet), 0);
  242. while (r > 0)
  243. {
  244. assert(0 == rtsp_client_input(ctx.rtsp, packet, r));
  245. if (ctx.status == 1)
  246. break;
  247. r = socket_recv(ctx.socket, packet, sizeof(packet), 0);
  248. }
  249. while (r > 0 && ctx.status == 1)
  250. {
  251. system_sleep(5);
  252. if (1 == ctx.status)
  253. ctx.source->Play();
  254. // TODO: check rtsp session activity
  255. }
  256. assert(0 == rtsp_client_teardown(ctx.rtsp));
  257. rtsp_client_destroy(ctx.rtsp);
  258. socket_close(ctx.socket);
  259. socket_cleanup();
  260. }
  261. #endif