19efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala/*
29efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * Copyright (C) 2011 The Android Open Source Project
39efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala *
49efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); you may not
59efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * use this file except in compliance with the License. You may obtain a copy of
69efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * the License at
79efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala *
89efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0
99efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala *
109efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software
119efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
129efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
139efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * License for the specific language governing permissions and limitations under
149efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * the License.
159efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala */
169efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalapackage com.android.camera;
189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
199efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.content.Context;
2085a5556fb58f1cdc016f5afe5e07cbe1b419ffd8Eino-Ville Talvalaimport android.content.res.AssetFileDescriptor;
219efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterfw.GraphEnvironment;
229efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterfw.core.Filter;
23a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvalaimport android.filterfw.core.GLEnvironment;
249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterfw.core.GraphRunner;
259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterfw.core.GraphRunner.OnRunnerDoneListener;
262c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvalaimport android.filterfw.geometry.Point;
272c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvalaimport android.filterfw.geometry.Quad;
289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterpacks.videoproc.BackDropperFilter;
299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.filterpacks.videoproc.BackDropperFilter.LearningDoneListener;
30caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroniimport android.filterpacks.videosink.MediaEncoderFilter.OnRecordingDoneListener;
31caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroniimport android.filterpacks.videosrc.SurfaceTextureSource.SurfaceTextureSourceListener;
329efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
339efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.graphics.SurfaceTexture;
349efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.hardware.Camera;
351461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvalaimport android.media.MediaActionSound;
369efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.media.MediaRecorder;
379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.media.CamcorderProfile;
389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.os.Handler;
399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.os.Looper;
409efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.os.ParcelFileDescriptor;
419efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.util.Log;
429efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.view.Surface;
439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport android.view.SurfaceHolder;
449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
459efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport java.io.IOException;
4685a5556fb58f1cdc016f5afe5e07cbe1b419ffd8Eino-Ville Talvalaimport java.io.FileNotFoundException;
4785a5556fb58f1cdc016f5afe5e07cbe1b419ffd8Eino-Ville Talvalaimport java.io.File;
489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalaimport java.lang.Runnable;
49dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketiimport java.io.FileDescriptor;
509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5185a5556fb58f1cdc016f5afe5e07cbe1b419ffd8Eino-Ville Talvala
529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala/**
539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * Encapsulates the mobile filter framework components needed to record video with
549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala * effects applied. Modeled after MediaRecorder.
559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala */
569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvalapublic class EffectsRecorder {
579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_NONE        = 0;
599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GOOFY_FACE  = 1;
609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_BACKDROPPER = 2;
619efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_SQUEEZE     = 0;
639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_BIG_EYES    = 1;
649efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_BIG_MOUTH   = 2;
659efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_SMALL_MOUTH = 3;
669efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_BIG_NOSE    = 4;
679efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_GF_SMALL_EYES  = 5;
681e99673af90451eaffeb100735f38e6ce0f18456Wu-cheng Li    public static final int  NUM_OF_GF_EFFECTS = EFFECT_GF_SMALL_EYES + 1;
699efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
709efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_MSG_STARTED_LEARNING = 0;
719efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static final int  EFFECT_MSG_DONE_LEARNING    = 1;
72926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala    public static final int  EFFECT_MSG_SWITCHING_EFFECT = 2;
73926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala    public static final int  EFFECT_MSG_EFFECTS_STOPPED  = 3;
74caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni    public static final int  EFFECT_MSG_RECORDING_DONE   = 4;
7587e72ba9d89f8b83b1356f17077b9652346a29d4Pannag Sanketi    public static final int  EFFECT_MSG_PREVIEW_RUNNING  = 5;
769efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
779efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private Context mContext;
789efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private Handler mHandler;
799efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private boolean mReleased;
809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private Camera mCameraDevice;
829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private CamcorderProfile mProfile;
83d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala    private double mCaptureRate = 0;
849efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private SurfaceHolder mPreviewSurfaceHolder;
859efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mPreviewWidth;
869efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mPreviewHeight;
879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private MediaRecorder.OnInfoListener mInfoListener;
889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private MediaRecorder.OnErrorListener mErrorListener;
899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
909efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private String mOutputFile;
91dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi    private FileDescriptor mFd;
929efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mOrientationHint = 0;
939c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi    private long mMaxFileSize = 0;
94db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    private int mMaxDurationMs = 0;
952c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala    private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
9614a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala    private boolean mAppIsLandscape;
979efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mEffect = EFFECT_NONE;
999efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mCurrentEffect = EFFECT_NONE;
1009efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private EffectsListener mEffectsListener;
1019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1029efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private Object mEffectParameter;
1039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private GraphEnvironment mGraphEnv;
1059efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mGraphId;
1062670b3d7c318604f07b680b22360d349103144beWei Hua    private GraphRunner mRunner = null;
107a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    private GraphRunner mOldRunner = null;
1089efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1099efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private SurfaceTexture mTextureSource;
1109efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1119efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private static final int STATE_CONFIGURE              = 0;
1129efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private static final int STATE_WAITING_FOR_SURFACE    = 1;
113cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala    private static final int STATE_STARTING_PREVIEW       = 2;
114cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala    private static final int STATE_PREVIEW                = 3;
115cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala    private static final int STATE_RECORD                 = 4;
116cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala    private static final int STATE_RELEASED               = 5;
1179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private int mState = STATE_CONFIGURE;
1189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1197e6b690c96b36b134d6825562b4ae66e055ba6a8Eino-Ville Talvala    private boolean mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE);
1209efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private static final String TAG = "effectsrecorder";
1211461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala    private MediaActionSound mCameraSound;
1229efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1239efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    /** Determine if a given effect is supported at runtime
1249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala     * Some effects require libraries not available on all devices
1259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala     */
1269efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public static boolean isEffectSupported(int effectId) {
1279efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (effectId) {
1289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case EFFECT_GOOFY_FACE:
1299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return Filter.isAvailable("com.google.android.filterpacks.facedetect.GoofyRenderFilter");
1309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case EFFECT_BACKDROPPER:
1319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return Filter.isAvailable("android.filterpacks.videoproc.BackDropperFilter");
1329efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
1339efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return false;
1349efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
1359efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
1369efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public EffectsRecorder(Context context) {
1389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "EffectsRecorder created (" + this + ")");
1399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mContext = context;
1409efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mHandler = new Handler(Looper.getMainLooper());
1411461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala        mCameraSound = new MediaActionSound();
1429efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
1439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setCamera(Camera cameraDevice) {
1459efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
1469efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_PREVIEW:
1479efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setCamera cannot be called while previewing!");
1489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
1499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setCamera cannot be called while recording!");
1509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
1519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setCamera called on an already released recorder!");
1529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
1539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
1549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
1559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mCameraDevice = cameraDevice;
1579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
1589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setProfile(CamcorderProfile profile) {
1609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
1619efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
1629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setProfile cannot be called while recording!");
1639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
1649efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setProfile called on an already released recorder!");
1659efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
1669efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
1679efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
1689efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mProfile = profile;
1699efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
1709efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1719efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setOutputFile(String outputFile) {
1729efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
1739efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
1749efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setOutputFile cannot be called while recording!");
1759efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
1769efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setOutputFile called on an already released recorder!");
1779efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
1789efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
1799efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
1809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mOutputFile = outputFile;
182dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        mFd = null;
183dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi    }
184dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi
185dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi    public void setOutputFile(FileDescriptor fd) {
186dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        switch (mState) {
187dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            case STATE_RECORD:
188dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                throw new RuntimeException("setOutputFile cannot be called while recording!");
189dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            case STATE_RELEASED:
190dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                throw new RuntimeException("setOutputFile called on an already released recorder!");
191dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            default:
192dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                break;
193dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        }
194dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi
195dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        mOutputFile = null;
196dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        mFd = fd;
1979efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
1989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
1999c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi    /**
2009c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi     * Sets the maximum filesize (in bytes) of the recording session.
2019c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi     * This will be passed on to the MediaEncoderFilter and then to the
2029c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi     * MediaRecorder ultimately. If zero or negative, the MediaRecorder will
2039c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi     * disable the limit
2049c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi    */
2059c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi    public synchronized void setMaxFileSize(long maxFileSize) {
206d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        switch (mState) {
207d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            case STATE_RECORD:
208d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                throw new RuntimeException("setMaxFileSize cannot be called while recording!");
209d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            case STATE_RELEASED:
210d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                throw new RuntimeException("setMaxFileSize called on an already released recorder!");
211d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            default:
212d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                break;
213d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        }
2149c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi        mMaxFileSize = maxFileSize;
2159c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi    }
2169c96da0c452cf980eb368cbb5a63afc4ab5f4bc4Pannag Sanketi
217db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    /**
218db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    * Sets the maximum recording duration (in ms) for the next recording session
219db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    * Setting it to zero (the default) disables the limit.
220db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    */
221db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    public synchronized void setMaxDuration(int maxDurationMs) {
222db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi        switch (mState) {
223db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi            case STATE_RECORD:
224db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi                throw new RuntimeException("setMaxDuration cannot be called while recording!");
225db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi            case STATE_RELEASED:
226db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi                throw new RuntimeException("setMaxDuration called on an already released recorder!");
227db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi            default:
228db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi                break;
229db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi        }
230db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi        mMaxDurationMs = maxDurationMs;
231db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi    }
232db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi
233db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi
234d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala    public void setCaptureRate(double fps) {
235d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        switch (mState) {
236d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            case STATE_RECORD:
237d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                throw new RuntimeException("setCaptureRate cannot be called while recording!");
238d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            case STATE_RELEASED:
239d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                throw new RuntimeException("setCaptureRate called on an already released recorder!");
240d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            default:
241d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                break;
242d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        }
243d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala
244d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Setting time lapse capture rate to " + fps + " fps");
245d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        mCaptureRate = fps;
246d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala    }
247d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala
2489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setPreviewDisplay(SurfaceHolder previewSurfaceHolder,
2499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                                  int previewWidth,
2509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                                  int previewHeight) {
2519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "setPreviewDisplay (" + this + ")");
2529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
2539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
2549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setPreviewDisplay cannot be called while recording!");
2559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
2569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setPreviewDisplay called on an already released recorder!");
2579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
2589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
2599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
2609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
2619efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mPreviewSurfaceHolder = previewSurfaceHolder;
2629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mPreviewWidth = previewWidth;
2639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mPreviewHeight = previewHeight;
2649efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
2659efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
2669efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_WAITING_FOR_SURFACE:
2679efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                startPreview();
2689efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
269cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            case STATE_STARTING_PREVIEW:
2709efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_PREVIEW:
2719efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                initializeEffect(true);
2729efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
2739efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
2749efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
2759efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
2769efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setEffect(int effect, Object effectParameter) {
2779efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG,
278926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                               "setEffect: effect ID " + effect +
279926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                               ", parameter " + effectParameter.toString() );
2809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
2819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
2829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setEffect cannot be called while recording!");
2839efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
2849efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setEffect called on an already released recorder!");
2859efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
2869efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
2879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
2889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
2899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mEffect = effect;
2909efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mEffectParameter = effectParameter;
2919efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
292cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala        if (mState == STATE_PREVIEW ||
293cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                mState == STATE_STARTING_PREVIEW) {
2949efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            initializeEffect(false);
2959efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
2969efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
2979efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
2989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public interface EffectsListener {
2999efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        public void onEffectsUpdate(int effectId, int effectMsg);
300d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn        public void onEffectsError(Exception exception, String filePath);
3019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
3029efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
3039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setEffectsListener(EffectsListener listener) {
3049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mEffectsListener = listener;
3059efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
3069efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
30751b06d6696a4743339d026b3b3bd282645725b27Eino-Ville Talvala    private void setFaceDetectOrientation() {
3082670b3d7c318604f07b680b22360d349103144beWei Hua        if (mCurrentEffect == EFFECT_GOOFY_FACE) {
3092670b3d7c318604f07b680b22360d349103144beWei Hua            Filter rotateFilter = mRunner.getGraph().getFilter("rotate");
3102670b3d7c318604f07b680b22360d349103144beWei Hua            Filter metaRotateFilter = mRunner.getGraph().getFilter("metarotate");
31151b06d6696a4743339d026b3b3bd282645725b27Eino-Ville Talvala            rotateFilter.setInputValue("rotation", mOrientationHint);
31251b06d6696a4743339d026b3b3bd282645725b27Eino-Ville Talvala            int reverseDegrees = (360 - mOrientationHint) % 360;
3132670b3d7c318604f07b680b22360d349103144beWei Hua            metaRotateFilter.setInputValue("rotation", reverseDegrees);
3142670b3d7c318604f07b680b22360d349103144beWei Hua        }
3152670b3d7c318604f07b680b22360d349103144beWei Hua    }
3162670b3d7c318604f07b680b22360d349103144beWei Hua
3172c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala    private void setRecordingOrientation() {
318c3a0c2d4b7c1ec7bd8dc6190a0a68a6ff90cb629Eino-Ville Talvala        if ( mState != STATE_RECORD && mRunner != null) {
3192c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Point bl = new Point(0, 0);
3202c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Point br = new Point(1, 0);
3212c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Point tl = new Point(0, 1);
3222c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Point tr = new Point(1, 1);
3232c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Quad recordingRegion;
3242c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) {
3252c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                // The back camera is not mirrored, so use a identity transform
3262c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                recordingRegion = new Quad(bl, br, tl, tr);
3272c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            } else {
3282c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                // Recording region needs to be tweaked for front cameras, since they
3292c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                // mirror their preview
3302c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                if (mOrientationHint == 0 || mOrientationHint == 180) {
3312c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                    // Horizontal flip in landscape
3322c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                    recordingRegion = new Quad(br, bl, tr, tl);
3332c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                } else {
3342c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                    // Horizontal flip in portrait
3352c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                    recordingRegion = new Quad(tl, tr, bl, br);
3362c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                }
3372c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            }
3382c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            Filter recorder = mRunner.getGraph().getFilter("recorder");
3392c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            recorder.setInputValue("inputRegion", recordingRegion);
3402c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        }
3412c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala    }
3429efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setOrientationHint(int degrees) {
3439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
3449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
3452670b3d7c318604f07b680b22360d349103144beWei Hua                throw new RuntimeException(
3462670b3d7c318604f07b680b22360d349103144beWei Hua                        "setOrientationHint called on an already released recorder!");
3479efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
3489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
3499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
3503ac6ed3a95322fa9e29f81377e92669ebaeb77fbEino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Setting orientation hint to: " + degrees);
3519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mOrientationHint = degrees;
35251b06d6696a4743339d026b3b3bd282645725b27Eino-Ville Talvala        setFaceDetectOrientation();
3532c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        setRecordingOrientation();
3542c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala    }
3552c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala
35614a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala    /** Passes the native orientation of the Camera app (device dependent)
35714a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala     * to allow for correct output aspect ratio. Defaults to portrait */
35814a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala    public void setAppToLandscape(boolean landscape) {
35914a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala        if (mState != STATE_CONFIGURE) {
36014a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala            throw new RuntimeException(
36114a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala                "setAppToLandscape called after configuration!");
36214a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala        }
36314a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala        mAppIsLandscape = landscape;
36414a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala    }
36514a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala
3662c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala    public void setCameraFacing(int facing) {
3672c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        switch (mState) {
3682c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            case STATE_RELEASED:
3692c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                throw new RuntimeException(
3702c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                    "setCameraFacing called on alrady released recorder!");
3712c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala            default:
3722c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala                break;
3732c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        }
3742c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        mCameraFacing = facing;
3752c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        setRecordingOrientation();
3769efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
3779efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
3789efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setOnInfoListener(MediaRecorder.OnInfoListener infoListener) {
3799efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
3809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
3819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setInfoListener cannot be called while recording!");
3829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
3839efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setInfoListener called on an already released recorder!");
3849efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
3859efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
3869efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
3879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mInfoListener = infoListener;
3889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
3899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
3909efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public void setOnErrorListener(MediaRecorder.OnErrorListener errorListener) {
3919efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
3929efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
3939efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setErrorListener cannot be called while recording!");
3949efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
3959efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setErrorListener called on an already released recorder!");
3969efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
3979efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
3989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
3999efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mErrorListener = errorListener;
4009efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
4019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
402a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    private void initializeFilterFramework() {
4039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mGraphEnv = new GraphEnvironment();
4049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mGraphEnv.createGLEnvironment();
4059efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
406926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala        if (mLogVerbose) {
407926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala            Log.v(TAG, "Effects framework initializing. Recording size "
408926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                  + mProfile.videoFrameWidth + ", " + mProfile.videoFrameHeight);
409926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala        }
41014a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala        if (!mAppIsLandscape) {
41114a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala            int tmp;
41214a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala            tmp = mProfile.videoFrameWidth;
41314a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala            mProfile.videoFrameWidth = mProfile.videoFrameHeight;
41414a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala            mProfile.videoFrameHeight = tmp;
41514a3ffc328740e8fd4734dfa124e4682df8bdd4aEino-Ville Talvala        }
4169efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mGraphEnv.addReferences(
4179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                "textureSourceCallback", mSourceReadyCallback,
4189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                "recordingWidth", mProfile.videoFrameWidth,
4199efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                "recordingHeight", mProfile.videoFrameHeight,
4209efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                "recordingProfile", mProfile,
421caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni                "learningDoneListener", mLearningDoneListener,
422caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni                "recordingDoneListener", mRecordingDoneListener);
4239efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mRunner = null;
4249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mGraphId = -1;
4259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mCurrentEffect = EFFECT_NONE;
4269efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
4279efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
428a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    private synchronized void initializeEffect(boolean forceReset) {
4299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (forceReset ||
4309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mCurrentEffect != mEffect ||
4319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mCurrentEffect == EFFECT_BACKDROPPER) {
432926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala            if (mLogVerbose) {
433926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                Log.v(TAG, "Effect initializing. Preview size "
434926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                       + mPreviewWidth + ", " + mPreviewHeight);
435926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala            }
4362c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala
4379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mGraphEnv.addReferences(
4389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    "previewSurface", mPreviewSurfaceHolder.getSurface(),
4399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    "previewWidth", mPreviewWidth,
440d5ec81fea464e1f9db3cb06f7db3de3cf2e3be94Eino-Ville Talvala                    "previewHeight", mPreviewHeight,
441d5ec81fea464e1f9db3cb06f7db3de3cf2e3be94Eino-Ville Talvala                    "orientation", mOrientationHint);
442cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            if (mState == STATE_PREVIEW ||
443cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                    mState == STATE_STARTING_PREVIEW) {
444a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                // Switching effects while running. Inform video camera.
445926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                sendMessage(mCurrentEffect, EFFECT_MSG_SWITCHING_EFFECT);
4469efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            }
447a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala
4489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            switch (mEffect) {
4499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                case EFFECT_GOOFY_FACE:
4509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    mGraphId = mGraphEnv.loadGraph(mContext, R.raw.goofy_face);
4519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    break;
4529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                case EFFECT_BACKDROPPER:
4539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    sendMessage(EFFECT_BACKDROPPER, EFFECT_MSG_STARTED_LEARNING);
4549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    mGraphId = mGraphEnv.loadGraph(mContext, R.raw.backdropper);
4559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    break;
4569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                default:
4579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    throw new RuntimeException("Unknown effect ID" + mEffect + "!");
4589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            }
4599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mCurrentEffect = mEffect;
4609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
461a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala            mOldRunner = mRunner;
4629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mRunner = mGraphEnv.getRunner(mGraphId, GraphEnvironment.MODE_ASYNCHRONOUS);
4639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mRunner.setDoneCallback(mRunnerDoneCallback);
464d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala            if (mLogVerbose) {
465d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                Log.v(TAG, "New runner: " + mRunner
466d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                      + ". Old runner: " + mOldRunner);
467d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala            }
468cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            if (mState == STATE_PREVIEW ||
469cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                    mState == STATE_STARTING_PREVIEW) {
470a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                // Switching effects while running. Stop existing runner.
471a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                // The stop callback will take care of starting new runner.
472a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                mCameraDevice.stopPreview();
473a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                try {
474a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                    mCameraDevice.setPreviewTexture(null);
475a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                } catch(IOException e) {
476a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                    throw new RuntimeException("Unable to connect camera to effect input", e);
477a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                }
478a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                mOldRunner.stop();
479a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala            }
4809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
4819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
4829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mCurrentEffect) {
4839efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case EFFECT_GOOFY_FACE:
48407d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala                tryEnableVideoStabilization(true);
4859efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                Filter goofyFilter = mRunner.getGraph().getFilter("goofyrenderer");
4869efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                goofyFilter.setInputValue("currentEffect",
4879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                                          ((Integer)mEffectParameter).intValue());
4889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
4899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case EFFECT_BACKDROPPER:
49007d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala                tryEnableVideoStabilization(false);
4919efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                Filter backgroundSrc = mRunner.getGraph().getFilter("background");
4929efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                backgroundSrc.setInputValue("sourceUrl",
4939efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                                            (String)mEffectParameter);
4948d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                // For front camera, the background video needs to be mirrored in the
4958d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                // backdropper filter
4968d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
4978d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                    Filter replacer = mRunner.getGraph().getFilter("replacer");
4988d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                    replacer.setInputValue("mirrorBg", true);
4998d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                    if (mLogVerbose) Log.v(TAG, "Setting the background to be mirrored");
5008d51fc281ca4e14c87eac278d153e162c0e1fcf2Pannag Sanketi                }
5019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
5029efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
5039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
5049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
50551b06d6696a4743339d026b3b3bd282645725b27Eino-Ville Talvala        setFaceDetectOrientation();
5062c2550bd42c614330a3c968bda005ac23d12f8d1Eino-Ville Talvala        setRecordingOrientation();
5079efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
5089efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
509a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    public synchronized void startPreview() {
5109efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Starting preview (" + this + ")");
5119efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5129efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
513cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            case STATE_STARTING_PREVIEW:
5149efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_PREVIEW:
5159efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                // Already running preview
5169efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                Log.w(TAG, "startPreview called when already running preview");
5179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return;
5189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
5199efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("Cannot start preview when already recording!");
5209efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
5219efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("setEffect called on an already released recorder!");
5229efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
5239efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
5249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5269efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mEffect == EFFECT_NONE) {
5279efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            throw new RuntimeException("No effect selected!");
5289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mEffectParameter == null) {
5309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            throw new RuntimeException("No effect parameter provided!");
5319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5329efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mProfile == null) {
5339efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            throw new RuntimeException("No recording profile provided!");
5349efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5359efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mPreviewSurfaceHolder == null) {
5369efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "Passed a null surface holder; waiting for valid one");
5379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mState = STATE_WAITING_FOR_SURFACE;
5389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            return;
5399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5409efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mCameraDevice == null) {
5419efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            throw new RuntimeException("No camera to record from!");
5429efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
5439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Initializing filter graph");
5459efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5469efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        initializeFilterFramework();
5479efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        initializeEffect(true);
5499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Starting filter graph");
5519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
552cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala        mState = STATE_STARTING_PREVIEW;
5539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mRunner.run();
5549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        // Rest of preview startup handled in mSourceReadyCallback
5559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
5569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
5579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private SurfaceTextureSourceListener mSourceReadyCallback =
5589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            new SurfaceTextureSourceListener() {
5599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        public void onSurfaceTextureSourceReady(SurfaceTexture source) {
5609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "SurfaceTexture ready callback received");
5619efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            synchronized(EffectsRecorder.this) {
5629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                mTextureSource = source;
5639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
56407b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                if (mState == STATE_CONFIGURE) {
56507b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    // Stop preview happened while the runner was doing startup tasks
56607b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    // Since we haven't started anything up, don't do anything
56707b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    // Rest of cleanup will happen in onRunnerDone
56807b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    if (mLogVerbose) Log.v(TAG, "Ready callback: Already stopped, skipping.");
56907b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    return;
57007b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                }
57107b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                if (mState == STATE_RELEASED) {
57207b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    // EffectsRecorder has been released, so don't touch the camera device
57307b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    // or anything else
57407b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    if (mLogVerbose) Log.v(TAG, "Ready callback: Already released, skipping.");
57507b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                    return;
57607b77037f2f5aa28d6d3188f78588dc7f2d49398Eino-Ville Talvala                }
57758cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                if (source == null) {
57858cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                    if (mState == STATE_PREVIEW ||
579cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                            mState == STATE_STARTING_PREVIEW ||
58058cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                            mState == STATE_RECORD) {
58158cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        // A null source here means the graph is shutting down
58258cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        // unexpectedly, so we need to turn off preview before
58358cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        // the surface texture goes away.
58458cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        mCameraDevice.stopPreview();
58558cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        try {
58658cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                            mCameraDevice.setPreviewTexture(null);
58758cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        } catch(IOException e) {
58858cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                            throw new RuntimeException("Unable to disconnect " +
58958cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                                    "camera from effect input", e);
59058cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                        }
59158cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                    }
59258cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                    return;
59358cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala                }
59458cede9e3e8004f6be9731e9cb9a135238a2efd8Eino-Ville Talvala
59507d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala                // Lock AE/AWB to reduce transition flicker
59607d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala                tryEnable3ALocks(true);
59707d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala
5989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                mCameraDevice.stopPreview();
5999efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Runner active, connecting effects preview");
6009efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                try {
6019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    mCameraDevice.setPreviewTexture(mTextureSource);
6029efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                } catch(IOException e) {
6039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    throw new RuntimeException("Unable to connect camera to effect input", e);
6049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                }
6059efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6069efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                mCameraDevice.startPreview();
6079efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6089efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                // Unlock AE/AWB after preview started
6099efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                tryEnable3ALocks(false);
6109efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6119efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                mState = STATE_PREVIEW;
6129efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6139efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                if (mLogVerbose) Log.v(TAG, "Start preview/effect switch complete");
61487e72ba9d89f8b83b1356f17077b9652346a29d4Pannag Sanketi
61587e72ba9d89f8b83b1356f17077b9652346a29d4Pannag Sanketi                // Sending a message to listener that preview is complete
61687e72ba9d89f8b83b1356f17077b9652346a29d4Pannag Sanketi                sendMessage(mCurrentEffect, EFFECT_MSG_PREVIEW_RUNNING);
6179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            }
6189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
6199efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    };
6209efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6219efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private LearningDoneListener mLearningDoneListener =
6229efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            new LearningDoneListener() {
6239efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        public void onLearningDone(BackDropperFilter filter) {
6249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "Learning done callback triggered");
6259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            // Called in a processing thread, so have to post message back to UI
6269efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            // thread
6279efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            sendMessage(EFFECT_BACKDROPPER, EFFECT_MSG_DONE_LEARNING);
6289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            enable3ALocks(true);
6299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
6309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    };
6319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
632caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni    // A callback to finalize the media after the recording is done.
633caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni    private OnRecordingDoneListener mRecordingDoneListener =
634caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni            new OnRecordingDoneListener() {
635caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni        // Forward the callback to the VideoCamera object (as an asynchronous event).
636caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni        public void onRecordingDone() {
637caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni            if (mLogVerbose) Log.v(TAG, "Recording done callback triggered");
638caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni            sendMessage(EFFECT_NONE, EFFECT_MSG_RECORDING_DONE);
639caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni        }
640caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni    };
641caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni
642a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    public synchronized void startRecording() {
6439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Starting recording (" + this + ")");
6449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6459efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
6469efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
6479efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("Already recording, cannot begin anew!");
6489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
6499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("startRecording called on an already released recorder!");
6509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
6519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
6529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
6539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
654dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        if ((mOutputFile == null) && (mFd == null)) {
655dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            throw new RuntimeException("No output file name or descriptor provided!");
6569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
6579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
6589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mState == STATE_CONFIGURE) {
6599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            startPreview();
6609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
661dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi
6629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        Filter recorder = mRunner.getGraph().getFilter("recorder");
663dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        if (mFd != null) {
664dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            recorder.setInputValue("outputFileDescriptor", mFd);
665dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        } else {
666dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi            recorder.setInputValue("outputFile", mOutputFile);
667dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi        }
668d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // It is ok to set the audiosource without checking for timelapse here
669d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // since that check will be done in the MediaEncoderFilter itself
670d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        recorder.setInputValue("audioSource", MediaRecorder.AudioSource.CAMCORDER);
671dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi
672d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        recorder.setInputValue("recordingProfile", mProfile);
6739efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        recorder.setInputValue("orientationHint", mOrientationHint);
674d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // Important to set the timelapseinterval to 0 if the capture rate is not >0
675d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // since the recorder does not get created every time the recording starts.
676d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // The recorder infers whether the capture is timelapsed based on the value of
677d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        // this interval
678d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        boolean captureTimeLapse = mCaptureRate > 0;
679d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        if (captureTimeLapse) {
680d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            double timeBetweenFrameCapture = 1 / mCaptureRate;
681d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            recorder.setInputValue("timelapseRecordingIntervalUs",
682d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala                    (long) (1000000 * timeBetweenFrameCapture));
683d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        } else {
684d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala            recorder.setInputValue("timelapseRecordingIntervalUs", 0L);
685d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        }
686d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala
6879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mInfoListener != null) {
6889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            recorder.setInputValue("infoListener", mInfoListener);
6899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
6909efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mErrorListener != null) {
6919efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            recorder.setInputValue("errorListener", mErrorListener);
6929efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
693d979079aa0735beb302dd58797af0c6b600edfeaEino-Ville Talvala        recorder.setInputValue("maxFileSize", mMaxFileSize);
694db1596dc704d2085a3f2f7b5652e6cb43696c265Pannag Sanketi        recorder.setInputValue("maxDurationMs", mMaxDurationMs);
6959efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        recorder.setInputValue("recording", true);
6961461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala        mCameraSound.play(MediaActionSound.START_VIDEO_RECORDING);
6979efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mState = STATE_RECORD;
6989efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
6999efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
700a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    public synchronized void stopRecording() {
7019efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Stop recording (" + this + ")");
7029efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7039efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
7049efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_CONFIGURE:
705cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            case STATE_STARTING_PREVIEW:
7069efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_PREVIEW:
7079efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                Log.w(TAG, "StopRecording called when recording not active!");
7089efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return;
7099efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
7109efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("stopRecording called on released EffectsRecorder!");
7119efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
7129efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
7139efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
7149efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        Filter recorder = mRunner.getGraph().getFilter("recorder");
7159efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        recorder.setInputValue("recording", false);
7161461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala        mCameraSound.play(MediaActionSound.STOP_VIDEO_RECORDING);
7179efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mState = STATE_PREVIEW;
7189efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
7199efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7209efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    // Stop and release effect resources
721a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala    public synchronized void stopPreview() {
7229efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Stopping preview (" + this + ")");
7239efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7249efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
7259efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_CONFIGURE:
7269efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                Log.w(TAG, "StopPreview called when preview not active!");
7279efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                return;
7289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RELEASED:
7299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                throw new RuntimeException("stopPreview called on released EffectsRecorder!");
7309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
7319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
7329efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
7339efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7349efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mState == STATE_RECORD) {
7359efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            stopRecording();
7369efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
7379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mCurrentEffect = EFFECT_NONE;
7399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
740a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala        mCameraDevice.stopPreview();
741a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala        try {
742a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala            mCameraDevice.setPreviewTexture(null);
743a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala        } catch(IOException e) {
744a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala            throw new RuntimeException("Unable to connect camera to effect input", e);
745a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala        }
74690089f9eddde732725c43dcad07f4567ed8cb776Wu-cheng Li        mCameraSound.release();
747a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala
7489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mState = STATE_CONFIGURE;
749a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala        mOldRunner = mRunner;
7509efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        mRunner.stop();
751d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala        mRunner = null;
7529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        // Rest of stop and release handled in mRunnerDoneCallback
7539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
7549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
75507d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala    // Try to enable/disable video stabilization if supported; otherwise return false
75607d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala    boolean tryEnableVideoStabilization(boolean toggle) {
75707d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        Camera.Parameters params = mCameraDevice.getParameters();
75807d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala
75907d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        String vstabSupported = params.get("video-stabilization-supported");
76007d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        if ("true".equals(vstabSupported)) {
76107d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala            if (mLogVerbose) Log.v(TAG, "Setting video stabilization to " + toggle);
76207d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala            params.set("video-stabilization", toggle ? "true" : "false");
76307d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala            mCameraDevice.setParameters(params);
76407d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala            return true;
76507d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        }
76607d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Video stabilization not supported");
76707d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala        return false;
76807d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala    }
76907d5f8c27d144f7e72820b48fe5cb08f691435adEino-Ville Talvala
7709efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    // Try to enable/disable 3A locks if supported; otherwise return false
7719efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    boolean tryEnable3ALocks(boolean toggle) {
7729efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        Camera.Parameters params = mCameraDevice.getParameters();
7739efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (params.isAutoExposureLockSupported() &&
7749efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            params.isAutoWhiteBalanceLockSupported() ) {
7759efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            params.setAutoExposureLock(toggle);
7769efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            params.setAutoWhiteBalanceLock(toggle);
7779efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mCameraDevice.setParameters(params);
7789efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            return true;
7799efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
7809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        return false;
7819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
7829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7839efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    // Try to enable/disable 3A locks if supported; otherwise, throw error
7849efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    // Use this when locks are essential to success
7859efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    void enable3ALocks(boolean toggle) {
7869efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        Camera.Parameters params = mCameraDevice.getParameters();
7879efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (!tryEnable3ALocks(toggle)) {
7889efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            throw new RuntimeException("Attempt to lock 3A on camera with no locking support!");
7899efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
7909efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
7919efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
7929efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private OnRunnerDoneListener mRunnerDoneCallback =
7939efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            new OnRunnerDoneListener() {
7949efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        public void onRunnerDone(int result) {
7959efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            synchronized(EffectsRecorder.this) {
796d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                if (mLogVerbose) {
797d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                    Log.v(TAG,
798d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                          "Graph runner done (" + EffectsRecorder.this
799d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                          + ", mRunner " + mRunner
800d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                          + ", mOldRunner " + mOldRunner + ")");
801d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                }
802d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                if (result == GraphRunner.RESULT_ERROR) {
803d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                    // Handle error case
804d519d3bff76107eda37dfc81b6d1a7c6e0091e42Eino-Ville Talvala                    Log.e(TAG, "Error running filter graph!");
8050e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                    Exception e = null;
8060e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                    if (mRunner != null) {
8070e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                        e = mRunner.getError();
8080e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                    } else if (mOldRunner != null) {
8090e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                        e = mOldRunner.getError();
8100e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                    }
8110e3f8387302b4aa882c20891f1faba74030f1a4fEino-Ville Talvala                    raiseError(e);
812d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                }
813a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                if (mOldRunner != null) {
814d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                    // Tear down old graph if available
815a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                    if (mLogVerbose) Log.v(TAG, "Tearing down old graph.");
816a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                    GLEnvironment glEnv = mGraphEnv.getContext().getGLEnvironment();
817a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                    if (glEnv != null && !glEnv.isActive()) {
818a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                        glEnv.activate();
819a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                    }
820a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                    mOldRunner.getGraph().tearDown(mGraphEnv.getContext());
821a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                    if (glEnv != null && glEnv.isActive()) {
822a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                        glEnv.deactivate();
823a91df49eb460aec8bcae4169e7d29ddc7f9ac3ecEino-Ville Talvala                    }
824a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                    mOldRunner = null;
825a7409d87247162002fca1719c035de67fa7e7535Eino-Ville Talvala                }
826cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                if (mState == STATE_PREVIEW ||
827cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala                        mState == STATE_STARTING_PREVIEW) {
8289efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    // Switching effects, start up the new runner
8299efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    if (mLogVerbose) Log.v(TAG, "Previous effect halted, starting new effect.");
8309efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    tryEnable3ALocks(false);
8319efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    mRunner.run();
8329efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                } else if (mState != STATE_RELEASED) {
8339efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    // Shutting down effects
8349efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    if (mLogVerbose) Log.v(TAG, "Runner halted, restoring direct preview");
835f3b7efa21a1f2b365655acd8efffbdc1b83e6b0cEino-Ville Talvala                    tryEnable3ALocks(false);
836926405a84a882ab78f2f5aa1e88c4961640724f7Eino-Ville Talvala                    sendMessage(EFFECT_NONE, EFFECT_MSG_EFFECTS_STOPPED);
8379efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                } else {
8389efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                    // STATE_RELEASED - camera will be/has been released as well, do nothing.
8399efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                }
8409efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            }
8419efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
8429efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    };
8439efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
8449efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    // Indicates that all camera/recording activity needs to halt
8459efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    public synchronized void release() {
8469efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mLogVerbose) Log.v(TAG, "Releasing (" + this + ")");
8479efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
8489efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        switch (mState) {
8499efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_RECORD:
850cfc9bcc6dc56135d905ffdaaf1b9838cf12a1558Eino-Ville Talvala            case STATE_STARTING_PREVIEW:
8519efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            case STATE_PREVIEW:
8529efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                stopPreview();
8539efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                // Fall-through
8549efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            default:
8559efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                mState = STATE_RELEASED;
8569efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                break;
8579efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
8589efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
8599efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala
8609efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    private void sendMessage(final int effect, final int msg) {
8619efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        if (mEffectsListener != null) {
8629efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            mHandler.post(new Runnable() {
8639efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                public void run() {
864d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                    mEffectsListener.onEffectsUpdate(effect, msg);
865d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                }
866d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn            });
867d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn        }
868d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn    }
869d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn
870d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn    private void raiseError(final Exception exception) {
871d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn        if (mEffectsListener != null) {
872d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn            mHandler.post(new Runnable() {
873d97adb8f99e522a613d484d9d5725dd84921489fMarius Renn                public void run() {
874dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                    if (mFd != null) {
875dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                        mEffectsListener.onEffectsError(exception, null);
876dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                    } else {
877dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                        mEffectsListener.onEffectsError(exception, mOutputFile);
878dca2af0a95ccb682d57bcea43f03fb01b929edf3Pannag Sanketi                    }
8799efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala                }
8809efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala            });
8819efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala        }
8829efb0b19fa929c528253f0a9b6f5b27791e1ee52Eino-Ville Talvala    }
883caf8466dcdf6d6c496e46961bb3132126363ef83Rodrigo Carceroni
8842670b3d7c318604f07b680b22360d349103144beWei Hua}
885