/* * copyright (C) 2006 The AndroID Open Source Project * copyright (c) 2014 Chukong TechnologIEs Inc. * * licensed under the Apache license,Version 2.0 (the "license"); * you may not use this file except in compliance with the license. * You may obtain a copy of the license at * * http://www.apache.org/licenses/liCENSE-2.0 * * Unless required by applicable law or agreed to in writing,software * distributed under the license is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implIEd. * See the license for the specific language governing permissions and * limitations under the license. */package org.cocos2dx.lib;import androID.app.AlertDialog;import androID.content.DialogInterface;import androID.content.Intent;import androID.content.res.AssetfileDescriptor;import androID.content.res.Resources;import androID.media.AudioManager;import androID.media.MediaPlayer;import androID.media.MediaPlayer.OnErrorListener;import androID.net.Uri;import androID.util.Log;import androID.vIEw.Gravity;import androID.vIEw.MotionEvent;import androID.vIEw.SurfaceHolder;import androID.vIEw.SurfaceVIEw;import androID.Widget.FrameLayout;import androID.Widget.MediaController.MediaPlayerControl;import java.io.IOException;import java.util.Map;public class Cocos2dxVIDeoVIEw extends SurfaceVIEw implements MediaPlayerControl { private String TAG = "Cocos2dxVIDeoVIEw"; private Uri mVIDeoUri; private int mDuration; // all possible internal states private static final int STATE_ERROR = -1; private static final int STATE_IDLE = 0; private static final int STATE_PREPARING = 1; private static final int STATE_PREPARED = 2; private static final int STATE_PLAYING = 3; private static final int STATE_PAUSED = 4; private static final int STATE_PLAYBACK_COMPLETED = 5; /** * mCurrentState is a VIDeoVIEw object's current state. * mTargetState is the state that a method caller intends to reach. * For instance,regardless the VIDeoVIEw object's current state,* calling pause() intends to bring the object to a target state * of STATE_PAUSED. */ private int mCurrentState = STATE_IDLE; private int mTargetState = STATE_IDLE; // All the stuff we need for playing and showing a vIDeo private SurfaceHolder mSurfaceHolder = null; private MediaPlayer mMediaPlayer = null; private int mVIDeoWIDth = 0; private int mVIDeoHeight = 0; private OnVIDeoEventListener mOnVIDeoEventListener; private MediaPlayer.OnPreparedListener mOnPreparedListener; private int mCurrentBufferPercentage; private OnErrorListener mOnErrorListener; // recording the seek position while preparing private int mSeekWhenPrepared; protected Cocos2dxActivity mCocos2dxActivity = null; protected int mVIEwleft = 0; protected int mVIEwtop = 0; protected int mVIEwWIDth = 0; protected int mVIEwHeight = 0; protected int mVisibleleft = 0; protected int mVisibletop = 0; protected int mVisibleWIDth = 0; protected int mVisibleHeight = 0; protected boolean mFullScreenEnabled = false; protected int mFullScreenWIDth = 0; protected int mFullScreenHeight = 0; private int mVIEwTag = 0; private boolean isComplete = false; public Cocos2dxVIDeoVIEw(Cocos2dxActivity activity,int tag) { super(activity); mVIEwTag = tag; mCocos2dxActivity = activity; initVIDeoVIEw(); } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { if (mVIDeoWIDth == 0 || mVIDeoHeight == 0) { setMeasuredDimension(mVIEwWIDth,mVIEwHeight); Log.i(TAG,""+mVIEwWIDth+ ":" +mVIEwHeight); } else { setMeasuredDimension(mVisibleWIDth,mVisibleHeight); Log.i(TAG,""+mVisibleWIDth+ ":" +mVisibleHeight); } } public voID setVIDeoRect(int left,int top,int maxWIDth,int maxHeight) { mVIEwleft = left; mVIEwtop = top; mVIEwWIDth = maxWIDth; mVIEwHeight = maxHeight; fixSize(mVIEwleft,mVIEwtop,mVIEwWIDth,mVIEwHeight); } public voID setFullScreenEnabled(boolean enabled,int wIDth,int height) { if (mFullScreenEnabled != enabled) { mFullScreenEnabled = enabled; if (wIDth != 0 && height != 0) { mFullScreenWIDth = wIDth; mFullScreenHeight = height; } fixSize(); } } public int resolveAdjustedSize(int desiredSize,int measureSpec) { int result = desiredSize; int specMode = MeasureSpec.getMode(measureSpec); int specsize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UnspecIFIED: /* Parent says we can be as big as we want. Just don't be larger * than max size imposed on ourselves. */ result = desiredSize; break; case MeasureSpec.AT_MOST: /* Parent says we can be as big as we want,up to specsize. * Don't be larger than specsize,and don't be larger than * the max size imposed on ourselves. */ result = Math.min(desiredSize,specsize); break; case MeasureSpec.EXACTLY: // No choice. Do what we are told. result = specsize; break; } return result; } private boolean mNeedResume = false; @OverrIDe public voID setVisibility(int visibility) { if (visibility == INVISIBLE) { mNeedResume = isPlaying(); if (mNeedResume) { mSeekWhenPrepared = getCurrentposition(); } } else if (mNeedResume){ start(); mNeedResume = false; } super.setVisibility(visibility); } private voID initVIDeoVIEw() { mVIDeoWIDth = 0; mVIDeoHeight = 0; getHolder().addCallback(mSHCallback); //Fix issue#11516:Can't play vIDeo on AndroID 2.3.x getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); setFocusable(true); setFocusableIntouchMode(true); mCurrentState = STATE_IDLE; mTargetState = STATE_IDLE; } @OverrIDe public boolean ontouchEvent(MotionEvent event) { if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { if (isPlaying()) { pause(); } else if(mCurrentState == STATE_PAUSED){ resume(); } } return true; } private boolean mIsAssetRouse = false; private String mVIDeofilePath = null; private static final String AssetResourceRoot = "assets/"; public voID setVIDeofilename(String path) { if (path.startsWith(AssetResourceRoot)) { path = path.substring(AssetResourceRoot.length()); } if (path.startsWith("/")) { mIsAssetRouse = false; setVIDeoURI(Uri.parse(path),null); } else { mVIDeofilePath = path; mIsAssetRouse = true; setVIDeoURI(Uri.parse(path),null); } } public voID setVIDeoURL(String url) { mIsAssetRouse = false; setVIDeoURI(Uri.parse(url),null); } /** * @hIDe */ private voID setVIDeoURI(Uri uri,Map<String,String> headers) { mVIDeoUri = uri; mSeekWhenPrepared = 0; mVIDeoWIDth = 0; mVIDeoHeight = 0; openVIDeo(); requestLayout(); invalIDate(); } public voID stopPlayback() { if (mMediaPlayer != null) { mMediaPlayer.stop(); mMediaPlayer.release(); mMediaPlayer = null; mCurrentState = STATE_IDLE; mTargetState = STATE_IDLE; } } private voID openVIDeo() { if (mSurfaceHolder == null) { // not ready for playback just yet,will try again later return; } if (mIsAssetRouse) { if(mVIDeofilePath == null) return; } else if(mVIDeoUri == null) { return; } // Tell the music playback service to pause // Todo: these constants need to be published somewhere in the framework. Intent i = new Intent("com.androID.music.musicservicecommand"); i.putExtra("command","pause"); mCocos2dxActivity.sendbroadcast(i); // we shouldn't clear the target state,because somebody might have // called start() prevIoUsly release(false); try { //if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayer(); mMediaPlayer.setonPreparedListener(mPreparedListener); mMediaPlayer.setonVIDeoSizeChangedListener(mSizeChangedListener); mMediaPlayer.setonCompletionListener(mCompletionListener); mMediaPlayer.setonErrorListener(mErrorListener); mMediaPlayer.setonBufferingUpdateListener(mBufferingUpdateListener); mMediaPlayer.setdisplay(mSurfaceHolder); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mMediaPlayer.setScreenOnWhilePlaying(true); //} mDuration = -1; mCurrentBufferPercentage = 0; if (mIsAssetRouse) { AssetfileDescriptor afd = mCocos2dxActivity.getAssets().openFd(mVIDeofilePath); mMediaPlayer.setDataSource(afd.getfileDescriptor(),afd.getStartOffset(),afd.getLength()); } else { mMediaPlayer.setDataSource(mCocos2dxActivity,mVIDeoUri); } mMediaPlayer.prepareAsync(); /** * Don't set the target state here either,but preserve the target state that was there before. */ mCurrentState = STATE_PREPARING; } catch (IOException ex) { Log.w(TAG,"Unable to open content: " + mVIDeoUri,ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer,MediaPlayer.MEDIA_ERROR_UNKNowN,0); return; } catch (IllegalArgumentException ex) { Log.w(TAG,0); return; } } private boolean mKeepRatio = false; public voID setKeepRatio(boolean enabled) { mKeepRatio = enabled; fixSize(); } public voID fixSize() { if (mFullScreenEnabled) { fixSize(0,mFullScreenWIDth,mFullScreenHeight); } else { fixSize(mVIEwleft,mVIEwHeight); } } public voID fixSize(int left,int height) { if (mVIDeoWIDth == 0 || mVIDeoHeight == 0) { mVisibleleft = left; mVisibletop = top; mVisibleWIDth = wIDth; mVisibleHeight = height; } else if (wIDth != 0 && height != 0) { if (mKeepRatio) { if ( mVIDeoWIDth * height > wIDth * mVIDeoHeight ) { mVisibleWIDth = wIDth; mVisibleHeight = wIDth * mVIDeoHeight / mVIDeoWIDth; } else if ( mVIDeoWIDth * height < wIDth * mVIDeoHeight ) { mVisibleWIDth = height * mVIDeoWIDth / mVIDeoHeight; mVisibleHeight = height; } mVisibleleft = left + (wIDth - mVisibleWIDth) / 2; mVisibletop = top + (height - mVisibleHeight) / 2; } else { mVisibleleft = left; mVisibletop = top; mVisibleWIDth = wIDth; mVisibleHeight = height; } } else { mVisibleleft = left; mVisibletop = top; mVisibleWIDth = mVIDeoWIDth; mVisibleHeight = mVIDeoHeight; } getHolder().setFixedSize(mVisibleWIDth,mVisibleHeight); FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,FrameLayout.LayoutParams.WRAP_CONTENT); lParams.leftmargin = mVisibleleft; lParams.topmargin = mVisibletop; lParams.gravity = Gravity.top | Gravity.left; setLayoutParams(lParams); } protected MediaPlayer.OnVIDeoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVIDeoSizeChangedListener() { public voID onVIDeoSizeChanged(MediaPlayer mp,int height) { mVIDeoWIDth = mp.getVIDeoWIDth(); mVIDeoHeight = mp.getVIDeoHeight(); if (mVIDeoWIDth != 0 && mVIDeoHeight != 0) { getHolder().setFixedSize(mVIDeoWIDth,mVIDeoHeight); } } }; MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { public voID onPrepared(MediaPlayer mp) { mCurrentState = STATE_PREPARED; if (mOnPreparedListener != null) { mOnPreparedListener.onPrepared(mMediaPlayer); } mVIDeoWIDth = mp.getVIDeoWIDth(); mVIDeoHeight = mp.getVIDeoHeight(); // mSeekWhenPrepared may be changed after seekTo() call int seekToposition = mSeekWhenPrepared; if (seekToposition != 0) { seekTo(seekToposition); } if (mVIDeoWIDth != 0 && mVIDeoHeight != 0) { fixSize(); } if (mTargetState == STATE_PLAYING || !isComplete) { if (seekToposition != 0) { seekTo(seekToposition); } start(); } } }; private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public voID onCompletion(MediaPlayer mp) { mCurrentState = STATE_PLAYBACK_COMPLETED; mTargetState = STATE_PLAYBACK_COMPLETED; release(true); if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_COMPLETED); } } }; private static final int EVENT_PLAYING = 0; private static final int EVENT_PAUSED = 1; private static final int EVENT_StopPED = 2; private static final int EVENT_COMPLETED = 3; public interface OnVIDeoEventListener { voID onVIDeoEvent(int tag,int event); } private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp,int framework_err,int impl_err) { Log.d(TAG,"Error: " + framework_err + "," + impl_err); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; /* If an error handler has been supplIEd,use it and finish. */ if (mOnErrorListener != null) { if (mOnErrorListener.onError(mMediaPlayer,framework_err,impl_err)) { return true; } } /* Otherwise,pop up an error dialog so the user kNows that * something bad has happened. Only try and pop up the dialog * if we're attached to a window. When we're going away and no * longer have a window,don't bother showing the user an error. */ if (getwindowToken() != null) { Resources r = mCocos2dxActivity.getResources(); int messageID; if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { // messageID = com.androID.internal.R.string.VIDeoVIEw_error_text_invalID_progressive_playback; messageID = r.getIDentifIEr("VIDeoVIEw_error_text_invalID_progressive_playback","string","androID"); } else { // messageID = com.androID.internal.R.string.VIDeoVIEw_error_text_unkNown; messageID = r.getIDentifIEr("VIDeoVIEw_error_text_unkNown","androID"); } int TitleID = r.getIDentifIEr("VIDeoVIEw_error_Title","androID"); int buttonStringID = r.getIDentifIEr("VIDeoVIEw_error_button","androID"); new AlertDialog.Builder(mCocos2dxActivity) .setTitle(r.getString(TitleID)) .setMessage(messageID) .setPositivebutton(r.getString(buttonStringID),new DialogInterface.OnClickListener() { public voID onClick(DialogInterface dialog,int whichbutton) { /* If we get here,there is no onError Listener,so * at least inform them that the vIDeo is over. */ if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_COMPLETED); } } }) .setCancelable(false) .show(); } return true; } }; private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { public voID onBufferingUpdate(MediaPlayer mp,int percent) { mCurrentBufferPercentage = percent; } }; /** * Register a callback to be invoked when the media file * is loaded and ready to go. * * @param l The callback that will be run */ public voID setonPreparedListener(MediaPlayer.OnPreparedListener l) { mOnPreparedListener = l; } /** * Register a callback to be invoked when the end of a media file * has been reached during play back. * * @param l The callback that will be run */ public voID setonCompletionListener(OnVIDeoEventListener l) { mOnVIDeoEventListener = l; } /** * Register a callback to be invoked when an error occurs * during play back or setup. If no Listener is specifIEd,* or if the Listener returned false,VIDeoVIEw will inform * the user of any errors. * * @param l The callback that will be run */ public voID setonErrorListener(OnErrorListener l) { mOnErrorListener = l; } SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { public voID surfaceChanged(SurfaceHolder holder,int format,int w,int h) { boolean isValIDState = (mTargetState == STATE_PLAYING) || !isComplete; boolean hasValIDSize = (mVIDeoWIDth == w && mVIDeoHeight == h); if (mMediaPlayer != null && isValIDState && hasValIDSize) { if (mSeekWhenPrepared != 0) { seekTo(mSeekWhenPrepared); } start(); } } public voID surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; openVIDeo(); } public voID surfaceDestroyed(SurfaceHolder holder) { if(mCurrentState == STATE_PLAYING) { isComplete = mMediaPlayer.getCurrentposition() == mMediaPlayer.getDuration(); mSeekWhenPrepared = mMediaPlayer.getCurrentposition(); } mSurfaceHolder = null; release(true); } }; /* * release the media player in any state */ private voID release(boolean cleartargetstate) { if (mMediaPlayer != null) { mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer = null; mCurrentState = STATE_IDLE; if (cleartargetstate) { mTargetState = STATE_IDLE; } } } public voID start() { if (isInPlaybackState()) { mMediaPlayer.start(); mCurrentState = STATE_PLAYING; if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_PLAYING); } } mTargetState = STATE_PLAYING; } public voID pause() { if (isInPlaybackState()) { if (mMediaPlayer.isPlaying()) { mMediaPlayer.pause(); mCurrentState = STATE_PAUSED; if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_PAUSED); } } } mTargetState = STATE_PAUSED; } public voID stop() { if (isInPlaybackState()) { if (mMediaPlayer.isPlaying()) { stopPlayback(); if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_StopPED); } } } } public voID suspend() { release(false); } public voID resume() { if (isInPlaybackState()) { if (mCurrentState == STATE_PAUSED) { mMediaPlayer.start(); mCurrentState = STATE_PLAYING; if (mOnVIDeoEventListener != null) { mOnVIDeoEventListener.onVIDeoEvent(mVIEwTag,EVENT_PLAYING); } } } } public voID restart() { if (isInPlaybackState()) { mMediaPlayer.seekTo(0); mMediaPlayer.start(); mCurrentState = STATE_PLAYING; mTargetState = STATE_PLAYING; } } // cache duration as mDuration for faster access public int getDuration() { if (isInPlaybackState()) { if (mDuration > 0) { return mDuration; } mDuration = mMediaPlayer.getDuration(); return mDuration; } mDuration = -1; return mDuration; } public int getCurrentposition() { if (isInPlaybackState()) { return mMediaPlayer.getCurrentposition(); } return 0; } public voID seekTo(int msec) { if (isInPlaybackState()) { mMediaPlayer.seekTo(msec); mSeekWhenPrepared = 0; } else { mSeekWhenPrepared = msec; } } public boolean isPlaying() { return isInPlaybackState() && mMediaPlayer.isPlaying(); } public int getBufferPercentage() { if (mMediaPlayer != null) { return mCurrentBufferPercentage; } return 0; } public boolean isInPlaybackState() { return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); } @OverrIDe public boolean canPause() { return true; } @OverrIDe public boolean canSeekBackward() { return true; } @OverrIDe public boolean canSeekForward() { return true; } public int getAudioSessionID () { return mMediaPlayer.getAudioSessionID(); }}
@H_502_4@
@H_502_4@
做了一下改动.@H_502_4@
主要参考:http://blog.sina.com.cn/s/blog_93add5520102w6n9.HTML@H_502_4@
很感谢这个博主,哈哈@H_502_4@
@H_502_4@
@H_502_4@ 总结
以上是内存溢出为你收集整理的cocos2dx 3.x 播放视频bug全部内容,希望文章能够帮你解决cocos2dx 3.x 播放视频bug所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)