android 将opengles渲染线程嵌入到exoplayer解码线程内

根据项目需要实现这个功能,所以又开始改exoplayer源码了。我以前也改过修改ExoPlayer源码,获取帧时间,现在我要在这个的基础上进行修改

修改VideoTimeListener.java,添加新的回调函数

public interface VideoTimeListener {
    void onVideoTimeChanged(long time);
    Surface onSurface(Surface surface);
    void onSizeChanged(int width,int height);
    void onRelease();
    void onStart();
    void onStop();
}

接下来修改SimpleExoPlayer.java的ComponentListener内代码,添加上边的函数

@Override
public Surface onSurface(Surface surface) {
  for (VideoTimeListener videoTimeListener : videoTimeListeners) {
    return videoTimeListener.onSurface(surface);
  }
  return surface;
}

@Override
public void onSizeChanged(int width, int height) {
  for (VideoTimeListener videoTimeListener : videoTimeListeners) {
     videoTimeListener.onSizeChanged(width,height);
  }
}

@Override
public void onRelease() {
  for (VideoTimeListener videoTimeListener : videoTimeListeners) {
    videoTimeListener.onRelease();
  }
}

@Override
public void onStart() {
  for (VideoTimeListener videoTimeListener : videoTimeListeners) {
    videoTimeListener.onStart();
  }
}

@Override
public void onStop() {
  for (VideoTimeListener videoTimeListener : videoTimeListeners) {
    videoTimeListener.onStop();
  }
}

好了,这样就可以监听exoplayer的解码线程的生命周期了,exoplayer的解码线程我没找到,不过找到了解码调用的类MediaCodecVideoRenderer.java
下面要添加代码的函数都在MediaCodecVideoRenderer.java内

先在setSurface(Surface surface)内添加代码

private void setSurface(Surface surface) throws ExoPlaybackException {
  Surface s = null;
  if(timeListener != null){
    s = timeListener.onSurface(surface);
  }
  if(s != null){
    surface = s;
  }
  //省略代码
}

在configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,MediaCrypto crypto)内添加代码

@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
    MediaCrypto crypto) throws DecoderQueryException {
  //省略代码
  if(timeListener != null){
    timeListener.onSizeChanged(mediaFormat.getInteger(MediaFormat.KEY_WIDTH),mediaFormat.getInteger(MediaFormat.KEY_HEIGHT));
  }
  codec.configure(mediaFormat, surface, crypto, 0);

  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}

这里要注意,正常情况下configureCodec比setSurface先运行,可是我在debug模式下,没打断点的时候是setSurface比configureCodec先运行

在onStarted()和onStopped()内添加代码,这样就可以监听开始播放和停止播放了,需要注意的是在播放时候seekTo会调用onStarted和onStopped,所以要回调的地方判断一下

@Override
protected void onStarted() {
  super.onStarted();
  droppedFrames = 0;
  droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime();
  lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000;
  if(timeListener != null){
    timeListener.onStart();
  }
}

@Override
protected void onStopped() {
  joiningDeadlineMs = C.TIME_UNSET;
  maybeNotifyDroppedFrames();
  super.onStopped();
  if(timeListener != null){
    timeListener.onStop();
  }
}

在onDisabled()内添加代码

@Override
protected void onDisabled() {
  if (timeListener != null) {
    timeListener.onRelease();
  }
  //省略代码
}

添加属性

private long timeUsIndex;
private long timeIndex;
private long timeUs;

在上面的configureCodec函数内初始化

timeUsIndex = timeIndex = 0;

将在renderOutputBufferV21和renderOutputBuffer内获取帧时间的代码删掉,改成

timeUsIndex++;
timeUs = presentationTimeUs;

重写render(long positionUs, long elapsedRealtimeUs)函数,这个函数是MediaCodecVideoRenderer的父类的,他会每隔几毫秒调用一次,就算不解码也会调用,用它来进行渲染

@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
  while (timeIndex < timeUsIndex){
    timeIndex++;
    if(surface != null && timeListener != null && timeIndex == timeUsIndex){
      timeListener.onVideoTimeChanged(timeUs/1000);
    }
  }
  super.render(positionUs, elapsedRealtimeUs);
}

大致就这样

GitHub

基于这篇写的全景播放器

ExoEditVR

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值