Home | History | Annotate | Download | only in media
      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 
     17 package android.media;
     18 
     19 import android.app.ActivityThread;
     20 import android.hardware.Camera;
     21 import android.os.Handler;
     22 import android.os.Looper;
     23 import android.os.Message;
     24 import android.util.Log;
     25 import android.view.Surface;
     26 
     27 import java.io.FileDescriptor;
     28 import java.io.FileOutputStream;
     29 import java.io.IOException;
     30 import java.lang.ref.WeakReference;
     31 
     32 /**
     33  * Used to record audio and video. The recording control is based on a
     34  * simple state machine (see below).
     35  *
     36  * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" />
     37  * </p>
     38  *
     39  * <p>A common case of using MediaRecorder to record audio works as follows:
     40  *
     41  * <pre>MediaRecorder recorder = new MediaRecorder();
     42  * recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
     43  * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
     44  * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
     45  * recorder.setOutputFile(PATH_NAME);
     46  * recorder.prepare();
     47  * recorder.start();   // Recording is now started
     48  * ...
     49  * recorder.stop();
     50  * recorder.reset();   // You can reuse the object by going back to setAudioSource() step
     51  * recorder.release(); // Now the object cannot be reused
     52  * </pre>
     53  *
     54  * <p>Applications may want to register for informational and error
     55  * events in order to be informed of some internal update and possible
     56  * runtime errors during recording. Registration for such events is
     57  * done by setting the appropriate listeners (via calls
     58  * (to {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener and/or
     59  * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener).
     60  * In order to receive the respective callback associated with these listeners,
     61  * applications are required to create MediaRecorder objects on threads with a
     62  * Looper running (the main UI thread by default already has a Looper running).
     63  *
     64  * <p><strong>Note:</strong> Currently, MediaRecorder does not work on the emulator.
     65  *
     66  * <div class="special reference">
     67  * <h3>Developer Guides</h3>
     68  * <p>For more information about how to use MediaRecorder for recording video, read the
     69  * <a href="{@docRoot}guide/topics/media/camera.html#capture-video">Camera</a> developer guide.
     70  * For more information about how to use MediaRecorder for recording sound, read the
     71  * <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
     72  * </div>
     73  */
     74 public class MediaRecorder
     75 {
     76     static {
     77         System.loadLibrary("media_jni");
     78         native_init();
     79     }
     80     private final static String TAG = "MediaRecorder";
     81 
     82     // The two fields below are accessed by native methods
     83     @SuppressWarnings("unused")
     84     private int mNativeContext;
     85 
     86     @SuppressWarnings("unused")
     87     private Surface mSurface;
     88 
     89     private String mPath;
     90     private FileDescriptor mFd;
     91     private EventHandler mEventHandler;
     92     private OnErrorListener mOnErrorListener;
     93     private OnInfoListener mOnInfoListener;
     94 
     95     /**
     96      * Default constructor.
     97      */
     98     public MediaRecorder() {
     99 
    100         Looper looper;
    101         if ((looper = Looper.myLooper()) != null) {
    102             mEventHandler = new EventHandler(this, looper);
    103         } else if ((looper = Looper.getMainLooper()) != null) {
    104             mEventHandler = new EventHandler(this, looper);
    105         } else {
    106             mEventHandler = null;
    107         }
    108 
    109         String packageName = ActivityThread.currentPackageName();
    110         /* Native setup requires a weak reference to our object.
    111          * It's easier to create it here than in C++.
    112          */
    113         native_setup(new WeakReference<MediaRecorder>(this), packageName);
    114     }
    115 
    116     /**
    117      * Sets a Camera to use for recording. Use this function to switch
    118      * quickly between preview and capture mode without a teardown of
    119      * the camera object. {@link android.hardware.Camera#unlock()} should be
    120      * called before this. Must call before prepare().
    121      *
    122      * @param c the Camera to use for recording
    123      */
    124     public native void setCamera(Camera c);
    125 
    126     /**
    127      * Sets a Surface to show a preview of recorded media (video). Calls this
    128      * before prepare() to make sure that the desirable preview display is
    129      * set. If {@link #setCamera(Camera)} is used and the surface has been
    130      * already set to the camera, application do not need to call this. If
    131      * this is called with non-null surface, the preview surface of the camera
    132      * will be replaced by the new surface. If this method is called with null
    133      * surface or not called at all, media recorder will not change the preview
    134      * surface of the camera.
    135      *
    136      * @param sv the Surface to use for the preview
    137      * @see android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)
    138      */
    139     public void setPreviewDisplay(Surface sv) {
    140         mSurface = sv;
    141     }
    142 
    143     /**
    144      * Defines the audio source. These constants are used with
    145      * {@link MediaRecorder#setAudioSource(int)}.
    146      */
    147     public final class AudioSource {
    148       /* Do not change these values without updating their counterparts
    149        * in system/core/include/system/audio.h!
    150        */
    151         private AudioSource() {}
    152 
    153         /** Default audio source **/
    154         public static final int DEFAULT = 0;
    155 
    156         /** Microphone audio source */
    157         public static final int MIC = 1;
    158 
    159         /** Voice call uplink (Tx) audio source */
    160         public static final int VOICE_UPLINK = 2;
    161 
    162         /** Voice call downlink (Rx) audio source */
    163         public static final int VOICE_DOWNLINK = 3;
    164 
    165         /** Voice call uplink + downlink audio source */
    166         public static final int VOICE_CALL = 4;
    167 
    168         /** Microphone audio source with same orientation as camera if available, the main
    169          *  device microphone otherwise */
    170         public static final int CAMCORDER = 5;
    171 
    172         /** Microphone audio source tuned for voice recognition if available, behaves like
    173          *  {@link #DEFAULT} otherwise. */
    174         public static final int VOICE_RECOGNITION = 6;
    175 
    176         /** Microphone audio source tuned for voice communications such as VoIP. It
    177          *  will for instance take advantage of echo cancellation or automatic gain control
    178          *  if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
    179          *  is applied.
    180          */
    181         public static final int VOICE_COMMUNICATION = 7;
    182 
    183         /**
    184          * Audio source for a submix of audio streams to be presented remotely.
    185          * <p>
    186          * An application can use this audio source to capture a mix of audio streams
    187          * that should be transmitted to a remote receiver such as a Wifi display.
    188          * While recording is active, these audio streams are redirected to the remote
    189          * submix instead of being played on the device speaker or headset.
    190          * </p><p>
    191          * Certain streams are excluded from the remote submix, including
    192          * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_ALARM},
    193          * and {@link AudioManager#STREAM_NOTIFICATION}.  These streams will continue
    194          * to be presented locally as usual.
    195          * </p><p>
    196          * Capturing the remote submix audio requires the
    197          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
    198          * This permission is reserved for use by system components and is not available to
    199          * third-party applications.
    200          * </p>
    201          */
    202         public static final int REMOTE_SUBMIX = 8;
    203 
    204         /**
    205          * Audio source for preemptible, low-priority software hotword detection
    206          * It presents the same gain and pre processing tuning as {@link #VOICE_RECOGNITION}.
    207          * <p>
    208          * An application should use this audio source when it wishes to do
    209          * always-on software hotword detection, while gracefully giving in to any other application
    210          * that might want to read from the microphone.
    211          * </p>
    212          * This is a hidden audio source.
    213          * @hide
    214          */
    215         protected static final int HOTWORD = 1999;
    216     }
    217 
    218     /**
    219      * Defines the video source. These constants are used with
    220      * {@link MediaRecorder#setVideoSource(int)}.
    221      */
    222     public final class VideoSource {
    223       /* Do not change these values without updating their counterparts
    224        * in include/media/mediarecorder.h!
    225        */
    226         private VideoSource() {}
    227         public static final int DEFAULT = 0;
    228         /** Camera video source */
    229         public static final int CAMERA = 1;
    230         /** @hide */
    231         public static final int GRALLOC_BUFFER = 2;
    232     }
    233 
    234     /**
    235      * Defines the output format. These constants are used with
    236      * {@link MediaRecorder#setOutputFormat(int)}.
    237      */
    238     public final class OutputFormat {
    239       /* Do not change these values without updating their counterparts
    240        * in include/media/mediarecorder.h!
    241        */
    242         private OutputFormat() {}
    243         public static final int DEFAULT = 0;
    244         /** 3GPP media file format*/
    245         public static final int THREE_GPP = 1;
    246         /** MPEG4 media file format*/
    247         public static final int MPEG_4 = 2;
    248 
    249         /** The following formats are audio only .aac or .amr formats */
    250 
    251         /**
    252          * AMR NB file format
    253          * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
    254          */
    255         public static final int RAW_AMR = 3;
    256 
    257         /** AMR NB file format */
    258         public static final int AMR_NB = 3;
    259 
    260         /** AMR WB file format */
    261         public static final int AMR_WB = 4;
    262 
    263         /** @hide AAC ADIF file format */
    264         public static final int AAC_ADIF = 5;
    265 
    266         /** AAC ADTS file format */
    267         public static final int AAC_ADTS = 6;
    268 
    269         /** @hide Stream over a socket, limited to a single stream */
    270         public static final int OUTPUT_FORMAT_RTP_AVP = 7;
    271 
    272         /** @hide H.264/AAC data encapsulated in MPEG2/TS */
    273         public static final int OUTPUT_FORMAT_MPEG2TS = 8;
    274     };
    275 
    276     /**
    277      * Defines the audio encoding. These constants are used with
    278      * {@link MediaRecorder#setAudioEncoder(int)}.
    279      */
    280     public final class AudioEncoder {
    281       /* Do not change these values without updating their counterparts
    282        * in include/media/mediarecorder.h!
    283        */
    284         private AudioEncoder() {}
    285         public static final int DEFAULT = 0;
    286         /** AMR (Narrowband) audio codec */
    287         public static final int AMR_NB = 1;
    288         /** AMR (Wideband) audio codec */
    289         public static final int AMR_WB = 2;
    290         /** AAC Low Complexity (AAC-LC) audio codec */
    291         public static final int AAC = 3;
    292         /** High Efficiency AAC (HE-AAC) audio codec */
    293         public static final int HE_AAC = 4;
    294         /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
    295         public static final int AAC_ELD = 5;
    296     }
    297 
    298     /**
    299      * Defines the video encoding. These constants are used with
    300      * {@link MediaRecorder#setVideoEncoder(int)}.
    301      */
    302     public final class VideoEncoder {
    303       /* Do not change these values without updating their counterparts
    304        * in include/media/mediarecorder.h!
    305        */
    306         private VideoEncoder() {}
    307         public static final int DEFAULT = 0;
    308         public static final int H263 = 1;
    309         public static final int H264 = 2;
    310         public static final int MPEG_4_SP = 3;
    311     }
    312 
    313     /**
    314      * Sets the audio source to be used for recording. If this method is not
    315      * called, the output file will not contain an audio track. The source needs
    316      * to be specified before setting recording-parameters or encoders. Call
    317      * this only before setOutputFormat().
    318      *
    319      * @param audio_source the audio source to use
    320      * @throws IllegalStateException if it is called after setOutputFormat()
    321      * @see android.media.MediaRecorder.AudioSource
    322      */
    323     public native void setAudioSource(int audio_source)
    324             throws IllegalStateException;
    325 
    326     /**
    327      * Gets the maximum value for audio sources.
    328      * @see android.media.MediaRecorder.AudioSource
    329      */
    330     public static final int getAudioSourceMax() {
    331         return AudioSource.REMOTE_SUBMIX;
    332     }
    333 
    334     /**
    335      * Sets the video source to be used for recording. If this method is not
    336      * called, the output file will not contain an video track. The source needs
    337      * to be specified before setting recording-parameters or encoders. Call
    338      * this only before setOutputFormat().
    339      *
    340      * @param video_source the video source to use
    341      * @throws IllegalStateException if it is called after setOutputFormat()
    342      * @see android.media.MediaRecorder.VideoSource
    343      */
    344     public native void setVideoSource(int video_source)
    345             throws IllegalStateException;
    346 
    347     /**
    348      * Uses the settings from a CamcorderProfile object for recording. This method should
    349      * be called after the video AND audio sources are set, and before setOutputFile().
    350      * If a time lapse CamcorderProfile is used, audio related source or recording
    351      * parameters are ignored.
    352      *
    353      * @param profile the CamcorderProfile to use
    354      * @see android.media.CamcorderProfile
    355      */
    356     public void setProfile(CamcorderProfile profile) {
    357         setOutputFormat(profile.fileFormat);
    358         setVideoFrameRate(profile.videoFrameRate);
    359         setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
    360         setVideoEncodingBitRate(profile.videoBitRate);
    361         setVideoEncoder(profile.videoCodec);
    362         if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
    363              profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
    364             // Nothing needs to be done. Call to setCaptureRate() enables
    365             // time lapse video recording.
    366         } else {
    367             setAudioEncodingBitRate(profile.audioBitRate);
    368             setAudioChannels(profile.audioChannels);
    369             setAudioSamplingRate(profile.audioSampleRate);
    370             setAudioEncoder(profile.audioCodec);
    371         }
    372     }
    373 
    374     /**
    375      * Set video frame capture rate. This can be used to set a different video frame capture
    376      * rate than the recorded video's playback rate. This method also sets the recording mode
    377      * to time lapse. In time lapse video recording, only video is recorded. Audio related
    378      * parameters are ignored when a time lapse recording session starts, if an application
    379      * sets them.
    380      *
    381      * @param fps Rate at which frames should be captured in frames per second.
    382      * The fps can go as low as desired. However the fastest fps will be limited by the hardware.
    383      * For resolutions that can be captured by the video camera, the fastest fps can be computed using
    384      * {@link android.hardware.Camera.Parameters#getPreviewFpsRange(int[])}. For higher
    385      * resolutions the fastest fps may be more restrictive.
    386      * Note that the recorder cannot guarantee that frames will be captured at the
    387      * given rate due to camera/encoder limitations. However it tries to be as close as
    388      * possible.
    389      */
    390     public void setCaptureRate(double fps) {
    391         // Make sure that time lapse is enabled when this method is called.
    392         setParameter("time-lapse-enable=1");
    393 
    394         double timeBetweenFrameCapture = 1 / fps;
    395         int timeBetweenFrameCaptureMs = (int) (1000 * timeBetweenFrameCapture);
    396         setParameter("time-between-time-lapse-frame-capture=" + timeBetweenFrameCaptureMs);
    397     }
    398 
    399     /**
    400      * Sets the orientation hint for output video playback.
    401      * This method should be called before prepare(). This method will not
    402      * trigger the source video frame to rotate during video recording, but to
    403      * add a composition matrix containing the rotation angle in the output
    404      * video if the output format is OutputFormat.THREE_GPP or
    405      * OutputFormat.MPEG_4 so that a video player can choose the proper
    406      * orientation for playback. Note that some video players may choose
    407      * to ignore the compostion matrix in a video during playback.
    408      *
    409      * @param degrees the angle to be rotated clockwise in degrees.
    410      * The supported angles are 0, 90, 180, and 270 degrees.
    411      * @throws IllegalArgumentException if the angle is not supported.
    412      *
    413      */
    414     public void setOrientationHint(int degrees) {
    415         if (degrees != 0   &&
    416             degrees != 90  &&
    417             degrees != 180 &&
    418             degrees != 270) {
    419             throw new IllegalArgumentException("Unsupported angle: " + degrees);
    420         }
    421         setParameter("video-param-rotation-angle-degrees=" + degrees);
    422     }
    423 
    424     /**
    425      * Set and store the geodata (latitude and longitude) in the output file.
    426      * This method should be called before prepare(). The geodata is
    427      * stored in udta box if the output format is OutputFormat.THREE_GPP
    428      * or OutputFormat.MPEG_4, and is ignored for other output formats.
    429      * The geodata is stored according to ISO-6709 standard.
    430      *
    431      * @param latitude latitude in degrees. Its value must be in the
    432      * range [-90, 90].
    433      * @param longitude longitude in degrees. Its value must be in the
    434      * range [-180, 180].
    435      *
    436      * @throws IllegalArgumentException if the given latitude or
    437      * longitude is out of range.
    438      *
    439      */
    440     public void setLocation(float latitude, float longitude) {
    441         int latitudex10000  = (int) (latitude * 10000 + 0.5);
    442         int longitudex10000 = (int) (longitude * 10000 + 0.5);
    443 
    444         if (latitudex10000 > 900000 || latitudex10000 < -900000) {
    445             String msg = "Latitude: " + latitude + " out of range.";
    446             throw new IllegalArgumentException(msg);
    447         }
    448         if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
    449             String msg = "Longitude: " + longitude + " out of range";
    450             throw new IllegalArgumentException(msg);
    451         }
    452 
    453         setParameter("param-geotag-latitude=" + latitudex10000);
    454         setParameter("param-geotag-longitude=" + longitudex10000);
    455     }
    456 
    457     /**
    458      * Sets the format of the output file produced during recording. Call this
    459      * after setAudioSource()/setVideoSource() but before prepare().
    460      *
    461      * <p>It is recommended to always use 3GP format when using the H.263
    462      * video encoder and AMR audio encoder. Using an MPEG-4 container format
    463      * may confuse some desktop players.</p>
    464      *
    465      * @param output_format the output format to use. The output format
    466      * needs to be specified before setting recording-parameters or encoders.
    467      * @throws IllegalStateException if it is called after prepare() or before
    468      * setAudioSource()/setVideoSource().
    469      * @see android.media.MediaRecorder.OutputFormat
    470      */
    471     public native void setOutputFormat(int output_format)
    472             throws IllegalStateException;
    473 
    474     /**
    475      * Sets the width and height of the video to be captured.  Must be called
    476      * after setVideoSource(). Call this after setOutFormat() but before
    477      * prepare().
    478      *
    479      * @param width the width of the video to be captured
    480      * @param height the height of the video to be captured
    481      * @throws IllegalStateException if it is called after
    482      * prepare() or before setOutputFormat()
    483      */
    484     public native void setVideoSize(int width, int height)
    485             throws IllegalStateException;
    486 
    487     /**
    488      * Sets the frame rate of the video to be captured.  Must be called
    489      * after setVideoSource(). Call this after setOutFormat() but before
    490      * prepare().
    491      *
    492      * @param rate the number of frames per second of video to capture
    493      * @throws IllegalStateException if it is called after
    494      * prepare() or before setOutputFormat().
    495      *
    496      * NOTE: On some devices that have auto-frame rate, this sets the
    497      * maximum frame rate, not a constant frame rate. Actual frame rate
    498      * will vary according to lighting conditions.
    499      */
    500     public native void setVideoFrameRate(int rate) throws IllegalStateException;
    501 
    502     /**
    503      * Sets the maximum duration (in ms) of the recording session.
    504      * Call this after setOutFormat() but before prepare().
    505      * After recording reaches the specified duration, a notification
    506      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    507      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
    508      * and recording will be stopped. Stopping happens asynchronously, there
    509      * is no guarantee that the recorder will have stopped by the time the
    510      * listener is notified.
    511      *
    512      * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
    513      *
    514      */
    515     public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
    516 
    517     /**
    518      * Sets the maximum filesize (in bytes) of the recording session.
    519      * Call this after setOutFormat() but before prepare().
    520      * After recording reaches the specified filesize, a notification
    521      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    522      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
    523      * and recording will be stopped. Stopping happens asynchronously, there
    524      * is no guarantee that the recorder will have stopped by the time the
    525      * listener is notified.
    526      *
    527      * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
    528      *
    529      */
    530     public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
    531 
    532     /**
    533      * Sets the audio encoder to be used for recording. If this method is not
    534      * called, the output file will not contain an audio track. Call this after
    535      * setOutputFormat() but before prepare().
    536      *
    537      * @param audio_encoder the audio encoder to use.
    538      * @throws IllegalStateException if it is called before
    539      * setOutputFormat() or after prepare().
    540      * @see android.media.MediaRecorder.AudioEncoder
    541      */
    542     public native void setAudioEncoder(int audio_encoder)
    543             throws IllegalStateException;
    544 
    545     /**
    546      * Sets the video encoder to be used for recording. If this method is not
    547      * called, the output file will not contain an video track. Call this after
    548      * setOutputFormat() and before prepare().
    549      *
    550      * @param video_encoder the video encoder to use.
    551      * @throws IllegalStateException if it is called before
    552      * setOutputFormat() or after prepare()
    553      * @see android.media.MediaRecorder.VideoEncoder
    554      */
    555     public native void setVideoEncoder(int video_encoder)
    556             throws IllegalStateException;
    557 
    558     /**
    559      * Sets the audio sampling rate for recording. Call this method before prepare().
    560      * Prepare() may perform additional checks on the parameter to make sure whether
    561      * the specified audio sampling rate is applicable. The sampling rate really depends
    562      * on the format for the audio recording, as well as the capabilities of the platform.
    563      * For instance, the sampling rate supported by AAC audio coding standard ranges
    564      * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
    565      * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
    566      * standard for the supported audio sampling rate.
    567      *
    568      * @param samplingRate the sampling rate for audio in samples per second.
    569      */
    570     public void setAudioSamplingRate(int samplingRate) {
    571         if (samplingRate <= 0) {
    572             throw new IllegalArgumentException("Audio sampling rate is not positive");
    573         }
    574         setParameter("audio-param-sampling-rate=" + samplingRate);
    575     }
    576 
    577     /**
    578      * Sets the number of audio channels for recording. Call this method before prepare().
    579      * Prepare() may perform additional checks on the parameter to make sure whether the
    580      * specified number of audio channels are applicable.
    581      *
    582      * @param numChannels the number of audio channels. Usually it is either 1 (mono) or 2
    583      * (stereo).
    584      */
    585     public void setAudioChannels(int numChannels) {
    586         if (numChannels <= 0) {
    587             throw new IllegalArgumentException("Number of channels is not positive");
    588         }
    589         setParameter("audio-param-number-of-channels=" + numChannels);
    590     }
    591 
    592     /**
    593      * Sets the audio encoding bit rate for recording. Call this method before prepare().
    594      * Prepare() may perform additional checks on the parameter to make sure whether the
    595      * specified bit rate is applicable, and sometimes the passed bitRate will be clipped
    596      * internally to ensure the audio recording can proceed smoothly based on the
    597      * capabilities of the platform.
    598      *
    599      * @param bitRate the audio encoding bit rate in bits per second.
    600      */
    601     public void setAudioEncodingBitRate(int bitRate) {
    602         if (bitRate <= 0) {
    603             throw new IllegalArgumentException("Audio encoding bit rate is not positive");
    604         }
    605         setParameter("audio-param-encoding-bitrate=" + bitRate);
    606     }
    607 
    608     /**
    609      * Sets the video encoding bit rate for recording. Call this method before prepare().
    610      * Prepare() may perform additional checks on the parameter to make sure whether the
    611      * specified bit rate is applicable, and sometimes the passed bitRate will be
    612      * clipped internally to ensure the video recording can proceed smoothly based on
    613      * the capabilities of the platform.
    614      *
    615      * @param bitRate the video encoding bit rate in bits per second.
    616      */
    617     public void setVideoEncodingBitRate(int bitRate) {
    618         if (bitRate <= 0) {
    619             throw new IllegalArgumentException("Video encoding bit rate is not positive");
    620         }
    621         setParameter("video-param-encoding-bitrate=" + bitRate);
    622     }
    623 
    624     /**
    625      * Currently not implemented. It does nothing.
    626      * @deprecated Time lapse mode video recording using camera still image capture
    627      * is not desirable, and will not be supported.
    628      * @hide
    629      */
    630     public void setAuxiliaryOutputFile(FileDescriptor fd)
    631     {
    632         Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
    633     }
    634 
    635     /**
    636      * Currently not implemented. It does nothing.
    637      * @deprecated Time lapse mode video recording using camera still image capture
    638      * is not desirable, and will not be supported.
    639      * @hide
    640      */
    641     public void setAuxiliaryOutputFile(String path)
    642     {
    643         Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
    644     }
    645 
    646     /**
    647      * Pass in the file descriptor of the file to be written. Call this after
    648      * setOutputFormat() but before prepare().
    649      *
    650      * @param fd an open file descriptor to be written into.
    651      * @throws IllegalStateException if it is called before
    652      * setOutputFormat() or after prepare()
    653      */
    654     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
    655     {
    656         mPath = null;
    657         mFd = fd;
    658     }
    659 
    660     /**
    661      * Sets the path of the output file to be produced. Call this after
    662      * setOutputFormat() but before prepare().
    663      *
    664      * @param path The pathname to use.
    665      * @throws IllegalStateException if it is called before
    666      * setOutputFormat() or after prepare()
    667      */
    668     public void setOutputFile(String path) throws IllegalStateException
    669     {
    670         mFd = null;
    671         mPath = path;
    672     }
    673 
    674     // native implementation
    675     private native void _setOutputFile(FileDescriptor fd, long offset, long length)
    676         throws IllegalStateException, IOException;
    677     private native void _prepare() throws IllegalStateException, IOException;
    678 
    679     /**
    680      * Prepares the recorder to begin capturing and encoding data. This method
    681      * must be called after setting up the desired audio and video sources,
    682      * encoders, file format, etc., but before start().
    683      *
    684      * @throws IllegalStateException if it is called after
    685      * start() or before setOutputFormat().
    686      * @throws IOException if prepare fails otherwise.
    687      */
    688     public void prepare() throws IllegalStateException, IOException
    689     {
    690         if (mPath != null) {
    691             FileOutputStream fos = new FileOutputStream(mPath);
    692             try {
    693                 _setOutputFile(fos.getFD(), 0, 0);
    694             } finally {
    695                 fos.close();
    696             }
    697         } else if (mFd != null) {
    698             _setOutputFile(mFd, 0, 0);
    699         } else {
    700             throw new IOException("No valid output file");
    701         }
    702 
    703         _prepare();
    704     }
    705 
    706     /**
    707      * Begins capturing and encoding data to the file specified with
    708      * setOutputFile(). Call this after prepare().
    709      *
    710      * <p>Since API level 13, if applications set a camera via
    711      * {@link #setCamera(Camera)}, the apps can use the camera after this method
    712      * call. The apps do not need to lock the camera again. However, if this
    713      * method fails, the apps should still lock the camera back. The apps should
    714      * not start another recording session during recording.
    715      *
    716      * @throws IllegalStateException if it is called before
    717      * prepare().
    718      */
    719     public native void start() throws IllegalStateException;
    720 
    721     /**
    722      * Stops recording. Call this after start(). Once recording is stopped,
    723      * you will have to configure it again as if it has just been constructed.
    724      * Note that a RuntimeException is intentionally thrown to the
    725      * application, if no valid audio/video data has been received when stop()
    726      * is called. This happens if stop() is called immediately after
    727      * start(). The failure lets the application take action accordingly to
    728      * clean up the output file (delete the output file, for instance), since
    729      * the output file is not properly constructed when this happens.
    730      *
    731      * @throws IllegalStateException if it is called before start()
    732      */
    733     public native void stop() throws IllegalStateException;
    734 
    735     /**
    736      * Restarts the MediaRecorder to its idle state. After calling
    737      * this method, you will have to configure it again as if it had just been
    738      * constructed.
    739      */
    740     public void reset() {
    741         native_reset();
    742 
    743         // make sure none of the listeners get called anymore
    744         mEventHandler.removeCallbacksAndMessages(null);
    745     }
    746 
    747     private native void native_reset();
    748 
    749     /**
    750      * Returns the maximum absolute amplitude that was sampled since the last
    751      * call to this method. Call this only after the setAudioSource().
    752      *
    753      * @return the maximum absolute amplitude measured since the last call, or
    754      * 0 when called for the first time
    755      * @throws IllegalStateException if it is called before
    756      * the audio source has been set.
    757      */
    758     public native int getMaxAmplitude() throws IllegalStateException;
    759 
    760     /* Do not change this value without updating its counterpart
    761      * in include/media/mediarecorder.h or mediaplayer.h!
    762      */
    763     /** Unspecified media recorder error.
    764      * @see android.media.MediaRecorder.OnErrorListener
    765      */
    766     public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
    767     /** Media server died. In this case, the application must release the
    768      * MediaRecorder object and instantiate a new one.
    769      * @see android.media.MediaRecorder.OnErrorListener
    770      */
    771     public static final int MEDIA_ERROR_SERVER_DIED = 100;
    772 
    773     /**
    774      * Interface definition for a callback to be invoked when an error
    775      * occurs while recording.
    776      */
    777     public interface OnErrorListener
    778     {
    779         /**
    780          * Called when an error occurs while recording.
    781          *
    782          * @param mr the MediaRecorder that encountered the error
    783          * @param what    the type of error that has occurred:
    784          * <ul>
    785          * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
    786          * <li>{@link #MEDIA_ERROR_SERVER_DIED}
    787          * </ul>
    788          * @param extra   an extra code, specific to the error type
    789          */
    790         void onError(MediaRecorder mr, int what, int extra);
    791     }
    792 
    793     /**
    794      * Register a callback to be invoked when an error occurs while
    795      * recording.
    796      *
    797      * @param l the callback that will be run
    798      */
    799     public void setOnErrorListener(OnErrorListener l)
    800     {
    801         mOnErrorListener = l;
    802     }
    803 
    804     /* Do not change these values without updating their counterparts
    805      * in include/media/mediarecorder.h!
    806      */
    807     /** Unspecified media recorder error.
    808      * @see android.media.MediaRecorder.OnInfoListener
    809      */
    810     public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
    811     /** A maximum duration had been setup and has now been reached.
    812      * @see android.media.MediaRecorder.OnInfoListener
    813      */
    814     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
    815     /** A maximum filesize had been setup and has now been reached.
    816      * @see android.media.MediaRecorder.OnInfoListener
    817      */
    818     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
    819 
    820     /** informational events for individual tracks, for testing purpose.
    821      * The track informational event usually contains two parts in the ext1
    822      * arg of the onInfo() callback: bit 31-28 contains the track id; and
    823      * the rest of the 28 bits contains the informational event defined here.
    824      * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the
    825      * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE;
    826      * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track
    827      * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The
    828      * application should extract the track id and the type of informational
    829      * event from ext1, accordingly.
    830      *
    831      * FIXME:
    832      * Please update the comment for onInfo also when these
    833      * events are unhidden so that application knows how to extract the track
    834      * id and the informational event type from onInfo callback.
    835      *
    836      * {@hide}
    837      */
    838     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START        = 1000;
    839     /** Signal the completion of the track for the recording session.
    840      * {@hide}
    841      */
    842     public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000;
    843     /** Indicate the recording progress in time (ms) during recording.
    844      * {@hide}
    845      */
    846     public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME  = 1001;
    847     /** Indicate the track type: 0 for Audio and 1 for Video.
    848      * {@hide}
    849      */
    850     public static final int MEDIA_RECORDER_TRACK_INFO_TYPE              = 1002;
    851     /** Provide the track duration information.
    852      * {@hide}
    853      */
    854     public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS       = 1003;
    855     /** Provide the max chunk duration in time (ms) for the given track.
    856      * {@hide}
    857      */
    858     public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS  = 1004;
    859     /** Provide the total number of recordd frames.
    860      * {@hide}
    861      */
    862     public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES    = 1005;
    863     /** Provide the max spacing between neighboring chunks for the given track.
    864      * {@hide}
    865      */
    866     public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS    = 1006;
    867     /** Provide the elapsed time measuring from the start of the recording
    868      * till the first output frame of the given track is received, excluding
    869      * any intentional start time offset of a recording session for the
    870      * purpose of eliminating the recording sound in the recorded file.
    871      * {@hide}
    872      */
    873     public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS  = 1007;
    874     /** Provide the start time difference (delay) betweeen this track and
    875      * the start of the movie.
    876      * {@hide}
    877      */
    878     public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS   = 1008;
    879     /** Provide the total number of data (in kilo-bytes) encoded.
    880      * {@hide}
    881      */
    882     public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES       = 1009;
    883     /**
    884      * {@hide}
    885      */
    886     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END          = 2000;
    887 
    888 
    889     /**
    890      * Interface definition for a callback to be invoked when an error
    891      * occurs while recording.
    892      */
    893     public interface OnInfoListener
    894     {
    895         /**
    896          * Called when an error occurs while recording.
    897          *
    898          * @param mr the MediaRecorder that encountered the error
    899          * @param what    the type of error that has occurred:
    900          * <ul>
    901          * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
    902          * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
    903          * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
    904          * </ul>
    905          * @param extra   an extra code, specific to the error type
    906          */
    907         void onInfo(MediaRecorder mr, int what, int extra);
    908     }
    909 
    910     /**
    911      * Register a callback to be invoked when an informational event occurs while
    912      * recording.
    913      *
    914      * @param listener the callback that will be run
    915      */
    916     public void setOnInfoListener(OnInfoListener listener)
    917     {
    918         mOnInfoListener = listener;
    919     }
    920 
    921     private class EventHandler extends Handler
    922     {
    923         private MediaRecorder mMediaRecorder;
    924 
    925         public EventHandler(MediaRecorder mr, Looper looper) {
    926             super(looper);
    927             mMediaRecorder = mr;
    928         }
    929 
    930         /* Do not change these values without updating their counterparts
    931          * in include/media/mediarecorder.h!
    932          */
    933         private static final int MEDIA_RECORDER_EVENT_LIST_START = 1;
    934         private static final int MEDIA_RECORDER_EVENT_ERROR      = 1;
    935         private static final int MEDIA_RECORDER_EVENT_INFO       = 2;
    936         private static final int MEDIA_RECORDER_EVENT_LIST_END   = 99;
    937 
    938         /* Events related to individual tracks */
    939         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100;
    940         private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR      = 100;
    941         private static final int MEDIA_RECORDER_TRACK_EVENT_INFO       = 101;
    942         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END   = 1000;
    943 
    944 
    945         @Override
    946         public void handleMessage(Message msg) {
    947             if (mMediaRecorder.mNativeContext == 0) {
    948                 Log.w(TAG, "mediarecorder went away with unhandled events");
    949                 return;
    950             }
    951             switch(msg.what) {
    952             case MEDIA_RECORDER_EVENT_ERROR:
    953             case MEDIA_RECORDER_TRACK_EVENT_ERROR:
    954                 if (mOnErrorListener != null)
    955                     mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
    956 
    957                 return;
    958 
    959             case MEDIA_RECORDER_EVENT_INFO:
    960             case MEDIA_RECORDER_TRACK_EVENT_INFO:
    961                 if (mOnInfoListener != null)
    962                     mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
    963 
    964                 return;
    965 
    966             default:
    967                 Log.e(TAG, "Unknown message type " + msg.what);
    968                 return;
    969             }
    970         }
    971     }
    972 
    973     /**
    974      * Called from native code when an interesting event happens.  This method
    975      * just uses the EventHandler system to post the event back to the main app thread.
    976      * We use a weak reference to the original MediaRecorder object so that the native
    977      * code is safe from the object disappearing from underneath it.  (This is
    978      * the cookie passed to native_setup().)
    979      */
    980     private static void postEventFromNative(Object mediarecorder_ref,
    981                                             int what, int arg1, int arg2, Object obj)
    982     {
    983         MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
    984         if (mr == null) {
    985             return;
    986         }
    987 
    988         if (mr.mEventHandler != null) {
    989             Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
    990             mr.mEventHandler.sendMessage(m);
    991         }
    992     }
    993 
    994     /**
    995      * Releases resources associated with this MediaRecorder object.
    996      * It is good practice to call this method when you're done
    997      * using the MediaRecorder. In particular, whenever an Activity
    998      * of an application is paused (its onPause() method is called),
    999      * or stopped (its onStop() method is called), this method should be
   1000      * invoked to release the MediaRecorder object, unless the application
   1001      * has a special need to keep the object around. In addition to
   1002      * unnecessary resources (such as memory and instances of codecs)
   1003      * being held, failure to call this method immediately if a
   1004      * MediaRecorder object is no longer needed may also lead to
   1005      * continuous battery consumption for mobile devices, and recording
   1006      * failure for other applications if no multiple instances of the
   1007      * same codec are supported on a device. Even if multiple instances
   1008      * of the same codec are supported, some performance degradation
   1009      * may be expected when unnecessary multiple instances are used
   1010      * at the same time.
   1011      */
   1012     public native void release();
   1013 
   1014     private static native final void native_init();
   1015 
   1016     private native final void native_setup(Object mediarecorder_this,
   1017             String clientName) throws IllegalStateException;
   1018 
   1019     private native final void native_finalize();
   1020 
   1021     private native void setParameter(String nameValuePair);
   1022 
   1023     @Override
   1024     protected void finalize() { native_finalize(); }
   1025 }
   1026