Browse code

* 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

Philip Gladstone authored on 2002/05/19 06:33:05
Showing 1 changed files
... ...
@@ -125,6 +125,8 @@ typedef struct FFStream {
125 125
     /* feed specific */
126 126
     int feed_opened;     /* true if someone if writing to feed */
127 127
     int is_feed;         /* true if it is a feed */
128
+    int conns_served;
129
+    INT64 bytes_served;
128 130
     INT64 feed_max_size;      /* maximum storage size */
129 131
     INT64 feed_write_index;   /* current write position in feed (it wraps round) */
130 132
     INT64 feed_size;          /* current size of feed */
... ...
@@ -272,7 +274,7 @@ static int http_server(struct sockaddr_in my_addr)
272 272
                 /* need to catch errors */
273 273
                 c->poll_entry = poll_entry;
274 274
                 poll_entry->fd = fd;
275
-                poll_entry->events = 0;
275
+                poll_entry->events = POLLIN;/* Maybe this will work */
276 276
                 poll_entry++;
277 277
                 break;
278 278
             default:
... ...
@@ -398,6 +400,8 @@ static int handle_http(HTTPContext *c, long cur_time)
398 398
             }
399 399
         } else {
400 400
             c->buffer_ptr += len;
401
+            c->stream->bytes_served += len;
402
+            c->data_count += len;
401 403
             if (c->buffer_ptr >= c->buffer_end) {
402 404
                 /* if error, exit */
403 405
                 if (c->http_error)
... ...
@@ -432,7 +436,7 @@ static int handle_http(HTTPContext *c, long cur_time)
432 432
         break;
433 433
     case HTTPSTATE_WAIT_FEED:
434 434
         /* no need to read if no events */
435
-        if (c->poll_entry->revents & (POLLERR | POLLHUP))
435
+        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
436 436
             return -1;
437 437
 
438 438
         /* nothing to do, we'll be waken up by incoming feed packets */
... ...
@@ -647,6 +651,7 @@ static int http_parse_request(HTTPContext *c)
647 647
     }
648 648
 
649 649
     c->stream = stream;
650
+    stream->conns_served++;
650 651
 
651 652
     /* XXX: add there authenticate and IP match */
652 653
 
... ...
@@ -770,79 +775,113 @@ static void compute_stats(HTTPContext *c)
770 770
     q += sprintf(q, "<H1>FFServer Status</H1>\n");
771 771
     /* format status */
772 772
     q += sprintf(q, "<H2>Available Streams</H2>\n");
773
-    q += sprintf(q, "<TABLE>\n");
774
-    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");
773
+    q += sprintf(q, "<TABLE cellspacing=0 cellpadding=4>\n");
774
+    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");
775 775
     stream = first_stream;
776 776
     while (stream != NULL) {
777 777
         char sfilename[1024];
778 778
         char *eosf;
779 779
 
780
-        strlcpy(sfilename, stream->filename, sizeof(sfilename) - 1);
781
-        eosf = sfilename + strlen(sfilename);
782
-        if (eosf - sfilename >= 4) {
783
-            if (strcmp(eosf - 4, ".asf") == 0) {
784
-                strcpy(eosf - 4, ".asx");
785
-            } else if (strcmp(eosf - 3, ".rm") == 0) {
786
-                strcpy(eosf - 3, ".ram");
780
+        if (stream->feed != stream) {
781
+            strlcpy(sfilename, stream->filename, sizeof(sfilename) - 1);
782
+            eosf = sfilename + strlen(sfilename);
783
+            if (eosf - sfilename >= 4) {
784
+                if (strcmp(eosf - 4, ".asf") == 0) {
785
+                    strcpy(eosf - 4, ".asx");
786
+                } else if (strcmp(eosf - 3, ".rm") == 0) {
787
+                    strcpy(eosf - 3, ".ram");
788
+                }
787 789
             }
788
-        }
789
-        
790
-        q += sprintf(q, "<TR><TD><A HREF=\"/%s\">%s</A> ", 
791
-                     sfilename, stream->filename);
792
-        switch(stream->stream_type) {
793
-        case STREAM_TYPE_LIVE:
794
-            {
795
-                int audio_bit_rate = 0;
796
-                int video_bit_rate = 0;
797
-                char *audio_codec_name = "";
798
-                char *video_codec_name = "";
799
-                char *audio_codec_name_extra = "";
800
-                char *video_codec_name_extra = "";
801
-
802
-                for(i=0;i<stream->nb_streams;i++) {
803
-                    AVStream *st = stream->streams[i];
804
-                    AVCodec *codec = avcodec_find_encoder(st->codec.codec_id);
805
-                    switch(st->codec.codec_type) {
806
-                    case CODEC_TYPE_AUDIO:
807
-                        audio_bit_rate += st->codec.bit_rate;
808
-                        if (codec) {
809
-                            if (*audio_codec_name)
810
-                                audio_codec_name_extra = "...";
811
-                            audio_codec_name = codec->name;
812
-                        }
813
-                        break;
814
-                    case CODEC_TYPE_VIDEO:
815
-                        video_bit_rate += st->codec.bit_rate;
816
-                        if (codec) {
817
-                            if (*video_codec_name)
818
-                                video_codec_name_extra = "...";
819
-                            video_codec_name = codec->name;
790
+            
791
+            q += sprintf(q, "<TR><TD><A HREF=\"/%s\">%s</A> ", 
792
+                         sfilename, stream->filename);
793
+            q += sprintf(q, "<td align=right> %d <td align=right> %lld",
794
+                        stream->conns_served, stream->bytes_served / 1000);
795
+            switch(stream->stream_type) {
796
+            case STREAM_TYPE_LIVE:
797
+                {
798
+                    int audio_bit_rate = 0;
799
+                    int video_bit_rate = 0;
800
+                    char *audio_codec_name = "";
801
+                    char *video_codec_name = "";
802
+                    char *audio_codec_name_extra = "";
803
+                    char *video_codec_name_extra = "";
804
+
805
+                    for(i=0;i<stream->nb_streams;i++) {
806
+                        AVStream *st = stream->streams[i];
807
+                        AVCodec *codec = avcodec_find_encoder(st->codec.codec_id);
808
+                        switch(st->codec.codec_type) {
809
+                        case CODEC_TYPE_AUDIO:
810
+                            audio_bit_rate += st->codec.bit_rate;
811
+                            if (codec) {
812
+                                if (*audio_codec_name)
813
+                                    audio_codec_name_extra = "...";
814
+                                audio_codec_name = codec->name;
815
+                            }
816
+                            break;
817
+                        case CODEC_TYPE_VIDEO:
818
+                            video_bit_rate += st->codec.bit_rate;
819
+                            if (codec) {
820
+                                if (*video_codec_name)
821
+                                    video_codec_name_extra = "...";
822
+                                video_codec_name = codec->name;
823
+                            }
824
+                            break;
825
+                        default:
826
+                            abort();
820 827
                         }
821
-                        break;
822
-                    default:
823
-                        abort();
824 828
                     }
829
+                    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", 
830
+                                 stream->fmt->name,
831
+                                 (audio_bit_rate + video_bit_rate) / 1000,
832
+                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
833
+                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
834
+                    if (stream->feed) {
835
+                        q += sprintf(q, "<TD>%s", stream->feed->filename);
836
+                    } else {
837
+                        q += sprintf(q, "<TD>%s", stream->feed_filename);
838
+                    }
839
+                    q += sprintf(q, "\n");
825 840
                 }
826
-                q += sprintf(q, "<TD> %s <TD> %d <TD> %d <TD> %s %s <TD> %d <TD> %s %s", 
827
-                             stream->fmt->name,
828
-                             (audio_bit_rate + video_bit_rate) / 1000,
829
-                             video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
830
-                             audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
831
-                if (stream->feed) {
832
-                    q += sprintf(q, "<TD>%s", stream->feed->filename);
833
-                } else {
834
-                    q += sprintf(q, "<TD>%s", stream->feed_filename);
835
-                }
836
-                q += sprintf(q, "\n");
841
+                break;
842
+            default:
843
+                q += sprintf(q, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n");
844
+                break;
837 845
             }
838
-            break;
839
-        default:
840
-            q += sprintf(q, "<TD> - <TD> - <TD COLSPAN=2> - <TD COLSPAN=2> -\n");
841
-            break;
842 846
         }
843 847
         stream = stream->next;
844 848
     }
845 849
     q += sprintf(q, "</TABLE>\n");
850
+
851
+    stream = first_stream;
852
+    while (stream != NULL) {
853
+        if (stream->feed == stream) {
854
+            q += sprintf(q, "<h2>Feed %s</h2>", stream->filename);
855
+            q += sprintf(q, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec\n");
856
+
857
+            for (i = 0; i < stream->nb_streams; i++) {
858
+                AVStream *st = stream->streams[i];
859
+                AVCodec *codec = avcodec_find_encoder(st->codec.codec_id);
860
+                char *type = "unknown";
861
+
862
+                switch(st->codec.codec_type) {
863
+                case CODEC_TYPE_AUDIO:
864
+                    type = "audio";
865
+                    break;
866
+                case CODEC_TYPE_VIDEO:
867
+                    type = "video";
868
+                    break;
869
+                default:
870
+                    abort();
871
+                }
872
+                q += sprintf(q, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s\n",
873
+                        i, type, st->codec.bit_rate/1000, codec ? codec->name : "");
874
+            }
875
+            q += sprintf(q, "</table>\n");
876
+
877
+        }       
878
+        stream = stream->next;
879
+    }
846 880
     
847 881
 #if 0
848 882
     {
... ...
@@ -887,7 +926,7 @@ static void compute_stats(HTTPContext *c)
887 887
     q += sprintf(q, "<TR><TD>#<TD>File<TD>IP<TD>State<TD>Size\n");
888 888
     c1 = first_http_ctx;
889 889
     i = 0;
890
-    while (c1 != NULL) {
890
+    while (c1 != NULL && q < (char *) c->buffer + sizeof(c->buffer) - 2048) {
891 891
         i++;
892 892
         p = inet_ntoa(c1->from_addr.sin_addr);
893 893
         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)
903 903
     /* date */
904 904
     ti = time(NULL);
905 905
     p = ctime(&ti);
906
-    q += sprintf(q, "<HR>Generated at %s", p);
906
+    q += sprintf(q, "<HR size=1 noshade>Generated at %s", p);
907 907
     q += sprintf(q, "</BODY>\n</HTML>\n");
908 908
 
909 909
     c->buffer_ptr = c->buffer;
... ...
@@ -1088,6 +1127,7 @@ static int http_prepare_data(HTTPContext *c)
1088 1088
                                     c->stream->feed->feed_write_index,
1089 1089
                                     c->stream->feed->feed_size);
1090 1090
             }
1091
+            
1091 1092
             if (av_read_packet(c->fmt_in, &pkt) < 0) {
1092 1093
                 if (c->stream->feed && c->stream->feed->feed_opened) {
1093 1094
                     /* if coming from feed, it means we reached the end of the
... ...
@@ -1168,7 +1208,7 @@ static int http_send_data(HTTPContext *c)
1168 1168
         if (ret < 0)
1169 1169
             return -1;
1170 1170
         else if (ret == 0) {
1171
-            break;
1171
+            continue;
1172 1172
         } else {
1173 1173
             /* state change requested */
1174 1174
             return 0;
... ...
@@ -1185,6 +1225,7 @@ static int http_send_data(HTTPContext *c)
1185 1185
         } else {
1186 1186
             c->buffer_ptr += len;
1187 1187
             c->data_count += len;
1188
+            c->stream->bytes_served += len;
1188 1189
         }
1189 1190
     }
1190 1191
     return 0;
... ...
@@ -1216,9 +1257,26 @@ static int http_start_receive_data(HTTPContext *c)
1216 1216
     
1217 1217
 static int http_receive_data(HTTPContext *c)
1218 1218
 {
1219
-    int len;
1220 1219
     HTTPContext *c1;
1221 1220
 
1221
+    if (c->buffer_end > c->buffer_ptr) {
1222
+        int len;
1223
+
1224
+        len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
1225
+        if (len < 0) {
1226
+            if (errno != EAGAIN && errno != EINTR) {
1227
+                /* error : close connection */
1228
+                goto fail;
1229
+            }
1230
+        } else if (len == 0) {
1231
+            /* end of connection : close it */
1232
+            goto fail;
1233
+        } else {
1234
+            c->buffer_ptr += len;
1235
+            c->data_count += len;
1236
+        }
1237
+    }
1238
+
1222 1239
     if (c->buffer_ptr >= c->buffer_end) {
1223 1240
         FFStream *feed = c->stream;
1224 1241
         /* a packet has been received : write it in the store, except
... ...
@@ -1276,19 +1334,6 @@ static int http_receive_data(HTTPContext *c)
1276 1276
         c->buffer_ptr = c->buffer;
1277 1277
     }
1278 1278
 
1279
-    len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
1280
-    if (len < 0) {
1281
-        if (errno != EAGAIN && errno != EINTR) {
1282
-            /* error : close connection */
1283
-            goto fail;
1284
-        }
1285
-    } else if (len == 0) {
1286
-        /* end of connection : close it */
1287
-        goto fail;
1288
-    } else {
1289
-        c->buffer_ptr += len;
1290
-        c->data_count += len;
1291
-    }
1292 1279
     return 0;
1293 1280
  fail:
1294 1281
     c->stream->feed_opened = 0;