Skip to content

Commit

Permalink
Codec failure retry timeout logic (#821)
Browse files Browse the repository at this point in the history
  • Loading branch information
volodymyr-bondarenko85 authored Jun 3, 2024
1 parent 53ffec6 commit 6287fbc
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.kaltura.playkit;

import android.content.Context;
import android.os.Handler;

import androidx.annotation.NonNull;

import com.kaltura.android.exoplayer2.DefaultRenderersFactory;
import com.kaltura.android.exoplayer2.ExoPlaybackException;
import com.kaltura.android.exoplayer2.PlaybackException;
import com.kaltura.android.exoplayer2.Renderer;
import com.kaltura.android.exoplayer2.mediacodec.MediaCodecSelector;
import com.kaltura.android.exoplayer2.video.MediaCodecVideoRenderer;
import com.kaltura.android.exoplayer2.video.VideoRendererEventListener;
import com.kaltura.playkit.player.PlayerSettings;

import java.util.ArrayList;

public class KDefaultRenderersFactory {
private static final PKLog log = PKLog.get("KDefaultRenderersFactory");

public static DefaultRenderersFactory createDecoderInitErrorRetryFactory(
Context context,
PlayerSettings playerSettings
) {
return new DefaultRenderersFactory(context) {
@Override
protected void buildVideoRenderers(@NonNull Context context,
int extensionRendererMode,
@NonNull MediaCodecSelector mediaCodecSelector,
boolean enableDecoderFallback,
@NonNull Handler eventHandler,
@NonNull VideoRendererEventListener eventListener,
long allowedVideoJoiningTimeMs,
@NonNull ArrayList<Renderer> out) {
ArrayList<Renderer> renderersArrayList = new ArrayList<>();
super.buildVideoRenderers(context,
extensionRendererMode,
mediaCodecSelector,
enableDecoderFallback,
eventHandler,
eventListener,
allowedVideoJoiningTimeMs,
renderersArrayList);
for (Renderer renderer : renderersArrayList) {
if (renderer instanceof MediaCodecVideoRenderer) {
out.add(new MediaCodecVideoRenderer(
context,
this.getCodecAdapterFactory(),
mediaCodecSelector,
allowedVideoJoiningTimeMs,
enableDecoderFallback,
eventHandler,
eventListener,
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY) {
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
try {
super.render(positionUs, elapsedRealtimeUs);
} catch (ExoPlaybackException e) {
if (e.errorCode == PlaybackException.ERROR_CODE_DECODER_INIT_FAILED
&& playerSettings.getCodecFailureRetryCount() > 0 && playerSettings.getCodecFailureRetryTimeout() > 0) {
for(int i = 0; i < playerSettings.getCodecFailureRetryCount(); i++) {
log.d("Retrying on coded init failure (" + i + ")");
super.onReset();
try {
Thread.sleep(playerSettings.getCodecFailureRetryTimeout());
} catch (Exception e1) {
log.d("Interrupted while sleeping: " + e1.getMessage());
e1.printStackTrace();
}
try {
super.render(positionUs, elapsedRealtimeUs);
log.d("Retrying on coded init failure successful");
// Stop retrying if no exception was thrown
break;
} catch (ExoPlaybackException e2) {
if (e2.errorCode != PlaybackException.ERROR_CODE_DECODER_INIT_FAILED
|| i == playerSettings.getCodecFailureRetryCount() - 1) {
// Some other error happened or last retry. Throw exception to the caller
log.d("Codec init retry failed: " + e2.getMessage());
throw e2;
}
}
}
}
}
}
}
);
} else {
out.add(renderer);
}
}
}
};
}
}
16 changes: 16 additions & 0 deletions playkit/src/main/java/com/kaltura/playkit/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,22 @@ interface Settings {
*/
Settings setShutterStaysOnRenderedFirstFrame(boolean shutterStaysOnRenderedFirstFrame);

/**
* Set codecFailureRetryCount - count of the codec initialization failure retries
*
* @param codecFailureRetryCount
* @return - Player Settings
*/
Settings setCodecFailureRetryCount(int codecFailureRetryCount);

/**
* Set codecFailureRetryTimeout - timeout to wait between retries of codec re-initialization on failure
*
* @param codecFailureRetryTimeout
* @return - Player Settings
*/
Settings setCodecFailureRetryTimeout(int codecFailureRetryTimeout);

/**
* Set preference to choose internal subtitles over external subtitles (Only in the case if the same language is present
* in both Internal and External subtitles) - Default is true (Internal is preferred)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import com.kaltura.android.exoplayer2.upstream.cache.CacheDataSource;
import com.kaltura.android.exoplayer2.util.TimestampAdjuster;
import com.kaltura.android.exoplayer2.video.ConfigurableLoadControl;
import com.kaltura.playkit.KDefaultRenderersFactory;
import com.kaltura.playkit.LocalAssetsManager;
import com.kaltura.playkit.LocalAssetsManagerExo;
import com.kaltura.playkit.PKAbrFilter;
Expand Down Expand Up @@ -248,7 +249,7 @@ private void initializePlayer() {
}
DefaultRenderersFactory renderersFactory = this.useSpeedAdjustingRenderer
? SpeedAdjustedRenderersFactory.createSpeedAdjustedRenderersFactory(context, playerSettings, exoPlayerView)
: new DefaultRenderersFactory(context);
: KDefaultRenderersFactory.createDecoderInitErrorRetryFactory(context, playerSettings);
renderersFactory.setAllowedVideoJoiningTimeMs(playerSettings.getLoadControlBuffers().getAllowedVideoJoiningTimeMs());
renderersFactory.setEnableDecoderFallback(playerSettings.enableDecoderFallback());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public class PlayerSettings implements Player.Settings {
private PKRequestParams.Adapter contentRequestAdapter;
private PKRequestParams.Adapter licenseRequestAdapter;
private Object customLoadControlStrategy = null;
private int codecFailureRetryCount = -1;
private int codecFailureRetryTimeout = -1;

public PKRequestParams.Adapter getContentRequestAdapter() {
return contentRequestAdapter;
Expand Down Expand Up @@ -179,6 +181,14 @@ public Object getCustomLoadControlStrategy() {
return customLoadControlStrategy;
}

public int getCodecFailureRetryCount() {
return codecFailureRetryCount;
}

public int getCodecFailureRetryTimeout() {
return codecFailureRetryTimeout;
}

public boolean isTunneledAudioPlayback() {
return isTunneledAudioPlayback;
}
Expand Down Expand Up @@ -395,6 +405,18 @@ public Player.Settings setCustomLoadControlStrategy(Object customLoadControlStra
return this;
}

@Override
public Player.Settings setCodecFailureRetryCount(int codecFailureRetryCount) {
this.codecFailureRetryCount = codecFailureRetryCount;
return this;
}

@Override
public Player.Settings setCodecFailureRetryTimeout(int codecFailureRetryTimeout) {
this.codecFailureRetryTimeout = codecFailureRetryTimeout;
return this;
}

@Override
public Player.Settings setTunneledAudioPlayback(boolean isTunneledAudioPlayback) {
this.isTunneledAudioPlayback = isTunneledAudioPlayback;
Expand Down

0 comments on commit 6287fbc

Please sign in to comment.