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"); you may not use this file except 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * in compliance with the License. You may obtain a copy of the License at 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software distributed under the License 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * or implied. See the License for the specific language governing permissions and limitations under 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the License. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw; 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.ConditionVariable; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.SystemClock; 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashSet; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Set; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Stack; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.concurrent.LinkedBlockingQueue; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A GraphRunner schedules and executes the filter nodes of a graph. 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Typically, you create a GraphRunner given a FilterGraph instance, and execute it by calling 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #start(FilterGraph)}. 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The scheduling strategy determines how the filter nodes are selected 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * for scheduling. More precisely, given the set of nodes that can be scheduled, the scheduling 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * strategy determines which node of this set to select for execution. For instance, an LFU 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * scheduler (the default) chooses the node that has been executed the least amount of times. 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic final class GraphRunner { 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static int PRIORITY_SLEEP = -1; 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static int PRIORITY_STOP = -2; 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event BEGIN_EVENT = new Event(Event.BEGIN, null); 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event FLUSH_EVENT = new Event(Event.FLUSH, null); 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event HALT_EVENT = new Event(Event.HALT, null); 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event KILL_EVENT = new Event(Event.KILL, null); 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event PAUSE_EVENT = new Event(Event.PAUSE, null); 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event RELEASE_FRAMES_EVENT = new Event(Event.RELEASE_FRAMES, null); 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event RESTART_EVENT = new Event(Event.RESTART, null); 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event RESUME_EVENT = new Event(Event.RESUME, null); 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event STEP_EVENT = new Event(Event.STEP, null); 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Event STOP_EVENT = new Event(Event.STOP, null); 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static class State { 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STOPPED = 1; 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int PREPARING = 2; 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int RUNNING = 4; 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int PAUSED = 8; 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int HALTED = 16; 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mCurrent = STOPPED; 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized void setState(int newState) { 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCurrent = newState; 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized boolean check(int state) { 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return ((mCurrent & state) == state); 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized boolean addState(int state) { 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if ((mCurrent & state) != state) { 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCurrent |= state; 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return true; 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized boolean removeState(int state) { 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks boolean result = (mCurrent & state) == state; 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCurrent &= (~state); 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return result; 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized int current() { 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mCurrent; 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static class Event { 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int PREPARE = 1; 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int BEGIN = 2; 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STEP = 3; 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STOP = 4; 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int PAUSE = 6; 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int HALT = 7; 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int RESUME = 8; 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int RESTART = 9; 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int FLUSH = 10; 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int TEARDOWN = 11; 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int KILL = 12; 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int RELEASE_FRAMES = 13; 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int code; 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Object object; 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Event(int code, Object object) { 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks this.code = code; 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks this.object = object; 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final class GraphRunLoop implements Runnable { 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private State mState = new State(); 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final boolean mAllowOpenGL; 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private RenderTarget mRenderTarget = null; 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private LinkedBlockingQueue<Event> mEventQueue = new LinkedBlockingQueue<Event>(); 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Exception mCaughtException = null; 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean mClosedSuccessfully = true; 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Stack<Filter[]> mFilters = new Stack<Filter[]>(); 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Stack<SubListener> mSubListeners = new Stack<SubListener>(); 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Set<FilterGraph> mOpenedGraphs = new HashSet<FilterGraph>(); 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ConditionVariable mStopCondition = new ConditionVariable(true); 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void loop() { 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks boolean killed = false; 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks while (!killed) { 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Event event = nextEvent(); 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (event == null) continue; 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (event.code) { 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.PREPARE: 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onPrepare((FilterGraph)event.object); 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.BEGIN: 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onBegin(); 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.STEP: 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onStep(); 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.STOP: 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onStop(); 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.PAUSE: 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onPause(); 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.HALT: 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onHalt(); 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.RESUME: 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onResume(); 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.RESTART: 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onRestart(); 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.FLUSH: 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onFlush(); 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.TEARDOWN: 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onTearDown((FilterGraph)event.object); 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.KILL: 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks killed = true; 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case Event.RELEASE_FRAMES: 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onReleaseFrames(); 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (Exception e) { 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mCaughtException == null) { 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCaughtException = e; 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mClosedSuccessfully = true; 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks e.printStackTrace(); 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STOP_EVENT); 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Exception during exception recovery? Abort all processing. Do not 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // overwrite the original exception. 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mClosedSuccessfully = false; 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mEventQueue.clear(); 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks cleanUp(); 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphRunLoop(boolean allowOpenGL) { 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mAllowOpenGL = allowOpenGL; 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void run() { 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onInit(); 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks loop(); 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onDestroy(); 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void enterSubGraph(FilterGraph graph, SubListener listener) { 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.check(State.RUNNING)) { 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onOpenGraph(graph); 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mSubListeners.push(listener); 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void pushWakeEvent(Event event) { 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // This is of course not race-condition proof. The worst case is that the event 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // is pushed even though the queue was not empty, which is acceptible for our cases. 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mEventQueue.isEmpty()) { 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(event); 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void pushEvent(Event event) { 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mEventQueue.offer(event); 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void pushEvent(int eventId, Object object) { 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mEventQueue.offer(new Event(eventId, object)); 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean checkState(int state) { 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mState.check(state); 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public ConditionVariable getStopCondition() { 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mStopCondition; 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isOpenGLAllowed() { 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Does not need synchronization as mAllowOpenGL flag is final. 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mAllowOpenGL; 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Event nextEvent() { 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mEventQueue.take(); 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (InterruptedException e) { 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Ignore and keep going. 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.w("GraphRunner", "Event queue processing was interrupted."); 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return null; 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onPause() { 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mState.addState(State.PAUSED); 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onResume() { 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.removeState(State.PAUSED)) { 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.current() == State.RUNNING) { 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STEP_EVENT); 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onHalt() { 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.addState(State.HALTED) && mState.check(State.RUNNING)) { 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks closeAllFilters(); 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onRestart() { 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.removeState(State.HALTED)) { 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.current() == State.RUNNING) { 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STEP_EVENT); 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onDestroy() { 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFrameManager.destroyBackings(); 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mRenderTarget != null) { 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRenderTarget.release(); 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRenderTarget = null; 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onReleaseFrames() { 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFrameManager.destroyBackings(); 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onInit() { 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mThreadRunner.set(GraphRunner.this); 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (getContext().isOpenGLSupported()) { 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRenderTarget = RenderTarget.newTarget(1, 1); 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRenderTarget.focus(); 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onPrepare(FilterGraph graph) { 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.current() == State.STOPPED) { 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mState.setState(State.PREPARING); 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCaughtException = null; 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onOpenGraph(graph); 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onOpenGraph(FilterGraph graph) { 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks loadFilters(graph); 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOpenedGraphs.add(graph); 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler.prepare(currentFilters()); 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(BEGIN_EVENT); 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onBegin() { 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.current() == State.PREPARING) { 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mState.setState(State.RUNNING); 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STEP_EVENT); 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onStarve() { 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFilters.pop(); 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mFilters.empty()) { 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onStop(); 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SubListener listener = mSubListeners.pop(); 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (listener != null) { 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks listener.onSubGraphRunEnded(GraphRunner.this); 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler.prepare(currentFilters()); 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STEP_EVENT); 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onStop() { 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.check(State.RUNNING)) { 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Close filters if not already halted (and already closed) 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (!mState.check(State.HALTED)) { 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks closeAllFilters(); 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks cleanUp(); 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void cleanUp() { 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mState.setState(State.STOPPED); 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (flushOnClose()) { 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onFlush(); 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mOpenedGraphs.clear(); 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFilters.clear(); 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onRunnerStopped(mCaughtException, mClosedSuccessfully); 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mStopCondition.open(); 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onStep() { 347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.current() == State.RUNNING) { 348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter bestFilter = null; 349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks long maxPriority = PRIORITY_STOP; 350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler.beginStep(); 351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter[] filters = currentFilters(); 352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < filters.length; ++i) { 353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter filter = filters[i]; 354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks long priority = mScheduler.priorityForFilter(filter); 355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (priority > maxPriority) { 356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks maxPriority = priority; 357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks bestFilter = filter; 358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (maxPriority == PRIORITY_SLEEP) { 361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // NOOP: When going into sleep mode, we simply do not schedule another node. 362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If some other event (such as a resume()) does schedule, then we may schedule 363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // during sleeping. This is an edge case an irrelevant. (On the other hand, 364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // going into a dedicated "sleep state" requires highly complex synchronization 365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // to not "miss" a wake-up event. Thus we choose the more defensive approach 366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // here). 367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (maxPriority == PRIORITY_STOP) { 368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onStarve(); 369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scheduleFilter(bestFilter); 371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks pushEvent(STEP_EVENT); 372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.w("GraphRunner", "State is not running! (" + mState.current() + ")"); 375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onFlush() { 379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mState.check(State.HALTED) || mState.check(State.STOPPED)) { 380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (FilterGraph graph : mOpenedGraphs) { 381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks graph.flushFrames(); 382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onTearDown(FilterGraph graph) { 387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (Filter filter : graph.getAllFilters()) { 388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filter.performTearDown(); 389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks graph.wipe(); 391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void loadFilters(FilterGraph graph) { 394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter[] filters = graph.getAllFilters(); 395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFilters.push(filters); 396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void closeAllFilters() { 399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (FilterGraph graph : mOpenedGraphs) { 400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks closeFilters(graph); 401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void closeFilters(FilterGraph graph) { 405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // [Non-iterator looping] 406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.v("GraphRunner", "CLOSING FILTERS"); 407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Filter[] filters = graph.getAllFilters(); 408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks boolean isVerbose = isVerbose(); 409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < filters.length; ++i) { 410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (isVerbose) { 411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.i("GraphRunner", "Closing Filter " + filters[i] + "!"); 412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filters[i].softReset(); 414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Filter[] currentFilters() { 418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mFilters.peek(); 419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void scheduleFilter(Filter filter) { 422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks long scheduleTime = 0; 423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (isVerbose()) { 424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks scheduleTime = SystemClock.elapsedRealtime(); 425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.i("GraphRunner", scheduleTime + ": Scheduling " + filter + "!"); 426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filter.execute(); 428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (isVerbose()) { 429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks long nowTime = SystemClock.elapsedRealtime(); 430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.i("GraphRunner", 431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "-> Schedule time (" + filter + ") = " + (nowTime - scheduleTime) + " ms."); 432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // GraphRunner.Scheduler classes /////////////////////////////////////////////////////////////// 438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private interface Scheduler { 439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void prepare(Filter[] filters); 440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getStrategy(); 442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void beginStep(); 444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public long priorityForFilter(Filter filter); 446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private class LruScheduler implements Scheduler { 450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private long mNow; 452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void prepare(Filter[] filters) { 455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getStrategy() { 459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return STRATEGY_LRU; 460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void beginStep() { 464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // TODO(renn): We could probably do this with a simple GraphRunner counter that would 465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // represent GraphRunner local time. This would allow us to use integers instead of 466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // longs, and save us calls to the system clock. 467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mNow = SystemClock.elapsedRealtime(); 468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public long priorityForFilter(Filter filter) { 472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (filter.isSleeping()) { 473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return PRIORITY_SLEEP; 474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (filter.canSchedule()) { 475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mNow - filter.getLastScheduleTime(); 476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return PRIORITY_STOP; 478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private class LfuScheduler implements Scheduler { 484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final int MAX_PRIORITY = Integer.MAX_VALUE; 486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void prepare(Filter[] filters) { 489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // [Non-iterator looping] 490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < filters.length; ++i) { 491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filters[i].resetScheduleCount(); 492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getStrategy() { 497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return STRATEGY_LFU; 498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void beginStep() { 502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public long priorityForFilter(Filter filter) { 506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return filter.isSleeping() ? PRIORITY_SLEEP 507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks : (filter.canSchedule() ? (MAX_PRIORITY - filter.getScheduleCount()) 508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks : PRIORITY_STOP); 509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private class OneShotScheduler extends LfuScheduler { 514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mCurCount = 1; 515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void prepare(Filter[] filters) { 518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // [Non-iterator looping] 519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks for (int i = 0; i < filters.length; ++i) { 520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks filters[i].resetScheduleCount(); 521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getStrategy() { 526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return STRATEGY_ONESHOT; 527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void beginStep() { 531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public long priorityForFilter(Filter filter) { 535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return filter.getScheduleCount() < mCurCount ? super.priorityForFilter(filter) 536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks : PRIORITY_STOP; 537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // GraphRunner.Listener callback class ///////////////////////////////////////////////////////// 542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public interface Listener { 543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Callback method that is called when the runner completes a run. This method is called 545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * only if the graph completed without an error. 546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onGraphRunnerStopped(GraphRunner runner); 548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Callback method that is called when runner encounters an error. 551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Any exceptions thrown in the GraphRunner's thread will cause the run to abort. The 553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * thrown exception is passed to the listener in this method. If no listener is set, the 554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * exception message is logged to the error stream. You will not receive an 555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #onGraphRunnerStopped(GraphRunner)} callback in case of an error. 556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param exception the exception that was thrown. 558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param closedSuccessfully true, if the graph was closed successfully after the error. 559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onGraphRunnerError(Exception exception, boolean closedSuccessfully); 561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public interface SubListener { 564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onSubGraphRunEnded(GraphRunner runner); 565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 568227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Config class to setup a GraphRunner with a custom configuration. 569227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 570227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The configuration object is passed to the constructor. Any changes to it will not affect 571227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the created GraphRunner instance. 572227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 573227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static class Config { 574227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** The runner's thread priority. */ 575227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int threadPriority = Thread.NORM_PRIORITY; 576227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Whether to allow filters to use OpenGL or not. */ 577227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean allowOpenGL = true; 578227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 579227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 580227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Parameters shared between run-thread and GraphRunner frontend. */ 581227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private class RunParameters { 582227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Listener listener = null; 583227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isVerbose = false; 584227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean flushOnClose = true; 585227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 586227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 587227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // GraphRunner implementation ////////////////////////////////////////////////////////////////// 588227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Schedule strategy: From set of candidates, pick a random one. */ 589227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STRATEGY_RANDOM = 1; 590227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Schedule strategy: From set of candidates, pick node executed least recently executed. */ 591227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STRATEGY_LRU = 2; 592227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Schedule strategy: From set of candidates, pick node executed least number of times. */ 593227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STRATEGY_LFU = 3; 594227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Schedule strategy: Schedules no node more than once. */ 595227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int STRATEGY_ONESHOT = 4; 596227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 597227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final MffContext mContext; 598227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 599227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FilterGraph mRunningGraph = null; 600227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Set<FilterGraph> mGraphs = new HashSet<FilterGraph>(); 601227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 602227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Scheduler mScheduler; 603227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 604227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private GraphRunLoop mRunLoop; 605227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 606227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Thread mRunThread = null; 607227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 608227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private FrameManager mFrameManager = null; 609227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 610227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static ThreadLocal<GraphRunner> mThreadRunner = new ThreadLocal<GraphRunner>(); 611227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 612227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private RunParameters mParams = new RunParameters(); 613227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 614227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 615227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Creates a new GraphRunner with the default configuration. You must attach FilterGraph 616227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * instances to this runner before you can execute any of these graphs. 617227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 618227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param context The MffContext instance for this runner. 619227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 620227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphRunner(MffContext context) { 621227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext = context; 622227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks init(new Config()); 623227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 624227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 625227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 626227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Creates a new GraphRunner with the specified configuration. You must attach FilterGraph 627227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * instances to this runner before you can execute any of these graphs. 628227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 629227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param context The MffContext instance for this runner. 630227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param config A Config instance with the configuration of this runner. 631227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 632227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public GraphRunner(MffContext context, Config config) { 633227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext = context; 634227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks init(config); 635227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 636227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 637227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 638227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the currently running graph-runner. 639227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return The currently running graph-runner. 640227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 641227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static GraphRunner current() { 642227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mThreadRunner.get(); 643227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 644227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 645227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 646227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the graph that this runner is currently executing. Returns null if no graph is 647227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * currently being executed by this runner. 648227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 649227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the FilterGraph instance that this GraphRunner is executing. 650227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 651227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized FilterGraph getRunningGraph() { 652227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunningGraph; 653227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 654227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 655227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 656227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the context that this runner is bound to. 657227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 658227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the MffContext instance that this runner is bound to. 659227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 660227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public MffContext getContext() { 661227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mContext; 662227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 663227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 664227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 665227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Begins graph execution. The graph filters are scheduled and executed until processing 666227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * finishes or is stopped. 667227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 668227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public synchronized void start(FilterGraph graph) { 669227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (graph.mRunner != this) { 670227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Graph must be attached to runner!"); 671227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 672227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunningGraph = graph; 673227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.getStopCondition().close(); 674227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(Event.PREPARE, graph); 675227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 676227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 677227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 678227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Begin executing a sub-graph. This only succeeds if the current runner is already 679227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * executing. 680227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 681227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void enterSubGraph(FilterGraph graph, SubListener listener) { 682227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (Thread.currentThread() != mRunThread) { 683227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException("enterSubGraph must be called from the runner's thread!"); 684227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 685227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.enterSubGraph(graph, listener); 686227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 687227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 688227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 689227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Waits until graph execution has finished or stopped with an error. 690227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Care must be taken when using this method to not block the UI thread. This is typically 691227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * used when a graph is run in one-shot mode to compute a result. 692227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 693227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void waitUntilStop() { 694227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.getStopCondition().block(); 695227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 696227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 697227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 698227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Pauses graph execution. 699227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 700227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void pause() { 701227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(PAUSE_EVENT); 702227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 703227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 704227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 705227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Resumes graph execution after pausing. 706227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 707227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void resume() { 708227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(RESUME_EVENT); 709227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 710227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 711227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 712227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Stops graph execution. 713227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 714227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void stop() { 715227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(STOP_EVENT); 716227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 717227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 718227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 719227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the graph is currently being executed. A graph is considered to be running, 720227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * even if it is paused or in the process of being stopped. 721227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 722227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if the graph is currently being executed. 723227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 724227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isRunning() { 725227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return !mRunLoop.checkState(State.STOPPED); 726227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 727227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 728227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 729227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the graph is currently paused. 730227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 731227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if the graph is currently paused. 732227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 733227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isPaused() { 734227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunLoop.checkState(State.PAUSED); 735227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 736227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 737227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 738227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the graph is currently stopped. 739227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 740227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if the graph is currently stopped. 741227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 742227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isStopped() { 743227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunLoop.checkState(State.STOPPED); 744227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 745227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 746227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 747227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Sets the filter scheduling strategy. This method can not be called when the GraphRunner is 748227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * running. 749227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 750227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param strategy a constant specifying which scheduler strategy to use. 751227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws RuntimeException if the GraphRunner is running. 752227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalArgumentException if invalid strategy is specified. 753227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #getSchedulerStrategy() 754227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 755227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setSchedulerStrategy(int strategy) { 756227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (isRunning()) { 757227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new RuntimeException( 758227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "Attempting to change scheduling strategy on running " + "GraphRunner!"); 759227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 760227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks createScheduler(strategy); 761227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 762227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 763227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 764227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the current scheduling strategy. 765227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 766227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the scheduling strategy used by this GraphRunner. 767227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setSchedulerStrategy(int) 768227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 769227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getSchedulerStrategy() { 770227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mScheduler.getStrategy(); 771227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 772227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 773227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 774227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Set whether or not the runner is verbose. When set to true, the runner will output individual 775227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * scheduling steps that may help identify and debug problems in the graph structure. The 776227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * default is false. 777227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 778227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param isVerbose true, if the GraphRunner should log scheduling details. 779227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #isVerbose() 780227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 781227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setIsVerbose(boolean isVerbose) { 782227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 783227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParams.isVerbose = isVerbose; 784227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 785227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 786227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 787227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 788227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the GraphRunner is verbose. 789227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 790227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if the GraphRunner logs scheduling details. 791227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setIsVerbose(boolean) 792227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 793227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isVerbose() { 794227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 795227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mParams.isVerbose; 796227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 797227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 798227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 799227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 800227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether Filters of this GraphRunner can use OpenGL. 801227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 802227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Filters may use OpenGL if the MffContext supports OpenGL and the GraphRunner allows it. 803227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 804227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if Filters are allowed to use OpenGL. 805227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 806227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean isOpenGLSupported() { 807227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mRunLoop.isOpenGLAllowed() && mContext.isOpenGLSupported(); 808227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 809227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 810227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 811227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Enable flushing all frames from the graph when running completes. 812227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 813227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * If this is set to false, then frames may remain in the pipeline even after running completes. 814227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The default value is true. 815227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 816227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param flush true, if the GraphRunner should flush the graph when running completes. 817227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #flushOnClose() 818227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 819227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setFlushOnClose(boolean flush) { 820227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 821227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParams.flushOnClose = flush; 822227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 823227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 824227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 825227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 826227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns whether the GraphRunner flushes frames when running completes. 827227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 828227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return true, if the GraphRunner flushes frames when running completes. 829227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setFlushOnClose(boolean) 830227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 831227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean flushOnClose() { 832227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 833227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mParams.flushOnClose; 834227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 835227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 836227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 837227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 838227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Sets the listener for receiving runtime events. A GraphRunner.Listener instance can be used 839227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to determine when certain events occur during graph execution (and react on them). See the 840227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link GraphRunner.Listener} class for details. 841227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 842227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param listener the GraphRunner.Listener instance to set. 843227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #getListener() 844227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 845227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setListener(Listener listener) { 846227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 847227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParams.listener = listener; 848227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 849227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 850227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 851227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 852227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the currently assigned GraphRunner.Listener. 853227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 854227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the currently assigned GraphRunner.Listener instance. 855227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setListener(Listener) 856227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 857227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Listener getListener() { 858227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 859227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mParams.listener; 860227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 861227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 862227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 863227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 864227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the FrameManager that manages the runner's frames. 865227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 866227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the FrameManager instance that manages the runner's frames. 867227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 868227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public FrameManager getFrameManager() { 869227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mFrameManager; 870227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 871227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 872227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 873227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Tear down a GraphRunner and all its resources. 874227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 875227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You must make sure that before calling this, no more graphs are attached to this runner. 876227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Typically, graphs are removed from runners when they are torn down. 877227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 878227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalStateException if there are still graphs attached to this runner. 879227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 880227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void tearDown() { 881227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mGraphs) { 882227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (!mGraphs.isEmpty()) { 883227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalStateException("Attempting to tear down runner with " 884227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + mGraphs.size() + " graphs still attached!"); 885227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 886227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 887227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(KILL_EVENT); 888227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Wait for thread to complete, so that everything is torn down by the time we return. 889227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks try { 890227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunThread.join(); 891227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } catch (InterruptedException e) { 892227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.e("GraphRunner", "Error waiting for runner thread to finish!"); 893227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 894227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 895227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 896227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 897227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Release all frames managed by this runner. 898227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 899227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Note, that you must make sure no graphs are attached to this runner before calling this 900227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * method, as otherwise Filters in the graph may reference frames that are now released. 901227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 902227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: Eventually, this method should be removed. Instead we should have better analysis 903227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * that catches leaking frames from filters. 904227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 905227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @throws IllegalStateException if there are still graphs attached to this runner. 906227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 907227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void releaseFrames() { 908227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mGraphs) { 909227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (!mGraphs.isEmpty()) { 910227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalStateException("Attempting to release frames with " 911227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + mGraphs.size() + " graphs still attached!"); 912227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 913227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 914227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(RELEASE_FRAMES_EVENT); 915227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 916227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 917227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Core internal methods /////////////////////////////////////////////////////////////////////// 918227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void attachGraph(FilterGraph graph) { 919227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mGraphs) { 920227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mGraphs.add(graph); 921227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 922227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 923227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 924227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void signalWakeUp() { 925227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushWakeEvent(STEP_EVENT); 926227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 927227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 928227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void begin() { 929227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(BEGIN_EVENT); 930227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 931227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 932227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Like pause(), but closes all filters. Can be resumed using restart(). */ 933227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void halt() { 934227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(HALT_EVENT); 935227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 936227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 937227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** Resumes a previously halted runner, and restores it to its non-halted state. */ 938227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void restart() { 939227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(RESTART_EVENT); 940227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 941227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 942227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 943227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Tears down the specified graph. 944227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 945227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The graph must be attached to this runner. 946227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 947227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void tearDownGraph(FilterGraph graph) { 948227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (graph.getRunner() != this) { 949227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException("Attempting to tear down graph with foreign " 950227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + "GraphRunner!"); 951227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 952227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(Event.TEARDOWN, graph); 953227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mGraphs) { 954227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mGraphs.remove(graph); 955227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 956227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 957227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 958227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 959227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Remove all frames that are waiting to be processed. 960227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 961227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Removes and releases frames that are waiting in the graph connections of the currently 962227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * halted graphs, i.e. frames that are waiting to be processed. This does not include frames 963227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * that may be held or cached by filters themselves. 964227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 965227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * TODO: With the new sub-graph architecture, this can now be simplified and made public. 966227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * It can then no longer rely on opened graphs, and instead flush a graph and all its 967227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * sub-graphs. 968227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 969227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks void flushFrames() { 970227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop.pushEvent(FLUSH_EVENT); 971227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 972227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 973227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Private methods ///////////////////////////////////////////////////////////////////////////// 974227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void init(Config config) { 975227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mFrameManager = new FrameManager(this, FrameManager.FRAME_CACHE_LRU); 976227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks createScheduler(STRATEGY_LRU); 977227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunLoop = new GraphRunLoop(config.allowOpenGL); 978227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunThread = new Thread(mRunLoop); 979227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunThread.setPriority(config.threadPriority); 980227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunThread.start(); 981227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext.addRunner(this); 982227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 983227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 984227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void createScheduler(int strategy) { 985227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (strategy) { 986227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case STRATEGY_LRU: 987227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler = new LruScheduler(); 988227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 989227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case STRATEGY_LFU: 990227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler = new LfuScheduler(); 991227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 992227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case STRATEGY_ONESHOT: 993227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mScheduler = new OneShotScheduler(); 994227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 995227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks default: 996227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks throw new IllegalArgumentException( 997227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "Unknown schedule-strategy constant " + strategy + "!"); 998227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 999227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1000227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 1001227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Called within the runner's thread 1002227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onRunnerStopped(final Exception exception, final boolean closed) { 1003227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mRunningGraph = null; 1004227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks synchronized (mParams) { 1005227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mParams.listener != null) { 1006227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks getContext().postRunnable(new Runnable() { 1007227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 1008227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void run() { 1009227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (exception == null) { 1010227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParams.listener.onGraphRunnerStopped(GraphRunner.this); 1011227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 1012227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParams.listener.onGraphRunnerError(exception, closed); 1013227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1014227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1015227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 1016227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (exception != null) { 1017227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Log.e("GraphRunner", 1018227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks "Uncaught exception during graph execution! Stack Trace: "); 1019227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks exception.printStackTrace(); 1020227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1021227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1022227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 1023227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 1024