javacv icon indicating copy to clipboard operation
javacv copied to clipboard

FFmpegFrameGrabber.grabFrame,AVPacket.stream_index,Lock

Open dute7liang opened this issue 1 year ago • 1 comments

Hi everyone,I'm having an unsolvable problem when trying to take a screenshot of a video

The version number I use : 1.5.6

my code

private static void cutOutFirstOfVideo(String path,File targetFile) throws FrameGrabber.Exception {
        StopWatch stopWatch = new StopWatch("javacv-screenshot");
        stopWatch.start();
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(path);
        OpenCVFrameConverter.ToIplImage converter = null;
        IplImage src = null;
        Frame f = null;
        try{
            ff.start();
            int lenght = ff.getLengthInFrames();
            int i = 0;
            while (i < lenght) {
                f = ff.grabFrame();
                if ((i > 1) && (f.image != null)) {
                    f.close();
                    break;
                }
                i++;
                f.close();
            }
            String rotate =ff.getVideoMetadata("rotate");
            f =ff.grabImage();
            if(null != rotate && rotate.length() > 1) {
                converter = new OpenCVFrameConverter.ToIplImage();
                src  = converter.convert(f);
                f = converter.convert(rotate(src, Integer.parseInt(rotate)));
            }
            doExecuteFrame(f,targetFile);
        } finally {
            if(src != null){
                src.close();
            }
            if(f != null){
                f.close();
            }
            if(converter != null){
                converter.close();
            }
            stopWatch.stop();
            log.info("截图处理: javacv 截图结束 耗时={}毫秒",stopWatch.getTotalTimeMillis());
        }
    }

private static void doExecuteFrame(Frame f,File targetFile) {
        if (null ==f || null ==f.image) {
            return;
        }
        try (Java2DFrameConverter converter =new Java2DFrameConverter();
             FileOutputStream fileOutputStream = new FileOutputStream(targetFile)){
            BufferedImage buffImg =converter.getBufferedImage(f);
            ImageIO.write(buffImg,FileSuffixConstant.JPEG,fileOutputStream);
            buffImg.flush();
        }catch (IOException e) {
            log.error("视频保存失败",e);
            throw new RuntimeException(e.getMessage(),e);
        }
    }

jstack

"pool-16-thread-3" #527 prio=5 os_prio=0 tid=0x00007fbe48058000 nid=0x232 runnable [0x00007fba7026c000]
   java.lang.Thread.State: RUNNABLE
	at org.bytedeco.ffmpeg.avcodec.AVPacket.stream_index(Native Method)
	at org.bytedeco.javacv.FFmpegFrameGrabber.grabFrame(FFmpegFrameGrabber.java:1357)
	- locked <0x00000004cb29e470> (a org.bytedeco.javacv.FFmpegFrameGrabber)
	at org.bytedeco.javacv.FFmpegFrameGrabber.grabImage(FFmpegFrameGrabber.java:1283)
	at com.fcbox.vas.dispatch.util.JavacvUtil.cutOutFirstOfVideo(JavacvUtil.java:82)
	at com.fcbox.vas.dispatch.util.JavacvUtil.cutOutFirstOfVideo(JavacvUtil.java:43)
	at com.fcbox.vas.dispatch.util.VideoUtil.cutPicture(VideoUtil.java:67)
	at com.fcbox.vas.dispatch.task.handle.ScreenshotHandle.transFileAndCutPicture(ScreenshotHandle.java:182)
	at com.fcbox.vas.dispatch.task.handle.ScreenshotHandle.run(ScreenshotHandle.java:139)
	at com.fcbox.vas.dispatch.task.handle.ScreenshotHandle.lambda$handle$20(ScreenshotHandle.java:103)
	at com.fcbox.vas.dispatch.task.handle.ScreenshotHandle$$Lambda$1071/1600206385.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745) 

It's been stuck here for more than 5 hours,no sign of release. Seems to be stuck somewhere in FFmpegFrameGrabber.grabFrame、AVPacket.stream_index.

It should be noted that this method I will use in multi-threading

This happens occasionally, and it can't be fixed. This has caused me a lot of trouble. What can I do to fix it?

dute7liang avatar Sep 21 '22 05:09 dute7liang

There's nothing related to FFmpeg in AVPacket.stream_index() than can block, it's just literally return stream_index. What is causing this issue is thus JNI and something in the JVM. You'll need to figure out what that is, but it's unrelated to JavaCV, JavaCPP, or FFmpeg.

saudet avatar Sep 21 '22 10:09 saudet

Thank you very much, I found the problem, because the network is unstable, the URL has been blocked, maybe I need to add a timeout mechanism

dute7liang avatar May 10 '23 08:05 dute7liang

Thank you very much, I found the problem, because the network is unstable, the URL has been blocked, maybe I need to add a timeout mechanism

how do you resolve it,i found the same problem,grabber.grabFrame() gets stuck for a long time。

tank520 avatar Aug 08 '23 12:08 tank520