Skip to content
Snippets Groups Projects
ffserver_config.c 45.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •         if (ffserver_save_avoption("lumi_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
    
        } else if (!av_strcasecmp(cmd, "DarkMask")) {
            ffserver_get_arg(arg, sizeof(arg), p);
    
            if (ffserver_save_avoption("dark_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
    
        } else if (!av_strcasecmp(cmd, "NoVideo")) {
    
            config->no_video = 1;
    
        } else if (!av_strcasecmp(cmd, "NoAudio")) {
    
            config->no_audio = 1;
    
        } else if (!av_strcasecmp(cmd, "ACL")) {
    
            ffserver_parse_acl_row(stream, NULL, NULL, *p, config->filename,
    
        } else if (!av_strcasecmp(cmd, "DynamicACL")) {
            ffserver_get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), p);
        } else if (!av_strcasecmp(cmd, "RTSPOption")) {
            ffserver_get_arg(arg, sizeof(arg), p);
            av_freep(&stream->rtsp_option);
            stream->rtsp_option = av_strdup(arg);
        } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
            ffserver_get_arg(arg, sizeof(arg), p);
    
            if (resolve_host(&stream->multicast_ip, arg))
    
                ERROR("Invalid host/IP address: %s\n", arg);
            stream->is_multicast = 1;
            stream->loop = 1; /* default is looping */
        } else if (!av_strcasecmp(cmd, "MulticastPort")) {
            ffserver_get_arg(arg, sizeof(arg), p);
    
            ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
    
                    "Invalid MulticastPort: %s\n", arg);
    
            stream->multicast_port = val;
    
        } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
            ffserver_get_arg(arg, sizeof(arg), p);
    
            ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config,
    
                    "Invalid MulticastTTL: %s\n", arg);
    
            stream->multicast_ttl = val;
    
        } else if (!av_strcasecmp(cmd, "NoLoop")) {
            stream->loop = 0;
        } else if (!av_strcasecmp(cmd, "</Stream>")) {
    
            config->stream_use_defaults &= 1;
    
            if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm")) {
    
                if (config->dummy_actx->codec_id == AV_CODEC_ID_NONE)
                    config->dummy_actx->codec_id = config->guessed_audio_codec_id;
                if (!config->no_audio && config->dummy_actx->codec_id != AV_CODEC_ID_NONE) {
                    AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_actx->codec_id));
    
                    add_codec(stream, audio_enc, config);
    
                if (config->dummy_vctx->codec_id == AV_CODEC_ID_NONE)
                    config->dummy_vctx->codec_id = config->guessed_video_codec_id;
                if (!config->no_video && config->dummy_vctx->codec_id != AV_CODEC_ID_NONE) {
                    AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_vctx->codec_id));
    
                    add_codec(stream, video_enc, config);
    
            av_dict_free(&config->video_opts);
            av_dict_free(&config->audio_opts);
    
            avcodec_free_context(&config->dummy_vctx);
            avcodec_free_context(&config->dummy_actx);
    
            *pstream = NULL;
        } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
    
            ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename),
                    p);
    
        } else if (!av_strcasecmp(cmd, "UseDefaults")) {
            if (config->stream_use_defaults > 1)
                WARNING("Multiple UseDefaults/NoDefaults entries.\n");
            config->stream_use_defaults = 3;
        } else if (!av_strcasecmp(cmd, "NoDefaults")) {
            if (config->stream_use_defaults > 1)
                WARNING("Multiple UseDefaults/NoDefaults entries.\n");
            config->stream_use_defaults = 2;
    
        } else {
            ERROR("Invalid entry '%s' inside <Stream></Stream>\n", cmd);
        }
        return 0;
    
      nomem:
        av_log(NULL, AV_LOG_ERROR, "Out of memory. Aborting.\n");
        av_dict_free(&config->video_opts);
        av_dict_free(&config->audio_opts);
    
        avcodec_free_context(&config->dummy_vctx);
        avcodec_free_context(&config->dummy_actx);
    
        return AVERROR(ENOMEM);
    
    }
    
    static int ffserver_parse_config_redirect(FFServerConfig *config, const char *cmd, const char **p,
    
                                              FFServerStream **predirect)
    
    {
        FFServerStream *redirect;
        av_assert0(predirect);
        redirect = *predirect;
    
        if (!av_strcasecmp(cmd, "<Redirect")) {
            char *q;
            redirect = av_mallocz(sizeof(FFServerStream));
            if (!redirect)
                return AVERROR(ENOMEM);
    
            ffserver_get_arg(redirect->filename, sizeof(redirect->filename), p);
            q = strrchr(redirect->filename, '>');
            if (*q)
                *q = '\0';
            redirect->stream_type = STREAM_TYPE_REDIRECT;
            *predirect = redirect;
            return 0;
        }
        av_assert0(redirect);
        if (!av_strcasecmp(cmd, "URL")) {
    
            ffserver_get_arg(redirect->feed_filename,
                    sizeof(redirect->feed_filename), p);
    
        } else if (!av_strcasecmp(cmd, "</Redirect>")) {
            if (!redirect->feed_filename[0])
                ERROR("No URL found for <Redirect>\n");
            *predirect = NULL;
        } else {
            ERROR("Invalid entry '%s' inside <Redirect></Redirect>\n", cmd);
        }
        return 0;
    }
    
    
    int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config)
    {
        FILE *f;
        char line[1024];
        char cmd[64];
        const char *p;
    
        FFServerStream **last_stream, *stream = NULL, *redirect = NULL;
        FFServerStream **last_feed, *feed = NULL;
    
        f = fopen(filename, "r");
        if (!f) {
            ret = AVERROR(errno);
    
            av_log(NULL, AV_LOG_ERROR,
                    "Could not open the configuration file '%s'\n", filename);
    
            return ret;
        }
    
        config->first_stream = NULL;
        last_stream = &config->first_stream;
        config->first_feed = NULL;
        last_feed = &config->first_feed;
    
        config->errors = config->warnings = 0;
    
    
        for(;;) {
            if (fgets(line, sizeof(line), f) == NULL)
                break;
    
            p = line;
            while (av_isspace(*p))
                p++;
            if (*p == '\0' || *p == '#')
                continue;
    
            ffserver_get_arg(cmd, sizeof(cmd), &p);
    
    
            if (feed || !av_strcasecmp(cmd, "<Feed")) {
                int opening = !av_strcasecmp(cmd, "<Feed");
                if (opening && (stream || feed || redirect)) {
    
                    ERROR("Already in a tag\n");
                } else {
    
                    if ((ret = ffserver_parse_config_feed(config, cmd, &p, &feed)) < 0)
    
                    if (opening) {
                        /* add in stream list */
                        *last_stream = feed;
                        last_stream = &feed->next;
                        /* add in feed list */
                        *last_feed = feed;
                        last_feed = &feed->next_feed;
    
            } else if (stream || !av_strcasecmp(cmd, "<Stream")) {
                int opening = !av_strcasecmp(cmd, "<Stream");
                if (opening && (stream || feed || redirect)) {
    
                    ERROR("Already in a tag\n");
                } else {
    
                    if ((ret = ffserver_parse_config_stream(config, cmd, &p, &stream)) < 0)
    
                        break;
                    if (opening) {
                        /* add in stream list */
                        *last_stream = stream;
                        last_stream = &stream->next;
    
            } else if (redirect || !av_strcasecmp(cmd, "<Redirect")) {
                int opening = !av_strcasecmp(cmd, "<Redirect");
                if (opening && (stream || feed || redirect))
    
                    ERROR("Already in a tag\n");
    
                    if ((ret = ffserver_parse_config_redirect(config, cmd, &p, &redirect)) < 0)
    
                        break;
                    if (opening) {
                        /* add in stream list */
                        *last_stream = redirect;
                        last_stream = &redirect->next;
    
                ffserver_parse_config_global(config, cmd, &p);
    
        if (stream || feed || redirect)
            ERROR("Not closed tag %s\n", stream ? "<Stream>" : (feed ? "<Feed>" : "<Redirect>"));
    
    
        fclose(f);
        if (ret < 0)
            return ret;
    
            return AVERROR(EINVAL);
        else
            return 0;
    }