/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ***
*
* Original: https://github.com/google/ExoPlayer/blob/bcb9f8282df7b05a66329e5115511c67f1651d2d/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java
* Modifications: Kickstarter have added some modifiers and annotations. References to DRM, metadata and other extraneous
* features from the original `DemoPlayer` have been removed.
*/
package com.kickstarter.libs;
import android.support.annotation.NonNull;
import android.view.Surface;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
import com.google.android.exoplayer.util.PlayerControl;
/**
* ExoPlayer wrapper that provides higher level interface.
*/
public final class KSVideoPlayer implements ExoPlayer.Listener {
private final int TRACK_RENDERER_COUNT = 3; // audio, video, text
private boolean lastReportedPlayWhenReady;
private int lastReportedPlaybackState;
private final ExoPlayer player;
private MediaCodecVideoTrackRenderer videoRenderer;
private PlayerControl playerControl;
private final RendererBuilder rendererBuilder;
private Surface surface;
private Listener listener;
public interface Listener {
void onStateChanged(boolean playWhenReady, int playbackState);
}
public interface RendererBuilder {
void buildRenderers(KSVideoPlayer player);
}
public KSVideoPlayer(final @NonNull RendererBuilder rendererBuilder) {
this.player = ExoPlayer.Factory.newInstance(TRACK_RENDERER_COUNT);
this.rendererBuilder = rendererBuilder;
playerControl = new PlayerControl(player);
player.addListener(this);
}
@Override
public void onPlayerStateChanged(final boolean playWhenReady, final int playbackState) {
reportPlayerState();
}
@Override
public void onPlayWhenReadyCommitted() {}
@Override
public void onPlayerError(final @NonNull ExoPlaybackException error) {}
/* ExoPlayer helpers */
public long getCurrentPosition() {
return player.getCurrentPosition();
}
public long getDuration() {
return player.getDuration();
}
public int getPlaybackState() {
return player.getPlaybackState();
}
public PlayerControl getPlayerControl() {
return playerControl;
}
public void pushSurface(final boolean blockForSurfacePush) {
if (videoRenderer == null) {
return;
}
if (blockForSurfacePush) {
player.blockingSendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
} else {
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
}
}
public void prepare() {
videoRenderer = null;
reportPlayerState();
rendererBuilder.buildRenderers(this);
}
public void prepareRenderers(final @NonNull MediaCodecVideoTrackRenderer videoRenderer,
final @NonNull MediaCodecAudioTrackRenderer audioTrackRenderer) {
this.videoRenderer = videoRenderer;
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
player.prepare(videoRenderer, audioTrackRenderer);
}
public void release() {
surface = null;
player.release();
}
public void reportPlayerState() {
final boolean playWhenReady = player.getPlayWhenReady();
final int playbackState = player.getPlaybackState();
if (lastReportedPlayWhenReady != playWhenReady || lastReportedPlaybackState != playbackState) {
listener.onStateChanged(playWhenReady, playbackState);
}
lastReportedPlaybackState = playbackState;
lastReportedPlayWhenReady = playWhenReady;
}
public void seekTo(final long position) {
player.seekTo(position);
}
public void setListener(final @NonNull Listener listener) {
this.listener = listener;
}
public void setPlayWhenReady(final boolean playWhenReady) {
player.setPlayWhenReady(playWhenReady);
}
public void setSurface(final @NonNull Surface surface) {
this.surface = surface;
pushSurface(false);
}
}