/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.filterfw.core; import android.filterfw.core.Frame; /** * @hide */ public class NativeBuffer { // These are set by the native layer private long mDataPointer = 0; private int mSize = 0; private Frame mAttachedFrame; private boolean mOwnsData = false; private int mRefCount = 1; public NativeBuffer() { } public NativeBuffer(int count) { allocate(count * getElementSize()); mOwnsData = true; } public NativeBuffer mutableCopy() { NativeBuffer result = null; try { Class myClass = getClass(); result = (NativeBuffer)myClass.newInstance(); } catch (Exception e) { throw new RuntimeException("Unable to allocate a copy of " + getClass() + "! Make " + "sure the class has a default constructor!"); } if (mSize > 0 && !nativeCopyTo(result)) { throw new RuntimeException("Failed to copy NativeBuffer to mutable instance!"); } return result; } public int size() { return mSize; } public int count() { return (mDataPointer != 0) ? mSize / getElementSize() : 0; } public int getElementSize() { return 1; } public NativeBuffer retain() { if (mAttachedFrame != null) { mAttachedFrame.retain(); } else if (mOwnsData) { ++mRefCount; } return this; } public NativeBuffer release() { // Decrement refcount boolean doDealloc = false; if (mAttachedFrame != null) { doDealloc = (mAttachedFrame.release() == null); } else if (mOwnsData) { --mRefCount; doDealloc = (mRefCount == 0); } // Deallocate if necessary if (doDealloc) { deallocate(mOwnsData); return null; } else { return this; } } public boolean isReadOnly() { return (mAttachedFrame != null) ? mAttachedFrame.isReadOnly() : false; } static { System.loadLibrary("filterfw"); } void attachToFrame(Frame frame) { // We do not auto-retain. We expect the user to call retain() if they want to hold on to // the frame. mAttachedFrame = frame; } protected void assertReadable() { if (mDataPointer == 0 || mSize == 0 || (mAttachedFrame != null && !mAttachedFrame.hasNativeAllocation())) { throw new NullPointerException("Attempting to read from null data frame!"); } } protected void assertWritable() { if (isReadOnly()) { throw new RuntimeException("Attempting to modify read-only native (structured) data!"); } } private native boolean allocate(int size); private native boolean deallocate(boolean ownsData); private native boolean nativeCopyTo(NativeBuffer buffer); }