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

📄 ffserver.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 5 页
字号:

    if (c->stream->stream_type == STREAM_TYPE_STATUS)
        goto send_stats;

    /* open input stream */
    if (open_input_stream(c, info) < 0) {
        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
        goto send_error;
    }

    /* prepare http header */
    q = c->buffer;
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
    mime_type = c->stream->fmt->mime_type;
    if (!mime_type)
        mime_type = "application/x-octet-stream";
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");

    /* for asf, we need extra headers */
    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
        /* Need to allocate a client id */

        c->wmp_client_id = av_random(&random_state) & 0x7fffffff;

        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);
    }
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");

    /* prepare output buffer */
    c->http_error = 0;
    c->buffer_ptr = c->buffer;
    c->buffer_end = q;
    c->state = HTTPSTATE_SEND_HEADER;
    return 0;
 send_error:
    c->http_error = 404;
    q = c->buffer;
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n");
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html");
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n");
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg);
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</HTML>\n");

    /* prepare output buffer */
    c->buffer_ptr = c->buffer;
    c->buffer_end = q;
    c->state = HTTPSTATE_SEND_HEADER;
    return 0;
 send_stats:
    compute_stats(c);
    c->http_error = 200; /* horrible : we use this value to avoid
                            going to the send data state */
    c->state = HTTPSTATE_SEND_HEADER;
    return 0;
}

static void fmt_bytecount(ByteIOContext *pb, int64_t count)
{
    static const char *suffix = " kMGTP";
    const char *s;

    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);

    url_fprintf(pb, "%"PRId64"%c", count, *s);
}

static void compute_stats(HTTPContext *c)
{
    HTTPContext *c1;
    FFStream *stream;
    char *p;
    time_t ti;
    int i, len;
    ByteIOContext pb1, *pb = &pb1;

    if (url_open_dyn_buf(pb) < 0) {
        /* XXX: return an error ? */
        c->buffer_ptr = c->buffer;
        c->buffer_end = c->buffer;
        return;
    }

    url_fprintf(pb, "HTTP/1.0 200 OK\r\n");
    url_fprintf(pb, "Content-type: %s\r\n", "text/html");
    url_fprintf(pb, "Pragma: no-cache\r\n");
    url_fprintf(pb, "\r\n");

    url_fprintf(pb, "<HEAD><TITLE>FFServer Status</TITLE>\n");
    if (c->stream->feed_filename)
        url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
    url_fprintf(pb, "</HEAD>\n<BODY>");
    url_fprintf(pb, "<H1>FFServer Status</H1>\n");
    /* format status */
    url_fprintf(pb, "<H2>Available Streams</H2>\n");
    url_fprintf(pb, "<TABLE cellspacing=0 cellpadding=4>\n");
    url_fprintf(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");
    stream = first_stream;
    while (stream != NULL) {
        char sfilename[1024];
        char *eosf;

        if (stream->feed != stream) {
            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
            eosf = sfilename + strlen(sfilename);
            if (eosf - sfilename >= 4) {
                if (strcmp(eosf - 4, ".asf") == 0)
                    strcpy(eosf - 4, ".asx");
                else if (strcmp(eosf - 3, ".rm") == 0)
                    strcpy(eosf - 3, ".ram");
                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
                    /* generate a sample RTSP director if
                       unicast. Generate an SDP redirector if
                       multicast */
                    eosf = strrchr(sfilename, '.');
                    if (!eosf)
                        eosf = sfilename + strlen(sfilename);
                    if (stream->is_multicast)
                        strcpy(eosf, ".sdp");
                    else
                        strcpy(eosf, ".rtsp");
                }
            }

            url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ",
                         sfilename, stream->filename);
            url_fprintf(pb, "<td align=right> %d <td align=right> ",
                        stream->conns_served);
            fmt_bytecount(pb, stream->bytes_served);
            switch(stream->stream_type) {
            case STREAM_TYPE_LIVE:
                {
                    int audio_bit_rate = 0;
                    int video_bit_rate = 0;
                    const char *audio_codec_name = "";
                    const char *video_codec_name = "";
                    const char *audio_codec_name_extra = "";
                    const char *video_codec_name_extra = "";

                    for(i=0;i<stream->nb_streams;i++) {
                        AVStream *st = stream->streams[i];
                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
                        switch(st->codec->codec_type) {
                        case CODEC_TYPE_AUDIO:
                            audio_bit_rate += st->codec->bit_rate;
                            if (codec) {
                                if (*audio_codec_name)
                                    audio_codec_name_extra = "...";
                                audio_codec_name = codec->name;
                            }
                            break;
                        case CODEC_TYPE_VIDEO:
                            video_bit_rate += st->codec->bit_rate;
                            if (codec) {
                                if (*video_codec_name)
                                    video_codec_name_extra = "...";
                                video_codec_name = codec->name;
                            }
                            break;
                        case CODEC_TYPE_DATA:
                            video_bit_rate += st->codec->bit_rate;
                            break;
                        default:
                            abort();
                        }
                    }
                    url_fprintf(pb, "<TD align=center> %s <TD align=right> %d <TD align=right> %d <TD> %s %s <TD align=right> %d <TD> %s %s",
                                 stream->fmt->name,
                                 stream->bandwidth,
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
                    if (stream->feed)
                        url_fprintf(pb, "<TD>%s", stream->feed->filename);
                    else
                        url_fprintf(pb, "<TD>%s", stream->feed_filename);
                    url_fprintf(pb, "\n");
                }
                break;
            default:
                url_fprintf(pb, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n");
                break;
            }
        }
        stream = stream->next;
    }
    url_fprintf(pb, "</TABLE>\n");

    stream = first_stream;
    while (stream != NULL) {
        if (stream->feed == stream) {
            url_fprintf(pb, "<h2>Feed %s</h2>", stream->filename);
            if (stream->pid) {
                url_fprintf(pb, "Running as pid %d.\n", stream->pid);

#if defined(linux) && !defined(CONFIG_NOCUTILS)
                {
                    FILE *pid_stat;
                    char ps_cmd[64];

                    /* This is somewhat linux specific I guess */
                    snprintf(ps_cmd, sizeof(ps_cmd),
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
                             stream->pid);

                    pid_stat = popen(ps_cmd, "r");
                    if (pid_stat) {
                        char cpuperc[10];
                        char cpuused[64];

                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
                                   cpuused) == 2) {
                            url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
                                         cpuperc, cpuused);
                        }
                        fclose(pid_stat);
                    }
                }
#endif

                url_fprintf(pb, "<p>");
            }
            url_fprintf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");

            for (i = 0; i < stream->nb_streams; i++) {
                AVStream *st = stream->streams[i];
                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
                const char *type = "unknown";
                char parameters[64];

                parameters[0] = 0;

                switch(st->codec->codec_type) {
                case CODEC_TYPE_AUDIO:
                    type = "audio";
                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
                    break;
                case CODEC_TYPE_VIDEO:
                    type = "video";
                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
                    break;
                default:
                    abort();
                }
                url_fprintf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
            }
            url_fprintf(pb, "</table>\n");

        }
        stream = stream->next;
    }

#if 0
    {
        float avg;
        AVCodecContext *enc;
        char buf[1024];

        /* feed status */
        stream = first_feed;
        while (stream != NULL) {
            url_fprintf(pb, "<H1>Feed '%s'</H1>\n", stream->filename);
            url_fprintf(pb, "<TABLE>\n");
            url_fprintf(pb, "<TR><TD>Parameters<TD>Frame count<TD>Size<TD>Avg bitrate (kbits/s)\n");
            for(i=0;i<stream->nb_streams;i++) {
                AVStream *st = stream->streams[i];
                FeedData *fdata = st->priv_data;
                enc = st->codec;

                avcodec_string(buf, sizeof(buf), enc);
                avg = fdata->avg_frame_size * (float)enc->rate * 8.0;
                if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
                    avg /= enc->frame_size;
                url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %"PRId64" <TD> %0.1f\n",
                             buf, enc->frame_number, fdata->data_count, avg / 1000.0);
            }
            url_fprintf(pb, "</TABLE>\n");
            stream = stream->next_feed;
        }
    }
#endif

    /* connection status */
    url_fprintf(pb, "<H2>Connection Status</H2>\n");

    url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
                 nb_connections, nb_max_connections);

    url_fprintf(pb, "Bandwidth in use: %dk / %dk<BR>\n",
                 current_bandwidth, max_bandwidth);

    url_fprintf(pb, "<TABLE>\n");
    url_fprintf(pb, "<TR><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
    c1 = first_http_ctx;
    i = 0;
    while (c1 != NULL) {
        int bitrate;
        int j;

        bitrate = 0;
        if (c1->stream) {
            for (j = 0; j < c1->stream->nb_streams; j++) {
                if (!c1->stream->feed)
                    bitrate += c1->stream->streams[j]->codec->bit_rate;
                else if (c1->feed_streams[j] >= 0)
                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
            }
        }

        i++;
        p = inet_ntoa(c1->from_addr.sin_addr);
        url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>",
                    i,
                    c1->stream ? c1->stream->filename : "",
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
                    p,
                    c1->protocol,
                    http_state[c1->state]);
        fmt_bytecount(pb, bitrate);
        url_fprintf(pb, "<td align=right>");
        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
        url_fprintf(pb, "<td align=right>");
        fmt_bytecount(pb, c1->data_count);
        url_fprintf(pb, "\n");
        c1 = c1->next;
    }
    url_fprintf(pb, "</TABLE>\n");

    /* date */
    ti = time(NULL);
    p = ctime(&ti);
    url_fprintf(pb, "<HR size=1 noshade>Generated at %s", p);
    url_fprintf(pb, "</BODY>\n</HTML>\n");

    len = url_close_dyn_buf(pb, &c->pb_buffer);
    c->buffer_ptr = c->pb_buffer;
    c->buffer_end = c->pb_buffer + len;
}

/* check if the parser needs to be opened for stream i */
static void open_parser(AVFormatContext *s, int i)
{
    AVStream *st = s->streams[i];
    AVCodec *codec;

    if (!st->codec->codec) {
        codec = avcodec_find_decoder(st->codec->codec_id);
        if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
            st->codec->parse_only = 1;
            if (avcodec_open(st->codec, codec) < 0)
                st->codec->parse_only = 0;
        }
    }
}

static int open_input_stream(HTTPContext *c, const char *info)
{
    char buf[128];
    char input_filename[1024];
    AVFormatContext *s;
    int buf_size, i;
    int64_t stream_pos;

    /* find file name */
    if (c->stream->feed) {
        strcpy(input_filename, c->stream->feed->feed_filename);
        buf_size = FFM_PACKET_SIZE;
        /* compute position (absolute time) */
        if (find_info_tag(buf, sizeof(buf), "date", info))
        {
            stream_pos = parse_date(buf, 0);
            if (stream_pos == INT64_MIN)
           

⌨️ 快捷键说明

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