summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/widget/VideoView.java68
-rw-r--r--media/java/android/media/MediaPlayer.java12
3 files changed, 81 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index 458c577..4c18909 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12892,7 +12892,9 @@ package android.media {
field public static final int MEDIA_INFO_BUFFERING_START = 701; // 0x2bd
field public static final int MEDIA_INFO_METADATA_UPDATE = 802; // 0x322
field public static final int MEDIA_INFO_NOT_SEEKABLE = 801; // 0x321
+ field public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; // 0x386
field public static final int MEDIA_INFO_UNKNOWN = 1; // 0x1
+ field public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; // 0x385
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
@@ -32659,6 +32661,7 @@ package android.widget {
ctor public VideoView(android.content.Context);
ctor public VideoView(android.content.Context, android.util.AttributeSet);
ctor public VideoView(android.content.Context, android.util.AttributeSet, int);
+ method public void addSubtitleSource(java.io.InputStream, android.media.MediaFormat);
method public boolean canPause();
method public boolean canSeekBackward();
method public boolean canSeekForward();
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index ebf9fe0..855ce12 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -22,11 +22,12 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.media.AudioManager;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
-import android.media.Metadata;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
+import android.media.Metadata;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
@@ -40,7 +41,9 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.MediaController.MediaPlayerControl;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Map;
+import java.util.Vector;
/**
* Displays a video file. The VideoView class
@@ -194,6 +197,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
+ mPendingSubtitleTracks = 0;
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
}
@@ -218,6 +222,47 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
invalidate();
}
+ /**
+ * Adds an external subtitle source file (from the provided input stream.)
+ *
+ * Note that a single external subtitle source may contain multiple or no
+ * supported tracks in it. If the source contained at least one track in
+ * it, one will receive an {@link MediaPlayer#MEDIA_INFO_METADATA_UPDATE}
+ * info message. Otherwise, if reading the source takes excessive time,
+ * one will receive a {@link MediaPlayer#MEDIA_INFO_SUBTITLE_TIMED_OUT}
+ * message. If the source contained no supported track (including an empty
+ * source file or null input stream), one will receive a {@link
+ * MediaPlayer#MEDIA_INFO_UNSUPPORTED_SUBTITLE} message. One can find the
+ * total number of available tracks using {@link MediaPlayer#getTrackInfo()}
+ * to see what additional tracks become available after this method call.
+ *
+ * @param is input stream containing the subtitle data. It will be
+ * closed by the media framework.
+ * @param format the format of the subtitle track(s). Must contain at least
+ * the mime type ({@link MediaFormat#KEY_MIME}) and the
+ * language ({@link MediaFormat#KEY_LANGUAGE}) of the file.
+ * If the file itself contains the language information,
+ * specify "und" for the language.
+ */
+ public void addSubtitleSource(InputStream is, MediaFormat format) {
+ // always signal unsupported message for now
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (IOException e) {
+ }
+
+ if (mMediaPlayer == null) {
+ ++mPendingSubtitleTracks;
+ } else {
+ mInfoListener.onInfo(
+ mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0);
+ }
+ }
+
+ private int mPendingSubtitleTracks;
+
public void stopPlayback() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
@@ -253,7 +298,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
- mMediaPlayer.setOnInfoListener(mOnInfoListener);
+ mMediaPlayer.setOnInfoListener(mInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
@@ -261,6 +306,12 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
+
+ for (int ix = 0; ix < mPendingSubtitleTracks; ix++) {
+ mInfoListener.onInfo(
+ mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0);
+ }
+
// we don't set the target state here either, but preserve the
// target state that was there before.
mCurrentState = STATE_PREPARING;
@@ -277,6 +328,8 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
+ } finally {
+ mPendingSubtitleTracks = 0;
}
}
@@ -386,6 +439,16 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
}
};
+ private MediaPlayer.OnInfoListener mInfoListener =
+ new MediaPlayer.OnInfoListener() {
+ public boolean onInfo(MediaPlayer mp, int arg1, int arg2) {
+ if (mOnInfoListener != null) {
+ mOnInfoListener.onInfo(mp, arg1, arg2);
+ }
+ return true;
+ }
+ };
+
private MediaPlayer.OnErrorListener mErrorListener =
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
@@ -530,6 +593,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
+ mPendingSubtitleTracks = 0;
mCurrentState = STATE_IDLE;
if (cleartargetstate) {
mTargetState = STATE_IDLE;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 946dd71..1b9bdaf 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2382,6 +2382,16 @@ public class MediaPlayer
*/
public static final int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
+ /** Subtitle track was not supported by the media framework.
+ * @see android.media.MediaPlayer.OnInfoListener
+ */
+ public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
+
+ /** Reading the subtitle track takes too long.
+ * @see android.media.MediaPlayer.OnInfoListener
+ */
+ public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
+
/**
* Interface definition of a callback to be invoked to communicate some
* info and/or warning about the media or its playback.
@@ -2402,6 +2412,8 @@ public class MediaPlayer
* <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
* <li>{@link #MEDIA_INFO_NOT_SEEKABLE}
* <li>{@link #MEDIA_INFO_METADATA_UPDATE}
+ * <li>{@link #MEDIA_INFO_UNSUPPORTED_SUBTITLE}
+ * <li>{@link #MEDIA_INFO_SUBTITLE_TIMED_OUT}
* </ul>
* @param extra an extra code, specific to the info. Typically
* implementation dependent.