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 9520fd6..52aa881 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 @@ -1006,10 +1006,10 @@ static void output_packet(OutputFile *of, AVPacket *pkt, /* apply the output bitstream filters */ if (ost->bsf_ctx) { ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt); - if (ret < 0) - goto finish; + if (ret < 0) + goto finish; while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0) - write_packet(of, pkt, ost, 0); + write_packet(of, pkt, ost, 0); if (ret == AVERROR(EAGAIN)) ret = 0; } else if (!eof) @@ -1396,8 +1396,8 @@ static void do_video_out(OutputFile *of, /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { AVFrame *in_picture; - int forced_keyframe = 0; - double pts_time; + int forced_keyframe = 0; + double pts_time; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; @@ -3556,7 +3556,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->frame_rate = ist->framerate; if (ist && !ost->frame_rate.num) ost->frame_rate = ist->st->r_frame_rate; - if (ist && !ost->frame_rate.num) { + if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; av_log(NULL, AV_LOG_WARNING, "No information " @@ -3566,6 +3566,11 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->file_index, ost->index); } + if (ost->max_frame_rate.num && + (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || + !ost->frame_rate.den)) + ost->frame_rate = ost->max_frame_rate; + if (ost->enc->supported_framerates && !ost->force_fps) { int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; 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 599d7c7..e94af10 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 @@ -131,6 +131,8 @@ typedef struct OptionsContext { int nb_audio_sample_rate; SpecifierOpt *frame_rates; int nb_frame_rates; + SpecifierOpt *max_frame_rates; + int nb_max_frame_rates; SpecifierOpt *frame_sizes; int nb_frame_sizes; SpecifierOpt *frame_pix_fmts; @@ -502,6 +504,7 @@ typedef struct OutputStream { /* video only */ AVRational frame_rate; + AVRational max_frame_rate; int is_cfr; int force_fps; int top_field_first; 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 70a4e98..41d1dbe 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 @@ -648,13 +648,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if (audio_volume != 256 && 0) { - char args[256]; - - snprintf(args, sizeof(args), "%f", audio_volume / 256.); - AUTO_INSERT_FILTER("-vol", "volume", args); - } - if (ost->apad && of->shortest) { char args[256]; int i; @@ -1213,15 +1206,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) return 0; } -int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) -{ - int i; - for (i = 0; i < fg->nb_inputs; i++) - if (fg->inputs[i]->ist == ist) - return 1; - return 0; -} - int filtergraph_is_simple(FilterGraph *fg) { return !fg->graph_desc; 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 5618a96..b0ebcb8 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 @@ -73,6 +73,7 @@ static const char *const opt_name_codec_names[] = {"c", "codec", " static const char *const opt_name_audio_channels[] = {"ac", NULL}; static const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; static const char *const opt_name_frame_rates[] = {"r", NULL}; +static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; static const char *const opt_name_frame_sizes[] = {"s", NULL}; static const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL}; static const char *const opt_name_ts_scale[] = {"itsscale", NULL}; @@ -1708,7 +1709,7 @@ OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int sourc AVStream *st; OutputStream *ost; AVCodecContext *video_enc; - char *frame_rate = NULL, *frame_aspect_ratio = NULL; + char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; @@ -1719,8 +1720,21 @@ OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int sourc 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(max_frame_rates, str, max_frame_rate, oc, st); + if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); + exit_program(1); + } + + if (frame_rate && max_frame_rate) { + av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); + exit_program(1); + } + + if ((frame_rate || max_frame_rate) && + video_sync_method == VSYNC_PASSTHROUGH) + av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r/-fpsmax can produce invalid output files\n"); MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) { @@ -2661,6 +2675,9 @@ loop_end: if(o->recording_time != INT64_MAX) av_dict_set(&oc->metadata, "duration", NULL, 0); av_dict_set(&oc->metadata, "creation_time", NULL, 0); + av_dict_set(&oc->metadata, "company_name", NULL, 0); + av_dict_set(&oc->metadata, "product_name", NULL, 0); + av_dict_set(&oc->metadata, "product_version", NULL, 0); } if (!o->metadata_streams_manual) for (i = of->ost_index; i < nb_output_streams; i++) { diff --git a/apple/src/fftools_ffmpeg.c b/apple/src/fftools_ffmpeg.c index ae221ae..e71211d 100644 --- a/apple/src/fftools_ffmpeg.c +++ b/apple/src/fftools_ffmpeg.c @@ -3553,7 +3553,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->frame_rate = ist->framerate; if (ist && !ost->frame_rate.num) ost->frame_rate = ist->st->r_frame_rate; - if (ist && !ost->frame_rate.num) { + if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; av_log(NULL, AV_LOG_WARNING, "No information " @@ -3563,6 +3563,11 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->file_index, ost->index); } + if (ost->max_frame_rate.num && + (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || + !ost->frame_rate.den)) + ost->frame_rate = ost->max_frame_rate; + if (ost->enc->supported_framerates && !ost->force_fps) { int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; diff --git a/apple/src/fftools_ffmpeg.h b/apple/src/fftools_ffmpeg.h index 599d7c7..e94af10 100644 --- a/apple/src/fftools_ffmpeg.h +++ b/apple/src/fftools_ffmpeg.h @@ -131,6 +131,8 @@ typedef struct OptionsContext { int nb_audio_sample_rate; SpecifierOpt *frame_rates; int nb_frame_rates; + SpecifierOpt *max_frame_rates; + int nb_max_frame_rates; SpecifierOpt *frame_sizes; int nb_frame_sizes; SpecifierOpt *frame_pix_fmts; @@ -502,6 +504,7 @@ typedef struct OutputStream { /* video only */ AVRational frame_rate; + AVRational max_frame_rate; int is_cfr; int force_fps; int top_field_first; diff --git a/apple/src/fftools_ffmpeg_filter.c b/apple/src/fftools_ffmpeg_filter.c index 70a4e98..41d1dbe 100644 --- a/apple/src/fftools_ffmpeg_filter.c +++ b/apple/src/fftools_ffmpeg_filter.c @@ -648,13 +648,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if (audio_volume != 256 && 0) { - char args[256]; - - snprintf(args, sizeof(args), "%f", audio_volume / 256.); - AUTO_INSERT_FILTER("-vol", "volume", args); - } - if (ost->apad && of->shortest) { char args[256]; int i; @@ -1213,15 +1206,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) return 0; } -int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) -{ - int i; - for (i = 0; i < fg->nb_inputs; i++) - if (fg->inputs[i]->ist == ist) - return 1; - return 0; -} - int filtergraph_is_simple(FilterGraph *fg) { return !fg->graph_desc; diff --git a/apple/src/fftools_ffmpeg_opt.c b/apple/src/fftools_ffmpeg_opt.c index de7c497..4cb32f5 100644 --- a/apple/src/fftools_ffmpeg_opt.c +++ b/apple/src/fftools_ffmpeg_opt.c @@ -70,6 +70,7 @@ static const char *const opt_name_codec_names[] = {"c", "codec", " static const char *const opt_name_audio_channels[] = {"ac", NULL}; static const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; static const char *const opt_name_frame_rates[] = {"r", NULL}; +static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; static const char *const opt_name_frame_sizes[] = {"s", NULL}; static const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL}; static const char *const opt_name_ts_scale[] = {"itsscale", NULL}; @@ -1705,7 +1706,7 @@ OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int sourc AVStream *st; OutputStream *ost; AVCodecContext *video_enc; - char *frame_rate = NULL, *frame_aspect_ratio = NULL; + char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; @@ -1716,8 +1717,21 @@ OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int sourc 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(max_frame_rates, str, max_frame_rate, oc, st); + if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); + exit_program(1); + } + + if (frame_rate && max_frame_rate) { + av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); + exit_program(1); + } + + if ((frame_rate || max_frame_rate) && + video_sync_method == VSYNC_PASSTHROUGH) + av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r/-fpsmax can produce invalid output files\n"); MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) { @@ -2658,6 +2672,9 @@ loop_end: if(o->recording_time != INT64_MAX) av_dict_set(&oc->metadata, "duration", NULL, 0); av_dict_set(&oc->metadata, "creation_time", NULL, 0); + av_dict_set(&oc->metadata, "company_name", NULL, 0); + av_dict_set(&oc->metadata, "product_name", NULL, 0); + av_dict_set(&oc->metadata, "product_version", NULL, 0); } if (!o->metadata_streams_manual) for (i = of->ost_index; i < nb_output_streams; i++) { diff --git a/scripts/source.sh b/scripts/source.sh index c75d4da..4acf747 100755 --- a/scripts/source.sh +++ b/scripts/source.sh @@ -33,9 +33,9 @@ get_library_source() { ;; ffmpeg) SOURCE_REPO_URL="https://github.com/tanersener/FFmpeg" - SOURCE_ID="9f38fac053010205806ece11e6aea9b7d3bde041" + SOURCE_ID="c0d0b1c4f6f804796488adf3e552be88c0cee1a4" SOURCE_TYPE="COMMIT" - SOURCE_GIT_DESCRIBE="n4.4-dev-2765-g9f38fac053" # git describe --tags + SOURCE_GIT_DESCRIBE="n4.4-dev-3015-gc0d0b1c4f6" # git describe --tags ;; fontconfig) SOURCE_REPO_URL="https://github.com/tanersener/fontconfig"