嗨,我正在研究 android 中的增强现实概念,使用 vouforia sdk 能够在 vedioplayback 示例中播放 vedios,在 vedioplay back 示例应用程序中使用 assets 文件夹用于不同的目标图像正在播放不同的视频,但我的问题是我需要播放不同的 youtube 视频针对不同的目标图像。
public class VideoPlayerHelper implements OnPreparedListener,
OnBufferingUpdateListener,
OnCompletionListener,
OnErrorListener
{
public static final int CURRENT_POSITION = -1;
private MediaPlayer mMediaPlayer = null;
private MEDIA_TYPE mVideoType = MEDIA_TYPE.UNKNOWN;
private SurfaceTexture mSurfaceTexture = null;
private int mCurrentBufferingPercentage = 0;
private String mMovieName = "";
private byte mTextureID = 0;
Intent mPlayerHelperActivityIntent = null;
private Activity mParentActivity = null;
private MEDIA_STATE mCurrentState = MEDIA_STATE.NOT_READY;
private boolean mShouldPlayImmediately = false;
private int mSeekPosition = CURRENT_POSITION;
private ReentrantLock mMediaPlayerLock = null;
private ReentrantLock mSurfaceTextureLock = null;
// This enum declares the possible states a media can have:
public enum MEDIA_STATE
{
REACHED_END (0),
PAUSED (1),
STOPPED (2),
PLAYING (3),
READY (4),
NOT_READY (5),
ERROR (6);
private int type;
MEDIA_STATE (int i)
{
this.type = i;
}
public int getNumericType()
{
return type;
}
}
// This enum declares what type of playback we can do, share with the team:
public enum MEDIA_TYPE
{
ON_TEXTURE (0),
FULLSCREEN (1),
ON_TEXTURE_FULLSCREEN (2),
UNKNOWN (3);
private int type;
MEDIA_TYPE (int i)
{
this.type = i;
}
public int getNumericType()
{
return type;
}
}
/** Initializes the VideoPlayerHelper object. */
public boolean init()
{
mMediaPlayerLock = new ReentrantLock();
mSurfaceTextureLock = new ReentrantLock();
return true;
}
/** Deinitializes the VideoPlayerHelper object. */
public boolean deinit()
{
unload();
mSurfaceTextureLock.lock();
mSurfaceTexture = null;
mSurfaceTextureLock.unlock();
return true;
}
/** Loads a movie from a file in the assets folder */
@SuppressLint("NewApi")
public boolean load(String filename, MEDIA_TYPE requestedType,
boolean playOnTextureImmediately, int seekPosition)
{
// If the client requests that we should be able to play ON_TEXTURE,
// then we need to create a MediaPlayer:
boolean canBeOnTexture = false;
boolean canBeFullscreen = false;
boolean result = false;
mMediaPlayerLock.lock();
mSurfaceTextureLock.lock();
// If the media has already been loaded then exit.
// The client must first call unload() before calling load again:
if ((mCurrentState == MEDIA_STATE.READY) || (mMediaPlayer != null))
{
DebugLog.LOGD("Already loaded");
}
else
{
if (((requestedType == MEDIA_TYPE.ON_TEXTURE) || // If the client requests on texture only
(requestedType == MEDIA_TYPE.ON_TEXTURE_FULLSCREEN)) && // or on texture with full screen
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)) // and this is an ICS device
{
if (mSurfaceTexture == null)
{
DebugLog.LOGD("Can't load file to ON_TEXTURE because the Surface Texture is not ready");
}
else
{
try
{
mMediaPlayer = new MediaPlayer();
// This example shows how to load the movie from the assets folder of the app
// However, if you would like to load the movie from the sdcard or from a network location
// simply comment the three lines below
AssetFileDescriptor afd = mParentActivity.getAssets().openFd(filename);
mMediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
afd.close();
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setSurface(new Surface(mSurfaceTexture));
canBeOnTexture = true;
mShouldPlayImmediately = playOnTextureImmediately;
}
catch (Exception e)
{
DebugLog.LOGE("Error while creating the MediaPlayer: " + e.toString());
mCurrentState = MEDIA_STATE.ERROR;
mMediaPlayerLock.unlock();
mSurfaceTextureLock.unlock();
return false;
}
}
}
else
{
try
{
// We need to verify that the file exists
AssetFileDescriptor afd = mParentActivity.getAssets().openFd(filename);
afd.close();
}
catch (Exception e)
{
DebugLog.LOGD("File does not exist");
mCurrentState = MEDIA_STATE.ERROR;
mMediaPlayerLock.unlock();
mSurfaceTextureLock.unlock();
return false;
}
}
// If the client requests that we should be able to play FULLSCREEN
// then we need to create a FullscreenPlaybackActivity
if ((requestedType == MEDIA_TYPE.FULLSCREEN) || (requestedType == MEDIA_TYPE.ON_TEXTURE_FULLSCREEN))
{
mPlayerHelperActivityIntent = new Intent(mParentActivity, FullscreenPlayback.class);
mPlayerHelperActivityIntent.setAction(android.content.Intent.ACTION_VIEW);
canBeFullscreen = true;
}
// We store the parameters for further use
mMovieName = filename;
mSeekPosition = seekPosition;
if (canBeFullscreen && canBeOnTexture) mVideoType = MEDIA_TYPE.ON_TEXTURE_FULLSCREEN;
else if (canBeFullscreen) { mVideoType = MEDIA_TYPE.FULLSCREEN; mCurrentState = MEDIA_STATE.READY; } // If it is pure fullscreen then we're ready otherwise we let the MediaPlayer load first
else if (canBeOnTexture) mVideoType = MEDIA_TYPE.ON_TEXTURE;
else mVideoType = MEDIA_TYPE.UNKNOWN;
result = true;
}
mSurfaceTextureLock.unlock();
mMediaPlayerLock.unlock();
return result;
}
/** Unloads the currently loaded movie
After this is called a new load() has to be invoked */
public boolean unload()
{
mMediaPlayerLock.lock();
if (mMediaPlayer != null) {
try
{
mMediaPlayer.stop();
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not start playback");
}
mMediaPlayer.release();
mMediaPlayer = null;
}
mMediaPlayerLock.unlock();
mCurrentState = MEDIA_STATE.NOT_READY;
mVideoType = MEDIA_TYPE.UNKNOWN;
return true;
}
/** Indicates whether the movie can be played on a texture */
public boolean isPlayableOnTexture()
{
if ((mVideoType == MEDIA_TYPE.ON_TEXTURE) || (mVideoType == MEDIA_TYPE.ON_TEXTURE_FULLSCREEN))
return true;
return false;
}
/** Indicates whether the movie can be played fullscreen */
public boolean isPlayableFullscreen()
{
if ((mVideoType == MEDIA_TYPE.FULLSCREEN) || (mVideoType == MEDIA_TYPE.ON_TEXTURE_FULLSCREEN))
return true;
return false;
}
/** Return the current status of the movie such as Playing, Paused or Not Ready */
MEDIA_STATE getStatus()
{
return mCurrentState;
}
/** Returns the width of the video frame */
public int getVideoWidth()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot get the video width if it is not playable on texture");
return -1;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot get the video width if it is not ready");
return -1;
}
int result=-1;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
result = mMediaPlayer.getVideoWidth();
mMediaPlayerLock.unlock();
return result;
}
/** Returns the height of the video frame */
public int getVideoHeight()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot get the video height if it is not playable on texture");
return -1;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot get the video height if it is not ready");
return -1;
}
int result=-1;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
result = mMediaPlayer.getVideoHeight();
mMediaPlayerLock.unlock();
return result;
}
/** Returns the length of the current movie */
public float getLength()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot get the video length if it is not playable on texture");
return -1;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot get the video length if it is not ready");
return -1;
}
int result=-1;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
result = mMediaPlayer.getDuration()/1000;
mMediaPlayerLock.unlock();
return result;
}
/** Request a movie to be played either full screen or on texture and at a given position */
public boolean play(boolean fullScreen, int seekPosition)
{
if (fullScreen)
{
// If the play request was for fullscreen playback
// We check first whether this was requested upon load time
if (!isPlayableFullscreen())
{
DebugLog.LOGD("Cannot play this video fullscreen, it was not requested on load");
return false;
}
if (isPlayableOnTexture())
{
// If it can also play on texture then we forward information such as whether
// it is currently playing (shouldPlayImmediately) and in which position
// it was being played previously (currentSeekPosition)
mMediaPlayerLock.lock();
if (mMediaPlayer == null)
{
mMediaPlayerLock.unlock();
return false;
}
if (mMediaPlayer.isPlaying())
mPlayerHelperActivityIntent.putExtra("shouldPlayImmediately", true);
else
mPlayerHelperActivityIntent.putExtra("shouldPlayImmediately", false);
try
{
mMediaPlayer.pause();
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not pause playback");
}
if (seekPosition != CURRENT_POSITION)
mPlayerHelperActivityIntent.putExtra("currentSeekPosition", seekPosition);
else
mPlayerHelperActivityIntent.putExtra("currentSeekPosition", mMediaPlayer.getCurrentPosition());
mMediaPlayerLock.unlock();
}
else
{
// If it cannot play on texture then we set these values to default
mPlayerHelperActivityIntent.putExtra("currentSeekPosition", 0);
mPlayerHelperActivityIntent.putExtra("shouldPlayImmediately", true);
if (seekPosition != CURRENT_POSITION)
mPlayerHelperActivityIntent.putExtra("currentSeekPosition", seekPosition);
else
mPlayerHelperActivityIntent.putExtra("currentSeekPosition", 0);
}
// We must pass the current playback orientation of the activity
// and the name of the movie currently being played
mPlayerHelperActivityIntent.putExtra("requestedOrientation", mParentActivity.getRequestedOrientation());
mPlayerHelperActivityIntent.putExtra("movieName", mMovieName);
mParentActivity.startActivityForResult(mPlayerHelperActivityIntent,1);
return true;
}
else
{
// If the client requested playback on texture
// we must first verify that it is possible
if (!isPlayableOnTexture())
{
DebugLog.LOGD("Cannot play this video on texture, it was either not requested on load or is not supported on this plattform");
return false;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
DebugLog.LOGD("Cannot play this video if it is not ready");
return false;
}
mMediaPlayerLock.lock();
// If the client requests a given position
if (seekPosition != CURRENT_POSITION)
{
try
{
mMediaPlayer.seekTo(seekPosition);
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not seek to position");
}
}
else // If it had reached the end loop it back
{
if (mCurrentState == MEDIA_STATE.REACHED_END)
{
try
{
mMediaPlayer.seekTo(0);
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not seek to position");
}
}
}
// Then simply start playing
try
{
mMediaPlayer.start();
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not start playback");
}
mCurrentState = MEDIA_STATE.PLAYING;
mMediaPlayerLock.unlock();
return true;
}
}
/** Pauses the current movie being played */
public boolean pause()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot pause this video since it is not on texture");
return false;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot pause this video if it is not ready");
return false;
}
boolean result = false;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
{
if (mMediaPlayer.isPlaying())
{
try
{
mMediaPlayer.pause();
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not pause playback");
}
mCurrentState = MEDIA_STATE.PAUSED;
result = true;
}
}
mMediaPlayerLock.unlock();
return result;
}
/** Stops the current movie being played */
public boolean stop()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot stop this video since it is not on texture");
return false;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot stop this video if it is not ready");
return false;
}
boolean result = false;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
{
mCurrentState = MEDIA_STATE.STOPPED;
try
{
mMediaPlayer.stop();
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not stop playback");
}
result = true;
}
mMediaPlayerLock.unlock();
return result;
}
/** Tells the VideoPlayerHelper to update the data from the video feed */
@SuppressLint("NewApi")
public byte updateVideoData()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot update the data of this video since it is not on texture");
return -1;
}
byte result = -1;
mSurfaceTextureLock.lock();
if (mSurfaceTexture != null)
{
// Only request an update if currently playing
if (mCurrentState == MEDIA_STATE.PLAYING)
mSurfaceTexture.updateTexImage();
result = mTextureID;
}
mSurfaceTextureLock.unlock();
return result;
}
/** Moves the movie to the requested seek position */
public boolean seekTo(int position)
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot seek-to on this video since it is not on texture");
return false;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot seek-to on this video if it is not ready");
return false;
}
boolean result = false;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
{
try
{
mMediaPlayer.seekTo(position);
}
catch (Exception e)
{
mMediaPlayerLock.unlock();
DebugLog.LOGE("Could not seek to position");
}
result = true;
}
mMediaPlayerLock.unlock();
return result;
}
/** Gets the current seek position */
public int getCurrentPosition()
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot get the current playback position of this video since it is not on texture");
return -1;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot get the current playback position of this video if it is not ready");
return -1;
}
int result = -1;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
result = mMediaPlayer.getCurrentPosition();
mMediaPlayerLock.unlock();
return result;
}
/** Sets the volume of the movie to the desired value */
public boolean setVolume(float value)
{
if (!isPlayableOnTexture())
{
// DebugLog.LOGD("Cannot set the volume of this video since it is not on texture");
return false;
}
if ((mCurrentState == MEDIA_STATE.NOT_READY) || (mCurrentState == MEDIA_STATE.ERROR))
{
// DebugLog.LOGD("Cannot set the volume of this video if it is not ready");
return false;
}
boolean result = false;
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
{
mMediaPlayer.setVolume(value, value);
result = true;
}
mMediaPlayerLock.unlock();
return result;
}
/**
* The following functions are specific to Android
* and will likely not be implemented on other platforms
*/
/** Gets the buffering percentage in case the movie is loaded from network */
public int getCurrentBufferingPercentage()
{
return mCurrentBufferingPercentage;
}
/** Listener call for buffering */
public void onBufferingUpdate(MediaPlayer arg0, int arg1) {
//DebugLog.LOGD("onBufferingUpdate " + arg1);
mMediaPlayerLock.lock();
if (mMediaPlayer != null)
{
if (arg0 == mMediaPlayer)
mCurrentBufferingPercentage = arg1;
}
mMediaPlayerLock.unlock();
}
/** With this we can set the parent activity */
public void setActivity(Activity newActivity)
{
mParentActivity = newActivity;
}
/** To set a value upon completion */
public void onCompletion(MediaPlayer arg0) {
// Signal that the video finished playing
mCurrentState = MEDIA_STATE.REACHED_END;
}
/** Used to set up the surface texture*/
@SuppressLint("NewApi")
public boolean setupSurfaceTexture(int nativeTextureID)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
// We create a surface texture where the video can be played
// We have to give it a texture id of an already created (in native) // OpenGL texture
mSurfaceTextureLock.lock();
mSurfaceTexture = new SurfaceTexture(nativeTextureID);
mTextureID = (byte)nativeTextureID;
mSurfaceTextureLock.unlock();
return true;
}
else
return false;
}
@SuppressLint("NewApi")
public void getSurfaceTextureTransformMatrix(float []mtx)
{
mSurfaceTextureLock.lock();
if (mSurfaceTexture != null)
mSurfaceTexture.getTransformMatrix(mtx);
mSurfaceTextureLock.unlock();
}
/** This is called when the movie is ready for playback */
public void onPrepared(MediaPlayer mediaplayer)
{
mCurrentState = MEDIA_STATE.READY;
// If requested an immediate play
if (mShouldPlayImmediately)
play(false, mSeekPosition);
mSeekPosition = 0;
}
public boolean onError(MediaPlayer mp, int what, int extra) {
if (mp == mMediaPlayer)
{
String errorDescription;
switch (what)
{
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
errorDescription = "The video is streamed and its container is not valid for progressive playback";
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
errorDescription = "Media server died";
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
errorDescription = "Unspecified media player error";
break;
default:
errorDescription = "Unknown error " + what;
}
DebugLog.LOGE("Error while opening the file. Unloading the media player (" + errorDescription + ", " + extra + ")");
unload();
mCurrentState = MEDIA_STATE.ERROR;
return true;
}
return false;
}
}