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.
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.
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.