cegredev
cegredev

Reputation: 1579

JavaCV FFmpegFrameFilter does not work for fps filter

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

Answers (1)

cegredev
cegredev

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

Related Questions