Loading media/java/android/media/MediaPlayer.java +136 −79 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; import android.util.Log; import android.util.Pair; import android.view.Surface; import android.view.SurfaceHolder; import android.widget.VideoView; Loading Loading @@ -70,6 +71,8 @@ import java.lang.Runnable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetSocketAddress; import java.util.BitSet; import java.util.HashSet; import java.util.Map; import java.util.Scanner; import java.util.Set; Loading Loading @@ -639,9 +642,7 @@ public class MediaPlayer implements SubtitleController.Listener } mTimeProvider = new TimeProvider(this); mOutOfBandSubtitleTracks = new Vector<SubtitleTrack>(); mOpenSubtitleSources = new Vector<InputStream>(); mInbandSubtitleTracks = new SubtitleTrack[0]; IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); Loading Loading @@ -1693,8 +1694,6 @@ public class MediaPlayer implements SubtitleController.Listener } mOpenSubtitleSources.clear(); } mOutOfBandSubtitleTracks.clear(); mInbandSubtitleTracks = new SubtitleTrack[0]; if (mSubtitleController != null) { mSubtitleController.reset(); } Loading @@ -1709,6 +1708,11 @@ public class MediaPlayer implements SubtitleController.Listener if (mEventHandler != null) { mEventHandler.removeCallbacksAndMessages(null); } synchronized (mIndexTrackPairs) { mIndexTrackPairs.clear(); mInbandTrackIndices.clear(); }; } private native void _reset(); Loading Loading @@ -2050,6 +2054,16 @@ public class MediaPlayer implements SubtitleController.Listener }; // We would like domain specific classes with more informative names than the `first` and `second` // in generic Pair, but we would also like to avoid creating new/trivial classes. As a compromise // we document the meanings of `first` and `second` here: // // Pair.first - inband track index; non-null iff representing an inband track. // Pair.second - a SubtitleTrack registered with mSubtitleController; non-null iff representing // an inband subtitle track or any out-of-band track (subtitle or timedtext). private Vector<Pair<Integer, SubtitleTrack>> mIndexTrackPairs = new Vector<>(); private BitSet mInbandTrackIndices = new BitSet(); /** * Returns an array of track information. * Loading @@ -2061,18 +2075,21 @@ public class MediaPlayer implements SubtitleController.Listener public TrackInfo[] getTrackInfo() throws IllegalStateException { TrackInfo trackInfo[] = getInbandTrackInfo(); // add out-of-band tracks TrackInfo allTrackInfo[] = new TrackInfo[trackInfo.length + mOutOfBandSubtitleTracks.size()]; System.arraycopy(trackInfo, 0, allTrackInfo, 0, trackInfo.length); int i = trackInfo.length; for (SubtitleTrack track: mOutOfBandSubtitleTracks) { int type = track.isTimedText() ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE; allTrackInfo[i] = new TrackInfo(type, track.getFormat()); ++i; synchronized (mIndexTrackPairs) { TrackInfo allTrackInfo[] = new TrackInfo[mIndexTrackPairs.size()]; for (int i = 0; i < allTrackInfo.length; i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.first != null) { // inband track allTrackInfo[i] = trackInfo[p.first]; } else { SubtitleTrack track = p.second; allTrackInfo[i] = new TrackInfo(track.getTrackType(), track.getFormat()); } } return allTrackInfo; } } private TrackInfo[] getInbandTrackInfo() throws IllegalStateException { Parcel request = Parcel.obtain(); Loading Loading @@ -2167,24 +2184,23 @@ public class MediaPlayer implements SubtitleController.Listener } } private final Object mInbandSubtitleLock = new Object(); private SubtitleTrack[] mInbandSubtitleTracks; private int mSelectedSubtitleTrackIndex = -1; private Vector<SubtitleTrack> mOutOfBandSubtitleTracks; private Vector<InputStream> mOpenSubtitleSources; private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() { @Override public void onSubtitleData(MediaPlayer mp, SubtitleData data) { int index = data.getTrackIndex(); if (index >= mInbandSubtitleTracks.length) { return; } SubtitleTrack track = mInbandSubtitleTracks[index]; if (track != null) { synchronized (mIndexTrackPairs) { for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { if (p.first != null && p.first == index && p.second != null) { // inband subtitle track that owns data SubtitleTrack track = p.second; track.onData(data); } } } } }; /** @hide */ Loading @@ -2201,17 +2217,23 @@ public class MediaPlayer implements SubtitleController.Listener if (track == null) { return; } for (int i = 0; i < mInbandSubtitleTracks.length; i++) { if (mInbandSubtitleTracks[i] == track) { Log.v(TAG, "Selecting subtitle track " + i); mSelectedSubtitleTrackIndex = i; synchronized (mIndexTrackPairs) { for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { if (p.first != null && p.second == track) { // inband subtitle track that is selected mSelectedSubtitleTrackIndex = p.first; break; } } } if (mSelectedSubtitleTrackIndex >= 0) { try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true); } catch (IllegalStateException e) { } setOnSubtitleDataListener(mSubtitleDataListener); break; } } // no need to select out-of-band tracks } Loading Loading @@ -2252,7 +2274,9 @@ public class MediaPlayer implements SubtitleController.Listener mOpenSubtitleSources.remove(fIs); } scanner.close(); mOutOfBandSubtitleTracks.add(track); synchronized (mIndexTrackPairs) { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); } track.onData(contents.getBytes(), true /* eos */, ~0 /* runID: keep forever */); return MEDIA_INFO_EXTERNAL_METADATA_UPDATE; } Loading @@ -2274,23 +2298,33 @@ public class MediaPlayer implements SubtitleController.Listener setSubtitleAnchor(); } populateInbandTracks(); if (mSubtitleController != null) { mSubtitleController.selectDefaultTrack(); } } private void populateInbandTracks() { TrackInfo[] tracks = getInbandTrackInfo(); synchronized (mInbandSubtitleLock) { SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length]; synchronized (mIndexTrackPairs) { for (int i = 0; i < tracks.length; i++) { if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { if (i < mInbandSubtitleTracks.length) { inbandTracks[i] = mInbandSubtitleTracks[i]; if (mInbandTrackIndices.get(i)) { continue; } else { mInbandTrackIndices.set(i); } // newly appeared inband track if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { SubtitleTrack track = mSubtitleController.addTrack( tracks[i].getFormat()); inbandTracks[i] = track; } mIndexTrackPairs.add(Pair.create(i, track)); } else { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(i, null)); } } mInbandSubtitleTracks = inbandTracks; } mSubtitleController.selectDefaultTrack(); } /* TODO: Limit the total number of external timed text source to a reasonable number. Loading Loading @@ -2438,7 +2472,9 @@ public class MediaPlayer implements SubtitleController.Listener mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler)); } final SubtitleTrack track = mSubtitleController.addTrack(fFormat); mOutOfBandSubtitleTracks.add(track); synchronized (mIndexTrackPairs) { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); } final FileDescriptor fd3 = fd2; final long offset2 = offset; Loading Loading @@ -2510,12 +2546,18 @@ public class MediaPlayer implements SubtitleController.Listener * @see #deselectTrack(int) */ public int getSelectedTrack(int trackType) throws IllegalStateException { if (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE && mSubtitleController != null) { if (mSubtitleController != null && (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT)) { SubtitleTrack subtitleTrack = mSubtitleController.getSelectedTrack(); if (subtitleTrack != null) { int index = mOutOfBandSubtitleTracks.indexOf(subtitleTrack); if (index >= 0) { return mInbandSubtitleTracks.length + index; synchronized (mIndexTrackPairs) { for (int i = 0; i < mIndexTrackPairs.size(); i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.second == subtitleTrack && subtitleTrack.getTrackType() == trackType) { return i; } } } } } Loading @@ -2527,8 +2569,16 @@ public class MediaPlayer implements SubtitleController.Listener request.writeInt(INVOKE_ID_GET_SELECTED_TRACK); request.writeInt(trackType); invoke(request, reply); int selectedTrack = reply.readInt(); return selectedTrack; int inbandTrackIndex = reply.readInt(); synchronized (mIndexTrackPairs) { for (int i = 0; i < mIndexTrackPairs.size(); i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.first != null && p.first == inbandTrackIndex) { return i; } } } return -1; } finally { request.recycle(); reply.recycle(); Loading Loading @@ -2588,36 +2638,30 @@ public class MediaPlayer implements SubtitleController.Listener private void selectOrDeselectTrack(int index, boolean select) throws IllegalStateException { // handle subtitle track through subtitle controller SubtitleTrack track = null; synchronized (mInbandSubtitleLock) { if (mInbandSubtitleTracks.length == 0) { TrackInfo[] tracks = getInbandTrackInfo(); mInbandSubtitleTracks = new SubtitleTrack[tracks.length]; for (int i=0; i < tracks.length; i++) { if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { mInbandSubtitleTracks[i] = mSubtitleController.addTrack(tracks[i].getFormat()); } } } } populateInbandTracks(); if (index < mInbandSubtitleTracks.length) { track = mInbandSubtitleTracks[index]; } else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) { track = mOutOfBandSubtitleTracks.get(index - mInbandSubtitleTracks.length); Pair<Integer,SubtitleTrack> p = null; try { p = mIndexTrackPairs.get(index); } catch (ArrayIndexOutOfBoundsException e) { // ignore bad index return; } if (mSubtitleController != null && track != null) { if (select) { if (track.isTimedText()) { int ttIndex = getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); if (ttIndex >= 0 && ttIndex < mInbandSubtitleTracks.length) { // deselect inband counterpart selectOrDeselectInbandTrack(ttIndex, false); SubtitleTrack track = p.second; if (track == null) { // inband (de)select selectOrDeselectInbandTrack(p.first, select); return; } if (mSubtitleController == null) { return; } mSubtitleController.selectTrack(track); } else if (mSubtitleController.getSelectedTrack() == track) { if (!select) { // out-of-band deselect if (mSubtitleController.getSelectedTrack() == track) { mSubtitleController.selectTrack(null); } else { Log.w(TAG, "trying to deselect track that was not selected"); Loading @@ -2625,7 +2669,20 @@ public class MediaPlayer implements SubtitleController.Listener return; } selectOrDeselectInbandTrack(index, select); // out-of-band select if (track.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { int ttIndex = getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); synchronized (mIndexTrackPairs) { if (ttIndex >= 0 && ttIndex < mIndexTrackPairs.size()) { Pair<Integer,SubtitleTrack> p2 = mIndexTrackPairs.get(ttIndex); if (p2.first != null && p2.second == null) { // deselect inband counterpart selectOrDeselectInbandTrack(p2.first, false); } } } } mSubtitleController.selectTrack(track); } private void selectOrDeselectInbandTrack(int index, boolean select) Loading media/java/android/media/SubtitleController.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.util.Locale; import java.util.Vector; import android.content.Context; import android.media.MediaPlayer.TrackInfo; import android.media.SubtitleTrack.RenderingWidget; import android.os.Handler; import android.os.Looper; Loading Loading @@ -275,7 +276,8 @@ public class SubtitleController { mSelectedTrack.getFormat().getInteger( MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) { show(); } else if (mSelectedTrack != null && !mSelectedTrack.isTimedText()) { } else if (mSelectedTrack != null && mSelectedTrack.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { hide(); } mVisibilityIsExplicit = false; Loading media/java/android/media/SubtitleTrack.java +5 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.media; import android.graphics.Canvas; import android.media.MediaPlayer.TrackInfo; import android.os.Handler; import android.util.Log; import android.util.LongSparseArray; Loading Loading @@ -609,8 +610,10 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide whether this is a text track who fires events instead getting rendered */ public boolean isTimedText() { return getRenderingWidget() == null; public int getTrackType() { return getRenderingWidget() == null ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE; } Loading Loading
media/java/android/media/MediaPlayer.java +136 −79 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.provider.Settings; import android.system.ErrnoException; import android.system.OsConstants; import android.util.Log; import android.util.Pair; import android.view.Surface; import android.view.SurfaceHolder; import android.widget.VideoView; Loading Loading @@ -70,6 +71,8 @@ import java.lang.Runnable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetSocketAddress; import java.util.BitSet; import java.util.HashSet; import java.util.Map; import java.util.Scanner; import java.util.Set; Loading Loading @@ -639,9 +642,7 @@ public class MediaPlayer implements SubtitleController.Listener } mTimeProvider = new TimeProvider(this); mOutOfBandSubtitleTracks = new Vector<SubtitleTrack>(); mOpenSubtitleSources = new Vector<InputStream>(); mInbandSubtitleTracks = new SubtitleTrack[0]; IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); Loading Loading @@ -1693,8 +1694,6 @@ public class MediaPlayer implements SubtitleController.Listener } mOpenSubtitleSources.clear(); } mOutOfBandSubtitleTracks.clear(); mInbandSubtitleTracks = new SubtitleTrack[0]; if (mSubtitleController != null) { mSubtitleController.reset(); } Loading @@ -1709,6 +1708,11 @@ public class MediaPlayer implements SubtitleController.Listener if (mEventHandler != null) { mEventHandler.removeCallbacksAndMessages(null); } synchronized (mIndexTrackPairs) { mIndexTrackPairs.clear(); mInbandTrackIndices.clear(); }; } private native void _reset(); Loading Loading @@ -2050,6 +2054,16 @@ public class MediaPlayer implements SubtitleController.Listener }; // We would like domain specific classes with more informative names than the `first` and `second` // in generic Pair, but we would also like to avoid creating new/trivial classes. As a compromise // we document the meanings of `first` and `second` here: // // Pair.first - inband track index; non-null iff representing an inband track. // Pair.second - a SubtitleTrack registered with mSubtitleController; non-null iff representing // an inband subtitle track or any out-of-band track (subtitle or timedtext). private Vector<Pair<Integer, SubtitleTrack>> mIndexTrackPairs = new Vector<>(); private BitSet mInbandTrackIndices = new BitSet(); /** * Returns an array of track information. * Loading @@ -2061,18 +2075,21 @@ public class MediaPlayer implements SubtitleController.Listener public TrackInfo[] getTrackInfo() throws IllegalStateException { TrackInfo trackInfo[] = getInbandTrackInfo(); // add out-of-band tracks TrackInfo allTrackInfo[] = new TrackInfo[trackInfo.length + mOutOfBandSubtitleTracks.size()]; System.arraycopy(trackInfo, 0, allTrackInfo, 0, trackInfo.length); int i = trackInfo.length; for (SubtitleTrack track: mOutOfBandSubtitleTracks) { int type = track.isTimedText() ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE; allTrackInfo[i] = new TrackInfo(type, track.getFormat()); ++i; synchronized (mIndexTrackPairs) { TrackInfo allTrackInfo[] = new TrackInfo[mIndexTrackPairs.size()]; for (int i = 0; i < allTrackInfo.length; i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.first != null) { // inband track allTrackInfo[i] = trackInfo[p.first]; } else { SubtitleTrack track = p.second; allTrackInfo[i] = new TrackInfo(track.getTrackType(), track.getFormat()); } } return allTrackInfo; } } private TrackInfo[] getInbandTrackInfo() throws IllegalStateException { Parcel request = Parcel.obtain(); Loading Loading @@ -2167,24 +2184,23 @@ public class MediaPlayer implements SubtitleController.Listener } } private final Object mInbandSubtitleLock = new Object(); private SubtitleTrack[] mInbandSubtitleTracks; private int mSelectedSubtitleTrackIndex = -1; private Vector<SubtitleTrack> mOutOfBandSubtitleTracks; private Vector<InputStream> mOpenSubtitleSources; private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() { @Override public void onSubtitleData(MediaPlayer mp, SubtitleData data) { int index = data.getTrackIndex(); if (index >= mInbandSubtitleTracks.length) { return; } SubtitleTrack track = mInbandSubtitleTracks[index]; if (track != null) { synchronized (mIndexTrackPairs) { for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { if (p.first != null && p.first == index && p.second != null) { // inband subtitle track that owns data SubtitleTrack track = p.second; track.onData(data); } } } } }; /** @hide */ Loading @@ -2201,17 +2217,23 @@ public class MediaPlayer implements SubtitleController.Listener if (track == null) { return; } for (int i = 0; i < mInbandSubtitleTracks.length; i++) { if (mInbandSubtitleTracks[i] == track) { Log.v(TAG, "Selecting subtitle track " + i); mSelectedSubtitleTrackIndex = i; synchronized (mIndexTrackPairs) { for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) { if (p.first != null && p.second == track) { // inband subtitle track that is selected mSelectedSubtitleTrackIndex = p.first; break; } } } if (mSelectedSubtitleTrackIndex >= 0) { try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true); } catch (IllegalStateException e) { } setOnSubtitleDataListener(mSubtitleDataListener); break; } } // no need to select out-of-band tracks } Loading Loading @@ -2252,7 +2274,9 @@ public class MediaPlayer implements SubtitleController.Listener mOpenSubtitleSources.remove(fIs); } scanner.close(); mOutOfBandSubtitleTracks.add(track); synchronized (mIndexTrackPairs) { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); } track.onData(contents.getBytes(), true /* eos */, ~0 /* runID: keep forever */); return MEDIA_INFO_EXTERNAL_METADATA_UPDATE; } Loading @@ -2274,23 +2298,33 @@ public class MediaPlayer implements SubtitleController.Listener setSubtitleAnchor(); } populateInbandTracks(); if (mSubtitleController != null) { mSubtitleController.selectDefaultTrack(); } } private void populateInbandTracks() { TrackInfo[] tracks = getInbandTrackInfo(); synchronized (mInbandSubtitleLock) { SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length]; synchronized (mIndexTrackPairs) { for (int i = 0; i < tracks.length; i++) { if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { if (i < mInbandSubtitleTracks.length) { inbandTracks[i] = mInbandSubtitleTracks[i]; if (mInbandTrackIndices.get(i)) { continue; } else { mInbandTrackIndices.set(i); } // newly appeared inband track if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { SubtitleTrack track = mSubtitleController.addTrack( tracks[i].getFormat()); inbandTracks[i] = track; } mIndexTrackPairs.add(Pair.create(i, track)); } else { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(i, null)); } } mInbandSubtitleTracks = inbandTracks; } mSubtitleController.selectDefaultTrack(); } /* TODO: Limit the total number of external timed text source to a reasonable number. Loading Loading @@ -2438,7 +2472,9 @@ public class MediaPlayer implements SubtitleController.Listener mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler)); } final SubtitleTrack track = mSubtitleController.addTrack(fFormat); mOutOfBandSubtitleTracks.add(track); synchronized (mIndexTrackPairs) { mIndexTrackPairs.add(Pair.<Integer, SubtitleTrack>create(null, track)); } final FileDescriptor fd3 = fd2; final long offset2 = offset; Loading Loading @@ -2510,12 +2546,18 @@ public class MediaPlayer implements SubtitleController.Listener * @see #deselectTrack(int) */ public int getSelectedTrack(int trackType) throws IllegalStateException { if (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE && mSubtitleController != null) { if (mSubtitleController != null && (trackType == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT)) { SubtitleTrack subtitleTrack = mSubtitleController.getSelectedTrack(); if (subtitleTrack != null) { int index = mOutOfBandSubtitleTracks.indexOf(subtitleTrack); if (index >= 0) { return mInbandSubtitleTracks.length + index; synchronized (mIndexTrackPairs) { for (int i = 0; i < mIndexTrackPairs.size(); i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.second == subtitleTrack && subtitleTrack.getTrackType() == trackType) { return i; } } } } } Loading @@ -2527,8 +2569,16 @@ public class MediaPlayer implements SubtitleController.Listener request.writeInt(INVOKE_ID_GET_SELECTED_TRACK); request.writeInt(trackType); invoke(request, reply); int selectedTrack = reply.readInt(); return selectedTrack; int inbandTrackIndex = reply.readInt(); synchronized (mIndexTrackPairs) { for (int i = 0; i < mIndexTrackPairs.size(); i++) { Pair<Integer, SubtitleTrack> p = mIndexTrackPairs.get(i); if (p.first != null && p.first == inbandTrackIndex) { return i; } } } return -1; } finally { request.recycle(); reply.recycle(); Loading Loading @@ -2588,36 +2638,30 @@ public class MediaPlayer implements SubtitleController.Listener private void selectOrDeselectTrack(int index, boolean select) throws IllegalStateException { // handle subtitle track through subtitle controller SubtitleTrack track = null; synchronized (mInbandSubtitleLock) { if (mInbandSubtitleTracks.length == 0) { TrackInfo[] tracks = getInbandTrackInfo(); mInbandSubtitleTracks = new SubtitleTrack[tracks.length]; for (int i=0; i < tracks.length; i++) { if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { mInbandSubtitleTracks[i] = mSubtitleController.addTrack(tracks[i].getFormat()); } } } } populateInbandTracks(); if (index < mInbandSubtitleTracks.length) { track = mInbandSubtitleTracks[index]; } else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) { track = mOutOfBandSubtitleTracks.get(index - mInbandSubtitleTracks.length); Pair<Integer,SubtitleTrack> p = null; try { p = mIndexTrackPairs.get(index); } catch (ArrayIndexOutOfBoundsException e) { // ignore bad index return; } if (mSubtitleController != null && track != null) { if (select) { if (track.isTimedText()) { int ttIndex = getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); if (ttIndex >= 0 && ttIndex < mInbandSubtitleTracks.length) { // deselect inband counterpart selectOrDeselectInbandTrack(ttIndex, false); SubtitleTrack track = p.second; if (track == null) { // inband (de)select selectOrDeselectInbandTrack(p.first, select); return; } if (mSubtitleController == null) { return; } mSubtitleController.selectTrack(track); } else if (mSubtitleController.getSelectedTrack() == track) { if (!select) { // out-of-band deselect if (mSubtitleController.getSelectedTrack() == track) { mSubtitleController.selectTrack(null); } else { Log.w(TAG, "trying to deselect track that was not selected"); Loading @@ -2625,7 +2669,20 @@ public class MediaPlayer implements SubtitleController.Listener return; } selectOrDeselectInbandTrack(index, select); // out-of-band select if (track.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { int ttIndex = getSelectedTrack(TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); synchronized (mIndexTrackPairs) { if (ttIndex >= 0 && ttIndex < mIndexTrackPairs.size()) { Pair<Integer,SubtitleTrack> p2 = mIndexTrackPairs.get(ttIndex); if (p2.first != null && p2.second == null) { // deselect inband counterpart selectOrDeselectInbandTrack(p2.first, false); } } } } mSubtitleController.selectTrack(track); } private void selectOrDeselectInbandTrack(int index, boolean select) Loading
media/java/android/media/SubtitleController.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.util.Locale; import java.util.Vector; import android.content.Context; import android.media.MediaPlayer.TrackInfo; import android.media.SubtitleTrack.RenderingWidget; import android.os.Handler; import android.os.Looper; Loading Loading @@ -275,7 +276,8 @@ public class SubtitleController { mSelectedTrack.getFormat().getInteger( MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) { show(); } else if (mSelectedTrack != null && !mSelectedTrack.isTimedText()) { } else if (mSelectedTrack != null && mSelectedTrack.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) { hide(); } mVisibilityIsExplicit = false; Loading
media/java/android/media/SubtitleTrack.java +5 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.media; import android.graphics.Canvas; import android.media.MediaPlayer.TrackInfo; import android.os.Handler; import android.util.Log; import android.util.LongSparseArray; Loading Loading @@ -609,8 +610,10 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide whether this is a text track who fires events instead getting rendered */ public boolean isTimedText() { return getRenderingWidget() == null; public int getTrackType() { return getRenderingWidget() == null ? TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT : TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE; } Loading