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