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.

897 lines
25KB

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