1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package android.filterfw.core;
19
20import android.filterfw.core.FrameFormat;
21import android.filterfw.core.FrameManager;
22import android.graphics.Bitmap;
23import android.util.Log;
24
25import java.nio.ByteBuffer;
26
27/**
28 * @hide
29 */
30public abstract class Frame {
31
32    public final static int NO_BINDING = 0;
33
34    public final static long TIMESTAMP_NOT_SET = -2;
35    public final static long TIMESTAMP_UNKNOWN = -1;
36
37    private FrameFormat mFormat;
38    private FrameManager mFrameManager;
39    private boolean mReadOnly = false;
40    private boolean mReusable = false;
41    private int mRefCount = 1;
42    private int mBindingType = NO_BINDING;
43    private long mBindingId = 0;
44    private long mTimestamp = TIMESTAMP_NOT_SET;
45
46    Frame(FrameFormat format, FrameManager frameManager) {
47        mFormat = format.mutableCopy();
48        mFrameManager = frameManager;
49    }
50
51    Frame(FrameFormat format, FrameManager frameManager, int bindingType, long bindingId) {
52        mFormat = format.mutableCopy();
53        mFrameManager = frameManager;
54        mBindingType = bindingType;
55        mBindingId = bindingId;
56    }
57
58    public FrameFormat getFormat() {
59        return mFormat;
60    }
61
62    public int getCapacity() {
63        return getFormat().getSize();
64    }
65
66    public boolean isReadOnly() {
67        return mReadOnly;
68    }
69
70    public int getBindingType() {
71        return mBindingType;
72    }
73
74    public long getBindingId() {
75        return mBindingId;
76    }
77
78    public void setObjectValue(Object object) {
79        assertFrameMutable();
80
81        // Attempt to set the value using a specific setter (which may be more optimized), and
82        // fall back to the setGenericObjectValue(...) in case of no match.
83        if (object instanceof int[]) {
84            setInts((int[])object);
85        } else if (object instanceof float[]) {
86            setFloats((float[])object);
87        } else if (object instanceof ByteBuffer) {
88            setData((ByteBuffer)object);
89        } else if (object instanceof Bitmap) {
90            setBitmap((Bitmap)object);
91        } else {
92            setGenericObjectValue(object);
93        }
94    }
95
96    public abstract Object getObjectValue();
97
98    public abstract void setInts(int[] ints);
99
100    public abstract int[] getInts();
101
102    public abstract void setFloats(float[] floats);
103
104    public abstract float[] getFloats();
105
106    public abstract void setData(ByteBuffer buffer, int offset, int length);
107
108    public void setData(ByteBuffer buffer) {
109        setData(buffer, 0, buffer.limit());
110    }
111
112    public void setData(byte[] bytes, int offset, int length) {
113        setData(ByteBuffer.wrap(bytes, offset, length));
114    }
115
116    public abstract ByteBuffer getData();
117
118    public abstract void setBitmap(Bitmap bitmap);
119
120    public abstract Bitmap getBitmap();
121
122    public void setTimestamp(long timestamp) {
123        mTimestamp = timestamp;
124    }
125
126    public long getTimestamp() {
127        return mTimestamp;
128    }
129
130    public void setDataFromFrame(Frame frame) {
131        setData(frame.getData());
132    }
133
134    protected boolean requestResize(int[] newDimensions) {
135        return false;
136    }
137
138    public int getRefCount() {
139        return mRefCount;
140    }
141
142    public Frame release() {
143        if (mFrameManager != null) {
144            return mFrameManager.releaseFrame(this);
145        } else {
146            return this;
147        }
148    }
149
150    public Frame retain() {
151        if (mFrameManager != null) {
152            return mFrameManager.retainFrame(this);
153        } else {
154            return this;
155        }
156    }
157
158    public FrameManager getFrameManager() {
159        return mFrameManager;
160    }
161
162    protected void assertFrameMutable() {
163        if (isReadOnly()) {
164            throw new RuntimeException("Attempting to modify read-only frame!");
165        }
166    }
167
168    protected void setReusable(boolean reusable) {
169        mReusable = reusable;
170    }
171
172    protected void setFormat(FrameFormat format) {
173        mFormat = format.mutableCopy();
174    }
175
176    protected void setGenericObjectValue(Object value) {
177        throw new RuntimeException(
178            "Cannot set object value of unsupported type: " + value.getClass());
179    }
180
181    protected static Bitmap convertBitmapToRGBA(Bitmap bitmap) {
182        if (bitmap.getConfig() == Bitmap.Config.ARGB_8888) {
183            return bitmap;
184        } else {
185            Bitmap result = bitmap.copy(Bitmap.Config.ARGB_8888, false);
186            if (result == null) {
187                throw new RuntimeException("Error converting bitmap to RGBA!");
188            } else if (result.getRowBytes() != result.getWidth() * 4) {
189                throw new RuntimeException("Unsupported row byte count in bitmap!");
190            }
191            return result;
192        }
193    }
194
195    protected void reset(FrameFormat newFormat) {
196        mFormat = newFormat.mutableCopy();
197        mReadOnly = false;
198        mRefCount = 1;
199    }
200
201    /**
202     * Called just before a frame is stored, such as when storing to a cache or context.
203     */
204    protected void onFrameStore() {
205    }
206
207    /**
208     * Called when a frame is fetched from an internal store such as a cache.
209     */
210    protected void onFrameFetch() {
211    }
212
213    // Core internal methods ///////////////////////////////////////////////////////////////////////
214    protected abstract boolean hasNativeAllocation();
215
216    protected abstract void releaseNativeAllocation();
217
218    final int incRefCount() {
219        ++mRefCount;
220        return mRefCount;
221    }
222
223    final int decRefCount() {
224        --mRefCount;
225        return mRefCount;
226    }
227
228    final boolean isReusable() {
229        return mReusable;
230    }
231
232    final void markReadOnly() {
233        mReadOnly = true;
234    }
235
236}
237