1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Arrays;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Frames are the data containers that are transported between Filters.
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Frames may be used only within a Filter during filter graph execution. Accessing Frames outside
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * of graph execution may cause unexpected results.
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * There are two ways to obtain new Frame instances. You can call
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link OutputPort#fetchAvailableFrame(int[])} on an OutputPort to obtain a Frame to pass to an
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * output. You can also call {@link #create(FrameType, int[])} to obtain
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * a detached Frame instance that you may hold onto in your filter. If you need to hold on to a
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Frame that is owned by an input or output queue, you must call
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #retain()} on it.
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * When you are done using a detached Frame, you must release it yourself.
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * To access frame data, call any of the {@code lock}-methods. This will give you access to the
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * frame data in the desired format. You must pass in a {@code mode} indicating whether you wish
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to read or write to the data. Writing to a read-locked Frame may produce unexpected results and
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * interfere with other filters. When you are done reading or writing to the data, you must call
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #unlock()}. Note, that a Frame must be unlocked before you push it into an output queue.
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Generally, any type of access format to a Frame's data will be granted. However, it is strongly
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * recommended to specify the access format that you intend to use in your filter's signature or
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * in the access flags passed to {@code newFrame()}. This will allow the Frame to allocate
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the most efficient backings for the intended type of access.
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A frame can be be pushed to an OutputPort by calling the {@link OutputPort#pushFrame(Frame)}
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * method. Frames that have been pushed become read-only, and can no longer be modified.
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * On the other end, a Filter can pull in an input Frame by calling {@link InputPort#pullFrame()}
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * on the desired InputPort. Such frames are always read-only.
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class Frame {
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Special timestamp value indicating that no time-stamp was set. */
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static final long TIMESTAMP_NOT_SET = -1;
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Frame data access mode: Read */
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static final int MODE_READ = 1;
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Frame data access mode: Write */
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static final int MODE_WRITE = 2;
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    BackingStore mBackingStore;
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    boolean mReadOnly = false;
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Public API //////////////////////////////////////////////////////////////////////////////////
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the frame's type.
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return A FrameType instance describing the frame data-type.
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameType getType() {
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mBackingStore.getFrameType();
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final int getElementCount() {
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mBackingStore.getElementCount();
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Set the frame's timestamp in nanoseconds.
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param timestamp the timestamp of this frame in nanoseconds.
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final void setTimestamp(long timestamp) {
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackingStore.setTimestamp(timestamp);
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the frame's timestamp in nanoseconds.
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final long getTimestamp() {
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mBackingStore.getTimestamp();
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the frame's timestamp in milliseconds.
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final long getTimestampMillis() {
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mBackingStore.getTimestamp() / 1000000L;
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final boolean isReadOnly() {
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mReadOnly;
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameValue asFrameValue() {
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return FrameValue.create(mBackingStore);
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameValues asFrameValues() {
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return FrameValues.create(mBackingStore);
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameBuffer1D asFrameBuffer1D() {
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return FrameBuffer1D.create(mBackingStore);
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameBuffer2D asFrameBuffer2D() {
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return FrameBuffer2D.create(mBackingStore);
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final FrameImage2D asFrameImage2D() {
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return FrameImage2D.create(mBackingStore);
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String toString() {
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return "Frame[" + getType().toString() + "]: " + mBackingStore;
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean equals(Object object) {
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return object instanceof Frame && ((Frame)object).mBackingStore == mBackingStore;
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static Frame create(FrameType type, int[] dimensions) {
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameManager manager = FrameManager.current();
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (manager == null) {
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Attempting to create new Frame outside of "
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + "FrameManager context!");
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return new Frame(type, dimensions, manager);
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final Frame release() {
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackingStore = mBackingStore.release();
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mBackingStore != null ? this : null;
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final Frame retain() {
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackingStore = mBackingStore.retain();
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return this;
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void unlock() {
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!mBackingStore.unlock()) {
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Attempting to unlock frame that is not locked!");
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public int[] getDimensions() {
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] dim = mBackingStore.getDimensions();
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return dim != null ? Arrays.copyOf(dim, dim.length) : null;
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    Frame(FrameType type, int[] dimensions, FrameManager manager) {
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackingStore = new BackingStore(type, dimensions, manager);
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    Frame(BackingStore backingStore) {
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackingStore = backingStore;
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    final void assertAccessible(int mode) {
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Make sure frame is in write-mode
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mReadOnly && mode == MODE_WRITE) {
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Attempting to write to read-only frame " + this + "!");
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    final void setReadOnly(boolean readOnly) {
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mReadOnly = readOnly;
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void resize(int[] newDims) {
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int[] oldDims = mBackingStore.getDimensions();
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int oldCount = oldDims == null ? 0 : oldDims.length;
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int newCount = newDims == null ? 0 : newDims.length;
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (oldCount != newCount) {
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Cannot resize " + oldCount + "-dimensional "
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + "Frame to " + newCount + "-dimensional Frame!");
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else if (newDims != null && !Arrays.equals(oldDims, newDims)) {
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBackingStore.resize(newDims);
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    Frame makeCpuCopy(FrameManager frameManager) {
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Frame frame = new Frame(getType(), getDimensions(), frameManager);
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        frame.mBackingStore.importStore(mBackingStore);
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return frame;
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
204