Loading include/media/mediaplayer.h +20 −3 Original line number Diff line number Diff line Loading @@ -120,6 +120,9 @@ enum media_info_type { MEDIA_INFO_NOT_SEEKABLE = 801, // New media metadata is available. MEDIA_INFO_METADATA_UPDATE = 802, //9xx MEDIA_INFO_TIMED_TEXT_ERROR = 900, }; Loading @@ -140,9 +143,6 @@ enum media_player_states { // The same enum space is used for both set and get, in case there are future keys that // can be both set and get. But as of now, all parameters are either set only or get only. enum media_parameter_keys { KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000, // set only KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001, // set only // Streaming/buffering parameters KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only Loading @@ -155,6 +155,23 @@ enum media_parameter_keys { KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300, // set only }; // Keep INVOKE_ID_* in sync with MediaPlayer.java. enum media_player_invoke_ids { INVOKE_ID_GET_TRACK_INFO = 1, INVOKE_ID_ADD_EXTERNAL_SOURCE = 2, INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3, INVOKE_ID_SELECT_TRACK = 4, INVOKE_ID_UNSELECT_TRACK = 5, }; // Keep MEDIA_TRACK_TYPE_* in sync with MediaPlayer.java. enum media_track_type { MEDIA_TRACK_TYPE_UNKNOWN = 0, MEDIA_TRACK_TYPE_VIDEO = 1, MEDIA_TRACK_TYPE_AUDIO = 2, MEDIA_TRACK_TYPE_TIMEDTEXT = 3, }; // ---------------------------------------------------------------------------- // ref-counted object for callbacks class MediaPlayerListener: virtual public RefBase Loading include/media/stagefright/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS; extern const char *MEDIA_MIMETYPE_CONTAINER_WVM; extern const char *MEDIA_MIMETYPE_TEXT_3GPP; extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP; } // namespace android Loading include/media/stagefright/timedtext/TimedTextDriver.h +10 −10 Original line number Diff line number Diff line Loading @@ -37,26 +37,26 @@ public: ~TimedTextDriver(); // TODO: pause-resume pair seems equivalent to stop-start pair. // Check if it is replaceable with stop-start. status_t start(); status_t stop(); status_t pause(); status_t resume(); status_t selectTrack(int32_t index); status_t unselectTrack(int32_t index); status_t seekToAsync(int64_t timeUs); status_t addInBandTextSource(const sp<MediaSource>& source); status_t addOutOfBandTextSource(const Parcel &request); status_t addOutOfBandTextSource(const char *uri, const char *mimeType); // Caller owns the file desriptor and caller is responsible for closing it. status_t addOutOfBandTextSource( int fd, off64_t offset, size_t length, const char *mimeType); status_t setTimedTextTrackIndex(int32_t index); void getTrackInfo(Parcel *parcel); private: Mutex mLock; enum State { UNINITIALIZED, STOPPED, PLAYING, PAUSED, }; Loading @@ -67,11 +67,11 @@ private: // Variables to be guarded by mLock. State mState; Vector<sp<TimedTextSource> > mTextInBandVector; Vector<sp<TimedTextSource> > mTextOutOfBandVector; int32_t mCurrentTrackIndex; Vector<sp<TimedTextSource> > mTextSourceVector; // -- End of variables to be guarded by mLock status_t setTimedTextTrackIndex_l(int32_t index); status_t selectTrack_l(int32_t index); DISALLOW_EVIL_CONSTRUCTORS(TimedTextDriver); }; Loading media/java/android/media/MediaPlayer.java +316 −44 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.util.Log; Loading Loading @@ -455,6 +456,22 @@ import java.lang.ref.WeakReference; * <td>Successful invoke of this method in a valid state transfers the * object to the <em>Stopped</em> state. Calling this method in an * invalid state transfers the object to the <em>Error</em> state.</p></td></tr> * <tr><td>getTrackInfo </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>addExternalSource </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>selectTrack </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>disableTrack </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * * </table> * Loading Loading @@ -572,6 +589,15 @@ public class MediaPlayer */ private native void _setVideoSurface(Surface surface); /* Do not change these values (starting with INVOKE_ID) without updating * their counterparts in include/media/mediaplayer.h! */ private static final int INVOKE_ID_GET_TRACK_INFO = 1; private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE = 2; private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3; private static final int INVOKE_ID_SELECT_TRACK = 4; private static final int INVOKE_ID_UNSELECT_TRACK = 5; /** * Create a request parcel which can be routed to the native media * player using {@link #invoke(Parcel, Parcel)}. The Parcel Loading Loading @@ -1312,23 +1338,6 @@ public class MediaPlayer /* Do not change these values (starting with KEY_PARAMETER) without updating * their counterparts in include/media/mediaplayer.h! */ /* * Key used in setParameter method. * Indicates the index of the timed text track to be enabled/disabled. * The index includes both the in-band and out-of-band timed text. * The index should start from in-band text if any. Application can retrieve the number * of in-band text tracks by using MediaMetadataRetriever::extractMetadata(). * Note it might take a few hundred ms to scan an out-of-band text file * before displaying it. */ private static final int KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000; /* * Key used in setParameter method. * Used to add out-of-band timed text source path. * Application can add multiple text sources by calling setParameter() with * KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE multiple times. */ private static final int KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001; // There are currently no defined keys usable from Java with get*Parameter. // But if any keys are defined, the order must be kept in sync with include/media/mediaplayer.h. Loading Loading @@ -1373,7 +1382,7 @@ public class MediaPlayer return ret; } /** /* * Gets the value of the parameter indicated by key. * @param key key indicates the parameter to get. * @param reply value of the parameter to get. Loading Loading @@ -1435,7 +1444,7 @@ public class MediaPlayer */ public native void setAuxEffectSendLevel(float level); /** /* * @param request Parcel destinated to the media player. The * Interface token must be set to the IMediaPlayer * one to be routed correctly through the system. Loading @@ -1445,7 +1454,7 @@ public class MediaPlayer private native final int native_invoke(Parcel request, Parcel reply); /** /* * @param update_only If true fetch only the set of metadata that have * changed since the last invocation of getMetadata. * The set is built using the unfiltered Loading @@ -1462,7 +1471,7 @@ public class MediaPlayer boolean apply_filter, Parcel reply); /** /* * @param request Parcel with the 2 serialized lists of allowed * metadata types followed by the one to be * dropped. Each list starts with an integer Loading @@ -1476,33 +1485,289 @@ public class MediaPlayer private native final void native_finalize(); /** * @param index The index of the text track to be turned on. * @return true if the text track is enabled successfully. * Class for MediaPlayer to return each audio/video/subtitle track's metadata. * * {@see #getTrackInfo()}. * {@hide} */ static public class TrackInfo implements Parcelable { /** * Gets the track type. * @return TrackType which indicates if the track is video, audio, timed text. */ public int getTrackType() { return mTrackType; } /** * Gets the language code of the track. * @return a language code in either way of ISO-639-1 or ISO-639-2. * When the language is unknown or could not be determined, * ISO-639-2 language code, "und", is returned. */ public String getLanguage() { return mLanguage; } public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; public static final int MEDIA_TRACK_TYPE_VIDEO = 1; public static final int MEDIA_TRACK_TYPE_AUDIO = 2; public static final int MEDIA_TRACK_TYPE_TIMEDTEXT = 3; final int mTrackType; final String mLanguage; TrackInfo(Parcel in) { mTrackType = in.readInt(); mLanguage = in.readString(); } /* * No special parcel contents. Keep it as hide. * {@hide} */ @Override public int describeContents() { return 0; } /* * {@hide} */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mTrackType); dest.writeString(mLanguage); } /** * Used to read a TrackInfo from a Parcel. */ static final Parcelable.Creator<TrackInfo> CREATOR = new Parcelable.Creator<TrackInfo>() { @Override public TrackInfo createFromParcel(Parcel in) { return new TrackInfo(in); } @Override public TrackInfo[] newArray(int size) { return new TrackInfo[size]; } }; }; /** * Returns an array of track information. * * @return Array of track info. null if an error occured. * {@hide} */ public boolean enableTimedTextTrackIndex(int index) { if (index < 0) { // FIXME: It returns timed text tracks' information for now. Other types of tracks will be // supported in future. public TrackInfo[] getTrackInfo() { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_GET_TRACK_INFO); invoke(request, reply); TrackInfo trackInfo[] = reply.createTypedArray(TrackInfo.CREATOR); return trackInfo; } /* * A helper function to check if the mime type is supported by media framework. */ private boolean availableMimeTypeForExternalSource(String mimeType) { if (mimeType == MEDIA_MIMETYPE_TEXT_SUBRIP) { return true; } return false; } return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, index); /* TODO: Limit the total number of external timed text source to a reasonable number. */ /** * Adds an external source file. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param path The file path of external source file. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(String path, String mimeType) throws IllegalArgumentException { if (!availableMimeTypeForExternalSource(mimeType)) { throw new IllegalArgumentException("Illegal mimeType for external source: " + mimeType); } Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_ADD_EXTERNAL_SOURCE); request.writeString(path); request.writeString(mimeType); invoke(request, reply); } /** * Enables the first timed text track if any. * @return true if the text track is enabled successfully * Adds an external source file (Uri). * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * {@hide} */ public boolean enableTimedText() { return enableTimedTextTrackIndex(0); // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(Context context, Uri uri, String mimeType) throws IOException, IllegalArgumentException { String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { addExternalSource(uri.getPath(), mimeType); return; } AssetFileDescriptor fd = null; try { ContentResolver resolver = context.getContentResolver(); fd = resolver.openAssetFileDescriptor(uri, "r"); if (fd == null) { return; } addExternalSource(fd.getFileDescriptor(), mimeType); return; } catch (SecurityException ex) { } catch (IOException ex) { } finally { if (fd != null) { fd.close(); } } // TODO: try server side. } /* Do not change these values without updating their counterparts * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp! */ /** * Disables timed text display. * @return true if the text track is disabled successfully. * MIME type for SubRip (SRT) container. Used in {@link #addExternalSource()} APIs. * {@hide} */ public boolean disableTimedText() { return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, -1); public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip"; /** * Adds an external source file (FileDescriptor). * It is the caller's responsibility to close the file descriptor. * It is safe to do so as soon as this call returns. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param fd the FileDescriptor for the file you want to play * @param mimeType A MIME type for the content. It can be null. * <ul> * <li>{@link #MEDIA_MIMETYPE_TEXT_SUBRIP} * </ul> * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(FileDescriptor fd, String mimeType) throws IllegalArgumentException { // intentionally less than LONG_MAX addExternalSource(fd, 0, 0x7ffffffffffffffL, mimeType); } /** * Adds an external timed text file (FileDescriptor). * It is the caller's responsibility to close the file descriptor. * It is safe to do so as soon as this call returns. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param fd the FileDescriptor for the file you want to play * @param offset the offset into the file where the data to be played starts, in bytes * @param length the length in bytes of the data to be played * @param mimeType A MIME type for the content. It can be null. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(FileDescriptor fd, long offset, long length, String mimeType) throws IllegalArgumentException { if (!availableMimeTypeForExternalSource(mimeType)) { throw new IllegalArgumentException("Illegal mimeType for external source: " + mimeType); } Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_ADD_EXTERNAL_SOURCE_FD); request.writeFileDescriptor(fd); request.writeLong(offset); request.writeLong(length); request.writeString(mimeType); invoke(request, reply); } /** * Selects a track. * <p> * If a MediaPlayer is in invalid state, it throws exception. * If a MediaPlayer is in Started state, the selected track will be presented immediately. * If a MediaPlayer is not in Started state, it just marks the track to be played. * </p> * <p> * In any valid state, if it is called multiple times on the same type of track (ie. Video, * Audio, Timed Text), the most recent one will be chosen. * </p> * <p> * The first audio and video tracks will be selected by default, even though this function is not * called. However, no timed text track will be selected until this function is called. * </p> * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException, IllegalArgumentException). public void selectTrack(int index) { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_SELECT_TRACK); request.writeInt(index); invoke(request, reply); } /** * Unselect a track. * If the track identified by index has not been selected before, it throws an exception. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException, IllegalArgumentException). public void unselectTrack(int index) { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_UNSELECT_TRACK); request.writeInt(index); invoke(request, reply); } /** Loading Loading @@ -1641,7 +1906,8 @@ public class MediaPlayer // No real default action so far. return; case MEDIA_TIMED_TEXT: if (mOnTimedTextListener != null) { if (mOnTimedTextListener == null) return; if (msg.obj == null) { mOnTimedTextListener.onTimedText(mMediaPlayer, null); } else { Loading @@ -1650,7 +1916,6 @@ public class MediaPlayer mOnTimedTextListener.onTimedText(mMediaPlayer, text); } } } return; case MEDIA_NOP: // interface test message - ignore Loading @@ -1663,7 +1928,7 @@ public class MediaPlayer } } /** /* * Called from native code when an interesting event happens. This method * just uses the EventHandler system to post the event back to the main app thread. * We use a weak reference to the original MediaPlayer object so that the native Loading Loading @@ -1977,6 +2242,13 @@ public class MediaPlayer */ public static final int MEDIA_INFO_METADATA_UPDATE = 802; /** Failed to handle timed text track properly. * @see android.media.MediaPlayer.OnInfoListener * * {@hide} */ public static final int MEDIA_INFO_TIMED_TEXT_ERROR = 900; /** * Interface definition of a callback to be invoked to communicate some * info and/or warning about the media or its playback. Loading media/libmediaplayerservice/StagefrightPlayer.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -166,7 +166,8 @@ player_type StagefrightPlayer::playerType() { } status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) { return INVALID_OPERATION; ALOGV("invoke()"); return mPlayer->invoke(request, reply); } void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) { Loading Loading
include/media/mediaplayer.h +20 −3 Original line number Diff line number Diff line Loading @@ -120,6 +120,9 @@ enum media_info_type { MEDIA_INFO_NOT_SEEKABLE = 801, // New media metadata is available. MEDIA_INFO_METADATA_UPDATE = 802, //9xx MEDIA_INFO_TIMED_TEXT_ERROR = 900, }; Loading @@ -140,9 +143,6 @@ enum media_player_states { // The same enum space is used for both set and get, in case there are future keys that // can be both set and get. But as of now, all parameters are either set only or get only. enum media_parameter_keys { KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000, // set only KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001, // set only // Streaming/buffering parameters KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only Loading @@ -155,6 +155,23 @@ enum media_parameter_keys { KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300, // set only }; // Keep INVOKE_ID_* in sync with MediaPlayer.java. enum media_player_invoke_ids { INVOKE_ID_GET_TRACK_INFO = 1, INVOKE_ID_ADD_EXTERNAL_SOURCE = 2, INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3, INVOKE_ID_SELECT_TRACK = 4, INVOKE_ID_UNSELECT_TRACK = 5, }; // Keep MEDIA_TRACK_TYPE_* in sync with MediaPlayer.java. enum media_track_type { MEDIA_TRACK_TYPE_UNKNOWN = 0, MEDIA_TRACK_TYPE_VIDEO = 1, MEDIA_TRACK_TYPE_AUDIO = 2, MEDIA_TRACK_TYPE_TIMEDTEXT = 3, }; // ---------------------------------------------------------------------------- // ref-counted object for callbacks class MediaPlayerListener: virtual public RefBase Loading
include/media/stagefright/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS; extern const char *MEDIA_MIMETYPE_CONTAINER_WVM; extern const char *MEDIA_MIMETYPE_TEXT_3GPP; extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP; } // namespace android Loading
include/media/stagefright/timedtext/TimedTextDriver.h +10 −10 Original line number Diff line number Diff line Loading @@ -37,26 +37,26 @@ public: ~TimedTextDriver(); // TODO: pause-resume pair seems equivalent to stop-start pair. // Check if it is replaceable with stop-start. status_t start(); status_t stop(); status_t pause(); status_t resume(); status_t selectTrack(int32_t index); status_t unselectTrack(int32_t index); status_t seekToAsync(int64_t timeUs); status_t addInBandTextSource(const sp<MediaSource>& source); status_t addOutOfBandTextSource(const Parcel &request); status_t addOutOfBandTextSource(const char *uri, const char *mimeType); // Caller owns the file desriptor and caller is responsible for closing it. status_t addOutOfBandTextSource( int fd, off64_t offset, size_t length, const char *mimeType); status_t setTimedTextTrackIndex(int32_t index); void getTrackInfo(Parcel *parcel); private: Mutex mLock; enum State { UNINITIALIZED, STOPPED, PLAYING, PAUSED, }; Loading @@ -67,11 +67,11 @@ private: // Variables to be guarded by mLock. State mState; Vector<sp<TimedTextSource> > mTextInBandVector; Vector<sp<TimedTextSource> > mTextOutOfBandVector; int32_t mCurrentTrackIndex; Vector<sp<TimedTextSource> > mTextSourceVector; // -- End of variables to be guarded by mLock status_t setTimedTextTrackIndex_l(int32_t index); status_t selectTrack_l(int32_t index); DISALLOW_EVIL_CONSTRUCTORS(TimedTextDriver); }; Loading
media/java/android/media/MediaPlayer.java +316 −44 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.util.Log; Loading Loading @@ -455,6 +456,22 @@ import java.lang.ref.WeakReference; * <td>Successful invoke of this method in a valid state transfers the * object to the <em>Stopped</em> state. Calling this method in an * invalid state transfers the object to the <em>Error</em> state.</p></td></tr> * <tr><td>getTrackInfo </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>addExternalSource </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>selectTrack </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * <tr><td>disableTrack </p></td> * <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td> * <td>{Idle, Initialized, Error}</p></td> * <td>Successful invoke of this method does not change the state.</p></td></tr> * * </table> * Loading Loading @@ -572,6 +589,15 @@ public class MediaPlayer */ private native void _setVideoSurface(Surface surface); /* Do not change these values (starting with INVOKE_ID) without updating * their counterparts in include/media/mediaplayer.h! */ private static final int INVOKE_ID_GET_TRACK_INFO = 1; private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE = 2; private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3; private static final int INVOKE_ID_SELECT_TRACK = 4; private static final int INVOKE_ID_UNSELECT_TRACK = 5; /** * Create a request parcel which can be routed to the native media * player using {@link #invoke(Parcel, Parcel)}. The Parcel Loading Loading @@ -1312,23 +1338,6 @@ public class MediaPlayer /* Do not change these values (starting with KEY_PARAMETER) without updating * their counterparts in include/media/mediaplayer.h! */ /* * Key used in setParameter method. * Indicates the index of the timed text track to be enabled/disabled. * The index includes both the in-band and out-of-band timed text. * The index should start from in-band text if any. Application can retrieve the number * of in-band text tracks by using MediaMetadataRetriever::extractMetadata(). * Note it might take a few hundred ms to scan an out-of-band text file * before displaying it. */ private static final int KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000; /* * Key used in setParameter method. * Used to add out-of-band timed text source path. * Application can add multiple text sources by calling setParameter() with * KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE multiple times. */ private static final int KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001; // There are currently no defined keys usable from Java with get*Parameter. // But if any keys are defined, the order must be kept in sync with include/media/mediaplayer.h. Loading Loading @@ -1373,7 +1382,7 @@ public class MediaPlayer return ret; } /** /* * Gets the value of the parameter indicated by key. * @param key key indicates the parameter to get. * @param reply value of the parameter to get. Loading Loading @@ -1435,7 +1444,7 @@ public class MediaPlayer */ public native void setAuxEffectSendLevel(float level); /** /* * @param request Parcel destinated to the media player. The * Interface token must be set to the IMediaPlayer * one to be routed correctly through the system. Loading @@ -1445,7 +1454,7 @@ public class MediaPlayer private native final int native_invoke(Parcel request, Parcel reply); /** /* * @param update_only If true fetch only the set of metadata that have * changed since the last invocation of getMetadata. * The set is built using the unfiltered Loading @@ -1462,7 +1471,7 @@ public class MediaPlayer boolean apply_filter, Parcel reply); /** /* * @param request Parcel with the 2 serialized lists of allowed * metadata types followed by the one to be * dropped. Each list starts with an integer Loading @@ -1476,33 +1485,289 @@ public class MediaPlayer private native final void native_finalize(); /** * @param index The index of the text track to be turned on. * @return true if the text track is enabled successfully. * Class for MediaPlayer to return each audio/video/subtitle track's metadata. * * {@see #getTrackInfo()}. * {@hide} */ static public class TrackInfo implements Parcelable { /** * Gets the track type. * @return TrackType which indicates if the track is video, audio, timed text. */ public int getTrackType() { return mTrackType; } /** * Gets the language code of the track. * @return a language code in either way of ISO-639-1 or ISO-639-2. * When the language is unknown or could not be determined, * ISO-639-2 language code, "und", is returned. */ public String getLanguage() { return mLanguage; } public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0; public static final int MEDIA_TRACK_TYPE_VIDEO = 1; public static final int MEDIA_TRACK_TYPE_AUDIO = 2; public static final int MEDIA_TRACK_TYPE_TIMEDTEXT = 3; final int mTrackType; final String mLanguage; TrackInfo(Parcel in) { mTrackType = in.readInt(); mLanguage = in.readString(); } /* * No special parcel contents. Keep it as hide. * {@hide} */ @Override public int describeContents() { return 0; } /* * {@hide} */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mTrackType); dest.writeString(mLanguage); } /** * Used to read a TrackInfo from a Parcel. */ static final Parcelable.Creator<TrackInfo> CREATOR = new Parcelable.Creator<TrackInfo>() { @Override public TrackInfo createFromParcel(Parcel in) { return new TrackInfo(in); } @Override public TrackInfo[] newArray(int size) { return new TrackInfo[size]; } }; }; /** * Returns an array of track information. * * @return Array of track info. null if an error occured. * {@hide} */ public boolean enableTimedTextTrackIndex(int index) { if (index < 0) { // FIXME: It returns timed text tracks' information for now. Other types of tracks will be // supported in future. public TrackInfo[] getTrackInfo() { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_GET_TRACK_INFO); invoke(request, reply); TrackInfo trackInfo[] = reply.createTypedArray(TrackInfo.CREATOR); return trackInfo; } /* * A helper function to check if the mime type is supported by media framework. */ private boolean availableMimeTypeForExternalSource(String mimeType) { if (mimeType == MEDIA_MIMETYPE_TEXT_SUBRIP) { return true; } return false; } return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, index); /* TODO: Limit the total number of external timed text source to a reasonable number. */ /** * Adds an external source file. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param path The file path of external source file. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(String path, String mimeType) throws IllegalArgumentException { if (!availableMimeTypeForExternalSource(mimeType)) { throw new IllegalArgumentException("Illegal mimeType for external source: " + mimeType); } Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_ADD_EXTERNAL_SOURCE); request.writeString(path); request.writeString(mimeType); invoke(request, reply); } /** * Enables the first timed text track if any. * @return true if the text track is enabled successfully * Adds an external source file (Uri). * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * {@hide} */ public boolean enableTimedText() { return enableTimedTextTrackIndex(0); // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(Context context, Uri uri, String mimeType) throws IOException, IllegalArgumentException { String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { addExternalSource(uri.getPath(), mimeType); return; } AssetFileDescriptor fd = null; try { ContentResolver resolver = context.getContentResolver(); fd = resolver.openAssetFileDescriptor(uri, "r"); if (fd == null) { return; } addExternalSource(fd.getFileDescriptor(), mimeType); return; } catch (SecurityException ex) { } catch (IOException ex) { } finally { if (fd != null) { fd.close(); } } // TODO: try server side. } /* Do not change these values without updating their counterparts * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp! */ /** * Disables timed text display. * @return true if the text track is disabled successfully. * MIME type for SubRip (SRT) container. Used in {@link #addExternalSource()} APIs. * {@hide} */ public boolean disableTimedText() { return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, -1); public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip"; /** * Adds an external source file (FileDescriptor). * It is the caller's responsibility to close the file descriptor. * It is safe to do so as soon as this call returns. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param fd the FileDescriptor for the file you want to play * @param mimeType A MIME type for the content. It can be null. * <ul> * <li>{@link #MEDIA_MIMETYPE_TEXT_SUBRIP} * </ul> * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(FileDescriptor fd, String mimeType) throws IllegalArgumentException { // intentionally less than LONG_MAX addExternalSource(fd, 0, 0x7ffffffffffffffL, mimeType); } /** * Adds an external timed text file (FileDescriptor). * It is the caller's responsibility to close the file descriptor. * It is safe to do so as soon as this call returns. * * Currently supported format is SubRip with the file extension .srt, case insensitive. * Note that a single external source may contain multiple tracks in it. * One can find the total number of available tracks using {@link #getTrackInfo()} to see what * additional tracks become available after this method call. * * @param fd the FileDescriptor for the file you want to play * @param offset the offset into the file where the data to be played starts, in bytes * @param length the length in bytes of the data to be played * @param mimeType A MIME type for the content. It can be null. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException). public void addExternalSource(FileDescriptor fd, long offset, long length, String mimeType) throws IllegalArgumentException { if (!availableMimeTypeForExternalSource(mimeType)) { throw new IllegalArgumentException("Illegal mimeType for external source: " + mimeType); } Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_ADD_EXTERNAL_SOURCE_FD); request.writeFileDescriptor(fd); request.writeLong(offset); request.writeLong(length); request.writeString(mimeType); invoke(request, reply); } /** * Selects a track. * <p> * If a MediaPlayer is in invalid state, it throws exception. * If a MediaPlayer is in Started state, the selected track will be presented immediately. * If a MediaPlayer is not in Started state, it just marks the track to be played. * </p> * <p> * In any valid state, if it is called multiple times on the same type of track (ie. Video, * Audio, Timed Text), the most recent one will be chosen. * </p> * <p> * The first audio and video tracks will be selected by default, even though this function is not * called. However, no timed text track will be selected until this function is called. * </p> * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException, IllegalArgumentException). public void selectTrack(int index) { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_SELECT_TRACK); request.writeInt(index); invoke(request, reply); } /** * Unselect a track. * If the track identified by index has not been selected before, it throws an exception. * {@hide} */ // FIXME: define error codes and throws exceptions according to the error codes. // (IllegalStateException, IOException, IllegalArgumentException). public void unselectTrack(int index) { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); request.writeInterfaceToken(IMEDIA_PLAYER); request.writeInt(INVOKE_ID_UNSELECT_TRACK); request.writeInt(index); invoke(request, reply); } /** Loading Loading @@ -1641,7 +1906,8 @@ public class MediaPlayer // No real default action so far. return; case MEDIA_TIMED_TEXT: if (mOnTimedTextListener != null) { if (mOnTimedTextListener == null) return; if (msg.obj == null) { mOnTimedTextListener.onTimedText(mMediaPlayer, null); } else { Loading @@ -1650,7 +1916,6 @@ public class MediaPlayer mOnTimedTextListener.onTimedText(mMediaPlayer, text); } } } return; case MEDIA_NOP: // interface test message - ignore Loading @@ -1663,7 +1928,7 @@ public class MediaPlayer } } /** /* * Called from native code when an interesting event happens. This method * just uses the EventHandler system to post the event back to the main app thread. * We use a weak reference to the original MediaPlayer object so that the native Loading Loading @@ -1977,6 +2242,13 @@ public class MediaPlayer */ public static final int MEDIA_INFO_METADATA_UPDATE = 802; /** Failed to handle timed text track properly. * @see android.media.MediaPlayer.OnInfoListener * * {@hide} */ public static final int MEDIA_INFO_TIMED_TEXT_ERROR = 900; /** * Interface definition of a callback to be invoked to communicate some * info and/or warning about the media or its playback. Loading
media/libmediaplayerservice/StagefrightPlayer.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -166,7 +166,8 @@ player_type StagefrightPlayer::playerType() { } status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) { return INVALID_OPERATION; ALOGV("invoke()"); return mPlayer->invoke(request, reply); } void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) { Loading