StateStartingPreview.java revision cc6139467c1c9545de1f098d938409e182c9b7ad
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.camera.captureintent.state; 18 19import com.google.common.base.Optional; 20 21import com.android.camera.CaptureModuleUtil; 22import com.android.camera.async.RefCountBase; 23import com.android.camera.captureintent.resource.ResourceConstructed; 24import com.android.camera.captureintent.resource.ResourceOpenedCamera; 25import com.android.camera.captureintent.resource.ResourceOpenedCameraImpl; 26import com.android.camera.captureintent.resource.ResourceSurfaceTexture; 27import com.android.camera.captureintent.stateful.EventHandler; 28import com.android.camera.captureintent.event.EventOnStartPreviewFailed; 29import com.android.camera.captureintent.event.EventOnStartPreviewSucceeded; 30import com.android.camera.captureintent.event.EventOnTextureViewLayoutChanged; 31import com.android.camera.captureintent.event.EventPause; 32import com.android.camera.captureintent.stateful.State; 33import com.android.camera.captureintent.stateful.StateImpl; 34import com.android.camera.debug.Log; 35import com.android.camera.exif.Rational; 36import com.android.camera.one.OneCamera; 37import com.android.camera.one.OneCameraAccessException; 38import com.android.camera.one.OneCameraCharacteristics; 39import com.android.camera.util.Size; 40 41import java.util.List; 42 43/** 44 * Represents a state that the module is waiting for the preview video stream 45 * to be started. 46 */ 47public final class StateStartingPreview extends StateImpl { 48 private static final Log.Tag TAG = new Log.Tag("StStartingPreview"); 49 50 private final RefCountBase<ResourceConstructed> mResourceConstructed; 51 private final RefCountBase<ResourceSurfaceTexture> mResourceSurfaceTexture; 52 private final RefCountBase<ResourceOpenedCamera> mResourceOpenedCamera; 53 54 public static StateStartingPreview from( 55 State previousState, 56 RefCountBase<ResourceConstructed> resourceConstructed, 57 RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, 58 OneCamera camera, 59 OneCamera.Facing cameraFacing, 60 OneCameraCharacteristics cameraCharacteristics, 61 Size pictureSize) { 62 return new StateStartingPreview( 63 previousState, 64 resourceConstructed, 65 resourceSurfaceTexture, 66 camera, 67 cameraFacing, 68 cameraCharacteristics, 69 pictureSize); 70 } 71 72 private StateStartingPreview( 73 State previousState, 74 RefCountBase<ResourceConstructed> resourceConstructed, 75 RefCountBase<ResourceSurfaceTexture> resourceSurfaceTexture, 76 OneCamera camera, 77 OneCamera.Facing cameraFacing, 78 OneCameraCharacteristics cameraCharacteristics, 79 Size pictureSize) { 80 super(previousState); 81 mResourceConstructed = resourceConstructed; 82 mResourceConstructed.addRef(); // Will be balanced in onLeave(). 83 mResourceSurfaceTexture = resourceSurfaceTexture; 84 mResourceSurfaceTexture.addRef(); // Will be balanced in onLeave(). 85 mResourceOpenedCamera = ResourceOpenedCameraImpl.create( 86 camera, cameraFacing, cameraCharacteristics, pictureSize); 87 registerEventHandlers(); 88 } 89 90 public void registerEventHandlers() { 91 /** Handles EventPause. */ 92 EventHandler<EventPause> pauseHandler = new EventHandler<EventPause>() { 93 @Override 94 public Optional<State> processEvent(EventPause event) { 95 return Optional.of((State) StateBackgroundWithSurfaceTexture.from( 96 StateStartingPreview.this, 97 mResourceConstructed, 98 mResourceSurfaceTexture)); 99 } 100 }; 101 setEventHandler(EventPause.class, pauseHandler); 102 103 /** Handles EventOnTextureViewLayoutChanged. */ 104 EventHandler<EventOnTextureViewLayoutChanged> onTextureViewLayoutChangedHandler = 105 new EventHandler<EventOnTextureViewLayoutChanged>() { 106 @Override 107 public Optional<State> processEvent(EventOnTextureViewLayoutChanged event) { 108 mResourceSurfaceTexture.get().setPreviewLayoutSize(event.getLayoutSize()); 109 return NO_CHANGE; 110 } 111 }; 112 setEventHandler(EventOnTextureViewLayoutChanged.class, onTextureViewLayoutChangedHandler); 113 114 /** Handles EventOnStartPreviewSucceeded. */ 115 EventHandler<EventOnStartPreviewSucceeded> onStartPreviewSucceededHandler = 116 new EventHandler<EventOnStartPreviewSucceeded>() { 117 @Override 118 public Optional<State> processEvent(EventOnStartPreviewSucceeded event) { 119 mResourceConstructed.get().getMainThread().execute(new Runnable() { 120 @Override 121 public void run() { 122 mResourceConstructed.get().getModuleUI().onPreviewStarted(); 123 } 124 }); 125 return Optional.of((State) StateReadyForCapture.from( 126 StateStartingPreview.this, 127 mResourceConstructed, 128 mResourceSurfaceTexture, 129 mResourceOpenedCamera)); 130 } 131 }; 132 setEventHandler(EventOnStartPreviewSucceeded.class, onStartPreviewSucceededHandler); 133 134 /** Handles EventOnStartPreviewFailed. */ 135 EventHandler<EventOnStartPreviewFailed> onStartPreviewFailedHandler = 136 new EventHandler<EventOnStartPreviewFailed>() { 137 @Override 138 public Optional<State> processEvent(EventOnStartPreviewFailed event) { 139 Log.e(TAG, "processOnPreviewSetupFailed"); 140 return Optional.of((State) StateFatal.from( 141 StateStartingPreview.this, mResourceConstructed)); 142 } 143 }; 144 setEventHandler(EventOnStartPreviewFailed.class, onStartPreviewFailedHandler); 145 } 146 147 @Override 148 public Optional<State> onEnter() { 149 final Size previewSize; 150 try { 151 // Pick a preview size with the right aspect ratio. 152 final List<Size> supportedPreviewSizes = mResourceOpenedCamera.get() 153 .getCameraCharacteristics().getSupportedPreviewSizes(); 154 final Rational pictureAspectRatio = 155 mResourceConstructed.get().getResolutionSetting().getPictureAspectRatio( 156 mResourceOpenedCamera.get().getCameraFacing()); 157 previewSize = CaptureModuleUtil.getOptimalPreviewSize( 158 supportedPreviewSizes.toArray(new Size[(supportedPreviewSizes.size())]), 159 pictureAspectRatio.toDouble(), 160 null); 161 if (previewSize == null) { 162 return Optional.of((State) StateFatal.from(this, mResourceConstructed)); 163 } 164 } catch (OneCameraAccessException ex) { 165 return Optional.of((State) StateFatal.from(this, mResourceConstructed)); 166 } 167 168 // Must do this before calling ResourceOpenedCamera.startPreview() 169 // since SurfaceTexture.setDefaultBufferSize() needs to be called 170 // before starting preview. Otherwise the size of preview video stream 171 // will be wrong. 172 mResourceSurfaceTexture.get().setPreviewSize(previewSize); 173 174 OneCamera.CaptureReadyCallback captureReadyCallback = 175 new OneCamera.CaptureReadyCallback() { 176 @Override 177 public void onSetupFailed() { 178 getStateMachine().processEvent(new EventOnStartPreviewFailed()); 179 } 180 181 @Override 182 public void onReadyForCapture() { 183 getStateMachine().processEvent(new EventOnStartPreviewSucceeded()); 184 } 185 }; 186 187 // Start preview right away. Don't dispatch it on other threads or it 188 // will cause race condition. b/19522251. 189 mResourceOpenedCamera.get().startPreview( 190 mResourceSurfaceTexture.get().createPreviewSurface(), captureReadyCallback); 191 return Optional.absent(); 192 } 193 194 @Override 195 public void onLeave() { 196 mResourceConstructed.close(); 197 mResourceSurfaceTexture.close(); 198 mResourceOpenedCamera.close(); 199 } 200} 201