MediaRecorder.java revision 1dc2ae2871aa3e958229e08ccf34099dff2fa402
1/* 2 * Copyright (C) 2007 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 android.media; 18 19import android.hardware.Camera; 20import android.os.Handler; 21import android.os.Looper; 22import android.os.Message; 23import android.util.Log; 24import android.view.Surface; 25import java.io.IOException; 26import java.io.FileNotFoundException; 27import java.io.FileOutputStream; 28import java.io.FileDescriptor; 29import java.lang.ref.WeakReference; 30 31/** 32 * Used to record audio and video. The recording control is based on a 33 * simple state machine (see below). 34 * 35 * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" /> 36 * </p> 37 * 38 * <p>A common case of using MediaRecorder to record audio works as follows: 39 * 40 * <pre>MediaRecorder recorder = new MediaRecorder(); 41 * recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 42 * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 43 * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 44 * recorder.setOutputFile(PATH_NAME); 45 * recorder.prepare(); 46 * recorder.start(); // Recording is now started 47 * ... 48 * recorder.stop(); 49 * recorder.reset(); // You can reuse the object by going back to setAudioSource() step 50 * recorder.release(); // Now the object cannot be reused 51 * </pre> 52 * 53 * <p>See the <a href="{@docRoot}guide/topics/media/index.html">Audio and Video</a> 54 * documentation for additional help with using MediaRecorder. 55 */ 56public class MediaRecorder 57{ 58 static { 59 System.loadLibrary("media_jni"); 60 native_init(); 61 } 62 private final static String TAG = "MediaRecorder"; 63 64 // The two fields below are accessed by native methods 65 @SuppressWarnings("unused") 66 private int mNativeContext; 67 68 @SuppressWarnings("unused") 69 private Surface mSurface; 70 71 private String mPath; 72 private FileDescriptor mFd; 73 private EventHandler mEventHandler; 74 private OnErrorListener mOnErrorListener; 75 private OnInfoListener mOnInfoListener; 76 77 /** 78 * Default constructor. 79 */ 80 public MediaRecorder() { 81 82 Looper looper; 83 if ((looper = Looper.myLooper()) != null) { 84 mEventHandler = new EventHandler(this, looper); 85 } else if ((looper = Looper.getMainLooper()) != null) { 86 mEventHandler = new EventHandler(this, looper); 87 } else { 88 mEventHandler = null; 89 } 90 91 /* Native setup requires a weak reference to our object. 92 * It's easier to create it here than in C++. 93 */ 94 native_setup(new WeakReference<MediaRecorder>(this)); 95 } 96 97 /** 98 * Sets a Camera to use for recording. Use this function to switch 99 * quickly between preview and capture mode without a teardown of 100 * the camera object. Must call before prepare(). 101 * 102 * @param c the Camera to use for recording 103 */ 104 public native void setCamera(Camera c); 105 106 /** 107 * Sets a Surface to show a preview of recorded media (video). Calls this 108 * before prepare() to make sure that the desirable preview display is 109 * set. 110 * 111 * @param sv the Surface to use for the preview 112 */ 113 public void setPreviewDisplay(Surface sv) { 114 mSurface = sv; 115 } 116 117 /** 118 * Defines the audio source. These constants are used with 119 * {@link MediaRecorder#setAudioSource(int)}. 120 */ 121 public final class AudioSource { 122 /* Do not change these values without updating their counterparts 123 * in include/media/mediarecorder.h! 124 */ 125 private AudioSource() {} 126 public static final int DEFAULT = 0; 127 /** Microphone audio source */ 128 public static final int MIC = 1; 129 130 /** Voice call uplink (Tx) audio source */ 131 public static final int VOICE_UPLINK = 2; 132 133 /** Voice call downlink (Rx) audio source */ 134 public static final int VOICE_DOWNLINK = 3; 135 136 /** Voice call uplink + downlink audio source */ 137 public static final int VOICE_CALL = 4; 138 139 /** Microphone audio source with same orientation as camera */ 140 public static final int CAMCORDER = 5; 141 142 /** Microphone audio source tuned for voice recognition */ 143 public static final int VOICE_RECOGNITION = 6; 144 } 145 146 /** 147 * Defines the video source. These constants are used with 148 * {@link MediaRecorder#setVideoSource(int)}. 149 */ 150 public final class VideoSource { 151 /* Do not change these values without updating their counterparts 152 * in include/media/mediarecorder.h! 153 */ 154 private VideoSource() {} 155 public static final int DEFAULT = 0; 156 /** Camera video source */ 157 public static final int CAMERA = 1; 158 } 159 160 /** 161 * Defines the output format. These constants are used with 162 * {@link MediaRecorder#setOutputFormat(int)}. 163 */ 164 public final class OutputFormat { 165 /* Do not change these values without updating their counterparts 166 * in include/media/mediarecorder.h! 167 */ 168 private OutputFormat() {} 169 public static final int DEFAULT = 0; 170 /** 3GPP media file format*/ 171 public static final int THREE_GPP = 1; 172 /** MPEG4 media file format*/ 173 public static final int MPEG_4 = 2; 174 175 /** The following formats are audio only .aac or .amr formats **/ 176 /** @deprecated Deprecated in favor of AMR_NB */ 177 /** TODO: change link when AMR_NB is exposed. Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */ 178 public static final int RAW_AMR = 3; 179 /** @hide AMR NB file format */ 180 public static final int AMR_NB = 3; 181 /** @hide AMR WB file format */ 182 public static final int AMR_WB = 4; 183 /** @hide AAC ADIF file format */ 184 public static final int AAC_ADIF = 5; 185 /** @hide AAC ADTS file format */ 186 public static final int AAC_ADTS = 6; 187 }; 188 189 /** 190 * Defines the audio encoding. These constants are used with 191 * {@link MediaRecorder#setAudioEncoder(int)}. 192 */ 193 public final class AudioEncoder { 194 /* Do not change these values without updating their counterparts 195 * in include/media/mediarecorder.h! 196 */ 197 private AudioEncoder() {} 198 public static final int DEFAULT = 0; 199 /** AMR (Narrowband) audio codec */ 200 public static final int AMR_NB = 1; 201 /** @hide AMR (Wideband) audio codec */ 202 public static final int AMR_WB = 2; 203 /** @hide AAC audio codec */ 204 public static final int AAC = 3; 205 /** @hide enhanced AAC audio codec */ 206 public static final int AAC_PLUS = 4; 207 /** @hide enhanced AAC plus audio codec */ 208 public static final int EAAC_PLUS = 5; 209 } 210 211 /** 212 * Defines the video encoding. These constants are used with 213 * {@link MediaRecorder#setVideoEncoder(int)}. 214 */ 215 public final class VideoEncoder { 216 /* Do not change these values without updating their counterparts 217 * in include/media/mediarecorder.h! 218 */ 219 private VideoEncoder() {} 220 public static final int DEFAULT = 0; 221 public static final int H263 = 1; 222 public static final int H264 = 2; 223 public static final int MPEG_4_SP = 3; 224 } 225 226 227 /** 228 * @hide Defines the audio sampling rate. This must be set before 229 * setAudioEncoder() or it will be ignored. 230 * This parameter is used with 231 * {@link MediaRecorder#setParameters(String)}. 232 */ 233 public final class AudioParamSamplingRate { 234 /* Do not change these values without updating their counterparts 235 * in include/media/mediarecorder.h! 236 */ 237 private AudioParamSamplingRate() {} 238 public static final String AUDIO_PARAM_SAMPLING_RATE_KEY = "audio-param-sampling-rate="; 239 } 240 241 /** 242 * @hide Defines the audio number of channels. This must be set before 243 * setAudioEncoder() or it will be ignored. 244 * This parameter is used with 245 * {@link MediaRecorder#setParameters(String)}. 246 */ 247 public final class AudioParamChannels { 248 /* Do not change these values without updating their counterparts 249 * in include/media/mediarecorder.h! 250 */ 251 private AudioParamChannels() {} 252 public static final String AUDIO_PARAM_NUMBER_OF_CHANNELS = "audio-param-number-of-channels="; 253 } 254 255 /** 256 * @hide Defines the audio encoding bitrate. This must be set before 257 * setAudioEncoder() or it will be ignored. 258 * This parameter is used with 259 * {@link MediaRecorder#setParameters(String)}. 260 */ 261 public final class AudioParamEncodingBitrate{ 262 private AudioParamEncodingBitrate() {} 263 public static final String AUDIO_PARAM_ENCODING_BITRATE = "audio-param-encoding-bitrate="; 264 } 265 266 /** 267 * Sets the audio source to be used for recording. If this method is not 268 * called, the output file will not contain an audio track. The source needs 269 * to be specified before setting recording-parameters or encoders. Call 270 * this only before setOutputFormat(). 271 * 272 * @param audio_source the audio source to use 273 * @throws IllegalStateException if it is called after setOutputFormat() 274 * @see android.media.MediaRecorder.AudioSource 275 */ 276 public native void setAudioSource(int audio_source) 277 throws IllegalStateException; 278 279 /** 280 * Gets the maximum value for audio sources. 281 * @see android.media.MediaRecorder.AudioSource 282 */ 283 public static final int getAudioSourceMax() { return AudioSource.VOICE_RECOGNITION; } 284 285 /** 286 * Sets the video source to be used for recording. If this method is not 287 * called, the output file will not contain an video track. The source needs 288 * to be specified before setting recording-parameters or encoders. Call 289 * this only before setOutputFormat(). 290 * 291 * @param video_source the video source to use 292 * @throws IllegalStateException if it is called after setOutputFormat() 293 * @see android.media.MediaRecorder.VideoSource 294 */ 295 public native void setVideoSource(int video_source) 296 throws IllegalStateException; 297 298 /** 299 * Sets the format of the output file produced during recording. Call this 300 * after setAudioSource()/setVideoSource() but before prepare(). 301 * 302 * <p>It is recommended to always use 3GP format when using the H.263 303 * video encoder and AMR audio encoder. Using an MPEG-4 container format 304 * may confuse some desktop players.</p> 305 * 306 * @param output_format the output format to use. The output format 307 * needs to be specified before setting recording-parameters or encoders. 308 * @throws IllegalStateException if it is called after prepare() or before 309 * setAudioSource()/setVideoSource(). 310 * @see android.media.MediaRecorder.OutputFormat 311 */ 312 public native void setOutputFormat(int output_format) 313 throws IllegalStateException; 314 315 /** 316 * Sets the width and height of the video to be captured. Must be called 317 * after setVideoSource(). Call this after setOutFormat() but before 318 * prepare(). 319 * 320 * @param width the width of the video to be captured 321 * @param height the height of the video to be captured 322 * @throws IllegalStateException if it is called after 323 * prepare() or before setOutputFormat() 324 */ 325 public native void setVideoSize(int width, int height) 326 throws IllegalStateException; 327 328 /** 329 * Sets the frame rate of the video to be captured. Must be called 330 * after setVideoSource(). Call this after setOutFormat() but before 331 * prepare(). 332 * 333 * @param rate the number of frames per second of video to capture 334 * @throws IllegalStateException if it is called after 335 * prepare() or before setOutputFormat(). 336 * 337 * NOTE: On some devices that have auto-frame rate, this sets the 338 * maximum frame rate, not a constant frame rate. Actual frame rate 339 * will vary according to lighting conditions. 340 */ 341 public native void setVideoFrameRate(int rate) throws IllegalStateException; 342 343 /** 344 * Sets the maximum duration (in ms) of the recording session. 345 * Call this after setOutFormat() but before prepare(). 346 * After recording reaches the specified duration, a notification 347 * will be sent to the {@link android.media.MediaRecorder.OnInfoListener} 348 * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED} 349 * and recording will be stopped. Stopping happens asynchronously, there 350 * is no guarantee that the recorder will have stopped by the time the 351 * listener is notified. 352 * 353 * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit) 354 * 355 */ 356 public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException; 357 358 /** 359 * Sets the maximum filesize (in bytes) of the recording session. 360 * Call this after setOutFormat() but before prepare(). 361 * After recording reaches the specified filesize, a notification 362 * will be sent to the {@link android.media.MediaRecorder.OnInfoListener} 363 * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED} 364 * and recording will be stopped. Stopping happens asynchronously, there 365 * is no guarantee that the recorder will have stopped by the time the 366 * listener is notified. 367 * 368 * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit) 369 * 370 */ 371 public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException; 372 373 /** 374 * Sets the audio encoder to be used for recording. If this method is not 375 * called, the output file will not contain an audio track. Call this after 376 * setOutputFormat() but before prepare(). 377 * 378 * @param audio_encoder the audio encoder to use. 379 * @throws IllegalStateException if it is called before 380 * setOutputFormat() or after prepare(). 381 * @see android.media.MediaRecorder.AudioEncoder 382 */ 383 public native void setAudioEncoder(int audio_encoder) 384 throws IllegalStateException; 385 386 /** 387 * Sets the video encoder to be used for recording. If this method is not 388 * called, the output file will not contain an video track. Call this after 389 * setOutputFormat() and before prepare(). 390 * 391 * @param video_encoder the video encoder to use. 392 * @throws IllegalStateException if it is called before 393 * setOutputFormat() or after prepare() 394 * @see android.media.MediaRecorder.VideoEncoder 395 */ 396 public native void setVideoEncoder(int video_encoder) 397 throws IllegalStateException; 398 399 /** 400 * @hide Sets a parameter in the author engine. 401 * 402 * @param params the parameter to set. 403 * @see android.media.MediaRecorder.AudioParamSamplingRate 404 * @see android.media.MediaRecorder.AudioParamChannels 405 * @see android.media.MediaRecorder.AudioParamEncodingBitrate 406 */ 407 public native void setParameters(String params); 408 409 /** 410 * Pass in the file descriptor of the file to be written. Call this after 411 * setOutputFormat() but before prepare(). 412 * 413 * @param fd an open file descriptor to be written into. 414 * @throws IllegalStateException if it is called before 415 * setOutputFormat() or after prepare() 416 */ 417 public void setOutputFile(FileDescriptor fd) throws IllegalStateException 418 { 419 mPath = null; 420 mFd = fd; 421 } 422 423 /** 424 * Sets the path of the output file to be produced. Call this after 425 * setOutputFormat() but before prepare(). 426 * 427 * @param path The pathname to use. 428 * @throws IllegalStateException if it is called before 429 * setOutputFormat() or after prepare() 430 */ 431 public void setOutputFile(String path) throws IllegalStateException 432 { 433 mFd = null; 434 mPath = path; 435 } 436 437 // native implementation 438 private native void _setOutputFile(FileDescriptor fd, long offset, long length) 439 throws IllegalStateException, IOException; 440 private native void _prepare() throws IllegalStateException, IOException; 441 442 /** 443 * Prepares the recorder to begin capturing and encoding data. This method 444 * must be called after setting up the desired audio and video sources, 445 * encoders, file format, etc., but before start(). 446 * 447 * @throws IllegalStateException if it is called after 448 * start() or before setOutputFormat(). 449 * @throws IOException if prepare fails otherwise. 450 */ 451 public void prepare() throws IllegalStateException, IOException 452 { 453 if (mPath != null) { 454 FileOutputStream fos = new FileOutputStream(mPath); 455 try { 456 _setOutputFile(fos.getFD(), 0, 0); 457 } finally { 458 fos.close(); 459 } 460 } else if (mFd != null) { 461 _setOutputFile(mFd, 0, 0); 462 } else { 463 throw new IOException("No valid output file"); 464 } 465 _prepare(); 466 } 467 468 /** 469 * Begins capturing and encoding data to the file specified with 470 * setOutputFile(). Call this after prepare(). 471 * 472 * @throws IllegalStateException if it is called before 473 * prepare(). 474 */ 475 public native void start() throws IllegalStateException; 476 477 /** 478 * Stops recording. Call this after start(). Once recording is stopped, 479 * you will have to configure it again as if it has just been constructed. 480 * 481 * @throws IllegalStateException if it is called before start() 482 */ 483 public native void stop() throws IllegalStateException; 484 485 /** 486 * Restarts the MediaRecorder to its idle state. After calling 487 * this method, you will have to configure it again as if it had just been 488 * constructed. 489 */ 490 public void reset() { 491 native_reset(); 492 493 // make sure none of the listeners get called anymore 494 mEventHandler.removeCallbacksAndMessages(null); 495 } 496 497 private native void native_reset(); 498 499 /** 500 * Returns the maximum absolute amplitude that was sampled since the last 501 * call to this method. Call this only after the setAudioSource(). 502 * 503 * @return the maximum absolute amplitude measured since the last call, or 504 * 0 when called for the first time 505 * @throws IllegalStateException if it is called before 506 * the audio source has been set. 507 */ 508 public native int getMaxAmplitude() throws IllegalStateException; 509 510 /* Do not change this value without updating its counterpart 511 * in include/media/mediarecorder.h! 512 */ 513 /** Unspecified media recorder error. 514 * @see android.media.MediaRecorder.OnErrorListener 515 */ 516 public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; 517 518 /** 519 * Interface definition for a callback to be invoked when an error 520 * occurs while recording. 521 */ 522 public interface OnErrorListener 523 { 524 /** 525 * Called when an error occurs while recording. 526 * 527 * @param mr the MediaRecorder that encountered the error 528 * @param what the type of error that has occurred: 529 * <ul> 530 * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN} 531 * </ul> 532 * @param extra an extra code, specific to the error type 533 */ 534 void onError(MediaRecorder mr, int what, int extra); 535 } 536 537 /** 538 * Register a callback to be invoked when an error occurs while 539 * recording. 540 * 541 * @param l the callback that will be run 542 */ 543 public void setOnErrorListener(OnErrorListener l) 544 { 545 mOnErrorListener = l; 546 } 547 548 /* Do not change these values without updating their counterparts 549 * in include/media/mediarecorder.h! 550 */ 551 /** Unspecified media recorder error. 552 * @see android.media.MediaRecorder.OnInfoListener 553 */ 554 public static final int MEDIA_RECORDER_INFO_UNKNOWN = 1; 555 /** A maximum duration had been setup and has now been reached. 556 * @see android.media.MediaRecorder.OnInfoListener 557 */ 558 public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; 559 /** A maximum filesize had been setup and has now been reached. 560 * @see android.media.MediaRecorder.OnInfoListener 561 */ 562 public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; 563 564 /** 565 * Interface definition for a callback to be invoked when an error 566 * occurs while recording. 567 */ 568 public interface OnInfoListener 569 { 570 /** 571 * Called when an error occurs while recording. 572 * 573 * @param mr the MediaRecorder that encountered the error 574 * @param what the type of error that has occurred: 575 * <ul> 576 * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN} 577 * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED} 578 * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED} 579 * </ul> 580 * @param extra an extra code, specific to the error type 581 */ 582 void onInfo(MediaRecorder mr, int what, int extra); 583 } 584 585 /** 586 * Register a callback to be invoked when an informational event occurs while 587 * recording. 588 * 589 * @param listener the callback that will be run 590 */ 591 public void setOnInfoListener(OnInfoListener listener) 592 { 593 mOnInfoListener = listener; 594 } 595 596 private class EventHandler extends Handler 597 { 598 private MediaRecorder mMediaRecorder; 599 600 public EventHandler(MediaRecorder mr, Looper looper) { 601 super(looper); 602 mMediaRecorder = mr; 603 } 604 605 /* Do not change these values without updating their counterparts 606 * in include/media/mediarecorder.h! 607 */ 608 private static final int MEDIA_RECORDER_EVENT_ERROR = 1; 609 private static final int MEDIA_RECORDER_EVENT_INFO = 2; 610 611 @Override 612 public void handleMessage(Message msg) { 613 if (mMediaRecorder.mNativeContext == 0) { 614 Log.w(TAG, "mediarecorder went away with unhandled events"); 615 return; 616 } 617 switch(msg.what) { 618 case MEDIA_RECORDER_EVENT_ERROR: 619 if (mOnErrorListener != null) 620 mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2); 621 622 return; 623 624 case MEDIA_RECORDER_EVENT_INFO: 625 if (mOnInfoListener != null) 626 mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2); 627 628 return; 629 630 default: 631 Log.e(TAG, "Unknown message type " + msg.what); 632 return; 633 } 634 } 635 } 636 637 /** 638 * Called from native code when an interesting event happens. This method 639 * just uses the EventHandler system to post the event back to the main app thread. 640 * We use a weak reference to the original MediaRecorder object so that the native 641 * code is safe from the object disappearing from underneath it. (This is 642 * the cookie passed to native_setup().) 643 */ 644 private static void postEventFromNative(Object mediarecorder_ref, 645 int what, int arg1, int arg2, Object obj) 646 { 647 MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get(); 648 if (mr == null) { 649 return; 650 } 651 652 if (mr.mEventHandler != null) { 653 Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj); 654 mr.mEventHandler.sendMessage(m); 655 } 656 } 657 658 /** 659 * Releases resources associated with this MediaRecorder object. 660 * It is good practice to call this method when you're done 661 * using the MediaRecorder. 662 */ 663 public native void release(); 664 665 private static native final void native_init(); 666 667 private native final void native_setup(Object mediarecorder_this) throws IllegalStateException; 668 669 private native final void native_finalize(); 670 671 @Override 672 protected void finalize() { native_finalize(); } 673} 674