OSDN Git Service

VideoView: add addSubtitleSource
authorLajos Molnar <lajos@google.com>
Fri, 16 Aug 2013 03:56:53 +0000 (20:56 -0700)
committerLajos Molnar <lajos@google.com>
Fri, 30 Aug 2013 21:59:46 +0000 (14:59 -0700)
A way to add external subtitle file to VideoView.

Change-Id: Ic110238408550a5b4088851bc5da5e94eb58d831
Signed-off-by: Lajos Molnar <lajos@google.com>
Bug: 10326117

api/current.txt
core/java/android/widget/VideoView.java
media/java/android/media/MediaPlayer.java

index 27a8480..7149868 100644 (file)
@@ -12768,7 +12768,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";
@@ -32439,6 +32441,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();
index ebf9fe0..855ce12 100644 (file)
@@ -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;
index 946dd71..1b9bdaf 100644 (file)
@@ -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.