diff options
Diffstat (limited to 'media/java/android')
-rw-r--r-- | media/java/android/media/AudioManager.java | 7 | ||||
-rw-r--r-- | media/java/android/media/AudioRecord.java | 3 | ||||
-rw-r--r-- | media/java/android/media/AudioService.java | 3 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 3 | ||||
-rw-r--r-- | media/java/android/media/MediaMetadataRetriever.java | 252 | ||||
-rw-r--r-- | media/java/android/media/MediaRecorder.java | 30 | ||||
-rw-r--r-- | media/java/android/media/MediaScanner.java | 5 | ||||
-rw-r--r-- | media/java/android/media/ThumbnailUtils.java | 7 | ||||
-rwxr-xr-x | media/java/android/media/audiofx/Visualizer.java | 46 |
9 files changed, 275 insertions, 81 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index bbbba74..4459505 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -966,9 +966,14 @@ public class AudioManager { */ public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE; /** - * In call audio mode. A call is established. + * In call audio mode. A telephony call is established. */ public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL; + /** + * @hide + * In communication audio mode. An audio/video chat or VoIP call is established. + */ + public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; /* Routing bits for setRouting/getRouting API */ /** diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index c48eaad..0eb39db 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -252,7 +252,8 @@ public class AudioRecord //-------------- // audio source if ( (audioSource < MediaRecorder.AudioSource.DEFAULT) || - (audioSource > MediaRecorder.getAudioSourceMax()) ) { + (audioSource > MediaRecorder.AudioSource.VOICE_COMMUNICATION) ) { + //(audioSource > MediaRecorder.getAudioSourceMax()) ) { throw (new IllegalArgumentException("Invalid audio source.")); } else { mRecordSource = audioSource; diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 41d2cc5..06e00c5 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -708,7 +708,7 @@ public class AudioService extends IAudioService.Stub { return; } - if (mode < AudioSystem.MODE_CURRENT || mode > AudioSystem.MODE_IN_CALL) { + if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { return; } @@ -2259,6 +2259,7 @@ public class AudioService extends IAudioService.Stub { // add modify the phone app to take advantage of the new API synchronized(mRingingLock) { if (mIsRinging || (getMode() == AudioSystem.MODE_IN_CALL) || + (getMode() == AudioSystem.MODE_IN_COMMUNICATION) || (getMode() == AudioSystem.MODE_RINGTONE) ) { return; } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index a4818ff..4ddbb35 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -106,7 +106,8 @@ public class AudioSystem public static final int MODE_NORMAL = 0; public static final int MODE_RINGTONE = 1; public static final int MODE_IN_CALL = 2; - public static final int NUM_MODES = 3; + public static final int MODE_IN_COMMUNICATION = 3; + public static final int NUM_MODES = 4; /* Routing bits for setRouting/getRouting API */ diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 681751b..77e939e 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -29,7 +29,6 @@ import java.io.IOException; /** * MediaMetadataRetriever class provides a unified interface for retrieving * frame and meta data from an input media file. - * {@hide} */ public class MediaMetadataRetriever { @@ -42,41 +41,13 @@ public class MediaMetadataRetriever @SuppressWarnings("unused") private int mNativeContext; + private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF; + public MediaMetadataRetriever() { native_setup(); } /** - * Call this method before setDataSource() so that the mode becomes - * effective for subsequent operations. This method can be called only once - * at the beginning if the intended mode of operation for a - * MediaMetadataRetriever object remains the same for its whole lifetime, - * and thus it is unnecessary to call this method each time setDataSource() - * is called. If this is not never called (which is allowed), by default the - * intended mode of operation is to both capture frame and retrieve meta - * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). - * Often, this may not be what one wants, since doing this has negative - * performance impact on execution time of a call to setDataSource(), since - * both types of operations may be time consuming. - * - * @param mode The intended mode of operation. Can be any combination of - * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: - * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: - * For neither frame capture nor meta data retrieval - * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only - * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only - * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: - * For both frame capture and meta data retrieval - */ - public native void setMode(int mode); - - /** - * @return the current mode of operation. A negative return value indicates - * some runtime error has occurred. - */ - public native int getMode(); - - /** * Sets the data source (file pathname) to use. Call this * method before the rest of the methods in this class. This method may be * time-consuming. @@ -190,22 +161,99 @@ public class MediaMetadataRetriever /** * Call this method after setDataSource(). This method finds a - * representative frame if successful and returns it as a bitmap. This is - * useful for generating a thumbnail for an input media source. - * + * representative frame close to the given time position by considering + * the given option if possible, and returns it as a bitmap. This is + * useful for generating a thumbnail for an input data source or just + * obtain and display a frame at the given time position. + * + * @param timeUs The time position where the frame will be retrieved. + * When retrieving the frame at the given time position, there is no + * guarantee that the data source has a frame located at the position. + * When this happens, a frame nearby will be returned. If timeUs is + * negative, time position and option will ignored, and any frame + * that the implementation considers as representative may be returned. + * + * @param option a hint on how the frame is found. Use + * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame + * that has a timestamp earlier than or the same as timeUs. Use + * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame + * that has a timestamp later than or the same as timeUs. Use + * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame + * that has a timestamp closest to or the same as timeUs. Use + * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may + * or may not be a sync frame but is closest to or the same as timeUs. + * {@link #OPTION_CLOSEST} often has larger performance overhead compared + * to the other options if there is no sync frame located at timeUs. + * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. */ - public native Bitmap captureFrame(); + public Bitmap getFrameAtTime(long timeUs, int option) { + if (option < OPTION_PREVIOUS_SYNC || + option > OPTION_CLOSEST) { + throw new IllegalArgumentException("Unsupported option: " + option); + } + + return _getFrameAtTime(timeUs, option); + } + + /** + * Call this method after setDataSource(). This method finds a + * representative frame close to the given time position if possible, + * and returns it as a bitmap. This is useful for generating a thumbnail + * for an input data source. Call this method if one does not care + * how the frame is found as long as it is close to the given time; + * otherwise, please call {@link #getFrameAtTime(long, int)}. + * + * @param timeUs The time position where the frame will be retrieved. + * When retrieving the frame at the given time position, there is no + * guarentee that the data source has a frame located at the position. + * When this happens, a frame nearby will be returned. If timeUs is + * negative, time position and option will ignored, and any frame + * that the implementation considers as representative may be returned. + * + * @return A Bitmap containing a representative video frame, which + * can be null, if such a frame cannot be retrieved. + * + * @see #getFrameAtTime(long, int) + */ + public Bitmap getFrameAtTime(long timeUs) { + return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC); + } + + /** + * Call this method after setDataSource(). This method finds a + * representative frame at any time position if possible, + * and returns it as a bitmap. This is useful for generating a thumbnail + * for an input data source. Call this method if one does not + * care about where the frame is located; otherwise, please call + * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)} + * + * @return A Bitmap containing a representative video frame, which + * can be null, if such a frame cannot be retrieved. + * + * @see #getFrameAtTime(long) + * @see #getFrameAtTime(long, int) + */ + public Bitmap getFrameAtTime() { + return getFrameAtTime(-1, OPTION_CLOSEST_SYNC); + } + + private native Bitmap _getFrameAtTime(long timeUs, int option); + /** * Call this method after setDataSource(). This method finds the optional - * graphic or album art associated (embedded or external url linked) the - * related data source. + * graphic or album art associated associated with the data source. If + * there are more than one pictures, (any) one of them is returned. * * @return null if no such graphic is found. */ - public native byte[] extractAlbumArt(); + public byte[] getEmbeddedPicture() { + return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY); + } + + private native byte[] getEmbeddedPicture(int pictureType); /** * Call it when one is done with the object. This method releases the memory @@ -226,37 +274,129 @@ public class MediaMetadataRetriever } } - public static final int MODE_GET_METADATA_ONLY = 0x01; - public static final int MODE_CAPTURE_FRAME_ONLY = 0x02; + /** + * Option used in method {@link #getFrameAtTime(long, int)} to get a + * frame at a specified location. + * + * @see #getFrameAtTime(long, int) + */ + /* Do not change these option values without updating their counterparts + * in include/media/stagefright/MediaSource.h! + */ + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * right before or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_PREVIOUS_SYNC = 0x00; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * right after or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_NEXT_SYNC = 0x01; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a sync (or key) frame associated with a data source that is located + * closest to (in time) or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_CLOSEST_SYNC = 0x02; + /** + * This option is used with {@link #getFrameAtTime(long, int)} to retrieve + * a frame (not necessarily a key frame) associated with a data source that + * is located closest to or at the given time. + * + * @see #getFrameAtTime(long, int) + */ + public static final int OPTION_CLOSEST = 0x03; /* - * Do not change these values without updating their counterparts - * in include/media/mediametadataretriever.h! + * Do not change these metadata key values without updating their + * counterparts in include/media/mediametadataretriever.h! + */ + /** + * The metadata key to retrieve the numberic string describing the + * order of the audio data source on its original recording. */ public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; + /** + * The metadata key to retrieve the information about the album title + * of the data source. + */ public static final int METADATA_KEY_ALBUM = 1; + /** + * The metadata key to retrieve the information about the artist of + * the data source. + */ public static final int METADATA_KEY_ARTIST = 2; + /** + * The metadata key to retrieve the information about the author of + * the data source. + */ public static final int METADATA_KEY_AUTHOR = 3; + /** + * The metadata key to retrieve the information about the composer of + * the data source. + */ public static final int METADATA_KEY_COMPOSER = 4; + /** + * The metadata key to retrieve the date when the data source was created + * or modified. + */ public static final int METADATA_KEY_DATE = 5; + /** + * The metadata key to retrieve the content type or genre of the data + * source. + */ public static final int METADATA_KEY_GENRE = 6; + /** + * The metadata key to retrieve the data source title. + */ public static final int METADATA_KEY_TITLE = 7; + /** + * The metadata key to retrieve the year when the data source was created + * or modified. + */ public static final int METADATA_KEY_YEAR = 8; + /** + * The metadata key to retrieve the playback duration of the data source. + */ public static final int METADATA_KEY_DURATION = 9; + /** + * The metadata key to retrieve the number of tracks, such as audio, video, + * text, in the data source, such as a mp4 or 3gpp file. + */ public static final int METADATA_KEY_NUM_TRACKS = 10; - public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11; - public static final int METADATA_KEY_CODEC = 12; - public static final int METADATA_KEY_RATING = 13; - public static final int METADATA_KEY_COMMENT = 14; - public static final int METADATA_KEY_COPYRIGHT = 15; - public static final int METADATA_KEY_BIT_RATE = 16; - public static final int METADATA_KEY_FRAME_RATE = 17; - public static final int METADATA_KEY_VIDEO_FORMAT = 18; - public static final int METADATA_KEY_VIDEO_HEIGHT = 19; - public static final int METADATA_KEY_VIDEO_WIDTH = 20; - public static final int METADATA_KEY_WRITER = 21; - public static final int METADATA_KEY_MIMETYPE = 22; - public static final int METADATA_KEY_DISCNUMBER = 23; - public static final int METADATA_KEY_ALBUMARTIST = 24; + /** + * The metadata key to retrieve the information of the writer (such as + * lyricist) of the data source. + */ + public static final int METADATA_KEY_WRITER = 11; + /** + * The metadata key to retrieve the mime type of the data source. Some + * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", + * etc. + */ + public static final int METADATA_KEY_MIMETYPE = 12; + /** + * The metadata key to retrieve the information about the performers or + * artist associated with the data source. + */ + public static final int METADATA_KEY_ALBUMARTIST = 13; + /** + * The metadata key to retrieve the numberic string that describes which + * part of a set the audio data source comes from. + */ + public static final int METADATA_KEY_DISC_NUMBER = 14; + /** + * The metadata key to retrieve the music album compilation status. + */ + public static final int METADATA_KEY_COMPILATION = 15; // Add more here... } diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index ecabae8..4e87c73 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -145,6 +145,15 @@ public class MediaRecorder /** Microphone audio source tuned for voice recognition if available, behaves like * {@link #DEFAULT} otherwise. */ public static final int VOICE_RECOGNITION = 6; + + /** + * @hide + * Microphone audio source tuned for voice communications such as VoIP. It + * will for instance take advantage of echo cancellation or automatic gain control + * if available. It otherwise behaves like {@link #DEFAULT} if no voice processing + * is available. + */ + public static final int VOICE_COMMUNICATION = 7; } /** @@ -178,11 +187,12 @@ public class MediaRecorder /** The following formats are audio only .aac or .amr formats **/ /** @deprecated Deprecated in favor of AMR_NB */ - /** TODO: change link when AMR_NB is exposed. Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */ + /** Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */ + /** AMR NB file format */ public static final int RAW_AMR = 3; - /** @hide AMR NB file format */ + /** AMR NB file format */ public static final int AMR_NB = 3; - /** @hide AMR WB file format */ + /** AMR WB file format */ public static final int AMR_WB = 4; /** @hide AAC ADIF file format */ public static final int AAC_ADIF = 5; @@ -208,9 +218,9 @@ public class MediaRecorder public static final int DEFAULT = 0; /** AMR (Narrowband) audio codec */ public static final int AMR_NB = 1; - /** @hide AMR (Wideband) audio codec */ + /** AMR (Wideband) audio codec */ public static final int AMR_WB = 2; - /** @hide AAC audio codec */ + /** AAC audio codec */ public static final int AAC = 3; /** @hide enhanced AAC audio codec */ public static final int AAC_PLUS = 4; @@ -306,7 +316,7 @@ public class MediaRecorder degrees != 270) { throw new IllegalArgumentException("Unsupported angle: " + degrees); } - setParameter(String.format("video-param-rotation-angle-degrees=%d", degrees)); + setParameter("video-param-rotation-angle-degrees=" + degrees); } /** @@ -425,7 +435,7 @@ public class MediaRecorder if (samplingRate <= 0) { throw new IllegalArgumentException("Audio sampling rate is not positive"); } - setParameter(String.format("audio-param-sampling-rate=%d", samplingRate)); + setParameter("audio-param-sampling-rate=" + samplingRate); } /** @@ -440,7 +450,7 @@ public class MediaRecorder if (numChannels <= 0) { throw new IllegalArgumentException("Number of channels is not positive"); } - setParameter(String.format("audio-param-number-of-channels=%d", numChannels)); + setParameter("audio-param-number-of-channels=" + numChannels); } /** @@ -456,7 +466,7 @@ public class MediaRecorder if (bitRate <= 0) { throw new IllegalArgumentException("Audio encoding bit rate is not positive"); } - setParameter(String.format("audio-param-encoding-bitrate=%d", bitRate)); + setParameter("audio-param-encoding-bitrate=" + bitRate); } /** @@ -472,7 +482,7 @@ public class MediaRecorder if (bitRate <= 0) { throw new IllegalArgumentException("Video encoding bit rate is not positive"); } - setParameter(String.format("video-param-encoding-bitrate=%d", bitRate)); + setParameter("video-param-encoding-bitrate=" + bitRate); } /** diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 3333268..ab2c6ea 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -402,6 +402,7 @@ public class MediaScanner private long mLastModified; private long mFileSize; private String mWriter; + private int mCompilation; public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) { @@ -486,6 +487,7 @@ public class MediaScanner mPath = path; mLastModified = lastModified; mWriter = null; + mCompilation = 0; return entry; } @@ -596,6 +598,8 @@ public class MediaScanner mDuration = parseSubstring(value, 0, 0); } else if (name.equalsIgnoreCase("writer") || name.startsWith("writer;")) { mWriter = value.trim(); + } else if (name.equalsIgnoreCase("compilation")) { + mCompilation = parseSubstring(value, 0, 0); } } @@ -646,6 +650,7 @@ public class MediaScanner } map.put(Audio.Media.TRACK, mTrack); map.put(Audio.Media.DURATION, mDuration); + map.put(Audio.Media.COMPILATION, mCompilation); } return map; } diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java index 3d85e31..b276e33 100644 --- a/media/java/android/media/ThumbnailUtils.java +++ b/media/java/android/media/ThumbnailUtils.java @@ -83,7 +83,7 @@ public class ThumbnailUtils { * * @param filePath the path of image file * @param kind could be MINI_KIND or MICRO_KIND - * @return Bitmap + * @return Bitmap, or null on failures * * @hide This method is only used by media framework and media provider internally. */ @@ -123,6 +123,8 @@ public class ThumbnailUtils { bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options); } catch (IOException ex) { Log.e(TAG, "", ex); + } catch (OutOfMemoryError oom) { + Log.e(TAG, "Unable to decode file " + filePath + ". OutOfMemoryError.", oom); } } @@ -146,9 +148,8 @@ public class ThumbnailUtils { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { - retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); retriever.setDataSource(filePath); - bitmap = retriever.captureFrame(); + bitmap = retriever.getFrameAtTime(-1); } catch (IllegalArgumentException ex) { // Assume this is a corrupt video file } catch (RuntimeException ex) { diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java index 0c48556..41309dc 100755 --- a/media/java/android/media/audiofx/Visualizer.java +++ b/media/java/android/media/audiofx/Visualizer.java @@ -43,10 +43,8 @@ import android.os.Message; * <li>Frequency data: 8-bit magnitude FFT by using the {@link #getFft(byte[])} method</li> * </ul> * <p>The length of the capture can be retrieved or specified by calling respectively - * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. Note that the size of the FFT - * is half of the specified capture size but both sides of the spectrum are returned yielding in a - * number of bytes equal to the capture size. The capture size must be a power of 2 in the range - * returned by {@link #getCaptureSizeRange()}. + * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. The capture size must be a + * power of 2 in the range returned by {@link #getCaptureSizeRange()}. * <p>In addition to the polling capture mode described above with {@link #getWaveForm(byte[])} and * {@link #getFft(byte[])} methods, a callback mode is also available by installing a listener by * use of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method. @@ -333,11 +331,43 @@ public class Visualizer { } } /** - * Returns a frequency capture of currently playing audio content. The capture is a 8-bit - * magnitude FFT. Note that the size of the FFT is half of the specified capture size but both - * sides of the spectrum are returned yielding in a number of bytes equal to the capture size. - * {@see #getCaptureSize()}. + * Returns a frequency capture of currently playing audio content. * <p>This method must be called when the Visualizer is enabled. + * <p>The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of + * the sampling rate returned by {@link #getSamplingRate()}. The capture returns the real and + * imaginary parts of a number of frequency points equal to half of the capture size plus one. + * <p>Note: only the real part is returned for the first point (DC) and the last point + * (sampling frequency / 2). + * <p>The layout in the returned byte array is as follows: + * <ul> + * <li> n is the capture size returned by getCaptureSize()</li> + * <li> Rfk, Ifk are respectively the real and imaginary parts of the kth frequency + * component</li> + * <li> If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is: + * (k*Fs)/(n/2) </li> + * </ul> + * <table border="0" cellspacing="0" cellpadding="0"> + * <tr><td>Index </p></td> + * <td>0 </p></td> + * <td>1 </p></td> + * <td>2 </p></td> + * <td>3 </p></td> + * <td>4 </p></td> + * <td>5 </p></td> + * <td>... </p></td> + * <td>n - 2 </p></td> + * <td>n - 1 </p></td></tr> + * <tr><td>Data </p></td> + * <td>Rf0 </p></td> + * <td>Rf(n/2) </p></td> + * <td>Rf1 </p></td> + * <td>If1 </p></td> + * <td>Rf2 </p></td> + * <td>If2 </p></td> + * <td>... </p></td> + * <td>Rf(n-1)/2 </p></td> + * <td>If(n-1)/2 </p></td></tr> + * </table> * @param fft array of bytes where the FFT should be returned * @return {@link #SUCCESS} in case of success, * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} |