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.

874 lines
24KB

  1. /*
  2. * RTSP client
  3. * Copyright (c) 2002 Fabrice Bellard.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "avformat.h"
  20. #include <sys/time.h>
  21. #include <netinet/in.h>
  22. #include <sys/socket.h>
  23. #include <arpa/inet.h>
  24. //#define DEBUG
  25. typedef struct RTSPState {
  26. URLContext *rtsp_hd; /* RTSP TCP connexion handle */
  27. ByteIOContext rtsp_gb;
  28. int seq; /* RTSP command sequence number */
  29. char session_id[512];
  30. enum RTSPProtocol protocol;
  31. char last_reply[2048]; /* XXX: allocate ? */
  32. } RTSPState;
  33. typedef struct RTSPStream {
  34. AVFormatContext *ic;
  35. int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */
  36. char control_url[1024]; /* url for this stream */
  37. } RTSPStream;
  38. /* suppress this hack */
  39. int rtsp_abort_req = 0;
  40. /* XXX: currently, the only way to change the protocols consists in
  41. changing this variable */
  42. int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST);
  43. FFRTSPCallback *ff_rtsp_callback = NULL;
  44. static int rtsp_probe(AVProbeData *p)
  45. {
  46. if (strstart(p->filename, "rtsp:", NULL))
  47. return AVPROBE_SCORE_MAX;
  48. return 0;
  49. }
  50. static int redir_isspace(int c)
  51. {
  52. return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
  53. }
  54. static void skip_spaces(const char **pp)
  55. {
  56. const char *p;
  57. p = *pp;
  58. while (redir_isspace(*p))
  59. p++;
  60. *pp = p;
  61. }
  62. static void get_word_sep(char *buf, int buf_size, const char *sep,
  63. const char **pp)
  64. {
  65. const char *p;
  66. char *q;
  67. p = *pp;
  68. skip_spaces(&p);
  69. q = buf;
  70. while (!strchr(sep, *p) && *p != '\0') {
  71. if ((q - buf) < buf_size - 1)
  72. *q++ = *p;
  73. p++;
  74. }
  75. if (buf_size > 0)
  76. *q = '\0';
  77. *pp = p;
  78. }
  79. static void get_word(char *buf, int buf_size, const char **pp)
  80. {
  81. const char *p;
  82. char *q;
  83. p = *pp;
  84. skip_spaces(&p);
  85. q = buf;
  86. while (!redir_isspace(*p) && *p != '\0') {
  87. if ((q - buf) < buf_size - 1)
  88. *q++ = *p;
  89. p++;
  90. }
  91. if (buf_size > 0)
  92. *q = '\0';
  93. *pp = p;
  94. }
  95. static void sdp_parse_line(AVFormatContext *s,
  96. int letter, const char *buf)
  97. {
  98. char buf1[64], st_type[64];
  99. const char *p;
  100. int codec_type, payload_type;
  101. AVStream *st;
  102. RTSPStream *rtsp_st;
  103. #ifdef DEBUG
  104. printf("sdp: %c='%s'\n", letter, buf);
  105. #endif
  106. p = buf;
  107. switch(letter) {
  108. case 's':
  109. pstrcpy(s->title, sizeof(s->title), p);
  110. break;
  111. case 'i':
  112. if (s->nb_streams == 0) {
  113. pstrcpy(s->comment, sizeof(s->comment), p);
  114. break;
  115. }
  116. break;
  117. case 'm':
  118. /* new stream */
  119. get_word(st_type, sizeof(st_type), &p);
  120. if (!strcmp(st_type, "audio")) {
  121. codec_type = CODEC_TYPE_AUDIO;
  122. } else if (!strcmp(st_type, "video")) {
  123. codec_type = CODEC_TYPE_VIDEO;
  124. } else {
  125. return;
  126. }
  127. get_word(buf1, sizeof(buf1), &p); /* port */
  128. get_word(buf1, sizeof(buf1), &p); /* protocol */
  129. /* XXX: handle list of formats */
  130. get_word(buf1, sizeof(buf1), &p); /* format list */
  131. payload_type = atoi(buf1);
  132. rtsp_st = av_mallocz(sizeof(RTSPStream));
  133. if (!rtsp_st)
  134. return;
  135. st = av_new_stream(s, s->nb_streams);
  136. if (!st)
  137. return;
  138. st->priv_data = rtsp_st;
  139. /* put a default control url */
  140. pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), s->filename);
  141. st->codec.codec_type = codec_type;
  142. rtp_get_codec_info(&st->codec, payload_type);
  143. break;
  144. case 'a':
  145. if (strstart(p, "control:", &p) && s->nb_streams > 0) {
  146. char proto[32];
  147. /* get the control url */
  148. st = s->streams[s->nb_streams - 1];
  149. rtsp_st = st->priv_data;
  150. /* XXX: may need to add full url resolution */
  151. url_split(proto, sizeof(proto), NULL, 0, NULL, NULL, 0, p);
  152. if (proto[0] == '\0') {
  153. /* relative control URL */
  154. pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/");
  155. pstrcat(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
  156. } else {
  157. pstrcpy(rtsp_st->control_url, sizeof(rtsp_st->control_url), p);
  158. }
  159. }
  160. break;
  161. }
  162. }
  163. int sdp_parse(AVFormatContext *s, const char *content)
  164. {
  165. const char *p;
  166. int letter;
  167. char buf[1024], *q;
  168. p = content;
  169. for(;;) {
  170. skip_spaces(&p);
  171. letter = *p;
  172. if (letter == '\0')
  173. break;
  174. p++;
  175. if (*p != '=')
  176. goto next_line;
  177. p++;
  178. /* get the content */
  179. q = buf;
  180. while (*p != '\n' && *p != '\0') {
  181. if ((q - buf) < sizeof(buf) - 1)
  182. *q++ = *p;
  183. p++;
  184. }
  185. *q = '\0';
  186. sdp_parse_line(s, letter, buf);
  187. next_line:
  188. while (*p != '\n' && *p != '\0')
  189. p++;
  190. if (*p == '\n')
  191. p++;
  192. }
  193. return 0;
  194. }
  195. static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
  196. {
  197. const char *p;
  198. int v;
  199. p = *pp;
  200. skip_spaces(&p);
  201. v = strtol(p, (char **)&p, 10);
  202. if (*p == '-') {
  203. p++;
  204. *min_ptr = v;
  205. v = strtol(p, (char **)&p, 10);
  206. *max_ptr = v;
  207. } else {
  208. *min_ptr = v;
  209. *max_ptr = v;
  210. }
  211. *pp = p;
  212. }
  213. /* XXX: only one transport specification is parsed */
  214. static void rtsp_parse_transport(RTSPHeader *reply, const char *p)
  215. {
  216. char transport_protocol[16];
  217. char profile[16];
  218. char lower_transport[16];
  219. char parameter[16];
  220. RTSPTransportField *th;
  221. char buf[256];
  222. reply->nb_transports = 0;
  223. for(;;) {
  224. skip_spaces(&p);
  225. if (*p == '\0')
  226. break;
  227. th = &reply->transports[reply->nb_transports];
  228. get_word_sep(transport_protocol, sizeof(transport_protocol),
  229. "/", &p);
  230. if (*p == '/')
  231. p++;
  232. get_word_sep(profile, sizeof(profile), "/;,", &p);
  233. lower_transport[0] = '\0';
  234. if (*p == '/') {
  235. get_word_sep(lower_transport, sizeof(lower_transport),
  236. ";,", &p);
  237. }
  238. if (!strcmp(lower_transport, "TCP"))
  239. th->protocol = RTSP_PROTOCOL_RTP_TCP;
  240. else
  241. th->protocol = RTSP_PROTOCOL_RTP_UDP;
  242. if (*p == ';')
  243. p++;
  244. /* get each parameter */
  245. while (*p != '\0' && *p != ',') {
  246. get_word_sep(parameter, sizeof(parameter), "=;,", &p);
  247. if (!strcmp(parameter, "port")) {
  248. if (*p == '=') {
  249. p++;
  250. rtsp_parse_range(&th->port_min, &th->port_max, &p);
  251. }
  252. } else if (!strcmp(parameter, "client_port")) {
  253. if (*p == '=') {
  254. p++;
  255. rtsp_parse_range(&th->client_port_min,
  256. &th->client_port_max, &p);
  257. }
  258. } else if (!strcmp(parameter, "server_port")) {
  259. if (*p == '=') {
  260. p++;
  261. rtsp_parse_range(&th->server_port_min,
  262. &th->server_port_max, &p);
  263. }
  264. } else if (!strcmp(parameter, "interleaved")) {
  265. if (*p == '=') {
  266. p++;
  267. rtsp_parse_range(&th->interleaved_min,
  268. &th->interleaved_max, &p);
  269. }
  270. } else if (!strcmp(parameter, "multicast")) {
  271. if (th->protocol == RTSP_PROTOCOL_RTP_UDP)
  272. th->protocol = RTSP_PROTOCOL_RTP_UDP_MULTICAST;
  273. } else if (!strcmp(parameter, "ttl")) {
  274. if (*p == '=') {
  275. p++;
  276. th->ttl = strtol(p, (char **)&p, 10);
  277. }
  278. } else if (!strcmp(parameter, "destination")) {
  279. struct in_addr ipaddr;
  280. if (*p == '=') {
  281. p++;
  282. get_word_sep(buf, sizeof(buf), ";,", &p);
  283. if (inet_aton(buf, &ipaddr))
  284. th->destination = ntohl(ipaddr.s_addr);
  285. }
  286. }
  287. while (*p != ';' && *p != '\0' && *p != ',')
  288. p++;
  289. if (*p == ';')
  290. p++;
  291. }
  292. if (*p == ',')
  293. p++;
  294. reply->nb_transports++;
  295. }
  296. }
  297. void rtsp_parse_line(RTSPHeader *reply, const char *buf)
  298. {
  299. const char *p;
  300. /* NOTE: we do case independent match for broken servers */
  301. p = buf;
  302. if (stristart(p, "Session:", &p)) {
  303. get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
  304. } else if (stristart(p, "Content-Length:", &p)) {
  305. reply->content_length = strtol(p, NULL, 10);
  306. } else if (stristart(p, "Transport:", &p)) {
  307. rtsp_parse_transport(reply, p);
  308. } else if (stristart(p, "CSeq:", &p)) {
  309. reply->seq = strtol(p, NULL, 10);
  310. }
  311. }
  312. static void rtsp_send_cmd(AVFormatContext *s,
  313. const char *cmd, RTSPHeader *reply,
  314. unsigned char **content_ptr)
  315. {
  316. RTSPState *rt = s->priv_data;
  317. char buf[4096], buf1[1024], *q;
  318. unsigned char ch;
  319. const char *p;
  320. int content_length, line_count;
  321. unsigned char *content = NULL;
  322. memset(reply, 0, sizeof(RTSPHeader));
  323. rt->seq++;
  324. pstrcpy(buf, sizeof(buf), cmd);
  325. snprintf(buf1, sizeof(buf1), "CSeq: %d\n", rt->seq);
  326. pstrcat(buf, sizeof(buf), buf1);
  327. if (rt->session_id[0] != '\0' && !strstr(cmd, "\nIf-Match:")) {
  328. snprintf(buf1, sizeof(buf1), "Session: %s\n", rt->session_id);
  329. pstrcat(buf, sizeof(buf), buf1);
  330. }
  331. pstrcat(buf, sizeof(buf), "\n");
  332. #ifdef DEBUG
  333. printf("Sending:\n%s--\n", buf);
  334. #endif
  335. url_write(rt->rtsp_hd, buf, strlen(buf));
  336. /* parse reply (XXX: use buffers) */
  337. line_count = 0;
  338. rt->last_reply[0] = '\0';
  339. for(;;) {
  340. q = buf;
  341. for(;;) {
  342. if (url_read(rt->rtsp_hd, &ch, 1) == 0)
  343. break;
  344. if (ch == '\n')
  345. break;
  346. if (ch != '\r') {
  347. if ((q - buf) < sizeof(buf) - 1)
  348. *q++ = ch;
  349. }
  350. }
  351. *q = '\0';
  352. #ifdef DEBUG
  353. printf("line='%s'\n", buf);
  354. #endif
  355. /* test if last line */
  356. if (buf[0] == '\0')
  357. break;
  358. p = buf;
  359. if (line_count == 0) {
  360. /* get reply code */
  361. get_word(buf1, sizeof(buf1), &p);
  362. get_word(buf1, sizeof(buf1), &p);
  363. reply->status_code = atoi(buf1);
  364. } else {
  365. rtsp_parse_line(reply, p);
  366. pstrcat(rt->last_reply, sizeof(rt->last_reply), p);
  367. pstrcat(rt->last_reply, sizeof(rt->last_reply), "\n");
  368. }
  369. line_count++;
  370. }
  371. if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
  372. pstrcpy(rt->session_id, sizeof(rt->session_id), reply->session_id);
  373. content_length = reply->content_length;
  374. if (content_length > 0) {
  375. /* leave some room for a trailing '\0' (useful for simple parsing) */
  376. content = av_malloc(content_length + 1);
  377. url_read(rt->rtsp_hd, content, content_length);
  378. content[content_length] = '\0';
  379. }
  380. if (content_ptr)
  381. *content_ptr = content;
  382. }
  383. /* useful for modules: set RTSP callback function */
  384. void rtsp_set_callback(FFRTSPCallback *rtsp_cb)
  385. {
  386. ff_rtsp_callback = rtsp_cb;
  387. }
  388. static int rtsp_read_header(AVFormatContext *s,
  389. AVFormatParameters *ap)
  390. {
  391. RTSPState *rt = s->priv_data;
  392. char host[1024], path[1024], tcpname[1024], cmd[2048];
  393. URLContext *rtsp_hd;
  394. int port, i, ret, err;
  395. RTSPHeader reply1, *reply = &reply1;
  396. unsigned char *content = NULL;
  397. AVStream *st;
  398. RTSPStream *rtsp_st;
  399. int protocol_mask;
  400. rtsp_abort_req = 0;
  401. /* extract hostname and port */
  402. url_split(NULL, 0,
  403. host, sizeof(host), &port, path, sizeof(path), s->filename);
  404. if (port < 0)
  405. port = RTSP_DEFAULT_PORT;
  406. /* open the tcp connexion */
  407. snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
  408. if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
  409. return AVERROR_IO;
  410. rt->rtsp_hd = rtsp_hd;
  411. rt->seq = 0;
  412. /* describe the stream */
  413. snprintf(cmd, sizeof(cmd),
  414. "DESCRIBE %s RTSP/1.0\n"
  415. "Accept: application/sdp\n",
  416. s->filename);
  417. rtsp_send_cmd(s, cmd, reply, &content);
  418. if (!content) {
  419. err = AVERROR_INVALIDDATA;
  420. goto fail;
  421. }
  422. if (reply->status_code != RTSP_STATUS_OK) {
  423. err = AVERROR_INVALIDDATA;
  424. goto fail;
  425. }
  426. /* now we got the SDP description, we parse it */
  427. ret = sdp_parse(s, (const char *)content);
  428. av_freep(&content);
  429. if (ret < 0) {
  430. err = AVERROR_INVALIDDATA;
  431. goto fail;
  432. }
  433. protocol_mask = rtsp_default_protocols;
  434. /* for each stream, make the setup request */
  435. /* XXX: we assume the same server is used for the control of each
  436. RTSP stream */
  437. for(i=0;i<s->nb_streams;i++) {
  438. AVInputFormat *fmt;
  439. char transport[2048];
  440. st = s->streams[i];
  441. rtsp_st = st->priv_data;
  442. /* compute available transports */
  443. transport[0] = '\0';
  444. /* RTP/UDP */
  445. if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
  446. fmt = &rtp_demux;
  447. if (av_open_input_file(&rtsp_st->ic, "rtp://", fmt, 0, NULL) < 0) {
  448. err = AVERROR_INVALIDDATA;
  449. goto fail;
  450. }
  451. port = rtp_get_local_port(url_fileno(&rtsp_st->ic->pb));
  452. if (transport[0] != '\0')
  453. pstrcat(transport, sizeof(transport), ",");
  454. snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
  455. "RTP/AVP/UDP;unicast;client_port=%d-%d",
  456. port, port + 1);
  457. }
  458. /* RTP/TCP */
  459. if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
  460. if (transport[0] != '\0')
  461. pstrcat(transport, sizeof(transport), ",");
  462. snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
  463. "RTP/AVP/TCP");
  464. }
  465. if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
  466. if (transport[0] != '\0')
  467. pstrcat(transport, sizeof(transport), ",");
  468. snprintf(transport + strlen(transport),
  469. sizeof(transport) - strlen(transport) - 1,
  470. "RTP/AVP/UDP;multicast");
  471. }
  472. snprintf(cmd, sizeof(cmd),
  473. "SETUP %s RTSP/1.0\n"
  474. "Transport: %s\n",
  475. rtsp_st->control_url, transport);
  476. rtsp_send_cmd(s, cmd, reply, NULL);
  477. if (reply->status_code != RTSP_STATUS_OK ||
  478. reply->nb_transports != 1) {
  479. err = AVERROR_INVALIDDATA;
  480. goto fail;
  481. }
  482. /* XXX: same protocol for all streams is required */
  483. if (i > 0) {
  484. if (reply->transports[0].protocol != rt->protocol) {
  485. err = AVERROR_INVALIDDATA;
  486. goto fail;
  487. }
  488. } else {
  489. rt->protocol = reply->transports[0].protocol;
  490. }
  491. /* close RTP connection if not choosen */
  492. if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
  493. (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
  494. av_close_input_file(rtsp_st->ic);
  495. rtsp_st->ic = NULL;
  496. }
  497. switch(reply->transports[0].protocol) {
  498. case RTSP_PROTOCOL_RTP_TCP:
  499. fmt = &rtp_demux;
  500. if (av_open_input_file(&rtsp_st->ic, "null", fmt, 0, NULL) < 0) {
  501. err = AVERROR_INVALIDDATA;
  502. goto fail;
  503. }
  504. rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
  505. rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
  506. break;
  507. case RTSP_PROTOCOL_RTP_UDP:
  508. {
  509. char url[1024];
  510. /* XXX: also use address if specified */
  511. snprintf(url, sizeof(url), "rtp://%s:%d",
  512. host, reply->transports[0].server_port_min);
  513. if (rtp_set_remote_url(url_fileno(&rtsp_st->ic->pb), url) < 0) {
  514. err = AVERROR_INVALIDDATA;
  515. goto fail;
  516. }
  517. }
  518. break;
  519. case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
  520. {
  521. char url[1024];
  522. int ttl;
  523. fmt = &rtp_demux;
  524. ttl = reply->transports[0].ttl;
  525. if (!ttl)
  526. ttl = 16;
  527. snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",
  528. host,
  529. reply->transports[0].server_port_min,
  530. ttl);
  531. if (av_open_input_file(&rtsp_st->ic, url, fmt, 0, NULL) < 0) {
  532. err = AVERROR_INVALIDDATA;
  533. goto fail;
  534. }
  535. }
  536. break;
  537. }
  538. }
  539. /* use callback if available to extend setup */
  540. if (ff_rtsp_callback) {
  541. if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id,
  542. NULL, 0, rt->last_reply) < 0) {
  543. err = AVERROR_INVALIDDATA;
  544. goto fail;
  545. }
  546. }
  547. /* start playing */
  548. snprintf(cmd, sizeof(cmd),
  549. "PLAY %s RTSP/1.0\n",
  550. s->filename);
  551. rtsp_send_cmd(s, cmd, reply, NULL);
  552. if (reply->status_code != RTSP_STATUS_OK) {
  553. err = AVERROR_INVALIDDATA;
  554. goto fail;
  555. }
  556. /* open TCP with bufferized input */
  557. if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
  558. if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {
  559. err = AVERROR_NOMEM;
  560. goto fail;
  561. }
  562. }
  563. return 0;
  564. fail:
  565. for(i=0;i<s->nb_streams;i++) {
  566. st = s->streams[i];
  567. rtsp_st = st->priv_data;
  568. if (rtsp_st) {
  569. if (rtsp_st->ic)
  570. av_close_input_file(rtsp_st->ic);
  571. }
  572. av_free(rtsp_st);
  573. }
  574. av_freep(&content);
  575. url_close(rt->rtsp_hd);
  576. return err;
  577. }
  578. static int tcp_read_packet(AVFormatContext *s,
  579. AVPacket *pkt)
  580. {
  581. RTSPState *rt = s->priv_data;
  582. ByteIOContext *rtsp_gb = &rt->rtsp_gb;
  583. int c, id, len, i, ret;
  584. AVStream *st;
  585. RTSPStream *rtsp_st;
  586. char buf[RTP_MAX_PACKET_LENGTH];
  587. redo:
  588. for(;;) {
  589. c = url_fgetc(rtsp_gb);
  590. if (c == URL_EOF)
  591. return AVERROR_IO;
  592. if (c == '$')
  593. break;
  594. }
  595. id = get_byte(rtsp_gb);
  596. len = get_be16(rtsp_gb);
  597. if (len > RTP_MAX_PACKET_LENGTH || len < 12)
  598. goto redo;
  599. /* get the data */
  600. get_buffer(rtsp_gb, buf, len);
  601. /* find the matching stream */
  602. for(i = 0; i < s->nb_streams; i++) {
  603. st = s->streams[i];
  604. rtsp_st = st->priv_data;
  605. if (i >= rtsp_st->interleaved_min &&
  606. i <= rtsp_st->interleaved_max)
  607. goto found;
  608. }
  609. goto redo;
  610. found:
  611. ret = rtp_parse_packet(rtsp_st->ic, pkt, buf, len);
  612. if (ret < 0)
  613. goto redo;
  614. pkt->stream_index = i;
  615. return ret;
  616. }
  617. /* NOTE: output one packet at a time. May need to add a small fifo */
  618. static int udp_read_packet(AVFormatContext *s,
  619. AVPacket *pkt)
  620. {
  621. AVFormatContext *ic;
  622. AVStream *st;
  623. RTSPStream *rtsp_st;
  624. fd_set rfds;
  625. int fd1, fd2, fd_max, n, i, ret;
  626. char buf[RTP_MAX_PACKET_LENGTH];
  627. struct timeval tv;
  628. for(;;) {
  629. if (rtsp_abort_req)
  630. return -EIO;
  631. FD_ZERO(&rfds);
  632. fd_max = -1;
  633. for(i = 0; i < s->nb_streams; i++) {
  634. st = s->streams[i];
  635. rtsp_st = st->priv_data;
  636. ic = rtsp_st->ic;
  637. /* currently, we cannot probe RTCP handle because of blocking restrictions */
  638. rtp_get_file_handles(url_fileno(&ic->pb), &fd1, &fd2);
  639. if (fd1 > fd_max)
  640. fd_max = fd1;
  641. FD_SET(fd1, &rfds);
  642. }
  643. /* XXX: also add proper API to abort */
  644. tv.tv_sec = 0;
  645. tv.tv_usec = 500000;
  646. n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
  647. if (n > 0) {
  648. for(i = 0; i < s->nb_streams; i++) {
  649. st = s->streams[i];
  650. rtsp_st = st->priv_data;
  651. ic = rtsp_st->ic;
  652. rtp_get_file_handles(url_fileno(&ic->pb), &fd1, &fd2);
  653. if (FD_ISSET(fd1, &rfds)) {
  654. ret = url_read(url_fileno(&ic->pb), buf, sizeof(buf));
  655. if (ret >= 0 &&
  656. rtp_parse_packet(ic, pkt, buf, ret) == 0) {
  657. pkt->stream_index = i;
  658. return ret;
  659. }
  660. }
  661. }
  662. }
  663. }
  664. }
  665. static int rtsp_read_packet(AVFormatContext *s,
  666. AVPacket *pkt)
  667. {
  668. RTSPState *rt = s->priv_data;
  669. int ret;
  670. switch(rt->protocol) {
  671. default:
  672. case RTSP_PROTOCOL_RTP_TCP:
  673. ret = tcp_read_packet(s, pkt);
  674. break;
  675. case RTSP_PROTOCOL_RTP_UDP:
  676. ret = udp_read_packet(s, pkt);
  677. break;
  678. }
  679. return ret;
  680. }
  681. static int rtsp_read_close(AVFormatContext *s)
  682. {
  683. RTSPState *rt = s->priv_data;
  684. AVStream *st;
  685. RTSPStream *rtsp_st;
  686. RTSPHeader reply1, *reply = &reply1;
  687. int i;
  688. char cmd[1024];
  689. /* NOTE: it is valid to flush the buffer here */
  690. if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
  691. url_fclose(&rt->rtsp_gb);
  692. }
  693. snprintf(cmd, sizeof(cmd),
  694. "TEARDOWN %s RTSP/1.0\n",
  695. s->filename);
  696. rtsp_send_cmd(s, cmd, reply, NULL);
  697. if (ff_rtsp_callback) {
  698. ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id,
  699. NULL, 0, NULL);
  700. }
  701. for(i=0;i<s->nb_streams;i++) {
  702. st = s->streams[i];
  703. rtsp_st = st->priv_data;
  704. if (rtsp_st) {
  705. if (rtsp_st->ic)
  706. av_close_input_file(rtsp_st->ic);
  707. }
  708. av_free(rtsp_st);
  709. }
  710. url_close(rt->rtsp_hd);
  711. return 0;
  712. }
  713. static AVInputFormat rtsp_demux = {
  714. "rtsp",
  715. "RTSP input format",
  716. sizeof(RTSPState),
  717. rtsp_probe,
  718. rtsp_read_header,
  719. rtsp_read_packet,
  720. rtsp_read_close,
  721. flags: AVFMT_NOFILE,
  722. };
  723. /* dummy redirector format (used directly in av_open_input_file now) */
  724. static int redir_probe(AVProbeData *pd)
  725. {
  726. const char *p;
  727. p = pd->buf;
  728. while (redir_isspace(*p))
  729. p++;
  730. if (strstart(p, "http://", NULL) ||
  731. strstart(p, "rtsp://", NULL))
  732. return AVPROBE_SCORE_MAX;
  733. return 0;
  734. }
  735. /* called from utils.c */
  736. int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f)
  737. {
  738. char buf[4096], *q;
  739. int c;
  740. AVFormatContext *ic = NULL;
  741. /* parse each URL and try to open it */
  742. c = url_fgetc(f);
  743. while (c != URL_EOF) {
  744. /* skip spaces */
  745. for(;;) {
  746. if (!redir_isspace(c))
  747. break;
  748. c = url_fgetc(f);
  749. }
  750. if (c == URL_EOF)
  751. break;
  752. /* record url */
  753. q = buf;
  754. for(;;) {
  755. if (c == URL_EOF || redir_isspace(c))
  756. break;
  757. if ((q - buf) < sizeof(buf) - 1)
  758. *q++ = c;
  759. c = url_fgetc(f);
  760. }
  761. *q = '\0';
  762. //printf("URL='%s'\n", buf);
  763. /* try to open the media file */
  764. if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)
  765. break;
  766. }
  767. *ic_ptr = ic;
  768. if (!ic)
  769. return AVERROR_IO;
  770. else
  771. return 0;
  772. }
  773. AVInputFormat redir_demux = {
  774. "redir",
  775. "Redirector format",
  776. 0,
  777. redir_probe,
  778. NULL,
  779. NULL,
  780. NULL,
  781. };
  782. int rtsp_init(void)
  783. {
  784. av_register_input_format(&rtsp_demux);
  785. av_register_input_format(&redir_demux);
  786. return 0;
  787. }