From fd9ee206a5ca3eb2a5e04c5e630779f796e0499e Mon Sep 17 00:00:00 2001 From: "huangzhe.huang" Date: Mon, 25 Nov 2024 21:00:57 +0800 Subject: [PATCH 1/4] [fix] filter: add args modify --- .../bytedeco/javacv/FFmpegFrameFilter.java | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java index f42226ef..98bdcfe7 100644 --- a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java @@ -54,7 +54,9 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; +import java.util.Arrays; import java.util.Locale; + import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.DoublePointer; import org.bytedeco.javacpp.FloatPointer; @@ -90,6 +92,13 @@ public static class Exception extends FrameFilter.Exception { public Exception(String message, Throwable cause) { super(message, cause); } } + public static interface InputArgsGenerate { + public String generateArgs(int i,Object[] argCopy,String template); + } + + private InputArgsGenerate videoInputArgsGenerate; + private InputArgsGenerate audioInputArgsGenerate; + private static Exception loadingException = null; public static void tryLoad() throws Exception { if (loadingException != null) { @@ -342,16 +351,22 @@ private void startVideoUnsafe() throws Exception { /* buffer video source: the decoded frames from the decoder will be inserted here. */ AVRational r = av_d2q(aspectRatio > 0 ? aspectRatio : 1, 255); - String args = String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d", - imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den()); + Object[] argList=new Object[]{imageWidth,imageHeight,pixelFormat,time_base.num(),time_base.den(),r.num(), r.den(), frame_rate.num(), frame_rate.den()}; + String argsTemplate="video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d"; + String args = String.format(Locale.ROOT, argsTemplate, argList); + buffersrc_ctx = new AVFilterContext[videoInputs]; setpts_ctx = new AVFilterContext[videoInputs]; for (int i = 0; i < videoInputs; i++) { String name = videoInputs > 1 ? i + ":v" : "in"; outputs[i] = avfilter_inout_alloc(); + String realArgs=args; + if (this.videoInputArgsGenerate!=null){ + realArgs=this.videoInputArgsGenerate.generateArgs(i, Arrays.copyOf(argList,argList.length),argsTemplate); + } ret = avfilter_graph_create_filter(buffersrc_ctx[i] = new AVFilterContext().retainReference(), buffersrc, name, - args, null, filter_graph); + realArgs, null, filter_graph); if (ret < 0) { throw new Exception("avfilter_graph_create_filter() error " + ret + ": Cannot create video buffer source."); } @@ -441,14 +456,20 @@ private void startAudioUnsafe() throws Exception { abuffersrc_ctx = new AVFilterContext[audioInputs]; asetpts_ctx = new AVFilterContext[audioInputs]; + String argsTemplate="channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d"; for (int i = 0; i < audioInputs; i++) { String name = audioInputs > 1 ? i + ":a" : "in"; aoutputs[i] = avfilter_inout_alloc(); /* buffer audio source: the decoded frames from the decoder will be inserted here. */ av_channel_layout_default(default_layout, audioChannels); - String aargs = String.format(Locale.ROOT, "channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d", - audioChannels, sampleFormat, sampleRate, default_layout.u_mask()); + Object[] argList=new Object[]{audioChannels, sampleFormat, sampleRate, default_layout.u_mask()}; + String aargs = String.format(Locale.ROOT,argsTemplate,argList); + + if (this.audioInputArgsGenerate!=null){ + aargs=this.audioInputArgsGenerate.generateArgs(i,Arrays.copyOf(argList,argList.length),argsTemplate); + } + ret = avfilter_graph_create_filter(abuffersrc_ctx[i] = new AVFilterContext().retainReference(), abuffersrc, name, aargs, null, afilter_graph); if (ret < 0) { @@ -815,4 +836,12 @@ public synchronized Frame pullSamples() throws Exception { } } + + public void setVideoInputArgsGenerate(InputArgsGenerate videoInputArgsGenerate) { + this.videoInputArgsGenerate = videoInputArgsGenerate; + } + + public void setAudioInputArgsGenerate(InputArgsGenerate audioInputArgsGenerate) { + this.audioInputArgsGenerate = audioInputArgsGenerate; + } } From a5912584ca563c263c3283e94844e3dbcdf8ad25 Mon Sep 17 00:00:00 2001 From: fastZhe <526910607@qq.com> Date: Tue, 26 Nov 2024 10:46:10 +0800 Subject: [PATCH 2/4] [feat] filter: add input args property --- .../bytedeco/javacv/FFmpegFrameFilter.java | 46 +++++-------------- .../java/org/bytedeco/javacv/FrameFilter.java | 18 ++++++++ 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java index 98bdcfe7..332e0764 100644 --- a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java @@ -54,9 +54,7 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; -import java.util.Arrays; import java.util.Locale; - import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.DoublePointer; import org.bytedeco.javacpp.FloatPointer; @@ -92,13 +90,6 @@ public static class Exception extends FrameFilter.Exception { public Exception(String message, Throwable cause) { super(message, cause); } } - public static interface InputArgsGenerate { - public String generateArgs(int i,Object[] argCopy,String template); - } - - private InputArgsGenerate videoInputArgsGenerate; - private InputArgsGenerate audioInputArgsGenerate; - private static Exception loadingException = null; public static void tryLoad() throws Exception { if (loadingException != null) { @@ -317,6 +308,12 @@ public synchronized void startUnsafe() throws Exception { frame = new Frame(); default_layout = new AVChannelLayout().retainReference(); + if (videoFilterArgs!=null && videoInputs!=videoFilterArgs.length){ + throw new Exception("The length of videoFilterArgs is different from videoInputs"); + } + if (audioFilterArgs!=null && audioInputs!=audioFilterArgs.length){ + throw new Exception("The length of audioFilterArgs is different from audioInputs"); + } if (image_frame == null || samples_frame == null || filt_frame == null) { throw new Exception("Could not allocate frames"); } @@ -351,22 +348,17 @@ private void startVideoUnsafe() throws Exception { /* buffer video source: the decoded frames from the decoder will be inserted here. */ AVRational r = av_d2q(aspectRatio > 0 ? aspectRatio : 1, 255); - Object[] argList=new Object[]{imageWidth,imageHeight,pixelFormat,time_base.num(),time_base.den(),r.num(), r.den(), frame_rate.num(), frame_rate.den()}; - String argsTemplate="video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d"; - String args = String.format(Locale.ROOT, argsTemplate, argList); - + String argsBase = String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d", + imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den()); buffersrc_ctx = new AVFilterContext[videoInputs]; setpts_ctx = new AVFilterContext[videoInputs]; for (int i = 0; i < videoInputs; i++) { String name = videoInputs > 1 ? i + ":v" : "in"; outputs[i] = avfilter_inout_alloc(); - String realArgs=args; - if (this.videoInputArgsGenerate!=null){ - realArgs=this.videoInputArgsGenerate.generateArgs(i, Arrays.copyOf(argList,argList.length),argsTemplate); - } + String args=videoFilterArgs!=null && videoFilterArgs[i]!=null ? videoFilterArgs[i]:argsBase; ret = avfilter_graph_create_filter(buffersrc_ctx[i] = new AVFilterContext().retainReference(), buffersrc, name, - realArgs, null, filter_graph); + args, null, filter_graph); if (ret < 0) { throw new Exception("avfilter_graph_create_filter() error " + ret + ": Cannot create video buffer source."); } @@ -456,20 +448,14 @@ private void startAudioUnsafe() throws Exception { abuffersrc_ctx = new AVFilterContext[audioInputs]; asetpts_ctx = new AVFilterContext[audioInputs]; - String argsTemplate="channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d"; for (int i = 0; i < audioInputs; i++) { String name = audioInputs > 1 ? i + ":a" : "in"; aoutputs[i] = avfilter_inout_alloc(); /* buffer audio source: the decoded frames from the decoder will be inserted here. */ av_channel_layout_default(default_layout, audioChannels); - Object[] argList=new Object[]{audioChannels, sampleFormat, sampleRate, default_layout.u_mask()}; - String aargs = String.format(Locale.ROOT,argsTemplate,argList); - - if (this.audioInputArgsGenerate!=null){ - aargs=this.audioInputArgsGenerate.generateArgs(i,Arrays.copyOf(argList,argList.length),argsTemplate); - } - + String aargs = audioFilterArgs!=null && audioFilterArgs[i]!=null ?audioFilterArgs[i]:String.format(Locale.ROOT, "channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d", + audioChannels, sampleFormat, sampleRate, default_layout.u_mask()); ret = avfilter_graph_create_filter(abuffersrc_ctx[i] = new AVFilterContext().retainReference(), abuffersrc, name, aargs, null, afilter_graph); if (ret < 0) { @@ -836,12 +822,4 @@ public synchronized Frame pullSamples() throws Exception { } } - - public void setVideoInputArgsGenerate(InputArgsGenerate videoInputArgsGenerate) { - this.videoInputArgsGenerate = videoInputArgsGenerate; - } - - public void setAudioInputArgsGenerate(InputArgsGenerate audioInputArgsGenerate) { - this.audioInputArgsGenerate = audioInputArgsGenerate; - } } diff --git a/src/main/java/org/bytedeco/javacv/FrameFilter.java b/src/main/java/org/bytedeco/javacv/FrameFilter.java index b655a249..27156a77 100644 --- a/src/main/java/org/bytedeco/javacv/FrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FrameFilter.java @@ -49,6 +49,8 @@ public static FrameFilter createDefault(String filtersDescr, int imageWidth, int protected int sampleFormat; protected int sampleRate; protected int audioInputs; + protected String[] videoFilterArgs ; + protected String[] audioFilterArgs ; public String getFilters() { return filters; @@ -127,6 +129,22 @@ public void setAudioInputs(int audioInputs) { this.audioInputs = audioInputs; } + public String[] getVideoFilterArgs() { + return videoFilterArgs; + } + + public void setVideoFilterArgs(String[] videoFilterArgs) { + this.videoFilterArgs = videoFilterArgs; + } + + public String[] getAudioFilterArgs() { + return audioFilterArgs; + } + + public void setAudioFilterArgs(String[] audioFilterArgs) { + this.audioFilterArgs = audioFilterArgs; + } + public static class Exception extends IOException { public Exception(String message) { super(message); } public Exception(String message, Throwable cause) { super(message, cause); } From 39fc5860f5eaafc2cdcc1be88a1df07afddc7c5a Mon Sep 17 00:00:00 2001 From: Samuel Audet Date: Wed, 27 Nov 2024 18:22:19 +0900 Subject: [PATCH 3/4] Update CHANGELOG.md and fix nits --- CHANGELOG.md | 1 + .../bytedeco/javacv/FFmpegFrameFilter.java | 15 +++++++------- .../java/org/bytedeco/javacv/FrameFilter.java | 20 +++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 439d96e8..b794b8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ + * Add `FrameFilter.videoFilterArgs/audioFilterArgs` properties to support multiple different inputs ([pull #2304](https://github.com/bytedeco/javacv/pull/2304)) * Ensure `FFmpegFrameGrabber.start()` skips over streams with no codecs ([issue #2299](https://github.com/bytedeco/javacv/issues/2299)) * Add `FFmpegLogCallback.logRejectedOptions()` for debugging purposes ([pull #2301](https://github.com/bytedeco/javacv/pull/2301)) diff --git a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java index 332e0764..ae31ffc3 100644 --- a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java @@ -308,10 +308,10 @@ public synchronized void startUnsafe() throws Exception { frame = new Frame(); default_layout = new AVChannelLayout().retainReference(); - if (videoFilterArgs!=null && videoInputs!=videoFilterArgs.length){ + if (videoFilterArgs != null && videoInputs != videoFilterArgs.length) { throw new Exception("The length of videoFilterArgs is different from videoInputs"); } - if (audioFilterArgs!=null && audioInputs!=audioFilterArgs.length){ + if (audioFilterArgs != null && audioInputs != audioFilterArgs.length) { throw new Exception("The length of audioFilterArgs is different from audioInputs"); } if (image_frame == null || samples_frame == null || filt_frame == null) { @@ -348,15 +348,15 @@ private void startVideoUnsafe() throws Exception { /* buffer video source: the decoded frames from the decoder will be inserted here. */ AVRational r = av_d2q(aspectRatio > 0 ? aspectRatio : 1, 255); - String argsBase = String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d", - imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den()); buffersrc_ctx = new AVFilterContext[videoInputs]; setpts_ctx = new AVFilterContext[videoInputs]; for (int i = 0; i < videoInputs; i++) { String name = videoInputs > 1 ? i + ":v" : "in"; outputs[i] = avfilter_inout_alloc(); - String args=videoFilterArgs!=null && videoFilterArgs[i]!=null ? videoFilterArgs[i]:argsBase; + String args = videoFilterArgs != null && videoFilterArgs[i] != null ? videoFilterArgs[i] + : String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d", + imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den()); ret = avfilter_graph_create_filter(buffersrc_ctx[i] = new AVFilterContext().retainReference(), buffersrc, name, args, null, filter_graph); if (ret < 0) { @@ -454,8 +454,9 @@ private void startAudioUnsafe() throws Exception { /* buffer audio source: the decoded frames from the decoder will be inserted here. */ av_channel_layout_default(default_layout, audioChannels); - String aargs = audioFilterArgs!=null && audioFilterArgs[i]!=null ?audioFilterArgs[i]:String.format(Locale.ROOT, "channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d", - audioChannels, sampleFormat, sampleRate, default_layout.u_mask()); + String aargs = audioFilterArgs != null && audioFilterArgs[i] != null ? audioFilterArgs[i] + : String.format(Locale.ROOT, "channels=%d:sample_fmt=%d:sample_rate=%d:channel_layout=%d", + audioChannels, sampleFormat, sampleRate, default_layout.u_mask()); ret = avfilter_graph_create_filter(abuffersrc_ctx[i] = new AVFilterContext().retainReference(), abuffersrc, name, aargs, null, afilter_graph); if (ret < 0) { diff --git a/src/main/java/org/bytedeco/javacv/FrameFilter.java b/src/main/java/org/bytedeco/javacv/FrameFilter.java index 27156a77..b224902c 100644 --- a/src/main/java/org/bytedeco/javacv/FrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FrameFilter.java @@ -43,14 +43,14 @@ public static FrameFilter createDefault(String filtersDescr, int imageWidth, int protected double frameRate; protected double aspectRatio; protected int videoInputs; + protected String[] videoFilterArgs; protected String afilters; protected int audioChannels; protected int sampleFormat; protected int sampleRate; protected int audioInputs; - protected String[] videoFilterArgs ; - protected String[] audioFilterArgs ; + protected String[] audioFilterArgs; public String getFilters() { return filters; @@ -101,6 +101,14 @@ public void setVideoInputs(int videoInputs) { this.videoInputs = videoInputs; } + public String[] getVideoFilterArgs() { + return videoFilterArgs; + } + + public void setVideoFilterArgs(String[] videoFilterArgs) { + this.videoFilterArgs = videoFilterArgs; + } + public int getAudioChannels() { return audioChannels; } @@ -129,14 +137,6 @@ public void setAudioInputs(int audioInputs) { this.audioInputs = audioInputs; } - public String[] getVideoFilterArgs() { - return videoFilterArgs; - } - - public void setVideoFilterArgs(String[] videoFilterArgs) { - this.videoFilterArgs = videoFilterArgs; - } - public String[] getAudioFilterArgs() { return audioFilterArgs; } From f5b9b6445d30efb8eb36288ec6c80e3e8bc9131a Mon Sep 17 00:00:00 2001 From: Samuel Audet Date: Wed, 27 Nov 2024 18:25:19 +0900 Subject: [PATCH 4/4] Revert unnecessary change --- src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java index ae31ffc3..d0e64c5e 100644 --- a/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java +++ b/src/main/java/org/bytedeco/javacv/FFmpegFrameFilter.java @@ -358,7 +358,7 @@ private void startVideoUnsafe() throws Exception { : String.format(Locale.ROOT, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d:frame_rate=%d/%d", imageWidth, imageHeight, pixelFormat, time_base.num(), time_base.den(), r.num(), r.den(), frame_rate.num(), frame_rate.den()); ret = avfilter_graph_create_filter(buffersrc_ctx[i] = new AVFilterContext().retainReference(), buffersrc, name, - args, null, filter_graph); + args, null, filter_graph); if (ret < 0) { throw new Exception("avfilter_graph_create_filter() error " + ret + ": Cannot create video buffer source."); }