char buf[128];
int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
struct tm time = *gmtime((time_t*)&recording_timestamp);
- strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
+ if (!strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time))
+ return -1;
parse_option(o, "metadata", buf, options);
av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
if (canvas_size &&
- av_parse_video_size(&dec->width, &dec->height, canvas_size) < 0) {
+ av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) {
av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
exit_program(1);
}
char * video_codec_name = NULL;
char * audio_codec_name = NULL;
char *subtitle_codec_name = NULL;
+ int scan_all_pmts_set = 0;
if (o->format) {
if (!(file_iformat = av_find_input_format(o->format))) {
ic->flags |= AVFMT_FLAG_NONBLOCK;
ic->interrupt_callback = int_cb;
+ if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+ av_dict_set(&o->g->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+ scan_all_pmts_set = 1;
+ }
/* open the input file with generic avformat function */
err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
if (err < 0) {
print_error(filename, err);
exit_program(1);
}
+ if (scan_all_pmts_set)
+ av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
remove_avoptions(&o->g->format_opts, o->g->codec_opts);
assert_avoptions(o->g->format_opts);
av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
exit_program(1);
}
+ if (frame_rate && video_sync_method == VSYNC_PASSTHROUGH)
+ av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r can produce invalid output files\n");
MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
if (frame_aspect_ratio) {
return 0;
}
+static int ffserver_streams_copy_context(AVCodecContext *dest, const AVCodecContext *src,
+ const char *configuration)
+{
+ int ret;
+ if ((ret = avcodec_copy_context(dest, src)) < 0)
+ return ret;
+ dest->codec = avcodec_find_encoder(src->codec_id);
+ if (!dest->codec)
+ return AVERROR(EINVAL);
+ if (!dest->codec->priv_class || !dest->codec->priv_data_size)
+ return 0;
+ if (!dest->priv_data) {
+ dest->priv_data = av_mallocz(dest->codec->priv_data_size);
+ if (!dest->priv_data)
+ return AVERROR(ENOMEM);
+ *(const AVClass**)dest->priv_data = dest->codec->priv_class;
+ }
+ av_opt_set_defaults(dest->priv_data);
+ if (av_set_options_string(dest->priv_data, configuration, "=", ",") < 0) {
+ av_log(dest, AV_LOG_WARNING, "Cannot copy private codec options. Using defaults.\n");
+ av_opt_set_defaults(dest->priv_data);
+ }
+ return 0;
+}
+
static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
{
int i, err;
AVStream *st;
OutputStream *ost;
AVCodec *codec;
- AVCodecContext *avctx;
codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
if (!codec) {
av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id);
return AVERROR(EINVAL);
}
+ if (codec->type == AVMEDIA_TYPE_AUDIO)
+ opt_audio_codec(o, "c:a", codec->name);
+ else if (codec->type == AVMEDIA_TYPE_VIDEO)
+ opt_video_codec(o, "c:v", codec->name);
ost = new_output_stream(o, s, codec->type, -1);
st = ost->st;
- avctx = st->codec;
- ost->enc = codec;
- // FIXME: a more elegant solution is needed
- memcpy(st, ic->streams[i], sizeof(AVStream));
- st->cur_dts = 0;
- st->info = av_malloc(sizeof(*st->info));
- memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
- st->codec= avctx;
- avcodec_copy_context(st->codec, ic->streams[i]->codec);
+ ffserver_streams_copy_context(st->codec, ic->streams[i]->codec,
+ av_stream_get_recommended_encoder_configuration(ic->streams[i]));
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
choose_sample_fmt(st, codec);
else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
choose_pixel_fmt(st, st->codec, codec, st->codec->pix_fmt);
- avcodec_copy_context(ost->enc_ctx, st->codec);
+ ffserver_streams_copy_context(ost->enc_ctx, st->codec,
+ av_stream_get_recommended_encoder_configuration(ic->streams[i]));
}
avformat_close_input(&ic);
"add metadata", "string=string" },
{ "dframes", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
OPT_OUTPUT, { .func_arg = opt_data_frames },
- "set the number of data frames to record", "number" },
+ "set the number of data frames to output", "number" },
{ "benchmark", OPT_BOOL | OPT_EXPERT, { &do_benchmark },
"add timings for benchmarking" },
{ "benchmark_all", OPT_BOOL | OPT_EXPERT, { &do_benchmark_all },
{ "copypriorss", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(copy_prior_start) },
"copy or discard frames before start time" },
{ "frames", OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) },
- "set the number of frames to record", "number" },
+ "set the number of frames to output", "number" },
{ "tag", OPT_STRING | HAS_ARG | OPT_SPEC |
OPT_EXPERT | OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(codec_tags) },
"force codec tag/fourcc", "fourcc/tag" },
/* video options */
{ "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames },
- "set the number of video frames to record", "number" },
+ "set the number of video frames to output", "number" },
{ "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC |
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_rates) },
"set frame rate (Hz value, fraction or abbreviation)", "rate" },
/* audio options */
{ "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames },
- "set the number of audio frames to record", "number" },
+ "set the number of audio frames to output", "number" },
{ "aq", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_qscale },
"set audio quality (codec-specific)", "quality", },
{ "ar", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC |