1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.media; 6 7 import android.content.Context; 8 import android.media.AudioManager; 9 import android.media.MediaPlayer; 10 11 import org.chromium.base.CalledByNative; 12 import org.chromium.base.JNINamespace; 13 14 // This class implements all the listener interface for android mediaplayer. 15 // Callbacks will be sent to the native class for processing. 16 @JNINamespace("media") 17 class MediaPlayerListener implements MediaPlayer.OnPreparedListener, 18 MediaPlayer.OnCompletionListener, 19 MediaPlayer.OnBufferingUpdateListener, 20 MediaPlayer.OnSeekCompleteListener, 21 MediaPlayer.OnVideoSizeChangedListener, 22 MediaPlayer.OnErrorListener, 23 AudioManager.OnAudioFocusChangeListener { 24 // These values are mirrored as enums in media/base/android/media_player_bridge.h. 25 // Please ensure they stay in sync. 26 private static final int MEDIA_ERROR_FORMAT = 0; 27 private static final int MEDIA_ERROR_DECODE = 1; 28 private static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 2; 29 private static final int MEDIA_ERROR_INVALID_CODE = 3; 30 31 // These values are copied from android media player. 32 public static final int MEDIA_ERROR_MALFORMED = -1007; 33 public static final int MEDIA_ERROR_TIMED_OUT = -110; 34 35 // Used to determine the class instance to dispatch the native call to. 36 private long mNativeMediaPlayerListener = 0; 37 private final Context mContext; 38 MediaPlayerListener(long nativeMediaPlayerListener, Context context)39 private MediaPlayerListener(long nativeMediaPlayerListener, Context context) { 40 mNativeMediaPlayerListener = nativeMediaPlayerListener; 41 mContext = context; 42 } 43 44 @Override onError(MediaPlayer mp, int what, int extra)45 public boolean onError(MediaPlayer mp, int what, int extra) { 46 int errorType; 47 switch (what) { 48 case MediaPlayer.MEDIA_ERROR_UNKNOWN: 49 switch (extra) { 50 case MEDIA_ERROR_MALFORMED: 51 errorType = MEDIA_ERROR_DECODE; 52 break; 53 case MEDIA_ERROR_TIMED_OUT: 54 errorType = MEDIA_ERROR_INVALID_CODE; 55 break; 56 default: 57 errorType = MEDIA_ERROR_FORMAT; 58 break; 59 } 60 break; 61 case MediaPlayer.MEDIA_ERROR_SERVER_DIED: 62 errorType = MEDIA_ERROR_DECODE; 63 break; 64 case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: 65 errorType = MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK; 66 break; 67 default: 68 // There are some undocumented error codes for android media player. 69 // For example, when surfaceTexture got deleted before we setVideoSuface 70 // to NULL, mediaplayer will report error -38. These errors should be ignored 71 // and not be treated as an error to webkit. 72 errorType = MEDIA_ERROR_INVALID_CODE; 73 break; 74 } 75 nativeOnMediaError(mNativeMediaPlayerListener, errorType); 76 return true; 77 } 78 79 @Override onVideoSizeChanged(MediaPlayer mp, int width, int height)80 public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 81 nativeOnVideoSizeChanged(mNativeMediaPlayerListener, width, height); 82 } 83 84 @Override onSeekComplete(MediaPlayer mp)85 public void onSeekComplete(MediaPlayer mp) { 86 nativeOnSeekComplete(mNativeMediaPlayerListener); 87 } 88 89 @Override onBufferingUpdate(MediaPlayer mp, int percent)90 public void onBufferingUpdate(MediaPlayer mp, int percent) { 91 nativeOnBufferingUpdate(mNativeMediaPlayerListener, percent); 92 } 93 94 @Override onCompletion(MediaPlayer mp)95 public void onCompletion(MediaPlayer mp) { 96 nativeOnPlaybackComplete(mNativeMediaPlayerListener); 97 } 98 99 @Override onPrepared(MediaPlayer mp)100 public void onPrepared(MediaPlayer mp) { 101 nativeOnMediaPrepared(mNativeMediaPlayerListener); 102 } 103 104 @Override onAudioFocusChange(int focusChange)105 public void onAudioFocusChange(int focusChange) { 106 if (focusChange == AudioManager.AUDIOFOCUS_LOSS || 107 focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 108 nativeOnMediaInterrupted(mNativeMediaPlayerListener); 109 } 110 } 111 112 @CalledByNative releaseResources()113 public void releaseResources() { 114 if (mContext != null) { 115 // Unregister the wish for audio focus. 116 AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 117 if (am != null) { 118 am.abandonAudioFocus(this); 119 } 120 } 121 } 122 123 @CalledByNative create(int nativeMediaPlayerListener, Context context, MediaPlayerBridge mediaPlayerBridge)124 private static MediaPlayerListener create(int nativeMediaPlayerListener, 125 Context context, MediaPlayerBridge mediaPlayerBridge) { 126 final MediaPlayerListener listener = 127 new MediaPlayerListener(nativeMediaPlayerListener, context); 128 mediaPlayerBridge.setOnBufferingUpdateListener(listener); 129 mediaPlayerBridge.setOnCompletionListener(listener); 130 mediaPlayerBridge.setOnErrorListener(listener); 131 mediaPlayerBridge.setOnPreparedListener(listener); 132 mediaPlayerBridge.setOnSeekCompleteListener(listener); 133 mediaPlayerBridge.setOnVideoSizeChangedListener(listener); 134 135 AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 136 am.requestAudioFocus( 137 listener, 138 AudioManager.STREAM_MUSIC, 139 140 // Request permanent focus. 141 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); 142 return listener; 143 } 144 145 /** 146 * See media/base/android/media_player_listener.cc for all the following functions. 147 */ nativeOnMediaError( long nativeMediaPlayerListener, int errorType)148 private native void nativeOnMediaError( 149 long nativeMediaPlayerListener, 150 int errorType); 151 nativeOnVideoSizeChanged( long nativeMediaPlayerListener, int width, int height)152 private native void nativeOnVideoSizeChanged( 153 long nativeMediaPlayerListener, 154 int width, int height); 155 nativeOnBufferingUpdate( long nativeMediaPlayerListener, int percent)156 private native void nativeOnBufferingUpdate( 157 long nativeMediaPlayerListener, 158 int percent); 159 nativeOnMediaPrepared(long nativeMediaPlayerListener)160 private native void nativeOnMediaPrepared(long nativeMediaPlayerListener); 161 nativeOnPlaybackComplete(long nativeMediaPlayerListener)162 private native void nativeOnPlaybackComplete(long nativeMediaPlayerListener); 163 nativeOnSeekComplete(long nativeMediaPlayerListener)164 private native void nativeOnSeekComplete(long nativeMediaPlayerListener); 165 nativeOnMediaInterrupted(long nativeMediaPlayerListener)166 private native void nativeOnMediaInterrupted(long nativeMediaPlayerListener); 167 } 168