1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.annotation.TargetApi;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.app.Activity;
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.app.ActivityManager;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.content.Context;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.content.pm.ConfigurationInfo;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Build;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Handler;
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Looper;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.renderscript.RenderScript;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log;
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.SurfaceHolder;
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.SurfaceView;
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.ViewGroup;
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashSet;
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Set;
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The MffContext holds the state and resources of a Mobile Filter Framework processing instance.
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Though it is possible to create multiple MffContext instances, typical applications will rely on
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * a single MffContext to perform all processing within the Mobile Filter Framework.
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The MffContext class declares two methods {@link #onPause()} and {@link #onResume()}, that are
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * typically called when the application activity is paused and resumed. This will take care of
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * halting any processing in the context, and releasing resources while the activity is paused.
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class MffContext {
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Class to hold configuration information for MffContexts.
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static class Config {
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        /**
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * Set to true, if this context will make use of the camera.
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * If your application does not require the camera, the context does not guarantee that
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * a camera is available for streaming. That is, you may only use a CameraStreamer if
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * the context's {@link #isCameraStreamingSupported()} returns true.
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         */
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requireCamera = true;
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        /**
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * Set to true, if this context requires OpenGL.
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * If your application does not require OpenGL, the context does not guarantee that OpenGL
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * is available. That is, you may only use OpenGL (within filters running in this context)
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * if the context's {@link #isOpenGLSupported()} method returns true.
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         */
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requireOpenGL = true;
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        /**
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * On older Android versions the Camera may need a SurfaceView to render into in order to
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * function. You may specify a dummy SurfaceView here if you do not want the context to
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * create its own view. Note, that your view may or may not be used. You cannot rely on
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * your dummy view to be used by the Camera. If you pass null, no dummy view will be used.
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * In this case your application may not run correctly on older devices if you use the
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         * camera. This flag has no effect if you do not require the camera.
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks         */
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public SurfaceView dummySurface = null;
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        /** Force MFF to not use OpenGL in its processing. */
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean forceNoGL = false;
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static private class State {
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public static final int STATE_RUNNING = 1;
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public static final int STATE_PAUSED = 2;
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public static final int STATE_DESTROYED = 3;
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int current = STATE_RUNNING;
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The application context. */
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Context mApplicationContext = null;
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The set of filter graphs within this context */
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Set<FilterGraph> mGraphs = new HashSet<FilterGraph>();
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The set of graph runners within this context */
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Set<GraphRunner> mRunners = new HashSet<GraphRunner>();
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** True, if the context preserves frames when paused. */
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mPreserveFramesOnPause = false;
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The shared CameraStreamer that streams camera frames to CameraSource filters. */
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private CameraStreamer mCameraStreamer = null;
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The current context state. */
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private State mState = new State();
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** A dummy SurfaceView that is required for Camera operation on older devices. */
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private SurfaceView mDummySurfaceView = null;
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Handler to execute code in the context's thread, such as issuing callbacks. */
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Handler mHandler = null;
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Flag whether OpenGL ES 2 is supported in this context. */
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mGLSupport;
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Flag whether camera streaming is supported in this context. */
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mCameraStreamingSupport;
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** RenderScript base master class. */
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private RenderScript mRenderScript;
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Creates a new MffContext with the default configuration.
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * An MffContext must be attached to a Context object of an application. You may create
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * multiple MffContexts, however data between them cannot be shared. The context must be
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * created in a thread with a Looper (such as the main/UI thread).
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * On older versions of Android, the MffContext may create a visible dummy view for the
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * camera to render into. This is a 1x1 SurfaceView that is placed into the top-left corner.
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context The application context to attach the MffContext to.
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public MffContext(Context context) {
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        init(context, new Config());
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Creates a new MffContext with the specified configuration.
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * An MffContext must be attached to a Context object of an application. You may create
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * multiple MffContexts, however data between them cannot be shared. The context must be
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * created in a thread with a Looper (such as the main/UI thread).
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * On older versions of Android, the MffContext may create a visible dummy view for the
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * camera to render into. This is a 1x1 SurfaceView that is placed into the top-left corner.
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * You may alternatively specify your own SurfaceView in the configuration.
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param context The application context to attach the MffContext to.
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param config The configuration to use.
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws RuntimeException If no context for the requested configuration could be created.
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public MffContext(Context context, Config config) {
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        init(context, config);
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Put all processing in the context on hold.
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically called from your application's <code>onPause()</code> method, and will
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * stop all running graphs (closing their filters). If the context does not preserve frames on
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * pause (see {@link #setPreserveFramesOnPause(boolean)}) all frames attached to this context
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * are released.
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void onPause() {
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mState) {
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mState.current == State.STATE_RUNNING) {
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (mCameraStreamer != null) {
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mCameraStreamer.halt();
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                stopRunners(true);
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mState.current = State.STATE_PAUSED;
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Resumes the processing in this context.
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This is typically called from the application's <code>onResume()</code> method, and will
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * resume processing any of the previously stopped filter graphs.
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void onResume() {
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mState) {
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mState.current == State.STATE_PAUSED) {
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                resumeRunners();
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                resumeCamera();
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mState.current = State.STATE_RUNNING;
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Release all resources associated with this context.
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This will also stop any running graphs.
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void release() {
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mState) {
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mState.current != State.STATE_DESTROYED) {
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (mCameraStreamer != null) {
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mCameraStreamer.stop();
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mCameraStreamer.tearDown();
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (Build.VERSION.SDK_INT >= 11) {
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    maybeDestroyRenderScript();
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                stopRunners(false);
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                waitUntilStopped();
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                tearDown();
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mState.current = State.STATE_DESTROYED;
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Set whether frames are preserved when the context is paused.
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * When passing false, all Frames associated with this context are released. The default
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * value is true.
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param preserve true, to preserve frames when the context is paused.
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #getPreserveFramesOnPause()
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setPreserveFramesOnPause(boolean preserve) {
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mPreserveFramesOnPause = preserve;
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns whether frames are preserved when the context is paused.
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if frames are preserved when the context is paused.
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @see #setPreserveFramesOnPause(boolean)
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean getPreserveFramesOnPause() {
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mPreserveFramesOnPause;
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the application context that the MffContext is attached to.
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return The application context for this context.
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Context getApplicationContext() {
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mApplicationContext;
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the context's shared CameraStreamer.
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Use the CameraStreamer to control the Camera. Frames from the Camera are typically streamed
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * to CameraSource filters.
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return The context's CameraStreamer instance.
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public CameraStreamer getCameraStreamer() {
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mCameraStreamer == null) {
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCameraStreamer = new CameraStreamer(this);
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mCameraStreamer;
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Set the default EGL config chooser.
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * When an EGL context is required by the MFF, the channel sizes specified here are used. The
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * default sizes are 8 bits per R,G,B,A channel and 0 bits for depth and stencil channels.
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param redSize The size of the red channel in bits.
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param greenSize The size of the green channel in bits.
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param blueSize The size of the blue channel in bits.
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param alphaSize The size of the alpha channel in bits.
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param depthSize The size of the depth channel in bits.
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param stencilSize The size of the stencil channel in bits.
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void setEGLConfigChooser(int redSize,
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                           int greenSize,
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                           int blueSize,
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                           int alphaSize,
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                           int depthSize,
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                           int stencilSize) {
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        RenderTarget.setEGLConfigChooser(redSize,
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                         greenSize,
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                         blueSize,
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                         alphaSize,
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                         depthSize,
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                         stencilSize);
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if this context supports using OpenGL.
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if this context supports using OpenGL.
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final boolean isOpenGLSupported() {
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mGLSupport;
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns true, if this context supports camera streaming.
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return true, if this context supports camera streaming.
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final boolean isCameraStreamingSupported() {
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mCameraStreamingSupport;
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(11)
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final RenderScript getRenderScript() {
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRenderScript == null) {
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRenderScript = RenderScript.create(mApplicationContext);
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mRenderScript;
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    final void assertOpenGLSupported() {
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!isOpenGLSupported()) {
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Attempting to use OpenGL ES 2 in a context that does not "
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "support it!");
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void addGraph(FilterGraph graph) {
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mGraphs) {
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mGraphs.add(graph);
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void addRunner(GraphRunner runner) {
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mRunners) {
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRunners.add(runner);
328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    SurfaceView getDummySurfaceView() {
332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mDummySurfaceView;
333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void postRunnable(Runnable runnable) {
336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mHandler.post(runnable);
337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void init(Context context, Config config) {
340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        determineGLSupport(context, config);
341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        determineCameraSupport(config);
342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        createHandler();
343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mApplicationContext = context.getApplicationContext();
344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        fetchDummySurfaceView(context, config);
345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void fetchDummySurfaceView(Context context, Config config) {
348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (config.requireCamera && CameraStreamer.requireDummySurfaceView()) {
349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mDummySurfaceView = config.dummySurface != null
350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    ? config.dummySurface
351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    : createDummySurfaceView(context);
352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void determineGLSupport(Context context, Config config) {
356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (config.forceNoGL) {
357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mGLSupport = false;
358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mGLSupport = getPlatformSupportsGLES2(context);
360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (config.requireOpenGL && !mGLSupport) {
361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot create context that requires GL support on "
362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        + "this platform!");
363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void determineCameraSupport(Config config) {
368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCameraStreamingSupport = (CameraStreamer.getNumberOfCameras() > 0);
369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (config.requireCamera && !mCameraStreamingSupport) {
370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Cannot create context that requires a camera on "
371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "this platform!");
372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static boolean getPlatformSupportsGLES2(Context context) {
376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ConfigurationInfo configurationInfo = am.getDeviceConfigurationInfo();
378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return configurationInfo.reqGlEsVersion >= 0x20000;
379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void createHandler() {
382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (Looper.myLooper() == null) {
383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("MffContext must be created in a thread with a Looper!");
384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mHandler = new Handler();
386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void stopRunners(boolean haltOnly) {
389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mRunners) {
390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Halt all runners (does nothing if not running)
391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (GraphRunner runner : mRunners) {
392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (haltOnly) {
393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    runner.halt();
394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    runner.stop();
396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Flush all graphs if requested (this is queued up after the call to halt)
399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (!mPreserveFramesOnPause) {
400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                for (GraphRunner runner : mRunners) {
401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    runner.flushFrames();
402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void resumeRunners() {
408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        synchronized (mRunners) {
409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (GraphRunner runner : mRunners) {
410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                runner.restart();
411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void resumeCamera() {
416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Restart only affects previously halted cameras that were running.
417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mCameraStreamer != null) {
418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCameraStreamer.restart();
419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void waitUntilStopped() {
423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (GraphRunner runner : mRunners) {
424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            runner.waitUntilStop();
425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void tearDown() {
429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Tear down graphs
430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (FilterGraph graph : mGraphs) {
431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            graph.tearDown();
432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // Tear down runners
435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (GraphRunner runner : mRunners) {
436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            runner.tearDown();
437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @SuppressWarnings("deprecation")
441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private SurfaceView createDummySurfaceView(Context context) {
442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // This is only called on Gingerbread devices, so deprecation warning is unnecessary.
443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        SurfaceView dummySurfaceView = new SurfaceView(context);
444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        dummySurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // If we have an activity for this context we'll add the SurfaceView to it (as a 1x1 view
446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // in the top-left corner). If not, we warn the user that they may need to add one manually.
447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Activity activity = findActivityForContext(context);
448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (activity != null) {
449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(1, 1);
450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            activity.addContentView(dummySurfaceView, params);
451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Log.w("MffContext", "Could not find activity for dummy surface! Consider specifying "
453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "your own SurfaceView!");
454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return dummySurfaceView;
456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Activity findActivityForContext(Context context) {
459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return (context instanceof Activity) ? (Activity) context : null;
460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(11)
463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void maybeDestroyRenderScript() {
464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRenderScript != null) {
465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRenderScript.destroy();
466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRenderScript = null;
467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
471