mirror of https://git.ffmpeg.org/ffmpeg.git
* Add support for time-limiting a live stream. (Some guy streamed one of
my pondcam streams for 24 hours! I'll bet he wasn't watching. * Add code to allocate the priv_data so that the ffm header can be parsed again. [Fix crash] Originally committed as revision 577 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
935cdf0902
commit
ec3b22326d
34
ffserver.c
34
ffserver.c
|
@ -95,6 +95,7 @@ typedef struct HTTPContext {
|
||||||
int last_packet_sent; /* true if last data packet was sent */
|
int last_packet_sent; /* true if last data packet was sent */
|
||||||
int suppress_log;
|
int suppress_log;
|
||||||
int bandwidth;
|
int bandwidth;
|
||||||
|
time_t start_time;
|
||||||
char protocol[16];
|
char protocol[16];
|
||||||
char method[16];
|
char method[16];
|
||||||
char url[128];
|
char url[128];
|
||||||
|
@ -116,6 +117,7 @@ typedef struct FFStream {
|
||||||
AVOutputFormat *fmt;
|
AVOutputFormat *fmt;
|
||||||
int nb_streams;
|
int nb_streams;
|
||||||
int prebuffer; /* Number of millseconds early to start */
|
int prebuffer; /* Number of millseconds early to start */
|
||||||
|
time_t max_time;
|
||||||
int send_on_key;
|
int send_on_key;
|
||||||
AVStream *streams[MAX_STREAMS];
|
AVStream *streams[MAX_STREAMS];
|
||||||
int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
|
int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
|
||||||
|
@ -559,7 +561,7 @@ static int http_parse_request(HTTPContext *c)
|
||||||
c->bandwidth += st->codec.bit_rate;
|
c->bandwidth += st->codec.bit_rate;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
av_abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,7 +638,7 @@ static int http_parse_request(HTTPContext *c)
|
||||||
q += sprintf(q, "http://%s/%s%s\r\n",
|
q += sprintf(q, "http://%s/%s%s\r\n",
|
||||||
hostbuf, filename, info);
|
hostbuf, filename, info);
|
||||||
} else
|
} else
|
||||||
abort();
|
av_abort();
|
||||||
|
|
||||||
/* prepare output buffer */
|
/* prepare output buffer */
|
||||||
c->buffer_ptr = c->buffer;
|
c->buffer_ptr = c->buffer;
|
||||||
|
@ -829,7 +831,7 @@ static void compute_stats(HTTPContext *c)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
av_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",
|
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",
|
||||||
|
@ -873,7 +875,7 @@ static void compute_stats(HTTPContext *c)
|
||||||
type = "video";
|
type = "video";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
av_abort();
|
||||||
}
|
}
|
||||||
q += sprintf(q, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s\n",
|
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 : "");
|
i, type, st->codec.bit_rate/1000, codec ? codec->name : "");
|
||||||
|
@ -960,7 +962,7 @@ static void http_write_packet(void *opaque,
|
||||||
c->buffer_ptr = c->buffer_end = c->buffer;
|
c->buffer_ptr = c->buffer_end = c->buffer;
|
||||||
|
|
||||||
if (c->buffer_end - c->buffer + size > IOBUFFER_MAX_SIZE)
|
if (c->buffer_end - c->buffer + size > IOBUFFER_MAX_SIZE)
|
||||||
abort();
|
av_abort();
|
||||||
|
|
||||||
memcpy(c->buffer_end, buf, size);
|
memcpy(c->buffer_end, buf, size);
|
||||||
c->buffer_end += size;
|
c->buffer_end += size;
|
||||||
|
@ -1128,7 +1130,11 @@ static int http_prepare_data(HTTPContext *c)
|
||||||
c->stream->feed->feed_size);
|
c->stream->feed->feed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av_read_packet(c->fmt_in, &pkt) < 0) {
|
if (c->stream->max_time &&
|
||||||
|
c->stream->max_time + c->start_time > time(0)) {
|
||||||
|
/* We have timed out */
|
||||||
|
c->state = HTTPSTATE_SEND_DATA_TRAILER;
|
||||||
|
} else if (av_read_packet(c->fmt_in, &pkt) < 0) {
|
||||||
if (c->stream->feed && c->stream->feed->feed_opened) {
|
if (c->stream->feed && c->stream->feed->feed_opened) {
|
||||||
/* if coming from feed, it means we reached the end of the
|
/* if coming from feed, it means we reached the end of the
|
||||||
ffm file, so must wait for more data */
|
ffm file, so must wait for more data */
|
||||||
|
@ -1326,18 +1332,25 @@ static int http_receive_data(HTTPContext *c)
|
||||||
if (!fmt_in)
|
if (!fmt_in)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
s.priv_data = av_mallocz(fmt_in->priv_data_size);
|
||||||
|
if (!s.priv_data)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (fmt_in->read_header(&s, 0) < 0) {
|
if (fmt_in->read_header(&s, 0) < 0) {
|
||||||
|
av_freep(&s.priv_data);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we have the actual streams */
|
/* Now we have the actual streams */
|
||||||
if (s.nb_streams != feed->nb_streams) {
|
if (s.nb_streams != feed->nb_streams) {
|
||||||
|
av_freep(&s.priv_data);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
for (i = 0; i < s.nb_streams; i++) {
|
for (i = 0; i < s.nb_streams; i++) {
|
||||||
memcpy(&feed->streams[i]->codec,
|
memcpy(&feed->streams[i]->codec,
|
||||||
&s.streams[i]->codec, sizeof(AVCodecContext));
|
&s.streams[i]->codec, sizeof(AVCodecContext));
|
||||||
}
|
}
|
||||||
|
av_freep(&s.priv_data);
|
||||||
}
|
}
|
||||||
c->buffer_ptr = c->buffer;
|
c->buffer_ptr = c->buffer;
|
||||||
}
|
}
|
||||||
|
@ -1379,7 +1392,7 @@ int add_av_stream(FFStream *feed,
|
||||||
goto found;
|
goto found;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
av_abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1530,7 +1543,7 @@ void add_codec(FFStream *stream, AVCodecContext *av)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
av_abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
st = av_mallocz(sizeof(AVStream));
|
st = av_mallocz(sizeof(AVStream));
|
||||||
|
@ -1807,6 +1820,11 @@ int parse_ffconfig(const char *filename)
|
||||||
filename, line_num, arg);
|
filename, line_num, arg);
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(cmd, "MaxTime")) {
|
||||||
|
get_arg(arg, sizeof(arg), &p);
|
||||||
|
if (stream) {
|
||||||
|
stream->max_time = atoi(arg);
|
||||||
|
}
|
||||||
} else if (!strcasecmp(cmd, "AudioBitRate")) {
|
} else if (!strcasecmp(cmd, "AudioBitRate")) {
|
||||||
get_arg(arg, sizeof(arg), &p);
|
get_arg(arg, sizeof(arg), &p);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
|
|
Loading…
Reference in New Issue