bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.53k stars 1.58k forks source link

av_interleaved_write_frame() returns AVERROR_EOF error when pushing streaming video and audio with FFmpegFrameRecorder #2099

Closed lushangkan closed 1 year ago

lushangkan commented 1 year ago

Error while pushing streaming video and audio with FFmpegFrameRecorder:

[23:14:44] [Render thread/ERROR] (JavaCVStreamer) Could not record frame!
 org.bytedeco.javacv.FFmpegFrameRecorder$Exception: av_interleaved_write_frame() error -541478725 while writing interleaved video packet. (For more details, make sure FFmpegLogCallback.set() has been called.)
    at org.bytedeco.javacv.FFmpegFrameRecorder.writePacket(FFmpegFrameRecorder.java:1383) ~[javacv-1.5.9.jar:1.5.9]
    at org.bytedeco.javacv.FFmpegFrameRecorder.recordImage(FFmpegFrameRecorder.java:1139) ~[javacv-1.5.9.jar:1.5.9]
    at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:1017) ~[javacv-1.5.9.jar:1.5.9]
    at cn.cutemc.streamingassistant.streamingassistant.streamers.JavaCVStreamer.update(JavaCVStreamer.java:108) ~[main/:?]
    at cn.cutemc.streamingassistant.streamingassistant.listeners.FrameUpdateListener.onFrameUpdate(FrameUpdateListener.java:53) ~[main/:?]
...

If an attempt is made to save to a local file instead of stream to the server, the error does not occur.

Partial code:

create FFmpegFrameRecorder:

FFmpegLogCallback.set();
recorder = new FFmpegFrameRecorder(ModConfig.mainConfig.streamingUrl + '/' + ModConfig.mainConfig.streamingCode, 1080, 1920, 2);
recorder.setFormat("flv");
recorder.setPixelFormat(AV_PIX_FMT_YUV420P);

// audio
recorder.setAudioChannels(2);
recorder.setAudioBitrate(128000);
recorder.setSampleRate(44100);
recorder.setAudioCodec(AV_CODEC_ID_AAC);
recorder.setAudioQuality(0);
// video
recorder.setVideoCodec(AV_CODEC_ID_H264);
recorder.setVideoBitrate(9000000);
recorder.setVideoQuality(0);
recorder.setFrameRate(60);
recorder.setImageHeight(1920);
recorder.setImageWidth(1080);

update frame:

try (Frame frame = new Frame(width, height, Frame.DEPTH_BYTE, 4)){
    // Audio
    if (audio != null) {
        frame.sampleRate = recorder.getSampleRate();
        frame.samples = new Buffer[]{audio};
        frame.audioChannels = recorder.getAudioChannels();
    }
    // Video
    for (int i = 0; i < video.capacity(); i++) {
        ((ByteBuffer)frame.image[0]).put(i, video.get(i));
    }
    recorder.record(frame, AV_PIX_FMT_RGBA);
} catch (Exception e) {
    ...
}

The full code is available here.

saudet commented 1 year ago

Please make sure that FFmpegLogCallback.set() has been called.

lushangkan commented 1 year ago

Please make sure that FFmpegLogCallback.set() has been called.

Already set before creating FFmpegFrameRecorder. The logs have no errors from ffmpeg.

lushangkan commented 1 year ago

Please make sure that FFmpegLogCallback.set() has been called.

After trying to change CallbackLevel to TRACE, ffmpeg outputs: [STDERR]: Debug: [libx264 @ 000002bb4562df80] frame= 119 QP=0.00 NAL=2 Slice:P Poc:84 I:1640 P:3691 SKIP:2829 size=264795 bytes

lushangkan commented 1 year ago

Sometimes av_interleaved_write_frame() returns -10053, but I can't find what the code -10053 stands for.

log:

(JavaCVStreamer) Could not record frame!
org.bytedeco.javacv.FFmpegFrameRecorder$Exception: av_interleaved_write_frame() error -10053 while writing interleaved video packet. (For more details, make sure FFmpegLogCallback.set() has been called.)
    at org.bytedeco.javacv.FFmpegFrameRecorder.writePacket(FFmpegFrameRecorder.java:1383) ~[javacv-1.5.9.jar:1.5.9]
    at org.bytedeco.javacv.FFmpegFrameRecorder.recordImage(FFmpegFrameRecorder.java:1139) ~[javacv-1.5.9.jar:1.5.9]
    at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:1017) ~[javacv-1.5.9.jar:1.5.9]
    at cn.cutemc.streamingassistant.streamingassistant.streamers.JavaCVStreamer.update(JavaCVStreamer.java:108) ~[main/:?]
    at cn.cutemc.streamingassistant.streamingassistant.listeners.FrameUpdateListener.onFrameUpdate(FrameUpdateListener.java:53) ~[main/:?]
    at cn.cutemc.streamingassistant.streamingassistant.events.FrameUpdateEvent.lambda$static$0(FrameUpdateEvent.java:11) ~[main/:?]
....
[STDERR]: Debug: [libx264 @ 000001decc75df80] frame= 368 QP=14.01 NAL=2 Slice:B Poc:236 I:7    P:3981 SKIP:4172 size=28230 bytes

avutil.av_strerror(-10053, rt, 1024); return: Error number -10053 occurred

lushangkan commented 1 year ago

-10053 seems to be caused by unstable frame rate.

saudet commented 1 year ago

That sounds like an issue with your network.

lushangkan commented 1 year ago

It seems that -10053 and AVERROR_EOF are both caused by not transferring the image in time after I turn on Recorder, put Recorder.start() to before frame update, problem solved!

It is recommended to use try wrapping the Recorder.record() and restart when you get error code -10053 or error code -541478725 to avoid this error.