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 Hendricks/**
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Output ports are the data emitting ports of filters.
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Filters push data frames onto output-ports, which in turn push them onto their connected input
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * ports. Output ports must be connected to an input port before data can be pushed onto them.
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Input and output ports share their Frame slot, meaning that when a frame is waiting on an output
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * port, it is also waiting on the connected input port.
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * </p><p>
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Only one frame can be pushed onto an output port at a time. In other words, a Frame must first
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * be consumed by the target filter before a new frame can be pushed on the output port. If the
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * output port is set to wait until it becomes free (see {@link #setWaitsUntilAvailable(boolean)}),
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * it is guaranteed to be available when {@code onProcess()} is called. This is the default setting.
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * </p>
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class OutputPort {
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Filter mFilter;
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private String mName;
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Signature.PortInfo mInfo;
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private FrameQueue.Builder mQueueBuilder = null;
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private FrameQueue mQueue = null;
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mWaitsUntilAvailable = true;
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private InputPort mTarget = null;
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if this port is connected to a target port.
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if this port is connected to a target port.
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean isConnected() {
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mTarget != null;
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if there is no frame waiting on this port.
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if no Frame instance is waiting on this port.
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean isAvailable() {
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue == null || mQueue.canPush();
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns a frame for writing.
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Call this method to fetch a new frame to write into. When you have finished writing the
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * frame data, you can push it into the output queue using {@link #pushFrame(Frame)}. Note,
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * that the Frame returned is owned by the queue. If you wish to hold on to the frame, you
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * must detach it.
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param dimensions the size of the Frame you wish to obtain.
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return a writable Frame instance.
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Frame fetchAvailableFrame(int[] dimensions) {
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Frame frame = getQueue().fetchAvailableFrame(dimensions);
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (frame != null) {
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.i("OutputPort", "Adding frame " + frame + " to auto-release pool");
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFilter.addAutoReleaseFrame(frame);
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return frame;
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Pushes a frame onto this output port.
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically a Frame instance you obtained by previously calling
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link #fetchAvailableFrame(int[])}, but may come from other sources such as an input port
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * that is attached to this output port.
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Once you have pushed a frame to an output, you may no longer modify it as it may be shared
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * among other filters.
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param frame the frame to push to the output queue.
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void pushFrame(Frame frame) {
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Some queues allow pushing without fetching, so we need to make sure queue is open
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // before pushing!
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        long timestamp = frame.getTimestamp();
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (timestamp == Frame.TIMESTAMP_NOT_SET)
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            frame.setTimestamp(mFilter.getCurrentTimestamp());
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        getQueue().pushFrame(frame);
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Sets whether to wait until this port becomes available before processing.
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * When set to true, the Filter will not be scheduled for processing unless there is no Frame
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * waiting on this port. The default value is true.
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param wait true, if filter should wait for the port to become available before processing.
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #waitsUntilAvailable()
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setWaitsUntilAvailable(boolean wait) {
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mWaitsUntilAvailable = wait;
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns whether the filter waits until this port is available before processing.
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if the filter waits until this port is available before processing.
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #setWaitsUntilAvailable(boolean)
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean waitsUntilAvailable() {
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mWaitsUntilAvailable;
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the output port's name.
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is the name that was specified when the output port was connected.
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the output port's name.
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String getName() {
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mName;
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Return the filter object that this port belongs to.
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the output port's filter.
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Filter getFilter() {
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mFilter;
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String toString() {
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mFilter.getName() + ":" + mName;
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    OutputPort(Filter filter, String name, Signature.PortInfo info) {
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFilter = filter;
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mName = name;
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mInfo = info;
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void setTarget(InputPort target) {
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mTarget = target;
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Return the (input) port that this output port is connected to.
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the connected port, null if not connected.
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public InputPort getTarget() {
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mTarget;
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    FrameQueue getQueue() {
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue;
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void setQueue(FrameQueue queue) {
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueue = queue;
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder = null;
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void onOpen(FrameQueue.Builder builder) {
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder = builder;
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder.setWriteType(mInfo.type);
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFilter.onOutputPortOpen(this);
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    boolean isOpen() {
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue != null;
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    final boolean conditionsMet() {
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return !mWaitsUntilAvailable || isAvailable();
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void clear() {
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mQueue != null) {
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mQueue.clear();
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
194