Loading api/current.txt +14 −7 Original line number Diff line number Diff line Loading @@ -25547,8 +25547,8 @@ package android.media { method @NonNull public Object clearNextDataSources(); method public void clearPendingCommands(); method public void close(); method @NonNull public Object deselectTrack(int); method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, int); method @NonNull public Object deselectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public android.media.AudioAttributes getAudioAttributes(); method public int getAudioSessionId(); method public long getBufferedPosition(); Loading @@ -25563,8 +25563,8 @@ package android.media { method public float getPlayerVolume(); method @Nullable public android.media.AudioDeviceInfo getPreferredDevice(); method @Nullable public android.media.AudioDeviceInfo getRoutedDevice(); method public int getSelectedTrack(int); method public int getSelectedTrack(@NonNull android.media.DataSourceDesc, int); method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(int); method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(@NonNull android.media.DataSourceDesc, int); method public int getState(); method @NonNull public android.media.SyncParams getSyncParams(); method @Nullable public android.media.MediaTimestamp getTimestamp(); Loading @@ -25582,8 +25582,8 @@ package android.media { method public void reset(); method @NonNull public Object seekTo(long); method @NonNull public Object seekTo(long, int); method @NonNull public Object selectTrack(int); method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, int); method @NonNull public Object selectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object setAudioAttributes(@NonNull android.media.AudioAttributes); method @NonNull public Object setAudioSessionId(int); method @NonNull public Object setAuxEffectSendLevel(float); Loading Loading @@ -25715,7 +25715,7 @@ package android.media { method public void onError(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onMediaTimeDiscontinuity(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaTimestamp); method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.SubtitleData); method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.SubtitleData); method public void onTimedMetaDataAvailable(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.TimedMetaData); method public void onVideoSizeChanged(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.util.Size); } Loading @@ -25739,6 +25739,13 @@ package android.media { ctor public MediaPlayer2.NoDrmSchemeException(@Nullable String); } public static final class MediaPlayer2.SubtitleData { method @NonNull public byte[] getData(); method public long getDurationUs(); method public long getStartTimeUs(); method @NonNull public android.media.MediaPlayer2.TrackInfo getTrackInfo(); } public static class MediaPlayer2.TrackInfo { method @Nullable public android.media.MediaFormat getFormat(); method @NonNull public String getLanguage(); media/apex/java/android/media/MediaPlayer2.java +143 −51 Original line number Diff line number Diff line Loading @@ -1967,6 +1967,17 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { private native byte[] native_invoke(byte[] request); /** * @hide */ @IntDef(flag = false, prefix = "MEDIA_TRACK_TYPE", value = { TrackInfo.MEDIA_TRACK_TYPE_VIDEO, TrackInfo.MEDIA_TRACK_TYPE_AUDIO, TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE }) @Retention(RetentionPolicy.SOURCE) public @interface TrackType {} /** * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. * Loading Loading @@ -2014,10 +2025,11 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; public static final int MEDIA_TRACK_TYPE_METADATA = 5; final int mId; final int mTrackType; final MediaFormat mFormat; static TrackInfo create(Iterator<Value> in) { static TrackInfo create(int idx, Iterator<Value> in) { int trackType = in.next().getInt32Value(); // TODO: build the full MediaFormat; currently we are using createSubtitleFormat // even for audio/video tracks, meaning we only set the mime and language. Loading @@ -2030,11 +2042,12 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { format.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value()); format.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value()); } return new TrackInfo(trackType, format); return new TrackInfo(idx, trackType, format); } /** @hide */ TrackInfo(int type, MediaFormat format) { TrackInfo(int id, int type, MediaFormat format) { mId = id; mTrackType = type; mFormat = format; } Loading Loading @@ -2121,7 +2134,7 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { } TrackInfo[] trackInfo = new TrackInfo[size]; for (int i = 0; i < size; ++i) { trackInfo[i] = TrackInfo.create(in); trackInfo[i] = TrackInfo.create(i, in); } return trackInfo; } Loading @@ -2129,54 +2142,56 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}. * be used in calls to {@link #selectTrack(TrackInfo)} or {@link #deselectTrack(TrackInfo)}. * Same as {@link #getSelectedTrack(DataSourceDesc, int)} with * {@code dsd = getCurrentDataSource()}. * * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} * @return index of the audio, video, or subtitle track currently selected for playback; * a negative integer is returned when there is no selected track for {@code trackType} or * @return metadata corresponding to the audio, video, or subtitle track currently selected for * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if current data source is null * * @see #getTrackInfo() * @see #selectTrack(int) * @see #deselectTrack(int) * @see #selectTrack(TrackInfo) * @see #deselectTrack(TrackInfo) */ public int getSelectedTrack(int trackType) { @Nullable public TrackInfo getSelectedTrack(@TrackType int trackType) { return getSelectedTrack(getCurrentDataSource(), trackType); } /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can * be used in calls to {@link #selectTrack(DataSourceDesc, int)} or * {@link #deselectTrack(DataSourceDesc, int)}. * be used in calls to {@link #selectTrack(DataSourceDesc, TrackInfo)} or * {@link #deselectTrack(DataSourceDesc, TrackInfo)}. * * @param dsd the descriptor of data source of which you want to get selected track * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} * @return index of the audio, video, or subtitle track currently selected for playback; * a negative integer is returned when there is no selected track for {@code trackType} or * @return metadata corresponding to the audio, video, or subtitle track currently selected for * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if dsd is null * * @see #getTrackInfo(DataSourceDesc) * @see #selectTrack(DataSourceDesc, int) * @see #deselectTrack(DataSourceDesc, int) * @see #selectTrack(DataSourceDesc, TrackInfo) * @see #deselectTrack(DataSourceDesc, TrackInfo) */ public int getSelectedTrack(@NonNull DataSourceDesc dsd, int trackType) { @Nullable public TrackInfo getSelectedTrack(@NonNull DataSourceDesc dsd, @TrackType int trackType) { if (dsd == null) { throw new NullPointerException("non-null dsd is expected"); } SourceInfo sourceInfo = getSourceInfo(dsd); if (sourceInfo == null) { return -1; return null; } PlayerMessage request = PlayerMessage.newBuilder() Loading @@ -2186,26 +2201,30 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { .build(); PlayerMessage response = invoke(request); if (response == null) { return -1; return null; } return response.getValues(0).getInt32Value(); // TODO: return full TrackInfo data from native player instead of index final int idx = response.getValues(0).getInt32Value(); final List<TrackInfo> trackInfos = getTrackInfo(dsd); return trackInfos.isEmpty() ? null : trackInfos.get(idx); } /** * Selects a track of current data source. * Same as {@link #selectTrack(DataSourceDesc, int)} with * Same as {@link #selectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * * @param index the index of the track to be selected. The valid range of the index * is 0..total number of track - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo()} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo() */ // This is an asynchronous call. public @NonNull Object selectTrack(int index) { return selectTrack(getCurrentDataSource(), index); @NonNull public Object selectTrack(@NonNull TrackInfo trackInfo) { return selectTrack(getCurrentDataSource(), trackInfo); } /** Loading @@ -2230,38 +2249,40 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { * in that an audio track can only be selected in the <em>Prepared</em> state. * </p> * @param dsd the descriptor of data source of which you want to select track * @param index the index of the track to be selected. The valid range of the index * is 0..total number of track - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo(DataSourceDesc)} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ // This is an asynchronous call. public @NonNull Object selectTrack(@NonNull DataSourceDesc dsd, int index) { @NonNull public Object selectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) { @Override void process() { selectOrDeselectTrack(dsd, index, true /* select */); selectOrDeselectTrack(dsd, trackInfo.mId, true /* select */); } }); } /** * Deselect a track of current data source. * Same as {@link #deselectTrack(DataSourceDesc, int)} with * Same as {@link #deselectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * * @param index the index of the track to be deselected. The valid range of the index * is 0..total number of tracks - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo()} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo() */ // This is an asynchronous call. public @NonNull Object deselectTrack(int index) { return deselectTrack(getCurrentDataSource(), index); @NonNull public Object deselectTrack(@NonNull TrackInfo trackInfo) { return deselectTrack(getCurrentDataSource(), trackInfo); } /** Loading @@ -2272,19 +2293,20 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { * selected before, it throws an exception. * </p> * @param dsd the descriptor of data source of which you want to deselect track * @param index the index of the track to be deselected. The valid range of the index * is 0..total number of tracks - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ // This is an asynchronous call. public @NonNull Object deselectTrack(@NonNull DataSourceDesc dsd, int index) { @NonNull public Object deselectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) { @Override void process() { selectOrDeselectTrack(dsd, index, false /* select */); selectOrDeselectTrack(dsd, trackInfo.mId, false /* select */); } }); } Loading Loading @@ -2645,11 +2667,13 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { return; } Iterator<Value> in = playerMsg.getValuesList().iterator(); SubtitleData data = new SubtitleData( in.next().getInt32Value(), // trackIndex in.next().getInt64Value(), // startTimeUs in.next().getInt64Value(), // durationUs in.next().getBytesValue().toByteArray()); // data final int trackIndex = in.next().getInt32Value(); TrackInfo trackInfo = getTrackInfo(dsd).get(trackIndex); final long startTimeUs = in.next().getInt64Value(); final long durationTimeUs = in.next().getInt64Value(); final byte[] subData = in.next().getBytesValue().toByteArray(); SubtitleData data = new SubtitleData(trackInfo, startTimeUs, durationTimeUs, subData); sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { Loading Loading @@ -2769,6 +2793,74 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { } } /** * Class encapsulating subtitle data, as received through the * {@link EventCallback#onSubtitleData} interface. * <p> * A {@link SubtitleData} object includes: * <ul> * <li> track metadadta in a {@link TrackInfo} object</li> * <li> the start time (in microseconds) of the data</li> * <li> the duration (in microseconds) of the data</li> * <li> the actual data.</li> * </ul> * The data is stored in a byte-array, and is encoded in one of the supported in-band * subtitle formats. The subtitle encoding is determined by the MIME type of the * {@link TrackInfo} of the subtitle track, one of * {@link MediaFormat#MIMETYPE_TEXT_CEA_608}, {@link MediaFormat#MIMETYPE_TEXT_CEA_708}, * {@link MediaFormat#MIMETYPE_TEXT_VTT}. */ public static final class SubtitleData { private TrackInfo mTrackInfo; private long mStartTimeUs; private long mDurationUs; private byte[] mData; private SubtitleData(TrackInfo trackInfo, long startTimeUs, long durationUs, byte[] data) { mTrackInfo = trackInfo; mStartTimeUs = startTimeUs; mDurationUs = durationUs; mData = (data != null ? data : new byte[0]); } /** * @return metadata of track which contains this subtitle data */ @NonNull public TrackInfo getTrackInfo() { return mTrackInfo; } /** * @return media time at which the subtitle should start to be displayed in microseconds */ public long getStartTimeUs() { return mStartTimeUs; } /** * @return the duration in microsecond during which the subtitle should be displayed */ public long getDurationUs() { return mDurationUs; } /** * Returns the encoded data for the subtitle content. * Encoding format depends on the subtitle type, refer to * <a href="https://en.wikipedia.org/wiki/CEA-708">CEA 708</a>, * <a href="https://en.wikipedia.org/wiki/EIA-608">CEA/EIA 608</a> and * <a href="https://www.w3.org/TR/webvtt1/">WebVTT</a>, defined by the MIME type * of the subtitle track. * @return the encoded subtitle data */ @NonNull public byte[] getData() { return mData; } } /** * Interface definition for callbacks to be invoked when the player has the corresponding * events. Loading Loading
api/current.txt +14 −7 Original line number Diff line number Diff line Loading @@ -25547,8 +25547,8 @@ package android.media { method @NonNull public Object clearNextDataSources(); method public void clearPendingCommands(); method public void close(); method @NonNull public Object deselectTrack(int); method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, int); method @NonNull public Object deselectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public android.media.AudioAttributes getAudioAttributes(); method public int getAudioSessionId(); method public long getBufferedPosition(); Loading @@ -25563,8 +25563,8 @@ package android.media { method public float getPlayerVolume(); method @Nullable public android.media.AudioDeviceInfo getPreferredDevice(); method @Nullable public android.media.AudioDeviceInfo getRoutedDevice(); method public int getSelectedTrack(int); method public int getSelectedTrack(@NonNull android.media.DataSourceDesc, int); method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(int); method @Nullable public android.media.MediaPlayer2.TrackInfo getSelectedTrack(@NonNull android.media.DataSourceDesc, int); method public int getState(); method @NonNull public android.media.SyncParams getSyncParams(); method @Nullable public android.media.MediaTimestamp getTimestamp(); Loading @@ -25582,8 +25582,8 @@ package android.media { method public void reset(); method @NonNull public Object seekTo(long); method @NonNull public Object seekTo(long, int); method @NonNull public Object selectTrack(int); method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, int); method @NonNull public Object selectTrack(@NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.TrackInfo); method @NonNull public Object setAudioAttributes(@NonNull android.media.AudioAttributes); method @NonNull public Object setAudioSessionId(int); method @NonNull public Object setAuxEffectSendLevel(float); Loading Loading @@ -25715,7 +25715,7 @@ package android.media { method public void onError(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onInfo(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, int, int); method public void onMediaTimeDiscontinuity(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaTimestamp); method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.SubtitleData); method public void onSubtitleData(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.MediaPlayer2.SubtitleData); method public void onTimedMetaDataAvailable(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.media.TimedMetaData); method public void onVideoSizeChanged(@NonNull android.media.MediaPlayer2, @NonNull android.media.DataSourceDesc, @NonNull android.util.Size); } Loading @@ -25739,6 +25739,13 @@ package android.media { ctor public MediaPlayer2.NoDrmSchemeException(@Nullable String); } public static final class MediaPlayer2.SubtitleData { method @NonNull public byte[] getData(); method public long getDurationUs(); method public long getStartTimeUs(); method @NonNull public android.media.MediaPlayer2.TrackInfo getTrackInfo(); } public static class MediaPlayer2.TrackInfo { method @Nullable public android.media.MediaFormat getFormat(); method @NonNull public String getLanguage();
media/apex/java/android/media/MediaPlayer2.java +143 −51 Original line number Diff line number Diff line Loading @@ -1967,6 +1967,17 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { private native byte[] native_invoke(byte[] request); /** * @hide */ @IntDef(flag = false, prefix = "MEDIA_TRACK_TYPE", value = { TrackInfo.MEDIA_TRACK_TYPE_VIDEO, TrackInfo.MEDIA_TRACK_TYPE_AUDIO, TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE }) @Retention(RetentionPolicy.SOURCE) public @interface TrackType {} /** * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. * Loading Loading @@ -2014,10 +2025,11 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4; public static final int MEDIA_TRACK_TYPE_METADATA = 5; final int mId; final int mTrackType; final MediaFormat mFormat; static TrackInfo create(Iterator<Value> in) { static TrackInfo create(int idx, Iterator<Value> in) { int trackType = in.next().getInt32Value(); // TODO: build the full MediaFormat; currently we are using createSubtitleFormat // even for audio/video tracks, meaning we only set the mime and language. Loading @@ -2030,11 +2042,12 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { format.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value()); format.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value()); } return new TrackInfo(trackType, format); return new TrackInfo(idx, trackType, format); } /** @hide */ TrackInfo(int type, MediaFormat format) { TrackInfo(int id, int type, MediaFormat format) { mId = id; mTrackType = type; mFormat = format; } Loading Loading @@ -2121,7 +2134,7 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { } TrackInfo[] trackInfo = new TrackInfo[size]; for (int i = 0; i < size; ++i) { trackInfo[i] = TrackInfo.create(in); trackInfo[i] = TrackInfo.create(i, in); } return trackInfo; } Loading @@ -2129,54 +2142,56 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}. * be used in calls to {@link #selectTrack(TrackInfo)} or {@link #deselectTrack(TrackInfo)}. * Same as {@link #getSelectedTrack(DataSourceDesc, int)} with * {@code dsd = getCurrentDataSource()}. * * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} * @return index of the audio, video, or subtitle track currently selected for playback; * a negative integer is returned when there is no selected track for {@code trackType} or * @return metadata corresponding to the audio, video, or subtitle track currently selected for * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if current data source is null * * @see #getTrackInfo() * @see #selectTrack(int) * @see #deselectTrack(int) * @see #selectTrack(TrackInfo) * @see #deselectTrack(TrackInfo) */ public int getSelectedTrack(int trackType) { @Nullable public TrackInfo getSelectedTrack(@TrackType int trackType) { return getSelectedTrack(getCurrentDataSource(), trackType); } /** * Returns the index of the audio, video, or subtitle track currently selected for playback. * The return value is an index into the array returned by {@link #getTrackInfo}, and can * be used in calls to {@link #selectTrack(DataSourceDesc, int)} or * {@link #deselectTrack(DataSourceDesc, int)}. * be used in calls to {@link #selectTrack(DataSourceDesc, TrackInfo)} or * {@link #deselectTrack(DataSourceDesc, TrackInfo)}. * * @param dsd the descriptor of data source of which you want to get selected track * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO}, * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE} * @return index of the audio, video, or subtitle track currently selected for playback; * a negative integer is returned when there is no selected track for {@code trackType} or * @return metadata corresponding to the audio, video, or subtitle track currently selected for * playback; {@code null} is returned when there is no selected track for {@code trackType} or * when {@code trackType} is not one of audio, video, or subtitle. * @throws IllegalStateException if called after {@link #close()} * @throws NullPointerException if dsd is null * * @see #getTrackInfo(DataSourceDesc) * @see #selectTrack(DataSourceDesc, int) * @see #deselectTrack(DataSourceDesc, int) * @see #selectTrack(DataSourceDesc, TrackInfo) * @see #deselectTrack(DataSourceDesc, TrackInfo) */ public int getSelectedTrack(@NonNull DataSourceDesc dsd, int trackType) { @Nullable public TrackInfo getSelectedTrack(@NonNull DataSourceDesc dsd, @TrackType int trackType) { if (dsd == null) { throw new NullPointerException("non-null dsd is expected"); } SourceInfo sourceInfo = getSourceInfo(dsd); if (sourceInfo == null) { return -1; return null; } PlayerMessage request = PlayerMessage.newBuilder() Loading @@ -2186,26 +2201,30 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { .build(); PlayerMessage response = invoke(request); if (response == null) { return -1; return null; } return response.getValues(0).getInt32Value(); // TODO: return full TrackInfo data from native player instead of index final int idx = response.getValues(0).getInt32Value(); final List<TrackInfo> trackInfos = getTrackInfo(dsd); return trackInfos.isEmpty() ? null : trackInfos.get(idx); } /** * Selects a track of current data source. * Same as {@link #selectTrack(DataSourceDesc, int)} with * Same as {@link #selectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * * @param index the index of the track to be selected. The valid range of the index * is 0..total number of track - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo()} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo() */ // This is an asynchronous call. public @NonNull Object selectTrack(int index) { return selectTrack(getCurrentDataSource(), index); @NonNull public Object selectTrack(@NonNull TrackInfo trackInfo) { return selectTrack(getCurrentDataSource(), trackInfo); } /** Loading @@ -2230,38 +2249,40 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { * in that an audio track can only be selected in the <em>Prepared</em> state. * </p> * @param dsd the descriptor of data source of which you want to select track * @param index the index of the track to be selected. The valid range of the index * is 0..total number of track - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo(DataSourceDesc)} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ // This is an asynchronous call. public @NonNull Object selectTrack(@NonNull DataSourceDesc dsd, int index) { @NonNull public Object selectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) { @Override void process() { selectOrDeselectTrack(dsd, index, true /* select */); selectOrDeselectTrack(dsd, trackInfo.mId, true /* select */); } }); } /** * Deselect a track of current data source. * Same as {@link #deselectTrack(DataSourceDesc, int)} with * Same as {@link #deselectTrack(DataSourceDesc, TrackInfo)} with * {@code dsd = getCurrentDataSource()}. * * @param index the index of the track to be deselected. The valid range of the index * is 0..total number of tracks - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo()} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo() */ // This is an asynchronous call. public @NonNull Object deselectTrack(int index) { return deselectTrack(getCurrentDataSource(), index); @NonNull public Object deselectTrack(@NonNull TrackInfo trackInfo) { return deselectTrack(getCurrentDataSource(), trackInfo); } /** Loading @@ -2272,19 +2293,20 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { * selected before, it throws an exception. * </p> * @param dsd the descriptor of data source of which you want to deselect track * @param index the index of the track to be deselected. The valid range of the index * is 0..total number of tracks - 1. The total number of tracks as well as the type of * each individual track can be found by calling {@link #getTrackInfo} method. * @param trackInfo metadata corresponding to the track to be selected. A {@code trackInfo} * object can be obtained from {@link #getTrackInfo()}. * @return a token which can be used to cancel the operation later with {@link #cancelCommand}. * * This is an asynchronous call. * * @see MediaPlayer2#getTrackInfo(DataSourceDesc) */ // This is an asynchronous call. public @NonNull Object deselectTrack(@NonNull DataSourceDesc dsd, int index) { @NonNull public Object deselectTrack(@NonNull DataSourceDesc dsd, @NonNull TrackInfo trackInfo) { return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) { @Override void process() { selectOrDeselectTrack(dsd, index, false /* select */); selectOrDeselectTrack(dsd, trackInfo.mId, false /* select */); } }); } Loading Loading @@ -2645,11 +2667,13 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { return; } Iterator<Value> in = playerMsg.getValuesList().iterator(); SubtitleData data = new SubtitleData( in.next().getInt32Value(), // trackIndex in.next().getInt64Value(), // startTimeUs in.next().getInt64Value(), // durationUs in.next().getBytesValue().toByteArray()); // data final int trackIndex = in.next().getInt32Value(); TrackInfo trackInfo = getTrackInfo(dsd).get(trackIndex); final long startTimeUs = in.next().getInt64Value(); final long durationTimeUs = in.next().getInt64Value(); final byte[] subData = in.next().getBytesValue().toByteArray(); SubtitleData data = new SubtitleData(trackInfo, startTimeUs, durationTimeUs, subData); sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { Loading Loading @@ -2769,6 +2793,74 @@ public class MediaPlayer2 implements AutoCloseable, AudioRouting { } } /** * Class encapsulating subtitle data, as received through the * {@link EventCallback#onSubtitleData} interface. * <p> * A {@link SubtitleData} object includes: * <ul> * <li> track metadadta in a {@link TrackInfo} object</li> * <li> the start time (in microseconds) of the data</li> * <li> the duration (in microseconds) of the data</li> * <li> the actual data.</li> * </ul> * The data is stored in a byte-array, and is encoded in one of the supported in-band * subtitle formats. The subtitle encoding is determined by the MIME type of the * {@link TrackInfo} of the subtitle track, one of * {@link MediaFormat#MIMETYPE_TEXT_CEA_608}, {@link MediaFormat#MIMETYPE_TEXT_CEA_708}, * {@link MediaFormat#MIMETYPE_TEXT_VTT}. */ public static final class SubtitleData { private TrackInfo mTrackInfo; private long mStartTimeUs; private long mDurationUs; private byte[] mData; private SubtitleData(TrackInfo trackInfo, long startTimeUs, long durationUs, byte[] data) { mTrackInfo = trackInfo; mStartTimeUs = startTimeUs; mDurationUs = durationUs; mData = (data != null ? data : new byte[0]); } /** * @return metadata of track which contains this subtitle data */ @NonNull public TrackInfo getTrackInfo() { return mTrackInfo; } /** * @return media time at which the subtitle should start to be displayed in microseconds */ public long getStartTimeUs() { return mStartTimeUs; } /** * @return the duration in microsecond during which the subtitle should be displayed */ public long getDurationUs() { return mDurationUs; } /** * Returns the encoded data for the subtitle content. * Encoding format depends on the subtitle type, refer to * <a href="https://en.wikipedia.org/wiki/CEA-708">CEA 708</a>, * <a href="https://en.wikipedia.org/wiki/EIA-608">CEA/EIA 608</a> and * <a href="https://www.w3.org/TR/webvtt1/">WebVTT</a>, defined by the MIME type * of the subtitle track. * @return the encoded subtitle data */ @NonNull public byte[] getData() { return mData; } } /** * Interface definition for callbacks to be invoked when the player has the corresponding * events. Loading