On 22.10.2014 22:05, Reynaldo H. Verdejo Pinochet wrote:
Guess you are already considered dropping the explicit initialization
code as Reimaer suggested.
Looks good otherwise. Feel free to push.
I've attached updated patch.
To save your time:
1. I updated ffserver_apply_stream_config function,
2. added comments in FFServerConfig struct in header (according to
Stefano's remark)
3. in ffserver_parse_config_stream, at the end added:
av_freep(&config->video_preset);
av_freep(&config->audio_preset);
and checking result of ffserver_apply_stream_config calls
>From ca5e53e39254ce8ed205598b6ffc3ef0a3a41138 Mon Sep 17 00:00:00 2001
From: Lukasz Marek <lukasz.m.lu...@gmail.com>
Date: Sun, 19 Oct 2014 21:29:40 +0200
Subject: [PATCH] ffserver_config: postpone codec context creation
So far AVCodecContext was created without codec specified.
This causes internal data to not be initialized to defaults.
This commit postpone context creation until all information is gathered.
Partially fixes #1275
---
ffserver_config.c | 302 +++++++++++++++++++++++++++++++++---------------------
ffserver_config.h | 9 +-
2 files changed, 193 insertions(+), 118 deletions(-)
diff --git a/ffserver_config.c b/ffserver_config.c
index e44cdf7..65b7554 100644
--- a/ffserver_config.c
+++ b/ffserver_config.c
@@ -238,9 +238,8 @@ static void add_codec(FFServerStream *stream, AVCodecContext *av)
st = av_mallocz(sizeof(AVStream));
if (!st)
return;
- st->codec = avcodec_alloc_context3(NULL);
+ st->codec = av;
stream->streams[stream->nb_streams++] = st;
- memcpy(st->codec, av, sizeof(AVCodecContext));
}
static enum AVCodecID opt_codec(const char *name, enum AVMediaType type)
@@ -269,12 +268,15 @@ static int ffserver_opt_preset(const char *arg,
FILE *f=NULL;
char filename[1000], tmp[1000], tmp2[1000], line[1000];
int ret = 0;
- AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
+ AVCodec *codec = NULL;
+
+ if (avctx)
+ codec = avcodec_find_encoder(avctx->codec_id);
if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
codec ? codec->name : NULL))) {
fprintf(stderr, "File for preset '%s' not found\n", arg);
- return 1;
+ return AVERROR(EINVAL);
}
while(!feof(f)){
@@ -284,18 +286,17 @@ static int ffserver_opt_preset(const char *arg,
e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
if(e){
fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
- ret = 1;
+ ret = AVERROR(EINVAL);
break;
}
- if(!strcmp(tmp, "acodec")){
+ if (audio_id && !strcmp(tmp, "acodec")) {
*audio_id = opt_codec(tmp2, AVMEDIA_TYPE_AUDIO);
- }else if(!strcmp(tmp, "vcodec")){
+ } else if (video_id && !strcmp(tmp, "vcodec")){
*video_id = opt_codec(tmp2, AVMEDIA_TYPE_VIDEO);
- }else if(!strcmp(tmp, "scodec")){
+ } else if(!strcmp(tmp, "scodec")) {
/* opt_subtitle_codec(tmp2); */
- }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
+ } else if (avctx && (ret = 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;
}
}
@@ -502,6 +503,95 @@ static int ffserver_parse_config_feed(FFServerConfig *config, const char *cmd, c
return 0;
}
+static int ffserver_apply_stream_config(AVCodecContext *enc, const AVDictionary *conf, AVDictionary **opts)
+{
+ static const char *error_message = "Cannot parse '%s' as number for %s parameter.\n";
+ AVDictionaryEntry *e;
+ char *tailp;
+ int ret = 0;
+
+#define SET_INT_PARAM(factor, param, key) \
+ if ((e = av_dict_get(conf, #key, NULL, 0))) { \
+ if (!e->value[0]) { \
+ av_log(NULL, AV_LOG_ERROR, error_message, e->value, #key); \
+ ret = AVERROR(EINVAL); \
+ } \
+ enc->param = strtol(e->value, &tailp, 0); \
+ if (factor) enc->param *= (factor); \
+ if (tailp[0] || errno) { \
+ av_log(NULL, AV_LOG_ERROR, error_message, e->value, #key); \
+ ret = AVERROR(errno); \
+ } \
+ }
+#define SET_DOUBLE_PARAM(factor, param, key) \
+ if ((e = av_dict_get(conf, #key, NULL, 0))) { \
+ if (!e->value[0]) { \
+ av_log(NULL, AV_LOG_ERROR, error_message, e->value, #key); \
+ ret = AVERROR(EINVAL); \
+ } \
+ enc->param = strtod(e->value, &tailp); \
+ if (factor) enc->param *= (factor); \
+ if (tailp[0] || errno) { \
+ av_log(NULL, AV_LOG_ERROR, error_message, e->value, #key); \
+ ret = AVERROR(errno); \
+ } \
+ }
+
+ errno = 0;
+ //video params
+ SET_INT_PARAM(0, rc_min_rate, VideoBitRateRangeMin)
+ SET_INT_PARAM(0, rc_max_rate, VideoBitRateRangeMax)
+ SET_INT_PARAM(0, debug, Debug)
+ SET_INT_PARAM(0, strict_std_compliance, Strict)
+ SET_INT_PARAM(8*1024, rc_buffer_size, VideoBufferSize)
+ SET_INT_PARAM(1000, bit_rate_tolerance, VideoBitRateTolerance)
+ SET_INT_PARAM(1000, bit_rate, VideoBitRate)
+ SET_INT_PARAM(0, width, VideoSizeWidth)
+ SET_INT_PARAM(0, height, VideoSizeHeight)
+ SET_INT_PARAM(0, pix_fmt, PixelFormat)
+ SET_INT_PARAM(0, gop_size, VideoGopSize)
+ SET_INT_PARAM(0, time_base.num, VideoFrameRateNum)
+ SET_INT_PARAM(0, time_base.den, VideoFrameRateDen)
+ SET_INT_PARAM(0, max_qdiff, VideoQDiff)
+ SET_INT_PARAM(0, qmax, VideoQMax)
+ SET_INT_PARAM(0, qmin, VideoQMin)
+ SET_DOUBLE_PARAM(0, lumi_masking, LumiMask)
+ SET_DOUBLE_PARAM(0, dark_masking, DarkMask)
+ if (av_dict_get(conf, "BitExact", NULL, 0))
+ enc->flags |= CODEC_FLAG_BITEXACT;
+ if (av_dict_get(conf, "DctFastint", NULL, 0))
+ enc->dct_algo = FF_DCT_FASTINT;
+ if (av_dict_get(conf, "IdctSimple", NULL, 0))
+ enc->idct_algo = FF_IDCT_SIMPLE;
+ if (av_dict_get(conf, "VideoHighQuality", NULL, 0))
+ enc->mb_decision = FF_MB_DECISION_BITS;
+ if ((e = av_dict_get(conf, "VideoTag", NULL, 0)))
+ enc->codec_tag = MKTAG(e->value[0], e->value[1], e->value[2], e->value[3]);
+ if (av_dict_get(conf, "Qscale", NULL, 0)) {
+ enc->flags |= CODEC_FLAG_QSCALE;
+ SET_INT_PARAM(FF_QP2LAMBDA, global_quality, "Qscale")
+ }
+ if (av_dict_get(conf, "Video4MotionVector", NULL, 0)) {
+ enc->mb_decision = FF_MB_DECISION_BITS; //FIXME remove
+ enc->flags |= CODEC_FLAG_4MV;
+ }
+ //audio params
+ SET_INT_PARAM(0, channels, AudioChannels)
+ SET_INT_PARAM(0, sample_rate, AudioSampleRate)
+ SET_INT_PARAM(0, bit_rate, AudioBitRate)
+
+ av_opt_set_dict2(enc, opts, AV_OPT_SEARCH_CHILDREN);
+ e = NULL;
+ while (e = av_dict_get(*opts, "", e, AV_DICT_IGNORE_SUFFIX)) {
+ av_log(NULL, AV_LOG_ERROR, "Provided option '%s' doesn't match any existing option.\n", e->key);
+ ret = AVERROR(EINVAL);
+ }
+
+ return ret;
+#undef SET_INT_PARAM
+#undef SET_DOUBLE_PARAM
+}
+
static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, const char **p,
int line_num, FFServerStream **pstream)
{
@@ -528,14 +618,12 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd,
}
stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
- avcodec_get_context_defaults3(&config->video_enc, NULL);
- avcodec_get_context_defaults3(&config->audio_enc, NULL);
-
- config->audio_id = AV_CODEC_ID_NONE;
- config->video_id = AV_CODEC_ID_NONE;
if (stream->fmt) {
config->audio_id = stream->fmt->audio_codec;
config->video_id = stream->fmt->video_codec;
+ } else {
+ config->audio_id = AV_CODEC_ID_NONE;
+ config->video_id = AV_CODEC_ID_NONE;
}
*pstream = stream;
return 0;
@@ -624,136 +712,104 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd,
stream->max_time = atof(arg) * 1000;
} else if (!av_strcasecmp(cmd, "AudioBitRate")) {
ffserver_get_arg(arg, sizeof(arg), p);
- config->audio_enc.bit_rate = lrintf(atof(arg) * 1000);
- } else if (!av_strcasecmp(cmd, "AudioChannels")) {
+ av_dict_set_int(&config->audio_conf, cmd, lrintf(atof(arg) * 1000), 0);
+ } else if (!av_strcasecmp(cmd, "AudioChannels") ||
+ !av_strcasecmp(cmd, "AudioSampleRate")) {
ffserver_get_arg(arg, sizeof(arg), p);
- config->audio_enc.channels = atoi(arg);
- } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->audio_enc.sample_rate = atoi(arg);
+ av_dict_set(&config->audio_conf, cmd, arg, 0);
} else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
int minrate, maxrate;
ffserver_get_arg(arg, sizeof(arg), p);
if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
- config->video_enc.rc_min_rate = minrate * 1000;
- config->video_enc.rc_max_rate = maxrate * 1000;
+ av_dict_set_int(&config->video_conf, "VideoBitRateRangeMin", minrate * 1000, 0);
+ av_dict_set_int(&config->video_conf, "VideoBitRateRangeMax", maxrate * 1000, 0);
} else
ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
- } else if (!av_strcasecmp(cmd, "Debug")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.debug = strtol(arg,0,0);
- } else if (!av_strcasecmp(cmd, "Strict")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.strict_std_compliance = atoi(arg);
- } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.rc_buffer_size = atoi(arg) * 8*1024;
- } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.bit_rate_tolerance = atoi(arg) * 1000;
- } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.bit_rate = atoi(arg) * 1000;
+ } else if (!av_strcasecmp(cmd, "Debug") ||
+ !av_strcasecmp(cmd, "Strict") ||
+ !av_strcasecmp(cmd, "VideoBufferSize") ||
+ !av_strcasecmp(cmd, "VideoBitRateTolerance") ||
+ !av_strcasecmp(cmd, "VideoBitRate") ||
+ !av_strcasecmp(cmd, "VideoGopSize") ||
+ !av_strcasecmp(cmd, "Qscale") ||
+ !av_strcasecmp(cmd, "LumiMask") ||
+ !av_strcasecmp(cmd, "DarkMask")){
+ ffserver_get_arg(arg, sizeof(arg), p);
+ av_dict_set(&config->video_conf, cmd, arg, 0);
} else if (!av_strcasecmp(cmd, "VideoSize")) {
- int ret;
+ int ret, w, h;
ffserver_get_arg(arg, sizeof(arg), p);
- ret = av_parse_video_size(&config->video_enc.width, &config->video_enc.height, arg);
+ ret = av_parse_video_size(&w, &h, arg);
if (ret < 0)
ERROR("Invalid video size '%s'\n", arg);
- else if ((config->video_enc.width % 16) != 0 || (config->video_enc.height % 16) != 0)
+ else if ((w % 16) || (h % 16))
ERROR("Image size must be a multiple of 16\n");
+ av_dict_set_int(&config->video_conf, "VideoSizeWidth", w, 0);
+ av_dict_set_int(&config->video_conf, "VideoSizeHeight", h, 0);
} else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
AVRational frame_rate;
ffserver_get_arg(arg, sizeof(arg), p);
if (av_parse_video_rate(&frame_rate, arg) < 0) {
ERROR("Incorrect frame rate: %s\n", arg);
} else {
- config->video_enc.time_base.num = frame_rate.den;
- config->video_enc.time_base.den = frame_rate.num;
+ av_dict_set_int(&config->video_conf, "VideoFrameRateNum", frame_rate.num, 0);
+ av_dict_set_int(&config->video_conf, "VideoFrameRateDen", frame_rate.den, 0);
}
} else if (!av_strcasecmp(cmd, "PixelFormat")) {
+ enum AVPixelFormat pix_fmt;
ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.pix_fmt = av_get_pix_fmt(arg);
- if (config->video_enc.pix_fmt == AV_PIX_FMT_NONE)
+ pix_fmt = av_get_pix_fmt(arg);
+ if (pix_fmt == AV_PIX_FMT_NONE)
ERROR("Unknown pixel format: %s\n", arg);
- } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.gop_size = atoi(arg);
+ av_dict_set_int(&config->video_conf, cmd, pix_fmt, 0);
} else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
- config->video_enc.gop_size = 1;
- } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
- config->video_enc.mb_decision = FF_MB_DECISION_BITS;
- } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
- config->video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
- config->video_enc.flags |= CODEC_FLAG_4MV;
+ av_dict_set(&config->video_conf, "VideoGopSize", "1", 0);
} else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
!av_strcasecmp(cmd, "AVOptionAudio")) {
- AVCodecContext *avctx;
- int type;
+ AVDictionary **dict;
ffserver_get_arg(arg, sizeof(arg), p);
ffserver_get_arg(arg2, sizeof(arg2), p);
- if (!av_strcasecmp(cmd, "AVOptionVideo")) {
- avctx = &config->video_enc;
- type = AV_OPT_FLAG_VIDEO_PARAM;
- } else {
- avctx = &config->audio_enc;
- type = AV_OPT_FLAG_AUDIO_PARAM;
- }
- if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
- ERROR("Error setting %s option to %s %s\n", cmd, arg, arg2);
- }
+ if (!av_strcasecmp(cmd, "AVOptionVideo"))
+ dict = &config->video_opts;
+ else
+ dict = &config->audio_opts;
+ av_dict_set(dict, arg, arg2, 0);
} else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
!av_strcasecmp(cmd, "AVPresetAudio")) {
- AVCodecContext *avctx;
- int type;
+ char **preset = NULL;
ffserver_get_arg(arg, sizeof(arg), p);
if (!av_strcasecmp(cmd, "AVPresetVideo")) {
- avctx = &config->video_enc;
- config->video_enc.codec_id = config->video_id;
- type = AV_OPT_FLAG_VIDEO_PARAM;
+ preset = &config->video_preset;
+ ffserver_opt_preset(arg, NULL, 0, NULL, &config->video_id);
} else {
- avctx = &config->audio_enc;
- config->audio_enc.codec_id = config->audio_id;
- type = AV_OPT_FLAG_AUDIO_PARAM;
- }
- if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &config->audio_id, &config->video_id)) {
- ERROR("AVPreset error: %s\n", arg);
+ preset = &config->audio_preset;
+ ffserver_opt_preset(arg, NULL, 0, &config->audio_id, NULL);
}
+ *preset = av_strdup(arg);
+ if (!preset)
+ return AVERROR(ENOMEM);
} else if (!av_strcasecmp(cmd, "VideoTag")) {
ffserver_get_arg(arg, sizeof(arg), p);
if (strlen(arg) == 4)
- config->video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
- } else if (!av_strcasecmp(cmd, "BitExact")) {
- config->video_enc.flags |= CODEC_FLAG_BITEXACT;
- } else if (!av_strcasecmp(cmd, "DctFastint")) {
- config->video_enc.dct_algo = FF_DCT_FASTINT;
- } else if (!av_strcasecmp(cmd, "IdctSimple")) {
- config->video_enc.idct_algo = FF_IDCT_SIMPLE;
- } else if (!av_strcasecmp(cmd, "Qscale")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.flags |= CODEC_FLAG_QSCALE;
- config->video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
- } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.max_qdiff = atoi(arg);
- if (config->video_enc.max_qdiff < 1 || config->video_enc.max_qdiff > 31)
- ERROR("VideoQDiff out of range\n");
- } else if (!av_strcasecmp(cmd, "VideoQMax")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.qmax = atoi(arg);
- if (config->video_enc.qmax < 1 || config->video_enc.qmax > 31)
- ERROR("VideoQMax out of range\n");
- } else if (!av_strcasecmp(cmd, "VideoQMin")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.qmin = atoi(arg);
- if (config->video_enc.qmin < 1 || config->video_enc.qmin > 31)
- ERROR("VideoQMin out of range\n");
- } else if (!av_strcasecmp(cmd, "LumiMask")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.lumi_masking = atof(arg);
- } else if (!av_strcasecmp(cmd, "DarkMask")) {
- ffserver_get_arg(arg, sizeof(arg), p);
- config->video_enc.dark_masking = atof(arg);
+ av_dict_set(&config->video_conf, "VideoTag", "arg", 0);
+ else
+ ERROR("Invalid VideoTag %s\n", arg);
+ } else if (!av_strcasecmp(cmd, "BitExact") ||
+ !av_strcasecmp(cmd, "DctFastint") ||
+ !av_strcasecmp(cmd, "IdctSimple") ||
+ !av_strcasecmp(cmd, "VideoHighQuality") ||
+ !av_strcasecmp(cmd, "Video4MotionVector")) {
+ av_dict_set(&config->video_conf, cmd, "", 0);
+ } else if (!av_strcasecmp(cmd, "VideoQDiff") ||
+ !av_strcasecmp(cmd, "VideoQMin") ||
+ !av_strcasecmp(cmd, "VideoQMax")) {
+ int val;
+ ffserver_get_arg(arg, sizeof(arg), p);
+ val = atoi(arg);
+ if (val < 1 || val > 31)
+ ERROR("%s out of range\n", cmd);
+ else
+ av_dict_set(&config->video_conf, cmd, arg, 0);
} else if (!av_strcasecmp(cmd, "NoVideo")) {
config->video_id = AV_CODEC_ID_NONE;
} else if (!av_strcasecmp(cmd, "NoAudio")) {
@@ -783,16 +839,32 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd,
} else if (!av_strcasecmp(cmd, "</Stream>")) {
if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
if (config->audio_id != AV_CODEC_ID_NONE) {
- config->audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
- config->audio_enc.codec_id = config->audio_id;
- add_codec(stream, &config->audio_enc);
+ AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->audio_id));
+ if (config->audio_preset &&
+ ffserver_opt_preset(arg, audio_enc, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM,
+ NULL, NULL) < 0)
+ ERROR("Could not apply preset '%s'\n", arg);
+ if (ffserver_apply_stream_config(audio_enc, config->audio_conf, &config->audio_opts) < 0)
+ config->errors++;
+ add_codec(stream, audio_enc);
}
if (config->video_id != AV_CODEC_ID_NONE) {
- config->video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
- config->video_enc.codec_id = config->video_id;
- add_codec(stream, &config->video_enc);
+ AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->video_id));
+ if (config->video_preset &&
+ ffserver_opt_preset(arg, video_enc, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM,
+ NULL, NULL) < 0)
+ ERROR("Could not apply preset '%s'\n", arg);
+ if (ffserver_apply_stream_config(video_enc, config->video_conf, &config->video_opts) < 0)
+ config->errors++;
+ add_codec(stream, video_enc);
}
}
+ av_dict_free(&config->video_opts);
+ av_dict_free(&config->video_conf);
+ av_dict_free(&config->audio_opts);
+ av_dict_free(&config->audio_conf);
+ av_freep(&config->video_preset);
+ av_freep(&config->audio_preset);
*pstream = NULL;
} else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename), p);
diff --git a/ffserver_config.h b/ffserver_config.h
index 36d61d0..b6c955f 100644
--- a/ffserver_config.h
+++ b/ffserver_config.h
@@ -107,11 +107,14 @@ typedef struct FFServerConfig {
int errors;
int warnings;
// Following variables MUST NOT be used outside configuration parsing code.
- AVCodecContext audio_enc;
- AVCodecContext video_enc;
enum AVCodecID audio_id;
enum AVCodecID video_id;
-
+ AVDictionary *video_opts; /* Contains AVOptions for video encoder */
+ AVDictionary *video_conf; /* Contains values stored in video AVCodecContext.fields */
+ AVDictionary *audio_opts; /* Contains AVOptions for audio encoder */
+ AVDictionary *audio_conf; /* Contains values stored in audio AVCodecContext.fields */
+ char *video_preset;
+ char *audio_preset;
} FFServerConfig;
void ffserver_get_arg(char *buf, int buf_size, const char **pp);
--
1.9.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel