165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.core;
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameFormat;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameManager;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.GLFrame;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.NativeBuffer;
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.graphics.Bitmap;
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.nio.ByteBuffer;
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class NativeFrame extends Frame {
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int nativeFrameId = -1;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    NativeFrame(FrameFormat format, FrameManager frameManager) {
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(format, frameManager);
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int capacity = format.getSize();
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        nativeAllocate(capacity);
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setReusable(capacity != 0);
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected synchronized void releaseNativeAllocation() {
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        nativeDeallocate();
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        nativeFrameId = -1;
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected synchronized boolean hasNativeAllocation() {
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return nativeFrameId != -1;
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int getCapacity() {
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return getNativeCapacity();
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * Returns the native frame's Object value.
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     *
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * If the frame's base-type is not TYPE_OBJECT, this returns a data buffer containing the native
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * data (this is equivalent to calling getData().
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * If the frame is based on an object type, this type is expected to be a subclass of
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * NativeBuffer. The NativeBuffer returned is only valid for as long as the frame is alive. If
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * you need to hold on to the returned value, you must retain it.
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public Object getObjectValue() {
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // If this is not a structured frame, return our data
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (getFormat().getBaseType() != FrameFormat.TYPE_OBJECT) {
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return getData();
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Get the structure class
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Class structClass = getFormat().getObjectClass();
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (structClass == null) {
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Attempting to get object data from frame that does " +
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       "not specify a structure object class!");
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Make sure it is a NativeBuffer subclass
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!NativeBuffer.class.isAssignableFrom(structClass)) {
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("NativeFrame object class must be a subclass of " +
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       "NativeBuffer!");
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Instantiate a new empty instance of this class
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        NativeBuffer structData = null;
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        try {
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          structData = (NativeBuffer)structClass.newInstance();
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (Exception e) {
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          throw new RuntimeException("Could not instantiate new structure instance of type '" +
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                     structClass + "'!");
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Wrap it around our data
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!getNativeBuffer(structData)) {
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not get the native structured data for frame!");
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Attach this frame to it
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        structData.attachToFrame(this);
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return structData;
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setInts(int[] ints) {
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (ints.length * nativeIntSize() > getFormat().getSize()) {
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException(
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                "NativeFrame cannot hold " + ints.length + " integers. (Can only hold " +
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                (getFormat().getSize() / nativeIntSize()) + " integers).");
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (!setNativeInts(ints)) {
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set int values for native frame!");
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int[] getInts() {
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return getNativeInts(getFormat().getSize());
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setFloats(float[] floats) {
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (floats.length * nativeFloatSize() > getFormat().getSize()) {
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException(
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                "NativeFrame cannot hold " + floats.length + " floats. (Can only hold " +
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                (getFormat().getSize() / nativeFloatSize()) + " floats).");
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (!setNativeFloats(floats)) {
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set int values for native frame!");
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public float[] getFloats() {
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return getNativeFloats(getFormat().getSize());
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // TODO: This function may be a bit confusing: Is the offset the target or source offset? Maybe
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // we should allow specifying both? (May be difficult for other frame types).
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setData(ByteBuffer buffer, int offset, int length) {
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        byte[] bytes = buffer.array();
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if ((length + offset) > buffer.limit()) {
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Offset and length exceed buffer size in native setData: " +
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       (length + offset) + " bytes given, but only " + buffer.limit() +
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       " bytes available!");
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (getFormat().getSize() != length) {
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Data size in setData does not match native frame size: " +
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       "Frame size is " + getFormat().getSize() + " bytes, but " +
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       length + " bytes given!");
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (!setNativeData(bytes, offset, length)) {
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set native frame data!");
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public ByteBuffer getData() {
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        byte[] data = getNativeData(getFormat().getSize());
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return data == null ? null : ByteBuffer.wrap(data);
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setBitmap(Bitmap bitmap) {
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (getFormat().getNumberOfDimensions() != 2) {
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Attempting to set Bitmap for non 2-dimensional native frame!");
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (getFormat().getWidth()  != bitmap.getWidth() ||
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                   getFormat().getHeight() != bitmap.getHeight()) {
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Bitmap dimensions do not match native frame dimensions!");
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else {
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            Bitmap rgbaBitmap = convertBitmapToRGBA(bitmap);
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            int byteCount = rgbaBitmap.getByteCount();
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            int bps = getFormat().getBytesPerSample();
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (!setNativeBitmap(rgbaBitmap, byteCount, bps)) {
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                throw new RuntimeException("Could not set native frame bitmap data!");
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public Bitmap getBitmap() {
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (getFormat().getNumberOfDimensions() != 2) {
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Attempting to get Bitmap for non 2-dimensional native frame!");
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Bitmap result = Bitmap.createBitmap(getFormat().getWidth(),
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            getFormat().getHeight(),
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                            Bitmap.Config.ARGB_8888);
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int byteCount = result.getByteCount();
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        int bps = getFormat().getBytesPerSample();
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!getNativeBitmap(result, byteCount, bps)) {
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not get bitmap data from native frame!");
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return result;
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setDataFromFrame(Frame frame) {
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Make sure frame fits
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (getFormat().getSize() < frame.getFormat().getSize()) {
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException(
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                "Attempting to assign frame of size " + frame.getFormat().getSize() + " to " +
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                "smaller native frame of size " + getFormat().getSize() + "!");
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Invoke optimized implementations if possible
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (frame instanceof NativeFrame) {
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            nativeCopyFromNative((NativeFrame)frame);
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (frame instanceof GLFrame) {
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            nativeCopyFromGL((GLFrame)frame);
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (frame instanceof SimpleFrame) {
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setObjectValue(frame.getObjectValue());
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else {
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            super.setDataFromFrame(frame);
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public String toString() {
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return "NativeFrame id: " + nativeFrameId + " (" + getFormat() + ") of size "
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            + getCapacity();
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    static {
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        System.loadLibrary("filterfw");
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean nativeAllocate(int capacity);
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean nativeDeallocate();
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native int getNativeCapacity();
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static native int nativeIntSize();
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static native int nativeFloatSize();
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setNativeData(byte[] data, int offset, int length);
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native byte[] getNativeData(int byteCount);
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean getNativeBuffer(NativeBuffer buffer);
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setNativeInts(int[] ints);
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setNativeFloats(float[] floats);
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native int[] getNativeInts(int byteCount);
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native float[] getNativeFloats(int byteCount);
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setNativeBitmap(Bitmap bitmap, int size, int bytesPerSample);
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean getNativeBitmap(Bitmap bitmap, int size, int bytesPerSample);
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean nativeCopyFromNative(NativeFrame frame);
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean nativeCopyFromGL(GLFrame frame);
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
264