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 Renn
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class NativeBuffer {
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // These are set by the native layer
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private long mDataPointer = 0;
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mSize = 0;
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private Frame mAttachedFrame;
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private boolean mOwnsData = false;
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mRefCount = 1;
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public NativeBuffer() {
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public NativeBuffer(int count) {
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        allocate(count * getElementSize());
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mOwnsData = true;
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public NativeBuffer mutableCopy() {
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        NativeBuffer result = null;
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        try {
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            Class myClass = getClass();
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            result = (NativeBuffer)myClass.newInstance();
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (Exception e) {
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Unable to allocate a copy of " + getClass() + "! Make " +
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       "sure the class has a default constructor!");
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mSize > 0 && !nativeCopyTo(result)) {
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Failed to copy NativeBuffer to mutable instance!");
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return result;
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int size() {
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mSize;
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int count() {
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (mDataPointer != 0) ? mSize / getElementSize() : 0;
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int getElementSize() {
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return 1;
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public NativeBuffer retain() {
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mAttachedFrame != null) {
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mAttachedFrame.retain();
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (mOwnsData) {
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ++mRefCount;
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return this;
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public NativeBuffer release() {
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Decrement refcount
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        boolean doDealloc = false;
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mAttachedFrame != null) {
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            doDealloc = (mAttachedFrame.release() == null);
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else if (mOwnsData) {
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            --mRefCount;
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            doDealloc = (mRefCount == 0);
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Deallocate if necessary
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (doDealloc) {
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            deallocate(mOwnsData);
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return null;
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else {
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return this;
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public boolean isReadOnly() {
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (mAttachedFrame != null) ? mAttachedFrame.isReadOnly() : false;
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    static {
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        System.loadLibrary("filterfw");
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    void attachToFrame(Frame frame) {
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // We do not auto-retain. We expect the user to call retain() if they want to hold on to
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // the frame.
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mAttachedFrame = frame;
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void assertReadable() {
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mDataPointer == 0 || mSize == 0
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        || (mAttachedFrame != null && !mAttachedFrame.hasNativeAllocation())) {
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new NullPointerException("Attempting to read from null data frame!");
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void assertWritable() {
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (isReadOnly()) {
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Attempting to modify read-only native (structured) data!");
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean allocate(int size);
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean deallocate(boolean ownsData);
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean nativeCopyTo(NativeBuffer buffer);
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
130