[FFmpeg-devel] [PATCH 6/8] ffserver.c: Add config file reading
Michael Niedermayer
michael at niedermayer.cc
Sun May 20 23:13:35 EEST 2018
On Sun, May 20, 2018 at 08:54:02PM +0200, Stephan Holljes wrote:
> Signed-off-by: Stephan Holljes <klaxa1337 at googlemail.com>
> ---
> ffserver.c | 248 ++++++++++++++++++++++++++++++++++++++++++-------------------
> 1 file changed, 172 insertions(+), 76 deletions(-)
>
> diff --git a/ffserver.c b/ffserver.c
> index 44fc263..3d842d8 100644
> --- a/ffserver.c
> +++ b/ffserver.c
> @@ -38,6 +38,7 @@
> #include "segment.h"
> #include "publisher.h"
> #include "httpd.h"
> +#include "configreader.h"
>
> #define BUFFER_SECS 30
> #define LISTEN_TIMEOUT_MSEC 1000
> @@ -54,9 +55,11 @@ struct WriteInfo {
> };
>
> struct AcceptInfo {
> - struct PublisherContext *pub;
> + struct PublisherContext **pubs;
> struct HTTPDInterface *httpd;
> - AVFormatContext *ifmt_ctx;
> + AVFormatContext **ifmt_ctxs;
> + struct HTTPDConfig *config;
> + int nb_pub; /* number of publishers (streams) equal to number of ifmt_ctx */
> };
>
>
> @@ -287,52 +290,77 @@ void *accept_thread(void *arg)
> {
> struct AcceptInfo *info = (struct AcceptInfo*) arg;
> struct FFServerInfo *ffinfo = NULL;
> + struct PublisherContext *pub;
> char status[4096];
> + char *stream_name;
> struct HTTPClient *client = NULL;
> void *server = NULL;
> AVIOContext *client_ctx = NULL;
> AVFormatContext *ofmt_ctx = NULL;
> + AVFormatContext *ifmt_ctx;
> unsigned char *avio_buffer;
> AVOutputFormat *ofmt;
> AVDictionary *mkvopts = NULL;
> AVStream *in_stream, *out_stream;
> int ret, i, reply_code;
> - struct HTTPDConfig config = {
> - .bind_address = "0",
> - .port = 8080,
> - .accept_timeout = LISTEN_TIMEOUT_MSEC,
> - };
> -
> - info->httpd->init(&server, config);
> -
> -
> + int shutdown;
> + struct HTTPDConfig *config = info->config;
> +
> + info->httpd->init(&server, *config);
> +
> for (;;) {
> - if (info->pub->shutdown)
> + shutdown = 1;
> + for (i = 0; i < config->nb_streams; i++) {
> + if (info->pubs[i] && !info->pubs[i]->shutdown)
> + shutdown = 0;
> + }
> + if (shutdown)
> break;
> - publisher_gen_status_json(info->pub, status);
> - av_log(server, AV_LOG_INFO, status);
> + for (i = 0; i < config->nb_streams; i++) {
> + publisher_gen_status_json(info->pubs[i], status);
> + av_log(server, AV_LOG_INFO, status);
> + }
> client = NULL;
> av_log(server, AV_LOG_DEBUG, "Accepting new clients.\n");
> reply_code = 200;
> - if (publisher_reserve_client(info->pub)) {
> - av_log(client, AV_LOG_WARNING, "No more client slots free, Returning 503.\n");
> - reply_code = 503;
> - }
> -
> +
> if ((ret = info->httpd->accept(server, &client, reply_code)) < 0) {
> if (ret == HTTPD_LISTEN_TIMEOUT) {
> - publisher_cancel_reserve(info->pub);
> continue;
> } else if (ret == HTTPD_CLIENT_ERROR) {
> info->httpd->close(server, client);
> }
> av_log(server, AV_LOG_WARNING, "Error during accept, retrying.\n");
> - publisher_cancel_reserve(info->pub);
> continue;
> }
> -
> +
> + pub = NULL;
> + ifmt_ctx = NULL;
> + for (i = 0; i < config->nb_streams; i++) {
> + stream_name = info->pubs[i]->stream_name;
> + // skip leading '/' ---v
> + if(!strncmp(client->resource + 1, stream_name, strlen(stream_name))) {
> + pub = info->pubs[i];
> + ifmt_ctx = info->ifmt_ctxs[i];
> + break;
> + }
> + }
> +
> + if (!pub || !ifmt_ctx) {
> + av_log(client_ctx, AV_LOG_WARNING, "No suitable publisher found for resource: %s.\n",
> + client->resource ? client->resource : "(null)");
> + reply_code = 404;
> + }
> +
> +
> + if (pub && ifmt_ctx && publisher_reserve_client(pub)) {
> + av_log(client_ctx, AV_LOG_WARNING, "No more client slots free, Returning 503.\n");
> + reply_code = 503;
> + }
> +
> if (reply_code != 200) {
> - publisher_cancel_reserve(info->pub);
> + if (pub && ifmt_ctx)
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> continue;
> }
> @@ -345,7 +373,7 @@ void *accept_thread(void *arg)
> client_ctx = avio_alloc_context(avio_buffer, AV_BUFSIZE, 1, ffinfo, NULL, &ffserver_write, NULL);
> if (!client_ctx) {
> av_log(client, AV_LOG_ERROR, "Could not allocate output format context.\n");
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> av_free(client_ctx->buffer);
> avio_context_free(&client_ctx);
> @@ -355,7 +383,7 @@ void *accept_thread(void *arg)
> avformat_alloc_output_context2(&ofmt_ctx, NULL, "matroska", NULL);
> if (!ofmt_ctx) {
> av_log(client, AV_LOG_ERROR, "Could not allocate output format context.\n");
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> avformat_free_context(ofmt_ctx);
> av_free(client_ctx->buffer);
> @@ -365,7 +393,7 @@ void *accept_thread(void *arg)
> }
> if ((ret = av_dict_set(&mkvopts, "live", "1", 0)) < 0) {
> av_log(client, AV_LOG_ERROR, "Failed to set live mode for matroska: %s\n", av_err2str(ret));
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> avformat_free_context(ofmt_ctx);
> av_free(client_ctx->buffer);
> @@ -377,13 +405,13 @@ void *accept_thread(void *arg)
> ofmt = ofmt_ctx->oformat;
> ofmt->flags |= AVFMT_NOFILE | AVFMT_FLAG_AUTO_BSF;
>
> - for (i = 0; i < info->ifmt_ctx->nb_streams; i++) {
> - in_stream = info->ifmt_ctx->streams[i];
> + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> + in_stream = ifmt_ctx->streams[i];
> out_stream = avformat_new_stream(ofmt_ctx, NULL);
>
> if (!out_stream) {
> av_log(client, AV_LOG_ERROR, "Could not allocate output stream.\n");
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> avformat_free_context(ofmt_ctx);
> av_free(client_ctx->buffer);
> @@ -395,7 +423,7 @@ void *accept_thread(void *arg)
> ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
> if (ret < 0) {
> av_log(client, AV_LOG_ERROR, "Failed to copy context from input to output stream codec context: %s.\n", av_err2str(ret));
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> avformat_free_context(ofmt_ctx);
> av_free(client_ctx->buffer);
> @@ -412,12 +440,12 @@ void *accept_thread(void *arg)
> }
> av_dict_copy(&out_stream->metadata, in_stream->metadata, 0);
> }
> - av_dict_copy(&info->ifmt_ctx->metadata, ofmt_ctx->metadata, 0);
> + av_dict_copy(&ifmt_ctx->metadata, ofmt_ctx->metadata, 0);
> ofmt_ctx->pb = client_ctx;
> ret = avformat_write_header(ofmt_ctx, &mkvopts);
> if (ret < 0) {
> av_log(client, AV_LOG_ERROR, "Could not write header to client: %s.\n", av_err2str(ret));
> - publisher_cancel_reserve(info->pub);
> + publisher_cancel_reserve(pub);
> info->httpd->close(server, client);
> avformat_free_context(ofmt_ctx);
> av_free(client_ctx->buffer);
> @@ -425,7 +453,7 @@ void *accept_thread(void *arg)
> av_free(ffinfo);
> continue;
> }
> - publisher_add_client(info->pub, ofmt_ctx, ffinfo);
> + publisher_add_client(pub, ofmt_ctx, ffinfo);
> ofmt_ctx = NULL;
>
> }
> @@ -467,59 +495,127 @@ void *write_thread(void *arg)
> return NULL;
> }
>
> -
> -int main(int argc, char *argv[])
> -{
> - struct ReadInfo rinfo;
> +void *run_server(void *arg) {
> struct AcceptInfo ainfo;
> - struct WriteInfo *winfos;
> - struct PublisherContext *pub;
> - int ret, i;
> - pthread_t r_thread, a_thread;
> - pthread_t *w_threads;
> + struct ReadInfo *rinfos;
> + struct WriteInfo **winfos_p;
> + struct HTTPDConfig *config = (struct HTTPDConfig*) arg;
> + struct PublisherContext **pubs;
> + AVFormatContext **ifmt_ctxs;
> + int ret, i, stream_index;
> + pthread_t *r_threads;
> + pthread_t **w_threads_p;
>
> - AVFormatContext *ifmt_ctx = NULL;
> -
> - rinfo.in_filename = "pipe:0";
> - if (argc > 1)
> - rinfo.in_filename = argv[1];
> + pubs = av_mallocz(config->nb_streams * sizeof(struct PublisherContext*));
> + ifmt_ctxs = av_mallocz(config->nb_streams * sizeof(AVFormatContext*));
av_mallocz_array
also missing alloc failure checks
[...]
> + w_threads_p[stream_index] = w_threads;
> + pthread_create(&r_thread, NULL, read_thread, &rinfos[stream_index]);
> + r_threads[stream_index] = r_thread;
missing failure check
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20180520/84c983e4/attachment.sig>
More information about the ffmpeg-devel
mailing list