赞
踩
根据项目需要实现这个功能,所以又开始改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);
- }
大致就这样
基于这篇写的全景播放器
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。