Reputation: 1579
I am trying to change the frame rate of a video using the FFmpegFrameFilter and -grabber of JavaCV. However, filter.pull();
always returns null.
I have tried basically every combination of pulling and pushing frames, but nothing seems to work.
This is my code:
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new File("input.mp4"));
grabber.start();
FFmpegFrameFilter filter = new FFmpegFrameFilter("fps=fps=60", null, grabber.getImageWidth(), grabber.getImageHeight(), 0);
filter.setVideoInputs(1);
filter.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
for (int i = 0; i < 10; i++) {
//Push the newly grabbed frame to the filter.
Frame frame = grabber.grabImage();
int n = frame.image.length - 1;
filter.pushImage(n > 0 ? n : 0, frame.imageWidth, frame.imageHeight, frame.imageDepth, frame.imageChannels, frame.imageStride, grabber.getPixelFormat(), frame.image);
//Pull the frame from the filter, convert it to a BufferedImage, and save it.
//This line throws an IllegalArgumentException, stating the image is null.
ImageIO.write(converter.convert(filter.pullImage()), "jpg", new File(outputPath + i + ".jpg"));
}
My best guess is that I am giving pushImage(...)
the wrong arguments, as I am not sure what the first argument n
is supposed to be.
Upvotes: 0
Views: 690
Reputation: 1579
I figured out a way to avoid the filter.
class GrabWithDifferentFrameRate {
private Frame lastFrame;
private FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(input);
// Basically converts a frameNumber based on the desiredFrameRate
// to one fitting for the grabbers frameRate and returns the frame at that frameNumber
public Frame grabAt(int frameNumber, int desiredFrameRate) {
double stepSize = desiredFrameRate / grabber.getFrameRate();
double adjustedFrameNumber = calculateAdjustedFrameNumber(stepSize);
Frame frame = lastFrame;
while ((adjustedFrameNumber <= frameNumber && frameNumber / stepSize < grabber.getLengthInFrames())) {
frame = grabber.grabImage();
adjustedFrameNumber = calculateAdjustedFrameNumber(stepSize);
}
return frame;
}
private double calculateAdjustedFrameNumber(double stepSize) {
return grabber.getFrameNumber() * stepSize;
}
}
Upvotes: 0