diff options
author | Philip Gladstone <philipjsg@users.sourceforge.net> | 2002-05-18 21:33:05 +0000 |
---|---|---|
committer | Philip Gladstone <philipjsg@users.sourceforge.net> | 2002-05-18 21:33:05 +0000 |
commit | a6e14edde01bafbbe54f6f451efa718a48975b47 (patch) | |
tree | ab78aad77b4979995db30561911961eed847efe3 /ffserver.c | |
parent | 5e57424d118c2faa12b0caa0b9f7816942ba5be2 (diff) | |
download | ffmpeg-a6e14edde01bafbbe54f6f451efa718a48975b47.tar.gz |
* If a stream gets stuck in WAIT_FEED, then disconnecting the other end
will clear out the stream. I think that this is really a linux bug in
the handling of poll, but I did a workaround anyway.
* Improve the statistics output and prevent a buffer overrun when lots
of clients are connected.
* Process ffm input when it is received and don't always be one ffm
packet behind.
* Try to avoid going through the poll loop when not required.
Originally committed as revision 514 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'ffserver.c')
-rw-r--r-- | ffserver.c | 201 |
1 files changed, 123 insertions, 78 deletions
diff --git a/ffserver.c b/ffserver.c index 1b5d4a049f..3fc8250a51 100644 --- a/ffserver.c +++ b/ffserver.c @@ -125,6 +125,8 @@ typedef struct FFStream { /* feed specific */ int feed_opened; /* true if someone if writing to feed */ int is_feed; /* true if it is a feed */ + int conns_served; + INT64 bytes_served; INT64 feed_max_size; /* maximum storage size */ INT64 feed_write_index; /* current write position in feed (it wraps round) */ INT64 feed_size; /* current size of feed */ @@ -272,7 +274,7 @@ static int http_server(struct sockaddr_in my_addr) /* need to catch errors */ c->poll_entry = poll_entry; poll_entry->fd = fd; - poll_entry->events = 0; + poll_entry->events = POLLIN;/* Maybe this will work */ poll_entry++; break; default: @@ -398,6 +400,8 @@ static int handle_http(HTTPContext *c, long cur_time) } } else { c->buffer_ptr += len; + c->stream->bytes_served += len; + c->data_count += len; if (c->buffer_ptr >= c->buffer_end) { /* if error, exit */ if (c->http_error) @@ -432,7 +436,7 @@ static int handle_http(HTTPContext *c, long cur_time) break; case HTTPSTATE_WAIT_FEED: /* no need to read if no events */ - if (c->poll_entry->revents & (POLLERR | POLLHUP)) + if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP)) return -1; /* nothing to do, we'll be waken up by incoming feed packets */ @@ -647,6 +651,7 @@ static int http_parse_request(HTTPContext *c) } c->stream = stream; + stream->conns_served++; /* XXX: add there authenticate and IP match */ @@ -770,79 +775,113 @@ static void compute_stats(HTTPContext *c) q += sprintf(q, "<H1>FFServer Status</H1>\n"); /* format status */ q += sprintf(q, "<H2>Available Streams</H2>\n"); - q += sprintf(q, "<TABLE>\n"); - q += sprintf(q, "<TR><Th>Path<Th>Format<Th>Bit rate (kbits/s)<Th COLSPAN=2>Video<Th COLSPAN=2>Audio<Th align=left>Feed\n"); + q += sprintf(q, "<TABLE cellspacing=0 cellpadding=4>\n"); + q += sprintf(q, "<TR><Th valign=top>Path<th align=left>Served<br>Conns<Th><br>kbytes<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; - strlcpy(sfilename, stream->filename, sizeof(sfilename) - 1); - 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"); + if (stream->feed != stream) { + strlcpy(sfilename, stream->filename, sizeof(sfilename) - 1); + 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"); + } } - } - - q += sprintf(q, "<TR><TD><A HREF=\"/%s\">%s</A> ", - sfilename, stream->filename); - switch(stream->stream_type) { - case STREAM_TYPE_LIVE: - { - int audio_bit_rate = 0; - int video_bit_rate = 0; - char *audio_codec_name = ""; - char *video_codec_name = ""; - char *audio_codec_name_extra = ""; - 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; + + q += sprintf(q, "<TR><TD><A HREF=\"/%s\">%s</A> ", + sfilename, stream->filename); + q += sprintf(q, "<td align=right> %d <td align=right> %lld", + stream->conns_served, stream->bytes_served / 1000); + switch(stream->stream_type) { + case STREAM_TYPE_LIVE: + { + int audio_bit_rate = 0; + int video_bit_rate = 0; + char *audio_codec_name = ""; + char *video_codec_name = ""; + char *audio_codec_name_extra = ""; + 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; + default: + abort(); } - break; - default: - abort(); } + q += sprintf(q, "<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, + (audio_bit_rate + video_bit_rate) / 1000, + 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) { + q += sprintf(q, "<TD>%s", stream->feed->filename); + } else { + q += sprintf(q, "<TD>%s", stream->feed_filename); + } + q += sprintf(q, "\n"); } - q += sprintf(q, "<TD> %s <TD> %d <TD> %d <TD> %s %s <TD> %d <TD> %s %s", - stream->fmt->name, - (audio_bit_rate + video_bit_rate) / 1000, - 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) { - q += sprintf(q, "<TD>%s", stream->feed->filename); - } else { - q += sprintf(q, "<TD>%s", stream->feed_filename); - } - q += sprintf(q, "\n"); + break; + default: + q += sprintf(q, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n"); + break; } - break; - default: - q += sprintf(q, "<TD> - <TD> - <TD COLSPAN=2> - <TD COLSPAN=2> -\n"); - break; } stream = stream->next; } q += sprintf(q, "</TABLE>\n"); + + stream = first_stream; + while (stream != NULL) { + if (stream->feed == stream) { + q += sprintf(q, "<h2>Feed %s</h2>", stream->filename); + q += sprintf(q, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec\n"); + + for (i = 0; i < stream->nb_streams; i++) { + AVStream *st = stream->streams[i]; + AVCodec *codec = avcodec_find_encoder(st->codec.codec_id); + char *type = "unknown"; + + switch(st->codec.codec_type) { + case CODEC_TYPE_AUDIO: + type = "audio"; + break; + case CODEC_TYPE_VIDEO: + type = "video"; + break; + default: + abort(); + } + q += sprintf(q, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s\n", + i, type, st->codec.bit_rate/1000, codec ? codec->name : ""); + } + q += sprintf(q, "</table>\n"); + + } + stream = stream->next; + } #if 0 { @@ -887,7 +926,7 @@ static void compute_stats(HTTPContext *c) q += sprintf(q, "<TR><TD>#<TD>File<TD>IP<TD>State<TD>Size\n"); c1 = first_http_ctx; i = 0; - while (c1 != NULL) { + while (c1 != NULL && q < (char *) c->buffer + sizeof(c->buffer) - 2048) { i++; p = inet_ntoa(c1->from_addr.sin_addr); q += sprintf(q, "<TR><TD><B>%d</B><TD>%s%s <TD> %s <TD> %s <TD> %Ld\n", @@ -903,7 +942,7 @@ static void compute_stats(HTTPContext *c) /* date */ ti = time(NULL); p = ctime(&ti); - q += sprintf(q, "<HR>Generated at %s", p); + q += sprintf(q, "<HR size=1 noshade>Generated at %s", p); q += sprintf(q, "</BODY>\n</HTML>\n"); c->buffer_ptr = c->buffer; @@ -1088,6 +1127,7 @@ static int http_prepare_data(HTTPContext *c) c->stream->feed->feed_write_index, c->stream->feed->feed_size); } + if (av_read_packet(c->fmt_in, &pkt) < 0) { if (c->stream->feed && c->stream->feed->feed_opened) { /* if coming from feed, it means we reached the end of the @@ -1168,7 +1208,7 @@ static int http_send_data(HTTPContext *c) if (ret < 0) return -1; else if (ret == 0) { - break; + continue; } else { /* state change requested */ return 0; @@ -1185,6 +1225,7 @@ static int http_send_data(HTTPContext *c) } else { c->buffer_ptr += len; c->data_count += len; + c->stream->bytes_served += len; } } return 0; @@ -1216,9 +1257,26 @@ static int http_start_receive_data(HTTPContext *c) static int http_receive_data(HTTPContext *c) { - int len; HTTPContext *c1; + if (c->buffer_end > c->buffer_ptr) { + int len; + + len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); + if (len < 0) { + if (errno != EAGAIN && errno != EINTR) { + /* error : close connection */ + goto fail; + } + } else if (len == 0) { + /* end of connection : close it */ + goto fail; + } else { + c->buffer_ptr += len; + c->data_count += len; + } + } + if (c->buffer_ptr >= c->buffer_end) { FFStream *feed = c->stream; /* a packet has been received : write it in the store, except @@ -1276,19 +1334,6 @@ static int http_receive_data(HTTPContext *c) c->buffer_ptr = c->buffer; } - len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); - if (len < 0) { - if (errno != EAGAIN && errno != EINTR) { - /* error : close connection */ - goto fail; - } - } else if (len == 0) { - /* end of connection : close it */ - goto fail; - } else { - c->buffer_ptr += len; - c->data_count += len; - } return 0; fail: c->stream->feed_opened = 0; |