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

200 lines
6.1KB

  1. // RFC-2326 10.5 PLAY (p34)
  2. // 1. A PLAY request without a Range header is legal. It starts playing a
  3. // stream from the beginning unless the stream has been paused. If a
  4. // stream has been paused via PAUSE, stream delivery resumes at the pause point.
  5. // 2. If a stream is playing, such a PLAY request causes no
  6. // further action and can be used by the client to test server liveness.
  7. /*
  8. PLAY rtsp://audio.example.com/audio RTSP/1.0
  9. CSeq: 835
  10. Session: 12345678
  11. Range: npt=10-15
  12. C->S:
  13. PLAY rtsp://audio.example.com/twister.en RTSP/1.0
  14. CSeq: 833
  15. Session: 12345678
  16. Range: smpte=0:10:20-;time=19970123T153600Z
  17. S->C:
  18. RTSP/1.0 200 OK
  19. CSeq: 833
  20. Date: 23 Jan 1997 15:35:06 GMT
  21. Range: smpte=0:10:22-;time=19970123T153600Z
  22. C->S:
  23. PLAY rtsp://audio.example.com/meeting.en RTSP/1.0
  24. CSeq: 835
  25. Session: 12345678
  26. Range: clock=19961108T142300Z-19961108T143520Z
  27. S->C:
  28. RTSP/1.0 200 OK
  29. CSeq: 835
  30. Date: 23 Jan 1997 15:35:06 GMT
  31. */
  32. #include "rtsp-client.h"
  33. #include "rtsp-client-internal.h"
  34. #include "rtsp-header-range.h"
  35. #include "rtsp-header-rtp-info.h"
  36. #include <assert.h>
  37. static const char* sc_format =
  38. "PLAY %s RTSP/1.0\r\n"
  39. "CSeq: %u\r\n"
  40. "Session: %s\r\n"
  41. "%s" // Range
  42. "%s" // Speed
  43. "%s" // Authorization: Digest xxx
  44. "User-Agent: %s\r\n"
  45. "\r\n";
  46. static int rtsp_client_media_play(struct rtsp_client_t *rtsp, int i)
  47. {
  48. int r;
  49. assert(0 == rtsp->aggregate);
  50. assert(i < rtsp->media_count);
  51. assert(RTSP_PLAY == rtsp->state);
  52. if (i >= rtsp->media_count) return -1;
  53. assert(rtsp->media[i].uri[0] && rtsp->session[i].session[0]);
  54. r = rtsp_client_authenrization(rtsp, "PLAY", rtsp->media[i].uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
  55. r = snprintf(rtsp->req, sizeof(rtsp->req), sc_format, rtsp->media[i].uri, rtsp->cseq++, rtsp->session[i].session, rtsp->range, rtsp->speed, rtsp->authenrization, USER_AGENT);
  56. return (r > 0 && r < sizeof(rtsp->req) && r == rtsp->handler.send(rtsp->param, rtsp->media[i].uri, rtsp->req, r)) ? 0 : -1;
  57. }
  58. int rtsp_client_play(struct rtsp_client_t *rtsp, const uint64_t *npt, const float *speed)
  59. {
  60. int r;
  61. assert(RTSP_SETUP == rtsp->state || RTSP_PLAY == rtsp->state || RTSP_PAUSE == rtsp->state);
  62. rtsp->state = RTSP_PLAY;
  63. rtsp->progress = 0;
  64. rtsp->speed[0] = rtsp->range[0] = '\0';
  65. if ( (speed && snprintf(rtsp->speed, sizeof(rtsp->speed), "Speed: %.2f\r\n", *speed) >= sizeof(rtsp->speed))
  66. || (npt && snprintf(rtsp->range, sizeof(rtsp->range), "Range: npt=%" PRIu64 ".%" PRIu64 "-\r\n", *npt / 1000, *npt % 1000) >= sizeof(rtsp->range)) )
  67. return -1;
  68. if(rtsp->aggregate)
  69. {
  70. assert(rtsp->media_count > 0);
  71. assert(rtsp->aggregate_uri[0]);
  72. r = rtsp_client_authenrization(rtsp, "PLAY", rtsp->aggregate_uri, NULL, 0, rtsp->authenrization, sizeof(rtsp->authenrization));
  73. r = snprintf(rtsp->req, sizeof(rtsp->req), sc_format, rtsp->aggregate_uri, rtsp->cseq++, rtsp->session[0].session, rtsp->range, rtsp->speed, rtsp->authenrization, USER_AGENT);
  74. return (r > 0 && r < sizeof(rtsp->req) && r == rtsp->handler.send(rtsp->param, rtsp->aggregate_uri, rtsp->req, r)) ? 0 : -1;
  75. }
  76. else
  77. {
  78. return rtsp_client_media_play(rtsp, rtsp->progress);
  79. }
  80. }
  81. static int rtsp_client_media_play_onreply(struct rtsp_client_t* rtsp, void* parser)
  82. {
  83. int i, j, n, r;
  84. size_t len;
  85. uint64_t npt0 = (uint64_t)(-1);
  86. uint64_t npt1 = (uint64_t)(-1);
  87. double scale = 0.0f;
  88. const char *prange, *pscale, *prtpinfo, *pnext;
  89. struct rtsp_header_range_t range;
  90. struct rtsp_header_rtp_info_t rtpinfo[N_MEDIA];
  91. struct rtsp_rtp_info_t rtpInfo[N_MEDIA];
  92. if (200 != http_get_status_code(parser))
  93. return -1;
  94. prange = http_get_header_by_name(parser, "Range");
  95. pscale = http_get_header_by_name(parser, "Scale");
  96. prtpinfo = http_get_header_by_name(parser, "RTP-Info");
  97. if (pscale)
  98. {
  99. scale = atof(pscale);
  100. }
  101. if (prange && 0 == rtsp_header_range(prange, &range))
  102. {
  103. assert(range.from_value == RTSP_RANGE_TIME_NORMAL || range.from_value == RTSP_RANGE_TIME_NOW);
  104. assert(range.to_value != RTSP_RANGE_TIME_NOW);
  105. npt0 = range.from_value == RTSP_RANGE_TIME_NOW ? -1 : range.from;
  106. npt1 = range.to_value == RTSP_RANGE_TIME_NOVALUE ? -1 : range.to;
  107. }
  108. memset(rtpInfo, 0, sizeof(rtpInfo));
  109. for (n = i = 0; prtpinfo && i < sizeof(rtpInfo) / sizeof(rtpInfo[0]); i++)
  110. {
  111. prtpinfo += strspn(prtpinfo, " "); // skip space
  112. pnext = strchr(prtpinfo, ',');
  113. if (0 == rtsp_header_rtp_info(prtpinfo, &rtpinfo[i]))
  114. {
  115. rtpInfo[n].uri = rtpinfo[i].url;
  116. rtpInfo[n].seq = (unsigned int)rtpinfo[i].seq;
  117. rtpInfo[n].time = (unsigned int)rtpinfo[i].rtptime;
  118. n++;
  119. }
  120. prtpinfo = pnext ? pnext + 1 : pnext;
  121. }
  122. if(0 == rtsp->aggregate && rtsp->media_count > ++rtsp->progress)
  123. {
  124. r = rtsp->handler.onplay(rtsp->param, rtsp->progress-1, (uint64_t)(-1) == npt0 ? NULL : &npt0, (uint64_t)(-1) == npt1 ? NULL : &npt1, pscale ? &scale : NULL, rtpInfo, n);
  125. if(0 == r)
  126. return rtsp_client_media_play(rtsp, rtsp->progress);
  127. }
  128. else
  129. {
  130. for (r = j = 0; j < rtsp->media_count && 0 == r; j++)
  131. {
  132. for (i = 0; i < n; i++)
  133. {
  134. len = rtpInfo[i].uri ? strlen(rtpInfo[i].uri) : 0;
  135. if (len > 0 && strlen(rtsp->media[j].uri) >= len && 0 == strncmp(rtpInfo[i].uri, rtsp->media[j].uri+(strlen(rtsp->media[j].uri)-len), len))
  136. {
  137. r = rtsp->handler.onplay(rtsp->param, j, (uint64_t)(-1) == npt0 ? NULL : &npt0, (uint64_t)(-1) == npt1 ? NULL : &npt1, pscale ? &scale : NULL, &rtpInfo[i], 1);
  138. break; // only use the first <rtp-info>
  139. }
  140. }
  141. }
  142. }
  143. return r;
  144. }
  145. // aggregate control reply
  146. static int rtsp_client_aggregate_play_onreply(struct rtsp_client_t* rtsp, void* parser)
  147. {
  148. int code;
  149. assert(RTSP_PLAY == rtsp->state);
  150. assert(0 == rtsp->progress);
  151. assert(rtsp->aggregate);
  152. code = http_get_status_code(parser);
  153. if (459 == code) // 459 Aggregate operation not allowed (p26)
  154. {
  155. rtsp->aggregate = 0;
  156. return rtsp_client_media_play(rtsp, rtsp->progress);
  157. }
  158. else if (200 == code)
  159. {
  160. return rtsp_client_media_play_onreply(rtsp, parser);
  161. }
  162. else
  163. {
  164. return -1;
  165. }
  166. }
  167. int rtsp_client_play_onreply(struct rtsp_client_t* rtsp, void* parser)
  168. {
  169. assert(RTSP_PLAY == rtsp->state);
  170. assert(rtsp->progress < rtsp->media_count);
  171. if (rtsp->aggregate)
  172. return rtsp_client_aggregate_play_onreply(rtsp, parser);
  173. else
  174. return rtsp_client_media_play_onreply(rtsp, parser);
  175. }