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