From patchwork Sun Nov 27 18:06:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Niedermayer X-Patchwork-Id: 1576 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.90.1 with SMTP id o1csp1416072vsb; Sun, 27 Nov 2016 10:06:39 -0800 (PST) X-Received: by 10.28.98.66 with SMTP id w63mr17168916wmb.142.1480269999551; Sun, 27 Nov 2016 10:06:39 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id h17si51433989wjq.274.2016.11.27.10.06.39; Sun, 27 Nov 2016 10:06:39 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C2128689DB2; Sun, 27 Nov 2016 20:06:24 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from vie01a-dmta-pe04-1.mx.upcmail.net (vie01a-dmta-pe04-1.mx.upcmail.net [62.179.121.163]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 74E896897C8 for ; Sun, 27 Nov 2016 20:06:18 +0200 (EET) Received: from [172.31.216.43] (helo=vie01a-pemc-psmtp-pe01) by vie01a-dmta-pe04.mx.upcmail.net with esmtp (Exim 4.87) (envelope-from ) id 1cB3qJ-0002o4-Ic for ffmpeg-devel@ffmpeg.org; Sun, 27 Nov 2016 19:06:23 +0100 Received: from localhost ([213.47.41.20]) by vie01a-pemc-psmtp-pe01 with SMTP @ mailcloud.upcmail.net id D66N1u00m0S5wYM0166PmR; Sun, 27 Nov 2016 19:06:23 +0100 X-SourceIP: 213.47.41.20 From: Michael Niedermayer To: FFmpeg development discussions and patches Date: Sun, 27 Nov 2016 19:06:19 +0100 Message-Id: <20161127180620.18419-2-michael@niedermayer.cc> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161127180620.18419-1-michael@niedermayer.cc> References: <20161127180620.18419-1-michael@niedermayer.cc> Subject: [FFmpeg-devel] [PATCH 2/3] ffserver: Remove use of AVStream as a intermediate to store parameters X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Reynaldo Verdejo MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Michael Niedermayer --- ffserver.c | 91 +++++++++++++++++++++++++++++++++---------------------- ffserver_config.c | 6 ++-- ffserver_config.h | 20 +++++++++++- 3 files changed, 76 insertions(+), 41 deletions(-) diff --git a/ffserver.c b/ffserver.c index 6b8eb2c..1d8abd9 100644 --- a/ffserver.c +++ b/ffserver.c @@ -235,7 +235,7 @@ static int rtp_new_av_stream(HTTPContext *c, /* utils */ static size_t htmlencode (const char *src, char **dest); static inline void cp_html_entity (char *buffer, const char *entity); -static inline int check_codec_match(AVStream *ccf, AVStream *ccs, int stream); +static inline int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream); static const char *my_program_name; @@ -254,6 +254,21 @@ static AVLFG random_state; static FILE *logfile = NULL; +static void unlayer_stream(AVStream *st, LayeredAVStream *lst) +{ + avcodec_free_context(&st->codec); + avcodec_parameters_free(&st->codecpar); +#define COPY(a) st->a = lst->a; + COPY(index) + COPY(id) + COPY(codec) + COPY(codecpar) + COPY(time_base) + COPY(pts_wrap_bits) + COPY(sample_aspect_ratio) + COPY(recommended_encoder_configuration) +} + static inline void cp_html_entity (char *buffer, const char *entity) { if (!buffer || !entity) return; @@ -1864,7 +1879,7 @@ static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream) int i, stream_no; const char *type = "unknown"; char parameters[64]; - AVStream *st; + LayeredAVStream *st; AVCodec *codec; stream_no = stream->nb_streams; @@ -1984,7 +1999,7 @@ static void compute_status(HTTPContext *c) const char *video_codec_name_extra = ""; for(i=0;inb_streams;i++) { - AVStream *st = stream->streams[i]; + LayeredAVStream *st = stream->streams[i]; AVCodec *codec = avcodec_find_encoder(st->codecpar->codec_id); switch(st->codecpar->codec_type) { @@ -2256,14 +2271,12 @@ static int http_prepare_data(HTTPContext *c) return AVERROR(ENOMEM); c->pfmt_ctx = ctx; av_dict_copy(&(c->pfmt_ctx->metadata), c->stream->metadata, 0); - c->pfmt_ctx->streams = av_mallocz_array(c->stream->nb_streams, - sizeof(AVStream *)); - if (!c->pfmt_ctx->streams) - return AVERROR(ENOMEM); for(i=0;istream->nb_streams;i++) { - AVStream *src; - c->pfmt_ctx->streams[i] = av_mallocz(sizeof(AVStream)); + LayeredAVStream *src; + AVStream *st = avformat_new_stream(c->pfmt_ctx, NULL); + if (!st) + return AVERROR(ENOMEM); /* if file or feed, then just take streams from FFServerStream * struct */ @@ -2273,14 +2286,14 @@ static int http_prepare_data(HTTPContext *c) else src = c->stream->feed->streams[c->stream->feed_streams[i]]; - *(c->pfmt_ctx->streams[i]) = *src; - c->pfmt_ctx->streams[i]->priv_data = 0; + unlayer_stream(c->pfmt_ctx->streams[i], src); //TODO we no longer copy st->internal, does this matter? + av_assert0(!c->pfmt_ctx->streams[i]->priv_data); /* XXX: should be done in AVStream, not in codec */ c->pfmt_ctx->streams[i]->codec->frame_number = 0; } /* set output format parameters */ c->pfmt_ctx->oformat = c->stream->fmt; - c->pfmt_ctx->nb_streams = c->stream->nb_streams; + av_assert0(c->pfmt_ctx->nb_streams == c->stream->nb_streams); c->got_key_frame = 0; @@ -2807,7 +2820,7 @@ static int http_receive_data(HTTPContext *c) } for (i = 0; i < s->nb_streams; i++) { - AVStream *fst = feed->streams[i]; + LayeredAVStream *fst = feed->streams[i]; AVStream *st = s->streams[i]; avcodec_copy_context(fst->codec, st->codec); } @@ -3424,19 +3437,16 @@ static int rtp_new_av_stream(HTTPContext *c, if (!st) goto fail; - av_freep(&st->codec); - av_freep(&st->info); st_internal = st->internal; if (!c->stream->feed || c->stream->feed == c->stream) - memcpy(st, c->stream->streams[stream_index], sizeof(AVStream)); + unlayer_stream(st, c->stream->streams[stream_index]); else - memcpy(st, - c->stream->feed->streams[c->stream->feed_streams[stream_index]], - sizeof(AVStream)); - st->priv_data = NULL; - st->internal = st_internal; + unlayer_stream(st, + c->stream->feed->streams[c->stream->feed_streams[stream_index]]); + av_assert0(st->priv_data == NULL); + av_assert0(st->internal == st_internal); /* build destination RTP address */ ipaddr = inet_ntoa(dest_addr->sin_addr); @@ -3504,15 +3514,15 @@ static int rtp_new_av_stream(HTTPContext *c, /* ffserver initialization */ /* FIXME: This code should use avformat_new_stream() */ -static AVStream *add_av_stream1(FFServerStream *stream, +static LayeredAVStream *add_av_stream1(FFServerStream *stream, AVCodecContext *codec, int copy) { - AVStream *fst; + LayeredAVStream *fst; if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams)) return NULL; - fst = av_mallocz(sizeof(AVStream)); + fst = av_mallocz(sizeof(*fst)); if (!fst) return NULL; if (copy) { @@ -3528,20 +3538,20 @@ static AVStream *add_av_stream1(FFServerStream *stream, */ fst->codec = codec; - fst->internal = av_mallocz(sizeof(*fst->internal)); - fst->internal->avctx = avcodec_alloc_context3(NULL); + //NOTE we previously allocated internal & internal->avctx, these seemed uneeded though fst->codecpar = avcodec_parameters_alloc(); fst->index = stream->nb_streams; - avpriv_set_pts_info(fst, 33, 1, 90000); + fst->time_base = (AVRational) {1, 90000}; + fst->pts_wrap_bits = 33; fst->sample_aspect_ratio = codec->sample_aspect_ratio; stream->streams[stream->nb_streams++] = fst; return fst; } /* return the stream number in the feed */ -static int add_av_stream(FFServerStream *feed, AVStream *st) +static int add_av_stream(FFServerStream *feed, LayeredAVStream *st) { - AVStream *fst; + LayeredAVStream *fst; AVCodecContext *av, *av1; int i; @@ -3575,9 +3585,9 @@ static int add_av_stream(FFServerStream *feed, AVStream *st) fst = add_av_stream1(feed, av, 0); if (!fst) return -1; - if (av_stream_get_recommended_encoder_configuration(st)) - av_stream_set_recommended_encoder_configuration(fst, - av_strdup(av_stream_get_recommended_encoder_configuration(st))); + if (st->recommended_encoder_configuration) + fst->recommended_encoder_configuration = + av_strdup(st->recommended_encoder_configuration); return feed->nb_streams - 1; } @@ -3653,7 +3663,7 @@ static void build_file_streams(void) } static inline -int check_codec_match(AVStream *ccf, AVStream *ccs, int stream) +int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream) { int matches = 1; @@ -3741,7 +3751,8 @@ static int build_feed_streams(void) matches = 1; for(i=0;inb_streams;i++) { - AVStream *sf, *ss; + AVStream *ss; + LayeredAVStream *sf; sf = feed->streams[i]; ss = s->streams[i]; @@ -3796,8 +3807,14 @@ drop: goto bail; } s->oformat = feed->fmt; - s->nb_streams = feed->nb_streams; - s->streams = feed->streams; + for (i = 0; inb_streams; i++) { + AVStream *st = avformat_new_stream(s, NULL); // FIXME free this + if (!st) { + http_log("Failed to allocate stream\n"); + goto bail; + } + unlayer_stream(st, feed->streams[i]); + } if (avformat_write_header(s, NULL) < 0) { http_log("Container doesn't support the required parameters\n"); avio_closep(&s->pb); @@ -3847,7 +3864,7 @@ static void compute_bandwidth(void) for(stream = config.first_stream; stream; stream = stream->next) { bandwidth = 0; for(i=0;inb_streams;i++) { - AVStream *st = stream->streams[i]; + LayeredAVStream *st = stream->streams[i]; switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_VIDEO: diff --git a/ffserver_config.c b/ffserver_config.c index 99709b5..14c58ce 100644 --- a/ffserver_config.c +++ b/ffserver_config.c @@ -182,7 +182,7 @@ bail: static void add_codec(FFServerStream *stream, AVCodecContext *av, FFServerConfig *config) { - AVStream *st; + LayeredAVStream *st; AVDictionary **opts, *recommended = NULL; char *enc_config; @@ -313,12 +313,12 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av, } done: - st = av_mallocz(sizeof(AVStream)); + st = av_mallocz(sizeof(*st)); if (!st) return; av_dict_get_string(recommended, &enc_config, '=', ','); av_dict_free(&recommended); - av_stream_set_recommended_encoder_configuration(st, enc_config); + st->recommended_encoder_configuration = enc_config; st->codec = av; stream->streams[stream->nb_streams++] = st; } diff --git a/ffserver_config.h b/ffserver_config.h index 0bd4cfc..373767b 100644 --- a/ffserver_config.h +++ b/ffserver_config.h @@ -49,6 +49,24 @@ typedef struct FFServerIPAddressACL { struct in_addr last; } FFServerIPAddressACL; +/** + * This holds the stream parameters for an AVStream, it cannot be a AVStream + * because AVStreams cannot be instanciated without a AVFormatContext, especially + * not outside libavformat. + * + * The fields of this struct have the same semantics as the fields of an AVStream. + */ +typedef struct LayeredAVStream { + int index; + int id; + AVCodecParameters *codecpar; + AVCodecContext *codec; + AVRational time_base; + int pts_wrap_bits; + AVRational sample_aspect_ratio; + char *recommended_encoder_configuration; +} LayeredAVStream; + /* description of each stream of the ffserver.conf file */ typedef struct FFServerStream { enum FFServerStreamType stream_type; @@ -64,7 +82,7 @@ typedef struct FFServerStream { int prebuffer; /* Number of milliseconds early to start */ int64_t max_time; /* Number of milliseconds to run */ int send_on_key; - AVStream *streams[FFSERVER_MAX_STREAMS]; + LayeredAVStream *streams[FFSERVER_MAX_STREAMS]; int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */ char feed_filename[1024]; /* file name of the feed storage, or input file name for a stream */