]> git.sesse.net Git - ffmpeg/blobdiff - ffserver.c
fate/exr: add test for pxr24 with half and uint32 channel
[ffmpeg] / ffserver.c
index 18857cc389825c01b6abeb4bf11e4a442eb05794..3007e2d10603201622df8cbda5a1695db88a08c0 100644 (file)
@@ -44,6 +44,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/random_seed.h"
+#include "libavutil/rational.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
@@ -155,7 +156,7 @@ typedef struct HTTPContext {
     int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
     int switch_feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
     int switch_pending;
-    AVFormatContext fmt_ctx; /* instance of FFServerStream for one user */
+    AVFormatContext *pfmt_ctx; /* instance of FFServerStream for one user */
     int last_packet_sent; /* true if last data packet was sent */
     int suppress_log;
     DataRateData datarate;
@@ -239,8 +240,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(AVCodecContext *ccf, AVCodecContext *ccs,
-                                    int stream);
+static inline int check_codec_match(AVStream *ccf, AVStream *ccs, int stream);
 
 static const char *my_program_name;
 
@@ -930,21 +930,22 @@ static void close_connection(HTTPContext *c)
         ffurl_close(c->rtp_handles[i]);
     }
 
-    ctx = &c->fmt_ctx;
+    ctx = c->pfmt_ctx;
 
-    if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
-        /* prepare header */
-        if (ctx->oformat && avio_open_dyn_buf(&ctx->pb) >= 0) {
-            av_write_trailer(ctx);
-            av_freep(&c->pb_buffer);
-            avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
+    if (ctx) {
+        if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
+            /* prepare header */
+            if (ctx->oformat && avio_open_dyn_buf(&ctx->pb) >= 0) {
+                av_write_trailer(ctx);
+                av_freep(&c->pb_buffer);
+                avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
+            }
+        }
+        for(i=0; i<ctx->nb_streams; i++)
+            av_freep(&ctx->streams[i]);
+        av_freep(&ctx->streams);
+        av_freep(&ctx->priv_data);
         }
-    }
-
-    for(i=0; i<ctx->nb_streams; i++)
-        av_freep(&ctx->streams[i]);
-    av_freep(&ctx->streams);
-    av_freep(&ctx->priv_data);
 
     if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
         current_bandwidth -= c->stream->bandwidth;
@@ -1190,7 +1191,7 @@ static int extract_rates(char *rates, int ratelen, const char *request)
     return 0;
 }
 
-static int find_stream_in_feed(FFServerStream *feed, AVCodecContext *codec,
+static int find_stream_in_feed(FFServerStream *feed, AVCodecParameters *codec,
                                int bit_rate)
 {
     int i;
@@ -1198,7 +1199,7 @@ static int find_stream_in_feed(FFServerStream *feed, AVCodecContext *codec,
     int best = -1;
 
     for (i = 0; i < feed->nb_streams; i++) {
-        AVCodecContext *feed_codec = feed->streams[i]->codec;
+        AVCodecParameters *feed_codec = feed->streams[i]->codecpar;
 
         if (feed_codec->codec_id != codec->codec_id ||
             feed_codec->sample_rate != codec->sample_rate ||
@@ -1239,7 +1240,7 @@ static int modify_current_stream(HTTPContext *c, char *rates)
         return 0;
 
     for (i = 0; i < req->nb_streams; i++) {
-        AVCodecContext *codec = req->streams[i]->codec;
+        AVCodecParameters *codec = req->streams[i]->codecpar;
 
         switch(rates[i]) {
             case 0:
@@ -1273,6 +1274,8 @@ static void get_word(char *buf, int buf_size, const char **pp)
     const char *p;
     char *q;
 
+#define SPACE_CHARS " \t\r\n"
+
     p = *pp;
     p += strspn(p, SPACE_CHARS);
     q = buf;
@@ -1877,22 +1880,22 @@ static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream)
 
     for (i = 0; i < stream_no; i++) {
         st = stream->streams[i];
-        codec = avcodec_find_encoder(st->codec->codec_id);
+        codec = avcodec_find_encoder(st->codecpar->codec_id);
 
         parameters[0] = 0;
 
-        switch(st->codec->codec_type) {
+        switch(st->codecpar->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
             type = "audio";
             snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz",
-                     st->codec->channels, st->codec->sample_rate);
+                     st->codecpar->channels, st->codecpar->sample_rate);
             break;
         case AVMEDIA_TYPE_VIDEO:
             type = "video";
             snprintf(parameters, sizeof(parameters),
-                     "%dx%d, q=%d-%d, fps=%d", st->codec->width,
-                     st->codec->height, st->codec->qmin, st->codec->qmax,
-                     st->codec->time_base.den / st->codec->time_base.num);
+                     "%dx%d, q=%d-%d, fps=%d", st->codecpar->width,
+                     st->codecpar->height, st->codec->qmin, st->codec->qmax,
+                     st->time_base.den / st->time_base.num);
             break;
         default:
             abort();
@@ -1900,7 +1903,7 @@ static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream)
 
         avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%"PRId64
                         "<td>%s<td>%s\n",
-                    i, type, (int64_t)st->codec->bit_rate/1000,
+                    i, type, (int64_t)st->codecpar->bit_rate/1000,
                     codec ? codec->name : "", parameters);
      }
 
@@ -1987,11 +1990,11 @@ static void compute_status(HTTPContext *c)
 
             for(i=0;i<stream->nb_streams;i++) {
                 AVStream *st = stream->streams[i];
-                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
+                AVCodec *codec = avcodec_find_encoder(st->codecpar->codec_id);
 
-                switch(st->codec->codec_type) {
+                switch(st->codecpar->codec_type) {
                 case AVMEDIA_TYPE_AUDIO:
-                    audio_bit_rate += st->codec->bit_rate;
+                    audio_bit_rate += st->codecpar->bit_rate;
                     if (codec) {
                         if (*audio_codec_name)
                             audio_codec_name_extra = "...";
@@ -1999,7 +2002,7 @@ static void compute_status(HTTPContext *c)
                     }
                     break;
                 case AVMEDIA_TYPE_VIDEO:
-                    video_bit_rate += st->codec->bit_rate;
+                    video_bit_rate += st->codecpar->bit_rate;
                     if (codec) {
                         if (*video_codec_name)
                             video_codec_name_extra = "...";
@@ -2007,7 +2010,7 @@ static void compute_status(HTTPContext *c)
                     }
                     break;
                 case AVMEDIA_TYPE_DATA:
-                    video_bit_rate += st->codec->bit_rate;
+                    video_bit_rate += st->codecpar->bit_rate;
                     break;
                 default:
                     abort();
@@ -2104,9 +2107,9 @@ static void compute_status(HTTPContext *c)
         if (c1->stream) {
             for (j = 0; j < c1->stream->nb_streams; j++) {
                 if (!c1->stream->feed)
-                    bitrate += c1->stream->streams[j]->codec->bit_rate;
+                    bitrate += c1->stream->streams[j]->codecpar->bit_rate;
                 else if (c1->feed_streams[j] >= 0)
-                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
+                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codecpar->bit_rate;
             }
         }
 
@@ -2210,7 +2213,7 @@ static int open_input_stream(HTTPContext *c, const char *info)
     c->pts_stream_index = 0;
     for(i=0;i<c->stream->nb_streams;i++) {
         if (c->pts_stream_index == 0 &&
-            c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            c->stream->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             c->pts_stream_index = i;
         }
     }
@@ -2256,17 +2259,16 @@ static int http_prepare_data(HTTPContext *c)
         ctx = avformat_alloc_context();
         if (!ctx)
             return AVERROR(ENOMEM);
-        c->fmt_ctx = *ctx;
-        av_freep(&ctx);
-        av_dict_copy(&(c->fmt_ctx.metadata), c->stream->metadata, 0);
-        c->fmt_ctx.streams = av_mallocz_array(c->stream->nb_streams,
+        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->fmt_ctx.streams)
+        if (!c->pfmt_ctx->streams)
             return AVERROR(ENOMEM);
 
         for(i=0;i<c->stream->nb_streams;i++) {
             AVStream *src;
-            c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
+            c->pfmt_ctx->streams[i] = av_mallocz(sizeof(AVStream));
 
             /* if file or feed, then just take streams from FFServerStream
              * struct */
@@ -2276,39 +2278,39 @@ static int http_prepare_data(HTTPContext *c)
             else
                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
 
-            *(c->fmt_ctx.streams[i]) = *src;
-            c->fmt_ctx.streams[i]->priv_data = 0;
+            *(c->pfmt_ctx->streams[i]) = *src;
+            c->pfmt_ctx->streams[i]->priv_data = 0;
             /* XXX: should be done in AVStream, not in codec */
-            c->fmt_ctx.streams[i]->codec->frame_number = 0;
+            c->pfmt_ctx->streams[i]->codec->frame_number = 0;
         }
         /* set output format parameters */
-        c->fmt_ctx.oformat = c->stream->fmt;
-        c->fmt_ctx.nb_streams = c->stream->nb_streams;
+        c->pfmt_ctx->oformat = c->stream->fmt;
+        c->pfmt_ctx->nb_streams = c->stream->nb_streams;
 
         c->got_key_frame = 0;
 
         /* prepare header and save header data in a stream */
-        if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
+        if (avio_open_dyn_buf(&c->pfmt_ctx->pb) < 0) {
             /* XXX: potential leak */
             return -1;
         }
-        c->fmt_ctx.pb->seekable = 0;
+        c->pfmt_ctx->pb->seekable = 0;
 
         /*
          * HACK to avoid MPEG-PS muxer to spit many underflow errors
          * Default value from FFmpeg
          * Try to set it using configuration option
          */
-        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
+        c->pfmt_ctx->max_delay = (int)(0.7*AV_TIME_BASE);
 
-        if ((ret = avformat_write_header(&c->fmt_ctx, NULL)) < 0) {
+        if ((ret = avformat_write_header(c->pfmt_ctx, NULL)) < 0) {
             http_log("Error writing output header for stream '%s': %s\n",
                      c->stream->filename, av_err2str(ret));
             return ret;
         }
-        av_dict_free(&c->fmt_ctx.metadata);
+        av_dict_free(&c->pfmt_ctx->metadata);
 
-        len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
+        len = avio_close_dyn_buf(c->pfmt_ctx->pb, &c->pb_buffer);
         c->buffer_ptr = c->pb_buffer;
         c->buffer_end = c->pb_buffer + len;
 
@@ -2410,7 +2412,7 @@ static int http_prepare_data(HTTPContext *c)
                         /* only one stream per RTP connection */
                         pkt.stream_index = 0;
                     } else {
-                        ctx = &c->fmt_ctx;
+                        ctx = c->pfmt_ctx;
                         /* Fudge here */
                         codec = ctx->streams[pkt.stream_index]->codec;
                     }
@@ -2469,13 +2471,13 @@ static int http_prepare_data(HTTPContext *c)
         /* last packet test ? */
         if (c->last_packet_sent || c->is_packetized)
             return -1;
-        ctx = &c->fmt_ctx;
+        ctx = c->pfmt_ctx;
         /* prepare header */
         if (avio_open_dyn_buf(&ctx->pb) < 0) {
             /* XXX: potential leak */
             return -1;
         }
-        c->fmt_ctx.pb->seekable = 0;
+        c->pfmt_ctx->pb->seekable = 0;
         av_write_trailer(ctx);
         len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
         c->buffer_ptr = c->pb_buffer;
@@ -3709,26 +3711,25 @@ static void build_file_streams(void)
 }
 
 static inline
-int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs, int stream)
+int check_codec_match(AVStream *ccf, AVStream *ccs, int stream)
 {
     int matches = 1;
 
-#define CHECK_CODEC(x)  (ccf->x != ccs->x)
+/* FIXME: Missed check on AVCodecContext.flags */
+#define CHECK_CODEC(x)  (ccf->codecpar->x != ccs->codecpar->x)
     if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
         http_log("Codecs do not match for stream %d\n", stream);
         matches = 0;
-    } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
+    } else if (CHECK_CODEC(bit_rate)) {
         http_log("Codec bitrates do not match for stream %d\n", stream);
         matches = 0;
-    } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
-        if (CHECK_CODEC(time_base.den) ||
-            CHECK_CODEC(time_base.num) ||
-            CHECK_CODEC(width) ||
-            CHECK_CODEC(height)) {
+    } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (av_cmp_q(ccf->time_base, ccs->time_base) ||
+            CHECK_CODEC(width) || CHECK_CODEC(height)) {
             http_log("Codec width, height or framerate do not match for stream %d\n", stream);
             matches = 0;
         }
-    } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
+    } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
         if (CHECK_CODEC(sample_rate) ||
             CHECK_CODEC(channels) ||
             CHECK_CODEC(frame_size)) {
@@ -3810,7 +3811,7 @@ static int build_feed_streams(void)
                     break;
                 }
 
-                matches = check_codec_match (sf->codec, ss->codec, i);
+                matches = check_codec_match (sf, ss, i);
                 if (!matches)
                     break;
             }