Android 修复ijkPlayer进行m3u8 hls流播放时seek进度条拖动不准确的问题

来源:互联网 发布:生存之民工 知乎 编辑:程序博客网 时间:2024/04/30 01:21

项目中使用的播放器是ijkPlayer,发现播放切片特点的hls流(m3u8格式的视频)拖动seekBar的时候会莫名的跳转或者seek不到准确的位置,发现网友也遇到了同样的问题,ijk的开发者也说明了是因为UI层的问题导致的,需要自己排查。涉及到该问题的链接:

  • 通过ijkPlayer播放m3u8视频时快进不准确的解决方案

    http://www.jianshu.com/p/bc42ba6e4bf2

  • 为什么Sample里面的进度条,往前拖动进度条后,还会往后退几秒

    https://github.com/Bilibili/ijkplayer/issues/834

  • 向前拖动,进度条会往回跳

    https://github.com/Bilibili/ijkplayer/issues/313

    **bbcallen **commented on Jul 8, 2015

    UI部分seekbar的回调处理得不太合理,如果放手很快,最后一个位置不会被传给播放器,建议自行修改。

既然开发者都说了,那么就老实分析代码吧。因为项目中用到的MediaController继承自Android系统的MediaController,所以还得看看源码,分析得出系统中实现是将seek的listener监听器放在onProgressChanged这个方法中,这也是为什么我们断断续续拖动的时候播放器也会播放,知道这点就够了,把onProgressChanged中的mPlayer.seekTo((int) newposition);放到onStopTrackingTouch方法中。

执行顺序是:

onStartTrackingTouch(执行一次) —> onProgressChanged(拖动就会不停的执行) —> onStopTrackingTouch(停止后最后执行一次)

实现代码如下:

public class CustomMediaController extends MediaController implements ICustomMediaController {    // ....................代码省略.............................  // There are two scenarios that can trigger the seekbar listener to trigger:  //  // The first is the user using the touchpad to adjust the posititon of the  // seekbar's thumb. In this case onStartTrackingTouch is called followed by  // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.  // We're setting the field "mDragging" to true for the duration of the dragging  // session to avoid jumps in the position in case of ongoing playback.  //  // The second scenario involves the user operating the scroll ball, in this  // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,  // we will simply apply the updated position without suspending regular updates.  private OnSeekBarChangeListener mSeekListener=new OnSeekBarChangeListener(){    long newposition;    public void onStartTrackingTouch(SeekBar bar){      show(3600000);      mDragging=true;      if(seekerBarDraggingListener!=null)        seekerBarDraggingListener.getCurrentDraggingstatus(mDragging);      // By removing these pending progress messages we make sure      // that a) we won't update the progress while the user adjusts      // the seekbar and b) once the user is done dragging the thumb      // we will post one of these messages to the queue again and      // this ensures that there will be exactly one message queued up.      mHandler.removeMessages(SHOW_PROGRESS);    }    public void onProgressChanged(SeekBar bar,int progress,boolean fromuser){      if(!fromuser){        // We're not interested in programmatically generated changes to        // the progress bar's position.        return;      }      long duration=mPlayer.getDuration();      newposition=(duration*progress)/1000L;      // 系统原来的实现是在progress改变的时候时刻都在进行videoplayer的seek      //这会导致seek m3u8切片文件的时候拖动seek时不准确,所以需要在拖动完成后才进行播放器的seekTo()      //                mPlayer.seekTo((int) newposition);      if(mCurrentTime!=null)        mCurrentTime.setText(stringForTime((int)newposition));    }    public void onStopTrackingTouch(SeekBar bar){      mDragging=false;      mPlayer.seekTo((int)newposition);      if(seekerBarDraggingListener!=null)        seekerBarDraggingListener.getCurrentDraggingstatus(mDragging);      setProgress();      updatePausePlay();      if(isntNeedStayShowAfterDrag){        show(sDefaultTimeout);        // Ensure that progress is properly updated in the future,        // the call to show() does not guarantee this because it is a        // no-op if we are already showing.        mHandler.sendEmptyMessage(SHOW_PROGRESS);      }    }  };  // ....................代码省略.............................}
0 0
原创粉丝点击