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