⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffserver.c

📁 FFmpeg is an audio/video conversion tool. It includes libavcodec, the leading open source codec libr
💻 C
📖 第 1 页 / 共 5 页
字号:
                        dup2(i, 0);                    dup2(i, 1);                    dup2(i, 2);                    if (i)                        close(i);                }                pstrcpy(pathname, sizeof(pathname), my_program_name);                slash = strrchr(pathname, '/');                if (!slash) {                    slash = pathname;                } else {                    slash++;                }                strcpy(slash, "ffmpeg");                /* This is needed to make relative pathnames work */                chdir(my_program_dir);                signal(SIGPIPE, SIG_DFL);                execvp(pathname, feed->child_argv);                _exit(1);            }        }    }}/* open a listening socket */static int socket_open_listen(struct sockaddr_in *my_addr){    int server_fd, tmp;    server_fd = socket(AF_INET,SOCK_STREAM,0);    if (server_fd < 0) {        perror ("socket");        return -1;    }            tmp = 1;    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {        char bindmsg[32];        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));        perror (bindmsg);        close(server_fd);        return -1;    }      if (listen (server_fd, 5) < 0) {        perror ("listen");        close(server_fd);        return -1;    }    fcntl(server_fd, F_SETFL, O_NONBLOCK);    return server_fd;}/* start all multicast streams */static void start_multicast(void){    FFStream *stream;    char session_id[32];    HTTPContext *rtp_c;    struct sockaddr_in dest_addr;    int default_port, stream_index;    default_port = 6000;    for(stream = first_stream; stream != NULL; stream = stream->next) {        if (stream->is_multicast) {            /* open the RTP connection */            snprintf(session_id, sizeof(session_id),                      "%08x%08x", (int)random(), (int)random());            /* choose a port if none given */            if (stream->multicast_port == 0) {                stream->multicast_port = default_port;                default_port += 100;            }            dest_addr.sin_family = AF_INET;            dest_addr.sin_addr = stream->multicast_ip;            dest_addr.sin_port = htons(stream->multicast_port);            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,                                        RTSP_PROTOCOL_RTP_UDP_MULTICAST);            if (!rtp_c) {                continue;            }            if (open_input_stream(rtp_c, "") < 0) {                fprintf(stderr, "Could not open input stream for stream '%s'\n",                         stream->filename);                continue;            }            /* open each RTP stream */            for(stream_index = 0; stream_index < stream->nb_streams;                 stream_index++) {                dest_addr.sin_port = htons(stream->multicast_port +                                            2 * stream_index);                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {                    fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",                             stream->filename, stream_index);                    exit(1);                }            }            /* change state to send data */            rtp_c->state = HTTPSTATE_SEND_DATA;        }    }}/* main loop of the http server */static int http_server(void){    int server_fd, ret, rtsp_server_fd, delay, delay1;    struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 2], *poll_entry;    HTTPContext *c, *c_next;    server_fd = socket_open_listen(&my_http_addr);    if (server_fd < 0)        return -1;    rtsp_server_fd = socket_open_listen(&my_rtsp_addr);    if (rtsp_server_fd < 0)        return -1;        http_log("ffserver started.\n");    start_children(first_feed);    first_http_ctx = NULL;    nb_connections = 0;    start_multicast();    for(;;) {        poll_entry = poll_table;        poll_entry->fd = server_fd;        poll_entry->events = POLLIN;        poll_entry++;        poll_entry->fd = rtsp_server_fd;        poll_entry->events = POLLIN;        poll_entry++;        /* wait for events on each HTTP handle */        c = first_http_ctx;        delay = 1000;        while (c != NULL) {            int fd;            fd = c->fd;            switch(c->state) {            case HTTPSTATE_SEND_HEADER:            case RTSPSTATE_SEND_REPLY:            case RTSPSTATE_SEND_PACKET:                c->poll_entry = poll_entry;                poll_entry->fd = fd;                poll_entry->events = POLLOUT;                poll_entry++;                break;            case HTTPSTATE_SEND_DATA_HEADER:            case HTTPSTATE_SEND_DATA:            case HTTPSTATE_SEND_DATA_TRAILER:                if (!c->is_packetized) {                    /* for TCP, we output as much as we can (may need to put a limit) */                    c->poll_entry = poll_entry;                    poll_entry->fd = fd;                    poll_entry->events = POLLOUT;                    poll_entry++;                } else {                    /* when ffserver is doing the timing, we work by                       looking at which packet need to be sent every                       10 ms */                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */                    if (delay1 < delay)                        delay = delay1;                }                break;            case HTTPSTATE_WAIT_REQUEST:            case HTTPSTATE_RECEIVE_DATA:            case HTTPSTATE_WAIT_FEED:            case RTSPSTATE_WAIT_REQUEST:                /* need to catch errors */                c->poll_entry = poll_entry;                poll_entry->fd = fd;                poll_entry->events = POLLIN;/* Maybe this will work */                poll_entry++;                break;            default:                c->poll_entry = NULL;                break;            }            c = c->next;        }        /* wait for an event on one connection. We poll at least every           second to handle timeouts */        do {            ret = poll(poll_table, poll_entry - poll_table, delay);        } while (ret == -1);                cur_time = gettime_ms();        if (need_to_start_children) {            need_to_start_children = 0;            start_children(first_feed);        }        /* now handle the events */        for(c = first_http_ctx; c != NULL; c = c_next) {            c_next = c->next;            if (handle_connection(c) < 0) {                /* close and free the connection */                log_connection(c);                close_connection(c);            }        }        poll_entry = poll_table;        /* new HTTP connection request ? */        if (poll_entry->revents & POLLIN) {            new_connection(server_fd, 0);        }        poll_entry++;        /* new RTSP connection request ? */        if (poll_entry->revents & POLLIN) {            new_connection(rtsp_server_fd, 1);        }    }}/* start waiting for a new HTTP/RTSP request */static void start_wait_request(HTTPContext *c, int is_rtsp){    c->buffer_ptr = c->buffer;    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */    if (is_rtsp) {        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;        c->state = RTSPSTATE_WAIT_REQUEST;    } else {        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;        c->state = HTTPSTATE_WAIT_REQUEST;    }}static void new_connection(int server_fd, int is_rtsp){    struct sockaddr_in from_addr;    int fd, len;    HTTPContext *c = NULL;    len = sizeof(from_addr);    fd = accept(server_fd, (struct sockaddr *)&from_addr,                 &len);    if (fd < 0)        return;    fcntl(fd, F_SETFL, O_NONBLOCK);    /* XXX: should output a warning page when coming       close to the connection limit */    if (nb_connections >= nb_max_connections)        goto fail;        /* add a new connection */    c = av_mallocz(sizeof(HTTPContext));    if (!c)        goto fail;        c->fd = fd;    c->poll_entry = NULL;    c->from_addr = from_addr;    c->buffer_size = IOBUFFER_INIT_SIZE;    c->buffer = av_malloc(c->buffer_size);    if (!c->buffer)        goto fail;    c->next = first_http_ctx;    first_http_ctx = c;    nb_connections++;        start_wait_request(c, is_rtsp);    return; fail:    if (c) {        av_free(c->buffer);        av_free(c);    }    close(fd);}static void close_connection(HTTPContext *c){    HTTPContext **cp, *c1;    int i, nb_streams;    AVFormatContext *ctx;    URLContext *h;    AVStream *st;    /* remove connection from list */    cp = &first_http_ctx;    while ((*cp) != NULL) {        c1 = *cp;        if (c1 == c) {            *cp = c->next;        } else {            cp = &c1->next;        }    }    /* remove references, if any (XXX: do it faster) */    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {        if (c1->rtsp_c == c)            c1->rtsp_c = NULL;    }    /* remove connection associated resources */    if (c->fd >= 0)        close(c->fd);    if (c->fmt_in) {        /* close each frame parser */        for(i=0;i<c->fmt_in->nb_streams;i++) {            st = c->fmt_in->streams[i];            if (st->codec.codec) {                avcodec_close(&st->codec);            }        }        av_close_input_file(c->fmt_in);    }    /* free RTP output streams if any */    nb_streams = 0;    if (c->stream)         nb_streams = c->stream->nb_streams;        for(i=0;i<nb_streams;i++) {        ctx = c->rtp_ctx[i];        if (ctx) {            av_write_trailer(ctx);            av_free(ctx);        }        h = c->rtp_handles[i];        if (h) {            url_close(h);        }    }        ctx = &c->fmt_ctx;    if (!c->last_packet_sent) {        if (ctx->oformat) {            /* prepare header */            if (url_open_dyn_buf(&ctx->pb) >= 0) {                av_write_trailer(ctx);                url_close_dyn_buf(&ctx->pb, &c->pb_buffer);            }        }    }    for(i=0; i<ctx->nb_streams; i++)         av_free(ctx->streams[i]) ;     if (c->stream)        current_bandwidth -= c->stream->bandwidth;    av_freep(&c->pb_buffer);    av_freep(&c->packet_buffer);    av_free(c->buffer);    av_free(c);    nb_connections--;}static int handle_connection(HTTPContext *c){    int len, ret;        switch(c->state) {    case HTTPSTATE_WAIT_REQUEST:    case RTSPSTATE_WAIT_REQUEST:        /* timeout ? */        if ((c->timeout - cur_time) < 0)            return -1;        if (c->poll_entry->revents & (POLLERR | POLLHUP))            return -1;        /* no need to read if no events */        if (!(c->poll_entry->revents & POLLIN))            return 0;        /* read the data */    read_loop:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -