Filter.java revision 692c3bf7a1c7e2d5b1066cf7a1b057e993742c87
130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/*
230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project
330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License");
530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License.
630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at
730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *            http://www.apache.org/licenses/LICENSE-2.0
930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software
1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS,
1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and
1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License.
1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */
1630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipackage android.filterfw.core;
1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.content.Context;
21692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Rennimport android.filterfw.core.FilterContext;
2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FilterPort;
2330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FrameManager;
2430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.KeyValueMap;
2530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Protocol;
2630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.ProtocolException;
2730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.util.Log;
2830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport java.util.HashMap;
3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport java.util.HashSet;
3130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport java.util.LinkedList;
3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport java.util.Set;
3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipublic abstract class Filter {
3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_WAIT_FOR_ALL_INPUTS   = 0x0001;
3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_WAIT_FOR_ONE_INPUT    = 0x0002;
3830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_WAIT_FOR_FREE_OUTPUTS = 0x0004;
3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_WAIT_FOR_FREE_OUTPUT  = 0x0008;
4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_PAUSE                 = 0x0010;
4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_SLEEP                 = 0x0020;
4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_READY                 = 0x0040;
4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_FINISHED              = 0x0080;
4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public static final int STATUS_ERROR                 = 0x0100;
4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private String mName;
4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private int mInputCount = -1;
5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private int mOutputCount = -1;
5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private FilterPort[] mInputPorts;
5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private FilterPort[] mOutputPorts;
5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private HashMap<String, FilterPort> mInputPortNames;
5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private HashMap<String, FilterPort> mOutputPortNames;
5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private HashSet<Frame> mPulledFrames;
6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private KeyValueMap mParameters;
6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private Protocol mFilterProtocol;
6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private int mStatus = 0;
6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private boolean mIsOpen = false;
6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public Filter(String name) {
6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mName = name;
6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mPulledFrames = new HashSet<Frame>();
7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mStatus = STATUS_READY;
7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void initWithParameterMap(KeyValueMap parameters) throws ProtocolException {
7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.assertConformsToProtocol(getProtocol());
7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mParameters = parameters;
7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        setParameters(parameters, false);
7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        initFilter();
7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        setupIOPorts();
7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void initWithParameterString(String assignments) throws ProtocolException {
8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        KeyValueMap parameters = new KeyValueMap();
8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.readAssignments(assignments);
8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        initWithParameterMap(parameters);
8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void initWithParameterList(Object... keyValues) throws ProtocolException {
8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        KeyValueMap parameters = new KeyValueMap();
8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.setKeyValues(keyValues);
9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        initWithParameterMap(parameters);
9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void init() throws ProtocolException {
9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        KeyValueMap parameters = new KeyValueMap();
9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.assertConformsToProtocol(getProtocol());
9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        initWithParameterMap(parameters);
9730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
9930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void updateParameterMap(KeyValueMap parameters) throws ProtocolException {
10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mParameters = getProtocol().updateKVMap(mParameters, parameters);
10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        synchronized(this) {
10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            setParameters(parameters, true);
10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parametersUpdated(parameters.keySet());
10530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final void updateParameterList(Object... keyValues) throws ProtocolException {
10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        KeyValueMap parameters = new KeyValueMap();
10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.setKeyValues(keyValues);
11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        updateParameterMap(parameters);
11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final KeyValueMap getParameters() {
11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mParameters;
11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final Protocol getProtocol() {
11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (mFilterProtocol == null) {
11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mFilterProtocol = createParameterProtocol();
12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
12130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mFilterProtocol;
12230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public String getFilterClassName() {
12530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return getClass().getSimpleName();
12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
12730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final String getName() {
12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mName;
13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public boolean isOpen() {
13330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mIsOpen;
13430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
13530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
13630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected Protocol createParameterProtocol() {
13730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return Protocol.fromFilter(this);
13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
14030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected void setParameters(KeyValueMap parameters, boolean isUpdate) {
14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        parameters.setFilterParameters(this);
14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected void initFilter() {
14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
147692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    protected void prepare(FilterContext context) {
14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected void parametersUpdated(Set<String> updated) {
15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
15230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public abstract String[] getInputNames();
15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public abstract String[] getOutputNames();
15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
157692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public abstract boolean acceptsInputFormat(int index, FrameFormat format);
15830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
159b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn    public FrameFormat getInputFormat(int index) {
160b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        FilterPort inPort = getInputPortAtIndex(index);
161b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        return inPort.getFormat();
162b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn    }
163b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn
164692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public abstract FrameFormat getOutputFormat(int index);
165692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn
166692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public int open(FilterContext context) {
16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        int result = 0;
16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (getNumberOfInputs() > 0) {
16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            result |= STATUS_WAIT_FOR_ALL_INPUTS;
17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (getNumberOfOutputs() > 0) {
17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            result |= STATUS_WAIT_FOR_FREE_OUTPUTS;
17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return result;
17530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
177692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public abstract int process(FilterContext context);
17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public int getSleepDelay() {
18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return 250;
18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
183692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public void close(FilterContext context) {
18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
186692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    public void tearDown(FilterContext context) {
18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final int getNumberOfInputs() {
19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (mInputCount < 0) {
19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            String[] names = getInputNames();
19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mInputCount = names != null ? names.length : 0;
19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
19430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mInputCount;
19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final int getNumberOfOutputs() {
19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (mOutputCount < 0) {
19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            String[] names = getOutputNames();
20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mOutputCount = names != null ? names.length : 0;
20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mOutputCount;
20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final FilterPort getInputPort(String portName) {
206b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        FilterPort result = mInputPortNames.get(portName);
207b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        if (result == null) {
208b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn            throw new IllegalArgumentException("Unknown input port '" + portName + "' on filter "
209b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn                + this + "!");
210b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        }
211b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        return result;
21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final FilterPort getOutputPort(String portName) {
215b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        FilterPort result = mOutputPortNames.get(portName);
216b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        if (result == null) {
217b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn            throw new IllegalArgumentException("Unknown output port '" + portName + "' on filter "
218b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn                + this + "!");
219b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        }
220b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        return result;
22130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
22230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final FilterPort getInputPortAtIndex(int index) {
224b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        if (index >= mInputPorts.length) {
225b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn            throw new IllegalArgumentException("Input port index " + index + " on filter " + this
226b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn                + " out of bounds!");
227b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        }
228b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        return mInputPorts[index];
22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public final FilterPort getOutputPortAtIndex(int index) {
232b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        if (index >= mOutputPorts.length) {
233b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn            throw new IllegalArgumentException("Output port index " + index + " on filter " + this
234b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn                + " out of bounds!");
235b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        }
236b64fe6f6bbad306e4b10fafefcbdd981ec82a5baMarius Renn        return mOutputPorts[index];
23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected final void putOutput(int index, Frame frame) {
24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (index >= mOutputPorts.length) {
24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            throw new RuntimeException(
24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                "Attempting to push output to invalid port index " + index + "!");
24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if (mOutputPorts[index] == null) {
24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            throw new RuntimeException(
24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                "Attempting to push output to null port at index " + index + "!");
24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if (mOutputPorts[index].getConnection().putFrame(frame)) {
24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            frame.markReadOnly();
24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else {
24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            throw new RuntimeException("Cannot push output onto blocked connection!");
25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    protected final Frame pullInput(int index) {
25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (index >= mInputPorts.length) {
25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            throw new RuntimeException(
25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                "Attempting to pull input from invalid port index " + index + "!");
25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if (mInputPorts[index] == null) {
25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            throw new RuntimeException(
25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                "Attempting to pull input from null port at index " + index + "!");
26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        FilterConnection connection = mInputPorts[index].getConnection();
26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        Frame result = connection.getFrame().retain();
26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        connection.clearFrame();
26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mPulledFrames.add(result);
26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return result;
26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    public String toString() {
26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return "'" + getName() + "' (" + getFilterClassName() + ")";
27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Core internal methods ///////////////////////////////////////////////////////////////////////
27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final void setInputFrame(int index, Frame frame) {
27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (index < mInputPorts.length && mInputPorts[index] != null) {
27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mInputPorts[index].getConnection().putFrame(frame);
27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final synchronized boolean checkStatus(int flag) {
28030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return (mStatus & flag) != 0;
28130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
28330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final synchronized void unsetStatus(int flag) {
28430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mStatus &= ~flag;
28530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
28630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
287692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    final boolean performOpen(FilterContext context) {
28830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        synchronized(this) {
289692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn            mStatus = open(context);
29030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
29130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mIsOpen = true;
29230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mStatus != STATUS_ERROR;
29330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
29430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
295692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    final int performProcess(FilterContext context) {
29630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        synchronized(this) {
297692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn            mStatus = process(context);
298692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn            releasePulledFrames(context);
29930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
30030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return mStatus;
30130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
30230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
303692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    final void performClose(FilterContext context) {
30430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        synchronized(this) {
30530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mIsOpen = false;
306692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn            close(context);
30730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
30830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
30930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
31030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    synchronized final boolean canProcess() {
31130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Check general filter state
31230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if ((mStatus & STATUS_READY) != 0) {
31330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            return true;
31430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if (((mStatus & STATUS_FINISHED) != 0) ||
31530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                   ((mStatus & STATUS_ERROR) != 0)    ||
31630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                   ((mStatus & STATUS_SLEEP) != 0)) {
31730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            return false;
31830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
31930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
32030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Check input waiting state
32130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if ((mStatus & STATUS_WAIT_FOR_ALL_INPUTS) != 0) {
32230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (inputFramesWaiting() != getNumberOfInputs()) return false;
32330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if ((mStatus & STATUS_WAIT_FOR_ONE_INPUT) != 0) {
32430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (inputFramesWaiting() == 0) return false;
32530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
32630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
32730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        // Check output waiting state
32830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if ((mStatus & STATUS_WAIT_FOR_FREE_OUTPUTS) != 0) {
32930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (outputFramesWaiting() != 0) return false;
33030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        } else if ((mStatus & STATUS_WAIT_FOR_FREE_OUTPUT) != 0) {
33130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (outputFramesWaiting() == getNumberOfOutputs()) return false;
33230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
33330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
33430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return true;
33530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
33630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
33730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final boolean allInputsConnected() {
33830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mInputPorts) {
33930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (!port.isConnected()) {
34030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                return false;
34130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
34230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
34330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return true;
34430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
34530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
34630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final boolean allOutputsConnected() {
34730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mOutputPorts) {
34830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (!port.isConnected()) {
34930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                return false;
35030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
35130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
35230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return true;
35330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
35430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
35530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    final LinkedList<Filter> connectedFilters() {
35630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        LinkedList<Filter> result = new LinkedList<Filter>();
35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mInputPorts) {
35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (port.isConnected()) {
35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                result.add(port.getSourceFilter());
36030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
36130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
36230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mOutputPorts) {
36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (port.isConnected()) {
36430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                result.add(port.getTargetFilter());
36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return result;
36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
37030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Filter internal methods /////////////////////////////////////////////////////////////////////
37130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final void setupIOPorts() {
37230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mInputPorts = new FilterPort[getNumberOfInputs()];
37330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (int i = 0; i < mInputPorts.length; ++i) {
37430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mInputPorts[i] = new FilterPort(this, FilterPort.INPUT_PORT, i);
37530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
37630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
37730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mOutputPorts = new FilterPort[getNumberOfOutputs()];
37830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (int i = 0; i < mOutputPorts.length; ++i) {
37930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            mOutputPorts[i] = new FilterPort(this, FilterPort.OUTPUT_PORT, i);
38030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
38130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
38230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        setupIOPortNames();
38330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
38430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
38530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final void setupIOPortNames() {
38630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mInputPortNames = new HashMap<String, FilterPort>();
38730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mOutputPortNames = new HashMap<String, FilterPort>();
38830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
38930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        setupInputPortNames();
39030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        setupOutputPortNames();
39130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
39230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
39330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final void setupInputPortNames() {
39430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        int i = 0;
39530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        String[] names = getInputNames();
39630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (names != null) {
39730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            for (String name : names) {
39830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                if (name != null) {
39930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                    mInputPortNames.put(name, mInputPorts[i++]);
40030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                } else {
40130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                    throw new RuntimeException("Got null name for input port " + i +
40230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                               " on Filter " + this);
40330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                }
40430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
40530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
40630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
40730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
40830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final void setupOutputPortNames() {
40930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        int i = 0;
41030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        String[] names = getOutputNames();
41130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (names != null) {
41230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            for (String name : names) {
41330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                if (name != null) {
41430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                    mOutputPortNames.put(name, mOutputPorts[i++]);
41530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                } else {
41630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                    throw new RuntimeException("Got null name for output port " + i +
41730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                                               " on Filter " + this);
41830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                }
41930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
42030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
42130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
42230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
423692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn    private final void releasePulledFrames(FilterContext context) {
42430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (Frame frame : mPulledFrames) {
425692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn            context.getFrameManager().releaseFrame(frame);
42630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
42730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        mPulledFrames.clear();
42830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
42930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
43030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final int inputFramesWaiting() {
43130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        int c = 0;
43230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mInputPorts) {
43330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (port.getConnection().hasFrame()) {
43430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                ++c;
43530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
43630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
43730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return c;
43830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
43930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
44030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    private final int outputFramesWaiting() {
44130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        int c = 0;
44230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        for (FilterPort port : mOutputPorts) {
44330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            if (port.getConnection().hasFrame()) {
44430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni                ++c;
44530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni            }
44630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        }
44730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        return c;
44830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
44930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
45030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
451