1 package org.robolectric.shadows; 2 3 import android.graphics.SurfaceTexture; 4 import android.hardware.Camera; 5 import android.media.MediaRecorder; 6 import android.view.Surface; 7 import com.google.common.base.Preconditions; 8 import org.robolectric.annotation.Implementation; 9 import org.robolectric.annotation.Implements; 10 11 @Implements(MediaRecorder.class) 12 public class ShadowMediaRecorder { 13 @SuppressWarnings("UnusedDeclaration") 14 @Implementation __staticInitializer__()15 protected static void __staticInitializer__() { 16 // don't bind the JNI library 17 } 18 19 // Recording machine state, as per: 20 // http://developer.android.com/reference/android/media/MediaRecorder.html 21 public static final int STATE_ERROR = -1; 22 public static final int STATE_INITIAL = 1; 23 public static final int STATE_INITIALIZED = 2; 24 public static final int STATE_DATA_SOURCE_CONFIGURED = 3; 25 public static final int STATE_PREPARED = 4; 26 public static final int STATE_RECORDING = 5; 27 public static final int STATE_RELEASED = 6; 28 29 private int state; 30 31 private Camera camera; 32 private int audioChannels; 33 private int audioEncoder; 34 private int audioBitRate; 35 private int audioSamplingRate; 36 private int audioSource; 37 private int maxDuration; 38 private long maxFileSize; 39 private String outputPath; 40 private int outputFormat; 41 private int videoEncoder; 42 private int videoBitRate; 43 private int videoFrameRate; 44 private int videoWidth; 45 private int videoHeight; 46 private int videoSource; 47 48 private Surface previewDisplay; 49 private Surface recordingSurface; 50 private SurfaceTexture recordingSurfaceTexture; 51 private MediaRecorder.OnErrorListener errorListener; 52 private MediaRecorder.OnInfoListener infoListener; 53 54 @Implementation __constructor__()55 protected void __constructor__() { 56 state = STATE_INITIAL; 57 } 58 59 @Implementation setAudioChannels(int numChannels)60 protected void setAudioChannels(int numChannels) { 61 audioChannels = numChannels; 62 } 63 64 @Implementation setAudioEncoder(int audio_encoder)65 protected void setAudioEncoder(int audio_encoder) { 66 audioEncoder = audio_encoder; 67 state = STATE_DATA_SOURCE_CONFIGURED; 68 } 69 70 @Implementation setAudioEncodingBitRate(int bitRate)71 protected void setAudioEncodingBitRate(int bitRate) { 72 audioBitRate = bitRate; 73 } 74 75 @Implementation setAudioSamplingRate(int samplingRate)76 protected void setAudioSamplingRate(int samplingRate) { 77 audioSamplingRate = samplingRate; 78 } 79 80 @Implementation setAudioSource(int audio_source)81 protected void setAudioSource(int audio_source) { 82 audioSource = audio_source; 83 state = STATE_INITIALIZED; 84 } 85 86 @Implementation setCamera(Camera c)87 protected void setCamera(Camera c) { 88 camera = c; 89 } 90 91 @Implementation setMaxDuration(int max_duration_ms)92 protected void setMaxDuration(int max_duration_ms) { 93 maxDuration = max_duration_ms; 94 } 95 96 @Implementation setMaxFileSize(long max_filesize_bytes)97 protected void setMaxFileSize(long max_filesize_bytes) { 98 maxFileSize = max_filesize_bytes; 99 } 100 101 @Implementation setOnErrorListener(MediaRecorder.OnErrorListener l)102 protected void setOnErrorListener(MediaRecorder.OnErrorListener l) { 103 errorListener = l; 104 } 105 106 @Implementation setOnInfoListener(MediaRecorder.OnInfoListener listener)107 protected void setOnInfoListener(MediaRecorder.OnInfoListener listener) { 108 infoListener = listener; 109 } 110 111 @Implementation setOutputFile(String path)112 protected void setOutputFile(String path) { 113 outputPath = path; 114 state = STATE_DATA_SOURCE_CONFIGURED; 115 } 116 117 @Implementation setOutputFormat(int output_format)118 protected void setOutputFormat(int output_format) { 119 outputFormat = output_format; 120 state = STATE_DATA_SOURCE_CONFIGURED; 121 } 122 123 @Implementation setPreviewDisplay(Surface sv)124 protected void setPreviewDisplay(Surface sv) { 125 previewDisplay = sv; 126 state = STATE_DATA_SOURCE_CONFIGURED; 127 } 128 129 @Implementation setVideoEncoder(int video_encoder)130 protected void setVideoEncoder(int video_encoder) { 131 videoEncoder = video_encoder; 132 state = STATE_DATA_SOURCE_CONFIGURED; 133 } 134 135 @Implementation setVideoEncodingBitRate(int bitRate)136 protected void setVideoEncodingBitRate(int bitRate) { 137 videoBitRate = bitRate; 138 } 139 140 @Implementation setVideoFrameRate(int rate)141 protected void setVideoFrameRate(int rate) { 142 videoFrameRate = rate; 143 state = STATE_DATA_SOURCE_CONFIGURED; 144 } 145 146 @Implementation setVideoSize(int width, int height)147 protected void setVideoSize(int width, int height) { 148 videoWidth = width; 149 videoHeight = height; 150 state = STATE_DATA_SOURCE_CONFIGURED; 151 } 152 153 @Implementation setVideoSource(int video_source)154 protected void setVideoSource(int video_source) { 155 videoSource = video_source; 156 state = STATE_INITIALIZED; 157 } 158 159 @Implementation prepare()160 protected void prepare() { 161 state = STATE_PREPARED; 162 } 163 164 @Implementation start()165 protected void start() { 166 state = STATE_RECORDING; 167 } 168 169 @Implementation stop()170 protected void stop() { 171 state = STATE_INITIAL; 172 } 173 174 @Implementation reset()175 protected void reset() { 176 state = STATE_INITIAL; 177 } 178 179 @Implementation release()180 protected void release() { 181 state = STATE_RELEASED; 182 if (recordingSurface != null) { 183 recordingSurface.release(); 184 recordingSurface = null; 185 } 186 if (recordingSurfaceTexture != null) { 187 recordingSurfaceTexture.release(); 188 recordingSurfaceTexture = null; 189 } 190 } 191 192 @Implementation getSurface()193 protected Surface getSurface() { 194 Preconditions.checkState( 195 getVideoSource() == MediaRecorder.VideoSource.SURFACE, 196 "getSurface can only be called when setVideoSource is set to SURFACE"); 197 // There is a diagram of the MediaRecorder state machine here: 198 // https://developer.android.com/reference/android/media/MediaRecorder 199 Preconditions.checkState( 200 state == STATE_PREPARED || state == STATE_RECORDING, 201 "getSurface must be called after prepare() and before stop()"); 202 203 if (recordingSurface == null) { 204 recordingSurfaceTexture = new SurfaceTexture(/* texName= */ 0); 205 recordingSurface = new Surface(recordingSurfaceTexture); 206 } 207 208 return recordingSurface; 209 } 210 getCamera()211 public Camera getCamera() { 212 return camera; 213 } 214 getAudioChannels()215 public int getAudioChannels() { 216 return audioChannels; 217 } 218 getAudioEncoder()219 public int getAudioEncoder() { 220 return audioEncoder; 221 } 222 getAudioEncodingBitRate()223 public int getAudioEncodingBitRate() { 224 return audioBitRate; 225 } 226 getAudioSamplingRate()227 public int getAudioSamplingRate() { 228 return audioSamplingRate; 229 } 230 getAudioSource()231 public int getAudioSource() { 232 return audioSource; 233 } 234 getMaxDuration()235 public int getMaxDuration() { 236 return maxDuration; 237 } 238 getMaxFileSize()239 public long getMaxFileSize() { 240 return maxFileSize; 241 } 242 getOutputPath()243 public String getOutputPath() { 244 return outputPath; 245 } 246 getOutputFormat()247 public int getOutputFormat() { 248 return outputFormat; 249 } 250 getVideoEncoder()251 public int getVideoEncoder() { 252 return videoEncoder; 253 } 254 getVideoEncodingBitRate()255 public int getVideoEncodingBitRate() { 256 return videoBitRate; 257 } 258 getVideoFrameRate()259 public int getVideoFrameRate() { 260 return videoFrameRate; 261 } 262 getVideoWidth()263 public int getVideoWidth() { 264 return videoWidth; 265 } 266 getVideoHeight()267 public int getVideoHeight() { 268 return videoHeight; 269 } 270 getVideoSource()271 public int getVideoSource() { 272 return videoSource; 273 } 274 getPreviewDisplay()275 public Surface getPreviewDisplay() { 276 return previewDisplay; 277 } 278 getErrorListener()279 public MediaRecorder.OnErrorListener getErrorListener() { 280 return errorListener; 281 } 282 getInfoListener()283 public MediaRecorder.OnInfoListener getInfoListener() { 284 return infoListener; 285 } 286 getState()287 public int getState() { 288 return state; 289 } 290 } 291