~ppsspp/ppsspp/ffmpeg

« back to all changes in this revision

Viewing changes to ffserver.c

  • Committer: Henrik Rydgård
  • Date: 2014-01-03 10:44:32 UTC
  • Revision ID: git-v1:87c6c126784b1718bfa448ecf2e6a9fef781eb4e
Update our ffmpeg snapshot to a clone of the official repository.

This is because Maxim's at3plus support has been officially merged!

Show diffs side-by-side

added added

removed removed

Lines of Context:
216
216
    struct FFStream *feed;   /* feed we are using (can be null if
217
217
                                coming from file) */
218
218
    AVDictionary *in_opts;   /* input parameters */
 
219
    AVDictionary *metadata;  /* metadata to set on the stream */
219
220
    AVInputFormat *ifmt;       /* if non NULL, force input format */
220
221
    AVOutputFormat *fmt;
221
222
    IPAddressACL *acl;
228
229
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
229
230
    char feed_filename[1024]; /* file name of the feed storage, or
230
231
                                 input file name for a stream */
231
 
    char author[512];
232
 
    char title[512];
233
 
    char copyright[512];
234
 
    char comment[512];
235
232
    pid_t pid;  /* Of ffmpeg process */
236
233
    time_t pid_start;  /* Of ffmpeg process */
237
234
    char **child_argv;
509
506
                char *slash;
510
507
                int i;
511
508
 
 
509
                /* replace "ffserver" with "ffmpeg" in the path of current program,
 
510
                 * ignore user provided path */
512
511
                av_strlcpy(pathname, my_program_name, sizeof(pathname));
513
 
 
514
512
                slash = strrchr(pathname, '/');
515
513
                if (!slash)
516
514
                    slash = pathname;
2183
2181
        buf_size = FFM_PACKET_SIZE;
2184
2182
        /* compute position (absolute time) */
2185
2183
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2186
 
            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
 
2184
            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) {
 
2185
                http_log("Invalid date specification '%s' for stream\n", buf);
2187
2186
                return ret;
 
2187
            }
2188
2188
        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2189
2189
            int prebuffer = strtol(buf, 0, 10);
2190
2190
            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2195
2195
        buf_size = 0;
2196
2196
        /* compute position (relative time) */
2197
2197
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2198
 
            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
 
2198
            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) {
 
2199
                http_log("Invalid date specification '%s' for stream\n", buf);
2199
2200
                return ret;
 
2201
            }
2200
2202
        } else
2201
2203
            stream_pos = 0;
2202
2204
    }
2203
 
    if (input_filename[0] == '\0')
2204
 
        return -1;
 
2205
    if (!input_filename[0]) {
 
2206
        http_log("No filename was specified for stream\n");
 
2207
        return AVERROR(EINVAL);
 
2208
    }
2205
2209
 
2206
2210
    /* open stream */
2207
2211
    if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2208
 
        http_log("could not open %s: %d\n", input_filename, ret);
2209
 
        return -1;
 
2212
        http_log("Could not open input '%s': %s\n", input_filename, av_err2str(ret));
 
2213
        return ret;
2210
2214
    }
2211
2215
 
2212
2216
    /* set buffer size */
2214
2218
 
2215
2219
    s->flags |= AVFMT_FLAG_GENPTS;
2216
2220
    c->fmt_in = s;
2217
 
    if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2218
 
        http_log("Could not find stream info '%s'\n", input_filename);
 
2221
    if (strcmp(s->iformat->name, "ffm") &&
 
2222
        (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) {
 
2223
        http_log("Could not find stream info for input '%s'\n", input_filename);
2219
2224
        avformat_close_input(&s);
2220
 
        return -1;
 
2225
        return ret;
2221
2226
    }
2222
2227
 
2223
2228
    /* choose stream as clock source (we favorize video stream if
2271
2276
    switch(c->state) {
2272
2277
    case HTTPSTATE_SEND_DATA_HEADER:
2273
2278
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2274
 
        av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2275
 
        av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2276
 
        av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2277
 
        av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2278
 
 
 
2279
        av_dict_copy(&(c->fmt_ctx.metadata), c->stream->metadata, 0);
2279
2280
        c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2280
2281
 
2281
2282
        for(i=0;i<c->stream->nb_streams;i++) {
2313
2314
         */
2314
2315
        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2315
2316
 
2316
 
        if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2317
 
            http_log("Error writing output header\n");
2318
 
            return -1;
 
2317
        if ((ret = avformat_write_header(&c->fmt_ctx, NULL)) < 0) {
 
2318
            http_log("Error writing output header for stream '%s': %s\n",
 
2319
                     c->stream->filename, av_err2str(ret));
 
2320
            return ret;
2319
2321
        }
2320
2322
        av_dict_free(&c->fmt_ctx.metadata);
2321
2323
 
2446
2448
                    if (pkt.pts != AV_NOPTS_VALUE)
2447
2449
                        pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2448
2450
                    pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2449
 
                    if (av_write_frame(ctx, &pkt) < 0) {
2450
 
                        http_log("Error writing frame to output\n");
 
2451
                    if ((ret = av_write_frame(ctx, &pkt)) < 0) {
 
2452
                        http_log("Error writing frame to output for stream '%s': %s\n",
 
2453
                                 c->stream->filename, av_err2str(ret));
2451
2454
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2452
2455
                    }
2453
2456
 
2614
2617
static int http_start_receive_data(HTTPContext *c)
2615
2618
{
2616
2619
    int fd;
 
2620
    int ret;
2617
2621
 
2618
 
    if (c->stream->feed_opened)
2619
 
        return -1;
 
2622
    if (c->stream->feed_opened) {
 
2623
        http_log("Stream feed '%s' was not opened\n", c->stream->feed_filename);
 
2624
        return AVERROR(EINVAL);
 
2625
    }
2620
2626
 
2621
2627
    /* Don't permit writing to this one */
2622
 
    if (c->stream->readonly)
2623
 
        return -1;
 
2628
    if (c->stream->readonly) {
 
2629
        http_log("Cannot write to read-only file '%s'\n", c->stream->feed_filename);
 
2630
        return AVERROR(EINVAL);
 
2631
    }
2624
2632
 
2625
2633
    /* open feed */
2626
2634
    fd = open(c->stream->feed_filename, O_RDWR);
2627
2635
    if (fd < 0) {
2628
 
        http_log("Error opening feeder file: %s\n", strerror(errno));
2629
 
        return -1;
 
2636
        ret = AVERROR(errno);
 
2637
        http_log("Could not open feed file '%s': %s\n",
 
2638
                 c->stream->feed_filename, strerror(errno));
 
2639
        return ret;
2630
2640
    }
2631
2641
    c->feed_fd = fd;
2632
2642
 
2635
2645
        ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2636
2646
        http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2637
2647
        if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2638
 
            http_log("Error truncating feed file: %s\n", strerror(errno));
2639
 
            return -1;
 
2648
            ret = AVERROR(errno);
 
2649
            http_log("Error truncating feed file '%s': %s\n",
 
2650
                     c->stream->feed_filename, strerror(errno));
 
2651
            return ret;
2640
2652
        }
2641
2653
    } else {
2642
 
        if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2643
 
            http_log("Error reading write index from feed file: %s\n", strerror(errno));
2644
 
            return -1;
 
2654
        ret = ffm_read_write_index(fd);
 
2655
        if (ret < 0) {
 
2656
            http_log("Error reading write index from feed file '%s': %s\n",
 
2657
                     c->stream->feed_filename, strerror(errno));
 
2658
            return ret;
 
2659
        } else {
 
2660
            c->stream->feed_write_index = ret;
2645
2661
        }
2646
2662
    }
2647
2663
 
2970
2986
    AVFormatContext *avc;
2971
2987
    AVStream *avs = NULL;
2972
2988
    AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
 
2989
    AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0);
2973
2990
    int i;
2974
2991
 
2975
2992
    avc =  avformat_alloc_context();
2978
2995
    }
2979
2996
    avc->oformat = rtp_format;
2980
2997
    av_dict_set(&avc->metadata, "title",
2981
 
               stream->title[0] ? stream->title : "No Title", 0);
 
2998
                entry ? entry->value : "No Title", 0);
2982
2999
    avc->nb_streams = stream->nb_streams;
2983
3000
    if (stream->is_multicast) {
2984
3001
        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
3669
3686
                av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3670
3687
            }
3671
3688
 
3672
 
            http_log("Opening file '%s'\n", stream->feed_filename);
 
3689
            if (!stream->feed_filename[0]) {
 
3690
                http_log("Unspecified feed file for stream '%s'\n", stream->filename);
 
3691
                goto fail;
 
3692
            }
 
3693
 
 
3694
            http_log("Opening feed file '%s' for stream '%s'\n", stream->feed_filename, stream->filename);
3673
3695
            if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3674
 
                http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
 
3696
                http_log("Could not open '%s': %s\n", stream->feed_filename, av_err2str(ret));
3675
3697
                /* remove stream (no need to spend more time on it) */
3676
3698
            fail:
3677
3699
                remove_stream(stream);
3942
3964
    memcpy(st->codec, av, sizeof(AVCodecContext));
3943
3965
}
3944
3966
 
3945
 
static enum AVCodecID opt_audio_codec(const char *arg)
3946
 
{
3947
 
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3948
 
 
3949
 
    if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3950
 
        return AV_CODEC_ID_NONE;
3951
 
 
3952
 
    return p->id;
3953
 
}
3954
 
 
3955
 
static enum AVCodecID opt_video_codec(const char *arg)
3956
 
{
3957
 
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3958
 
 
3959
 
    if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3960
 
        return AV_CODEC_ID_NONE;
3961
 
 
3962
 
    return p->id;
 
3967
static enum AVCodecID opt_codec(const char *name, enum AVMediaType type)
 
3968
{
 
3969
    AVCodec *codec = avcodec_find_encoder_by_name(name);
 
3970
 
 
3971
    if (!codec || codec->type != type)
 
3972
        return AV_CODEC_ID_NONE;
 
3973
    return codec->id;
3963
3974
}
3964
3975
 
3965
3976
static int ffserver_opt_default(const char *opt, const char *arg,
3998
4009
            break;
3999
4010
        }
4000
4011
        if(!strcmp(tmp, "acodec")){
4001
 
            *audio_id = opt_audio_codec(tmp2);
 
4012
            *audio_id = opt_codec(tmp2, AVMEDIA_TYPE_AUDIO);
4002
4013
        }else if(!strcmp(tmp, "vcodec")){
4003
 
            *video_id = opt_video_codec(tmp2);
 
4014
            *video_id = opt_codec(tmp2, AVMEDIA_TYPE_VIDEO);
4004
4015
        }else if(!strcmp(tmp, "scodec")){
4005
4016
            /* opt_subtitle_codec(tmp2); */
4006
4017
        }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
4034
4045
    return fmt;
4035
4046
}
4036
4047
 
4037
 
static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
 
4048
static void report_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, ...)
4038
4049
{
4039
4050
    va_list vl;
4040
4051
    va_start(vl, fmt);
4041
 
    fprintf(stderr, "%s:%d: ", filename, line_num);
4042
 
    vfprintf(stderr, fmt, vl);
 
4052
    av_log(NULL, log_level, "%s:%d: ", filename, line_num);
 
4053
    av_vlog(NULL, log_level, fmt, vl);
4043
4054
    va_end(vl);
4044
4055
 
4045
4056
    (*errors)++;
4050
4061
    FILE *f;
4051
4062
    char line[1024];
4052
4063
    char cmd[64];
4053
 
    char arg[1024];
 
4064
    char arg[1024], arg2[1024];
4054
4065
    const char *p;
4055
 
    int val, errors, line_num;
 
4066
    int val, errors, warnings, line_num;
4056
4067
    FFStream **last_stream, *stream, *redirect;
4057
4068
    FFStream **last_feed, *feed, *s;
4058
4069
    AVCodecContext audio_enc, video_enc;
4059
4070
    enum AVCodecID audio_id, video_id;
 
4071
    int ret = 0;
4060
4072
 
4061
4073
    f = fopen(filename, "r");
4062
4074
    if (!f) {
4063
 
        perror(filename);
4064
 
        return -1;
 
4075
        ret = AVERROR(errno);
 
4076
        av_log(NULL, AV_LOG_ERROR, "Could not open the configuration file '%s'\n", filename);
 
4077
        return ret;
4065
4078
    }
4066
4079
 
4067
 
    errors = 0;
 
4080
    errors = warnings = 0;
4068
4081
    line_num = 0;
4069
4082
    first_stream = NULL;
4070
4083
    last_stream = &first_stream;
4075
4088
    redirect = NULL;
4076
4089
    audio_id = AV_CODEC_ID_NONE;
4077
4090
    video_id = AV_CODEC_ID_NONE;
 
4091
#define ERROR(...)   report_config_error(filename, line_num, AV_LOG_ERROR,   &errors,   __VA_ARGS__)
 
4092
#define WARNING(...) report_config_error(filename, line_num, AV_LOG_WARNING, &warnings, __VA_ARGS__)
4078
4093
 
4079
 
#define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4080
4094
    for(;;) {
4081
4095
        if (fgets(line, sizeof(line), f) == NULL)
4082
4096
            break;
4102
4116
                ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4103
4117
            }
4104
4118
        } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4105
 
            // do nothing here, its the default now
 
4119
            WARNING("NoDaemon option has no effect, you should remove it\n");
4106
4120
        } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4107
4121
            get_arg(arg, sizeof(arg), &p);
4108
4122
            val = atoi(arg);
4149
4163
                ERROR("Already in a tag\n");
4150
4164
            } else {
4151
4165
                feed = av_mallocz(sizeof(FFStream));
 
4166
                if (!feed) {
 
4167
                    ret = AVERROR(ENOMEM);
 
4168
                    goto end;
 
4169
                }
4152
4170
                get_arg(feed->filename, sizeof(feed->filename), &p);
4153
4171
                q = strrchr(feed->filename, '>');
4154
4172
                if (*q)
4161
4179
                }
4162
4180
 
4163
4181
                feed->fmt = av_guess_format("ffm", NULL, NULL);
4164
 
                /* defaut feed file */
 
4182
                /* default feed file */
4165
4183
                snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4166
4184
                         "/tmp/%s.ffm", feed->filename);
4167
4185
                feed->feed_max_size = 5 * 1024 * 1024;
4180
4198
                int i;
4181
4199
 
4182
4200
                feed->child_argv = av_mallocz(64 * sizeof(char *));
4183
 
 
 
4201
                if (!feed->child_argv) {
 
4202
                    ret = AVERROR(ENOMEM);
 
4203
                    goto end;
 
4204
                }
4184
4205
                for (i = 0; i < 62; i++) {
4185
4206
                    get_arg(arg, sizeof(arg), &p);
4186
4207
                    if (!arg[0])
4187
4208
                        break;
4188
4209
 
4189
4210
                    feed->child_argv[i] = av_strdup(arg);
 
4211
                    if (!feed->child_argv[i]) {
 
4212
                        ret = AVERROR(ENOMEM);
 
4213
                        goto end;
 
4214
                    }
4190
4215
                }
4191
4216
 
4192
 
                feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
4193
 
                        (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4194
 
                    inet_ntoa(my_http_addr.sin_addr),
4195
 
                    ntohs(my_http_addr.sin_port), feed->filename);
 
4217
                feed->child_argv[i] =
 
4218
                    av_asprintf("http://%s:%d/%s",
 
4219
                                (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
 
4220
                                inet_ntoa(my_http_addr.sin_addr), ntohs(my_http_addr.sin_port),
 
4221
                                feed->filename);
 
4222
                if (!feed->child_argv[i]) {
 
4223
                    ret = AVERROR(ENOMEM);
 
4224
                    goto end;
 
4225
                }
4196
4226
            }
4197
 
        } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
 
4227
        } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
4198
4228
            if (feed) {
4199
4229
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4200
 
                feed->readonly = 1;
 
4230
                feed->readonly = !av_strcasecmp(cmd, "ReadOnlyFile");
4201
4231
            } else if (stream) {
4202
4232
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4203
4233
            }
4204
 
        } else if (!av_strcasecmp(cmd, "File")) {
4205
 
            if (feed) {
4206
 
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4207
 
            } else if (stream)
4208
 
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4209
4234
        } else if (!av_strcasecmp(cmd, "Truncate")) {
4210
4235
            if (feed) {
4211
4236
                get_arg(arg, sizeof(arg), &p);
4212
 
                feed->truncate = strtod(arg, NULL);
 
4237
                /* assume Truncate is true in case no argument is specified */
 
4238
                if (!arg[0]) {
 
4239
                    feed->truncate = 1;
 
4240
                } else {
 
4241
                    WARNING("Truncate N syntax in configuration file is deprecated, "
 
4242
                            "use Truncate alone with no arguments\n");
 
4243
                    feed->truncate = strtod(arg, NULL);
 
4244
                }
4213
4245
            }
4214
4246
        } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4215
4247
            if (feed) {
4249
4281
            } else {
4250
4282
                FFStream *s;
4251
4283
                stream = av_mallocz(sizeof(FFStream));
 
4284
                if (!stream) {
 
4285
                    ret = AVERROR(ENOMEM);
 
4286
                    goto end;
 
4287
                }
4252
4288
                get_arg(stream->filename, sizeof(stream->filename), &p);
4253
4289
                q = strrchr(stream->filename, '>');
4254
4290
                if (q)
4286
4322
                    sfeed = sfeed->next_feed;
4287
4323
                }
4288
4324
                if (!sfeed)
4289
 
                    ERROR("feed '%s' not defined\n", arg);
 
4325
                    ERROR("Feed with name '%s' for stream '%s' is not defined\n", arg, stream->filename);
4290
4326
                else
4291
4327
                    stream->feed = sfeed;
4292
4328
            }
4325
4361
            } else {
4326
4362
                ERROR("FaviconURL only permitted for status streams\n");
4327
4363
            }
4328
 
        } else if (!av_strcasecmp(cmd, "Author")) {
4329
 
            if (stream)
4330
 
                get_arg(stream->author, sizeof(stream->author), &p);
4331
 
        } else if (!av_strcasecmp(cmd, "Comment")) {
4332
 
            if (stream)
4333
 
                get_arg(stream->comment, sizeof(stream->comment), &p);
4334
 
        } else if (!av_strcasecmp(cmd, "Copyright")) {
4335
 
            if (stream)
4336
 
                get_arg(stream->copyright, sizeof(stream->copyright), &p);
4337
 
        } else if (!av_strcasecmp(cmd, "Title")) {
4338
 
            if (stream)
4339
 
                get_arg(stream->title, sizeof(stream->title), &p);
 
4364
        } else if (!av_strcasecmp(cmd, "Author")    ||
 
4365
                   !av_strcasecmp(cmd, "Comment")   ||
 
4366
                   !av_strcasecmp(cmd, "Copyright") ||
 
4367
                   !av_strcasecmp(cmd, "Title")) {
 
4368
            get_arg(arg, sizeof(arg), &p);
 
4369
 
 
4370
            if (stream) {
 
4371
                char key[32];
 
4372
                int i, ret;
 
4373
 
 
4374
                for (i = 0; i < strlen(cmd); i++)
 
4375
                    key[i] = av_tolower(cmd[i]);
 
4376
                key[i] = 0;
 
4377
                WARNING("'%s' option in configuration file is deprecated, "
 
4378
                        "use 'Metadata %s VALUE' instead\n", cmd, key);
 
4379
                if ((ret = av_dict_set(&stream->metadata, key, arg, 0)) < 0) {
 
4380
                    ERROR("Could not set metadata '%s' to value '%s': %s\n",
 
4381
                          key, arg, av_err2str(ret));
 
4382
                }
 
4383
            }
 
4384
        } else if (!av_strcasecmp(cmd, "Metadata")) {
 
4385
            get_arg(arg, sizeof(arg), &p);
 
4386
            get_arg(arg2, sizeof(arg2), &p);
 
4387
            if (stream) {
 
4388
                int ret;
 
4389
                if ((ret = av_dict_set(&stream->metadata, arg, arg2, 0)) < 0) {
 
4390
                    ERROR("Could not set metadata '%s' to value '%s': %s\n",
 
4391
                          arg, arg2, av_err2str(ret));
 
4392
                }
 
4393
            }
4340
4394
        } else if (!av_strcasecmp(cmd, "Preroll")) {
4341
4395
            get_arg(arg, sizeof(arg), &p);
4342
4396
            if (stream)
4346
4400
                stream->send_on_key = 1;
4347
4401
        } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4348
4402
            get_arg(arg, sizeof(arg), &p);
4349
 
            audio_id = opt_audio_codec(arg);
 
4403
            audio_id = opt_codec(arg, AVMEDIA_TYPE_AUDIO);
4350
4404
            if (audio_id == AV_CODEC_ID_NONE) {
4351
4405
                ERROR("Unknown AudioCodec: %s\n", arg);
4352
4406
            }
4353
4407
        } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4354
4408
            get_arg(arg, sizeof(arg), &p);
4355
 
            video_id = opt_video_codec(arg);
 
4409
            video_id = opt_codec(arg, AVMEDIA_TYPE_VIDEO);
4356
4410
            if (video_id == AV_CODEC_ID_NONE) {
4357
4411
                ERROR("Unknown VideoCodec: %s\n", arg);
4358
4412
            }
4372
4426
            get_arg(arg, sizeof(arg), &p);
4373
4427
            if (stream)
4374
4428
                audio_enc.sample_rate = atoi(arg);
4375
 
        } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4376
 
            get_arg(arg, sizeof(arg), &p);
4377
 
            if (stream) {
4378
 
//                audio_enc.quality = atof(arg) * 1000;
4379
 
            }
4380
4429
        } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4381
4430
            if (stream) {
4382
4431
                int minrate, maxrate;
4418
4467
        } else if (!av_strcasecmp(cmd, "VideoSize")) {
4419
4468
            get_arg(arg, sizeof(arg), &p);
4420
4469
            if (stream) {
4421
 
                av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4422
 
                if ((video_enc.width % 16) != 0 ||
4423
 
                    (video_enc.height % 16) != 0) {
4424
 
                    ERROR("Image size must be a multiple of 16\n");
 
4470
                ret = av_parse_video_size(&video_enc.width, &video_enc.height, arg);
 
4471
                if (ret < 0) {
 
4472
                    ERROR("Invalid video size '%s'\n", arg);
 
4473
                } else {
 
4474
                    if ((video_enc.width % 16) != 0 ||
 
4475
                        (video_enc.height % 16) != 0) {
 
4476
                        ERROR("Image size must be a multiple of 16\n");
 
4477
                    }
4425
4478
                }
4426
4479
            }
4427
4480
        } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4460
4513
            }
4461
4514
        } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4462
4515
                   !av_strcasecmp(cmd, "AVOptionAudio")) {
4463
 
            char arg2[1024];
4464
4516
            AVCodecContext *avctx;
4465
4517
            int type;
4466
4518
            get_arg(arg, sizeof(arg), &p);
4473
4525
                type = AV_OPT_FLAG_AUDIO_PARAM;
4474
4526
            }
4475
4527
            if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4476
 
                ERROR("AVOption error: %s %s\n", arg, arg2);
 
4528
                ERROR("Error setting %s option to %s %s\n", cmd, arg, arg2);
4477
4529
            }
4478
4530
        } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4479
4531
                   !av_strcasecmp(cmd, "AVPresetAudio")) {
4604
4656
                ERROR("Already in a tag\n");
4605
4657
            } else {
4606
4658
                redirect = av_mallocz(sizeof(FFStream));
 
4659
                if (!redirect) {
 
4660
                    ret = AVERROR(ENOMEM);
 
4661
                    goto end;
 
4662
                }
4607
4663
                *last_stream = redirect;
4608
4664
                last_stream = &redirect->next;
4609
4665
 
4633
4689
    }
4634
4690
#undef ERROR
4635
4691
 
 
4692
end:
4636
4693
    fclose(f);
 
4694
    if (ret < 0)
 
4695
        return ret;
4637
4696
    if (errors)
4638
 
        return -1;
 
4697
        return AVERROR(EINVAL);
4639
4698
    else
4640
4699
        return 0;
4641
4700
}
4690
4749
int main(int argc, char **argv)
4691
4750
{
4692
4751
    struct sigaction sigact = { { 0 } };
 
4752
    int ret = 0;
4693
4753
 
4694
4754
    config_filename = av_strdup("/etc/ffserver.conf");
4695
4755
 
4711
4771
    sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4712
4772
    sigaction(SIGCHLD, &sigact, 0);
4713
4773
 
4714
 
    if (parse_ffconfig(config_filename) < 0) {
4715
 
        fprintf(stderr, "Incorrect config file - exiting.\n");
 
4774
    if ((ret = parse_ffconfig(config_filename)) < 0) {
 
4775
        fprintf(stderr, "Error reading configuration file '%s': %s\n",
 
4776
                config_filename, av_err2str(ret));
4716
4777
        exit(1);
4717
4778
    }
4718
4779
    av_freep(&config_filename);