static int input_sync;
static int override_ffserver = 0;
static int input_stream_potentially_available = 0;
+static int ignore_unknown_streams = 0;
+static int copy_unknown_streams = 0;
static void uninit_options(OptionsContext *o)
{
ist->ts_scale = 1.0;
MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
+ ist->autorotate = 1;
+ MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st);
+
MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
if (codec_tag) {
uint32_t tag = strtol(codec_tag, &next, 0);
/* if seeking requested, we execute it */
if (o->start_time != AV_NOPTS_VALUE) {
- ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, timestamp, 0);
+ int64_t seek_timestamp = timestamp;
+
+ if (!(ic->iformat->flags & AVFMT_SEEK_TO_PTS)) {
+ int dts_heuristic = 0;
+ for (i=0; i<ic->nb_streams; i++) {
+ AVCodecContext *avctx = ic->streams[i]->codec;
+ if (avctx->has_b_frames)
+ dts_heuristic = 1;
+ }
+ if (dts_heuristic) {
+ seek_timestamp -= 3*AV_TIME_BASE / 23;
+ }
+ }
+ ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_timestamp, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
filename, (double)timestamp / AV_TIME_BASE);
return ost;
}
+static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
+{
+ OutputStream *ost;
+
+ ost = new_output_stream(o, oc, AVMEDIA_TYPE_UNKNOWN, source_index);
+ if (!ost->stream_copy) {
+ av_log(NULL, AV_LOG_FATAL, "Unknown stream encoding not supported yet (only streamcopy)\n");
+ exit_program(1);
+ }
+
+ return ost;
+}
+
static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
{
OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index);
case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_DATA: ost = new_data_stream (o, oc, src_idx); break;
case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc, src_idx); break;
+ case AVMEDIA_TYPE_UNKNOWN:
+ if (copy_unknown_streams) {
+ ost = new_unknown_stream (o, oc, src_idx);
+ break;
+ }
default:
- av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
+ av_log(NULL, ignore_unknown_streams ? AV_LOG_WARNING : AV_LOG_FATAL,
+ "Cannot map stream #%d:%d - unsupported type.\n",
map->file_index, map->stream_index);
- exit_program(1);
+ if (!ignore_unknown_streams) {
+ av_log(NULL, AV_LOG_FATAL,
+ "If you want unsupported types ignored instead "
+ "of failing, please use the -ignore_unknown option\n"
+ "If you want them copied, please use -copy_unknown\n");
+ exit_program(1);
+ }
}
}
}
continue;
ist = input_streams[output_streams[i]->source_index];
av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
- if (!output_streams[i]->stream_copy)
+ if (!output_streams[i]->stream_copy) {
av_dict_set(&output_streams[i]->st->metadata, "encoder", NULL, 0);
+ if (ist->autorotate)
+ av_dict_set(&output_streams[i]->st->metadata, "rotate", NULL, 0);
+ }
}
/* process manually set metadata */
parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec);
if (type == 's') {
for (j = 0; j < oc->nb_streams; j++) {
+ ost = output_streams[nb_output_streams - oc->nb_streams + j];
if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) {
av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0);
+ if (!strcmp(o->metadata[i].u.str, "rotate")) {
+ ost->rotate_overridden = 1;
+ }
} else if (ret < 0)
exit_program(1);
}
"overwrite output files" },
{ "n", OPT_BOOL, { &no_file_overwrite },
"never overwrite output files" },
+ { "ignore_unknown", OPT_BOOL, { &ignore_unknown_streams },
+ "Ignore unknown stream types" },
+ { "copy_unknown", OPT_BOOL | OPT_EXPERT, { ©_unknown_streams },
+ "Copy unknown stream types" },
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC |
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) },
"codec name", "codec" },
{ "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC |
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(ts_scale) },
"set the input ts scale", "scale" },
- { "timestamp", HAS_ARG | OPT_PERFILE, { .func_arg = opt_recording_timestamp },
+ { "timestamp", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_recording_timestamp },
"set the recording timestamp ('now' to set the current time)", "time" },
{ "metadata", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(metadata) },
"add metadata", "string=string" },
#if HAVE_VDPAU_X11
{ "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" },
#endif
+ { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC |
+ OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) },
+ "automatically insert correct rotate filters" },
/* audio options */
{ "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames },