Support presets in ffserver.conf
authorHoward Chu <hyc@highlandsun.com>
Tue, 8 Jun 2010 09:55:30 +0000 (09:55 +0000)
committerHoward Chu <hyc@highlandsun.com>
Tue, 8 Jun 2010 09:55:30 +0000 (09:55 +0000)
Originally committed as revision 23524 to svn://svn.ffmpeg.org/ffmpeg/trunk

doc/ffserver.conf
ffserver.c

index 2fbfecd..2171170 100644 (file)
@@ -306,6 +306,27 @@ StartSendOnKey
 #</Stream>
 
 
+# Transcode an incoming live feed to another live feed,
+# using libx264 and video presets
+
+#<Stream live.h264>
+#Format rtp
+#Feed feed1.ffm
+#VideoCodec libx264
+#VideoFrameRate 24
+#VideoBitRate 100
+#VideoSize 480x272
+#AVPresetVideo default
+#AVPresetVideo baseline
+#AVOptionVideo flags +global_header
+#
+#AudioCodec libfaac
+#AudioBitRate 32
+#AudioChannels 2
+#AudioSampleRate 22050
+#AVOptionAudio flags +global_header
+#</Stream>
+
 ##################################################################
 # SDP/multicast examples
 #
index 6d1e710..77340af 100644 (file)
@@ -3949,6 +3949,65 @@ static int ffserver_opt_default(const char *opt, const char *arg,
     return ret;
 }
 
+static int ffserver_opt_preset(const char *arg,
+                       AVCodecContext *avctx, int type,
+                       enum CodecID *audio_id, enum CodecID *video_id)
+{
+    FILE *f=NULL;
+    char filename[1000], tmp[1000], tmp2[1000], line[1000];
+    int i, ret = 0;
+    const char *base[3]= { getenv("FFMPEG_DATADIR"),
+                           getenv("HOME"),
+                           FFMPEG_DATADIR,
+                         };
+
+    for(i=0; i<3 && !f; i++){
+        if(!base[i])
+            continue;
+        snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", arg);
+        f= fopen(filename, "r");
+        if(!f){
+            AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
+            if (codec) {
+                snprintf(filename, sizeof(filename), "%s%s/%s-%s.ffpreset", base[i],  i != 1 ? "" : "/.ffmpeg", codec->name, arg);
+                f= fopen(filename, "r");
+            }
+        }
+    }
+
+    if(!f){
+        fprintf(stderr, "File for preset '%s' not found\n", arg);
+        return 1;
+    }
+
+    while(!feof(f)){
+        int e= fscanf(f, "%999[^\n]\n", line) - 1;
+        if(line[0] == '#' && !e)
+            continue;
+        e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
+        if(e){
+            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
+            ret = 1;
+            break;
+        }
+        if(!strcmp(tmp, "acodec")){
+            *audio_id = opt_audio_codec(tmp2);
+        }else if(!strcmp(tmp, "vcodec")){
+            *video_id = opt_video_codec(tmp2);
+        }else if(!strcmp(tmp, "scodec")){
+            /* opt_subtitle_codec(tmp2); */
+        }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
+            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
+            ret = 1;
+            break;
+        }
+    }
+
+    fclose(f);
+
+    return ret;
+}
+
 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
                                              const char *mime_type)
 {
@@ -4403,6 +4462,23 @@ static int parse_ffconfig(const char *filename)
             if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
                 ERROR("AVOption error: %s %s\n", arg, arg2);
             }
+        } else if (!strcasecmp(cmd, "AVPresetVideo") ||
+                   !strcasecmp(cmd, "AVPresetAudio")) {
+            AVCodecContext *avctx;
+            int type;
+            get_arg(arg, sizeof(arg), &p);
+            if (!strcasecmp(cmd, "AVPresetVideo")) {
+                avctx = &video_enc;
+                video_enc.codec_id = video_id;
+                type = AV_OPT_FLAG_VIDEO_PARAM;
+            } else {
+                avctx = &audio_enc;
+                audio_enc.codec_id = audio_id;
+                type = AV_OPT_FLAG_AUDIO_PARAM;
+            }
+            if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
+                ERROR("AVPreset error: %s\n", arg);
+            }
         } else if (!strcasecmp(cmd, "VideoTag")) {
             get_arg(arg, sizeof(arg), &p);
             if ((strlen(arg) == 4) && stream)