Javacv: Change the resolution when pushing with FFmpegFrameRecorder

Created on 29 Mar 2019  路  8Comments  路  Source: bytedeco/javacv

How do I configure the relevant configuration of FFmpegFrameRecorder to change the video resolution when implementing video stream output, just like the -s or -vf scale command in FFmpeg.

question

Most helpful comment

You are right. I used the start(AVFormatContext ifmt_ctx) method. After changing to the start() method, he worked normally. Thank you very much for your answer. It helped me a lot.

All 8 comments

All images get resized to the width and height values given in the constructor.

I think I used this method, but it didn't solve the corresponding problem.
This is my code

   public Stream pull() throws CommonException {
        grabber = new FFmpegFrameGrabber(sourceUrl);
        grabber.setOption("rtsp_transport", "tcp");
        try {
            grabber.start();
        } catch (FrameGrabber.Exception e) {
            logger.error(sourceUrl + " pull fail");
            e.printStackTrace();
            throw new CommonException("2001", Result.getMessage("2001"));
        }
        return this;
    }

    public Stream push() throws CommonException {
        recorder = new FFmpegFrameRecorder(outputUrl, width, height, audioRecord);
        recorder.setFormat("flv");
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setAudioCodecName("acc");
        avformat.AVFormatContext avFormatContext = grabber.getFormatContext();
        recorder.setAudioChannels(audioRecord);
        recorder.setSampleRate(44100);
        recorder.setVideoBitrate(videoBitrate);

        recorder.setVideoOption("tune", "zerolatency");
        recorder.setFrameRate(25);
        recorder.setGopSize(25 * 2);
        //recorder.setOption("vf scale", "480:320");
        try {
            recorder.start(avFormatContext);
        } catch (FrameRecorder.Exception e) {
            logger.error(outputUrl + " push fail");
            e.printStackTrace();
            throw new CommonException("2002", Result.getMessage("2002"));
        }
        return this;
    }
    public void start() throws CommonException {
        int errIndex = 0;
        for (int noFrameIndex = 0; noFrameIndex < 5 || errIndex > 1 || interrupted == 1; ) {
            isRun = true;
            avcodec.AVPacket avPacket;
            try {
                avPacket = grabber.grabPacket();
                if (avPacket == null || (avPacket.size() <= 0) || (avPacket.data() == null)) {
                    noFrameIndex++;
                    continue;
                }
                errIndex += recorder.recordPacket(avPacket) ? 0 : 1;
                av_free_packet(avPacket);

            } catch (FrameGrabber.Exception e) {
                e.printStackTrace();
                errIndex++;
            } catch (FrameRecorder.Exception e) {
                e.printStackTrace();
                errIndex++;
            }
        }
        if (interrupted == 0) {
            restart();
        } else {
            stop();
        }
    }

I use it like this.pull().push().start(),the source video resolution is 640x480,the creation statement of FFmpegFrameRecorder is new FFmpegFrameRecorder(outputUrl, 480, 272, 1),But the resolution of the output stream is still 640x480

You're not calling record() anywhere.
You'll need to call record() somewhere.

I modified the code for the start method.

    public void start() {
        long startTime = 0;
        Frame frame;
        try {
            while ((frame = grabber.grab()) != null) {
                if (startTime == 0)
                    startTime = System.currentTimeMillis();
                long time = System.currentTimeMillis() - startTime;
                recorder.setTimestamp(1000 * time);
                recorder.record(frame);
            }
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        } catch (FrameRecorder.Exception e) {
            e.printStackTrace();
        }
    }

But it didn't work and produced an exception,this is output information of ffmpeg

Input #0, rtsp, from 'rtsp://user:[email protected]:1554/h264/ch1/sub/av_stream':
  Metadata:
    title           : Media Presentation
  Duration: N/A, start: 0.240000, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 640x480 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 90k tbn, 50 tbc
[flv @ 0x7ff07c148900] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Output #0, flv, to 'rtmp://127.0.0.1:9100/live/a2334ccd-e030-41e5-8957-91761a636b1e':
  Metadata:
    encoder         : Lavf58.20.100
    Stream #0:0: Video: h264 (Main) ([7][0][0][0] / 0x0007), yuvj420p(pc, bt709, progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 25 fps, 1k tbn, 25 tbc
    Stream #0:1: Audio: aac (LC) ([10][0][0][0] / 0x000A), 44100 Hz, mono, fltp, 64 kb/s
[swscaler @ 0x7ff07c31b900] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x7ff07c4e4100] deprecated pixel format used, make sure you did set range correctly
Exception in thread "Thread-9" java.lang.NullPointerException
    at org.bytedeco.javacv.FFmpegFrameRecorder.recordImage(FFmpegFrameRecorder.java:931)
    at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:876)
    at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:869)

Passing null frames to FFmpegFrameRecorder isn't going to work. Make sure that doesn't happen.

Exceptions in this line of code in the recordImage method.

avutil.av_image_fill_arrays(new PointerPointer(this.tmp_picture), this.tmp_picture.linesize(), data, pixelFormat, width, height, 1);

this.tmp_picture is null,but I didn't see any instantiation about it during the debugging process.

It happens on start(). You should be getting another exception before that if you didn't call start(), but anyway, just call start(), it will work.

You are right. I used the start(AVFormatContext ifmt_ctx) method. After changing to the start() method, he worked normally. Thank you very much for your answer. It helped me a lot.

Was this page helpful?
0 / 5 - 0 ratings