1

When we retrieve a frame from FrameGrabber, we get a reference to the frame. The frame is added to a list. However, due to the fact that we are only referencing to the frame, all the objects in the list points to the same reference.

Since I don't have access to neither object Frame, or FrameGrabber I cannot make 'em cloneable or serializable. Hence no copying.

I believe that since we create a new object Frame each round, we get a new reference, rigth?

Frame frame = new Frame();

However, the object frame itself is a reference to:

frame = mFrameGrabber.grabFrame();

So the culprit is the mFrameGrabber, which returns the same reference every time.. Help me solve this.

Short: Capture a frame (object) and store the content (not reference) in an arraylist of type object.

private FrameGrabber mFrameGrabber;
List<Frame> frameBuffer = new ArrayList<Frame>();
public void run() {

    // Run forever
    while ( true )
    {
        Frame frame = new Frame();

        // Time to capture a frame ? 
        if ( captureTimer.hasTimerElapsed() == true )
        {
            try 
            {
                // Grab a frame
                frame = mFrameGrabber.grabFrame();

                if ( frameWindow.isVisible() && frame != null) 
                {
                    frameBuffer.add(frame);
                }

            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }
        }


    }
}

Classes are implemented from javaCV, from a jar file.

Edit: Okey. The frame object has objects itselfs. I've noticed that the only object I need to copy is a object of type buffer[]. Call it image.

I can clone image, gives me a new reference. However, the content within image seems still to be the same lol. So this is still not a deep copy .. Will try serialize aswell.

private Frame copyFrame(Frame frame)
    {
        // Frame that will hold the copy
        Frame cFrame = new Frame(640, 480, 8, 3);
        cFrame.image = frame.image.clone();

        return cFrame;
    }
ezFreak
  • 82
  • 2
  • 8
  • Please check [How do I copy an object in Java?](http://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java) – Jordi Castilla Sep 29 '15 at 10:37
  • 1
    You are aware that you create a new Frame object even if you won't use it ( time has not elapsed, yet) ? Also I think creating an instance is superfluent because you should get one from `grabFrame()`. – Fildor Sep 29 '15 at 10:38
  • frame = mFrameGrabber.grabFrame().clone(); may be ? – vincent Sep 29 '15 at 10:40
  • If `mFrameGrabber.grabFrame()` returns different references then it should not create any problem because in the while loop you will be adding value of those references which are distinct in each iteration. Or set all the essential property of frame to the newly created instance means clone it. – SacJn Sep 29 '15 at 10:41
  • @vincent OP says.... *I cannot make 'em cloneable or serializable. Hence no copying.* – Jordi Castilla Sep 29 '15 at 10:44
  • 1
    This does not solve your issue but you should get rid of the `new Frame()`. – Hermann Klecker Sep 29 '15 at 10:51
  • Fildor, Hermann Klecker, thanks for the input. Will take care of it. SacJn I've confirmed that it returns the same damn reference every time. By reading one time, copying it, reading another and comparing the reference. – ezFreak Sep 29 '15 at 11:03
  • @JordiCastilla Looking at the accepted answer - "nested objects would still be referencing the original source instance". That will be a problem for me. – ezFreak Sep 29 '15 at 11:06
  • 1
    Make a deeper copy, its your only way I think... – Jordi Castilla Sep 29 '15 at 11:09
  • If it returns the same reference and you know that, then why do you create a list of it anyway? What is the point of that list? – Tom Sep 29 '15 at 11:13
  • @JordiCastilla The methods to perform deeper clones I've seen has been serialize and clone. These two requires that I have acccess to the classes. Which I do not. Gaahh ! – ezFreak Sep 29 '15 at 11:13
  • @Tom The purpose is to have the latest x amount of frames (in time) in a buffer. These will be saved to a video file when asked to. I put 'em in a list to show my purpose, what I'm trying to achieve. – ezFreak Sep 29 '15 at 11:16
  • If you want to store the lastest frames, then shouldn't you advance the medium so the frame can be actually different? Your framegrapper has the method `start` to create a new frame. You may need that method. – Tom Sep 29 '15 at 11:31
  • @Tom That is true. There is such function. However, the module needs some time for it to be initialized, thus slowing the application. – ezFreak Sep 30 '15 at 08:26

2 Answers2

0

May be that can help

frame = (Frame)mFrameGrabber.grabFrame().clone();
w33
  • 36
  • 3
  • He is good discussion about what is better clone or copy constructor http://stackoverflow.com/questions/2326758/how-to-properly-override-clone-method – w33 Sep 29 '15 at 11:32
  • That line won't compile ;). – Tom Sep 29 '15 at 11:32
  • Because you need to implement clone function of Cloneable interface or implement copy constructor for you Frame class. – w33 Sep 29 '15 at 11:35
  • And because `clone` doesn't return `Frame`. Never. – Tom Sep 29 '15 at 11:45
  • 1
    Of cause you need to cast to to Frame from Object. Good point. – w33 Sep 29 '15 at 11:56
0

Problem has now been solved. Looking into the Class/Object "Frame", the conclusion was that the only component inside that had to be deep copied was:

public Buffer[] image;

Looking a bit deeper within the class, the following can be seen:

ByteBuffer buffer = ByteBuffer.allocateDirect(imageHeight * imageStride * pixelSize).order(ByteOrder.nativeOrder());
image[0] = buffer;  

So index 0 of the buffer is holding a ByteBuffer, which is not serializable! Thus I started to dig into the net how to deep copy such a object. With a good result.

Below is the solution. Thanks for the feedback guys!

private Frame copyFrame(Frame frame)
{
    // Frame that will hold the copy
    Frame cFrame = new Frame(640, 480, 8, 3);

    // Copy the byte buffer from frame
    ByteBuffer originalByteBuffer = (ByteBuffer) frame.image[0];

    // Create the clone buffer with same capacity as the original
    ByteBuffer cloneBuffer = ByteBuffer.allocateDirect(originalByteBuffer.capacity());
    //ByteBuffer cloneBuffer = deepCopy(originalByteBuffer);

    // Save parameters from the original byte buffer
    int position = originalByteBuffer.position();
    int limit = originalByteBuffer.limit();


    // Set range to the entire buffer
    originalByteBuffer.position(0).limit(originalByteBuffer.capacity());

    // Read from original and put into clone
    cloneBuffer.put(originalByteBuffer);

    // Set the order same as original
    cloneBuffer.order(originalByteBuffer.order());

    // Set clone position to 0 and set the range as the original
    cloneBuffer.position(0);
    cloneBuffer.position(position).limit(limit);

    // Save the clone 
    cFrame.image[0] = cloneBuffer;      

    return cFrame;
}
ezFreak
  • 82
  • 2
  • 8