Browse code

ffserver: Remove use of AVStream as a intermediate to store parameters

Reviewed-by: "Reynaldo H. Verdejo Pinochet" <reynaldo@osg.samsung.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

Michael Niedermayer authored on 2016/11/28 01:42:50
Showing 3 changed files
... ...
@@ -235,7 +235,7 @@ static int rtp_new_av_stream(HTTPContext *c,
235 235
 /* utils */
236 236
 static size_t htmlencode (const char *src, char **dest);
237 237
 static inline void cp_html_entity (char *buffer, const char *entity);
238
-static inline int check_codec_match(AVStream *ccf, AVStream *ccs, int stream);
238
+static inline int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream);
239 239
 
240 240
 static const char *my_program_name;
241 241
 
... ...
@@ -254,6 +254,21 @@ static AVLFG random_state;
254 254
 
255 255
 static FILE *logfile = NULL;
256 256
 
257
+static void unlayer_stream(AVStream *st, LayeredAVStream *lst)
258
+{
259
+    avcodec_free_context(&st->codec);
260
+    avcodec_parameters_free(&st->codecpar);
261
+#define COPY(a) st->a = lst->a;
262
+    COPY(index)
263
+    COPY(id)
264
+    COPY(codec)
265
+    COPY(codecpar)
266
+    COPY(time_base)
267
+    COPY(pts_wrap_bits)
268
+    COPY(sample_aspect_ratio)
269
+    COPY(recommended_encoder_configuration)
270
+}
271
+
257 272
 static inline void cp_html_entity (char *buffer, const char *entity) {
258 273
     if (!buffer || !entity)
259 274
         return;
... ...
@@ -1864,7 +1879,7 @@ static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream)
1864 1864
     int i, stream_no;
1865 1865
     const char *type = "unknown";
1866 1866
     char parameters[64];
1867
-    AVStream *st;
1867
+    LayeredAVStream *st;
1868 1868
     AVCodec *codec;
1869 1869
 
1870 1870
     stream_no = stream->nb_streams;
... ...
@@ -1984,7 +1999,7 @@ static void compute_status(HTTPContext *c)
1984 1984
             const char *video_codec_name_extra = "";
1985 1985
 
1986 1986
             for(i=0;i<stream->nb_streams;i++) {
1987
-                AVStream *st = stream->streams[i];
1987
+                LayeredAVStream *st = stream->streams[i];
1988 1988
                 AVCodec *codec = avcodec_find_encoder(st->codecpar->codec_id);
1989 1989
 
1990 1990
                 switch(st->codecpar->codec_type) {
... ...
@@ -2256,14 +2271,12 @@ static int http_prepare_data(HTTPContext *c)
2256 2256
             return AVERROR(ENOMEM);
2257 2257
         c->pfmt_ctx = ctx;
2258 2258
         av_dict_copy(&(c->pfmt_ctx->metadata), c->stream->metadata, 0);
2259
-        c->pfmt_ctx->streams = av_mallocz_array(c->stream->nb_streams,
2260
-                                              sizeof(AVStream *));
2261
-        if (!c->pfmt_ctx->streams)
2262
-            return AVERROR(ENOMEM);
2263 2259
 
2264 2260
         for(i=0;i<c->stream->nb_streams;i++) {
2265
-            AVStream *src;
2266
-            c->pfmt_ctx->streams[i] = av_mallocz(sizeof(AVStream));
2261
+            LayeredAVStream *src;
2262
+            AVStream *st = avformat_new_stream(c->pfmt_ctx, NULL);
2263
+            if (!st)
2264
+                return AVERROR(ENOMEM);
2267 2265
 
2268 2266
             /* if file or feed, then just take streams from FFServerStream
2269 2267
              * struct */
... ...
@@ -2273,14 +2286,14 @@ static int http_prepare_data(HTTPContext *c)
2273 2273
             else
2274 2274
                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2275 2275
 
2276
-            *(c->pfmt_ctx->streams[i]) = *src;
2277
-            c->pfmt_ctx->streams[i]->priv_data = 0;
2276
+            unlayer_stream(c->pfmt_ctx->streams[i], src); //TODO we no longer copy st->internal, does this matter?
2277
+            av_assert0(!c->pfmt_ctx->streams[i]->priv_data);
2278 2278
             /* XXX: should be done in AVStream, not in codec */
2279 2279
             c->pfmt_ctx->streams[i]->codec->frame_number = 0;
2280 2280
         }
2281 2281
         /* set output format parameters */
2282 2282
         c->pfmt_ctx->oformat = c->stream->fmt;
2283
-        c->pfmt_ctx->nb_streams = c->stream->nb_streams;
2283
+        av_assert0(c->pfmt_ctx->nb_streams == c->stream->nb_streams);
2284 2284
 
2285 2285
         c->got_key_frame = 0;
2286 2286
 
... ...
@@ -2807,7 +2820,7 @@ static int http_receive_data(HTTPContext *c)
2807 2807
             }
2808 2808
 
2809 2809
             for (i = 0; i < s->nb_streams; i++) {
2810
-                AVStream *fst = feed->streams[i];
2810
+                LayeredAVStream *fst = feed->streams[i];
2811 2811
                 AVStream *st = s->streams[i];
2812 2812
                 avcodec_copy_context(fst->codec, st->codec);
2813 2813
             }
... ...
@@ -3424,19 +3437,16 @@ static int rtp_new_av_stream(HTTPContext *c,
3424 3424
     if (!st)
3425 3425
         goto fail;
3426 3426
 
3427
-    av_freep(&st->codec);
3428
-    av_freep(&st->info);
3429 3427
     st_internal = st->internal;
3430 3428
 
3431 3429
     if (!c->stream->feed ||
3432 3430
         c->stream->feed == c->stream)
3433
-        memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3431
+        unlayer_stream(st, c->stream->streams[stream_index]);
3434 3432
     else
3435
-        memcpy(st,
3436
-               c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3437
-               sizeof(AVStream));
3438
-    st->priv_data = NULL;
3439
-    st->internal = st_internal;
3433
+        unlayer_stream(st,
3434
+               c->stream->feed->streams[c->stream->feed_streams[stream_index]]);
3435
+    av_assert0(st->priv_data == NULL);
3436
+    av_assert0(st->internal == st_internal);
3440 3437
 
3441 3438
     /* build destination RTP address */
3442 3439
     ipaddr = inet_ntoa(dest_addr->sin_addr);
... ...
@@ -3504,15 +3514,15 @@ static int rtp_new_av_stream(HTTPContext *c,
3504 3504
 /* ffserver initialization */
3505 3505
 
3506 3506
 /* FIXME: This code should use avformat_new_stream() */
3507
-static AVStream *add_av_stream1(FFServerStream *stream,
3507
+static LayeredAVStream *add_av_stream1(FFServerStream *stream,
3508 3508
                                 AVCodecContext *codec, int copy)
3509 3509
 {
3510
-    AVStream *fst;
3510
+    LayeredAVStream *fst;
3511 3511
 
3512 3512
     if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3513 3513
         return NULL;
3514 3514
 
3515
-    fst = av_mallocz(sizeof(AVStream));
3515
+    fst = av_mallocz(sizeof(*fst));
3516 3516
     if (!fst)
3517 3517
         return NULL;
3518 3518
     if (copy) {
... ...
@@ -3528,20 +3538,20 @@ static AVStream *add_av_stream1(FFServerStream *stream,
3528 3528
          */
3529 3529
         fst->codec = codec;
3530 3530
 
3531
-    fst->internal = av_mallocz(sizeof(*fst->internal));
3532
-    fst->internal->avctx = avcodec_alloc_context3(NULL);
3531
+    //NOTE we previously allocated internal & internal->avctx, these seemed uneeded though
3533 3532
     fst->codecpar = avcodec_parameters_alloc();
3534 3533
     fst->index = stream->nb_streams;
3535
-    avpriv_set_pts_info(fst, 33, 1, 90000);
3534
+    fst->time_base = (AVRational) {1, 90000};
3535
+    fst->pts_wrap_bits = 33;
3536 3536
     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3537 3537
     stream->streams[stream->nb_streams++] = fst;
3538 3538
     return fst;
3539 3539
 }
3540 3540
 
3541 3541
 /* return the stream number in the feed */
3542
-static int add_av_stream(FFServerStream *feed, AVStream *st)
3542
+static int add_av_stream(FFServerStream *feed, LayeredAVStream *st)
3543 3543
 {
3544
-    AVStream *fst;
3544
+    LayeredAVStream *fst;
3545 3545
     AVCodecContext *av, *av1;
3546 3546
     int i;
3547 3547
 
... ...
@@ -3575,9 +3585,9 @@ static int add_av_stream(FFServerStream *feed, AVStream *st)
3575 3575
     fst = add_av_stream1(feed, av, 0);
3576 3576
     if (!fst)
3577 3577
         return -1;
3578
-    if (av_stream_get_recommended_encoder_configuration(st))
3579
-        av_stream_set_recommended_encoder_configuration(fst,
3580
-            av_strdup(av_stream_get_recommended_encoder_configuration(st)));
3578
+    if (st->recommended_encoder_configuration)
3579
+        fst->recommended_encoder_configuration =
3580
+            av_strdup(st->recommended_encoder_configuration);
3581 3581
     return feed->nb_streams - 1;
3582 3582
 }
3583 3583
 
... ...
@@ -3653,7 +3663,7 @@ static void build_file_streams(void)
3653 3653
 }
3654 3654
 
3655 3655
 static inline
3656
-int check_codec_match(AVStream *ccf, AVStream *ccs, int stream)
3656
+int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream)
3657 3657
 {
3658 3658
     int matches = 1;
3659 3659
 
... ...
@@ -3741,7 +3751,8 @@ static int build_feed_streams(void)
3741 3741
 
3742 3742
             matches = 1;
3743 3743
             for(i=0;i<s->nb_streams;i++) {
3744
-                AVStream *sf, *ss;
3744
+                AVStream *ss;
3745
+                LayeredAVStream *sf;
3745 3746
 
3746 3747
                 sf = feed->streams[i];
3747 3748
                 ss = s->streams[i];
... ...
@@ -3796,8 +3807,14 @@ drop:
3796 3796
                 goto bail;
3797 3797
             }
3798 3798
             s->oformat = feed->fmt;
3799
-            s->nb_streams = feed->nb_streams;
3800
-            s->streams = feed->streams;
3799
+            for (i = 0; i<feed->nb_streams; i++) {
3800
+                AVStream *st = avformat_new_stream(s, NULL); // FIXME free this
3801
+                if (!st) {
3802
+                    http_log("Failed to allocate stream\n");
3803
+                    goto bail;
3804
+                }
3805
+                unlayer_stream(st, feed->streams[i]);
3806
+            }
3801 3807
             if (avformat_write_header(s, NULL) < 0) {
3802 3808
                 http_log("Container doesn't support the required parameters\n");
3803 3809
                 avio_closep(&s->pb);
... ...
@@ -3847,7 +3864,7 @@ static void compute_bandwidth(void)
3847 3847
     for(stream = config.first_stream; stream; stream = stream->next) {
3848 3848
         bandwidth = 0;
3849 3849
         for(i=0;i<stream->nb_streams;i++) {
3850
-            AVStream *st = stream->streams[i];
3850
+            LayeredAVStream *st = stream->streams[i];
3851 3851
             switch(st->codec->codec_type) {
3852 3852
             case AVMEDIA_TYPE_AUDIO:
3853 3853
             case AVMEDIA_TYPE_VIDEO:
... ...
@@ -182,7 +182,7 @@ bail:
182 182
 static void add_codec(FFServerStream *stream, AVCodecContext *av,
183 183
                       FFServerConfig *config)
184 184
 {
185
-    AVStream *st;
185
+    LayeredAVStream *st;
186 186
     AVDictionary **opts, *recommended = NULL;
187 187
     char *enc_config;
188 188
 
... ...
@@ -313,12 +313,12 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av,
313 313
     }
314 314
 
315 315
 done:
316
-    st = av_mallocz(sizeof(AVStream));
316
+    st = av_mallocz(sizeof(*st));
317 317
     if (!st)
318 318
         return;
319 319
     av_dict_get_string(recommended, &enc_config, '=', ',');
320 320
     av_dict_free(&recommended);
321
-    av_stream_set_recommended_encoder_configuration(st, enc_config);
321
+    st->recommended_encoder_configuration = enc_config;
322 322
     st->codec = av;
323 323
     stream->streams[stream->nb_streams++] = st;
324 324
 }
... ...
@@ -49,6 +49,24 @@ typedef struct FFServerIPAddressACL {
49 49
     struct in_addr last;
50 50
 } FFServerIPAddressACL;
51 51
 
52
+/**
53
+ * This holds the stream parameters for an AVStream, it cannot be a AVStream
54
+ * because AVStreams cannot be instanciated without a AVFormatContext, especially
55
+ * not outside libavformat.
56
+ *
57
+ * The fields of this struct have the same semantics as the fields of an AVStream.
58
+ */
59
+typedef struct LayeredAVStream {
60
+    int index;
61
+    int id;
62
+    AVCodecParameters *codecpar;
63
+    AVCodecContext *codec;
64
+    AVRational time_base;
65
+    int pts_wrap_bits;
66
+    AVRational sample_aspect_ratio;
67
+    char *recommended_encoder_configuration;
68
+} LayeredAVStream;
69
+
52 70
 /* description of each stream of the ffserver.conf file */
53 71
 typedef struct FFServerStream {
54 72
     enum FFServerStreamType stream_type;
... ...
@@ -64,7 +82,7 @@ typedef struct FFServerStream {
64 64
     int prebuffer;                /* Number of milliseconds early to start */
65 65
     int64_t max_time;             /* Number of milliseconds to run */
66 66
     int send_on_key;
67
-    AVStream *streams[FFSERVER_MAX_STREAMS];
67
+    LayeredAVStream *streams[FFSERVER_MAX_STREAMS];
68 68
     int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
69 69
     char feed_filename[1024];     /* file name of the feed storage, or
70 70
                                      input file name for a stream */