3

I am playing video with ExoPlayer and showing Google AdMob's Interstitial Video Ad.

After closing ads getting issue to play video again.

I am getting error as below:

    Playback error.com.google.android.exoplayer2.ExoPlaybackException
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.throwDecoderInitError(MediaCodecRenderer.java:441)
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodec(MediaCodecRenderer.java:428)
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:920)
       at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:503)
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:557)
       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:518)
       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:301)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:193)
       at android.os.HandlerThread.run(HandlerThread.java:65)
    Caused by: com.google.android.exoplayer2.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.qcom.video.decoder.avc, Format(1, null, video/avc, -1, null, [720, 420, -1.0], [-1, -1])
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodec(MediaCodecRenderer.java:428) 
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:920) 
       at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:503) 
       at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:557) 
       at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:518) 
       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:301) 
       at android.os.Handler.dispatchMessage(Handler.java:102) 
       at android.os.Looper.loop(Looper.java:193) 
       at android.os.HandlerThread.run(HandlerThread.java:65) 

Here is my dependency:

I am using libraries:

implementation 'com.google.android.exoplayer:exoplayer:2.8.1'

Code of Activity:

private ActivityVideoMakingBinding mBinding;
    private Activity mContext;
    private SimpleExoPlayer player;
    private PlayerView exoPlayerView;
    private long pause_dur = 0;

    private FirebaseRemoteConfig mFirebaseRemoteConfig;
    private InterstitialAd mInterstitialAd;
    private com.facebook.ads.InterstitialAd interstitialAd;

    private DataSource.Factory dataSourceFactory;
    private MediaSource mediaSource;
    private AdsLoader adsLoader;

    private void releaseAdsLoader() {
        if (adsLoader != null) {
            adsLoader.release();
            adsLoader = null;
            exoPlayerView.getOverlayFrameLayout().removeAllViews();
        }
    }

    private void releasePlayer() {
        if (player != null) {
            pause_dur = player.getCurrentPosition();
            player.release();
            player = null;
            mediaSource = null;
        }
        if (adsLoader != null) {
            releaseAdsLoader();
        }
    }

    private DataSource.Factory buildDataSourceFactory() {
        return MyApplication.getInstance().buildDataSourceFactory(null);
    }

    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle savedInstanceState){
        mBinding = DataBindingUtil.setContentView(mContext, R.layout.activity_video_making);
        mContext = VideoMakingActivity.this;
        outputVideo = getDirectoryPath(mContext) +
                zipFileName + File.separator + "output.mp4";

        exoPlayerView = mBinding.exoPlayerVideoDetail;
        initializeExoPlayer();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBinding.adView != null)
            mBinding.adView.destroy();
        releasePlayer();
    }

    @Override
    protected void onResume() {
        super.onResume();
        isOnPause = false;
        if (mBinding.adView != null)
            mBinding.adView.resume();
        if (flagIsFirstTime) {
            flagIsFirstTime = false;
        } else {
            initializeExoPlayer();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        isOnPause = true;
        releasePlayer();
        if (mBinding.adView != null)
            mBinding.adView.pause();
    }

    private void showAdsSettings() {
        mFirebaseRemoteConfig.fetch(3600).addOnCompleteListener(this, task -> {
            if (task.isSuccessful()) {
                mFirebaseRemoteConfig.activate();
                requestNewInterstitial();
            }
        });
    }

    private void requestNewInterstitial() {
        if (mFirebaseRemoteConfig.getString(Globals.ad_network_boo).equalsIgnoreCase("facebook")
                && getInstalled()) {
            interstitialAd = new com.facebook.ads.InterstitialAd(mContext,
                    getResources().getString(R.string.fb_video_making_inter));
            interstitialAd.loadAd();
            try {
                interstitialAd.setAdListener(new AbstractAdListener() {
                    @Override
                    public void onInterstitialDismissed(Ad ad) {
                        super.onInterstitialDismissed(ad);
                        if (interstitialAd != null) {
                            interstitialAd.destroy();
                            interstitialAd.loadAd();
                            goNextScreen();
                        }
                    }
                });
            } catch (Exception ignored) {

            }
        } else {
            mInterstitialAd = new InterstitialAd(this);
            mInterstitialAd.setAdUnitId(getString(R.string.gl_video_making_inter));
            mInterstitialAd.loadAd(new AdRequest.Builder().build());
            mInterstitialAd.setAdListener(new AdListener() {
                @Override
                public void onAdClosed() {
                    super.onAdClosed();
                    mInterstitialAd.loadAd(new AdRequest.Builder().build());
                    goNextScreen();
                }
            });
        }
    }

    private boolean getInstalled() {
        try {
            mContext.getPackageManager().getApplicationInfo("com.facebook.katana", 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            try {
                mContext.getPackageManager().getApplicationInfo("com.facebook.lite", 0);
                return true;
            } catch (Exception ex) {
                return false;
            }
        }
    }

    private void goNextScreen() {
        Intent intent = new Intent(mContext, VideoPreviewActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtra("filePath", finalVideoPath);
        intent.putExtra("fileName", fileName);
        intent.putExtra("video_object", new Gson().toJson(mVideoData));
        startActivity(intent);
    }

    private void initializeExoPlayer() {
        if (player == null) {
            player = ExoPlayerFactory.newSimpleInstance(
                    new DefaultRenderersFactory(this),
                    new DefaultTrackSelector(), new DefaultLoadControl());
            exoPlayerView.setPlayer(player);
            exoPlayerView.setBackgroundColor(Color.BLACK);
            exoPlayerView.setUseController(false);

            mBinding.viewMain.setOnClickListener(v -> {
                isPlaying = false;
                playPausePlayer(false);
            });

            mBinding.previewControls.rlPreviewControl.setOnClickListener(v -> {
                Globals.playSound(mContext, R.raw.button_tap);
                if (flagChanges) {
                    strExportVideo = "preview";
                    exportVideo();
                } else {
                    isPlaying = true;
                    playPausePlayer(true);
                }
            });

            player.addListener(new Player.DefaultEventListener() {
                @Override
                public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                    super.onPlayerStateChanged(playWhenReady, playbackState);
                    if (playbackState == Player.STATE_ENDED) {
                        mBinding.progressBarExoplayer.setVisibility(View.GONE);
                        player.seekTo(0);
                    } else if (playbackState == Player.STATE_BUFFERING) {
                        mBinding.progressBarExoplayer.setVisibility(View.VISIBLE);
                    } else if (playbackState == Player.STATE_READY) {
                        mBinding.progressBarExoplayer.setVisibility(View.GONE);
                    } else if (playbackState == Player.STATE_IDLE) {
                        mBinding.progressBarExoplayer.setVisibility(View.GONE);
                    }
                }
            });
            playPausePlayer(true);
        }
        prepareExoPlayer(outputVideo);
    }

    private void playPausePlayer(boolean play) {
        if (player != null)
            if (play) {
                mBinding.exoThumb.setVisibility(View.GONE);
                player.seekTo(pause_dur);
                player.setPlayWhenReady(true);
                player.getPlaybackState();
            } else {
                pause_dur = player.getCurrentPosition();
                player.setPlayWhenReady(false);
                player.getPlaybackState();
            }
    }

    private void prepareExoPlayer(String path) {
        Uri uri = Uri.parse(path);
        mediaSource = buildLocalMediaSource(uri);
        player.prepare(mediaSource, true, false);
    }

    private MediaSource buildLocalMediaSource(Uri uri) {
        return buildMediaSource(uri, null);
    }

    private MediaSource buildMediaSource(Uri uri, @androidx.annotation.Nullable String overrideExtension) {
        @C.ContentType int type = Util.inferContentType(uri, overrideExtension);
        switch (type) {
            case C.TYPE_HLS:
                return new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            case C.TYPE_OTHER:
                return new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
            default:
                throw new IllegalStateException("Unsupported type: " + type);
            case C.TYPE_DASH:
                throw new IllegalStateException("Unsupported type: " + type);
            case C.TYPE_SS:
                throw new IllegalStateException("Unsupported type: " + type);
        }
    }

    private String getDirectoryPath(Context mContext) {
        String externalDirectory = mContext.getFilesDir().getAbsolutePath();
        File dir = new File(externalDirectory + File.separator +
                mContext.getResources().getString(R.string.zip_directory));
        if (!dir.exists())
            dir.mkdir();

        return dir.getAbsolutePath() + File.separator;
    }
}

In above activity I am using single instance of DataSourceFactory So, Here is code of MyApplication.java:

public class MyApplication extends MultiDexApplication {

    protected String userAgent;
    private static MyApplication sInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        MultiDex.install(this);

        //Common User Agent  for all player
        userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
        sInstance = this;
    }

    public static MyApplication getInstance() {
        return sInstance;
    }

    /**
     * Returns a {@link DataSource.Factory}.
     */
    public DataSource.Factory buildDataSourceFactory(TransferListener<? super DataSource> listener) {
        return new DefaultDataSourceFactory(this, listener, buildHttpDataSourceFactory(listener));
    }

    /**
     * Returns a {@link HttpDataSource.Factory}.
     */
    public HttpDataSource.Factory buildHttpDataSourceFactory(
        TransferListener<? super DataSource> listener) {
        return new DefaultHttpDataSourceFactory(userAgent, listener);
    }
}

Well after analysis for some days, com.google.android.gms.internal.ads.zzgb error for interstitial ad is occurs whenever I used Video ads in Interstitial ad and its working fine when I off video ads which in general contains image ads only.

This thing is happening with Admob network only because I am using FB audience network also and its working with ExoPlayer.

Anyone can help? Thanks in advance.

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
  • I have the same problem, but in my case it's enough if I instantiate and load ad (without even displaying the video). Also disabling serving video ads does not help. It doesn't happen always, and also only on some devices (ie. Samsung SM-G920F). Seems like the Admob's internal exoplayer does not release some resources and device hardware codecs are not available any more. – bojan Oct 19 '19 at 20:33

0 Answers0