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.lang.reflect.Field;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Input ports are the receiving ports of frames in a filter.
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * InputPort instances receive Frame data from connected OutputPort instances of a previous filter.
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Frames flow from output ports to input ports. Filters can process frame data by calling
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #pullFrame()} on an input port. If the input port is set to wait for an input frame
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * (see {@link #setWaitsForFrame(boolean)}), there is guaranteed to be Frame on the port before
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@code onProcess()} is called. This is the default setting. Otherwise, calling
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #pullFrame()} may return a value of {@code null}.
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p/><p>
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * InputPorts may be bound to fields of the Filter. When an input port is bound to a field, Frame
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * values will be assigned to the field once a Frame is received on that port. The Frame value must
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * be of a type that is compatible with the field type.
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * </p>
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class InputPort {
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Filter mFilter;
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private String mName;
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Signature.PortInfo mInfo;
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private FrameListener mListener = null;
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private FrameQueue.Builder mQueueBuilder = null;
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private FrameQueue mQueue = null;
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mWaitForFrame = true;
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mAutoPullEnabled = false;
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public interface FrameListener {
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void onFrameReceived(InputPort port, Frame frame);
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private class FieldBinding implements FrameListener {
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Field mField;
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public FieldBinding(Field field) {
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mField = field;
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void onFrameReceived(InputPort port, Frame frame) {
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            try {
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if(port.mInfo.type.getNumberOfDimensions() > 0) {
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    FrameValues frameValues = frame.asFrameValues();
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mField.set(mFilter, frameValues.getValues());
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    FrameValue frameValue = frame.asFrameValue();
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mField.set(mFilter, frameValue.getValue());
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } catch (Exception e) {
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Assigning frame " + frame + " to field "
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + mField + " of filter " + mFilter + " caused exception!", e);
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Attach this input port to an output port for frame passing.
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Use this method whenever you plan on passing a Frame through from an input port to an
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * output port. This must be called from inside
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link Filter#onInputPortAttached(InputPort) onInputPortAttached}.
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param outputPort the output port that Frames will be pushed to.
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void attachToOutputPort(OutputPort outputPort) {
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertInAttachmentStage();
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFilter.openOutputPort(outputPort);
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder.attachQueue(outputPort.getQueue());
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Bind this input port to the specified listener.
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Use this when you wish to be notified of incoming frames. The listener method
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link FrameListener#onFrameReceived(InputPort, Frame)} will be called once a Frame is pulled
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * on this port. Typically this is called from inside
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link Filter#onInputPortAttached(InputPort) onInputPortAttached}, and used in
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * conjunction with {@link #setAutoPullEnabled(boolean)}. Overrides any previous bindings.
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param listener the listener to handle incoming Frames.
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void bindToListener(FrameListener listener) {
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertInAttachmentStage();
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mListener = listener;
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Bind this input port to the specified field.
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Use this when you wish to pull frames directly into a field of the filter. This requires
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * that the input frames can be interpreted as object-based frames of the field's class.
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Overrides any previous bindings.
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically called from inside
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link Filter#onInputPortAttached(InputPort) onInputPortAttached}, and used in
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * conjunction with {@link #setAutoPullEnabled(boolean)}.
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param field the field to pull frame data into.
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #bindToFieldNamed(String)
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #setAutoPullEnabled(boolean)
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void bindToField(Field field) {
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertInAttachmentStage();
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mListener = new FieldBinding(field);
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Bind this input port to the field with the specified name.
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Use this when you wish to pull frames directly into a field of the filter. This requires
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * that the input frames can be interpreted as object-based frames of the field's class.
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Overrides any previous bindings.
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically called from inside
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * {@link Filter#onInputPortAttached(InputPort) onInputPortAttached}, and used in
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * conjunction with {@link #setAutoPullEnabled(boolean)}.
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param fieldName the field to pull frame data into.
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #bindToField(Field)
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #setAutoPullEnabled(boolean)
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void bindToFieldNamed(String fieldName) {
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Field field = findFieldNamed(fieldName, mFilter.getClass());
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (field == null) {
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Attempting to bind to unknown field '"
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + fieldName + "'!");
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        bindToField(field);
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Set whether the InputPort automatically pulls frames.
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically only used when the port is bound to another target.
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param enabled true, if frames should be automatically pulled on this port.
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setAutoPullEnabled(boolean enabled) {
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mAutoPullEnabled = enabled;
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns whether the InputPort automatically pulls frames.
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if frames are automatically pulled on this port.
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean isAutoPullEnabled() {
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mAutoPullEnabled;
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Pull a waiting a frame from the port.
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Call this to pull a frame from the input port for processing. If no frame is waiting on the
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * input port, returns null. After this call the port will have no Frame waiting (empty port).
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Note, that this returns a frame owned by the input queue. You must detach the frame if you
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * wish to hold on to it.
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return Frame instance, or null if no frame is available for pulling.
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public synchronized Frame pullFrame() {
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mQueue == null) {
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Cannot pull frame from closed input port!");
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Frame frame = mQueue.pullFrame();
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (frame != null) {
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mListener != null) {
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mListener.onFrameReceived(this, frame);
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.i("InputPort", "Adding frame " + frame + " to auto-release pool");
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFilter.addAutoReleaseFrame(frame);
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            long timestamp = frame.getTimestamp();
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (timestamp != Frame.TIMESTAMP_NOT_SET) {
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mFilter.onPulledFrameWithTimestamp(frame.getTimestamp());
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return frame;
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public synchronized Frame peek() {
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mQueue == null) {
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Cannot pull frame from closed input port!");
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue.peek();
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if the port is connected.
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if there is an output port that connects to this port.
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean isConnected() {
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue != null;
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if there is a frame waiting on this port.
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if there is a frame waiting on this port.
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public synchronized boolean hasFrame() {
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue != null && mQueue.canPull();
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Sets whether to wait for a frame on this port before processing.
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * When set to true, the Filter will not be scheduled for processing unless there is a Frame
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * waiting on this port. The default value is true.
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param wait true, if the Filter should wait for a Frame before processing.
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #waitsForFrame()
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setWaitsForFrame(boolean wait) {
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mWaitForFrame = wait;
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns whether the filter waits for a frame on this port before processing.
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if the filter waits for a frame on this port before processing.
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #setWaitsForFrame(boolean)
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean waitsForFrame() {
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mWaitForFrame;
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the input port's name.
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is the name that was specified when the input port was connected.
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the input port's name.
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String getName() {
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mName;
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the FrameType of this port.
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is the type that was specified when the input port was declared.
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the input port's FrameType.
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public FrameType getType() {
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return getQueue().getType();
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Return the filter object that this port belongs to.
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the input port's filter.
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Filter getFilter() {
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mFilter;
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @Override
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public String toString() {
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mFilter.getName() + ":" + mName;
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Internal only ///////////////////////////////////////////////////////////////////////////////
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    InputPort(Filter filter, String name, Signature.PortInfo info) {
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFilter = filter;
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mName = name;
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mInfo = info;
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    boolean conditionsMet() {
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return !mWaitForFrame || hasFrame();
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void onOpen(FrameQueue.Builder builder) {
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder = builder;
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder.setReadType(mInfo.type);
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFilter.onInputPortOpen(this);
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void setQueue(FrameQueue queue) {
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueue = queue;
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mQueueBuilder = null;
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    FrameQueue getQueue() {
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mQueue;
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void clear() {
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mQueue != null) {
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mQueue.clear();
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void assertInAttachmentStage() {
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mQueueBuilder == null) {
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Attempting to attach port while not in attachment "
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + "stage!");
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Field findFieldNamed(String fieldName, Class<?> clazz) {
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Field field = null;
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        try {
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            field = clazz.getDeclaredField(fieldName);
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            field.setAccessible(true);
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } catch (NoSuchFieldException e) {
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Class<?> superClass = clazz.getSuperclass();
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (superClass != null) {
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                field = findFieldNamed(fieldName, superClass);
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return field;
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
328