00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #if !HAVE_CLOSESOCKET
00024 #define closesocket close
00025 #endif
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include "libavformat/avformat.h"
00029 #include "libavformat/ffm.h"
00030 #include "libavformat/network.h"
00031 #include "libavformat/os_support.h"
00032 #include "libavformat/rtpdec.h"
00033 #include "libavformat/rtsp.h"
00034
00035 #include "libavformat/avio_internal.h"
00036 #include "libavutil/avstring.h"
00037 #include "libavutil/lfg.h"
00038 #include "libavutil/dict.h"
00039 #include "libavutil/mathematics.h"
00040 #include "libavutil/random_seed.h"
00041 #include "libavutil/parseutils.h"
00042 #include "libavutil/opt.h"
00043 #include <stdarg.h>
00044 #include <unistd.h>
00045 #include <fcntl.h>
00046 #include <sys/ioctl.h>
00047 #if HAVE_POLL_H
00048 #include <poll.h>
00049 #endif
00050 #include <errno.h>
00051 #include <sys/time.h>
00052 #include <time.h>
00053 #include <sys/wait.h>
00054 #include <signal.h>
00055 #if HAVE_DLFCN_H
00056 #include <dlfcn.h>
00057 #endif
00058
00059 #include "cmdutils.h"
00060
00061 const char program_name[] = "ffserver";
00062 const int program_birth_year = 2000;
00063
00064 static const OptionDef options[];
00065
00066 enum HTTPState {
00067 HTTPSTATE_WAIT_REQUEST,
00068 HTTPSTATE_SEND_HEADER,
00069 HTTPSTATE_SEND_DATA_HEADER,
00070 HTTPSTATE_SEND_DATA,
00071 HTTPSTATE_SEND_DATA_TRAILER,
00072 HTTPSTATE_RECEIVE_DATA,
00073 HTTPSTATE_WAIT_FEED,
00074 HTTPSTATE_READY,
00075
00076 RTSPSTATE_WAIT_REQUEST,
00077 RTSPSTATE_SEND_REPLY,
00078 RTSPSTATE_SEND_PACKET,
00079 };
00080
00081 static const char *http_state[] = {
00082 "HTTP_WAIT_REQUEST",
00083 "HTTP_SEND_HEADER",
00084
00085 "SEND_DATA_HEADER",
00086 "SEND_DATA",
00087 "SEND_DATA_TRAILER",
00088 "RECEIVE_DATA",
00089 "WAIT_FEED",
00090 "READY",
00091
00092 "RTSP_WAIT_REQUEST",
00093 "RTSP_SEND_REPLY",
00094 "RTSP_SEND_PACKET",
00095 };
00096
00097 #define MAX_STREAMS 20
00098
00099 #define IOBUFFER_INIT_SIZE 8192
00100
00101
00102 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
00103 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
00104
00105 #define SYNC_TIMEOUT (10 * 1000)
00106
00107 typedef struct RTSPActionServerSetup {
00108 uint32_t ipaddr;
00109 char transport_option[512];
00110 } RTSPActionServerSetup;
00111
00112 typedef struct {
00113 int64_t count1, count2;
00114 int64_t time1, time2;
00115 } DataRateData;
00116
00117
00118 typedef struct HTTPContext {
00119 enum HTTPState state;
00120 int fd;
00121 struct sockaddr_in from_addr;
00122 struct pollfd *poll_entry;
00123 int64_t timeout;
00124 uint8_t *buffer_ptr, *buffer_end;
00125 int http_error;
00126 int post;
00127 int chunked_encoding;
00128 int chunk_size;
00129 struct HTTPContext *next;
00130 int got_key_frame;
00131 int64_t data_count;
00132
00133 int feed_fd;
00134
00135 AVFormatContext *fmt_in;
00136 int64_t start_time;
00137 int64_t first_pts;
00138 int64_t cur_pts;
00139 int64_t cur_frame_duration;
00140 int cur_frame_bytes;
00141
00142
00143 int pts_stream_index;
00144 int64_t cur_clock;
00145
00146 struct FFStream *stream;
00147
00148 int feed_streams[MAX_STREAMS];
00149 int switch_feed_streams[MAX_STREAMS];
00150 int switch_pending;
00151 AVFormatContext fmt_ctx;
00152 int last_packet_sent;
00153 int suppress_log;
00154 DataRateData datarate;
00155 int wmp_client_id;
00156 char protocol[16];
00157 char method[16];
00158 char url[128];
00159 int buffer_size;
00160 uint8_t *buffer;
00161 int is_packetized;
00162 int packet_stream_index;
00163
00164
00165 uint8_t *pb_buffer;
00166 AVIOContext *pb;
00167 int seq;
00168
00169
00170 enum RTSPLowerTransport rtp_protocol;
00171 char session_id[32];
00172 AVFormatContext *rtp_ctx[MAX_STREAMS];
00173
00174
00175 URLContext *rtp_handles[MAX_STREAMS];
00176
00177
00178 struct HTTPContext *rtsp_c;
00179 uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
00180 } HTTPContext;
00181
00182
00183 enum StreamType {
00184 STREAM_TYPE_LIVE,
00185 STREAM_TYPE_STATUS,
00186 STREAM_TYPE_REDIRECT,
00187 };
00188
00189 enum IPAddressAction {
00190 IP_ALLOW = 1,
00191 IP_DENY,
00192 };
00193
00194 typedef struct IPAddressACL {
00195 struct IPAddressACL *next;
00196 enum IPAddressAction action;
00197
00198 struct in_addr first;
00199 struct in_addr last;
00200 } IPAddressACL;
00201
00202
00203 typedef struct FFStream {
00204 enum StreamType stream_type;
00205 char filename[1024];
00206 struct FFStream *feed;
00207
00208 AVDictionary *in_opts;
00209 AVInputFormat *ifmt;
00210 AVOutputFormat *fmt;
00211 IPAddressACL *acl;
00212 char dynamic_acl[1024];
00213 int nb_streams;
00214 int prebuffer;
00215 int64_t max_time;
00216 int send_on_key;
00217 AVStream *streams[MAX_STREAMS];
00218 int feed_streams[MAX_STREAMS];
00219 char feed_filename[1024];
00220
00221 char author[512];
00222 char title[512];
00223 char copyright[512];
00224 char comment[512];
00225 pid_t pid;
00226 time_t pid_start;
00227 char **child_argv;
00228 struct FFStream *next;
00229 unsigned bandwidth;
00230
00231 char *rtsp_option;
00232
00233 int is_multicast;
00234 struct in_addr multicast_ip;
00235 int multicast_port;
00236 int multicast_ttl;
00237 int loop;
00238
00239
00240 int feed_opened;
00241 int is_feed;
00242 int readonly;
00243 int truncate;
00244 int conns_served;
00245 int64_t bytes_served;
00246 int64_t feed_max_size;
00247 int64_t feed_write_index;
00248 int64_t feed_size;
00249 struct FFStream *next_feed;
00250 } FFStream;
00251
00252 typedef struct FeedData {
00253 long long data_count;
00254 float avg_frame_size;
00255 } FeedData;
00256
00257 static struct sockaddr_in my_http_addr;
00258 static struct sockaddr_in my_rtsp_addr;
00259
00260 static char logfilename[1024];
00261 static HTTPContext *first_http_ctx;
00262 static FFStream *first_feed;
00263 static FFStream *first_stream;
00264
00265 static void new_connection(int server_fd, int is_rtsp);
00266 static void close_connection(HTTPContext *c);
00267
00268
00269 static int handle_connection(HTTPContext *c);
00270 static int http_parse_request(HTTPContext *c);
00271 static int http_send_data(HTTPContext *c);
00272 static void compute_status(HTTPContext *c);
00273 static int open_input_stream(HTTPContext *c, const char *info);
00274 static int http_start_receive_data(HTTPContext *c);
00275 static int http_receive_data(HTTPContext *c);
00276
00277
00278 static int rtsp_parse_request(HTTPContext *c);
00279 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
00280 static void rtsp_cmd_options(HTTPContext *c, const char *url);
00281 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00282 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00283 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00284 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
00285
00286
00287 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
00288 struct in_addr my_ip);
00289
00290
00291 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
00292 FFStream *stream, const char *session_id,
00293 enum RTSPLowerTransport rtp_protocol);
00294 static int rtp_new_av_stream(HTTPContext *c,
00295 int stream_index, struct sockaddr_in *dest_addr,
00296 HTTPContext *rtsp_c);
00297
00298 static const char *my_program_name;
00299 static const char *my_program_dir;
00300
00301 static const char *config_filename = "/etc/ffserver.conf";
00302
00303 static int ffserver_debug;
00304 static int ffserver_daemon;
00305 static int no_launch;
00306 static int need_to_start_children;
00307
00308
00309 static unsigned int nb_max_http_connections = 2000;
00310 static unsigned int nb_max_connections = 5;
00311 static unsigned int nb_connections;
00312
00313 static uint64_t max_bandwidth = 1000;
00314 static uint64_t current_bandwidth;
00315
00316 static int64_t cur_time;
00317
00318 static AVLFG random_state;
00319
00320 static FILE *logfile = NULL;
00321
00322
00323 void av_noreturn exit_program(int ret)
00324 {
00325 exit(ret);
00326 }
00327
00328
00329 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
00330 {
00331
00332 if (!ff_inet_aton(hostname, sin_addr)) {
00333 #if HAVE_GETADDRINFO
00334 struct addrinfo *ai, *cur;
00335 struct addrinfo hints;
00336 memset(&hints, 0, sizeof(hints));
00337 hints.ai_family = AF_INET;
00338 if (getaddrinfo(hostname, NULL, &hints, &ai))
00339 return -1;
00340
00341
00342
00343 for (cur = ai; cur; cur = cur->ai_next) {
00344 if (cur->ai_family == AF_INET) {
00345 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
00346 freeaddrinfo(ai);
00347 return 0;
00348 }
00349 }
00350 freeaddrinfo(ai);
00351 return -1;
00352 #else
00353 struct hostent *hp;
00354 hp = gethostbyname(hostname);
00355 if (!hp)
00356 return -1;
00357 memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
00358 #endif
00359 }
00360 return 0;
00361 }
00362
00363 static char *ctime1(char *buf2)
00364 {
00365 time_t ti;
00366 char *p;
00367
00368 ti = time(NULL);
00369 p = ctime(&ti);
00370 strcpy(buf2, p);
00371 p = buf2 + strlen(p) - 1;
00372 if (*p == '\n')
00373 *p = '\0';
00374 return buf2;
00375 }
00376
00377 static void http_vlog(const char *fmt, va_list vargs)
00378 {
00379 static int print_prefix = 1;
00380 if (logfile) {
00381 if (print_prefix) {
00382 char buf[32];
00383 ctime1(buf);
00384 fprintf(logfile, "%s ", buf);
00385 }
00386 print_prefix = strstr(fmt, "\n") != NULL;
00387 vfprintf(logfile, fmt, vargs);
00388 fflush(logfile);
00389 }
00390 }
00391
00392 #ifdef __GNUC__
00393 __attribute__ ((format (printf, 1, 2)))
00394 #endif
00395 static void http_log(const char *fmt, ...)
00396 {
00397 va_list vargs;
00398 va_start(vargs, fmt);
00399 http_vlog(fmt, vargs);
00400 va_end(vargs);
00401 }
00402
00403 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
00404 {
00405 static int print_prefix = 1;
00406 AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
00407 if (level > av_log_get_level())
00408 return;
00409 if (print_prefix && avc)
00410 http_log("[%s @ %p]", avc->item_name(ptr), ptr);
00411 print_prefix = strstr(fmt, "\n") != NULL;
00412 http_vlog(fmt, vargs);
00413 }
00414
00415 static void log_connection(HTTPContext *c)
00416 {
00417 if (c->suppress_log)
00418 return;
00419
00420 http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
00421 inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
00422 c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
00423 }
00424
00425 static void update_datarate(DataRateData *drd, int64_t count)
00426 {
00427 if (!drd->time1 && !drd->count1) {
00428 drd->time1 = drd->time2 = cur_time;
00429 drd->count1 = drd->count2 = count;
00430 } else if (cur_time - drd->time2 > 5000) {
00431 drd->time1 = drd->time2;
00432 drd->count1 = drd->count2;
00433 drd->time2 = cur_time;
00434 drd->count2 = count;
00435 }
00436 }
00437
00438
00439 static int compute_datarate(DataRateData *drd, int64_t count)
00440 {
00441 if (cur_time == drd->time1)
00442 return 0;
00443
00444 return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
00445 }
00446
00447
00448 static void start_children(FFStream *feed)
00449 {
00450 if (no_launch)
00451 return;
00452
00453 for (; feed; feed = feed->next) {
00454 if (feed->child_argv && !feed->pid) {
00455 feed->pid_start = time(0);
00456
00457 feed->pid = fork();
00458
00459 if (feed->pid < 0) {
00460 http_log("Unable to create children\n");
00461 exit(1);
00462 }
00463 if (!feed->pid) {
00464
00465 char pathname[1024];
00466 char *slash;
00467 int i;
00468
00469 av_strlcpy(pathname, my_program_name, sizeof(pathname));
00470
00471 slash = strrchr(pathname, '/');
00472 if (!slash)
00473 slash = pathname;
00474 else
00475 slash++;
00476 strcpy(slash, "ffmpeg");
00477
00478 http_log("Launch commandline: ");
00479 http_log("%s ", pathname);
00480 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
00481 http_log("%s ", feed->child_argv[i]);
00482 http_log("\n");
00483
00484 for (i = 3; i < 256; i++)
00485 close(i);
00486
00487 if (!ffserver_debug) {
00488 i = open("/dev/null", O_RDWR);
00489 if (i != -1) {
00490 dup2(i, 0);
00491 dup2(i, 1);
00492 dup2(i, 2);
00493 close(i);
00494 }
00495 }
00496
00497
00498 chdir(my_program_dir);
00499
00500 signal(SIGPIPE, SIG_DFL);
00501
00502 execvp(pathname, feed->child_argv);
00503
00504 _exit(1);
00505 }
00506 }
00507 }
00508 }
00509
00510
00511 static int socket_open_listen(struct sockaddr_in *my_addr)
00512 {
00513 int server_fd, tmp;
00514
00515 server_fd = socket(AF_INET,SOCK_STREAM,0);
00516 if (server_fd < 0) {
00517 perror ("socket");
00518 return -1;
00519 }
00520
00521 tmp = 1;
00522 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
00523
00524 my_addr->sin_family = AF_INET;
00525 if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
00526 char bindmsg[32];
00527 snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
00528 perror (bindmsg);
00529 closesocket(server_fd);
00530 return -1;
00531 }
00532
00533 if (listen (server_fd, 5) < 0) {
00534 perror ("listen");
00535 closesocket(server_fd);
00536 return -1;
00537 }
00538 ff_socket_nonblock(server_fd, 1);
00539
00540 return server_fd;
00541 }
00542
00543
00544 static void start_multicast(void)
00545 {
00546 FFStream *stream;
00547 char session_id[32];
00548 HTTPContext *rtp_c;
00549 struct sockaddr_in dest_addr;
00550 int default_port, stream_index;
00551
00552 default_port = 6000;
00553 for(stream = first_stream; stream != NULL; stream = stream->next) {
00554 if (stream->is_multicast) {
00555
00556 snprintf(session_id, sizeof(session_id), "%08x%08x",
00557 av_lfg_get(&random_state), av_lfg_get(&random_state));
00558
00559
00560 if (stream->multicast_port == 0) {
00561 stream->multicast_port = default_port;
00562 default_port += 100;
00563 }
00564
00565 dest_addr.sin_family = AF_INET;
00566 dest_addr.sin_addr = stream->multicast_ip;
00567 dest_addr.sin_port = htons(stream->multicast_port);
00568
00569 rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
00570 RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
00571 if (!rtp_c)
00572 continue;
00573
00574 if (open_input_stream(rtp_c, "") < 0) {
00575 http_log("Could not open input stream for stream '%s'\n",
00576 stream->filename);
00577 continue;
00578 }
00579
00580
00581 for(stream_index = 0; stream_index < stream->nb_streams;
00582 stream_index++) {
00583 dest_addr.sin_port = htons(stream->multicast_port +
00584 2 * stream_index);
00585 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
00586 http_log("Could not open output stream '%s/streamid=%d'\n",
00587 stream->filename, stream_index);
00588 exit(1);
00589 }
00590 }
00591
00592
00593 rtp_c->state = HTTPSTATE_SEND_DATA;
00594 }
00595 }
00596 }
00597
00598
00599 static int http_server(void)
00600 {
00601 int server_fd = 0, rtsp_server_fd = 0;
00602 int ret, delay, delay1;
00603 struct pollfd *poll_table, *poll_entry;
00604 HTTPContext *c, *c_next;
00605
00606 if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
00607 http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
00608 return -1;
00609 }
00610
00611 if (my_http_addr.sin_port) {
00612 server_fd = socket_open_listen(&my_http_addr);
00613 if (server_fd < 0)
00614 return -1;
00615 }
00616
00617 if (my_rtsp_addr.sin_port) {
00618 rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
00619 if (rtsp_server_fd < 0)
00620 return -1;
00621 }
00622
00623 if (!rtsp_server_fd && !server_fd) {
00624 http_log("HTTP and RTSP disabled.\n");
00625 return -1;
00626 }
00627
00628 http_log("FFserver started.\n");
00629
00630 start_children(first_feed);
00631
00632 start_multicast();
00633
00634 for(;;) {
00635 poll_entry = poll_table;
00636 if (server_fd) {
00637 poll_entry->fd = server_fd;
00638 poll_entry->events = POLLIN;
00639 poll_entry++;
00640 }
00641 if (rtsp_server_fd) {
00642 poll_entry->fd = rtsp_server_fd;
00643 poll_entry->events = POLLIN;
00644 poll_entry++;
00645 }
00646
00647
00648 c = first_http_ctx;
00649 delay = 1000;
00650 while (c != NULL) {
00651 int fd;
00652 fd = c->fd;
00653 switch(c->state) {
00654 case HTTPSTATE_SEND_HEADER:
00655 case RTSPSTATE_SEND_REPLY:
00656 case RTSPSTATE_SEND_PACKET:
00657 c->poll_entry = poll_entry;
00658 poll_entry->fd = fd;
00659 poll_entry->events = POLLOUT;
00660 poll_entry++;
00661 break;
00662 case HTTPSTATE_SEND_DATA_HEADER:
00663 case HTTPSTATE_SEND_DATA:
00664 case HTTPSTATE_SEND_DATA_TRAILER:
00665 if (!c->is_packetized) {
00666
00667 c->poll_entry = poll_entry;
00668 poll_entry->fd = fd;
00669 poll_entry->events = POLLOUT;
00670 poll_entry++;
00671 } else {
00672
00673
00674
00675 delay1 = 10;
00676 if (delay1 < delay)
00677 delay = delay1;
00678 }
00679 break;
00680 case HTTPSTATE_WAIT_REQUEST:
00681 case HTTPSTATE_RECEIVE_DATA:
00682 case HTTPSTATE_WAIT_FEED:
00683 case RTSPSTATE_WAIT_REQUEST:
00684
00685 c->poll_entry = poll_entry;
00686 poll_entry->fd = fd;
00687 poll_entry->events = POLLIN;
00688 poll_entry++;
00689 break;
00690 default:
00691 c->poll_entry = NULL;
00692 break;
00693 }
00694 c = c->next;
00695 }
00696
00697
00698
00699 do {
00700 ret = poll(poll_table, poll_entry - poll_table, delay);
00701 if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
00702 ff_neterrno() != AVERROR(EINTR))
00703 return -1;
00704 } while (ret < 0);
00705
00706 cur_time = av_gettime() / 1000;
00707
00708 if (need_to_start_children) {
00709 need_to_start_children = 0;
00710 start_children(first_feed);
00711 }
00712
00713
00714 for(c = first_http_ctx; c != NULL; c = c_next) {
00715 c_next = c->next;
00716 if (handle_connection(c) < 0) {
00717
00718 log_connection(c);
00719 close_connection(c);
00720 }
00721 }
00722
00723 poll_entry = poll_table;
00724 if (server_fd) {
00725
00726 if (poll_entry->revents & POLLIN)
00727 new_connection(server_fd, 0);
00728 poll_entry++;
00729 }
00730 if (rtsp_server_fd) {
00731
00732 if (poll_entry->revents & POLLIN)
00733 new_connection(rtsp_server_fd, 1);
00734 }
00735 }
00736 }
00737
00738
00739 static void start_wait_request(HTTPContext *c, int is_rtsp)
00740 {
00741 c->buffer_ptr = c->buffer;
00742 c->buffer_end = c->buffer + c->buffer_size - 1;
00743
00744 if (is_rtsp) {
00745 c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
00746 c->state = RTSPSTATE_WAIT_REQUEST;
00747 } else {
00748 c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
00749 c->state = HTTPSTATE_WAIT_REQUEST;
00750 }
00751 }
00752
00753 static void http_send_too_busy_reply(int fd)
00754 {
00755 char buffer[300];
00756 int len = snprintf(buffer, sizeof(buffer),
00757 "HTTP/1.0 503 Server too busy\r\n"
00758 "Content-type: text/html\r\n"
00759 "\r\n"
00760 "<html><head><title>Too busy</title></head><body>\r\n"
00761 "<p>The server is too busy to serve your request at this time.</p>\r\n"
00762 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
00763 "</body></html>\r\n",
00764 nb_connections, nb_max_connections);
00765 send(fd, buffer, len, 0);
00766 }
00767
00768
00769 static void new_connection(int server_fd, int is_rtsp)
00770 {
00771 struct sockaddr_in from_addr;
00772 int fd, len;
00773 HTTPContext *c = NULL;
00774
00775 len = sizeof(from_addr);
00776 fd = accept(server_fd, (struct sockaddr *)&from_addr,
00777 &len);
00778 if (fd < 0) {
00779 http_log("error during accept %s\n", strerror(errno));
00780 return;
00781 }
00782 ff_socket_nonblock(fd, 1);
00783
00784 if (nb_connections >= nb_max_connections) {
00785 http_send_too_busy_reply(fd);
00786 goto fail;
00787 }
00788
00789
00790 c = av_mallocz(sizeof(HTTPContext));
00791 if (!c)
00792 goto fail;
00793
00794 c->fd = fd;
00795 c->poll_entry = NULL;
00796 c->from_addr = from_addr;
00797 c->buffer_size = IOBUFFER_INIT_SIZE;
00798 c->buffer = av_malloc(c->buffer_size);
00799 if (!c->buffer)
00800 goto fail;
00801
00802 c->next = first_http_ctx;
00803 first_http_ctx = c;
00804 nb_connections++;
00805
00806 start_wait_request(c, is_rtsp);
00807
00808 return;
00809
00810 fail:
00811 if (c) {
00812 av_free(c->buffer);
00813 av_free(c);
00814 }
00815 closesocket(fd);
00816 }
00817
00818 static void close_connection(HTTPContext *c)
00819 {
00820 HTTPContext **cp, *c1;
00821 int i, nb_streams;
00822 AVFormatContext *ctx;
00823 URLContext *h;
00824 AVStream *st;
00825
00826
00827 cp = &first_http_ctx;
00828 while ((*cp) != NULL) {
00829 c1 = *cp;
00830 if (c1 == c)
00831 *cp = c->next;
00832 else
00833 cp = &c1->next;
00834 }
00835
00836
00837 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
00838 if (c1->rtsp_c == c)
00839 c1->rtsp_c = NULL;
00840 }
00841
00842
00843 if (c->fd >= 0)
00844 closesocket(c->fd);
00845 if (c->fmt_in) {
00846
00847 for(i=0;i<c->fmt_in->nb_streams;i++) {
00848 st = c->fmt_in->streams[i];
00849 if (st->codec->codec)
00850 avcodec_close(st->codec);
00851 }
00852 av_close_input_file(c->fmt_in);
00853 }
00854
00855
00856 nb_streams = 0;
00857 if (c->stream)
00858 nb_streams = c->stream->nb_streams;
00859
00860 for(i=0;i<nb_streams;i++) {
00861 ctx = c->rtp_ctx[i];
00862 if (ctx) {
00863 av_write_trailer(ctx);
00864 av_dict_free(&ctx->metadata);
00865 av_free(ctx->streams[0]);
00866 av_free(ctx);
00867 }
00868 h = c->rtp_handles[i];
00869 if (h)
00870 url_close(h);
00871 }
00872
00873 ctx = &c->fmt_ctx;
00874
00875 if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
00876 if (ctx->oformat) {
00877
00878 if (avio_open_dyn_buf(&ctx->pb) >= 0) {
00879 av_write_trailer(ctx);
00880 av_freep(&c->pb_buffer);
00881 avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
00882 }
00883 }
00884 }
00885
00886 for(i=0; i<ctx->nb_streams; i++)
00887 av_free(ctx->streams[i]);
00888
00889 if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
00890 current_bandwidth -= c->stream->bandwidth;
00891
00892
00893 if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
00894 c->stream->feed_opened = 0;
00895 close(c->feed_fd);
00896 }
00897
00898 av_freep(&c->pb_buffer);
00899 av_freep(&c->packet_buffer);
00900 av_free(c->buffer);
00901 av_free(c);
00902 nb_connections--;
00903 }
00904
00905 static int handle_connection(HTTPContext *c)
00906 {
00907 int len, ret;
00908
00909 switch(c->state) {
00910 case HTTPSTATE_WAIT_REQUEST:
00911 case RTSPSTATE_WAIT_REQUEST:
00912
00913 if ((c->timeout - cur_time) < 0)
00914 return -1;
00915 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00916 return -1;
00917
00918
00919 if (!(c->poll_entry->revents & POLLIN))
00920 return 0;
00921
00922 read_loop:
00923 len = recv(c->fd, c->buffer_ptr, 1, 0);
00924 if (len < 0) {
00925 if (ff_neterrno() != AVERROR(EAGAIN) &&
00926 ff_neterrno() != AVERROR(EINTR))
00927 return -1;
00928 } else if (len == 0) {
00929 return -1;
00930 } else {
00931
00932 uint8_t *ptr;
00933 c->buffer_ptr += len;
00934 ptr = c->buffer_ptr;
00935 if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
00936 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
00937
00938 if (c->state == HTTPSTATE_WAIT_REQUEST) {
00939 ret = http_parse_request(c);
00940 } else {
00941 ret = rtsp_parse_request(c);
00942 }
00943 if (ret < 0)
00944 return -1;
00945 } else if (ptr >= c->buffer_end) {
00946
00947 return -1;
00948 } else goto read_loop;
00949 }
00950 break;
00951
00952 case HTTPSTATE_SEND_HEADER:
00953 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00954 return -1;
00955
00956
00957 if (!(c->poll_entry->revents & POLLOUT))
00958 return 0;
00959 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
00960 if (len < 0) {
00961 if (ff_neterrno() != AVERROR(EAGAIN) &&
00962 ff_neterrno() != AVERROR(EINTR)) {
00963
00964 av_freep(&c->pb_buffer);
00965 return -1;
00966 }
00967 } else {
00968 c->buffer_ptr += len;
00969 if (c->stream)
00970 c->stream->bytes_served += len;
00971 c->data_count += len;
00972 if (c->buffer_ptr >= c->buffer_end) {
00973 av_freep(&c->pb_buffer);
00974
00975 if (c->http_error)
00976 return -1;
00977
00978 c->state = HTTPSTATE_SEND_DATA_HEADER;
00979 c->buffer_ptr = c->buffer_end = c->buffer;
00980 }
00981 }
00982 break;
00983
00984 case HTTPSTATE_SEND_DATA:
00985 case HTTPSTATE_SEND_DATA_HEADER:
00986 case HTTPSTATE_SEND_DATA_TRAILER:
00987
00988
00989
00990 if (!c->is_packetized) {
00991 if (c->poll_entry->revents & (POLLERR | POLLHUP))
00992 return -1;
00993
00994
00995 if (!(c->poll_entry->revents & POLLOUT))
00996 return 0;
00997 }
00998 if (http_send_data(c) < 0)
00999 return -1;
01000
01001 if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
01002 return -1;
01003 break;
01004 case HTTPSTATE_RECEIVE_DATA:
01005
01006 if (c->poll_entry->revents & (POLLERR | POLLHUP))
01007 return -1;
01008 if (!(c->poll_entry->revents & POLLIN))
01009 return 0;
01010 if (http_receive_data(c) < 0)
01011 return -1;
01012 break;
01013 case HTTPSTATE_WAIT_FEED:
01014
01015 if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
01016 return -1;
01017
01018
01019 break;
01020
01021 case RTSPSTATE_SEND_REPLY:
01022 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
01023 av_freep(&c->pb_buffer);
01024 return -1;
01025 }
01026
01027 if (!(c->poll_entry->revents & POLLOUT))
01028 return 0;
01029 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
01030 if (len < 0) {
01031 if (ff_neterrno() != AVERROR(EAGAIN) &&
01032 ff_neterrno() != AVERROR(EINTR)) {
01033
01034 av_freep(&c->pb_buffer);
01035 return -1;
01036 }
01037 } else {
01038 c->buffer_ptr += len;
01039 c->data_count += len;
01040 if (c->buffer_ptr >= c->buffer_end) {
01041
01042 av_freep(&c->pb_buffer);
01043 start_wait_request(c, 1);
01044 }
01045 }
01046 break;
01047 case RTSPSTATE_SEND_PACKET:
01048 if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
01049 av_freep(&c->packet_buffer);
01050 return -1;
01051 }
01052
01053 if (!(c->poll_entry->revents & POLLOUT))
01054 return 0;
01055 len = send(c->fd, c->packet_buffer_ptr,
01056 c->packet_buffer_end - c->packet_buffer_ptr, 0);
01057 if (len < 0) {
01058 if (ff_neterrno() != AVERROR(EAGAIN) &&
01059 ff_neterrno() != AVERROR(EINTR)) {
01060
01061 av_freep(&c->packet_buffer);
01062 return -1;
01063 }
01064 } else {
01065 c->packet_buffer_ptr += len;
01066 if (c->packet_buffer_ptr >= c->packet_buffer_end) {
01067
01068 av_freep(&c->packet_buffer);
01069 c->state = RTSPSTATE_WAIT_REQUEST;
01070 }
01071 }
01072 break;
01073 case HTTPSTATE_READY:
01074
01075 break;
01076 default:
01077 return -1;
01078 }
01079 return 0;
01080 }
01081
01082 static int extract_rates(char *rates, int ratelen, const char *request)
01083 {
01084 const char *p;
01085
01086 for (p = request; *p && *p != '\r' && *p != '\n'; ) {
01087 if (av_strncasecmp(p, "Pragma:", 7) == 0) {
01088 const char *q = p + 7;
01089
01090 while (*q && *q != '\n' && isspace(*q))
01091 q++;
01092
01093 if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
01094 int stream_no;
01095 int rate_no;
01096
01097 q += 20;
01098
01099 memset(rates, 0xff, ratelen);
01100
01101 while (1) {
01102 while (*q && *q != '\n' && *q != ':')
01103 q++;
01104
01105 if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
01106 break;
01107
01108 stream_no--;
01109 if (stream_no < ratelen && stream_no >= 0)
01110 rates[stream_no] = rate_no;
01111
01112 while (*q && *q != '\n' && !isspace(*q))
01113 q++;
01114 }
01115
01116 return 1;
01117 }
01118 }
01119 p = strchr(p, '\n');
01120 if (!p)
01121 break;
01122
01123 p++;
01124 }
01125
01126 return 0;
01127 }
01128
01129 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
01130 {
01131 int i;
01132 int best_bitrate = 100000000;
01133 int best = -1;
01134
01135 for (i = 0; i < feed->nb_streams; i++) {
01136 AVCodecContext *feed_codec = feed->streams[i]->codec;
01137
01138 if (feed_codec->codec_id != codec->codec_id ||
01139 feed_codec->sample_rate != codec->sample_rate ||
01140 feed_codec->width != codec->width ||
01141 feed_codec->height != codec->height)
01142 continue;
01143
01144
01145
01146
01147
01148
01149
01150 if (feed_codec->bit_rate <= bit_rate) {
01151 if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
01152 best_bitrate = feed_codec->bit_rate;
01153 best = i;
01154 }
01155 } else {
01156 if (feed_codec->bit_rate < best_bitrate) {
01157 best_bitrate = feed_codec->bit_rate;
01158 best = i;
01159 }
01160 }
01161 }
01162
01163 return best;
01164 }
01165
01166 static int modify_current_stream(HTTPContext *c, char *rates)
01167 {
01168 int i;
01169 FFStream *req = c->stream;
01170 int action_required = 0;
01171
01172
01173 if (!req->feed)
01174 return 0;
01175
01176 for (i = 0; i < req->nb_streams; i++) {
01177 AVCodecContext *codec = req->streams[i]->codec;
01178
01179 switch(rates[i]) {
01180 case 0:
01181 c->switch_feed_streams[i] = req->feed_streams[i];
01182 break;
01183 case 1:
01184 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
01185 break;
01186 case 2:
01187
01188 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
01189 #ifdef WANTS_OFF
01190
01191 c->switch_feed_streams[i] = -2;
01192 c->feed_streams[i] = -2;
01193 #endif
01194 break;
01195 }
01196
01197 if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
01198 action_required = 1;
01199 }
01200
01201 return action_required;
01202 }
01203
01204
01205
01206 static void skip_spaces(const char **pp)
01207 {
01208 const char *p;
01209 p = *pp;
01210 while (*p == ' ' || *p == '\t')
01211 p++;
01212 *pp = p;
01213 }
01214
01215 static void get_word(char *buf, int buf_size, const char **pp)
01216 {
01217 const char *p;
01218 char *q;
01219
01220 p = *pp;
01221 skip_spaces(&p);
01222 q = buf;
01223 while (!isspace(*p) && *p != '\0') {
01224 if ((q - buf) < buf_size - 1)
01225 *q++ = *p;
01226 p++;
01227 }
01228 if (buf_size > 0)
01229 *q = '\0';
01230 *pp = p;
01231 }
01232
01233 static void get_arg(char *buf, int buf_size, const char **pp)
01234 {
01235 const char *p;
01236 char *q;
01237 int quote;
01238
01239 p = *pp;
01240 while (isspace(*p)) p++;
01241 q = buf;
01242 quote = 0;
01243 if (*p == '\"' || *p == '\'')
01244 quote = *p++;
01245 for(;;) {
01246 if (quote) {
01247 if (*p == quote)
01248 break;
01249 } else {
01250 if (isspace(*p))
01251 break;
01252 }
01253 if (*p == '\0')
01254 break;
01255 if ((q - buf) < buf_size - 1)
01256 *q++ = *p;
01257 p++;
01258 }
01259 *q = '\0';
01260 if (quote && *p == quote)
01261 p++;
01262 *pp = p;
01263 }
01264
01265 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
01266 const char *p, const char *filename, int line_num)
01267 {
01268 char arg[1024];
01269 IPAddressACL acl;
01270 int errors = 0;
01271
01272 get_arg(arg, sizeof(arg), &p);
01273 if (av_strcasecmp(arg, "allow") == 0)
01274 acl.action = IP_ALLOW;
01275 else if (av_strcasecmp(arg, "deny") == 0)
01276 acl.action = IP_DENY;
01277 else {
01278 fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
01279 filename, line_num, arg);
01280 errors++;
01281 }
01282
01283 get_arg(arg, sizeof(arg), &p);
01284
01285 if (resolve_host(&acl.first, arg) != 0) {
01286 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
01287 filename, line_num, arg);
01288 errors++;
01289 } else
01290 acl.last = acl.first;
01291
01292 get_arg(arg, sizeof(arg), &p);
01293
01294 if (arg[0]) {
01295 if (resolve_host(&acl.last, arg) != 0) {
01296 fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
01297 filename, line_num, arg);
01298 errors++;
01299 }
01300 }
01301
01302 if (!errors) {
01303 IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
01304 IPAddressACL **naclp = 0;
01305
01306 acl.next = 0;
01307 *nacl = acl;
01308
01309 if (stream)
01310 naclp = &stream->acl;
01311 else if (feed)
01312 naclp = &feed->acl;
01313 else if (ext_acl)
01314 naclp = &ext_acl;
01315 else {
01316 fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
01317 filename, line_num);
01318 errors++;
01319 }
01320
01321 if (naclp) {
01322 while (*naclp)
01323 naclp = &(*naclp)->next;
01324
01325 *naclp = nacl;
01326 }
01327 }
01328 }
01329
01330
01331 static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
01332 {
01333 FILE* f;
01334 char line[1024];
01335 char cmd[1024];
01336 IPAddressACL *acl = NULL;
01337 int line_num = 0;
01338 const char *p;
01339
01340 f = fopen(stream->dynamic_acl, "r");
01341 if (!f) {
01342 perror(stream->dynamic_acl);
01343 return NULL;
01344 }
01345
01346 acl = av_mallocz(sizeof(IPAddressACL));
01347
01348
01349 for(;;) {
01350 if (fgets(line, sizeof(line), f) == NULL)
01351 break;
01352 line_num++;
01353 p = line;
01354 while (isspace(*p))
01355 p++;
01356 if (*p == '\0' || *p == '#')
01357 continue;
01358 get_arg(cmd, sizeof(cmd), &p);
01359
01360 if (!av_strcasecmp(cmd, "ACL"))
01361 parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
01362 }
01363 fclose(f);
01364 return acl;
01365 }
01366
01367
01368 static void free_acl_list(IPAddressACL *in_acl)
01369 {
01370 IPAddressACL *pacl,*pacl2;
01371
01372 pacl = in_acl;
01373 while(pacl) {
01374 pacl2 = pacl;
01375 pacl = pacl->next;
01376 av_freep(pacl2);
01377 }
01378 }
01379
01380 static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
01381 {
01382 enum IPAddressAction last_action = IP_DENY;
01383 IPAddressACL *acl;
01384 struct in_addr *src = &c->from_addr.sin_addr;
01385 unsigned long src_addr = src->s_addr;
01386
01387 for (acl = in_acl; acl; acl = acl->next) {
01388 if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
01389 return (acl->action == IP_ALLOW) ? 1 : 0;
01390 last_action = acl->action;
01391 }
01392
01393
01394 return (last_action == IP_DENY) ? 1 : 0;
01395 }
01396
01397 static int validate_acl(FFStream *stream, HTTPContext *c)
01398 {
01399 int ret = 0;
01400 IPAddressACL *acl;
01401
01402
01403
01404 ret = validate_acl_list(stream->acl, c);
01405
01406 if (stream->dynamic_acl[0]) {
01407 acl = parse_dynamic_acl(stream, c);
01408
01409 ret = validate_acl_list(acl, c);
01410
01411 free_acl_list(acl);
01412 }
01413
01414 return ret;
01415 }
01416
01417
01418
01419 static void compute_real_filename(char *filename, int max_size)
01420 {
01421 char file1[1024];
01422 char file2[1024];
01423 char *p;
01424 FFStream *stream;
01425
01426
01427 av_strlcpy(file1, filename, sizeof(file1));
01428 p = strrchr(file1, '.');
01429 if (p)
01430 *p = '\0';
01431 for(stream = first_stream; stream != NULL; stream = stream->next) {
01432 av_strlcpy(file2, stream->filename, sizeof(file2));
01433 p = strrchr(file2, '.');
01434 if (p)
01435 *p = '\0';
01436 if (!strcmp(file1, file2)) {
01437 av_strlcpy(filename, stream->filename, max_size);
01438 break;
01439 }
01440 }
01441 }
01442
01443 enum RedirType {
01444 REDIR_NONE,
01445 REDIR_ASX,
01446 REDIR_RAM,
01447 REDIR_ASF,
01448 REDIR_RTSP,
01449 REDIR_SDP,
01450 };
01451
01452
01453 static int http_parse_request(HTTPContext *c)
01454 {
01455 char *p;
01456 enum RedirType redir_type;
01457 char cmd[32];
01458 char info[1024], filename[1024];
01459 char url[1024], *q;
01460 char protocol[32];
01461 char msg[1024];
01462 const char *mime_type;
01463 FFStream *stream;
01464 int i;
01465 char ratebuf[32];
01466 char *useragent = 0;
01467
01468 p = c->buffer;
01469 get_word(cmd, sizeof(cmd), (const char **)&p);
01470 av_strlcpy(c->method, cmd, sizeof(c->method));
01471
01472 if (!strcmp(cmd, "GET"))
01473 c->post = 0;
01474 else if (!strcmp(cmd, "POST"))
01475 c->post = 1;
01476 else
01477 return -1;
01478
01479 get_word(url, sizeof(url), (const char **)&p);
01480 av_strlcpy(c->url, url, sizeof(c->url));
01481
01482 get_word(protocol, sizeof(protocol), (const char **)&p);
01483 if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
01484 return -1;
01485
01486 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
01487
01488 if (ffserver_debug)
01489 http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
01490
01491
01492 p = strchr(url, '?');
01493 if (p) {
01494 av_strlcpy(info, p, sizeof(info));
01495 *p = '\0';
01496 } else
01497 info[0] = '\0';
01498
01499 av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
01500
01501 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01502 if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
01503 useragent = p + 11;
01504 if (*useragent && *useragent != '\n' && isspace(*useragent))
01505 useragent++;
01506 break;
01507 }
01508 p = strchr(p, '\n');
01509 if (!p)
01510 break;
01511
01512 p++;
01513 }
01514
01515 redir_type = REDIR_NONE;
01516 if (av_match_ext(filename, "asx")) {
01517 redir_type = REDIR_ASX;
01518 filename[strlen(filename)-1] = 'f';
01519 } else if (av_match_ext(filename, "asf") &&
01520 (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
01521
01522 redir_type = REDIR_ASF;
01523 } else if (av_match_ext(filename, "rpm,ram")) {
01524 redir_type = REDIR_RAM;
01525 strcpy(filename + strlen(filename)-2, "m");
01526 } else if (av_match_ext(filename, "rtsp")) {
01527 redir_type = REDIR_RTSP;
01528 compute_real_filename(filename, sizeof(filename) - 1);
01529 } else if (av_match_ext(filename, "sdp")) {
01530 redir_type = REDIR_SDP;
01531 compute_real_filename(filename, sizeof(filename) - 1);
01532 }
01533
01534
01535 if (!strlen(filename))
01536 av_strlcpy(filename, "index.html", sizeof(filename) - 1);
01537
01538 stream = first_stream;
01539 while (stream != NULL) {
01540 if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
01541 break;
01542 stream = stream->next;
01543 }
01544 if (stream == NULL) {
01545 snprintf(msg, sizeof(msg), "File '%s' not found", url);
01546 http_log("File '%s' not found\n", url);
01547 goto send_error;
01548 }
01549
01550 c->stream = stream;
01551 memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
01552 memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
01553
01554 if (stream->stream_type == STREAM_TYPE_REDIRECT) {
01555 c->http_error = 301;
01556 q = c->buffer;
01557 q += snprintf(q, c->buffer_size,
01558 "HTTP/1.0 301 Moved\r\n"
01559 "Location: %s\r\n"
01560 "Content-type: text/html\r\n"
01561 "\r\n"
01562 "<html><head><title>Moved</title></head><body>\r\n"
01563 "You should be <a href=\"%s\">redirected</a>.\r\n"
01564 "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
01565
01566 c->buffer_ptr = c->buffer;
01567 c->buffer_end = q;
01568 c->state = HTTPSTATE_SEND_HEADER;
01569 return 0;
01570 }
01571
01572
01573 if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
01574 if (modify_current_stream(c, ratebuf)) {
01575 for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
01576 if (c->switch_feed_streams[i] >= 0)
01577 c->switch_feed_streams[i] = -1;
01578 }
01579 }
01580 }
01581
01582 if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
01583 current_bandwidth += stream->bandwidth;
01584
01585
01586 if (stream->feed_opened) {
01587 snprintf(msg, sizeof(msg), "This feed is already being received.");
01588 http_log("Feed '%s' already being received\n", stream->feed_filename);
01589 goto send_error;
01590 }
01591
01592 if (c->post == 0 && max_bandwidth < current_bandwidth) {
01593 c->http_error = 503;
01594 q = c->buffer;
01595 q += snprintf(q, c->buffer_size,
01596 "HTTP/1.0 503 Server too busy\r\n"
01597 "Content-type: text/html\r\n"
01598 "\r\n"
01599 "<html><head><title>Too busy</title></head><body>\r\n"
01600 "<p>The server is too busy to serve your request at this time.</p>\r\n"
01601 "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
01602 "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
01603 "</body></html>\r\n", current_bandwidth, max_bandwidth);
01604
01605 c->buffer_ptr = c->buffer;
01606 c->buffer_end = q;
01607 c->state = HTTPSTATE_SEND_HEADER;
01608 return 0;
01609 }
01610
01611 if (redir_type != REDIR_NONE) {
01612 char *hostinfo = 0;
01613
01614 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01615 if (av_strncasecmp(p, "Host:", 5) == 0) {
01616 hostinfo = p + 5;
01617 break;
01618 }
01619 p = strchr(p, '\n');
01620 if (!p)
01621 break;
01622
01623 p++;
01624 }
01625
01626 if (hostinfo) {
01627 char *eoh;
01628 char hostbuf[260];
01629
01630 while (isspace(*hostinfo))
01631 hostinfo++;
01632
01633 eoh = strchr(hostinfo, '\n');
01634 if (eoh) {
01635 if (eoh[-1] == '\r')
01636 eoh--;
01637
01638 if (eoh - hostinfo < sizeof(hostbuf) - 1) {
01639 memcpy(hostbuf, hostinfo, eoh - hostinfo);
01640 hostbuf[eoh - hostinfo] = 0;
01641
01642 c->http_error = 200;
01643 q = c->buffer;
01644 switch(redir_type) {
01645 case REDIR_ASX:
01646 q += snprintf(q, c->buffer_size,
01647 "HTTP/1.0 200 ASX Follows\r\n"
01648 "Content-type: video/x-ms-asf\r\n"
01649 "\r\n"
01650 "<ASX Version=\"3\">\r\n"
01651
01652 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
01653 "</ASX>\r\n", hostbuf, filename, info);
01654 break;
01655 case REDIR_RAM:
01656 q += snprintf(q, c->buffer_size,
01657 "HTTP/1.0 200 RAM Follows\r\n"
01658 "Content-type: audio/x-pn-realaudio\r\n"
01659 "\r\n"
01660 "# Autogenerated by ffserver\r\n"
01661 "http://%s/%s%s\r\n", hostbuf, filename, info);
01662 break;
01663 case REDIR_ASF:
01664 q += snprintf(q, c->buffer_size,
01665 "HTTP/1.0 200 ASF Redirect follows\r\n"
01666 "Content-type: video/x-ms-asf\r\n"
01667 "\r\n"
01668 "[Reference]\r\n"
01669 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
01670 break;
01671 case REDIR_RTSP:
01672 {
01673 char hostname[256], *p;
01674
01675 av_strlcpy(hostname, hostbuf, sizeof(hostname));
01676 p = strrchr(hostname, ':');
01677 if (p)
01678 *p = '\0';
01679 q += snprintf(q, c->buffer_size,
01680 "HTTP/1.0 200 RTSP Redirect follows\r\n"
01681
01682 "Content-type: application/x-rtsp\r\n"
01683 "\r\n"
01684 "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
01685 }
01686 break;
01687 case REDIR_SDP:
01688 {
01689 uint8_t *sdp_data;
01690 int sdp_data_size, len;
01691 struct sockaddr_in my_addr;
01692
01693 q += snprintf(q, c->buffer_size,
01694 "HTTP/1.0 200 OK\r\n"
01695 "Content-type: application/sdp\r\n"
01696 "\r\n");
01697
01698 len = sizeof(my_addr);
01699 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
01700
01701
01702 sdp_data_size = prepare_sdp_description(stream,
01703 &sdp_data,
01704 my_addr.sin_addr);
01705 if (sdp_data_size > 0) {
01706 memcpy(q, sdp_data, sdp_data_size);
01707 q += sdp_data_size;
01708 *q = '\0';
01709 av_free(sdp_data);
01710 }
01711 }
01712 break;
01713 default:
01714 abort();
01715 break;
01716 }
01717
01718
01719 c->buffer_ptr = c->buffer;
01720 c->buffer_end = q;
01721 c->state = HTTPSTATE_SEND_HEADER;
01722 return 0;
01723 }
01724 }
01725 }
01726
01727 snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
01728 goto send_error;
01729 }
01730
01731 stream->conns_served++;
01732
01733
01734
01735 if (c->post) {
01736
01737 if (!stream->is_feed) {
01738
01739
01740 char *logline = 0;
01741 int client_id = 0;
01742
01743 for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
01744 if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
01745 logline = p;
01746 break;
01747 }
01748 if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
01749 client_id = strtol(p + 18, 0, 10);
01750 p = strchr(p, '\n');
01751 if (!p)
01752 break;
01753
01754 p++;
01755 }
01756
01757 if (logline) {
01758 char *eol = strchr(logline, '\n');
01759
01760 logline += 17;
01761
01762 if (eol) {
01763 if (eol[-1] == '\r')
01764 eol--;
01765 http_log("%.*s\n", (int) (eol - logline), logline);
01766 c->suppress_log = 1;
01767 }
01768 }
01769
01770 #ifdef DEBUG
01771 http_log("\nGot request:\n%s\n", c->buffer);
01772 #endif
01773
01774 if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
01775 HTTPContext *wmpc;
01776
01777
01778 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
01779 if (wmpc->wmp_client_id == client_id)
01780 break;
01781 }
01782
01783 if (wmpc && modify_current_stream(wmpc, ratebuf))
01784 wmpc->switch_pending = 1;
01785 }
01786
01787 snprintf(msg, sizeof(msg), "POST command not handled");
01788 c->stream = 0;
01789 goto send_error;
01790 }
01791 if (http_start_receive_data(c) < 0) {
01792 snprintf(msg, sizeof(msg), "could not open feed");
01793 goto send_error;
01794 }
01795 c->http_error = 0;
01796 c->state = HTTPSTATE_RECEIVE_DATA;
01797 return 0;
01798 }
01799
01800 #ifdef DEBUG
01801 if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
01802 http_log("\nGot request:\n%s\n", c->buffer);
01803 #endif
01804
01805 if (c->stream->stream_type == STREAM_TYPE_STATUS)
01806 goto send_status;
01807
01808
01809 if (open_input_stream(c, info) < 0) {
01810 snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
01811 goto send_error;
01812 }
01813
01814
01815 q = c->buffer;
01816 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
01817 mime_type = c->stream->fmt->mime_type;
01818 if (!mime_type)
01819 mime_type = "application/x-octet-stream";
01820 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
01821
01822
01823 if (!strcmp(c->stream->fmt->name,"asf_stream")) {
01824
01825
01826 c->wmp_client_id = av_lfg_get(&random_state);
01827
01828 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
01829 }
01830 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
01831 q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
01832
01833
01834 c->http_error = 0;
01835 c->buffer_ptr = c->buffer;
01836 c->buffer_end = q;
01837 c->state = HTTPSTATE_SEND_HEADER;
01838 return 0;
01839 send_error:
01840 c->http_error = 404;
01841 q = c->buffer;
01842 q += snprintf(q, c->buffer_size,
01843 "HTTP/1.0 404 Not Found\r\n"
01844 "Content-type: text/html\r\n"
01845 "\r\n"
01846 "<html>\n"
01847 "<head><title>404 Not Found</title></head>\n"
01848 "<body>%s</body>\n"
01849 "</html>\n", msg);
01850
01851 c->buffer_ptr = c->buffer;
01852 c->buffer_end = q;
01853 c->state = HTTPSTATE_SEND_HEADER;
01854 return 0;
01855 send_status:
01856 compute_status(c);
01857 c->http_error = 200;
01858
01859 c->state = HTTPSTATE_SEND_HEADER;
01860 return 0;
01861 }
01862
01863 static void fmt_bytecount(AVIOContext *pb, int64_t count)
01864 {
01865 static const char *suffix = " kMGTP";
01866 const char *s;
01867
01868 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
01869
01870 avio_printf(pb, "%"PRId64"%c", count, *s);
01871 }
01872
01873 static void compute_status(HTTPContext *c)
01874 {
01875 HTTPContext *c1;
01876 FFStream *stream;
01877 char *p;
01878 time_t ti;
01879 int i, len;
01880 AVIOContext *pb;
01881
01882 if (avio_open_dyn_buf(&pb) < 0) {
01883
01884 c->buffer_ptr = c->buffer;
01885 c->buffer_end = c->buffer;
01886 return;
01887 }
01888
01889 avio_printf(pb, "HTTP/1.0 200 OK\r\n");
01890 avio_printf(pb, "Content-type: %s\r\n", "text/html");
01891 avio_printf(pb, "Pragma: no-cache\r\n");
01892 avio_printf(pb, "\r\n");
01893
01894 avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
01895 if (c->stream->feed_filename[0])
01896 avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
01897 avio_printf(pb, "</head>\n<body>");
01898 avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
01899
01900 avio_printf(pb, "<h2>Available Streams</h2>\n");
01901 avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
01902 avio_printf(pb, "<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
01903 stream = first_stream;
01904 while (stream != NULL) {
01905 char sfilename[1024];
01906 char *eosf;
01907
01908 if (stream->feed != stream) {
01909 av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
01910 eosf = sfilename + strlen(sfilename);
01911 if (eosf - sfilename >= 4) {
01912 if (strcmp(eosf - 4, ".asf") == 0)
01913 strcpy(eosf - 4, ".asx");
01914 else if (strcmp(eosf - 3, ".rm") == 0)
01915 strcpy(eosf - 3, ".ram");
01916 else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
01917
01918
01919
01920 eosf = strrchr(sfilename, '.');
01921 if (!eosf)
01922 eosf = sfilename + strlen(sfilename);
01923 if (stream->is_multicast)
01924 strcpy(eosf, ".sdp");
01925 else
01926 strcpy(eosf, ".rtsp");
01927 }
01928 }
01929
01930 avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
01931 sfilename, stream->filename);
01932 avio_printf(pb, "<td align=right> %d <td align=right> ",
01933 stream->conns_served);
01934 fmt_bytecount(pb, stream->bytes_served);
01935 switch(stream->stream_type) {
01936 case STREAM_TYPE_LIVE: {
01937 int audio_bit_rate = 0;
01938 int video_bit_rate = 0;
01939 const char *audio_codec_name = "";
01940 const char *video_codec_name = "";
01941 const char *audio_codec_name_extra = "";
01942 const char *video_codec_name_extra = "";
01943
01944 for(i=0;i<stream->nb_streams;i++) {
01945 AVStream *st = stream->streams[i];
01946 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
01947 switch(st->codec->codec_type) {
01948 case AVMEDIA_TYPE_AUDIO:
01949 audio_bit_rate += st->codec->bit_rate;
01950 if (codec) {
01951 if (*audio_codec_name)
01952 audio_codec_name_extra = "...";
01953 audio_codec_name = codec->name;
01954 }
01955 break;
01956 case AVMEDIA_TYPE_VIDEO:
01957 video_bit_rate += st->codec->bit_rate;
01958 if (codec) {
01959 if (*video_codec_name)
01960 video_codec_name_extra = "...";
01961 video_codec_name = codec->name;
01962 }
01963 break;
01964 case AVMEDIA_TYPE_DATA:
01965 video_bit_rate += st->codec->bit_rate;
01966 break;
01967 default:
01968 abort();
01969 }
01970 }
01971 avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
01972 stream->fmt->name,
01973 stream->bandwidth,
01974 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
01975 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
01976 if (stream->feed)
01977 avio_printf(pb, "<td>%s", stream->feed->filename);
01978 else
01979 avio_printf(pb, "<td>%s", stream->feed_filename);
01980 avio_printf(pb, "\n");
01981 }
01982 break;
01983 default:
01984 avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
01985 break;
01986 }
01987 }
01988 stream = stream->next;
01989 }
01990 avio_printf(pb, "</table>\n");
01991
01992 stream = first_stream;
01993 while (stream != NULL) {
01994 if (stream->feed == stream) {
01995 avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
01996 if (stream->pid) {
01997 avio_printf(pb, "Running as pid %d.\n", stream->pid);
01998
01999 #if defined(linux) && !defined(CONFIG_NOCUTILS)
02000 {
02001 FILE *pid_stat;
02002 char ps_cmd[64];
02003
02004
02005 snprintf(ps_cmd, sizeof(ps_cmd),
02006 "ps -o \"%%cpu,cputime\" --no-headers %d",
02007 stream->pid);
02008
02009 pid_stat = popen(ps_cmd, "r");
02010 if (pid_stat) {
02011 char cpuperc[10];
02012 char cpuused[64];
02013
02014 if (fscanf(pid_stat, "%10s %64s", cpuperc,
02015 cpuused) == 2) {
02016 avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
02017 cpuperc, cpuused);
02018 }
02019 fclose(pid_stat);
02020 }
02021 }
02022 #endif
02023
02024 avio_printf(pb, "<p>");
02025 }
02026 avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
02027
02028 for (i = 0; i < stream->nb_streams; i++) {
02029 AVStream *st = stream->streams[i];
02030 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
02031 const char *type = "unknown";
02032 char parameters[64];
02033
02034 parameters[0] = 0;
02035
02036 switch(st->codec->codec_type) {
02037 case AVMEDIA_TYPE_AUDIO:
02038 type = "audio";
02039 snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
02040 break;
02041 case AVMEDIA_TYPE_VIDEO:
02042 type = "video";
02043 snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
02044 st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
02045 break;
02046 default:
02047 abort();
02048 }
02049 avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
02050 i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
02051 }
02052 avio_printf(pb, "</table>\n");
02053
02054 }
02055 stream = stream->next;
02056 }
02057
02058
02059 avio_printf(pb, "<h2>Connection Status</h2>\n");
02060
02061 avio_printf(pb, "Number of connections: %d / %d<br>\n",
02062 nb_connections, nb_max_connections);
02063
02064 avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
02065 current_bandwidth, max_bandwidth);
02066
02067 avio_printf(pb, "<table>\n");
02068 avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
02069 c1 = first_http_ctx;
02070 i = 0;
02071 while (c1 != NULL) {
02072 int bitrate;
02073 int j;
02074
02075 bitrate = 0;
02076 if (c1->stream) {
02077 for (j = 0; j < c1->stream->nb_streams; j++) {
02078 if (!c1->stream->feed)
02079 bitrate += c1->stream->streams[j]->codec->bit_rate;
02080 else if (c1->feed_streams[j] >= 0)
02081 bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
02082 }
02083 }
02084
02085 i++;
02086 p = inet_ntoa(c1->from_addr.sin_addr);
02087 avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
02088 i,
02089 c1->stream ? c1->stream->filename : "",
02090 c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
02091 p,
02092 c1->protocol,
02093 http_state[c1->state]);
02094 fmt_bytecount(pb, bitrate);
02095 avio_printf(pb, "<td align=right>");
02096 fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
02097 avio_printf(pb, "<td align=right>");
02098 fmt_bytecount(pb, c1->data_count);
02099 avio_printf(pb, "\n");
02100 c1 = c1->next;
02101 }
02102 avio_printf(pb, "</table>\n");
02103
02104
02105 ti = time(NULL);
02106 p = ctime(&ti);
02107 avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
02108 avio_printf(pb, "</body>\n</html>\n");
02109
02110 len = avio_close_dyn_buf(pb, &c->pb_buffer);
02111 c->buffer_ptr = c->pb_buffer;
02112 c->buffer_end = c->pb_buffer + len;
02113 }
02114
02115
02116 static void open_parser(AVFormatContext *s, int i)
02117 {
02118 AVStream *st = s->streams[i];
02119 AVCodec *codec;
02120
02121 if (!st->codec->codec) {
02122 codec = avcodec_find_decoder(st->codec->codec_id);
02123 if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
02124 st->codec->parse_only = 1;
02125 if (avcodec_open2(st->codec, codec, NULL) < 0)
02126 st->codec->parse_only = 0;
02127 }
02128 }
02129 }
02130
02131 static int open_input_stream(HTTPContext *c, const char *info)
02132 {
02133 char buf[128];
02134 char input_filename[1024];
02135 AVFormatContext *s = NULL;
02136 int i, ret;
02137 int64_t stream_pos;
02138
02139
02140 if (c->stream->feed) {
02141 strcpy(input_filename, c->stream->feed->feed_filename);
02142
02143 if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
02144 if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
02145 return ret;
02146 } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
02147 int prebuffer = strtol(buf, 0, 10);
02148 stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
02149 } else
02150 stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
02151 } else {
02152 strcpy(input_filename, c->stream->feed_filename);
02153
02154 if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
02155 if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
02156 return ret;
02157 } else
02158 stream_pos = 0;
02159 }
02160 if (input_filename[0] == '\0')
02161 return -1;
02162
02163
02164 if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
02165 http_log("could not open %s: %d\n", input_filename, ret);
02166 return -1;
02167 }
02168 s->flags |= AVFMT_FLAG_GENPTS;
02169 c->fmt_in = s;
02170 if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
02171 http_log("Could not find stream info '%s'\n", input_filename);
02172 av_close_input_file(s);
02173 return -1;
02174 }
02175
02176
02177 for(i=0;i<s->nb_streams;i++)
02178 open_parser(s, i);
02179
02180
02181
02182 c->pts_stream_index = 0;
02183 for(i=0;i<c->stream->nb_streams;i++) {
02184 if (c->pts_stream_index == 0 &&
02185 c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
02186 c->pts_stream_index = i;
02187 }
02188 }
02189
02190 if (c->fmt_in->iformat->read_seek)
02191 av_seek_frame(c->fmt_in, -1, stream_pos, 0);
02192
02193 c->start_time = cur_time;
02194 c->first_pts = AV_NOPTS_VALUE;
02195 return 0;
02196 }
02197
02198
02199 static int64_t get_server_clock(HTTPContext *c)
02200 {
02201
02202 return (cur_time - c->start_time) * 1000;
02203 }
02204
02205
02206
02207 static int64_t get_packet_send_clock(HTTPContext *c)
02208 {
02209 int bytes_left, bytes_sent, frame_bytes;
02210
02211 frame_bytes = c->cur_frame_bytes;
02212 if (frame_bytes <= 0)
02213 return c->cur_pts;
02214 else {
02215 bytes_left = c->buffer_end - c->buffer_ptr;
02216 bytes_sent = frame_bytes - bytes_left;
02217 return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
02218 }
02219 }
02220
02221
02222 static int http_prepare_data(HTTPContext *c)
02223 {
02224 int i, len, ret;
02225 AVFormatContext *ctx;
02226
02227 av_freep(&c->pb_buffer);
02228 switch(c->state) {
02229 case HTTPSTATE_SEND_DATA_HEADER:
02230 memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
02231 av_dict_set(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
02232 av_dict_set(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
02233 av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
02234 av_dict_set(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
02235
02236 c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
02237
02238 for(i=0;i<c->stream->nb_streams;i++) {
02239 AVStream *src;
02240 c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
02241
02242 if (!c->stream->feed ||
02243 c->stream->feed == c->stream)
02244 src = c->stream->streams[i];
02245 else
02246 src = c->stream->feed->streams[c->stream->feed_streams[i]];
02247
02248 *(c->fmt_ctx.streams[i]) = *src;
02249 c->fmt_ctx.streams[i]->priv_data = 0;
02250 c->fmt_ctx.streams[i]->codec->frame_number = 0;
02251
02252 }
02253
02254 c->fmt_ctx.oformat = c->stream->fmt;
02255 c->fmt_ctx.nb_streams = c->stream->nb_streams;
02256
02257 c->got_key_frame = 0;
02258
02259
02260 if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
02261
02262 return -1;
02263 }
02264 c->fmt_ctx.pb->seekable = 0;
02265
02266
02267
02268
02269
02270
02271 c->fmt_ctx.preload = (int)(0.5*AV_TIME_BASE);
02272 c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
02273
02274 if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
02275 http_log("Error writing output header\n");
02276 return -1;
02277 }
02278 av_dict_free(&c->fmt_ctx.metadata);
02279
02280 len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
02281 c->buffer_ptr = c->pb_buffer;
02282 c->buffer_end = c->pb_buffer + len;
02283
02284 c->state = HTTPSTATE_SEND_DATA;
02285 c->last_packet_sent = 0;
02286 break;
02287 case HTTPSTATE_SEND_DATA:
02288
02289
02290 if (c->stream->feed)
02291 ffm_set_write_index(c->fmt_in,
02292 c->stream->feed->feed_write_index,
02293 c->stream->feed->feed_size);
02294
02295 if (c->stream->max_time &&
02296 c->stream->max_time + c->start_time - cur_time < 0)
02297
02298 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02299 else {
02300 AVPacket pkt;
02301 redo:
02302 ret = av_read_frame(c->fmt_in, &pkt);
02303 if (ret < 0) {
02304 if (c->stream->feed) {
02305
02306
02307 c->state = HTTPSTATE_WAIT_FEED;
02308 return 1;
02309 } else if (ret == AVERROR(EAGAIN)) {
02310
02311 return 0;
02312 } else {
02313 if (c->stream->loop) {
02314 av_close_input_file(c->fmt_in);
02315 c->fmt_in = NULL;
02316 if (open_input_stream(c, "") < 0)
02317 goto no_loop;
02318 goto redo;
02319 } else {
02320 no_loop:
02321
02322 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02323 }
02324 }
02325 } else {
02326 int source_index = pkt.stream_index;
02327
02328 if (c->first_pts == AV_NOPTS_VALUE) {
02329 c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
02330 c->start_time = cur_time;
02331 }
02332
02333 if (c->stream->feed) {
02334
02335 if (c->switch_pending) {
02336 c->switch_pending = 0;
02337 for(i=0;i<c->stream->nb_streams;i++) {
02338 if (c->switch_feed_streams[i] == pkt.stream_index)
02339 if (pkt.flags & AV_PKT_FLAG_KEY)
02340 c->switch_feed_streams[i] = -1;
02341 if (c->switch_feed_streams[i] >= 0)
02342 c->switch_pending = 1;
02343 }
02344 }
02345 for(i=0;i<c->stream->nb_streams;i++) {
02346 if (c->stream->feed_streams[i] == pkt.stream_index) {
02347 AVStream *st = c->fmt_in->streams[source_index];
02348 pkt.stream_index = i;
02349 if (pkt.flags & AV_PKT_FLAG_KEY &&
02350 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
02351 c->stream->nb_streams == 1))
02352 c->got_key_frame = 1;
02353 if (!c->stream->send_on_key || c->got_key_frame)
02354 goto send_it;
02355 }
02356 }
02357 } else {
02358 AVCodecContext *codec;
02359 AVStream *ist, *ost;
02360 send_it:
02361 ist = c->fmt_in->streams[source_index];
02362
02363
02364
02365 if (c->is_packetized) {
02366
02367 c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
02368 c->cur_pts -= c->first_pts;
02369 c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
02370
02371 c->packet_stream_index = pkt.stream_index;
02372 ctx = c->rtp_ctx[c->packet_stream_index];
02373 if(!ctx) {
02374 av_free_packet(&pkt);
02375 break;
02376 }
02377 codec = ctx->streams[0]->codec;
02378
02379 pkt.stream_index = 0;
02380 } else {
02381 ctx = &c->fmt_ctx;
02382
02383 codec = ctx->streams[pkt.stream_index]->codec;
02384 }
02385
02386 if (c->is_packetized) {
02387 int max_packet_size;
02388 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
02389 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
02390 else
02391 max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
02392 ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
02393 } else {
02394 ret = avio_open_dyn_buf(&ctx->pb);
02395 }
02396 if (ret < 0) {
02397
02398 return -1;
02399 }
02400 ost = ctx->streams[pkt.stream_index];
02401
02402 ctx->pb->seekable = 0;
02403 if (pkt.dts != AV_NOPTS_VALUE)
02404 pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
02405 if (pkt.pts != AV_NOPTS_VALUE)
02406 pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
02407 pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
02408 if (av_write_frame(ctx, &pkt) < 0) {
02409 http_log("Error writing frame to output\n");
02410 c->state = HTTPSTATE_SEND_DATA_TRAILER;
02411 }
02412
02413 len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
02414 c->cur_frame_bytes = len;
02415 c->buffer_ptr = c->pb_buffer;
02416 c->buffer_end = c->pb_buffer + len;
02417
02418 codec->frame_number++;
02419 if (len == 0) {
02420 av_free_packet(&pkt);
02421 goto redo;
02422 }
02423 }
02424 av_free_packet(&pkt);
02425 }
02426 }
02427 break;
02428 default:
02429 case HTTPSTATE_SEND_DATA_TRAILER:
02430
02431 if (c->last_packet_sent || c->is_packetized)
02432 return -1;
02433 ctx = &c->fmt_ctx;
02434
02435 if (avio_open_dyn_buf(&ctx->pb) < 0) {
02436
02437 return -1;
02438 }
02439 c->fmt_ctx.pb->seekable = 0;
02440 av_write_trailer(ctx);
02441 len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
02442 c->buffer_ptr = c->pb_buffer;
02443 c->buffer_end = c->pb_buffer + len;
02444
02445 c->last_packet_sent = 1;
02446 break;
02447 }
02448 return 0;
02449 }
02450
02451
02452
02453
02454 static int http_send_data(HTTPContext *c)
02455 {
02456 int len, ret;
02457
02458 for(;;) {
02459 if (c->buffer_ptr >= c->buffer_end) {
02460 ret = http_prepare_data(c);
02461 if (ret < 0)
02462 return -1;
02463 else if (ret != 0)
02464
02465 break;
02466 } else {
02467 if (c->is_packetized) {
02468
02469 len = c->buffer_end - c->buffer_ptr;
02470 if (len < 4) {
02471
02472 fail1:
02473 c->buffer_ptr = c->buffer_end;
02474 return 0;
02475 }
02476 len = (c->buffer_ptr[0] << 24) |
02477 (c->buffer_ptr[1] << 16) |
02478 (c->buffer_ptr[2] << 8) |
02479 (c->buffer_ptr[3]);
02480 if (len > (c->buffer_end - c->buffer_ptr))
02481 goto fail1;
02482 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
02483
02484 return 0;
02485 }
02486
02487 c->data_count += len;
02488 update_datarate(&c->datarate, c->data_count);
02489 if (c->stream)
02490 c->stream->bytes_served += len;
02491
02492 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
02493
02494 AVIOContext *pb;
02495 int interleaved_index, size;
02496 uint8_t header[4];
02497 HTTPContext *rtsp_c;
02498
02499 rtsp_c = c->rtsp_c;
02500
02501 if (!rtsp_c)
02502 return -1;
02503
02504 if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
02505 break;
02506 if (avio_open_dyn_buf(&pb) < 0)
02507 goto fail1;
02508 interleaved_index = c->packet_stream_index * 2;
02509
02510 if (c->buffer_ptr[1] == 200)
02511 interleaved_index++;
02512
02513 header[0] = '$';
02514 header[1] = interleaved_index;
02515 header[2] = len >> 8;
02516 header[3] = len;
02517 avio_write(pb, header, 4);
02518
02519 c->buffer_ptr += 4;
02520 avio_write(pb, c->buffer_ptr, len);
02521 size = avio_close_dyn_buf(pb, &c->packet_buffer);
02522
02523 rtsp_c->packet_buffer_ptr = c->packet_buffer;
02524 rtsp_c->packet_buffer_end = c->packet_buffer + size;
02525 c->buffer_ptr += len;
02526
02527
02528 len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
02529 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
02530 if (len > 0)
02531 rtsp_c->packet_buffer_ptr += len;
02532 if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
02533
02534
02535
02536 rtsp_c->state = RTSPSTATE_SEND_PACKET;
02537 break;
02538 } else
02539
02540 av_freep(&c->packet_buffer);
02541 } else {
02542
02543 c->buffer_ptr += 4;
02544 url_write(c->rtp_handles[c->packet_stream_index],
02545 c->buffer_ptr, len);
02546 c->buffer_ptr += len;
02547
02548 }
02549 } else {
02550
02551 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
02552 if (len < 0) {
02553 if (ff_neterrno() != AVERROR(EAGAIN) &&
02554 ff_neterrno() != AVERROR(EINTR))
02555
02556 return -1;
02557 else
02558 return 0;
02559 } else
02560 c->buffer_ptr += len;
02561
02562 c->data_count += len;
02563 update_datarate(&c->datarate, c->data_count);
02564 if (c->stream)
02565 c->stream->bytes_served += len;
02566 break;
02567 }
02568 }
02569 }
02570 return 0;
02571 }
02572
02573 static int http_start_receive_data(HTTPContext *c)
02574 {
02575 int fd;
02576
02577 if (c->stream->feed_opened)
02578 return -1;
02579
02580
02581 if (c->stream->readonly)
02582 return -1;
02583
02584
02585 fd = open(c->stream->feed_filename, O_RDWR);
02586 if (fd < 0) {
02587 http_log("Error opening feeder file: %s\n", strerror(errno));
02588 return -1;
02589 }
02590 c->feed_fd = fd;
02591
02592 if (c->stream->truncate) {
02593
02594 ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
02595 ftruncate(c->feed_fd, FFM_PACKET_SIZE);
02596 http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
02597 } else {
02598 if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
02599 http_log("Error reading write index from feed file: %s\n", strerror(errno));
02600 return -1;
02601 }
02602 }
02603
02604 c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
02605 c->stream->feed_size = lseek(fd, 0, SEEK_END);
02606 lseek(fd, 0, SEEK_SET);
02607
02608
02609 c->buffer_ptr = c->buffer;
02610 c->buffer_end = c->buffer + FFM_PACKET_SIZE;
02611 c->stream->feed_opened = 1;
02612 c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
02613 return 0;
02614 }
02615
02616 static int http_receive_data(HTTPContext *c)
02617 {
02618 HTTPContext *c1;
02619 int len, loop_run = 0;
02620
02621 while (c->chunked_encoding && !c->chunk_size &&
02622 c->buffer_end > c->buffer_ptr) {
02623
02624 len = recv(c->fd, c->buffer_ptr, 1, 0);
02625
02626 if (len < 0) {
02627 if (ff_neterrno() != AVERROR(EAGAIN) &&
02628 ff_neterrno() != AVERROR(EINTR))
02629
02630 goto fail;
02631 return 0;
02632 } else if (len == 0) {
02633
02634 goto fail;
02635 } else if (c->buffer_ptr - c->buffer >= 2 &&
02636 !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
02637 c->chunk_size = strtol(c->buffer, 0, 16);
02638 if (c->chunk_size == 0)
02639 goto fail;
02640 c->buffer_ptr = c->buffer;
02641 break;
02642 } else if (++loop_run > 10) {
02643
02644 goto fail;
02645 } else {
02646 c->buffer_ptr++;
02647 }
02648 }
02649
02650 if (c->buffer_end > c->buffer_ptr) {
02651 len = recv(c->fd, c->buffer_ptr,
02652 FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
02653 if (len < 0) {
02654 if (ff_neterrno() != AVERROR(EAGAIN) &&
02655 ff_neterrno() != AVERROR(EINTR))
02656
02657 goto fail;
02658 } else if (len == 0)
02659
02660 goto fail;
02661 else {
02662 c->chunk_size -= len;
02663 c->buffer_ptr += len;
02664 c->data_count += len;
02665 update_datarate(&c->datarate, c->data_count);
02666 }
02667 }
02668
02669 if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
02670 if (c->buffer[0] != 'f' ||
02671 c->buffer[1] != 'm') {
02672 http_log("Feed stream has become desynchronized -- disconnecting\n");
02673 goto fail;
02674 }
02675 }
02676
02677 if (c->buffer_ptr >= c->buffer_end) {
02678 FFStream *feed = c->stream;
02679
02680
02681 if (c->data_count > FFM_PACKET_SIZE) {
02682
02683
02684
02685 lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
02686 if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
02687 http_log("Error writing to feed file: %s\n", strerror(errno));
02688 goto fail;
02689 }
02690
02691 feed->feed_write_index += FFM_PACKET_SIZE;
02692
02693 if (feed->feed_write_index > c->stream->feed_size)
02694 feed->feed_size = feed->feed_write_index;
02695
02696
02697 if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
02698 feed->feed_write_index = FFM_PACKET_SIZE;
02699
02700
02701 if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
02702 http_log("Error writing index to feed file: %s\n", strerror(errno));
02703 goto fail;
02704 }
02705
02706
02707 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
02708 if (c1->state == HTTPSTATE_WAIT_FEED &&
02709 c1->stream->feed == c->stream->feed)
02710 c1->state = HTTPSTATE_SEND_DATA;
02711 }
02712 } else {
02713
02714 AVFormatContext *s = avformat_alloc_context();
02715 AVIOContext *pb;
02716 AVInputFormat *fmt_in;
02717 int i;
02718
02719 if (!s)
02720 goto fail;
02721
02722
02723 fmt_in = av_find_input_format(feed->fmt->name);
02724 if (!fmt_in)
02725 goto fail;
02726
02727 pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
02728 0, NULL, NULL, NULL, NULL);
02729 pb->seekable = 0;
02730
02731 s->pb = pb;
02732 if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
02733 av_free(pb);
02734 goto fail;
02735 }
02736
02737
02738 if (s->nb_streams != feed->nb_streams) {
02739 av_close_input_stream(s);
02740 av_free(pb);
02741 http_log("Feed '%s' stream number does not match registered feed\n",
02742 c->stream->feed_filename);
02743 goto fail;
02744 }
02745
02746 for (i = 0; i < s->nb_streams; i++) {
02747 AVStream *fst = feed->streams[i];
02748 AVStream *st = s->streams[i];
02749 avcodec_copy_context(fst->codec, st->codec);
02750 }
02751
02752 av_close_input_stream(s);
02753 av_free(pb);
02754 }
02755 c->buffer_ptr = c->buffer;
02756 }
02757
02758 return 0;
02759 fail:
02760 c->stream->feed_opened = 0;
02761 close(c->feed_fd);
02762
02763 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
02764 if (c1->state == HTTPSTATE_WAIT_FEED &&
02765 c1->stream->feed == c->stream->feed)
02766 c1->state = HTTPSTATE_SEND_DATA_TRAILER;
02767 }
02768 return -1;
02769 }
02770
02771
02772
02773
02774 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
02775 {
02776 const char *str;
02777 time_t ti;
02778 struct tm *tm;
02779 char buf2[32];
02780
02781 switch(error_number) {
02782 case RTSP_STATUS_OK:
02783 str = "OK";
02784 break;
02785 case RTSP_STATUS_METHOD:
02786 str = "Method Not Allowed";
02787 break;
02788 case RTSP_STATUS_BANDWIDTH:
02789 str = "Not Enough Bandwidth";
02790 break;
02791 case RTSP_STATUS_SESSION:
02792 str = "Session Not Found";
02793 break;
02794 case RTSP_STATUS_STATE:
02795 str = "Method Not Valid in This State";
02796 break;
02797 case RTSP_STATUS_AGGREGATE:
02798 str = "Aggregate operation not allowed";
02799 break;
02800 case RTSP_STATUS_ONLY_AGGREGATE:
02801 str = "Only aggregate operation allowed";
02802 break;
02803 case RTSP_STATUS_TRANSPORT:
02804 str = "Unsupported transport";
02805 break;
02806 case RTSP_STATUS_INTERNAL:
02807 str = "Internal Server Error";
02808 break;
02809 case RTSP_STATUS_SERVICE:
02810 str = "Service Unavailable";
02811 break;
02812 case RTSP_STATUS_VERSION:
02813 str = "RTSP Version not supported";
02814 break;
02815 default:
02816 str = "Unknown Error";
02817 break;
02818 }
02819
02820 avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
02821 avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
02822
02823
02824 ti = time(NULL);
02825 tm = gmtime(&ti);
02826 strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
02827 avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
02828 }
02829
02830 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
02831 {
02832 rtsp_reply_header(c, error_number);
02833 avio_printf(c->pb, "\r\n");
02834 }
02835
02836 static int rtsp_parse_request(HTTPContext *c)
02837 {
02838 const char *p, *p1, *p2;
02839 char cmd[32];
02840 char url[1024];
02841 char protocol[32];
02842 char line[1024];
02843 int len;
02844 RTSPMessageHeader header1, *header = &header1;
02845
02846 c->buffer_ptr[0] = '\0';
02847 p = c->buffer;
02848
02849 get_word(cmd, sizeof(cmd), &p);
02850 get_word(url, sizeof(url), &p);
02851 get_word(protocol, sizeof(protocol), &p);
02852
02853 av_strlcpy(c->method, cmd, sizeof(c->method));
02854 av_strlcpy(c->url, url, sizeof(c->url));
02855 av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
02856
02857 if (avio_open_dyn_buf(&c->pb) < 0) {
02858
02859 c->pb = NULL;
02860 return -1;
02861 }
02862
02863
02864 if (strcmp(protocol, "RTSP/1.0") != 0) {
02865 rtsp_reply_error(c, RTSP_STATUS_VERSION);
02866 goto the_end;
02867 }
02868
02869
02870 memset(header, 0, sizeof(*header));
02871
02872 while (*p != '\n' && *p != '\0')
02873 p++;
02874 if (*p == '\n')
02875 p++;
02876 while (*p != '\0') {
02877 p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
02878 if (!p1)
02879 break;
02880 p2 = p1;
02881 if (p2 > p && p2[-1] == '\r')
02882 p2--;
02883
02884 if (p2 == p)
02885 break;
02886 len = p2 - p;
02887 if (len > sizeof(line) - 1)
02888 len = sizeof(line) - 1;
02889 memcpy(line, p, len);
02890 line[len] = '\0';
02891 ff_rtsp_parse_line(header, line, NULL, NULL);
02892 p = p1 + 1;
02893 }
02894
02895
02896 c->seq = header->seq;
02897
02898 if (!strcmp(cmd, "DESCRIBE"))
02899 rtsp_cmd_describe(c, url);
02900 else if (!strcmp(cmd, "OPTIONS"))
02901 rtsp_cmd_options(c, url);
02902 else if (!strcmp(cmd, "SETUP"))
02903 rtsp_cmd_setup(c, url, header);
02904 else if (!strcmp(cmd, "PLAY"))
02905 rtsp_cmd_play(c, url, header);
02906 else if (!strcmp(cmd, "PAUSE"))
02907 rtsp_cmd_pause(c, url, header);
02908 else if (!strcmp(cmd, "TEARDOWN"))
02909 rtsp_cmd_teardown(c, url, header);
02910 else
02911 rtsp_reply_error(c, RTSP_STATUS_METHOD);
02912
02913 the_end:
02914 len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
02915 c->pb = NULL;
02916 if (len < 0) {
02917
02918 return -1;
02919 }
02920 c->buffer_ptr = c->pb_buffer;
02921 c->buffer_end = c->pb_buffer + len;
02922 c->state = RTSPSTATE_SEND_REPLY;
02923 return 0;
02924 }
02925
02926 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
02927 struct in_addr my_ip)
02928 {
02929 AVFormatContext *avc;
02930 AVStream *avs = NULL;
02931 int i;
02932
02933 avc = avformat_alloc_context();
02934 if (avc == NULL) {
02935 return -1;
02936 }
02937 av_dict_set(&avc->metadata, "title",
02938 stream->title[0] ? stream->title : "No Title", 0);
02939 avc->nb_streams = stream->nb_streams;
02940 if (stream->is_multicast) {
02941 snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
02942 inet_ntoa(stream->multicast_ip),
02943 stream->multicast_port, stream->multicast_ttl);
02944 } else {
02945 snprintf(avc->filename, 1024, "rtp://0.0.0.0");
02946 }
02947
02948 if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
02949 !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
02950 goto sdp_done;
02951 if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
02952 !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
02953 goto sdp_done;
02954
02955 for(i = 0; i < stream->nb_streams; i++) {
02956 avc->streams[i] = &avs[i];
02957 avc->streams[i]->codec = stream->streams[i]->codec;
02958 }
02959 *pbuffer = av_mallocz(2048);
02960 av_sdp_create(&avc, 1, *pbuffer, 2048);
02961
02962 sdp_done:
02963 av_free(avc->streams);
02964 av_dict_free(&avc->metadata);
02965 av_free(avc);
02966 av_free(avs);
02967
02968 return strlen(*pbuffer);
02969 }
02970
02971 static void rtsp_cmd_options(HTTPContext *c, const char *url)
02972 {
02973
02974 avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
02975 avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
02976 avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
02977 avio_printf(c->pb, "\r\n");
02978 }
02979
02980 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
02981 {
02982 FFStream *stream;
02983 char path1[1024];
02984 const char *path;
02985 uint8_t *content;
02986 int content_length, len;
02987 struct sockaddr_in my_addr;
02988
02989
02990 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
02991 path = path1;
02992 if (*path == '/')
02993 path++;
02994
02995 for(stream = first_stream; stream != NULL; stream = stream->next) {
02996 if (!stream->is_feed &&
02997 stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
02998 !strcmp(path, stream->filename)) {
02999 goto found;
03000 }
03001 }
03002
03003 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03004 return;
03005
03006 found:
03007
03008
03009
03010 len = sizeof(my_addr);
03011 getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
03012 content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
03013 if (content_length < 0) {
03014 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
03015 return;
03016 }
03017 rtsp_reply_header(c, RTSP_STATUS_OK);
03018 avio_printf(c->pb, "Content-Base: %s/\r\n", url);
03019 avio_printf(c->pb, "Content-Type: application/sdp\r\n");
03020 avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
03021 avio_printf(c->pb, "\r\n");
03022 avio_write(c->pb, content, content_length);
03023 av_free(content);
03024 }
03025
03026 static HTTPContext *find_rtp_session(const char *session_id)
03027 {
03028 HTTPContext *c;
03029
03030 if (session_id[0] == '\0')
03031 return NULL;
03032
03033 for(c = first_http_ctx; c != NULL; c = c->next) {
03034 if (!strcmp(c->session_id, session_id))
03035 return c;
03036 }
03037 return NULL;
03038 }
03039
03040 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
03041 {
03042 RTSPTransportField *th;
03043 int i;
03044
03045 for(i=0;i<h->nb_transports;i++) {
03046 th = &h->transports[i];
03047 if (th->lower_transport == lower_transport)
03048 return th;
03049 }
03050 return NULL;
03051 }
03052
03053 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
03054 RTSPMessageHeader *h)
03055 {
03056 FFStream *stream;
03057 int stream_index, rtp_port, rtcp_port;
03058 char buf[1024];
03059 char path1[1024];
03060 const char *path;
03061 HTTPContext *rtp_c;
03062 RTSPTransportField *th;
03063 struct sockaddr_in dest_addr;
03064 RTSPActionServerSetup setup;
03065
03066
03067 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
03068 path = path1;
03069 if (*path == '/')
03070 path++;
03071
03072
03073 for(stream = first_stream; stream != NULL; stream = stream->next) {
03074 if (!stream->is_feed &&
03075 stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
03076
03077 if (!strcmp(path, stream->filename)) {
03078 if (stream->nb_streams != 1) {
03079 rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
03080 return;
03081 }
03082 stream_index = 0;
03083 goto found;
03084 }
03085
03086 for(stream_index = 0; stream_index < stream->nb_streams;
03087 stream_index++) {
03088 snprintf(buf, sizeof(buf), "%s/streamid=%d",
03089 stream->filename, stream_index);
03090 if (!strcmp(path, buf))
03091 goto found;
03092 }
03093 }
03094 }
03095
03096 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03097 return;
03098 found:
03099
03100
03101 if (h->session_id[0] == '\0')
03102 snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
03103 av_lfg_get(&random_state), av_lfg_get(&random_state));
03104
03105
03106 rtp_c = find_rtp_session(h->session_id);
03107 if (!rtp_c) {
03108
03109 th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
03110 if (!th) {
03111 th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
03112 if (!th) {
03113 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03114 return;
03115 }
03116 }
03117
03118 rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
03119 th->lower_transport);
03120 if (!rtp_c) {
03121 rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
03122 return;
03123 }
03124
03125
03126 if (open_input_stream(rtp_c, "") < 0) {
03127 rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
03128 return;
03129 }
03130 }
03131
03132
03133
03134 if (rtp_c->stream != stream) {
03135 rtsp_reply_error(c, RTSP_STATUS_SERVICE);
03136 return;
03137 }
03138
03139
03140 if (rtp_c->rtp_ctx[stream_index]) {
03141 rtsp_reply_error(c, RTSP_STATUS_STATE);
03142 return;
03143 }
03144
03145
03146 th = find_transport(h, rtp_c->rtp_protocol);
03147 if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
03148 th->client_port_min <= 0)) {
03149 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03150 return;
03151 }
03152
03153
03154 setup.transport_option[0] = '\0';
03155 dest_addr = rtp_c->from_addr;
03156 dest_addr.sin_port = htons(th->client_port_min);
03157
03158
03159 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
03160 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
03161 return;
03162 }
03163
03164
03165 rtsp_reply_header(c, RTSP_STATUS_OK);
03166
03167 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03168
03169 switch(rtp_c->rtp_protocol) {
03170 case RTSP_LOWER_TRANSPORT_UDP:
03171 rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
03172 rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
03173 avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
03174 "client_port=%d-%d;server_port=%d-%d",
03175 th->client_port_min, th->client_port_max,
03176 rtp_port, rtcp_port);
03177 break;
03178 case RTSP_LOWER_TRANSPORT_TCP:
03179 avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
03180 stream_index * 2, stream_index * 2 + 1);
03181 break;
03182 default:
03183 break;
03184 }
03185 if (setup.transport_option[0] != '\0')
03186 avio_printf(c->pb, ";%s", setup.transport_option);
03187 avio_printf(c->pb, "\r\n");
03188
03189
03190 avio_printf(c->pb, "\r\n");
03191 }
03192
03193
03194
03195
03196 static HTTPContext *find_rtp_session_with_url(const char *url,
03197 const char *session_id)
03198 {
03199 HTTPContext *rtp_c;
03200 char path1[1024];
03201 const char *path;
03202 char buf[1024];
03203 int s, len;
03204
03205 rtp_c = find_rtp_session(session_id);
03206 if (!rtp_c)
03207 return NULL;
03208
03209
03210 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
03211 path = path1;
03212 if (*path == '/')
03213 path++;
03214 if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
03215 for(s=0; s<rtp_c->stream->nb_streams; ++s) {
03216 snprintf(buf, sizeof(buf), "%s/streamid=%d",
03217 rtp_c->stream->filename, s);
03218 if(!strncmp(path, buf, sizeof(buf))) {
03219
03220 return rtp_c;
03221 }
03222 }
03223 len = strlen(path);
03224 if (len > 0 && path[len - 1] == '/' &&
03225 !strncmp(path, rtp_c->stream->filename, len - 1))
03226 return rtp_c;
03227 return NULL;
03228 }
03229
03230 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03231 {
03232 HTTPContext *rtp_c;
03233
03234 rtp_c = find_rtp_session_with_url(url, h->session_id);
03235 if (!rtp_c) {
03236 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03237 return;
03238 }
03239
03240 if (rtp_c->state != HTTPSTATE_SEND_DATA &&
03241 rtp_c->state != HTTPSTATE_WAIT_FEED &&
03242 rtp_c->state != HTTPSTATE_READY) {
03243 rtsp_reply_error(c, RTSP_STATUS_STATE);
03244 return;
03245 }
03246
03247 rtp_c->state = HTTPSTATE_SEND_DATA;
03248
03249
03250 rtsp_reply_header(c, RTSP_STATUS_OK);
03251
03252 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03253 avio_printf(c->pb, "\r\n");
03254 }
03255
03256 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03257 {
03258 HTTPContext *rtp_c;
03259
03260 rtp_c = find_rtp_session_with_url(url, h->session_id);
03261 if (!rtp_c) {
03262 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03263 return;
03264 }
03265
03266 if (rtp_c->state != HTTPSTATE_SEND_DATA &&
03267 rtp_c->state != HTTPSTATE_WAIT_FEED) {
03268 rtsp_reply_error(c, RTSP_STATUS_STATE);
03269 return;
03270 }
03271
03272 rtp_c->state = HTTPSTATE_READY;
03273 rtp_c->first_pts = AV_NOPTS_VALUE;
03274
03275 rtsp_reply_header(c, RTSP_STATUS_OK);
03276
03277 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03278 avio_printf(c->pb, "\r\n");
03279 }
03280
03281 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
03282 {
03283 HTTPContext *rtp_c;
03284
03285 rtp_c = find_rtp_session_with_url(url, h->session_id);
03286 if (!rtp_c) {
03287 rtsp_reply_error(c, RTSP_STATUS_SESSION);
03288 return;
03289 }
03290
03291
03292 rtsp_reply_header(c, RTSP_STATUS_OK);
03293
03294 avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
03295 avio_printf(c->pb, "\r\n");
03296
03297
03298 close_connection(rtp_c);
03299 }
03300
03301
03302
03303
03304
03305 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
03306 FFStream *stream, const char *session_id,
03307 enum RTSPLowerTransport rtp_protocol)
03308 {
03309 HTTPContext *c = NULL;
03310 const char *proto_str;
03311
03312
03313
03314 if (nb_connections >= nb_max_connections)
03315 goto fail;
03316
03317
03318 c = av_mallocz(sizeof(HTTPContext));
03319 if (!c)
03320 goto fail;
03321
03322 c->fd = -1;
03323 c->poll_entry = NULL;
03324 c->from_addr = *from_addr;
03325 c->buffer_size = IOBUFFER_INIT_SIZE;
03326 c->buffer = av_malloc(c->buffer_size);
03327 if (!c->buffer)
03328 goto fail;
03329 nb_connections++;
03330 c->stream = stream;
03331 av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
03332 c->state = HTTPSTATE_READY;
03333 c->is_packetized = 1;
03334 c->rtp_protocol = rtp_protocol;
03335
03336
03337 switch(c->rtp_protocol) {
03338 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
03339 proto_str = "MCAST";
03340 break;
03341 case RTSP_LOWER_TRANSPORT_UDP:
03342 proto_str = "UDP";
03343 break;
03344 case RTSP_LOWER_TRANSPORT_TCP:
03345 proto_str = "TCP";
03346 break;
03347 default:
03348 proto_str = "???";
03349 break;
03350 }
03351 av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
03352 av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
03353
03354 current_bandwidth += stream->bandwidth;
03355
03356 c->next = first_http_ctx;
03357 first_http_ctx = c;
03358 return c;
03359
03360 fail:
03361 if (c) {
03362 av_free(c->buffer);
03363 av_free(c);
03364 }
03365 return NULL;
03366 }
03367
03368
03369
03370
03371 static int rtp_new_av_stream(HTTPContext *c,
03372 int stream_index, struct sockaddr_in *dest_addr,
03373 HTTPContext *rtsp_c)
03374 {
03375 AVFormatContext *ctx;
03376 AVStream *st;
03377 char *ipaddr;
03378 URLContext *h = NULL;
03379 uint8_t *dummy_buf;
03380 int max_packet_size;
03381
03382
03383 ctx = avformat_alloc_context();
03384 if (!ctx)
03385 return -1;
03386 ctx->oformat = av_guess_format("rtp", NULL, NULL);
03387
03388 st = av_mallocz(sizeof(AVStream));
03389 if (!st)
03390 goto fail;
03391 ctx->nb_streams = 1;
03392 ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
03393 if (!ctx->streams)
03394 goto fail;
03395 ctx->streams[0] = st;
03396
03397 if (!c->stream->feed ||
03398 c->stream->feed == c->stream)
03399 memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
03400 else
03401 memcpy(st,
03402 c->stream->feed->streams[c->stream->feed_streams[stream_index]],
03403 sizeof(AVStream));
03404 st->priv_data = NULL;
03405
03406
03407 ipaddr = inet_ntoa(dest_addr->sin_addr);
03408
03409 switch(c->rtp_protocol) {
03410 case RTSP_LOWER_TRANSPORT_UDP:
03411 case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
03412
03413
03414
03415 if (c->stream->is_multicast) {
03416 int ttl;
03417 ttl = c->stream->multicast_ttl;
03418 if (!ttl)
03419 ttl = 16;
03420 snprintf(ctx->filename, sizeof(ctx->filename),
03421 "rtp://%s:%d?multicast=1&ttl=%d",
03422 ipaddr, ntohs(dest_addr->sin_port), ttl);
03423 } else {
03424 snprintf(ctx->filename, sizeof(ctx->filename),
03425 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
03426 }
03427
03428 if (url_open(&h, ctx->filename, AVIO_FLAG_WRITE) < 0)
03429 goto fail;
03430 c->rtp_handles[stream_index] = h;
03431 max_packet_size = url_get_max_packet_size(h);
03432 break;
03433 case RTSP_LOWER_TRANSPORT_TCP:
03434
03435 c->rtsp_c = rtsp_c;
03436 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
03437 break;
03438 default:
03439 goto fail;
03440 }
03441
03442 http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
03443 ipaddr, ntohs(dest_addr->sin_port),
03444 c->stream->filename, stream_index, c->protocol);
03445
03446
03447 if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
03448
03449 goto fail;
03450 }
03451 if (avformat_write_header(ctx, NULL) < 0) {
03452 fail:
03453 if (h)
03454 url_close(h);
03455 av_free(ctx);
03456 return -1;
03457 }
03458 avio_close_dyn_buf(ctx->pb, &dummy_buf);
03459 av_free(dummy_buf);
03460
03461 c->rtp_ctx[stream_index] = ctx;
03462 return 0;
03463 }
03464
03465
03466
03467
03468 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
03469 {
03470 AVStream *fst;
03471
03472 fst = av_mallocz(sizeof(AVStream));
03473 if (!fst)
03474 return NULL;
03475 if (copy) {
03476 fst->codec = avcodec_alloc_context3(NULL);
03477 memcpy(fst->codec, codec, sizeof(AVCodecContext));
03478 if (codec->extradata_size) {
03479 fst->codec->extradata = av_malloc(codec->extradata_size);
03480 memcpy(fst->codec->extradata, codec->extradata,
03481 codec->extradata_size);
03482 }
03483 } else {
03484
03485
03486
03487 fst->codec = codec;
03488 }
03489 fst->priv_data = av_mallocz(sizeof(FeedData));
03490 fst->index = stream->nb_streams;
03491 av_set_pts_info(fst, 33, 1, 90000);
03492 fst->sample_aspect_ratio = codec->sample_aspect_ratio;
03493 stream->streams[stream->nb_streams++] = fst;
03494 return fst;
03495 }
03496
03497
03498 static int add_av_stream(FFStream *feed, AVStream *st)
03499 {
03500 AVStream *fst;
03501 AVCodecContext *av, *av1;
03502 int i;
03503
03504 av = st->codec;
03505 for(i=0;i<feed->nb_streams;i++) {
03506 st = feed->streams[i];
03507 av1 = st->codec;
03508 if (av1->codec_id == av->codec_id &&
03509 av1->codec_type == av->codec_type &&
03510 av1->bit_rate == av->bit_rate) {
03511
03512 switch(av->codec_type) {
03513 case AVMEDIA_TYPE_AUDIO:
03514 if (av1->channels == av->channels &&
03515 av1->sample_rate == av->sample_rate)
03516 return i;
03517 break;
03518 case AVMEDIA_TYPE_VIDEO:
03519 if (av1->width == av->width &&
03520 av1->height == av->height &&
03521 av1->time_base.den == av->time_base.den &&
03522 av1->time_base.num == av->time_base.num &&
03523 av1->gop_size == av->gop_size)
03524 return i;
03525 break;
03526 default:
03527 abort();
03528 }
03529 }
03530 }
03531
03532 fst = add_av_stream1(feed, av, 0);
03533 if (!fst)
03534 return -1;
03535 return feed->nb_streams - 1;
03536 }
03537
03538 static void remove_stream(FFStream *stream)
03539 {
03540 FFStream **ps;
03541 ps = &first_stream;
03542 while (*ps != NULL) {
03543 if (*ps == stream)
03544 *ps = (*ps)->next;
03545 else
03546 ps = &(*ps)->next;
03547 }
03548 }
03549
03550
03551 static void extract_mpeg4_header(AVFormatContext *infile)
03552 {
03553 int mpeg4_count, i, size;
03554 AVPacket pkt;
03555 AVStream *st;
03556 const uint8_t *p;
03557
03558 mpeg4_count = 0;
03559 for(i=0;i<infile->nb_streams;i++) {
03560 st = infile->streams[i];
03561 if (st->codec->codec_id == CODEC_ID_MPEG4 &&
03562 st->codec->extradata_size == 0) {
03563 mpeg4_count++;
03564 }
03565 }
03566 if (!mpeg4_count)
03567 return;
03568
03569 printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
03570 while (mpeg4_count > 0) {
03571 if (av_read_packet(infile, &pkt) < 0)
03572 break;
03573 st = infile->streams[pkt.stream_index];
03574 if (st->codec->codec_id == CODEC_ID_MPEG4 &&
03575 st->codec->extradata_size == 0) {
03576 av_freep(&st->codec->extradata);
03577
03578
03579 p = pkt.data;
03580 while (p < pkt.data + pkt.size - 4) {
03581
03582 if (p[0] == 0x00 && p[1] == 0x00 &&
03583 p[2] == 0x01 && p[3] == 0xb6) {
03584 size = p - pkt.data;
03585
03586 st->codec->extradata = av_malloc(size);
03587 st->codec->extradata_size = size;
03588 memcpy(st->codec->extradata, pkt.data, size);
03589 break;
03590 }
03591 p++;
03592 }
03593 mpeg4_count--;
03594 }
03595 av_free_packet(&pkt);
03596 }
03597 }
03598
03599
03600 static void build_file_streams(void)
03601 {
03602 FFStream *stream, *stream_next;
03603 int i, ret;
03604
03605
03606 for(stream = first_stream; stream != NULL; stream = stream_next) {
03607 AVFormatContext *infile = NULL;
03608 stream_next = stream->next;
03609 if (stream->stream_type == STREAM_TYPE_LIVE &&
03610 !stream->feed) {
03611
03612
03613
03614 if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
03615
03616
03617 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
03618 }
03619
03620 http_log("Opening file '%s'\n", stream->feed_filename);
03621 if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
03622 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
03623
03624 fail:
03625 remove_stream(stream);
03626 } else {
03627
03628
03629 if (avformat_find_stream_info(infile, NULL) < 0) {
03630 http_log("Could not find codec parameters from '%s'\n",
03631 stream->feed_filename);
03632 av_close_input_file(infile);
03633 goto fail;
03634 }
03635 extract_mpeg4_header(infile);
03636
03637 for(i=0;i<infile->nb_streams;i++)
03638 add_av_stream1(stream, infile->streams[i]->codec, 1);
03639
03640 av_close_input_file(infile);
03641 }
03642 }
03643 }
03644 }
03645
03646
03647 static void build_feed_streams(void)
03648 {
03649 FFStream *stream, *feed;
03650 int i;
03651
03652
03653 for(stream = first_stream; stream != NULL; stream = stream->next) {
03654 feed = stream->feed;
03655 if (feed) {
03656 if (stream->is_feed) {
03657 for(i=0;i<stream->nb_streams;i++)
03658 stream->feed_streams[i] = i;
03659 } else {
03660
03661 for(i=0;i<stream->nb_streams;i++)
03662 stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
03663 }
03664 }
03665 }
03666
03667
03668 for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
03669 int fd;
03670
03671 if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
03672
03673 AVFormatContext *s = NULL;
03674 int matches = 0;
03675
03676 if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
03677
03678 if (s->nb_streams == feed->nb_streams) {
03679 matches = 1;
03680 for(i=0;i<s->nb_streams;i++) {
03681 AVStream *sf, *ss;
03682 sf = feed->streams[i];
03683 ss = s->streams[i];
03684
03685 if (sf->index != ss->index ||
03686 sf->id != ss->id) {
03687 http_log("Index & Id do not match for stream %d (%s)\n",
03688 i, feed->feed_filename);
03689 matches = 0;
03690 } else {
03691 AVCodecContext *ccf, *ccs;
03692
03693 ccf = sf->codec;
03694 ccs = ss->codec;
03695 #define CHECK_CODEC(x) (ccf->x != ccs->x)
03696
03697 if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
03698 http_log("Codecs do not match for stream %d\n", i);
03699 matches = 0;
03700 } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
03701 http_log("Codec bitrates do not match for stream %d\n", i);
03702 matches = 0;
03703 } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
03704 if (CHECK_CODEC(time_base.den) ||
03705 CHECK_CODEC(time_base.num) ||
03706 CHECK_CODEC(width) ||
03707 CHECK_CODEC(height)) {
03708 http_log("Codec width, height and framerate do not match for stream %d\n", i);
03709 matches = 0;
03710 }
03711 } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
03712 if (CHECK_CODEC(sample_rate) ||
03713 CHECK_CODEC(channels) ||
03714 CHECK_CODEC(frame_size)) {
03715 http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
03716 matches = 0;
03717 }
03718 } else {
03719 http_log("Unknown codec type\n");
03720 matches = 0;
03721 }
03722 }
03723 if (!matches)
03724 break;
03725 }
03726 } else
03727 http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
03728 feed->feed_filename, s->nb_streams, feed->nb_streams);
03729
03730 av_close_input_file(s);
03731 } else
03732 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
03733 feed->feed_filename);
03734
03735 if (!matches) {
03736 if (feed->readonly) {
03737 http_log("Unable to delete feed file '%s' as it is marked readonly\n",
03738 feed->feed_filename);
03739 exit(1);
03740 }
03741 unlink(feed->feed_filename);
03742 }
03743 }
03744 if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
03745 AVFormatContext s1 = {0}, *s = &s1;
03746
03747 if (feed->readonly) {
03748 http_log("Unable to create feed file '%s' as it is marked readonly\n",
03749 feed->feed_filename);
03750 exit(1);
03751 }
03752
03753
03754 if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
03755 http_log("Could not open output feed file '%s'\n",
03756 feed->feed_filename);
03757 exit(1);
03758 }
03759 s->oformat = feed->fmt;
03760 s->nb_streams = feed->nb_streams;
03761 s->streams = feed->streams;
03762 if (avformat_write_header(s, NULL) < 0) {
03763 http_log("Container doesn't supports the required parameters\n");
03764 exit(1);
03765 }
03766
03767 av_freep(&s->priv_data);
03768 avio_close(s->pb);
03769 }
03770
03771 fd = open(feed->feed_filename, O_RDONLY);
03772 if (fd < 0) {
03773 http_log("Could not open output feed file '%s'\n",
03774 feed->feed_filename);
03775 exit(1);
03776 }
03777
03778 feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
03779 feed->feed_size = lseek(fd, 0, SEEK_END);
03780
03781 if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
03782 feed->feed_max_size = feed->feed_size;
03783
03784 close(fd);
03785 }
03786 }
03787
03788
03789 static void compute_bandwidth(void)
03790 {
03791 unsigned bandwidth;
03792 int i;
03793 FFStream *stream;
03794
03795 for(stream = first_stream; stream != NULL; stream = stream->next) {
03796 bandwidth = 0;
03797 for(i=0;i<stream->nb_streams;i++) {
03798 AVStream *st = stream->streams[i];
03799 switch(st->codec->codec_type) {
03800 case AVMEDIA_TYPE_AUDIO:
03801 case AVMEDIA_TYPE_VIDEO:
03802 bandwidth += st->codec->bit_rate;
03803 break;
03804 default:
03805 break;
03806 }
03807 }
03808 stream->bandwidth = (bandwidth + 999) / 1000;
03809 }
03810 }
03811
03812
03813 static void add_codec(FFStream *stream, AVCodecContext *av)
03814 {
03815 AVStream *st;
03816
03817
03818 switch(av->codec_type) {
03819 case AVMEDIA_TYPE_AUDIO:
03820 if (av->bit_rate == 0)
03821 av->bit_rate = 64000;
03822 if (av->sample_rate == 0)
03823 av->sample_rate = 22050;
03824 if (av->channels == 0)
03825 av->channels = 1;
03826 break;
03827 case AVMEDIA_TYPE_VIDEO:
03828 if (av->bit_rate == 0)
03829 av->bit_rate = 64000;
03830 if (av->time_base.num == 0){
03831 av->time_base.den = 5;
03832 av->time_base.num = 1;
03833 }
03834 if (av->width == 0 || av->height == 0) {
03835 av->width = 160;
03836 av->height = 128;
03837 }
03838
03839 if (av->bit_rate_tolerance == 0)
03840 av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
03841 (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
03842 if (av->qmin == 0)
03843 av->qmin = 3;
03844 if (av->qmax == 0)
03845 av->qmax = 31;
03846 if (av->max_qdiff == 0)
03847 av->max_qdiff = 3;
03848 av->qcompress = 0.5;
03849 av->qblur = 0.5;
03850
03851 if (!av->nsse_weight)
03852 av->nsse_weight = 8;
03853
03854 av->frame_skip_cmp = FF_CMP_DCTMAX;
03855 if (!av->me_method)
03856 av->me_method = ME_EPZS;
03857 av->rc_buffer_aggressivity = 1.0;
03858
03859 if (!av->rc_eq)
03860 av->rc_eq = "tex^qComp";
03861 if (!av->i_quant_factor)
03862 av->i_quant_factor = -0.8;
03863 if (!av->b_quant_factor)
03864 av->b_quant_factor = 1.25;
03865 if (!av->b_quant_offset)
03866 av->b_quant_offset = 1.25;
03867 if (!av->rc_max_rate)
03868 av->rc_max_rate = av->bit_rate * 2;
03869
03870 if (av->rc_max_rate && !av->rc_buffer_size) {
03871 av->rc_buffer_size = av->rc_max_rate;
03872 }
03873
03874
03875 break;
03876 default:
03877 abort();
03878 }
03879
03880 st = av_mallocz(sizeof(AVStream));
03881 if (!st)
03882 return;
03883 st->codec = avcodec_alloc_context3(NULL);
03884 stream->streams[stream->nb_streams++] = st;
03885 memcpy(st->codec, av, sizeof(AVCodecContext));
03886 }
03887
03888 static enum CodecID opt_audio_codec(const char *arg)
03889 {
03890 AVCodec *p= avcodec_find_encoder_by_name(arg);
03891
03892 if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
03893 return CODEC_ID_NONE;
03894
03895 return p->id;
03896 }
03897
03898 static enum CodecID opt_video_codec(const char *arg)
03899 {
03900 AVCodec *p= avcodec_find_encoder_by_name(arg);
03901
03902 if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
03903 return CODEC_ID_NONE;
03904
03905 return p->id;
03906 }
03907
03908
03909
03910 #if HAVE_DLOPEN
03911 static void load_module(const char *filename)
03912 {
03913 void *dll;
03914 void (*init_func)(void);
03915 dll = dlopen(filename, RTLD_NOW);
03916 if (!dll) {
03917 fprintf(stderr, "Could not load module '%s' - %s\n",
03918 filename, dlerror());
03919 return;
03920 }
03921
03922 init_func = dlsym(dll, "ffserver_module_init");
03923 if (!init_func) {
03924 fprintf(stderr,
03925 "%s: init function 'ffserver_module_init()' not found\n",
03926 filename);
03927 dlclose(dll);
03928 }
03929
03930 init_func();
03931 }
03932 #endif
03933
03934 static int ffserver_opt_default(const char *opt, const char *arg,
03935 AVCodecContext *avctx, int type)
03936 {
03937 int ret = 0;
03938 const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
03939 if(o)
03940 ret = av_opt_set(avctx, opt, arg, 0);
03941 return ret;
03942 }
03943
03944 static int ffserver_opt_preset(const char *arg,
03945 AVCodecContext *avctx, int type,
03946 enum CodecID *audio_id, enum CodecID *video_id)
03947 {
03948 FILE *f=NULL;
03949 char filename[1000], tmp[1000], tmp2[1000], line[1000];
03950 int ret = 0;
03951 AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
03952
03953 if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
03954 codec ? codec->name : NULL))) {
03955 fprintf(stderr, "File for preset '%s' not found\n", arg);
03956 return 1;
03957 }
03958
03959 while(!feof(f)){
03960 int e= fscanf(f, "%999[^\n]\n", line) - 1;
03961 if(line[0] == '#' && !e)
03962 continue;
03963 e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
03964 if(e){
03965 fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
03966 ret = 1;
03967 break;
03968 }
03969 if(!strcmp(tmp, "acodec")){
03970 *audio_id = opt_audio_codec(tmp2);
03971 }else if(!strcmp(tmp, "vcodec")){
03972 *video_id = opt_video_codec(tmp2);
03973 }else if(!strcmp(tmp, "scodec")){
03974
03975 }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
03976 fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
03977 ret = 1;
03978 break;
03979 }
03980 }
03981
03982 fclose(f);
03983
03984 return ret;
03985 }
03986
03987 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
03988 const char *mime_type)
03989 {
03990 AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
03991
03992 if (fmt) {
03993 AVOutputFormat *stream_fmt;
03994 char stream_format_name[64];
03995
03996 snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
03997 stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
03998
03999 if (stream_fmt)
04000 fmt = stream_fmt;
04001 }
04002
04003 return fmt;
04004 }
04005
04006 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
04007 {
04008 va_list vl;
04009 va_start(vl, fmt);
04010 fprintf(stderr, "%s:%d: ", filename, line_num);
04011 vfprintf(stderr, fmt, vl);
04012 va_end(vl);
04013
04014 (*errors)++;
04015 }
04016
04017 static int parse_ffconfig(const char *filename)
04018 {
04019 FILE *f;
04020 char line[1024];
04021 char cmd[64];
04022 char arg[1024];
04023 const char *p;
04024 int val, errors, line_num;
04025 FFStream **last_stream, *stream, *redirect;
04026 FFStream **last_feed, *feed, *s;
04027 AVCodecContext audio_enc, video_enc;
04028 enum CodecID audio_id, video_id;
04029
04030 f = fopen(filename, "r");
04031 if (!f) {
04032 perror(filename);
04033 return -1;
04034 }
04035
04036 errors = 0;
04037 line_num = 0;
04038 first_stream = NULL;
04039 last_stream = &first_stream;
04040 first_feed = NULL;
04041 last_feed = &first_feed;
04042 stream = NULL;
04043 feed = NULL;
04044 redirect = NULL;
04045 audio_id = CODEC_ID_NONE;
04046 video_id = CODEC_ID_NONE;
04047
04048 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
04049 for(;;) {
04050 if (fgets(line, sizeof(line), f) == NULL)
04051 break;
04052 line_num++;
04053 p = line;
04054 while (isspace(*p))
04055 p++;
04056 if (*p == '\0' || *p == '#')
04057 continue;
04058
04059 get_arg(cmd, sizeof(cmd), &p);
04060
04061 if (!av_strcasecmp(cmd, "Port")) {
04062 get_arg(arg, sizeof(arg), &p);
04063 val = atoi(arg);
04064 if (val < 1 || val > 65536) {
04065 ERROR("Invalid_port: %s\n", arg);
04066 }
04067 my_http_addr.sin_port = htons(val);
04068 } else if (!av_strcasecmp(cmd, "BindAddress")) {
04069 get_arg(arg, sizeof(arg), &p);
04070 if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
04071 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
04072 }
04073 } else if (!av_strcasecmp(cmd, "NoDaemon")) {
04074 ffserver_daemon = 0;
04075 } else if (!av_strcasecmp(cmd, "RTSPPort")) {
04076 get_arg(arg, sizeof(arg), &p);
04077 val = atoi(arg);
04078 if (val < 1 || val > 65536) {
04079 ERROR("%s:%d: Invalid port: %s\n", arg);
04080 }
04081 my_rtsp_addr.sin_port = htons(atoi(arg));
04082 } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
04083 get_arg(arg, sizeof(arg), &p);
04084 if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
04085 ERROR("Invalid host/IP address: %s\n", arg);
04086 }
04087 } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
04088 get_arg(arg, sizeof(arg), &p);
04089 val = atoi(arg);
04090 if (val < 1 || val > 65536) {
04091 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
04092 }
04093 nb_max_http_connections = val;
04094 } else if (!av_strcasecmp(cmd, "MaxClients")) {
04095 get_arg(arg, sizeof(arg), &p);
04096 val = atoi(arg);
04097 if (val < 1 || val > nb_max_http_connections) {
04098 ERROR("Invalid MaxClients: %s\n", arg);
04099 } else {
04100 nb_max_connections = val;
04101 }
04102 } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
04103 int64_t llval;
04104 get_arg(arg, sizeof(arg), &p);
04105 llval = atoll(arg);
04106 if (llval < 10 || llval > 10000000) {
04107 ERROR("Invalid MaxBandwidth: %s\n", arg);
04108 } else
04109 max_bandwidth = llval;
04110 } else if (!av_strcasecmp(cmd, "CustomLog")) {
04111 if (!ffserver_debug)
04112 get_arg(logfilename, sizeof(logfilename), &p);
04113 } else if (!av_strcasecmp(cmd, "<Feed")) {
04114
04115
04116 char *q;
04117 if (stream || feed) {
04118 ERROR("Already in a tag\n");
04119 } else {
04120 feed = av_mallocz(sizeof(FFStream));
04121 get_arg(feed->filename, sizeof(feed->filename), &p);
04122 q = strrchr(feed->filename, '>');
04123 if (*q)
04124 *q = '\0';
04125
04126 for (s = first_feed; s; s = s->next) {
04127 if (!strcmp(feed->filename, s->filename)) {
04128 ERROR("Feed '%s' already registered\n", s->filename);
04129 }
04130 }
04131
04132 feed->fmt = av_guess_format("ffm", NULL, NULL);
04133
04134 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
04135 "/tmp/%s.ffm", feed->filename);
04136 feed->feed_max_size = 5 * 1024 * 1024;
04137 feed->is_feed = 1;
04138 feed->feed = feed;
04139
04140
04141 *last_stream = feed;
04142 last_stream = &feed->next;
04143
04144 *last_feed = feed;
04145 last_feed = &feed->next_feed;
04146 }
04147 } else if (!av_strcasecmp(cmd, "Launch")) {
04148 if (feed) {
04149 int i;
04150
04151 feed->child_argv = av_mallocz(64 * sizeof(char *));
04152
04153 for (i = 0; i < 62; i++) {
04154 get_arg(arg, sizeof(arg), &p);
04155 if (!arg[0])
04156 break;
04157
04158 feed->child_argv[i] = av_strdup(arg);
04159 }
04160
04161 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
04162
04163 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
04164 "http://%s:%d/%s",
04165 (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
04166 inet_ntoa(my_http_addr.sin_addr),
04167 ntohs(my_http_addr.sin_port), feed->filename);
04168 }
04169 } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
04170 if (feed) {
04171 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
04172 feed->readonly = 1;
04173 } else if (stream) {
04174 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
04175 }
04176 } else if (!av_strcasecmp(cmd, "File")) {
04177 if (feed) {
04178 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
04179 } else if (stream)
04180 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
04181 } else if (!av_strcasecmp(cmd, "Truncate")) {
04182 if (feed) {
04183 get_arg(arg, sizeof(arg), &p);
04184 feed->truncate = strtod(arg, NULL);
04185 }
04186 } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
04187 if (feed) {
04188 char *p1;
04189 double fsize;
04190
04191 get_arg(arg, sizeof(arg), &p);
04192 p1 = arg;
04193 fsize = strtod(p1, &p1);
04194 switch(toupper(*p1)) {
04195 case 'K':
04196 fsize *= 1024;
04197 break;
04198 case 'M':
04199 fsize *= 1024 * 1024;
04200 break;
04201 case 'G':
04202 fsize *= 1024 * 1024 * 1024;
04203 break;
04204 }
04205 feed->feed_max_size = (int64_t)fsize;
04206 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
04207 ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
04208 }
04209 }
04210 } else if (!av_strcasecmp(cmd, "</Feed>")) {
04211 if (!feed) {
04212 ERROR("No corresponding <Feed> for </Feed>\n");
04213 }
04214 feed = NULL;
04215 } else if (!av_strcasecmp(cmd, "<Stream")) {
04216
04217
04218 char *q;
04219 if (stream || feed) {
04220 ERROR("Already in a tag\n");
04221 } else {
04222 FFStream *s;
04223 stream = av_mallocz(sizeof(FFStream));
04224 get_arg(stream->filename, sizeof(stream->filename), &p);
04225 q = strrchr(stream->filename, '>');
04226 if (*q)
04227 *q = '\0';
04228
04229 for (s = first_stream; s; s = s->next) {
04230 if (!strcmp(stream->filename, s->filename)) {
04231 ERROR("Stream '%s' already registered\n", s->filename);
04232 }
04233 }
04234
04235 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
04236 avcodec_get_context_defaults2(&video_enc, AVMEDIA_TYPE_VIDEO);
04237 avcodec_get_context_defaults2(&audio_enc, AVMEDIA_TYPE_AUDIO);
04238
04239 audio_id = CODEC_ID_NONE;
04240 video_id = CODEC_ID_NONE;
04241 if (stream->fmt) {
04242 audio_id = stream->fmt->audio_codec;
04243 video_id = stream->fmt->video_codec;
04244 }
04245
04246 *last_stream = stream;
04247 last_stream = &stream->next;
04248 }
04249 } else if (!av_strcasecmp(cmd, "Feed")) {
04250 get_arg(arg, sizeof(arg), &p);
04251 if (stream) {
04252 FFStream *sfeed;
04253
04254 sfeed = first_feed;
04255 while (sfeed != NULL) {
04256 if (!strcmp(sfeed->filename, arg))
04257 break;
04258 sfeed = sfeed->next_feed;
04259 }
04260 if (!sfeed)
04261 ERROR("feed '%s' not defined\n", arg);
04262 else
04263 stream->feed = sfeed;
04264 }
04265 } else if (!av_strcasecmp(cmd, "Format")) {
04266 get_arg(arg, sizeof(arg), &p);
04267 if (stream) {
04268 if (!strcmp(arg, "status")) {
04269 stream->stream_type = STREAM_TYPE_STATUS;
04270 stream->fmt = NULL;
04271 } else {
04272 stream->stream_type = STREAM_TYPE_LIVE;
04273
04274 if (!strcmp(arg, "jpeg"))
04275 strcpy(arg, "mjpeg");
04276 stream->fmt = ffserver_guess_format(arg, NULL, NULL);
04277 if (!stream->fmt) {
04278 ERROR("Unknown Format: %s\n", arg);
04279 }
04280 }
04281 if (stream->fmt) {
04282 audio_id = stream->fmt->audio_codec;
04283 video_id = stream->fmt->video_codec;
04284 }
04285 }
04286 } else if (!av_strcasecmp(cmd, "InputFormat")) {
04287 get_arg(arg, sizeof(arg), &p);
04288 if (stream) {
04289 stream->ifmt = av_find_input_format(arg);
04290 if (!stream->ifmt) {
04291 ERROR("Unknown input format: %s\n", arg);
04292 }
04293 }
04294 } else if (!av_strcasecmp(cmd, "FaviconURL")) {
04295 if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
04296 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
04297 } else {
04298 ERROR("FaviconURL only permitted for status streams\n");
04299 }
04300 } else if (!av_strcasecmp(cmd, "Author")) {
04301 if (stream)
04302 get_arg(stream->author, sizeof(stream->author), &p);
04303 } else if (!av_strcasecmp(cmd, "Comment")) {
04304 if (stream)
04305 get_arg(stream->comment, sizeof(stream->comment), &p);
04306 } else if (!av_strcasecmp(cmd, "Copyright")) {
04307 if (stream)
04308 get_arg(stream->copyright, sizeof(stream->copyright), &p);
04309 } else if (!av_strcasecmp(cmd, "Title")) {
04310 if (stream)
04311 get_arg(stream->title, sizeof(stream->title), &p);
04312 } else if (!av_strcasecmp(cmd, "Preroll")) {
04313 get_arg(arg, sizeof(arg), &p);
04314 if (stream)
04315 stream->prebuffer = atof(arg) * 1000;
04316 } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
04317 if (stream)
04318 stream->send_on_key = 1;
04319 } else if (!av_strcasecmp(cmd, "AudioCodec")) {
04320 get_arg(arg, sizeof(arg), &p);
04321 audio_id = opt_audio_codec(arg);
04322 if (audio_id == CODEC_ID_NONE) {
04323 ERROR("Unknown AudioCodec: %s\n", arg);
04324 }
04325 } else if (!av_strcasecmp(cmd, "VideoCodec")) {
04326 get_arg(arg, sizeof(arg), &p);
04327 video_id = opt_video_codec(arg);
04328 if (video_id == CODEC_ID_NONE) {
04329 ERROR("Unknown VideoCodec: %s\n", arg);
04330 }
04331 } else if (!av_strcasecmp(cmd, "MaxTime")) {
04332 get_arg(arg, sizeof(arg), &p);
04333 if (stream)
04334 stream->max_time = atof(arg) * 1000;
04335 } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
04336 get_arg(arg, sizeof(arg), &p);
04337 if (stream)
04338 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
04339 } else if (!av_strcasecmp(cmd, "AudioChannels")) {
04340 get_arg(arg, sizeof(arg), &p);
04341 if (stream)
04342 audio_enc.channels = atoi(arg);
04343 } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
04344 get_arg(arg, sizeof(arg), &p);
04345 if (stream)
04346 audio_enc.sample_rate = atoi(arg);
04347 } else if (!av_strcasecmp(cmd, "AudioQuality")) {
04348 get_arg(arg, sizeof(arg), &p);
04349 if (stream) {
04350
04351 }
04352 } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
04353 if (stream) {
04354 int minrate, maxrate;
04355
04356 get_arg(arg, sizeof(arg), &p);
04357
04358 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
04359 video_enc.rc_min_rate = minrate * 1000;
04360 video_enc.rc_max_rate = maxrate * 1000;
04361 } else {
04362 ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
04363 }
04364 }
04365 } else if (!av_strcasecmp(cmd, "Debug")) {
04366 if (stream) {
04367 get_arg(arg, sizeof(arg), &p);
04368 video_enc.debug = strtol(arg,0,0);
04369 }
04370 } else if (!av_strcasecmp(cmd, "Strict")) {
04371 if (stream) {
04372 get_arg(arg, sizeof(arg), &p);
04373 video_enc.strict_std_compliance = atoi(arg);
04374 }
04375 } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
04376 if (stream) {
04377 get_arg(arg, sizeof(arg), &p);
04378 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
04379 }
04380 } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
04381 if (stream) {
04382 get_arg(arg, sizeof(arg), &p);
04383 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
04384 }
04385 } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
04386 get_arg(arg, sizeof(arg), &p);
04387 if (stream) {
04388 video_enc.bit_rate = atoi(arg) * 1000;
04389 }
04390 } else if (!av_strcasecmp(cmd, "VideoSize")) {
04391 get_arg(arg, sizeof(arg), &p);
04392 if (stream) {
04393 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
04394 if ((video_enc.width % 16) != 0 ||
04395 (video_enc.height % 16) != 0) {
04396 ERROR("Image size must be a multiple of 16\n");
04397 }
04398 }
04399 } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
04400 get_arg(arg, sizeof(arg), &p);
04401 if (stream) {
04402 AVRational frame_rate;
04403 if (av_parse_video_rate(&frame_rate, arg) < 0) {
04404 ERROR("Incorrect frame rate: %s\n", arg);
04405 } else {
04406 video_enc.time_base.num = frame_rate.den;
04407 video_enc.time_base.den = frame_rate.num;
04408 }
04409 }
04410 } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
04411 get_arg(arg, sizeof(arg), &p);
04412 if (stream)
04413 video_enc.gop_size = atoi(arg);
04414 } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
04415 if (stream)
04416 video_enc.gop_size = 1;
04417 } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
04418 if (stream)
04419 video_enc.mb_decision = FF_MB_DECISION_BITS;
04420 } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
04421 if (stream) {
04422 video_enc.mb_decision = FF_MB_DECISION_BITS;
04423 video_enc.flags |= CODEC_FLAG_4MV;
04424 }
04425 } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
04426 !av_strcasecmp(cmd, "AVOptionAudio")) {
04427 char arg2[1024];
04428 AVCodecContext *avctx;
04429 int type;
04430 get_arg(arg, sizeof(arg), &p);
04431 get_arg(arg2, sizeof(arg2), &p);
04432 if (!av_strcasecmp(cmd, "AVOptionVideo")) {
04433 avctx = &video_enc;
04434 type = AV_OPT_FLAG_VIDEO_PARAM;
04435 } else {
04436 avctx = &audio_enc;
04437 type = AV_OPT_FLAG_AUDIO_PARAM;
04438 }
04439 if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
04440 ERROR("AVOption error: %s %s\n", arg, arg2);
04441 }
04442 } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
04443 !av_strcasecmp(cmd, "AVPresetAudio")) {
04444 AVCodecContext *avctx;
04445 int type;
04446 get_arg(arg, sizeof(arg), &p);
04447 if (!av_strcasecmp(cmd, "AVPresetVideo")) {
04448 avctx = &video_enc;
04449 video_enc.codec_id = video_id;
04450 type = AV_OPT_FLAG_VIDEO_PARAM;
04451 } else {
04452 avctx = &audio_enc;
04453 audio_enc.codec_id = audio_id;
04454 type = AV_OPT_FLAG_AUDIO_PARAM;
04455 }
04456 if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
04457 ERROR("AVPreset error: %s\n", arg);
04458 }
04459 } else if (!av_strcasecmp(cmd, "VideoTag")) {
04460 get_arg(arg, sizeof(arg), &p);
04461 if ((strlen(arg) == 4) && stream)
04462 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
04463 } else if (!av_strcasecmp(cmd, "BitExact")) {
04464 if (stream)
04465 video_enc.flags |= CODEC_FLAG_BITEXACT;
04466 } else if (!av_strcasecmp(cmd, "DctFastint")) {
04467 if (stream)
04468 video_enc.dct_algo = FF_DCT_FASTINT;
04469 } else if (!av_strcasecmp(cmd, "IdctSimple")) {
04470 if (stream)
04471 video_enc.idct_algo = FF_IDCT_SIMPLE;
04472 } else if (!av_strcasecmp(cmd, "Qscale")) {
04473 get_arg(arg, sizeof(arg), &p);
04474 if (stream) {
04475 video_enc.flags |= CODEC_FLAG_QSCALE;
04476 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
04477 }
04478 } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
04479 get_arg(arg, sizeof(arg), &p);
04480 if (stream) {
04481 video_enc.max_qdiff = atoi(arg);
04482 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
04483 ERROR("VideoQDiff out of range\n");
04484 }
04485 }
04486 } else if (!av_strcasecmp(cmd, "VideoQMax")) {
04487 get_arg(arg, sizeof(arg), &p);
04488 if (stream) {
04489 video_enc.qmax = atoi(arg);
04490 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
04491 ERROR("VideoQMax out of range\n");
04492 }
04493 }
04494 } else if (!av_strcasecmp(cmd, "VideoQMin")) {
04495 get_arg(arg, sizeof(arg), &p);
04496 if (stream) {
04497 video_enc.qmin = atoi(arg);
04498 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
04499 ERROR("VideoQMin out of range\n");
04500 }
04501 }
04502 } else if (!av_strcasecmp(cmd, "LumaElim")) {
04503 get_arg(arg, sizeof(arg), &p);
04504 if (stream)
04505 video_enc.luma_elim_threshold = atoi(arg);
04506 } else if (!av_strcasecmp(cmd, "ChromaElim")) {
04507 get_arg(arg, sizeof(arg), &p);
04508 if (stream)
04509 video_enc.chroma_elim_threshold = atoi(arg);
04510 } else if (!av_strcasecmp(cmd, "LumiMask")) {
04511 get_arg(arg, sizeof(arg), &p);
04512 if (stream)
04513 video_enc.lumi_masking = atof(arg);
04514 } else if (!av_strcasecmp(cmd, "DarkMask")) {
04515 get_arg(arg, sizeof(arg), &p);
04516 if (stream)
04517 video_enc.dark_masking = atof(arg);
04518 } else if (!av_strcasecmp(cmd, "NoVideo")) {
04519 video_id = CODEC_ID_NONE;
04520 } else if (!av_strcasecmp(cmd, "NoAudio")) {
04521 audio_id = CODEC_ID_NONE;
04522 } else if (!av_strcasecmp(cmd, "ACL")) {
04523 parse_acl_row(stream, feed, NULL, p, filename, line_num);
04524 } else if (!av_strcasecmp(cmd, "DynamicACL")) {
04525 if (stream) {
04526 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
04527 }
04528 } else if (!av_strcasecmp(cmd, "RTSPOption")) {
04529 get_arg(arg, sizeof(arg), &p);
04530 if (stream) {
04531 av_freep(&stream->rtsp_option);
04532 stream->rtsp_option = av_strdup(arg);
04533 }
04534 } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
04535 get_arg(arg, sizeof(arg), &p);
04536 if (stream) {
04537 if (resolve_host(&stream->multicast_ip, arg) != 0) {
04538 ERROR("Invalid host/IP address: %s\n", arg);
04539 }
04540 stream->is_multicast = 1;
04541 stream->loop = 1;
04542 }
04543 } else if (!av_strcasecmp(cmd, "MulticastPort")) {
04544 get_arg(arg, sizeof(arg), &p);
04545 if (stream)
04546 stream->multicast_port = atoi(arg);
04547 } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
04548 get_arg(arg, sizeof(arg), &p);
04549 if (stream)
04550 stream->multicast_ttl = atoi(arg);
04551 } else if (!av_strcasecmp(cmd, "NoLoop")) {
04552 if (stream)
04553 stream->loop = 0;
04554 } else if (!av_strcasecmp(cmd, "</Stream>")) {
04555 if (!stream) {
04556 ERROR("No corresponding <Stream> for </Stream>\n");
04557 } else {
04558 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
04559 if (audio_id != CODEC_ID_NONE) {
04560 audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
04561 audio_enc.codec_id = audio_id;
04562 add_codec(stream, &audio_enc);
04563 }
04564 if (video_id != CODEC_ID_NONE) {
04565 video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
04566 video_enc.codec_id = video_id;
04567 add_codec(stream, &video_enc);
04568 }
04569 }
04570 stream = NULL;
04571 }
04572 } else if (!av_strcasecmp(cmd, "<Redirect")) {
04573
04574 char *q;
04575 if (stream || feed || redirect) {
04576 ERROR("Already in a tag\n");
04577 } else {
04578 redirect = av_mallocz(sizeof(FFStream));
04579 *last_stream = redirect;
04580 last_stream = &redirect->next;
04581
04582 get_arg(redirect->filename, sizeof(redirect->filename), &p);
04583 q = strrchr(redirect->filename, '>');
04584 if (*q)
04585 *q = '\0';
04586 redirect->stream_type = STREAM_TYPE_REDIRECT;
04587 }
04588 } else if (!av_strcasecmp(cmd, "URL")) {
04589 if (redirect)
04590 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
04591 } else if (!av_strcasecmp(cmd, "</Redirect>")) {
04592 if (!redirect) {
04593 ERROR("No corresponding <Redirect> for </Redirect>\n");
04594 } else {
04595 if (!redirect->feed_filename[0]) {
04596 ERROR("No URL found for <Redirect>\n");
04597 }
04598 redirect = NULL;
04599 }
04600 } else if (!av_strcasecmp(cmd, "LoadModule")) {
04601 get_arg(arg, sizeof(arg), &p);
04602 #if HAVE_DLOPEN
04603 load_module(arg);
04604 #else
04605 ERROR("Module support not compiled into this version: '%s'\n", arg);
04606 #endif
04607 } else {
04608 ERROR("Incorrect keyword: '%s'\n", cmd);
04609 }
04610 }
04611 #undef ERROR
04612
04613 fclose(f);
04614 if (errors)
04615 return -1;
04616 else
04617 return 0;
04618 }
04619
04620 static void handle_child_exit(int sig)
04621 {
04622 pid_t pid;
04623 int status;
04624
04625 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
04626 FFStream *feed;
04627
04628 for (feed = first_feed; feed; feed = feed->next) {
04629 if (feed->pid == pid) {
04630 int uptime = time(0) - feed->pid_start;
04631
04632 feed->pid = 0;
04633 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
04634
04635 if (uptime < 30)
04636
04637 feed->child_argv = 0;
04638 }
04639 }
04640 }
04641
04642 need_to_start_children = 1;
04643 }
04644
04645 static void opt_debug(void)
04646 {
04647 ffserver_debug = 1;
04648 ffserver_daemon = 0;
04649 logfilename[0] = '-';
04650 }
04651
04652 static int opt_help(const char *opt, const char *arg)
04653 {
04654 printf("usage: ffserver [options]\n"
04655 "Hyper fast multi format Audio/Video streaming server\n");
04656 printf("\n");
04657 show_help_options(options, "Main options:\n", 0, 0);
04658 return 0;
04659 }
04660
04661 static const OptionDef options[] = {
04662 #include "cmdutils_common_opts.h"
04663 { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
04664 { "d", 0, {(void*)opt_debug}, "enable debug mode" },
04665 { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
04666 { NULL },
04667 };
04668
04669 int main(int argc, char **argv)
04670 {
04671 struct sigaction sigact;
04672
04673 parse_loglevel(argc, argv, options);
04674 av_register_all();
04675 avformat_network_init();
04676
04677 show_banner(argc, argv, options);
04678
04679 my_program_name = argv[0];
04680 my_program_dir = getcwd(0, 0);
04681 ffserver_daemon = 1;
04682
04683 parse_options(NULL, argc, argv, options, NULL);
04684
04685 unsetenv("http_proxy");
04686
04687 av_lfg_init(&random_state, av_get_random_seed());
04688
04689 memset(&sigact, 0, sizeof(sigact));
04690 sigact.sa_handler = handle_child_exit;
04691 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
04692 sigaction(SIGCHLD, &sigact, 0);
04693
04694 if (parse_ffconfig(config_filename) < 0) {
04695 fprintf(stderr, "Incorrect config file - exiting.\n");
04696 exit(1);
04697 }
04698
04699
04700 if (logfilename[0] != '\0') {
04701 if (!strcmp(logfilename, "-"))
04702 logfile = stdout;
04703 else
04704 logfile = fopen(logfilename, "a");
04705 av_log_set_callback(http_av_log);
04706 }
04707
04708 build_file_streams();
04709
04710 build_feed_streams();
04711
04712 compute_bandwidth();
04713
04714
04715 if (ffserver_daemon) {
04716 int pid;
04717
04718 pid = fork();
04719 if (pid < 0) {
04720 perror("fork");
04721 exit(1);
04722 } else if (pid > 0) {
04723
04724 exit(0);
04725 } else {
04726
04727 setsid();
04728 close(0);
04729 open("/dev/null", O_RDWR);
04730 if (strcmp(logfilename, "-") != 0) {
04731 close(1);
04732 dup(0);
04733 }
04734 close(2);
04735 dup(0);
04736 }
04737 }
04738
04739
04740 signal(SIGPIPE, SIG_IGN);
04741
04742 if (ffserver_daemon)
04743 chdir("/");
04744
04745 if (http_server() < 0) {
04746 http_log("Could not start server\n");
04747 exit(1);
04748 }
04749
04750 return 0;
04751 }