Add ClippingConfiguration.allowUnseekableMedia

PiperOrigin-RevId: 731240278
This commit is contained in:
tonihei 2025-02-26 03:09:32 -08:00 committed by Copybara-Service
parent 676fe86028
commit 4f039eaafa
5 changed files with 43 additions and 6 deletions

View File

@ -1853,6 +1853,7 @@ public final class MediaItem {
private boolean relativeToLiveWindow; private boolean relativeToLiveWindow;
private boolean relativeToDefaultPosition; private boolean relativeToDefaultPosition;
private boolean startsAtKeyFrame; private boolean startsAtKeyFrame;
private boolean allowUnseekableMedia;
/** Creates a new instance with default values. */ /** Creates a new instance with default values. */
public Builder() { public Builder() {
@ -1865,6 +1866,7 @@ public final class MediaItem {
relativeToLiveWindow = clippingConfiguration.relativeToLiveWindow; relativeToLiveWindow = clippingConfiguration.relativeToLiveWindow;
relativeToDefaultPosition = clippingConfiguration.relativeToDefaultPosition; relativeToDefaultPosition = clippingConfiguration.relativeToDefaultPosition;
startsAtKeyFrame = clippingConfiguration.startsAtKeyFrame; startsAtKeyFrame = clippingConfiguration.startsAtKeyFrame;
allowUnseekableMedia = clippingConfiguration.allowUnseekableMedia;
} }
/** /**
@ -1942,6 +1944,21 @@ public final class MediaItem {
return this; return this;
} }
/**
* Sets whether clipping to a non-zero start position in unseekable media is allowed (Default:
* {@code false}).
*
* <p>Note that this could be inefficient because a player needs to read and decode all
* samples from the beginning of the file and it should only be used if the clip start
* position is small and the entire data before the start position fits into memory.
*/
@UnstableApi
@CanIgnoreReturnValue
public Builder setAllowUnseekableMedia(boolean allowUnseekableMedia) {
this.allowUnseekableMedia = allowUnseekableMedia;
return this;
}
/** /**
* Returns a {@link ClippingConfiguration} instance initialized with the values of this * Returns a {@link ClippingConfiguration} instance initialized with the values of this
* builder. * builder.
@ -1994,9 +2011,12 @@ public final class MediaItem {
*/ */
public final boolean relativeToDefaultPosition; public final boolean relativeToDefaultPosition;
/** Sets whether the start point is guaranteed to be a key frame. */ /** Whether the start point is guaranteed to be a key frame. */
public final boolean startsAtKeyFrame; public final boolean startsAtKeyFrame;
/** Whether clipping to a non-zero start position in unseekable media is allowed. */
@UnstableApi public final boolean allowUnseekableMedia;
private ClippingConfiguration(Builder builder) { private ClippingConfiguration(Builder builder) {
this.startPositionMs = usToMs(builder.startPositionUs); this.startPositionMs = usToMs(builder.startPositionUs);
this.endPositionMs = usToMs(builder.endPositionUs); this.endPositionMs = usToMs(builder.endPositionUs);
@ -2005,6 +2025,7 @@ public final class MediaItem {
this.relativeToLiveWindow = builder.relativeToLiveWindow; this.relativeToLiveWindow = builder.relativeToLiveWindow;
this.relativeToDefaultPosition = builder.relativeToDefaultPosition; this.relativeToDefaultPosition = builder.relativeToDefaultPosition;
this.startsAtKeyFrame = builder.startsAtKeyFrame; this.startsAtKeyFrame = builder.startsAtKeyFrame;
this.allowUnseekableMedia = builder.allowUnseekableMedia;
} }
/** Returns a {@link Builder} initialized with the values of this instance. */ /** Returns a {@link Builder} initialized with the values of this instance. */
@ -2027,7 +2048,8 @@ public final class MediaItem {
&& endPositionUs == other.endPositionUs && endPositionUs == other.endPositionUs
&& relativeToLiveWindow == other.relativeToLiveWindow && relativeToLiveWindow == other.relativeToLiveWindow
&& relativeToDefaultPosition == other.relativeToDefaultPosition && relativeToDefaultPosition == other.relativeToDefaultPosition
&& startsAtKeyFrame == other.startsAtKeyFrame; && startsAtKeyFrame == other.startsAtKeyFrame
&& allowUnseekableMedia == other.allowUnseekableMedia;
} }
@Override @Override
@ -2037,6 +2059,7 @@ public final class MediaItem {
result = 31 * result + (relativeToLiveWindow ? 1 : 0); result = 31 * result + (relativeToLiveWindow ? 1 : 0);
result = 31 * result + (relativeToDefaultPosition ? 1 : 0); result = 31 * result + (relativeToDefaultPosition ? 1 : 0);
result = 31 * result + (startsAtKeyFrame ? 1 : 0); result = 31 * result + (startsAtKeyFrame ? 1 : 0);
result = 31 * result + (allowUnseekableMedia ? 1 : 0);
return result; return result;
} }
@ -2045,8 +2068,9 @@ public final class MediaItem {
private static final String FIELD_RELATIVE_TO_LIVE_WINDOW = Util.intToStringMaxRadix(2); private static final String FIELD_RELATIVE_TO_LIVE_WINDOW = Util.intToStringMaxRadix(2);
private static final String FIELD_RELATIVE_TO_DEFAULT_POSITION = Util.intToStringMaxRadix(3); private static final String FIELD_RELATIVE_TO_DEFAULT_POSITION = Util.intToStringMaxRadix(3);
private static final String FIELD_STARTS_AT_KEY_FRAME = Util.intToStringMaxRadix(4); private static final String FIELD_STARTS_AT_KEY_FRAME = Util.intToStringMaxRadix(4);
static final String FIELD_START_POSITION_US = Util.intToStringMaxRadix(5); @VisibleForTesting static final String FIELD_START_POSITION_US = Util.intToStringMaxRadix(5);
static final String FIELD_END_POSITION_US = Util.intToStringMaxRadix(6); @VisibleForTesting static final String FIELD_END_POSITION_US = Util.intToStringMaxRadix(6);
private static final String FIELD_ALLOW_UNSEEKABLE_MEDIA = Util.intToStringMaxRadix(7);
@UnstableApi @UnstableApi
public Bundle toBundle() { public Bundle toBundle() {
@ -2072,6 +2096,9 @@ public final class MediaItem {
if (startsAtKeyFrame != UNSET.startsAtKeyFrame) { if (startsAtKeyFrame != UNSET.startsAtKeyFrame) {
bundle.putBoolean(FIELD_STARTS_AT_KEY_FRAME, startsAtKeyFrame); bundle.putBoolean(FIELD_STARTS_AT_KEY_FRAME, startsAtKeyFrame);
} }
if (allowUnseekableMedia != UNSET.allowUnseekableMedia) {
bundle.putBoolean(FIELD_ALLOW_UNSEEKABLE_MEDIA, allowUnseekableMedia);
}
return bundle; return bundle;
} }
@ -2096,7 +2123,11 @@ public final class MediaItem {
/* defaultValue= */ UNSET.relativeToDefaultPosition)) /* defaultValue= */ UNSET.relativeToDefaultPosition))
.setStartsAtKeyFrame( .setStartsAtKeyFrame(
bundle.getBoolean( bundle.getBoolean(
FIELD_STARTS_AT_KEY_FRAME, /* defaultValue= */ UNSET.startsAtKeyFrame)); FIELD_STARTS_AT_KEY_FRAME, /* defaultValue= */ UNSET.startsAtKeyFrame))
.setAllowUnseekableMedia(
bundle.getBoolean(
FIELD_ALLOW_UNSEEKABLE_MEDIA,
/* defaultValue= */ UNSET.allowUnseekableMedia));
long startPositionUs = long startPositionUs =
bundle.getLong(FIELD_START_POSITION_US, /* defaultValue= */ UNSET.startPositionUs); bundle.getLong(FIELD_START_POSITION_US, /* defaultValue= */ UNSET.startPositionUs);
if (startPositionUs != UNSET.startPositionUs) { if (startPositionUs != UNSET.startPositionUs) {

View File

@ -450,6 +450,7 @@ public class MediaItemTest {
.setRelativeToLiveWindow(true) .setRelativeToLiveWindow(true)
.setRelativeToDefaultPosition(true) .setRelativeToDefaultPosition(true)
.setStartsAtKeyFrame(true) .setStartsAtKeyFrame(true)
.setAllowUnseekableMedia(true)
.build()) .build())
.build(); .build();
@ -458,6 +459,7 @@ public class MediaItemTest {
assertThat(mediaItem.clippingConfiguration.relativeToLiveWindow).isTrue(); assertThat(mediaItem.clippingConfiguration.relativeToLiveWindow).isTrue();
assertThat(mediaItem.clippingConfiguration.relativeToDefaultPosition).isTrue(); assertThat(mediaItem.clippingConfiguration.relativeToDefaultPosition).isTrue();
assertThat(mediaItem.clippingConfiguration.startsAtKeyFrame).isTrue(); assertThat(mediaItem.clippingConfiguration.startsAtKeyFrame).isTrue();
assertThat(mediaItem.clippingConfiguration.allowUnseekableMedia).isTrue();
assertThat(mediaItem.clippingConfiguration).isEqualTo(mediaItem.clippingProperties); assertThat(mediaItem.clippingConfiguration).isEqualTo(mediaItem.clippingProperties);
} }
@ -475,6 +477,7 @@ public class MediaItemTest {
assertThat(clippingConfiguration.relativeToLiveWindow).isFalse(); assertThat(clippingConfiguration.relativeToLiveWindow).isFalse();
assertThat(clippingConfiguration.relativeToDefaultPosition).isFalse(); assertThat(clippingConfiguration.relativeToDefaultPosition).isFalse();
assertThat(clippingConfiguration.startsAtKeyFrame).isFalse(); assertThat(clippingConfiguration.startsAtKeyFrame).isFalse();
assertThat(clippingConfiguration.allowUnseekableMedia).isFalse();
assertThat(clippingConfiguration).isEqualTo(MediaItem.ClippingConfiguration.UNSET); assertThat(clippingConfiguration).isEqualTo(MediaItem.ClippingConfiguration.UNSET);
} }
@ -503,6 +506,7 @@ public class MediaItemTest {
.setStartPositionMs(1000L) .setStartPositionMs(1000L)
.setEndPositionUs(2000_031L) .setEndPositionUs(2000_031L)
.setStartsAtKeyFrame(true) .setStartsAtKeyFrame(true)
.setAllowUnseekableMedia(true)
.build(); .build();
MediaItem.ClippingConfiguration clippingConfigurationFromBundle = MediaItem.ClippingConfiguration clippingConfigurationFromBundle =

View File

@ -200,7 +200,7 @@ public final class ClippingMediaSource extends WrappingMediaSource {
* Sets whether clipping to a non-zero start position in unseekable media is allowed. * Sets whether clipping to a non-zero start position in unseekable media is allowed.
* *
* <p>Note that this is inefficient because the player needs to read and decode all samples from * <p>Note that this is inefficient because the player needs to read and decode all samples from
* the beginning of the file and it should only be used if the seek start position is small and * the beginning of the file and it should only be used if the clip start position is small and
* the entire data before the start position fits into memory. * the entire data before the start position fits into memory.
* *
* <p>The default value is {@code false}. * <p>The default value is {@code false}.

View File

@ -589,6 +589,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
.setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame) .setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame)
.setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow) .setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow)
.setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition) .setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition)
.setAllowUnseekableMedia(mediaItem.clippingConfiguration.allowUnseekableMedia)
.build(); .build();
} }

View File

@ -611,6 +611,7 @@ public final class ClippingMediaSourceTest {
.setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame) .setEnableInitialDiscontinuity(!mediaItem.clippingConfiguration.startsAtKeyFrame)
.setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow) .setAllowDynamicClippingUpdates(mediaItem.clippingConfiguration.relativeToLiveWindow)
.setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition) .setRelativeToDefaultPosition(mediaItem.clippingConfiguration.relativeToDefaultPosition)
.setAllowUnseekableMedia(mediaItem.clippingConfiguration.allowUnseekableMedia)
.build(); .build();
} }