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