Home | History | Annotate | Download | only in filterfw
      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      */
     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      */
     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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    136     public Filter getFilter() {
    137         return mFilter;
    138     }
    139 
    140     @Override
    141     public String toString() {
    142         return mFilter.getName() + ":" + mName;
    143     }
    144 
    145     OutputPort(Filter filter, String name, Signature.PortInfo info) {
    146         mFilter = filter;
    147         mName = name;
    148         mInfo = info;
    149     }
    150 
    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      */
    160     public InputPort getTarget() {
    161         return mTarget;
    162     }
    163 
    164     FrameQueue getQueue() {
    165         return mQueue;
    166     }
    167 
    168     void setQueue(FrameQueue queue) {
    169         mQueue = queue;
    170         mQueueBuilder = null;
    171     }
    172 
    173     void onOpen(FrameQueue.Builder builder) {
    174         mQueueBuilder = builder;
    175         mQueueBuilder.setWriteType(mInfo.type);
    176         mFilter.onOutputPortOpen(this);
    177     }
    178 
    179     boolean isOpen() {
    180         return mQueue != null;
    181     }
    182 
    183     final boolean conditionsMet() {
    184         return !mWaitsUntilAvailable || isAvailable();
    185     }
    186 
    187     void clear() {
    188         if (mQueue != null) {
    189             mQueue.clear();
    190         }
    191     }
    192 }
    193 
    194