bilibili / ijkplayer

Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
GNU General Public License v2.0
32.44k stars 8.11k forks source link

android IjkMediaPlayer播放列表切换视频源,画面卡住不动,只有声音,没有画面 #1849

Open Allen-cxl opened 8 years ago

Allen-cxl commented 8 years ago

1.这是切换视频源的函数 private void setPlayVideo(VideoUrl videoUrl, int seekTime) {

    mCurrentVideoUrl = videoUrl;
    showProgressView(seekTime <= 0);
    if(null != mMediaPlayer){
        mMediaPlayer.release();
        mMediaPlayer = null;
    }

    mMediaPlayer = createPlayer();
    try {
        mSurfaceView.setSurfaceTextureListener(callback);
        mMediaPlayer.setDataSource(videoUrl.getViewUrl());
        mMediaPlayer.prepareAsync();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.这是创建ijkMediaPlayer的函数 private IMediaPlayer createPlayer() {

    IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
    ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);

    if (usingMediaCodec) {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
        if (usingMediaCodecAutoRotate) {
            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
        } else {
            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
        }
    } else {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
    }

    if (usingOpenSLES) {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);
    } else {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
    }

    if (TextUtils.isEmpty(pixelFormat)) {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
    } else {
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", pixelFormat);
    }
    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);

    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 10000000);
    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);

    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);

    ijkMediaPlayer.setOnPreparedListener(mOnPreparedListener);
    ijkMediaPlayer.setOnInfoListener(mOnInfoListener);
    ijkMediaPlayer.setOnCompletionListener(mOnCompletionListener);
    ijkMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
    ijkMediaPlayer.setOnErrorListener(mOnErrorListener);
    ijkMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    ijkMediaPlayer.setScreenOnWhilePlaying(true);

    return ijkMediaPlayer;
}

3.这是SurfaceTextureListener callback监听。 private TextureView.SurfaceTextureListener callback = new TextureView.SurfaceTextureListener (){

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

        Log.i("Surface","onSurfaceTextureAvailable");
        mSurface = new Surface(surface);
        mMediaPlayer.setSurface(mSurface);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        Log.i("Surface","onSurfaceTextureSizeChanged");
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {

        Log.i("Surface","onSurfaceTextureDestroyed");
        if (null != mMediaPlayer && mMediaPlayer.isPlaying()) {

            surface.release();
            mSurface.release();
            mSurfaceView.refreshDrawableState();
            mMediaPlayer.stop();
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        Log.i("Surface","onSurfaceTextureUpdated");
    }
};

问题描述:刚进入视频播放页面第一个视频正常播放,切换到下一个视频的时候调用setPlayVideo函数,画面停止一个视频禁止不动?请问怎么解决呢?

ctiao commented 8 years ago

切换时重新 setSurface

Allen-cxl commented 8 years ago

还是卡住画面不动

ctiao commented 8 years ago

重建SurfaceView, 在mediaplayer.release里 mSurface应该也被release了,检查mSurface.isValid

Allen-cxl commented 8 years ago

重新创建是ok的,问题是解决了。有个建议,android原生的MediaPlayer,切换视频源的时候,只需要reset重新设置url,画面就会更新,为什么ijk不这样?

sanchibing commented 7 years ago

@Allen-cxl ,是在哪里重新创建的,能分享下吗,谢谢。

luvjennifer commented 6 years ago

@Allen-cxl 可以請問要怎麼重新創建呢?我已經重新設 mTextureView.setSurfaceTexture(new SurfaceTexture(mTextureView.getId())); 還是不行~請問該如何解決這問題呢? 非常感謝!

KnIfER commented 5 years ago

使用 textureview 的时候遇到这个问题。 首先,肯定不是重建播放器时的 oldplayer.release 造成的,这一点你可以注释掉看看。 重建 TextureView , 就是用新的 TextureView , 但是会造成切换时的黑屏。 3046

KnIfER commented 5 years ago

解决了,确实是重新绑定
可以复用 textureview,但是不要 new surface, reuse that surface instead。

public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                          if(player instanceof IjkMediaPlayer) {
                              IjkMediaPlayer mMediaPlayer = (IjkMediaPlayer) player;
                              mMediaPlayer.setSurface(mSurface = new Surface(surface));
}}
……
ReCreatePlayer();
if(mSurface!=null)
   mMediaPlayer.setSurface(mSurface);
KnIfER commented 5 years ago

切换视频 虽然需要重建什么的, 但是效率丝毫不差 不过有点建议 在不同尺寸的视频间切换,发现上一个视频的画面还在,但是尺寸已经变成下一个视频的尺寸了,导致短暂的画面拉伸,有点污眼睛。黑屏与拉伸不可兼去耶?

ikkyu0319 commented 4 years ago

Mark