rtsp.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Jim Hollinger
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *   * Redistributions of source code must retain the above copyright
00009  *     notice, this list of conditions and the following disclaimer.
00010  *   * Redistributions in binary form must reproduce the above copyright
00011  *     notice, this list of conditions and the following disclaimer in the
00012  *     documentation and/or other materials provided with the distribution.
00013  *   * Neither the name of Jim Hollinger nor the names of its contributors
00014  *     may be used to endorse or promote products derived from this
00015  *     software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00020  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00021  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00022  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00023  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00027  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  */
00030 /* <DESC>
00031  * A basic RTSP transfer
00032  * </DESC>
00033  */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #if defined (WIN32)
00040 #  include <conio.h>  /* _getch() */
00041 #else
00042 #  include <termios.h>
00043 #  include <unistd.h>
00044 
00045 static int _getch(void)
00046 {
00047   struct termios oldt, newt;
00048   int ch;
00049   tcgetattr(STDIN_FILENO, &oldt);
00050   newt = oldt;
00051   newt.c_lflag &= ~( ICANON | ECHO);
00052   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00053   ch = getchar();
00054   tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00055   return ch;
00056 }
00057 #endif
00058 
00059 #include <curl/curl.h>
00060 
00061 #define VERSION_STR  "V1.0"
00062 
00063 /* error handling macros */
00064 #define my_curl_easy_setopt(A, B, C)                             \
00065   res = curl_easy_setopt((A), (B), (C));                         \
00066   if(!res)                                                       \
00067     fprintf(stderr, "curl_easy_setopt(%s, %s, %s) failed: %d\n", \
00068             #A, #B, #C, res);
00069 
00070 #define my_curl_easy_perform(A)                                     \
00071   res = curl_easy_perform(A);                                       \
00072   if(!res)                                                          \
00073     fprintf(stderr, "curl_easy_perform(%s) failed: %d\n", #A, res);
00074 
00075 
00076 /* send RTSP OPTIONS request */
00077 static void rtsp_options(CURL *curl, const char *uri)
00078 {
00079   CURLcode res = CURLE_OK;
00080   printf("\nRTSP: OPTIONS %s\n", uri);
00081   my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri);
00082   my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
00083   my_curl_easy_perform(curl);
00084 }
00085 
00086 
00087 /* send RTSP DESCRIBE request and write sdp response to a file */
00088 static void rtsp_describe(CURL *curl, const char *uri,
00089                           const char *sdp_filename)
00090 {
00091   CURLcode res = CURLE_OK;
00092   FILE *sdp_fp = fopen(sdp_filename, "wb");
00093   printf("\nRTSP: DESCRIBE %s\n", uri);
00094   if(sdp_fp == NULL) {
00095     fprintf(stderr, "Could not open '%s' for writing\n", sdp_filename);
00096     sdp_fp = stdout;
00097   }
00098   else {
00099     printf("Writing SDP to '%s'\n", sdp_filename);
00100   }
00101   my_curl_easy_setopt(curl, CURLOPT_WRITEDATA, sdp_fp);
00102   my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
00103   my_curl_easy_perform(curl);
00104   my_curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout);
00105   if(sdp_fp != stdout) {
00106     fclose(sdp_fp);
00107   }
00108 }
00109 
00110 /* send RTSP SETUP request */
00111 static void rtsp_setup(CURL *curl, const char *uri, const char *transport)
00112 {
00113   CURLcode res = CURLE_OK;
00114   printf("\nRTSP: SETUP %s\n", uri);
00115   printf("      TRANSPORT %s\n", transport);
00116   my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri);
00117   my_curl_easy_setopt(curl, CURLOPT_RTSP_TRANSPORT, transport);
00118   my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
00119   my_curl_easy_perform(curl);
00120 }
00121 
00122 
00123 /* send RTSP PLAY request */
00124 static void rtsp_play(CURL *curl, const char *uri, const char *range)
00125 {
00126   CURLcode res = CURLE_OK;
00127   printf("\nRTSP: PLAY %s\n", uri);
00128   my_curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, uri);
00129   my_curl_easy_setopt(curl, CURLOPT_RANGE, range);
00130   my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
00131   my_curl_easy_perform(curl);
00132 }
00133 
00134 
00135 /* send RTSP TEARDOWN request */
00136 static void rtsp_teardown(CURL *curl, const char *uri)
00137 {
00138   CURLcode res = CURLE_OK;
00139   printf("\nRTSP: TEARDOWN %s\n", uri);
00140   my_curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
00141   my_curl_easy_perform(curl);
00142 }
00143 
00144 
00145 /* convert url into an sdp filename */
00146 static void get_sdp_filename(const char *url, char *sdp_filename,
00147                              size_t namelen)
00148 {
00149   const char *s = strrchr(url, '/');
00150   strcpy(sdp_filename, "video.sdp");
00151   if(s != NULL) {
00152     s++;
00153     if(s[0] != '\0') {
00154       snprintf(sdp_filename, namelen, "%s.sdp", s);
00155     }
00156   }
00157 }
00158 
00159 
00160 /* scan sdp file for media control attribute */
00161 static void get_media_control_attribute(const char *sdp_filename,
00162                                         char *control)
00163 {
00164   int max_len = 256;
00165   char *s = malloc(max_len);
00166   FILE *sdp_fp = fopen(sdp_filename, "rb");
00167   control[0] = '\0';
00168   if(sdp_fp != NULL) {
00169     while(fgets(s, max_len - 2, sdp_fp) != NULL) {
00170       sscanf(s, " a = control: %s", control);
00171     }
00172     fclose(sdp_fp);
00173   }
00174   free(s);
00175 }
00176 
00177 
00178 /* main app */
00179 int main(int argc, char * const argv[])
00180 {
00181 #if 1
00182   const char *transport = "RTP/AVP;unicast;client_port=1234-1235";  /* UDP */
00183 #else
00184   /* TCP */
00185   const char *transport = "RTP/AVP/TCP;unicast;client_port=1234-1235";
00186 #endif
00187   const char *range = "0.000-";
00188   int rc = EXIT_SUCCESS;
00189   char *base_name = NULL;
00190 
00191   printf("\nRTSP request %s\n", VERSION_STR);
00192   printf("    Project web site: http://code.google.com/p/rtsprequest/\n");
00193   printf("    Requires curl V7.20 or greater\n\n");
00194 
00195   /* check command line */
00196   if((argc != 2) && (argc != 3)) {
00197     base_name = strrchr(argv[0], '/');
00198     if(base_name == NULL) {
00199       base_name = strrchr(argv[0], '\\');
00200     }
00201     if(base_name == NULL) {
00202       base_name = argv[0];
00203     }
00204     else {
00205       base_name++;
00206     }
00207     printf("Usage:   %s url [transport]\n", base_name);
00208     printf("         url of video server\n");
00209     printf("         transport (optional) specifier for media stream"
00210            " protocol\n");
00211     printf("         default transport: %s\n", transport);
00212     printf("Example: %s rtsp://192.168.0.2/media/video1\n\n", base_name);
00213     rc = EXIT_FAILURE;
00214   }
00215   else {
00216     const char *url = argv[1];
00217     char *uri = malloc(strlen(url) + 32);
00218     char *sdp_filename = malloc(strlen(url) + 32);
00219     char *control = malloc(strlen(url) + 32);
00220     CURLcode res;
00221     get_sdp_filename(url, sdp_filename, strlen(url) + 32);
00222     if(argc == 3) {
00223       transport = argv[2];
00224     }
00225 
00226     /* initialize curl */
00227     res = curl_global_init(CURL_GLOBAL_ALL);
00228     if(res == CURLE_OK) {
00229       curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
00230       CURL *curl;
00231       fprintf(stderr, "    curl V%s loaded\n", data->version);
00232 
00233       /* initialize this curl session */
00234       curl = curl_easy_init();
00235       if(curl != NULL) {
00236         my_curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
00237         my_curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
00238         my_curl_easy_setopt(curl, CURLOPT_HEADERDATA, stdout);
00239         my_curl_easy_setopt(curl, CURLOPT_URL, url);
00240 
00241         /* request server options */
00242         snprintf(uri, strlen(url) + 32, "%s", url);
00243         rtsp_options(curl, uri);
00244 
00245         /* request session description and write response to sdp file */
00246         rtsp_describe(curl, uri, sdp_filename);
00247 
00248         /* get media control attribute from sdp file */
00249         get_media_control_attribute(sdp_filename, control);
00250 
00251         /* setup media stream */
00252         snprintf(uri, strlen(url) + 32, "%s/%s", url, control);
00253         rtsp_setup(curl, uri, transport);
00254 
00255         /* start playing media stream */
00256         snprintf(uri, strlen(url) + 32, "%s/", url);
00257         rtsp_play(curl, uri, range);
00258         printf("Playing video, press any key to stop ...");
00259         _getch();
00260         printf("\n");
00261 
00262         /* teardown session */
00263         rtsp_teardown(curl, uri);
00264 
00265         /* cleanup */
00266         curl_easy_cleanup(curl);
00267         curl = NULL;
00268       }
00269       else {
00270         fprintf(stderr, "curl_easy_init() failed\n");
00271       }
00272       curl_global_cleanup();
00273     }
00274     else {
00275       fprintf(stderr, "curl_global_init(%s) failed: %d\n",
00276               "CURL_GLOBAL_ALL", res);
00277     }
00278     free(control);
00279     free(sdp_filename);
00280     free(uri);
00281   }
00282 
00283   return rc;
00284 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06