Loading api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12758,6 +12758,9 @@ package android.media { field public static final java.lang.String KEY_FRAME_RATE = "frame-rate"; field public static final java.lang.String KEY_HEIGHT = "height"; field public static final java.lang.String KEY_IS_ADTS = "is-adts"; field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect"; field public static final java.lang.String KEY_IS_DEFAULT = "is-default"; field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle"; field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval"; field public static final java.lang.String KEY_LANGUAGE = "language"; field public static final java.lang.String KEY_MAX_HEIGHT = "max-height"; media/java/android/media/MediaFormat.java +23 −13 Original line number Diff line number Diff line Loading @@ -222,26 +222,36 @@ public final class MediaFormat { public static final String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level"; /** * A key for boolean AUTOSELECT field. Tracks with AUTOSELECT=true are * considered when automatically selecting a track without specific user * choice (as defined by HLS). * @hide * A key for boolean AUTOSELECT behavior for the track. Tracks with AUTOSELECT=true * are considered when automatically selecting a track without specific user * choice, based on the current locale. * This is currently only used for subtitle tracks, when the user selected * 'Default' for the captioning locale. * The associated value is an integer, where non-0 means TRUE. This is an optional * field; if not specified, AUTOSELECT defaults to TRUE. */ public static final String KEY_AUTOSELECT = "autoselect"; public static final String KEY_IS_AUTOSELECT = "is-autoselect"; /** * A key for boolean DEFAULT field. The track with DEFAULT=true is selected * in the absence of a specific user choice (as defined by HLS). * @hide * A key for boolean DEFAULT behavior for the track. The track with DEFAULT=true is * selected in the absence of a specific user choice. * This is currently only used for subtitle tracks, when the user selected * 'Default' for the captioning locale. * The associated value is an integer, where non-0 means TRUE. This is an optional * field; if not specified, DEFAULT is considered to be FALSE. */ public static final String KEY_DEFAULT = "default"; public static final String KEY_IS_DEFAULT = "is-default"; /** * A key for boolean FORCED field for subtitle tracks. True if it is a * forced subtitle track. * @hide * A key for the FORCED field for subtitle tracks. True if it is a * forced subtitle track. Forced subtitle tracks are essential for the * content and are shown even when the user turns off Captions. They * are used for example to translate foreign/alien dialogs or signs. * The associated value is an integer, where non-0 means TRUE. This is an * optional field; if not specified, FORCED defaults to FALSE. */ public static final String KEY_FORCED = "forced"; public static final String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle"; /* package private */ MediaFormat(Map<String, Object> map) { mMap = map; Loading media/java/android/media/MediaPlayer.java +36 −13 Original line number Diff line number Diff line Loading @@ -1606,9 +1606,9 @@ public class MediaPlayer implements SubtitleController.Listener } else if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { mFormat = MediaFormat.createSubtitleFormat( MEDIA_MIMETYPE_TEXT_VTT, language); mFormat.setInteger(MediaFormat.KEY_AUTOSELECT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_DEFAULT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_FORCED, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt()); } else { mFormat = new MediaFormat(); mFormat.setString(MediaFormat.KEY_LANGUAGE, language); Loading Loading @@ -1638,9 +1638,9 @@ public class MediaPlayer implements SubtitleController.Listener dest.writeString(getLanguage()); if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { dest.writeInt(mFormat.getInteger(MediaFormat.KEY_AUTOSELECT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_DEFAULT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_FORCED)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE)); } } Loading Loading @@ -1765,15 +1765,21 @@ public class MediaPlayer implements SubtitleController.Listener @Override public void onSubtitleTrackSelected(SubtitleTrack track) { if (mSelectedSubtitleTrackIndex >= 0) { deselectTrack(mSelectedSubtitleTrackIndex); try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, false); } catch (IllegalStateException e) { } mSelectedSubtitleTrackIndex = -1; } setOnSubtitleDataListener(null); for (int i = 0; i < mInbandSubtitleTracks.length; i++) { if (mInbandSubtitleTracks[i] == track) { Log.v(TAG, "Selecting subtitle track " + i); selectTrack(i); mSelectedSubtitleTrackIndex = i; try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true); } catch (IllegalStateException e) { } setOnSubtitleDataListener(mSubtitleDataListener); break; } Loading Loading @@ -2046,13 +2052,30 @@ public class MediaPlayer implements SubtitleController.Listener private void selectOrDeselectTrack(int index, boolean select) throws IllegalStateException { // ignore out-of-band tracks TrackInfo[] trackInfo = getInbandTrackInfo(); if (index >= trackInfo.length && index < trackInfo.length + mOutOfBandSubtitleTracks.size()) { // handle subtitle track through subtitle controller SubtitleTrack track = null; if (index < mInbandSubtitleTracks.length) { track = mInbandSubtitleTracks[index]; } else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) { track = mOutOfBandSubtitleTracks.get(index - mInbandSubtitleTracks.length); } if (mSubtitleController != null && track != null) { if (select) { mSubtitleController.selectTrack(track); } else if (mSubtitleController.getSelectedTrack() == track) { mSubtitleController.selectTrack(null); } else { Log.w(TAG, "trying to deselect track that was not selected"); } return; } selectOrDeselectInbandTrack(index, select); } private void selectOrDeselectInbandTrack(int index, boolean select) throws IllegalStateException { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { Loading media/java/android/media/SubtitleController.java +144 −35 Original line number Diff line number Diff line Loading @@ -38,6 +38,21 @@ public class SubtitleController { private boolean mShowing; private CaptioningManager mCaptioningManager; private CaptioningManager.CaptioningChangeListener mCaptioningChangeListener = new CaptioningManager.CaptioningChangeListener() { /** @hide */ @Override public void onEnabledChanged(boolean enabled) { selectDefaultTrack(); } /** @hide */ @Override public void onLocaleChanged(Locale locale) { selectDefaultTrack(); } }; /** * Creates a subtitle controller for a media playback object that implements * the MediaTimeProvider interface. Loading @@ -58,16 +73,25 @@ public class SubtitleController { (CaptioningManager)context.getSystemService(Context.CAPTIONING_SERVICE); } @Override protected void finalize() throws Throwable { mCaptioningManager.removeCaptioningChangeListener( mCaptioningChangeListener); super.finalize(); } /** * @return the available subtitle tracks for this media. These include * the tracks found by {@link MediaPlayer} as well as any tracks added * manually via {@link #addTrack}. */ public SubtitleTrack[] getTracks() { synchronized(mTracks) { SubtitleTrack[] tracks = new SubtitleTrack[mTracks.size()]; mTracks.toArray(tracks); return tracks; } } /** * @return the currently selected subtitle track Loading @@ -88,6 +112,8 @@ public class SubtitleController { * in-band data from the {@link MediaPlayer}. However, this does * not change the subtitle visibility. * * Must be called from the UI thread. * * @param track The subtitle track to select. This must be one of the * tracks in {@link #getTracks}. * @return true if the track was successfully selected. Loading @@ -107,7 +133,9 @@ public class SubtitleController { } mSelectedTrack = track; if (mAnchor != null) { mAnchor.setSubtitleWidget(getRenderingWidget()); } if (mSelectedTrack != null) { mSelectedTrack.setTimeProvider(mTimeProvider); Loading @@ -123,56 +151,123 @@ public class SubtitleController { /** * @return the default subtitle track based on system preferences, or null, * if no such track exists in this manager. * * Supports HLS-flags: AUTOSELECT, FORCED & DEFAULT. * * 1. If captioning is disabled, only consider FORCED tracks. Otherwise, * consider all tracks, but prefer non-FORCED ones. * 2. If user selected "Default" caption language: * a. If there is a considered track with DEFAULT=yes, returns that track * (favor the first one in the current language if there are more than * one default tracks, or the first in general if none of them are in * the current language). * b. Otherwise, if there is a track with AUTOSELECT=yes in the current * language, return that one. * c. If there are no default tracks, and no autoselectable tracks in the * current language, return null. * 3. If there is a track with the caption language, select that one. Prefer * the one with AUTOSELECT=no. * * The default values for these flags are DEFAULT=no, AUTOSELECT=yes * and FORCED=no. * * Must be called from the UI thread. */ public SubtitleTrack getDefaultTrack() { Locale locale = mCaptioningManager.getLocale(); SubtitleTrack bestTrack = null; int bestScore = -1; Locale selectedLocale = mCaptioningManager.getLocale(); Locale locale = selectedLocale; if (locale == null) { locale = Locale.getDefault(); } boolean selectForced = !mCaptioningManager.isEnabled(); synchronized(mTracks) { for (SubtitleTrack track: mTracks) { MediaFormat format = track.getFormat(); String language = format.getString(MediaFormat.KEY_LANGUAGE); // TODO: select track with best renderer. For now, we select first // track with local's language or first track if locale has none if (locale == null || boolean forced = format.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0; boolean autoselect = format.getInteger(MediaFormat.KEY_IS_AUTOSELECT, 1) != 0; boolean is_default = format.getInteger(MediaFormat.KEY_IS_DEFAULT, 0) != 0; boolean languageMatches = (locale == null || locale.getLanguage().equals("") || locale.getISO3Language().equals(language) || locale.getLanguage().equals(language)) { return track; locale.getLanguage().equals(language)); // is_default is meaningless unless caption language is 'default' int score = (forced ? 0 : 8) + (((selectedLocale == null) && is_default) ? 4 : 0) + (autoselect ? 0 : 2) + (languageMatches ? 1 : 0); if (selectForced && !forced) { continue; } // we treat null locale/language as matching any language if ((selectedLocale == null && is_default) || (languageMatches && (autoselect || forced || selectedLocale != null))) { if (score > bestScore) { bestScore = score; bestTrack = track; } return null; } } } return bestTrack; } private boolean mTrackIsExplicit = false; private boolean mVisibilityIsExplicit = false; /** @hide */ /** @hide - called from UI thread */ public void selectDefaultTrack() { if (mTrackIsExplicit) { // If track selection is explicit, but visibility // is not, it falls back to the captioning setting if (!mVisibilityIsExplicit) { if (mCaptioningManager.isEnabled() || (mSelectedTrack != null && mSelectedTrack.getFormat().getInteger( MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) { show(); } else { hide(); } mVisibilityIsExplicit = false; } return; } // We can have a default (forced) track even if captioning // is not enabled. This is handled by getDefaultTrack(). // Show this track unless subtitles were explicitly hidden. SubtitleTrack track = getDefaultTrack(); if (track != null) { selectTrack(track); mTrackIsExplicit = false; if (!mVisibilityIsExplicit) { if (mCaptioningManager.isEnabled()) { show(); } else { hide(); } mVisibilityIsExplicit = false; } } } /** @hide */ /** @hide - called from UI thread */ public void reset() { hide(); selectTrack(null); mTracks.clear(); mTrackIsExplicit = false; mVisibilityIsExplicit = false; mCaptioningManager.removeCaptioningChangeListener( mCaptioningChangeListener); } /** Loading @@ -183,20 +278,30 @@ public class SubtitleController { * @return the created {@link SubtitleTrack} object */ public SubtitleTrack addTrack(MediaFormat format) { synchronized(mRenderers) { for (Renderer renderer: mRenderers) { if (renderer.supports(format)) { SubtitleTrack track = renderer.createTrack(format); if (track != null) { synchronized(mTracks) { if (mTracks.size() == 0) { mCaptioningManager.addCaptioningChangeListener( mCaptioningChangeListener); } mTracks.add(track); } return track; } } } } return null; } /** * Show the selected (or default) subtitle track. * * Must be called from the UI thread. */ public void show() { mShowing = true; Loading @@ -208,6 +313,8 @@ public class SubtitleController { /** * Hide the selected (or default) subtitle track. * * Must be called from the UI thread. */ public void hide() { mVisibilityIsExplicit = true; Loading Loading @@ -257,12 +364,14 @@ public class SubtitleController { * support for a subtitle format. */ public void registerRenderer(Renderer renderer) { synchronized(mRenderers) { // TODO how to get available renderers in the system if (!mRenderers.contains(renderer)) { // TODO should added renderers override existing ones (to allow replacing?) mRenderers.add(renderer); } } } /** * Subtitle anchor, an object that is able to display a subtitle renderer, Loading @@ -279,7 +388,7 @@ public class SubtitleController { private Anchor mAnchor; /** @hide */ /** @hide - called from UI thread */ public void setAnchor(Anchor anchor) { if (mAnchor == anchor) { return; Loading media/java/android/media/SubtitleTrack.java +3 −3 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public MediaFormat getFormat() { public final MediaFormat getFormat() { return mFormat; } Loading Loading @@ -201,7 +201,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public void scheduleTimedEvents() { protected void scheduleTimedEvents() { /* get times for the next event */ if (mTimeProvider != null) { mNextScheduledTimeMs = mCues.nextTimeAfter(mLastTimeMs); Loading Loading @@ -363,7 +363,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public void setTimeProvider(MediaTimeProvider timeProvider) { public synchronized void setTimeProvider(MediaTimeProvider timeProvider) { if (mTimeProvider == timeProvider) { return; } Loading Loading
api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -12758,6 +12758,9 @@ package android.media { field public static final java.lang.String KEY_FRAME_RATE = "frame-rate"; field public static final java.lang.String KEY_HEIGHT = "height"; field public static final java.lang.String KEY_IS_ADTS = "is-adts"; field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect"; field public static final java.lang.String KEY_IS_DEFAULT = "is-default"; field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle"; field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval"; field public static final java.lang.String KEY_LANGUAGE = "language"; field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
media/java/android/media/MediaFormat.java +23 −13 Original line number Diff line number Diff line Loading @@ -222,26 +222,36 @@ public final class MediaFormat { public static final String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level"; /** * A key for boolean AUTOSELECT field. Tracks with AUTOSELECT=true are * considered when automatically selecting a track without specific user * choice (as defined by HLS). * @hide * A key for boolean AUTOSELECT behavior for the track. Tracks with AUTOSELECT=true * are considered when automatically selecting a track without specific user * choice, based on the current locale. * This is currently only used for subtitle tracks, when the user selected * 'Default' for the captioning locale. * The associated value is an integer, where non-0 means TRUE. This is an optional * field; if not specified, AUTOSELECT defaults to TRUE. */ public static final String KEY_AUTOSELECT = "autoselect"; public static final String KEY_IS_AUTOSELECT = "is-autoselect"; /** * A key for boolean DEFAULT field. The track with DEFAULT=true is selected * in the absence of a specific user choice (as defined by HLS). * @hide * A key for boolean DEFAULT behavior for the track. The track with DEFAULT=true is * selected in the absence of a specific user choice. * This is currently only used for subtitle tracks, when the user selected * 'Default' for the captioning locale. * The associated value is an integer, where non-0 means TRUE. This is an optional * field; if not specified, DEFAULT is considered to be FALSE. */ public static final String KEY_DEFAULT = "default"; public static final String KEY_IS_DEFAULT = "is-default"; /** * A key for boolean FORCED field for subtitle tracks. True if it is a * forced subtitle track. * @hide * A key for the FORCED field for subtitle tracks. True if it is a * forced subtitle track. Forced subtitle tracks are essential for the * content and are shown even when the user turns off Captions. They * are used for example to translate foreign/alien dialogs or signs. * The associated value is an integer, where non-0 means TRUE. This is an * optional field; if not specified, FORCED defaults to FALSE. */ public static final String KEY_FORCED = "forced"; public static final String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle"; /* package private */ MediaFormat(Map<String, Object> map) { mMap = map; Loading
media/java/android/media/MediaPlayer.java +36 −13 Original line number Diff line number Diff line Loading @@ -1606,9 +1606,9 @@ public class MediaPlayer implements SubtitleController.Listener } else if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { mFormat = MediaFormat.createSubtitleFormat( MEDIA_MIMETYPE_TEXT_VTT, language); mFormat.setInteger(MediaFormat.KEY_AUTOSELECT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_DEFAULT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_FORCED, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.readInt()); mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.readInt()); } else { mFormat = new MediaFormat(); mFormat.setString(MediaFormat.KEY_LANGUAGE, language); Loading Loading @@ -1638,9 +1638,9 @@ public class MediaPlayer implements SubtitleController.Listener dest.writeString(getLanguage()); if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) { dest.writeInt(mFormat.getInteger(MediaFormat.KEY_AUTOSELECT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_DEFAULT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_FORCED)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT)); dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE)); } } Loading Loading @@ -1765,15 +1765,21 @@ public class MediaPlayer implements SubtitleController.Listener @Override public void onSubtitleTrackSelected(SubtitleTrack track) { if (mSelectedSubtitleTrackIndex >= 0) { deselectTrack(mSelectedSubtitleTrackIndex); try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, false); } catch (IllegalStateException e) { } mSelectedSubtitleTrackIndex = -1; } setOnSubtitleDataListener(null); for (int i = 0; i < mInbandSubtitleTracks.length; i++) { if (mInbandSubtitleTracks[i] == track) { Log.v(TAG, "Selecting subtitle track " + i); selectTrack(i); mSelectedSubtitleTrackIndex = i; try { selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true); } catch (IllegalStateException e) { } setOnSubtitleDataListener(mSubtitleDataListener); break; } Loading Loading @@ -2046,13 +2052,30 @@ public class MediaPlayer implements SubtitleController.Listener private void selectOrDeselectTrack(int index, boolean select) throws IllegalStateException { // ignore out-of-band tracks TrackInfo[] trackInfo = getInbandTrackInfo(); if (index >= trackInfo.length && index < trackInfo.length + mOutOfBandSubtitleTracks.size()) { // handle subtitle track through subtitle controller SubtitleTrack track = null; if (index < mInbandSubtitleTracks.length) { track = mInbandSubtitleTracks[index]; } else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) { track = mOutOfBandSubtitleTracks.get(index - mInbandSubtitleTracks.length); } if (mSubtitleController != null && track != null) { if (select) { mSubtitleController.selectTrack(track); } else if (mSubtitleController.getSelectedTrack() == track) { mSubtitleController.selectTrack(null); } else { Log.w(TAG, "trying to deselect track that was not selected"); } return; } selectOrDeselectInbandTrack(index, select); } private void selectOrDeselectInbandTrack(int index, boolean select) throws IllegalStateException { Parcel request = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { Loading
media/java/android/media/SubtitleController.java +144 −35 Original line number Diff line number Diff line Loading @@ -38,6 +38,21 @@ public class SubtitleController { private boolean mShowing; private CaptioningManager mCaptioningManager; private CaptioningManager.CaptioningChangeListener mCaptioningChangeListener = new CaptioningManager.CaptioningChangeListener() { /** @hide */ @Override public void onEnabledChanged(boolean enabled) { selectDefaultTrack(); } /** @hide */ @Override public void onLocaleChanged(Locale locale) { selectDefaultTrack(); } }; /** * Creates a subtitle controller for a media playback object that implements * the MediaTimeProvider interface. Loading @@ -58,16 +73,25 @@ public class SubtitleController { (CaptioningManager)context.getSystemService(Context.CAPTIONING_SERVICE); } @Override protected void finalize() throws Throwable { mCaptioningManager.removeCaptioningChangeListener( mCaptioningChangeListener); super.finalize(); } /** * @return the available subtitle tracks for this media. These include * the tracks found by {@link MediaPlayer} as well as any tracks added * manually via {@link #addTrack}. */ public SubtitleTrack[] getTracks() { synchronized(mTracks) { SubtitleTrack[] tracks = new SubtitleTrack[mTracks.size()]; mTracks.toArray(tracks); return tracks; } } /** * @return the currently selected subtitle track Loading @@ -88,6 +112,8 @@ public class SubtitleController { * in-band data from the {@link MediaPlayer}. However, this does * not change the subtitle visibility. * * Must be called from the UI thread. * * @param track The subtitle track to select. This must be one of the * tracks in {@link #getTracks}. * @return true if the track was successfully selected. Loading @@ -107,7 +133,9 @@ public class SubtitleController { } mSelectedTrack = track; if (mAnchor != null) { mAnchor.setSubtitleWidget(getRenderingWidget()); } if (mSelectedTrack != null) { mSelectedTrack.setTimeProvider(mTimeProvider); Loading @@ -123,56 +151,123 @@ public class SubtitleController { /** * @return the default subtitle track based on system preferences, or null, * if no such track exists in this manager. * * Supports HLS-flags: AUTOSELECT, FORCED & DEFAULT. * * 1. If captioning is disabled, only consider FORCED tracks. Otherwise, * consider all tracks, but prefer non-FORCED ones. * 2. If user selected "Default" caption language: * a. If there is a considered track with DEFAULT=yes, returns that track * (favor the first one in the current language if there are more than * one default tracks, or the first in general if none of them are in * the current language). * b. Otherwise, if there is a track with AUTOSELECT=yes in the current * language, return that one. * c. If there are no default tracks, and no autoselectable tracks in the * current language, return null. * 3. If there is a track with the caption language, select that one. Prefer * the one with AUTOSELECT=no. * * The default values for these flags are DEFAULT=no, AUTOSELECT=yes * and FORCED=no. * * Must be called from the UI thread. */ public SubtitleTrack getDefaultTrack() { Locale locale = mCaptioningManager.getLocale(); SubtitleTrack bestTrack = null; int bestScore = -1; Locale selectedLocale = mCaptioningManager.getLocale(); Locale locale = selectedLocale; if (locale == null) { locale = Locale.getDefault(); } boolean selectForced = !mCaptioningManager.isEnabled(); synchronized(mTracks) { for (SubtitleTrack track: mTracks) { MediaFormat format = track.getFormat(); String language = format.getString(MediaFormat.KEY_LANGUAGE); // TODO: select track with best renderer. For now, we select first // track with local's language or first track if locale has none if (locale == null || boolean forced = format.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0; boolean autoselect = format.getInteger(MediaFormat.KEY_IS_AUTOSELECT, 1) != 0; boolean is_default = format.getInteger(MediaFormat.KEY_IS_DEFAULT, 0) != 0; boolean languageMatches = (locale == null || locale.getLanguage().equals("") || locale.getISO3Language().equals(language) || locale.getLanguage().equals(language)) { return track; locale.getLanguage().equals(language)); // is_default is meaningless unless caption language is 'default' int score = (forced ? 0 : 8) + (((selectedLocale == null) && is_default) ? 4 : 0) + (autoselect ? 0 : 2) + (languageMatches ? 1 : 0); if (selectForced && !forced) { continue; } // we treat null locale/language as matching any language if ((selectedLocale == null && is_default) || (languageMatches && (autoselect || forced || selectedLocale != null))) { if (score > bestScore) { bestScore = score; bestTrack = track; } return null; } } } return bestTrack; } private boolean mTrackIsExplicit = false; private boolean mVisibilityIsExplicit = false; /** @hide */ /** @hide - called from UI thread */ public void selectDefaultTrack() { if (mTrackIsExplicit) { // If track selection is explicit, but visibility // is not, it falls back to the captioning setting if (!mVisibilityIsExplicit) { if (mCaptioningManager.isEnabled() || (mSelectedTrack != null && mSelectedTrack.getFormat().getInteger( MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) { show(); } else { hide(); } mVisibilityIsExplicit = false; } return; } // We can have a default (forced) track even if captioning // is not enabled. This is handled by getDefaultTrack(). // Show this track unless subtitles were explicitly hidden. SubtitleTrack track = getDefaultTrack(); if (track != null) { selectTrack(track); mTrackIsExplicit = false; if (!mVisibilityIsExplicit) { if (mCaptioningManager.isEnabled()) { show(); } else { hide(); } mVisibilityIsExplicit = false; } } } /** @hide */ /** @hide - called from UI thread */ public void reset() { hide(); selectTrack(null); mTracks.clear(); mTrackIsExplicit = false; mVisibilityIsExplicit = false; mCaptioningManager.removeCaptioningChangeListener( mCaptioningChangeListener); } /** Loading @@ -183,20 +278,30 @@ public class SubtitleController { * @return the created {@link SubtitleTrack} object */ public SubtitleTrack addTrack(MediaFormat format) { synchronized(mRenderers) { for (Renderer renderer: mRenderers) { if (renderer.supports(format)) { SubtitleTrack track = renderer.createTrack(format); if (track != null) { synchronized(mTracks) { if (mTracks.size() == 0) { mCaptioningManager.addCaptioningChangeListener( mCaptioningChangeListener); } mTracks.add(track); } return track; } } } } return null; } /** * Show the selected (or default) subtitle track. * * Must be called from the UI thread. */ public void show() { mShowing = true; Loading @@ -208,6 +313,8 @@ public class SubtitleController { /** * Hide the selected (or default) subtitle track. * * Must be called from the UI thread. */ public void hide() { mVisibilityIsExplicit = true; Loading Loading @@ -257,12 +364,14 @@ public class SubtitleController { * support for a subtitle format. */ public void registerRenderer(Renderer renderer) { synchronized(mRenderers) { // TODO how to get available renderers in the system if (!mRenderers.contains(renderer)) { // TODO should added renderers override existing ones (to allow replacing?) mRenderers.add(renderer); } } } /** * Subtitle anchor, an object that is able to display a subtitle renderer, Loading @@ -279,7 +388,7 @@ public class SubtitleController { private Anchor mAnchor; /** @hide */ /** @hide - called from UI thread */ public void setAnchor(Anchor anchor) { if (mAnchor == anchor) { return; Loading
media/java/android/media/SubtitleTrack.java +3 −3 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public MediaFormat getFormat() { public final MediaFormat getFormat() { return mFormat; } Loading Loading @@ -201,7 +201,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public void scheduleTimedEvents() { protected void scheduleTimedEvents() { /* get times for the next event */ if (mTimeProvider != null) { mNextScheduledTimeMs = mCues.nextTimeAfter(mLastTimeMs); Loading Loading @@ -363,7 +363,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList } /** @hide */ public void setTimeProvider(MediaTimeProvider timeProvider) { public synchronized void setTimeProvider(MediaTimeProvider timeProvider) { if (mTimeProvider == timeProvider) { return; } Loading