[FFmpeg-devel] [PATCH 4/4] ffserver_config: postpone codec context creation

Reynaldo H. Verdejo Pinochet reynaldo at osg.samsung.com
Fri Oct 24 00:18:16 CEST 2014


Hi Lukasz

On 10/22/2014 06:44 PM, Lukasz Marek wrote:
> [..]
> 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

Thanks for the sum up.

> [..]
> @@ -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);                           \
> +        }                                                   \
> +    }

Can you turn those two macros into static inline funcs?. Also,
looks like it shouldn't be too hard to factor those two into
just 1 func. This is mostly to aid debugging. Nothing vital.

> [..]
> @@ -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);

Here and on every occurrence:

Any particular reason why not to check av_dict_set*()'s return
for < 0? Only reason I ask is because the config code already
has failed allocation checks elsewhere. Also, should help avoiding
some coverity scan noise.

> [..]
>      } 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);

I usually add braces for single statement ifs when the condition itself
has multiple lines. But I'm OK either way.

> [..]
> -
> +    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 */

Would drop the repeated "Contains".

Everything looks OK otherwise. Thanks a lot.

Bests,


-- 
Reynaldo H. Verdejo Pinochet
Open Source Group
Samsung Research America / Silicon Valley


More information about the ffmpeg-devel mailing list