bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.39k stars 1.56k forks source link

grabbing frames only in each second #2211

Open xseser opened 3 months ago

xseser commented 3 months ago

private void initialiseFrameGrabber() { log.info("Starting new stream"); this.frameGrabber = new FFmpegFrameGrabber(RTSP_URL); this.frameGrabber.setFrameRate(1); try { this.frameGrabber.start(); } catch (FrameGrabber.Exception e) { log.error("error during starting frame grabber {}", e.getMessage()); } }

private void grabAndProcessFrame() {
    while (true) {
        try {
            Frame frame = frameGrabber.grab();
            boolean t = frame.keyFrame;
            log.info("t: {}", t);
            if (frame != null) {
                log.info("Getting new frame with time: {}", now());
                byte[] image = imageConverter.convertFrameToByteArray(frame);
                executor.execute(() -> recognitionService.recognizePlate(image));
            }

// frameGrabber.waitForTimestamp() // Thread.sleep(1000); } catch (FrameGrabber.Exception e) { log.error("Exception during getting new frame! {}", e.getMessage()); } catch (InterruptedException e) { throw new RuntimeException(e); } } }

I want actually to grab frame only on each second. This is not valid code because it grabes frames which are in stream queue. Do you have some code or any solution how to handle getting frames only at each second, or to delay them somehow?

saudet commented 3 months ago

You might be able to use setTimestamp() for this.

xseser commented 3 months ago

@saudet Can you show me example of this usage?

xseser commented 3 months ago

@saudet I also after about an hour of usage have 100% usage of processor. How can I resolve issue? My goal is to keep server running with this library downloading images each second.

saudet commented 3 months ago

I'd start by calling something like grabber.setTimestamp(grabber.getTimestamp() + 1000000) before each call to grab().

xseser commented 3 months ago

Currently I am using function like: private void grabAndProcessFrame() { while (true) { try { frameGrabber.delayedGrab(1000000); Frame frame = frameGrabber.getDelayedFrame(); if (frame != null) { log.info("Getting new frame with time: {}", new Date(frame.timestamp)); byte[] image = imageConverter.convertFrameToByteArray(frame); executor.execute(() -> recognitionService.recognizePlate(image)); } } catch (InterruptedException | ExecutionException e) { log.error("Error while getting delayed frame {}", e.getMessage()); } } } It's working fine to me, but I have problems with 100% usage of memory, after about hour :/

saudet commented 3 months ago

That should work too. You'll need to make sure you don't keep copies of the images in memory to avoid running out of it

xseser commented 3 months ago

In my code I only grab a frame and I just put it in another service. Even thou in my component when I'm only grabbing frames I run out of memory.

saudet commented 3 months ago

Do you run out of memory only with delayedGrab()? Or does it happen with normal grab() as well?

saudet commented 2 months ago

In any case, if you could provide a small standalone code snippet to reproduce the issue, I would be able to look into this