From 98bb5c7619f6f7a421fb568a3065df689d94bbfc Mon Sep 17 00:00:00 2001 From: Taner Sener Date: Sat, 14 Aug 2021 22:19:51 +0300 Subject: [PATCH] use ffmpeg n4.5-dev-1598-gacd3c101ef --- .../src/main/cpp/fftools_cmdutils.c | 42 +++++-- .../src/main/cpp/fftools_cmdutils.h | 5 + .../src/main/cpp/fftools_ffmpeg.c | 57 +++++++--- .../src/main/cpp/fftools_ffmpeg.h | 6 +- .../src/main/cpp/fftools_ffmpeg_filter.c | 10 +- .../src/main/cpp/fftools_ffmpeg_hw.c | 12 ++ .../src/main/cpp/fftools_ffmpeg_opt.c | 103 ++++++++++++++---- .../src/main/cpp/fftools_ffprobe.c | 18 +-- apple/src/fftools_cmdutils.c | 42 +++++-- apple/src/fftools_cmdutils.h | 5 + apple/src/fftools_ffmpeg.c | 57 +++++++--- apple/src/fftools_ffmpeg.h | 6 +- apple/src/fftools_ffmpeg_filter.c | 10 +- apple/src/fftools_ffmpeg_hw.c | 12 ++ apple/src/fftools_ffmpeg_opt.c | 87 ++++++++++++--- apple/src/fftools_ffmpeg_videotoolbox.c | 8 ++ scripts/source.sh | 6 +- 17 files changed, 372 insertions(+), 114 deletions(-) diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.c index 2c6b907..852868f 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.c @@ -70,6 +70,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" #include "libavutil/display.h" #include "libavutil/mathematics.h" #include "libavutil/imgutils.h" @@ -82,6 +83,7 @@ #include "libavutil/cpu.h" #include "libavutil/ffversion.h" #include "libavutil/version.h" +#include "libavcodec/bsf.h" #include "fftools_cmdutils.h" #if HAVE_SYS_RESOURCE_H #include @@ -113,11 +115,6 @@ enum show_muxdemuxers { SHOW_MUXERS, }; -void init_opts(void) -{ - av_dict_set(&sws_dict, "flags", "bicubic", 0); -} - void uninit_opts(void) { av_dict_free(&swr_opts); @@ -708,7 +705,6 @@ static void finish_group(OptionParseContext *octx, int group_idx, resample_opts = NULL; sws_dict = NULL; swr_opts = NULL; - init_opts(); memset(&octx->cur_group, 0, sizeof(octx->cur_group)); } @@ -746,8 +742,6 @@ static void init_parse_context(OptionParseContext *octx, octx->global_opts.group_def = &global_group; octx->global_opts.arg = ""; - - init_opts(); } void uninit_parse_context(OptionParseContext *octx) @@ -899,6 +893,32 @@ int opt_cpuflags(void *optctx, const char *opt, const char *arg) return 0; } +int opt_cpucount(void *optctx, const char *opt, const char *arg) +{ + int ret; + int count; + + static const AVOption opts[] = { + {"count", NULL, 0, AV_OPT_TYPE_INT, { .i64 = -1}, -1, INT_MAX, 0}, + {NULL}, + }; + static const AVClass class = { + .class_name = "cpucount", + .item_name = av_default_item_name, + .option = opts, + .version = LIBAVUTIL_VERSION_INT, + }; + const AVClass *pclass = &class; + + ret = av_opt_eval_int(&pclass, opts, arg, &count); + + if (!ret) { + av_cpu_force_count(count); + } + + return ret; +} + int opt_loglevel(void *optctx, const char *opt, const char *arg) { const struct { const char *name; int level; } log_levels[] = { @@ -929,20 +949,18 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) if (!i && !cmd) { flags = 0; /* missing relative prefix, build absolute value */ } - if (!strncmp(token, "repeat", 6)) { + if (av_strstart(token, "repeat", &arg)) { if (cmd == '-') { flags |= AV_LOG_SKIP_REPEATED; } else { flags &= ~AV_LOG_SKIP_REPEATED; } - arg = token + 6; - } else if (!strncmp(token, "level", 5)) { + } else if (av_strstart(token, "level", &arg)) { if (cmd == '-') { flags &= ~AV_LOG_PRINT_LEVEL; } else { flags |= AV_LOG_PRINT_LEVEL; } - arg = token + 5; } else { break; } diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.h b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.h index ef1d92c..e337ee7 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.h +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_cmdutils.h @@ -115,6 +115,11 @@ void log_callback_help(void* ptr, int level, const char* fmt, va_list vl); */ int opt_cpuflags(void *optctx, const char *opt, const char *arg); +/** + * Override the cpucount. + */ +int opt_cpucount(void *optctx, const char *opt, const char *arg); + /** * Fallback for options that are not explicitly handled, these will be * parsed through AVOptions. diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.c index 62daaa1..12e4e2a 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.c @@ -1275,7 +1275,7 @@ static void do_video_out(OutputFile *of, if (frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); - if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) + if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); if (!ost->filters_script && @@ -1394,6 +1394,7 @@ static void do_video_out(OutputFile *of, } } ost->last_dropped = nb_frames == nb0_frames && next_picture; + ost->dropped_keyframe = ost->last_dropped && next_picture && next_picture->key_frame; /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { @@ -1454,6 +1455,11 @@ static void do_video_out(OutputFile *of, && in_picture->key_frame==1 && !i) { forced_keyframe = 1; + } else if ( ost->forced_keyframes + && !strncmp(ost->forced_keyframes, "source_no_drop", 14) + && !i) { + forced_keyframe = (in_picture->key_frame == 1) || ost->dropped_keyframe; + ost->dropped_keyframe = 0; } if (forced_keyframe) { @@ -2257,9 +2263,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } if (f->recording_time != INT64_MAX) { - start_time = f->ctx->start_time; - if (f->start_time != AV_NOPTS_VALUE && copy_ts) - start_time += f->start_time; + start_time = 0; + if (copy_ts) { + start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; + start_time += start_at_zero ? 0 : f->ctx->start_time; + } if (ist->pts >= f->recording_time + start_time) { close_output_stream(ost); return; @@ -2804,9 +2812,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo avpkt = ist->pkt; if (!ist->saw_first_ts) { + ist->first_dts = ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; ist->pts = 0; if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { + ist->first_dts = ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong } @@ -3139,7 +3149,9 @@ static int init_input_stream(int ist_index, char *error, int error_len) ist->dec_ctx->get_format = get_format; ist->dec_ctx->get_buffer2 = get_buffer; #if LIBAVCODEC_VERSION_MAJOR < 60 +FF_DISABLE_DEPRECATION_WARNINGS ist->dec_ctx->thread_safe_callbacks = 1; +FF_ENABLE_DEPRECATION_WARNINGS #endif if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && @@ -3651,12 +3663,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; } - if (ost->top_field_first == 0) { - enc_ctx->field_order = AV_FIELD_BB; - } else if (ost->top_field_first == 1) { - enc_ctx->field_order = AV_FIELD_TT; - } - + // Field order: autodetection if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) @@ -3671,6 +3678,13 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) enc_ctx->field_order = AV_FIELD_PROGRESSIVE; } + // Field order: override + if (ost->top_field_first == 0) { + enc_ctx->field_order = AV_FIELD_BB; + } else if (ost->top_field_first == 1) { + enc_ctx->field_order = AV_FIELD_TT; + } + if (ost->forced_keyframes) { if (!strncmp(ost->forced_keyframes, "expr:", 5)) { ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, @@ -3934,7 +3948,7 @@ static int transcode_init(void) /* init framerate emulation */ for (i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; - if (ifile->rate_emu) + if (ifile->readrate || ifile->rate_emu) for (j = 0; j < ifile->nb_streams; j++) input_streams[j + ifile->ist_index]->start = av_gettime_relative(); } @@ -4128,10 +4142,10 @@ static OutputStream *choose_output(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - int64_t opts = ost->st->cur_dts == AV_NOPTS_VALUE ? INT64_MIN : - av_rescale_q(ost->st->cur_dts, ost->st->time_base, + int64_t opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN : + av_rescale_q(ost->last_mux_dts, ost->st->time_base, AV_TIME_BASE_Q); - if (ost->st->cur_dts == AV_NOPTS_VALUE) + if (ost->last_mux_dts == AV_NOPTS_VALUE) av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished); @@ -4393,12 +4407,20 @@ static int get_input_packet_mt(InputFile *f, AVPacket **pkt) static int get_input_packet(InputFile *f, AVPacket **pkt) { - if (f->rate_emu) { + if (f->readrate || f->rate_emu) { int i; + int64_t file_start = copy_ts * ( + (f->ctx->start_time != AV_NOPTS_VALUE ? f->ctx->start_time * !start_at_zero : 0) + + (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) + ); + float scale = f->rate_emu ? 1.0 : f->readrate; for (i = 0; i < f->nb_streams; i++) { InputStream *ist = input_streams[f->ist_index + i]; - int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - int64_t now = av_gettime_relative() - ist->start; + int64_t stream_ts_offset, pts, now; + if (!ist->nb_packets || (ist->decoding_needed && !ist->got_output)) continue; + stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); + pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + now = (av_gettime_relative() - ist->start) * scale + stream_ts_offset; if (pts > now) return AVERROR(EAGAIN); } @@ -5225,6 +5247,7 @@ int ffmpeg_execute(int argc, char **argv) { "report", 0, { .func_arg = opt_report }, "generate a report" }, { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, + { "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, #if CONFIG_AVDEVICE diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.h b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.h index 63b3184..34b5b66 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.h +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg.h @@ -54,6 +54,7 @@ #include "libavformat/avio.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" #include "libavfilter/avfilter.h" @@ -83,7 +84,6 @@ enum HWAccelID { HWACCEL_AUTO, HWACCEL_GENERIC, HWACCEL_VIDEOTOOLBOX, - HWACCEL_QSV, }; typedef struct HWAccel { @@ -142,6 +142,7 @@ typedef struct OptionsContext { int64_t input_ts_offset; int loop; int rate_emu; + float readrate; int accurate_seek; int thread_queue_size; @@ -339,6 +340,7 @@ typedef struct InputStream { /* predicted dts of the next packet read for this stream or (when there are * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ int64_t next_dts; + int64_t first_dts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) @@ -440,6 +442,7 @@ typedef struct InputFile { from ctx.nb_streams if new streams appear during av_read_frame() */ int nb_streams_warn; /* number of streams that the user was warned of */ int rate_emu; + float readrate; int accurate_seek; AVPacket *pkt; @@ -526,6 +529,7 @@ typedef struct OutputStream { char *forced_keyframes; AVExpr *forced_keyframes_pexpr; double forced_keyframes_expr_const_values[FKF_NB]; + int dropped_keyframe; /* audio only */ int *audio_channels_map; /* list of the channels id to pick from the source stream */ diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_filter.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_filter.c index 996c1e8..0f25e51 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_filter.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_filter.c @@ -638,7 +638,7 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out); case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out); - default: av_assert0(0); + default: av_assert0(0); return 0; } } @@ -948,7 +948,7 @@ static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); - default: av_assert0(0); + default: av_assert0(0); return 0; } } @@ -987,7 +987,11 @@ int configure_filtergraph(FilterGraph *fg) } if (strlen(args)) args[strlen(args)-1] = 0; - fg->graph->scale_sws_opts = av_strdup(args); + + if (!strncmp(args, "sws_flags=", 10)) { + // keep the 'flags=' part + fg->graph->scale_sws_opts = av_strdup(args+4); + } args[0] = 0; while ((e = av_dict_get(ost->swr_opts, "", e, diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_hw.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_hw.c index 283474c..ee85e8c 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_hw.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_hw.c @@ -348,6 +348,18 @@ int hw_device_setup_for_decode(InputStream *ist) } else if (ist->hwaccel_id == HWACCEL_GENERIC) { type = ist->hwaccel_device_type; dev = hw_device_get_by_type(type); + + // When "-qsv_device device" is used, an internal QSV device named + // as "__qsv_device" is created. Another QSV device is created too + // if "-init_hw_device qsv=name:device" is used. There are 2 QSV devices + // if both "-qsv_device device" and "-init_hw_device qsv=name:device" + // are used, hw_device_get_by_type(AV_HWDEVICE_TYPE_QSV) returns NULL. + // To keep back-compatibility with the removed ad-hoc libmfx setup code, + // call hw_device_get_by_name("__qsv_device") to select the internal QSV + // device. + if (!dev && type == AV_HWDEVICE_TYPE_QSV) + dev = hw_device_get_by_name("__qsv_device"); + if (!dev) err = hw_device_init_from_type(type, NULL, &dev); } else { diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_opt.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_opt.c index c428b40..a188b18 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_opt.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffmpeg_opt.c @@ -45,6 +45,7 @@ #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" #include "libavfilter/avfilter.h" @@ -154,9 +155,6 @@ static const char *const opt_name_enc_time_bases[] = {"enc_time_base" const HWAccel hwaccels[] = { #if CONFIG_VIDEOTOOLBOX { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, -#endif -#if CONFIG_LIBMFX - { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif { 0 }, }; @@ -204,6 +202,7 @@ __thread int input_sync; __thread int input_stream_potentially_available = 0; __thread int ignore_unknown_streams = 0; __thread int copy_unknown_streams = 0; +__thread static int recast_media = 0; __thread int find_stream_info = 1; extern __thread OptionDef *ffmpeg_options; @@ -589,6 +588,23 @@ int opt_vaapi_device(void *optctx, const char *opt, const char *arg) } #endif +#if CONFIG_QSV +static int opt_qsv_device(void *optctx, const char *opt, const char *arg) +{ + const char *prefix = "qsv=__qsv_device:hw_any,child_device="; + int err; + char *tmp = av_asprintf("%s%s", prefix, arg); + + if (!tmp) + return AVERROR(ENOMEM); + + err = hw_device_init_from_string(tmp, NULL); + av_free(tmp); + + return err; +} +#endif + int opt_init_hw_device(void *optctx, const char *opt, const char *arg) { if (!strcmp(arg, "list")) { @@ -779,7 +795,7 @@ const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int en av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); exit_program(1); } - if (codec->type != type) { + if (codec->type != type && !recast_media) { av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); exit_program(1); } @@ -794,6 +810,8 @@ const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *s if (codec_name) { const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); st->codecpar->codec_id = codec->id; + if (recast_media && st->codecpar->codec_type != codec->type) + st->codecpar->codec_type = codec->type; return codec; } else return avcodec_find_decoder(st->codecpar->codec_id); @@ -829,6 +847,7 @@ void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->discard = 1; st->discard = AVDISCARD_ALL; ist->nb_samples = 0; + ist->first_dts = AV_NOPTS_VALUE; ist->min_pts = INT64_MAX; ist->max_pts = INT64_MIN; @@ -913,6 +932,12 @@ void add_input_streams(OptionsContext *o, AVFormatContext *ic) "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); ist->hwaccel_output_format = AV_PIX_FMT_CUDA; + } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { + av_log(NULL, AV_LOG_WARNING, + "WARNING: defaulting hwaccel_output_format to qsv for compatibility " + "with old commandlines. This behaviour is DEPRECATED and will be removed " + "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); + ist->hwaccel_output_format = AV_PIX_FMT_QSV; } else if (hwaccel_output_format) { ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { @@ -1302,6 +1327,17 @@ int open_input_file(OptionsContext *o, const char *filename) f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; + + f->readrate = o->readrate ? o->readrate : 0.0; + if (f->readrate < 0.0f) { + av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", nb_input_files, f->readrate); + exit_program(1); + } + if (f->readrate && f->rate_emu) { + av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", nb_input_files, f->readrate); + f->rate_emu = 0; + } + f->pkt = av_packet_alloc(); if (!f->pkt) exit_program(1); @@ -2264,22 +2300,34 @@ int open_output_file(OptionsContext *o, const char *filename) if (!o->video_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO) != AV_CODEC_ID_NONE) { int best_score = 0, idx = -1; int qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); - for (i = 0; i < nb_input_streams; i++) { - int score; - ist = input_streams[i]; - score = ist->st->codecpar->width * ist->st->codecpar->height + for (j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (i = 0; i < ifile->nb_streams; i++) { + int score; + ist = input_streams[ifile->ist_index + i]; + score = ist->st->codecpar->width * ist->st->codecpar->height + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); - if (ist->user_set_discard == AVDISCARD_ALL) - continue; - if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - score = 1; - if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - score > best_score) { - if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + if (ist->user_set_discard == AVDISCARD_ALL) continue; - best_score = score; - idx = i; + if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + score = 1; + if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + score > file_best_score) { + if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + continue; + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + if((qcr == MKTAG('A', 'P', 'I', 'C')) || !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } } } if (idx >= 0) @@ -2289,18 +2337,29 @@ int open_output_file(OptionsContext *o, const char *filename) /* audio: most channels */ if (!o->audio_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_AUDIO) != AV_CODEC_ID_NONE) { int best_score = 0, idx = -1; - for (i = 0; i < nb_input_streams; i++) { + for (j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (i = 0; i < ifile->nb_streams; i++) { int score; - ist = input_streams[i]; + ist = input_streams[ifile->ist_index + i]; score = ist->st->codecpar->channels + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); if (ist->user_set_discard == AVDISCARD_ALL) continue; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - score > best_score) { - best_score = score; - idx = i; + score > file_best_score) { + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } } } if (idx >= 0) diff --git a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffprobe.c b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffprobe.c index 051e901..fbda484 100644 --- a/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffprobe.c +++ b/android/ffmpeg-kit-android-lib/src/main/cpp/fftools_ffprobe.c @@ -40,6 +40,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" #include "libavutil/display.h" #include "libavutil/hash.h" #include "libavutil/hdr_dynamic_metadata.h" @@ -1688,9 +1689,9 @@ static void xml_print_section_header(WriterContext *wctx) wctx->section[wctx->level-1] : NULL; if (wctx->level == 0) { - const char *qual = " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " - "xmlns:ffprobe='http://www.ffmpeg.org/schema/ffprobe' " - "xsi:schemaLocation='http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd'"; + const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" " + "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\""; av_log(NULL, AV_LOG_STDERR, "\n"); av_log(NULL, AV_LOG_STDERR, "<%sffprobe%s>\n", @@ -2032,7 +2033,7 @@ static void print_pkt_side_data(WriterContext *w, print_int("dv_bl_signal_compatibility_id", dovi->dv_bl_signal_compatibility_id); } else if (sd->type == AV_PKT_DATA_AUDIO_SERVICE_TYPE) { enum AVAudioServiceType *t = (enum AVAudioServiceType *)sd->data; - print_int("type", *t); + print_int("service_type", *t); } else if (sd->type == AV_PKT_DATA_MPEGTS_STREAM_ID) { print_int("id", *sd->data); } else if (sd->type == AV_PKT_DATA_CPB_PROPERTIES) { @@ -2248,8 +2249,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, else print_str_opt("media_type", "unknown"); print_int("stream_index", stream->index); print_int("key_frame", frame->key_frame); - print_ts ("pkt_pts", frame->pts); - print_time("pkt_pts_time", frame->pts, &stream->time_base); + print_ts ("pts", frame->pts); + print_time("pts_time", frame->pts, &stream->time_base); print_ts ("pkt_dts", frame->pkt_dts); print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base); print_ts ("best_effort_timestamp", frame->best_effort_timestamp); @@ -3081,8 +3082,7 @@ static void close_input_file(InputFile *ifile) /* close decoder for each stream */ for (i = 0; i < ifile->nb_streams; i++) - if (ifile->streams[i].st->codecpar->codec_id != AV_CODEC_ID_NONE) - avcodec_free_context(&ifile->streams[i].dec_ctx); + avcodec_free_context(&ifile->streams[i].dec_ctx); av_freep(&ifile->streams); ifile->nb_streams = 0; @@ -3747,6 +3747,7 @@ int ffprobe_execute(int argc, char **argv) { "report", 0, { .func_arg = opt_report }, "generate a report" }, { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, + { "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, #if CONFIG_AVDEVICE @@ -3830,7 +3831,6 @@ int ffprobe_execute(int argc, char **argv) ffprobe_options = options; parse_loglevel(argc, argv, options); avformat_network_init(); - init_opts(); #if CONFIG_AVDEVICE avdevice_register_all(); #endif diff --git a/apple/src/fftools_cmdutils.c b/apple/src/fftools_cmdutils.c index 0c82523..d21cdae 100644 --- a/apple/src/fftools_cmdutils.c +++ b/apple/src/fftools_cmdutils.c @@ -67,6 +67,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" #include "libavutil/display.h" #include "libavutil/mathematics.h" #include "libavutil/imgutils.h" @@ -79,6 +80,7 @@ #include "libavutil/cpu.h" #include "libavutil/ffversion.h" #include "libavutil/version.h" +#include "libavcodec/bsf.h" #include "fftools_cmdutils.h" #if HAVE_SYS_RESOURCE_H #include @@ -110,11 +112,6 @@ enum show_muxdemuxers { SHOW_MUXERS, }; -void init_opts(void) -{ - av_dict_set(&sws_dict, "flags", "bicubic", 0); -} - void uninit_opts(void) { av_dict_free(&swr_opts); @@ -705,7 +702,6 @@ static void finish_group(OptionParseContext *octx, int group_idx, resample_opts = NULL; sws_dict = NULL; swr_opts = NULL; - init_opts(); memset(&octx->cur_group, 0, sizeof(octx->cur_group)); } @@ -743,8 +739,6 @@ static void init_parse_context(OptionParseContext *octx, octx->global_opts.group_def = &global_group; octx->global_opts.arg = ""; - - init_opts(); } void uninit_parse_context(OptionParseContext *octx) @@ -896,6 +890,32 @@ int opt_cpuflags(void *optctx, const char *opt, const char *arg) return 0; } +int opt_cpucount(void *optctx, const char *opt, const char *arg) +{ + int ret; + int count; + + static const AVOption opts[] = { + {"count", NULL, 0, AV_OPT_TYPE_INT, { .i64 = -1}, -1, INT_MAX, 0}, + {NULL}, + }; + static const AVClass class = { + .class_name = "cpucount", + .item_name = av_default_item_name, + .option = opts, + .version = LIBAVUTIL_VERSION_INT, + }; + const AVClass *pclass = &class; + + ret = av_opt_eval_int(&pclass, opts, arg, &count); + + if (!ret) { + av_cpu_force_count(count); + } + + return ret; +} + int opt_loglevel(void *optctx, const char *opt, const char *arg) { const struct { const char *name; int level; } log_levels[] = { @@ -926,20 +946,18 @@ int opt_loglevel(void *optctx, const char *opt, const char *arg) if (!i && !cmd) { flags = 0; /* missing relative prefix, build absolute value */ } - if (!strncmp(token, "repeat", 6)) { + if (av_strstart(token, "repeat", &arg)) { if (cmd == '-') { flags |= AV_LOG_SKIP_REPEATED; } else { flags &= ~AV_LOG_SKIP_REPEATED; } - arg = token + 6; - } else if (!strncmp(token, "level", 5)) { + } else if (av_strstart(token, "level", &arg)) { if (cmd == '-') { flags &= ~AV_LOG_PRINT_LEVEL; } else { flags |= AV_LOG_PRINT_LEVEL; } - arg = token + 5; } else { break; } diff --git a/apple/src/fftools_cmdutils.h b/apple/src/fftools_cmdutils.h index ef1d92c..e337ee7 100644 --- a/apple/src/fftools_cmdutils.h +++ b/apple/src/fftools_cmdutils.h @@ -115,6 +115,11 @@ void log_callback_help(void* ptr, int level, const char* fmt, va_list vl); */ int opt_cpuflags(void *optctx, const char *opt, const char *arg); +/** + * Override the cpucount. + */ +int opt_cpucount(void *optctx, const char *opt, const char *arg); + /** * Fallback for options that are not explicitly handled, these will be * parsed through AVOptions. diff --git a/apple/src/fftools_ffmpeg.c b/apple/src/fftools_ffmpeg.c index 964abb3..659fd01 100644 --- a/apple/src/fftools_ffmpeg.c +++ b/apple/src/fftools_ffmpeg.c @@ -1272,7 +1272,7 @@ static void do_video_out(OutputFile *of, if (frame_rate.num > 0 && frame_rate.den > 0) duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base)); - if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) + if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num) duration = FFMIN(duration, 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base))); if (!ost->filters_script && @@ -1391,6 +1391,7 @@ static void do_video_out(OutputFile *of, } } ost->last_dropped = nb_frames == nb0_frames && next_picture; + ost->dropped_keyframe = ost->last_dropped && next_picture && next_picture->key_frame; /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { @@ -1451,6 +1452,11 @@ static void do_video_out(OutputFile *of, && in_picture->key_frame==1 && !i) { forced_keyframe = 1; + } else if ( ost->forced_keyframes + && !strncmp(ost->forced_keyframes, "source_no_drop", 14) + && !i) { + forced_keyframe = (in_picture->key_frame == 1) || ost->dropped_keyframe; + ost->dropped_keyframe = 0; } if (forced_keyframe) { @@ -2254,9 +2260,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } if (f->recording_time != INT64_MAX) { - start_time = f->ctx->start_time; - if (f->start_time != AV_NOPTS_VALUE && copy_ts) - start_time += f->start_time; + start_time = 0; + if (copy_ts) { + start_time += f->start_time != AV_NOPTS_VALUE ? f->start_time : 0; + start_time += start_at_zero ? 0 : f->ctx->start_time; + } if (ist->pts >= f->recording_time + start_time) { close_output_stream(ost); return; @@ -2801,9 +2809,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo avpkt = ist->pkt; if (!ist->saw_first_ts) { + ist->first_dts = ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; ist->pts = 0; if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) { + ist->first_dts = ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong } @@ -3136,7 +3146,9 @@ static int init_input_stream(int ist_index, char *error, int error_len) ist->dec_ctx->get_format = get_format; ist->dec_ctx->get_buffer2 = get_buffer; #if LIBAVCODEC_VERSION_MAJOR < 60 +FF_DISABLE_DEPRECATION_WARNINGS ist->dec_ctx->thread_safe_callbacks = 1; +FF_ENABLE_DEPRECATION_WARNINGS #endif if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && @@ -3648,12 +3660,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; } - if (ost->top_field_first == 0) { - enc_ctx->field_order = AV_FIELD_BB; - } else if (ost->top_field_first == 1) { - enc_ctx->field_order = AV_FIELD_TT; - } - + // Field order: autodetection if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) @@ -3668,6 +3675,13 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) enc_ctx->field_order = AV_FIELD_PROGRESSIVE; } + // Field order: override + if (ost->top_field_first == 0) { + enc_ctx->field_order = AV_FIELD_BB; + } else if (ost->top_field_first == 1) { + enc_ctx->field_order = AV_FIELD_TT; + } + if (ost->forced_keyframes) { if (!strncmp(ost->forced_keyframes, "expr:", 5)) { ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, @@ -3931,7 +3945,7 @@ static int transcode_init(void) /* init framerate emulation */ for (i = 0; i < nb_input_files; i++) { InputFile *ifile = input_files[i]; - if (ifile->rate_emu) + if (ifile->readrate || ifile->rate_emu) for (j = 0; j < ifile->nb_streams; j++) input_streams[j + ifile->ist_index]->start = av_gettime_relative(); } @@ -4125,10 +4139,10 @@ static OutputStream *choose_output(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - int64_t opts = ost->st->cur_dts == AV_NOPTS_VALUE ? INT64_MIN : - av_rescale_q(ost->st->cur_dts, ost->st->time_base, + int64_t opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN : + av_rescale_q(ost->last_mux_dts, ost->st->time_base, AV_TIME_BASE_Q); - if (ost->st->cur_dts == AV_NOPTS_VALUE) + if (ost->last_mux_dts == AV_NOPTS_VALUE) av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n", ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished); @@ -4390,12 +4404,20 @@ static int get_input_packet_mt(InputFile *f, AVPacket **pkt) static int get_input_packet(InputFile *f, AVPacket **pkt) { - if (f->rate_emu) { + if (f->readrate || f->rate_emu) { int i; + int64_t file_start = copy_ts * ( + (f->ctx->start_time != AV_NOPTS_VALUE ? f->ctx->start_time * !start_at_zero : 0) + + (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0) + ); + float scale = f->rate_emu ? 1.0 : f->readrate; for (i = 0; i < f->nb_streams; i++) { InputStream *ist = input_streams[f->ist_index + i]; - int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); - int64_t now = av_gettime_relative() - ist->start; + int64_t stream_ts_offset, pts, now; + if (!ist->nb_packets || (ist->decoding_needed && !ist->got_output)) continue; + stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start); + pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE); + now = (av_gettime_relative() - ist->start) * scale + stream_ts_offset; if (pts > now) return AVERROR(EAGAIN); } @@ -5222,6 +5244,7 @@ int ffmpeg_execute(int argc, char **argv) { "report", 0, { .func_arg = opt_report }, "generate a report" }, { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, + { "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, #if CONFIG_AVDEVICE diff --git a/apple/src/fftools_ffmpeg.h b/apple/src/fftools_ffmpeg.h index 63b3184..34b5b66 100644 --- a/apple/src/fftools_ffmpeg.h +++ b/apple/src/fftools_ffmpeg.h @@ -54,6 +54,7 @@ #include "libavformat/avio.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" #include "libavfilter/avfilter.h" @@ -83,7 +84,6 @@ enum HWAccelID { HWACCEL_AUTO, HWACCEL_GENERIC, HWACCEL_VIDEOTOOLBOX, - HWACCEL_QSV, }; typedef struct HWAccel { @@ -142,6 +142,7 @@ typedef struct OptionsContext { int64_t input_ts_offset; int loop; int rate_emu; + float readrate; int accurate_seek; int thread_queue_size; @@ -339,6 +340,7 @@ typedef struct InputStream { /* predicted dts of the next packet read for this stream or (when there are * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ int64_t next_dts; + int64_t first_dts; ///< dts of the first packet read for this stream (in AV_TIME_BASE units) int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) @@ -440,6 +442,7 @@ typedef struct InputFile { from ctx.nb_streams if new streams appear during av_read_frame() */ int nb_streams_warn; /* number of streams that the user was warned of */ int rate_emu; + float readrate; int accurate_seek; AVPacket *pkt; @@ -526,6 +529,7 @@ typedef struct OutputStream { char *forced_keyframes; AVExpr *forced_keyframes_pexpr; double forced_keyframes_expr_const_values[FKF_NB]; + int dropped_keyframe; /* audio only */ int *audio_channels_map; /* list of the channels id to pick from the source stream */ diff --git a/apple/src/fftools_ffmpeg_filter.c b/apple/src/fftools_ffmpeg_filter.c index d525062..06a8409 100644 --- a/apple/src/fftools_ffmpeg_filter.c +++ b/apple/src/fftools_ffmpeg_filter.c @@ -636,7 +636,7 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out); case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out); - default: av_assert0(0); + default: av_assert0(0); return 0; } } @@ -946,7 +946,7 @@ static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); - default: av_assert0(0); + default: av_assert0(0); return 0; } } @@ -985,7 +985,11 @@ int configure_filtergraph(FilterGraph *fg) } if (strlen(args)) args[strlen(args)-1] = 0; - fg->graph->scale_sws_opts = av_strdup(args); + + if (!strncmp(args, "sws_flags=", 10)) { + // keep the 'flags=' part + fg->graph->scale_sws_opts = av_strdup(args+4); + } args[0] = 0; while ((e = av_dict_get(ost->swr_opts, "", e, diff --git a/apple/src/fftools_ffmpeg_hw.c b/apple/src/fftools_ffmpeg_hw.c index 283474c..ee85e8c 100644 --- a/apple/src/fftools_ffmpeg_hw.c +++ b/apple/src/fftools_ffmpeg_hw.c @@ -348,6 +348,18 @@ int hw_device_setup_for_decode(InputStream *ist) } else if (ist->hwaccel_id == HWACCEL_GENERIC) { type = ist->hwaccel_device_type; dev = hw_device_get_by_type(type); + + // When "-qsv_device device" is used, an internal QSV device named + // as "__qsv_device" is created. Another QSV device is created too + // if "-init_hw_device qsv=name:device" is used. There are 2 QSV devices + // if both "-qsv_device device" and "-init_hw_device qsv=name:device" + // are used, hw_device_get_by_type(AV_HWDEVICE_TYPE_QSV) returns NULL. + // To keep back-compatibility with the removed ad-hoc libmfx setup code, + // call hw_device_get_by_name("__qsv_device") to select the internal QSV + // device. + if (!dev && type == AV_HWDEVICE_TYPE_QSV) + dev = hw_device_get_by_name("__qsv_device"); + if (!dev) err = hw_device_init_from_type(type, NULL, &dev); } else { diff --git a/apple/src/fftools_ffmpeg_opt.c b/apple/src/fftools_ffmpeg_opt.c index 98bcda3..f29df66 100644 --- a/apple/src/fftools_ffmpeg_opt.c +++ b/apple/src/fftools_ffmpeg_opt.c @@ -42,6 +42,7 @@ #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" #include "libavfilter/avfilter.h" @@ -151,9 +152,6 @@ static const char *const opt_name_enc_time_bases[] = {"enc_time_base" const HWAccel hwaccels[] = { #if CONFIG_VIDEOTOOLBOX { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, -#endif -#if CONFIG_LIBMFX - { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif { 0 }, }; @@ -201,6 +199,7 @@ __thread int input_sync; __thread int input_stream_potentially_available = 0; __thread int ignore_unknown_streams = 0; __thread int copy_unknown_streams = 0; +__thread static int recast_media = 0; __thread int find_stream_info = 1; extern __thread OptionDef *ffmpeg_options; @@ -586,6 +585,23 @@ int opt_vaapi_device(void *optctx, const char *opt, const char *arg) } #endif +#if CONFIG_QSV +static int opt_qsv_device(void *optctx, const char *opt, const char *arg) +{ + const char *prefix = "qsv=__qsv_device:hw_any,child_device="; + int err; + char *tmp = av_asprintf("%s%s", prefix, arg); + + if (!tmp) + return AVERROR(ENOMEM); + + err = hw_device_init_from_string(tmp, NULL); + av_free(tmp); + + return err; +} +#endif + int opt_init_hw_device(void *optctx, const char *opt, const char *arg) { if (!strcmp(arg, "list")) { @@ -776,7 +792,7 @@ const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int en av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); exit_program(1); } - if (codec->type != type) { + if (codec->type != type && !recast_media) { av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); exit_program(1); } @@ -791,6 +807,8 @@ const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *s if (codec_name) { const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); st->codecpar->codec_id = codec->id; + if (recast_media && st->codecpar->codec_type != codec->type) + st->codecpar->codec_type = codec->type; return codec; } else return avcodec_find_decoder(st->codecpar->codec_id); @@ -826,6 +844,7 @@ void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->discard = 1; st->discard = AVDISCARD_ALL; ist->nb_samples = 0; + ist->first_dts = AV_NOPTS_VALUE; ist->min_pts = INT64_MAX; ist->max_pts = INT64_MIN; @@ -910,6 +929,12 @@ void add_input_streams(OptionsContext *o, AVFormatContext *ic) "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); ist->hwaccel_output_format = AV_PIX_FMT_CUDA; + } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { + av_log(NULL, AV_LOG_WARNING, + "WARNING: defaulting hwaccel_output_format to qsv for compatibility " + "with old commandlines. This behaviour is DEPRECATED and will be removed " + "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); + ist->hwaccel_output_format = AV_PIX_FMT_QSV; } else if (hwaccel_output_format) { ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { @@ -1299,6 +1324,17 @@ int open_input_file(OptionsContext *o, const char *filename) f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; + + f->readrate = o->readrate ? o->readrate : 0.0; + if (f->readrate < 0.0f) { + av_log(NULL, AV_LOG_ERROR, "Option -readrate for Input #%d is %0.3f; it must be non-negative.\n", nb_input_files, f->readrate); + exit_program(1); + } + if (f->readrate && f->rate_emu) { + av_log(NULL, AV_LOG_WARNING, "Both -readrate and -re set for Input #%d. Using -readrate %0.3f.\n", nb_input_files, f->readrate); + f->rate_emu = 0; + } + f->pkt = av_packet_alloc(); if (!f->pkt) exit_program(1); @@ -2261,9 +2297,12 @@ int open_output_file(OptionsContext *o, const char *filename) if (!o->video_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO) != AV_CODEC_ID_NONE) { int best_score = 0, idx = -1; int qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); - for (i = 0; i < nb_input_streams; i++) { + for (j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (i = 0; i < ifile->nb_streams; i++) { int score; - ist = input_streams[i]; + ist = input_streams[ifile->ist_index + i]; score = ist->st->codecpar->width * ist->st->codecpar->height + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); @@ -2272,11 +2311,20 @@ int open_output_file(OptionsContext *o, const char *filename) if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) score = 1; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - score > best_score) { + score > file_best_score) { if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) continue; - best_score = score; - idx = i; + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + if((qcr == MKTAG('A', 'P', 'I', 'C')) || !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } } } if (idx >= 0) @@ -2286,18 +2334,29 @@ int open_output_file(OptionsContext *o, const char *filename) /* audio: most channels */ if (!o->audio_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_AUDIO) != AV_CODEC_ID_NONE) { int best_score = 0, idx = -1; - for (i = 0; i < nb_input_streams; i++) { + for (j = 0; j < nb_input_files; j++) { + InputFile *ifile = input_files[j]; + int file_best_score = 0, file_best_idx = -1; + for (i = 0; i < ifile->nb_streams; i++) { int score; - ist = input_streams[i]; + ist = input_streams[ifile->ist_index + i]; score = ist->st->codecpar->channels + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); if (ist->user_set_discard == AVDISCARD_ALL) continue; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - score > best_score) { - best_score = score; - idx = i; + score > file_best_score) { + file_best_score = score; + file_best_idx = ifile->ist_index + i; + } + } + if (file_best_idx >= 0) { + file_best_score -= 5000000*!!(input_streams[file_best_idx]->st->disposition & AV_DISPOSITION_DEFAULT); + if (file_best_score > best_score) { + best_score = file_best_score; + idx = file_best_idx; + } } } if (idx >= 0) diff --git a/apple/src/fftools_ffmpeg_videotoolbox.c b/apple/src/fftools_ffmpeg_videotoolbox.c index e8e709f..1eb9421 100644 --- a/apple/src/fftools_ffmpeg_videotoolbox.c +++ b/apple/src/fftools_ffmpeg_videotoolbox.c @@ -29,6 +29,7 @@ typedef struct VTContext { AVFrame *tmp_frame; + int log_once; } VTContext; __thread char *videotoolbox_pixfmt; @@ -44,6 +45,13 @@ static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame) int linesize[4] = { 0 }; int planes, ret, i; + if (frame->format == ist->hwaccel_output_format) { + av_log_once(s, AV_LOG_INFO, AV_LOG_TRACE, &vt->log_once, + "There is no video filter for videotoolbox pix_fmt now, remove the " + "-hwaccel_output_format option if video filter doesn't work\n"); + return 0; + } + av_frame_unref(vt->tmp_frame); switch (pixel_format) { diff --git a/scripts/source.sh b/scripts/source.sh index af5586d..d38bfbc 100755 --- a/scripts/source.sh +++ b/scripts/source.sh @@ -8,7 +8,7 @@ get_library_source() { case $1 in config) SOURCE_REPO_URL="https://github.com/tanersener/gnu-config" - SOURCE_ID="v20201222" + SOURCE_ID="v20210814" SOURCE_TYPE="TAG" ;; chromaprint) @@ -33,9 +33,9 @@ get_library_source() { ;; ffmpeg) SOURCE_REPO_URL="https://github.com/tanersener/FFmpeg" - SOURCE_ID="c9a79532e5ec4ea265d3a82f185fca6e196088c2" + SOURCE_ID="acd3c101ef4b84aac9c608bfe6ab22431529c48f" SOURCE_TYPE="COMMIT" - SOURCE_GIT_DESCRIBE="n4.5-dev-899-gc9a79532e5" # git describe --tags + SOURCE_GIT_DESCRIBE="n4.5-dev-1598-gacd3c101ef" # git describe --tags ;; fontconfig) SOURCE_REPO_URL="https://github.com/tanersener/fontconfig"