00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038
00039 #if defined (WIN32)
00040 # include <conio.h>
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
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
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
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
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
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
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
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
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
00179 int main(int argc, char * const argv[])
00180 {
00181 #if 1
00182 const char *transport = "RTP/AVP;unicast;client_port=1234-1235";
00183 #else
00184
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
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
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
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
00242 snprintf(uri, strlen(url) + 32, "%s", url);
00243 rtsp_options(curl, uri);
00244
00245
00246 rtsp_describe(curl, uri, sdp_filename);
00247
00248
00249 get_media_control_attribute(sdp_filename, control);
00250
00251
00252 snprintf(uri, strlen(url) + 32, "%s/%s", url, control);
00253 rtsp_setup(curl, uri, transport);
00254
00255
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
00263 rtsp_teardown(curl, uri);
00264
00265
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 }