Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #215 from novoda/develop
Browse files Browse the repository at this point in the history
Prepare for release 4.5.4
  • Loading branch information
zegnus authored Apr 8, 2019
2 parents 99d6d47 + 182e928 commit ecfe867
Show file tree
Hide file tree
Showing 17 changed files with 291 additions and 19 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
allprojects {
version = '4.5.3'
version = '4.5.4'
}

def teamPropsFile(propsFile) {
Expand Down
18 changes: 17 additions & 1 deletion core/src/main/java/com/novoda/noplayer/NoPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ public interface NoPlayer extends PlayerState {
void play() throws IllegalStateException;

/**
* Plays content of a prepared Player at a given position.
* Deprecated: This does not perform the way it was originally intended. A seek can, and most likely will,
* occur after the content has already started playing. This can lead to some unexpected behaviour.
* Plays content of a prepared Player at a given position. Use {@link #loadVideo(Uri, Options)} passing
* a initial position to the {@link Options}.
*
* @param positionInMillis to start playing content from.
* @throws IllegalStateException - if called before {@link NoPlayer#loadVideo(Uri, Options)}.
* @see NoPlayer.PreparedListener
*/
@Deprecated
void playAt(long positionInMillis) throws IllegalStateException;

/**
Expand Down Expand Up @@ -223,6 +227,18 @@ public interface NoPlayer extends PlayerState {
@FloatRange(from = 0.0f, to = 1.0f)
float getVolume() throws IllegalStateException;

/**
* Clears the maximum video bitrate, if set.
*/
void clearMaxVideoBitrate();

/**
* Sets a maximum video bitrate. If the content is playing, the video will switch to a different quality.
*
* @param maxVideoBitrate The maximum video bitrate in bit per second.
*/
void setMaxVideoBitrate(int maxVideoBitrate);

interface PlayerError {

PlayerErrorType type();
Expand Down
54 changes: 52 additions & 2 deletions core/src/main/java/com/novoda/noplayer/Options.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
package com.novoda.noplayer;

import com.novoda.noplayer.internal.utils.Optional;

/**
* Options to customise the underlying player.
*/
public class Options {

private final ContentType contentType;
private final int minDurationBeforeQualityIncreaseInMillis;
private final int maxInitialBitrate;
private final int maxVideoBitrate;
private final Optional<Long> initialPositionInMillis;

/**
* Creates a {@link OptionsBuilder} from this Options.
*
* @return a new instance of {@link OptionsBuilder}.
*/
public OptionsBuilder toOptionsBuilder() {
OptionsBuilder optionsBuilder = new OptionsBuilder()
.withContentType(contentType)
.withMinDurationBeforeQualityIncreaseInMillis(minDurationBeforeQualityIncreaseInMillis)
.withMaxInitialBitrate(maxInitialBitrate)
.withMaxVideoBitrate(maxVideoBitrate);

Options(ContentType contentType, int minDurationBeforeQualityIncreaseInMillis, int maxInitialBitrate) {
if (initialPositionInMillis.isPresent()) {
optionsBuilder = optionsBuilder.withInitialPositionInMillis(initialPositionInMillis.get());
}
return optionsBuilder;
}

Options(ContentType contentType,
int minDurationBeforeQualityIncreaseInMillis,
int maxInitialBitrate,
int maxVideoBitrate,
Optional<Long> initialPositionInMillis) {
this.contentType = contentType;
this.minDurationBeforeQualityIncreaseInMillis = minDurationBeforeQualityIncreaseInMillis;
this.maxInitialBitrate = maxInitialBitrate;
this.maxVideoBitrate = maxVideoBitrate;
this.initialPositionInMillis = initialPositionInMillis;
}

public ContentType contentType() {
Expand All @@ -24,6 +55,14 @@ public int maxInitialBitrate() {
return maxInitialBitrate;
}

public int maxVideoBitrate() {
return maxVideoBitrate;
}

public Optional<Long> getInitialPositionInMillis() {
return initialPositionInMillis;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -41,14 +80,23 @@ public boolean equals(Object o) {
if (maxInitialBitrate != options.maxInitialBitrate) {
return false;
}
return contentType == options.contentType;
if (maxVideoBitrate != options.maxVideoBitrate) {
return false;
}
if (contentType != options.contentType) {
return false;
}
return initialPositionInMillis != null
? initialPositionInMillis.equals(options.initialPositionInMillis) : options.initialPositionInMillis == null;
}

@Override
public int hashCode() {
int result = contentType != null ? contentType.hashCode() : 0;
result = 31 * result + minDurationBeforeQualityIncreaseInMillis;
result = 31 * result + maxInitialBitrate;
result = 31 * result + maxVideoBitrate;
result = 31 * result + (initialPositionInMillis != null ? initialPositionInMillis.hashCode() : 0);
return result;
}

Expand All @@ -58,6 +106,8 @@ public String toString() {
+ "contentType=" + contentType
+ ", minDurationBeforeQualityIncreaseInMillis=" + minDurationBeforeQualityIncreaseInMillis
+ ", maxInitialBitrate=" + maxInitialBitrate
+ ", maxVideoBitrate=" + maxVideoBitrate
+ ", initialPositionInMillis=" + initialPositionInMillis
+ '}';
}
}
41 changes: 39 additions & 2 deletions core/src/main/java/com/novoda/noplayer/OptionsBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

import android.net.Uri;

import com.novoda.noplayer.internal.utils.Optional;

/**
* Builds instances of {@link Options} for {@link NoPlayer#loadVideo(Uri, Options)}.
*/
public class OptionsBuilder {

private static final int DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS = 10000;
private static final int DEFAULT_MAX_INITIAL_BITRATE = 800000;
private static final int DEFAULT_MAX_VIDEO_BITRATE = Integer.MAX_VALUE;

private ContentType contentType = ContentType.H264;
private int minDurationBeforeQualityIncreaseInMillis = DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS;
private int maxInitialBitrate = DEFAULT_MAX_INITIAL_BITRATE;
private int maxVideoBitrate = DEFAULT_MAX_VIDEO_BITRATE;
private Optional<Long> initialPositionInMillis = Optional.absent();

/**
* Sets {@link OptionsBuilder} to build {@link Options} with a given {@link ContentType}.
Expand Down Expand Up @@ -44,19 +49,51 @@ public OptionsBuilder withMinDurationBeforeQualityIncreaseInMillis(int minDurati
* allows the player to choose a higher quality video track at the beginning.
*
* @param maxInitialBitrate maximum bitrate that limits the initial track selection.
* @return {@link OptionsBuilder}
* @return {@link OptionsBuilder}.
*/
public OptionsBuilder withMaxInitialBitrate(int maxInitialBitrate) {
this.maxInitialBitrate = maxInitialBitrate;
return this;
}

/**
* Sets {@link OptionsBuilder} to build {@link Options} with given maximum video bitrate in order to
* control what is the maximum video quality with which {@link NoPlayer} starts the playback. Setting a higher value
* allows the player to choose a higher quality video track.
*
* @param maxVideoBitrate maximum bitrate that limits the initial track selection.
* @return {@link OptionsBuilder}
*/
public OptionsBuilder withMaxVideoBitrate(int maxVideoBitrate) {
this.maxVideoBitrate = maxVideoBitrate;
return this;
}

/**
* Sets {@link OptionsBuilder} to build {@link Options} with given initial position in millis in order
* to specify the start position of the content that will be played. Omitting to set this will start
* playback at the beginning of the content.
*
* @param initialPositionInMillis position that the content should begin playback at.
* @return {@link OptionsBuilder}.
*/
public OptionsBuilder withInitialPositionInMillis(long initialPositionInMillis) {
this.initialPositionInMillis = Optional.of(initialPositionInMillis);
return this;
}

/**
* Builds a new {@link Options} instance.
*
* @return a {@link Options} instance.
*/
public Options build() {
return new Options(contentType, minDurationBeforeQualityIncreaseInMillis, maxInitialBitrate);
return new Options(
contentType,
minDurationBeforeQualityIncreaseInMillis,
maxInitialBitrate,
maxVideoBitrate,
initialPositionInMillis
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,12 @@ List<PlayerSubtitleTrack> getSubtitleTracks(RendererTypeRequester rendererTypeRe
boolean clearSubtitleTrack(RendererTypeRequester rendererTypeRequester) {
return subtitleTrackSelector.clearSubtitleTrack(rendererTypeRequester);
}

void clearMaxVideoBitrate() {
videoTrackSelector.clearMaxVideoBitrate();
}

void setMaxVideoBitrate(int maxVideoBitrate) {
videoTrackSelector.setMaxVideoBitrate(maxVideoBitrate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ CompositeTrackSelector create(Options options, DefaultBandwidthMeter bandwidthMe
Clock.DEFAULT
);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
DefaultTrackSelector.Parameters trackSelectorParameters = trackSelector.buildUponParameters()
.setMaxVideoBitrate(options.maxVideoBitrate())
.build();
trackSelector.setParameters(trackSelectorParameters);

ExoPlayerTrackSelector exoPlayerTrackSelector = ExoPlayerTrackSelector.newInstance(trackSelector);
ExoPlayerAudioTrackSelector audioTrackSelector = new ExoPlayerAudioTrackSelector(exoPlayerTrackSelector);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

class ExoPlayerFacade {

private static final boolean RESET_POSITION = true;
private static final boolean DO_NOT_RESET_STATE = false;

private final BandwidthMeterCreator bandwidthMeterCreator;
Expand Down Expand Up @@ -136,7 +135,14 @@ void loadVideo(PlayerSurfaceHolder playerSurfaceHolder,
bandwidthMeter
);
attachToSurface(playerSurfaceHolder);
exoPlayer.prepare(mediaSource, RESET_POSITION, DO_NOT_RESET_STATE);

boolean hasInitialPosition = options.getInitialPositionInMillis().isPresent();
if (hasInitialPosition) {
Long initialPositionInMillis = options.getInitialPositionInMillis().get();
exoPlayer.seekTo(initialPositionInMillis);
}

exoPlayer.prepare(mediaSource, !hasInitialPosition, DO_NOT_RESET_STATE);
}

private void setMovieAudioAttributes(SimpleExoPlayer exoPlayer) {
Expand Down Expand Up @@ -231,10 +237,19 @@ float getVolume() {
return exoPlayer.getVolume();
}

void clearMaxVideoBitrate() {
assertVideoLoaded();
compositeTrackSelector.clearMaxVideoBitrate();
}

void setMaxVideoBitrate(int maxVideoBitrate) {
assertVideoLoaded();
compositeTrackSelector.setMaxVideoBitrate(maxVideoBitrate);
}

private void assertVideoLoaded() {
if (exoPlayer == null) {
throw new IllegalStateException("Video must be loaded before trying to interact with the player");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ public float getVolume() {
return exoPlayer.getVolume();
}

@Override
public void clearMaxVideoBitrate() {
exoPlayer.clearMaxVideoBitrate();
}

@Override
public void setMaxVideoBitrate(int maxVideoBitrate) {
exoPlayer.setMaxVideoBitrate(maxVideoBitrate);
}

@Override
public Listeners getListeners() {
return listenersHolder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,20 @@ boolean supportsTrackSwitching(TrackType trackType,
&& trackGroups.get(groupIndex).length > 0
&& trackInfo().getAdaptiveSupport(audioRendererIndex.get(), groupIndex, false) != RendererCapabilities.ADAPTIVE_NOT_SUPPORTED;
}

void clearMaxVideoBitrate() {
setMaxVideoBitrateParameter(Integer.MAX_VALUE);
}

void setMaxVideoBitrate(int maxVideoBitrate) {
setMaxVideoBitrateParameter(maxVideoBitrate);
}

private void setMaxVideoBitrateParameter(int maxValue) {
trackSelector.setParameters(
trackSelector.buildUponParameters()
.setMaxVideoBitrate(maxValue)
.build()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,12 @@ private Optional<PlayerVideoTrack> findSelectedVideoTrack(Format selectedVideoFo
public boolean clearVideoTrack(RendererTypeRequester rendererTypeRequester) {
return trackSelector.clearSelectionOverrideFor(VIDEO, rendererTypeRequester);
}

public void clearMaxVideoBitrate() {
trackSelector.clearMaxVideoBitrate();
}

public void setMaxVideoBitrate(int maxVideoBitrate) {
trackSelector.setMaxVideoBitrate(maxVideoBitrate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import static com.novoda.noplayer.internal.mediaplayer.PlaybackStateChecker.PlaybackState.PAUSED;
import static com.novoda.noplayer.internal.mediaplayer.PlaybackStateChecker.PlaybackState.PLAYING;

// Not much we can do, wrapping MediaPlayer is a lot of work
@SuppressWarnings("PMD.GodClass")
class AndroidMediaPlayerFacade {

private static final Map<String, String> NO_HEADERS = null;
Expand Down Expand Up @@ -322,4 +324,14 @@ float getVolume() {
assertIsInPlaybackState();
return volume;
}

void clearMaxVideoBitrate() {
assertIsInPlaybackState();
NoPlayerLog.w("Tried to clear max video bitrate but has not been implemented for MediaPlayer.");
}

void setMaxVideoBitrate(int maxVideoBitrate) {
assertIsInPlaybackState();
NoPlayerLog.w("Tried to set max video bitrate but has not been implemented for MediaPlayer.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;

import com.novoda.noplayer.Listeners;
import com.novoda.noplayer.NoPlayer;
import com.novoda.noplayer.Options;
Expand Down Expand Up @@ -366,6 +367,16 @@ public List<PlayerSubtitleTrack> getSubtitleTracks() throws IllegalStateExceptio
return mediaPlayer.getSubtitleTracks();
}

@Override
public void clearMaxVideoBitrate() {
mediaPlayer.clearMaxVideoBitrate();
}

@Override
public void setMaxVideoBitrate(int maxVideoBitrate) {
mediaPlayer.setMaxVideoBitrate(maxVideoBitrate);
}

@Override
public void stop() {
reset();
Expand Down
Loading

0 comments on commit ecfe867

Please sign in to comment.