| /* |
| * 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); |
| } |