Fix streaming from non-streaming ffm files. It turned out that you
always got 'index & id do not match' errors.
Add some more error detection on getting FFM feeds
Originally committed as revision 2523 to svn://svn.ffmpeg.org/ffmpeg/trunk
... | ... |
@@ -1253,7 +1253,7 @@ static int http_parse_request(HTTPContext *c) |
1253 | 1253 |
stream = stream->next; |
1254 | 1254 |
} |
1255 | 1255 |
if (stream == NULL) { |
1256 |
- sprintf(msg, "File '%s' not found", url); |
|
1256 |
+ snprintf(msg, sizeof(msg), "File '%s' not found", url); |
|
1257 | 1257 |
goto send_error; |
1258 | 1258 |
} |
1259 | 1259 |
|
... | ... |
@@ -1264,13 +1264,13 @@ static int http_parse_request(HTTPContext *c) |
1264 | 1264 |
if (stream->stream_type == STREAM_TYPE_REDIRECT) { |
1265 | 1265 |
c->http_error = 301; |
1266 | 1266 |
q = c->buffer; |
1267 |
- q += sprintf(q, "HTTP/1.0 301 Moved\r\n"); |
|
1268 |
- q += sprintf(q, "Location: %s\r\n", stream->feed_filename); |
|
1269 |
- q += sprintf(q, "Content-type: text/html\r\n"); |
|
1270 |
- q += sprintf(q, "\r\n"); |
|
1271 |
- q += sprintf(q, "<html><head><title>Moved</title></head><body>\r\n"); |
|
1272 |
- q += sprintf(q, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename); |
|
1273 |
- q += sprintf(q, "</body></html>\r\n"); |
|
1267 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n"); |
|
1268 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename); |
|
1269 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); |
|
1270 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1271 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Moved</title></head><body>\r\n"); |
|
1272 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename); |
|
1273 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n"); |
|
1274 | 1274 |
|
1275 | 1275 |
/* prepare output buffer */ |
1276 | 1276 |
c->buffer_ptr = c->buffer; |
... | ... |
@@ -1296,14 +1296,14 @@ static int http_parse_request(HTTPContext *c) |
1296 | 1296 |
if (post == 0 && max_bandwidth < current_bandwidth) { |
1297 | 1297 |
c->http_error = 200; |
1298 | 1298 |
q = c->buffer; |
1299 |
- q += sprintf(q, "HTTP/1.0 200 Server too busy\r\n"); |
|
1300 |
- q += sprintf(q, "Content-type: text/html\r\n"); |
|
1301 |
- q += sprintf(q, "\r\n"); |
|
1302 |
- q += sprintf(q, "<html><head><title>Too busy</title></head><body>\r\n"); |
|
1303 |
- q += sprintf(q, "The server is too busy to serve your request at this time.<p>\r\n"); |
|
1304 |
- q += sprintf(q, "The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec\r\n", |
|
1299 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n"); |
|
1300 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n"); |
|
1301 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1302 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Too busy</title></head><body>\r\n"); |
|
1303 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "The server is too busy to serve your request at this time.<p>\r\n"); |
|
1304 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "The bandwidth being served (including your stream) is %dkbit/sec, and this exceeds the limit of %dkbit/sec\r\n", |
|
1305 | 1305 |
current_bandwidth, max_bandwidth); |
1306 |
- q += sprintf(q, "</body></html>\r\n"); |
|
1306 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n"); |
|
1307 | 1307 |
|
1308 | 1308 |
/* prepare output buffer */ |
1309 | 1309 |
c->buffer_ptr = c->buffer; |
... | ... |
@@ -1347,29 +1347,29 @@ static int http_parse_request(HTTPContext *c) |
1347 | 1347 |
q = c->buffer; |
1348 | 1348 |
switch(redir_type) { |
1349 | 1349 |
case REDIR_ASX: |
1350 |
- q += sprintf(q, "HTTP/1.0 200 ASX Follows\r\n"); |
|
1351 |
- q += sprintf(q, "Content-type: video/x-ms-asf\r\n"); |
|
1352 |
- q += sprintf(q, "\r\n"); |
|
1353 |
- q += sprintf(q, "<ASX Version=\"3\">\r\n"); |
|
1354 |
- q += sprintf(q, "<!-- Autogenerated by ffserver -->\r\n"); |
|
1355 |
- q += sprintf(q, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n", |
|
1350 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n"); |
|
1351 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); |
|
1352 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1353 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n"); |
|
1354 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n"); |
|
1355 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n", |
|
1356 | 1356 |
hostbuf, filename, info); |
1357 |
- q += sprintf(q, "</ASX>\r\n"); |
|
1357 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n"); |
|
1358 | 1358 |
break; |
1359 | 1359 |
case REDIR_RAM: |
1360 |
- q += sprintf(q, "HTTP/1.0 200 RAM Follows\r\n"); |
|
1361 |
- q += sprintf(q, "Content-type: audio/x-pn-realaudio\r\n"); |
|
1362 |
- q += sprintf(q, "\r\n"); |
|
1363 |
- q += sprintf(q, "# Autogenerated by ffserver\r\n"); |
|
1364 |
- q += sprintf(q, "http://%s/%s%s\r\n", |
|
1360 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n"); |
|
1361 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n"); |
|
1362 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1363 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n"); |
|
1364 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n", |
|
1365 | 1365 |
hostbuf, filename, info); |
1366 | 1366 |
break; |
1367 | 1367 |
case REDIR_ASF: |
1368 |
- q += sprintf(q, "HTTP/1.0 200 ASF Redirect follows\r\n"); |
|
1369 |
- q += sprintf(q, "Content-type: video/x-ms-asf\r\n"); |
|
1370 |
- q += sprintf(q, "\r\n"); |
|
1371 |
- q += sprintf(q, "[Reference]\r\n"); |
|
1372 |
- q += sprintf(q, "Ref1=http://%s/%s%s\r\n", |
|
1368 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n"); |
|
1369 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n"); |
|
1370 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1371 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n"); |
|
1372 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n", |
|
1373 | 1373 |
hostbuf, filename, info); |
1374 | 1374 |
break; |
1375 | 1375 |
case REDIR_RTSP: |
... | ... |
@@ -1380,11 +1380,11 @@ static int http_parse_request(HTTPContext *c) |
1380 | 1380 |
p = strrchr(hostname, ':'); |
1381 | 1381 |
if (p) |
1382 | 1382 |
*p = '\0'; |
1383 |
- q += sprintf(q, "HTTP/1.0 200 RTSP Redirect follows\r\n"); |
|
1383 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n"); |
|
1384 | 1384 |
/* XXX: incorrect mime type ? */ |
1385 |
- q += sprintf(q, "Content-type: application/x-rtsp\r\n"); |
|
1386 |
- q += sprintf(q, "\r\n"); |
|
1387 |
- q += sprintf(q, "rtsp://%s:%d/%s\r\n", |
|
1385 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n"); |
|
1386 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1387 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n", |
|
1388 | 1388 |
hostname, ntohs(my_rtsp_addr.sin_port), |
1389 | 1389 |
filename); |
1390 | 1390 |
} |
... | ... |
@@ -1395,9 +1395,9 @@ static int http_parse_request(HTTPContext *c) |
1395 | 1395 |
int sdp_data_size, len; |
1396 | 1396 |
struct sockaddr_in my_addr; |
1397 | 1397 |
|
1398 |
- q += sprintf(q, "HTTP/1.0 200 OK\r\n"); |
|
1399 |
- q += sprintf(q, "Content-type: application/sdp\r\n"); |
|
1400 |
- q += sprintf(q, "\r\n"); |
|
1398 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); |
|
1399 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n"); |
|
1400 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1401 | 1401 |
|
1402 | 1402 |
len = sizeof(my_addr); |
1403 | 1403 |
getsockname(c->fd, (struct sockaddr *)&my_addr, &len); |
... | ... |
@@ -1428,7 +1428,7 @@ static int http_parse_request(HTTPContext *c) |
1428 | 1428 |
} |
1429 | 1429 |
} |
1430 | 1430 |
|
1431 |
- sprintf(msg, "ASX/RAM file not handled"); |
|
1431 |
+ snprintf(msg, sizeof(msg), "ASX/RAM file not handled"); |
|
1432 | 1432 |
goto send_error; |
1433 | 1433 |
} |
1434 | 1434 |
|
... | ... |
@@ -1493,12 +1493,12 @@ static int http_parse_request(HTTPContext *c) |
1493 | 1493 |
} |
1494 | 1494 |
} |
1495 | 1495 |
|
1496 |
- sprintf(msg, "POST command not handled"); |
|
1496 |
+ snprintf(msg, sizeof(msg), "POST command not handled"); |
|
1497 | 1497 |
c->stream = 0; |
1498 | 1498 |
goto send_error; |
1499 | 1499 |
} |
1500 | 1500 |
if (http_start_receive_data(c) < 0) { |
1501 |
- sprintf(msg, "could not open feed"); |
|
1501 |
+ snprintf(msg, sizeof(msg), "could not open feed"); |
|
1502 | 1502 |
goto send_error; |
1503 | 1503 |
} |
1504 | 1504 |
c->http_error = 0; |
... | ... |
@@ -1517,17 +1517,17 @@ static int http_parse_request(HTTPContext *c) |
1517 | 1517 |
|
1518 | 1518 |
/* open input stream */ |
1519 | 1519 |
if (open_input_stream(c, info) < 0) { |
1520 |
- sprintf(msg, "Input stream corresponding to '%s' not found", url); |
|
1520 |
+ snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url); |
|
1521 | 1521 |
goto send_error; |
1522 | 1522 |
} |
1523 | 1523 |
|
1524 | 1524 |
/* prepare http header */ |
1525 | 1525 |
q = c->buffer; |
1526 |
- q += sprintf(q, "HTTP/1.0 200 OK\r\n"); |
|
1526 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n"); |
|
1527 | 1527 |
mime_type = c->stream->fmt->mime_type; |
1528 | 1528 |
if (!mime_type) |
1529 | 1529 |
mime_type = "application/x-octet_stream"; |
1530 |
- q += sprintf(q, "Pragma: no-cache\r\n"); |
|
1530 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n"); |
|
1531 | 1531 |
|
1532 | 1532 |
/* for asf, we need extra headers */ |
1533 | 1533 |
if (!strcmp(c->stream->fmt->name,"asf_stream")) { |
... | ... |
@@ -1535,10 +1535,10 @@ static int http_parse_request(HTTPContext *c) |
1535 | 1535 |
|
1536 | 1536 |
c->wmp_client_id = random() & 0x7fffffff; |
1537 | 1537 |
|
1538 |
- q += sprintf(q, "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); |
|
1538 |
+ 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); |
|
1539 | 1539 |
} |
1540 |
- q += sprintf(q, "Content-Type: %s\r\n", mime_type); |
|
1541 |
- q += sprintf(q, "\r\n"); |
|
1540 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type); |
|
1541 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1542 | 1542 |
|
1543 | 1543 |
/* prepare output buffer */ |
1544 | 1544 |
c->http_error = 0; |
... | ... |
@@ -1549,13 +1549,13 @@ static int http_parse_request(HTTPContext *c) |
1549 | 1549 |
send_error: |
1550 | 1550 |
c->http_error = 404; |
1551 | 1551 |
q = c->buffer; |
1552 |
- q += sprintf(q, "HTTP/1.0 404 Not Found\r\n"); |
|
1553 |
- q += sprintf(q, "Content-type: %s\r\n", "text/html"); |
|
1554 |
- q += sprintf(q, "\r\n"); |
|
1555 |
- q += sprintf(q, "<HTML>\n"); |
|
1556 |
- q += sprintf(q, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"); |
|
1557 |
- q += sprintf(q, "<BODY>%s</BODY>\n", msg); |
|
1558 |
- q += sprintf(q, "</HTML>\n"); |
|
1552 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n"); |
|
1553 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html"); |
|
1554 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n"); |
|
1555 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n"); |
|
1556 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"); |
|
1557 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg); |
|
1558 |
+ q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</HTML>\n"); |
|
1559 | 1559 |
|
1560 | 1560 |
/* prepare output buffer */ |
1561 | 1561 |
c->buffer_ptr = c->buffer; |
... | ... |
@@ -1753,7 +1753,7 @@ static void compute_stats(HTTPContext *c) |
1753 | 1753 |
break; |
1754 | 1754 |
case CODEC_TYPE_VIDEO: |
1755 | 1755 |
type = "video"; |
1756 |
- sprintf(parameters, "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height, |
|
1756 |
+ snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height, |
|
1757 | 1757 |
st->codec.qmin, st->codec.qmax, st->codec.frame_rate / st->codec.frame_rate_base); |
1758 | 1758 |
break; |
1759 | 1759 |
default: |
... | ... |
@@ -2382,6 +2382,14 @@ static int http_receive_data(HTTPContext *c) |
2382 | 2382 |
} |
2383 | 2383 |
} |
2384 | 2384 |
|
2385 |
+ if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) { |
|
2386 |
+ if (c->buffer[0] != 'f' || |
|
2387 |
+ c->buffer[1] != 'm') { |
|
2388 |
+ http_log("Feed stream has become desynchronized -- disconnecting\n"); |
|
2389 |
+ goto fail; |
|
2390 |
+ } |
|
2391 |
+ } |
|
2392 |
+ |
|
2385 | 2393 |
if (c->buffer_ptr >= c->buffer_end) { |
2386 | 2394 |
FFStream *feed = c->stream; |
2387 | 2395 |
/* a packet has been received : write it in the store, except |
... | ... |
@@ -3210,6 +3218,7 @@ static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec) |
3210 | 3210 |
fst->priv_data = av_mallocz(sizeof(FeedData)); |
3211 | 3211 |
memcpy(&fst->codec, codec, sizeof(AVCodecContext)); |
3212 | 3212 |
fst->codec.coded_frame = &dummy_frame; |
3213 |
+ fst->index = stream->nb_streams; |
|
3213 | 3214 |
stream->streams[stream->nb_streams++] = fst; |
3214 | 3215 |
return fst; |
3215 | 3216 |
} |
... | ... |
@@ -3289,7 +3298,7 @@ static void extract_mpeg4_header(AVFormatContext *infile) |
3289 | 3289 |
if (!mpeg4_count) |
3290 | 3290 |
return; |
3291 | 3291 |
|
3292 |
- printf("MPEG4 without extra data: trying to find header\n"); |
|
3292 |
+ printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename); |
|
3293 | 3293 |
while (mpeg4_count > 0) { |
3294 | 3294 |
if (av_read_packet(infile, &pkt) < 0) |
3295 | 3295 |
break; |