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 package androidx.media.filterfw; 18 19 /** 20 * Output ports are the data emitting ports of filters. 21 * <p> 22 * Filters push data frames onto output-ports, which in turn push them onto their connected input 23 * ports. Output ports must be connected to an input port before data can be pushed onto them. 24 * Input and output ports share their Frame slot, meaning that when a frame is waiting on an output 25 * port, it is also waiting on the connected input port. 26 * </p><p> 27 * Only one frame can be pushed onto an output port at a time. In other words, a Frame must first 28 * be consumed by the target filter before a new frame can be pushed on the output port. If the 29 * output port is set to wait until it becomes free (see {@link #setWaitsUntilAvailable(boolean)}), 30 * it is guaranteed to be available when {@code onProcess()} is called. This is the default setting. 31 * </p> 32 */ 33 public final class OutputPort { 34 35 private Filter mFilter; 36 private String mName; 37 private Signature.PortInfo mInfo; 38 private FrameQueue.Builder mQueueBuilder = null; 39 private FrameQueue mQueue = null; 40 private boolean mWaitsUntilAvailable = true; 41 private InputPort mTarget = null; 42 43 /** 44 * Returns true, if this port is connected to a target port. 45 * @return true, if this port is connected to a target port. 46 */ isConnected()47 public boolean isConnected() { 48 return mTarget != null; 49 } 50 51 /** 52 * Returns true, if there is no frame waiting on this port. 53 * @return true, if no Frame instance is waiting on this port. 54 */ isAvailable()55 public boolean isAvailable() { 56 return mQueue == null || mQueue.canPush(); 57 } 58 59 /** 60 * Returns a frame for writing. 61 * 62 * Call this method to fetch a new frame to write into. When you have finished writing the 63 * frame data, you can push it into the output queue using {@link #pushFrame(Frame)}. Note, 64 * that the Frame returned is owned by the queue. If you wish to hold on to the frame, you 65 * must detach it. 66 * 67 * @param dimensions the size of the Frame you wish to obtain. 68 * @return a writable Frame instance. 69 */ fetchAvailableFrame(int[] dimensions)70 public Frame fetchAvailableFrame(int[] dimensions) { 71 Frame frame = getQueue().fetchAvailableFrame(dimensions); 72 if (frame != null) { 73 //Log.i("OutputPort", "Adding frame " + frame + " to auto-release pool"); 74 mFilter.addAutoReleaseFrame(frame); 75 } 76 return frame; 77 } 78 79 /** 80 * Pushes a frame onto this output port. 81 * 82 * This is typically a Frame instance you obtained by previously calling 83 * {@link #fetchAvailableFrame(int[])}, but may come from other sources such as an input port 84 * that is attached to this output port. 85 * 86 * Once you have pushed a frame to an output, you may no longer modify it as it may be shared 87 * among other filters. 88 * 89 * @param frame the frame to push to the output queue. 90 */ pushFrame(Frame frame)91 public void pushFrame(Frame frame) { 92 // Some queues allow pushing without fetching, so we need to make sure queue is open 93 // before pushing! 94 long timestamp = frame.getTimestamp(); 95 if (timestamp == Frame.TIMESTAMP_NOT_SET) 96 frame.setTimestamp(mFilter.getCurrentTimestamp()); 97 getQueue().pushFrame(frame); 98 } 99 100 /** 101 * Sets whether to wait until this port becomes available before processing. 102 * When set to true, the Filter will not be scheduled for processing unless there is no Frame 103 * waiting on this port. The default value is true. 104 * 105 * @param wait true, if filter should wait for the port to become available before processing. 106 * @see #waitsUntilAvailable() 107 */ setWaitsUntilAvailable(boolean wait)108 public void setWaitsUntilAvailable(boolean wait) { 109 mWaitsUntilAvailable = wait; 110 } 111 112 /** 113 * Returns whether the filter waits until this port is available before processing. 114 * @return true, if the filter waits until this port is available before processing. 115 * @see #setWaitsUntilAvailable(boolean) 116 */ waitsUntilAvailable()117 public boolean waitsUntilAvailable() { 118 return mWaitsUntilAvailable; 119 } 120 121 /** 122 * Returns the output port's name. 123 * This is the name that was specified when the output port was connected. 124 * 125 * @return the output port's name. 126 */ getName()127 public String getName() { 128 return mName; 129 } 130 131 /** 132 * Return the filter object that this port belongs to. 133 * 134 * @return the output port's filter. 135 */ getFilter()136 public Filter getFilter() { 137 return mFilter; 138 } 139 140 @Override toString()141 public String toString() { 142 return mFilter.getName() + ":" + mName; 143 } 144 OutputPort(Filter filter, String name, Signature.PortInfo info)145 OutputPort(Filter filter, String name, Signature.PortInfo info) { 146 mFilter = filter; 147 mName = name; 148 mInfo = info; 149 } 150 setTarget(InputPort target)151 void setTarget(InputPort target) { 152 mTarget = target; 153 } 154 155 /** 156 * Return the (input) port that this output port is connected to. 157 * 158 * @return the connected port, null if not connected. 159 */ getTarget()160 public InputPort getTarget() { 161 return mTarget; 162 } 163 getQueue()164 FrameQueue getQueue() { 165 return mQueue; 166 } 167 setQueue(FrameQueue queue)168 void setQueue(FrameQueue queue) { 169 mQueue = queue; 170 mQueueBuilder = null; 171 } 172 onOpen(FrameQueue.Builder builder)173 void onOpen(FrameQueue.Builder builder) { 174 mQueueBuilder = builder; 175 mQueueBuilder.setWriteType(mInfo.type); 176 mFilter.onOutputPortOpen(this); 177 } 178 isOpen()179 boolean isOpen() { 180 return mQueue != null; 181 } 182 conditionsMet()183 final boolean conditionsMet() { 184 return !mWaitsUntilAvailable || isAvailable(); 185 } 186 clear()187 void clear() { 188 if (mQueue != null) { 189 mQueue.clear(); 190 } 191 } 192 } 193 194