bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.58k stars 1.59k forks source link

[libmp3lame @ 0x7f6ef9084d40] 4 frames left in the queue on closing #2074

Open Mhuang77 opened 1 year ago

Mhuang77 commented 1 year ago

Get the exception in javacv "[libmp3lame @ 0x7f91cd0ce3c0] 4 frames left in the queue on closing"

test file: input_case.zip

1 The ffmpeg command does not have this exception.

ffmpeg -i input.m4a tmp.mp3

2 javacv code encounter this exception

2.1 lib version:

    implementation 'org.bytedeco:openblas:0.3.23-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:opencv:4.7.0-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:ffmpeg:6.0-1.5.9:linux-x86_64'
    implementation 'org.bytedeco:javacpp:1.5.9:linux-x86_64'
    implementation 'org.bytedeco:javacv:1.5.9'

2.2 jdk version

openjdk version "11.0.19" 2023-04-18

2.3 os version

Ubuntu 22.04.1 LTS

2.4 reproduce code:

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;

import java.io.*;

public class TestMain {
    final static String INPUT_FILE_NAME = "/tmp/input.m4a";
    final static String OUTPUT_FILE_PATH = "/tmp/";
    public static void main(String[] args) throws IOException {
        test1();
    }

    public static void test1() throws FileNotFoundException, FFmpegFrameRecorder.Exception, FrameGrabber.Exception {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(new FileInputStream(INPUT_FILE_NAME));
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(OUTPUT_FILE_PATH + "test1.mp3", 1);
        extracted(grabber, recorder);
        grabber.stop();
        recorder.stop();
    }

    private static void extracted(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder) throws FFmpegFrameRecorder.Exception, FrameGrabber.Exception {
        recorder.setFormat("MP3");
        recorder.start();
        grabber.start();
        Frame frame;
        while ((frame = grabber.grabFrame()) != null) {
            recorder.record(frame);
        }
    }
}

3 exception log

Output #0, mp3, to '/tmp/test1.mp3':
  Metadata:
    TSSE            : Lavf60.3.100
  Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 64 kb/s
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'java.io.BufferedInputStream@5aa9e4eb':
  Metadata:
    major_brand     : M4A 
    minor_version   : 512
    compatible_brands: M4A isomiso2
    encoder         : Lavf60.3.100
  Duration: 00:00:14.98, start: 0.000000, bitrate: 75 kb/s
  Stream #0:0[0x1](und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 74 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
[libmp3lame @ 0x7f91cd0ce3c0] 4 frames left in the queue on closing   <-------------------  this exception
Mhuang77 commented 1 year ago

@saudet What can I do to help track down this issue?

saudet commented 1 year ago

It sounds like FFmpegFrameRecorder.flush() isn't working properly. Someone needs to debug that.

Mhuang77 commented 1 year ago

It sounds like FFmpegFrameRecorder.flush() isn't working properly. Someone needs to debug that.

I set the log level to debug and got log messages

......
[SWR @ 0x7ff275307140] Using s16p internally between filters
[mp3 @ 0x7ff2751fedc0] av_interleaved_write_frame FLUSH
[libmp3lame @ 0x7ff275206e80] 4 frames left in the queue on closing
[AVIOContext @ 0x7ff2752eeb80] Statistics: 119579 bytes written, 0 seeks, 1 writeouts

Based on the provided log, it can be observed that "av_interleaved_write_frame FLUSH" occurs before "4 frames left in the queue on closing". Now there is a suspicion that av_interleaved_write_frame has a problem.

How to debug the native method "org.bytedeco.ffmpeg.global.avformat#av_interleaved_write_frame"?

saudet commented 1 year ago

It sounds to me like the problem lies in libmp3lame. We need to figure out how to properly flush that specific codec.