Add microsecond precision to MediaItem.ClippingConfiguration
PiperOrigin-RevId: 578881990
This commit is contained in:
parent
dab9eb33a4
commit
3253f1b5cd
@ -18,6 +18,8 @@ package androidx.media3.common;
|
|||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
|
import static androidx.media3.common.util.Util.msToUs;
|
||||||
|
import static androidx.media3.common.util.Util.usToMs;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -1837,20 +1839,20 @@ public final class MediaItem implements Bundleable {
|
|||||||
|
|
||||||
/** Builder for {@link ClippingConfiguration} instances. */
|
/** Builder for {@link ClippingConfiguration} instances. */
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private long startPositionMs;
|
private long startPositionUs;
|
||||||
private long endPositionMs;
|
private long endPositionUs;
|
||||||
private boolean relativeToLiveWindow;
|
private boolean relativeToLiveWindow;
|
||||||
private boolean relativeToDefaultPosition;
|
private boolean relativeToDefaultPosition;
|
||||||
private boolean startsAtKeyFrame;
|
private boolean startsAtKeyFrame;
|
||||||
|
|
||||||
/** Creates a new instance with default values. */
|
/** Creates a new instance with default values. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
endPositionMs = C.TIME_END_OF_SOURCE;
|
endPositionUs = C.TIME_END_OF_SOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder(ClippingConfiguration clippingConfiguration) {
|
private Builder(ClippingConfiguration clippingConfiguration) {
|
||||||
startPositionMs = clippingConfiguration.startPositionMs;
|
startPositionUs = clippingConfiguration.startPositionUs;
|
||||||
endPositionMs = clippingConfiguration.endPositionMs;
|
endPositionUs = clippingConfiguration.endPositionUs;
|
||||||
relativeToLiveWindow = clippingConfiguration.relativeToLiveWindow;
|
relativeToLiveWindow = clippingConfiguration.relativeToLiveWindow;
|
||||||
relativeToDefaultPosition = clippingConfiguration.relativeToDefaultPosition;
|
relativeToDefaultPosition = clippingConfiguration.relativeToDefaultPosition;
|
||||||
startsAtKeyFrame = clippingConfiguration.startsAtKeyFrame;
|
startsAtKeyFrame = clippingConfiguration.startsAtKeyFrame;
|
||||||
@ -1862,8 +1864,18 @@ public final class MediaItem implements Bundleable {
|
|||||||
*/
|
*/
|
||||||
@CanIgnoreReturnValue
|
@CanIgnoreReturnValue
|
||||||
public Builder setStartPositionMs(@IntRange(from = 0) long startPositionMs) {
|
public Builder setStartPositionMs(@IntRange(from = 0) long startPositionMs) {
|
||||||
Assertions.checkArgument(startPositionMs >= 0);
|
return setStartPositionUs(msToUs(startPositionMs));
|
||||||
this.startPositionMs = startPositionMs;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional start position in microseconds which must be a value larger than or equal
|
||||||
|
* to zero (Default: 0).
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setStartPositionUs(@IntRange(from = 0) long startPositionUs) {
|
||||||
|
Assertions.checkArgument(startPositionUs >= 0);
|
||||||
|
this.startPositionUs = startPositionUs;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,8 +1886,19 @@ public final class MediaItem implements Bundleable {
|
|||||||
*/
|
*/
|
||||||
@CanIgnoreReturnValue
|
@CanIgnoreReturnValue
|
||||||
public Builder setEndPositionMs(long endPositionMs) {
|
public Builder setEndPositionMs(long endPositionMs) {
|
||||||
Assertions.checkArgument(endPositionMs == C.TIME_END_OF_SOURCE || endPositionMs >= 0);
|
return setEndPositionUs(msToUs(endPositionMs));
|
||||||
this.endPositionMs = endPositionMs;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional end position in milliseconds which must be a value larger than or equal
|
||||||
|
* to zero, or {@link C#TIME_END_OF_SOURCE} to end when playback reaches the end of media
|
||||||
|
* (Default: {@link C#TIME_END_OF_SOURCE}).
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setEndPositionUs(long endPositionUs) {
|
||||||
|
Assertions.checkArgument(endPositionUs == C.TIME_END_OF_SOURCE || endPositionUs >= 0);
|
||||||
|
this.endPositionUs = endPositionUs;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1932,12 +1955,23 @@ public final class MediaItem implements Bundleable {
|
|||||||
@IntRange(from = 0)
|
@IntRange(from = 0)
|
||||||
public final long startPositionMs;
|
public final long startPositionMs;
|
||||||
|
|
||||||
|
/** The start position in microseconds. This is a value larger than or equal to zero. */
|
||||||
|
@UnstableApi
|
||||||
|
@IntRange(from = 0)
|
||||||
|
public final long startPositionUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The end position in milliseconds. This is a value larger than or equal to zero or {@link
|
* The end position in milliseconds. This is a value larger than or equal to zero or {@link
|
||||||
* C#TIME_END_OF_SOURCE} to play to the end of the stream.
|
* C#TIME_END_OF_SOURCE} to play to the end of the stream.
|
||||||
*/
|
*/
|
||||||
public final long endPositionMs;
|
public final long endPositionMs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The end position in microseconds. This is a value larger than or equal to zero or {@link
|
||||||
|
* C#TIME_END_OF_SOURCE} to play to the end of the stream.
|
||||||
|
*/
|
||||||
|
@UnstableApi public final long endPositionUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the clipping of active media periods moves with a live window. If {@code false},
|
* Whether the clipping of active media periods moves with a live window. If {@code false},
|
||||||
* playback ends when it reaches {@link #endPositionMs}.
|
* playback ends when it reaches {@link #endPositionMs}.
|
||||||
@ -1954,8 +1988,10 @@ public final class MediaItem implements Bundleable {
|
|||||||
public final boolean startsAtKeyFrame;
|
public final boolean startsAtKeyFrame;
|
||||||
|
|
||||||
private ClippingConfiguration(Builder builder) {
|
private ClippingConfiguration(Builder builder) {
|
||||||
this.startPositionMs = builder.startPositionMs;
|
this.startPositionMs = usToMs(builder.startPositionUs);
|
||||||
this.endPositionMs = builder.endPositionMs;
|
this.endPositionMs = usToMs(builder.endPositionUs);
|
||||||
|
this.startPositionUs = builder.startPositionUs;
|
||||||
|
this.endPositionUs = builder.endPositionUs;
|
||||||
this.relativeToLiveWindow = builder.relativeToLiveWindow;
|
this.relativeToLiveWindow = builder.relativeToLiveWindow;
|
||||||
this.relativeToDefaultPosition = builder.relativeToDefaultPosition;
|
this.relativeToDefaultPosition = builder.relativeToDefaultPosition;
|
||||||
this.startsAtKeyFrame = builder.startsAtKeyFrame;
|
this.startsAtKeyFrame = builder.startsAtKeyFrame;
|
||||||
@ -1977,8 +2013,8 @@ public final class MediaItem implements Bundleable {
|
|||||||
|
|
||||||
ClippingConfiguration other = (ClippingConfiguration) obj;
|
ClippingConfiguration other = (ClippingConfiguration) obj;
|
||||||
|
|
||||||
return startPositionMs == other.startPositionMs
|
return startPositionUs == other.startPositionUs
|
||||||
&& endPositionMs == other.endPositionMs
|
&& endPositionUs == other.endPositionUs
|
||||||
&& relativeToLiveWindow == other.relativeToLiveWindow
|
&& relativeToLiveWindow == other.relativeToLiveWindow
|
||||||
&& relativeToDefaultPosition == other.relativeToDefaultPosition
|
&& relativeToDefaultPosition == other.relativeToDefaultPosition
|
||||||
&& startsAtKeyFrame == other.startsAtKeyFrame;
|
&& startsAtKeyFrame == other.startsAtKeyFrame;
|
||||||
@ -1986,8 +2022,8 @@ public final class MediaItem implements Bundleable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = (int) (startPositionMs ^ (startPositionMs >>> 32));
|
int result = (int) (startPositionUs ^ (startPositionUs >>> 32));
|
||||||
result = 31 * result + (int) (endPositionMs ^ (endPositionMs >>> 32));
|
result = 31 * result + (int) (endPositionUs ^ (endPositionUs >>> 32));
|
||||||
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);
|
||||||
@ -2001,6 +2037,8 @@ public final class MediaItem implements Bundleable {
|
|||||||
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);
|
||||||
|
static final String FIELD_END_POSITION_US = Util.intToStringMaxRadix(6);
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@Override
|
@Override
|
||||||
@ -2012,6 +2050,12 @@ public final class MediaItem implements Bundleable {
|
|||||||
if (endPositionMs != UNSET.endPositionMs) {
|
if (endPositionMs != UNSET.endPositionMs) {
|
||||||
bundle.putLong(FIELD_END_POSITION_MS, endPositionMs);
|
bundle.putLong(FIELD_END_POSITION_MS, endPositionMs);
|
||||||
}
|
}
|
||||||
|
if (startPositionUs != UNSET.startPositionUs) {
|
||||||
|
bundle.putLong(FIELD_START_POSITION_US, startPositionUs);
|
||||||
|
}
|
||||||
|
if (endPositionUs != UNSET.endPositionUs) {
|
||||||
|
bundle.putLong(FIELD_END_POSITION_US, endPositionUs);
|
||||||
|
}
|
||||||
if (relativeToLiveWindow != UNSET.relativeToLiveWindow) {
|
if (relativeToLiveWindow != UNSET.relativeToLiveWindow) {
|
||||||
bundle.putBoolean(FIELD_RELATIVE_TO_LIVE_WINDOW, relativeToLiveWindow);
|
bundle.putBoolean(FIELD_RELATIVE_TO_LIVE_WINDOW, relativeToLiveWindow);
|
||||||
}
|
}
|
||||||
@ -2027,25 +2071,38 @@ public final class MediaItem implements Bundleable {
|
|||||||
/** An object that can restore {@link ClippingConfiguration} from a {@link Bundle}. */
|
/** An object that can restore {@link ClippingConfiguration} from a {@link Bundle}. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public static final Creator<ClippingProperties> CREATOR =
|
public static final Creator<ClippingProperties> CREATOR =
|
||||||
bundle ->
|
bundle -> {
|
||||||
new ClippingConfiguration.Builder()
|
ClippingConfiguration.Builder clippingConfiguration =
|
||||||
.setStartPositionMs(
|
new ClippingConfiguration.Builder()
|
||||||
bundle.getLong(
|
.setStartPositionMs(
|
||||||
FIELD_START_POSITION_MS, /* defaultValue= */ UNSET.startPositionMs))
|
bundle.getLong(
|
||||||
.setEndPositionMs(
|
FIELD_START_POSITION_MS, /* defaultValue= */ UNSET.startPositionMs))
|
||||||
bundle.getLong(FIELD_END_POSITION_MS, /* defaultValue= */ UNSET.endPositionMs))
|
.setEndPositionMs(
|
||||||
.setRelativeToLiveWindow(
|
bundle.getLong(
|
||||||
bundle.getBoolean(
|
FIELD_END_POSITION_MS, /* defaultValue= */ UNSET.endPositionMs))
|
||||||
FIELD_RELATIVE_TO_LIVE_WINDOW,
|
.setRelativeToLiveWindow(
|
||||||
/* defaultValue= */ UNSET.relativeToLiveWindow))
|
bundle.getBoolean(
|
||||||
.setRelativeToDefaultPosition(
|
FIELD_RELATIVE_TO_LIVE_WINDOW,
|
||||||
bundle.getBoolean(
|
/* defaultValue= */ UNSET.relativeToLiveWindow))
|
||||||
FIELD_RELATIVE_TO_DEFAULT_POSITION,
|
.setRelativeToDefaultPosition(
|
||||||
/* defaultValue= */ UNSET.relativeToDefaultPosition))
|
bundle.getBoolean(
|
||||||
.setStartsAtKeyFrame(
|
FIELD_RELATIVE_TO_DEFAULT_POSITION,
|
||||||
bundle.getBoolean(
|
/* defaultValue= */ UNSET.relativeToDefaultPosition))
|
||||||
FIELD_STARTS_AT_KEY_FRAME, /* defaultValue= */ UNSET.startsAtKeyFrame))
|
.setStartsAtKeyFrame(
|
||||||
.buildClippingProperties();
|
bundle.getBoolean(
|
||||||
|
FIELD_STARTS_AT_KEY_FRAME, /* defaultValue= */ UNSET.startsAtKeyFrame));
|
||||||
|
long startPositionUs =
|
||||||
|
bundle.getLong(FIELD_START_POSITION_US, /* defaultValue= */ UNSET.startPositionUs);
|
||||||
|
if (startPositionUs != UNSET.startPositionUs) {
|
||||||
|
clippingConfiguration.setStartPositionUs(startPositionUs);
|
||||||
|
}
|
||||||
|
long endPositionUs =
|
||||||
|
bundle.getLong(FIELD_END_POSITION_US, /* defaultValue= */ UNSET.endPositionUs);
|
||||||
|
if (endPositionUs != UNSET.endPositionUs) {
|
||||||
|
clippingConfiguration.setEndPositionUs(endPositionUs);
|
||||||
|
}
|
||||||
|
return clippingConfiguration.buildClippingProperties();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.common;
|
package androidx.media3.common;
|
||||||
|
|
||||||
|
import static androidx.media3.common.MediaItem.ClippingConfiguration.FIELD_END_POSITION_US;
|
||||||
|
import static androidx.media3.common.MediaItem.ClippingConfiguration.FIELD_START_POSITION_US;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
||||||
@ -438,7 +440,9 @@ public class MediaItemTest {
|
|||||||
// Please refrain from altering default values since doing so would cause issues with backwards
|
// Please refrain from altering default values since doing so would cause issues with backwards
|
||||||
// compatibility.
|
// compatibility.
|
||||||
assertThat(clippingConfiguration.startPositionMs).isEqualTo(0L);
|
assertThat(clippingConfiguration.startPositionMs).isEqualTo(0L);
|
||||||
|
assertThat(clippingConfiguration.startPositionUs).isEqualTo(0L);
|
||||||
assertThat(clippingConfiguration.endPositionMs).isEqualTo(C.TIME_END_OF_SOURCE);
|
assertThat(clippingConfiguration.endPositionMs).isEqualTo(C.TIME_END_OF_SOURCE);
|
||||||
|
assertThat(clippingConfiguration.endPositionUs).isEqualTo(C.TIME_END_OF_SOURCE);
|
||||||
assertThat(clippingConfiguration.relativeToLiveWindow).isFalse();
|
assertThat(clippingConfiguration.relativeToLiveWindow).isFalse();
|
||||||
assertThat(clippingConfiguration.relativeToDefaultPosition).isFalse();
|
assertThat(clippingConfiguration.relativeToDefaultPosition).isFalse();
|
||||||
assertThat(clippingConfiguration.startsAtKeyFrame).isFalse();
|
assertThat(clippingConfiguration.startsAtKeyFrame).isFalse();
|
||||||
@ -468,6 +472,7 @@ public class MediaItemTest {
|
|||||||
MediaItem.ClippingConfiguration clippingConfiguration =
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
new MediaItem.ClippingConfiguration.Builder()
|
new MediaItem.ClippingConfiguration.Builder()
|
||||||
.setStartPositionMs(1000L)
|
.setStartPositionMs(1000L)
|
||||||
|
.setEndPositionUs(2000_031L)
|
||||||
.setStartsAtKeyFrame(true)
|
.setStartsAtKeyFrame(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -477,6 +482,51 @@ public class MediaItemTest {
|
|||||||
assertThat(clippingConfigurationFromBundle).isEqualTo(clippingConfiguration);
|
assertThat(clippingConfigurationFromBundle).isEqualTo(clippingConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createClippingConfigurationInstance_viaBundleWithOnlyMs_yieldsEqualInstance() {
|
||||||
|
// Creates instance by setting some non-default values
|
||||||
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
|
new MediaItem.ClippingConfiguration.Builder()
|
||||||
|
.setStartPositionMs(1000L)
|
||||||
|
.setEndPositionMs(2000L)
|
||||||
|
.setStartsAtKeyFrame(true)
|
||||||
|
.build();
|
||||||
|
Bundle clippingConfigurationBundle = clippingConfiguration.toBundle();
|
||||||
|
clippingConfigurationBundle.remove(FIELD_START_POSITION_US);
|
||||||
|
clippingConfigurationBundle.remove(FIELD_END_POSITION_US);
|
||||||
|
|
||||||
|
MediaItem.ClippingConfiguration clippingConfigurationFromBundle =
|
||||||
|
MediaItem.ClippingConfiguration.CREATOR.fromBundle(clippingConfigurationBundle);
|
||||||
|
|
||||||
|
assertThat(clippingConfigurationFromBundle).isEqualTo(clippingConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createClippingConfigurationInstance_setsStartPositionInMsAndUs_fieldsAreConsistent() {
|
||||||
|
// Creates instance by setting some non-default values
|
||||||
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
|
new MediaItem.ClippingConfiguration.Builder()
|
||||||
|
.setStartPositionMs(1000L)
|
||||||
|
.setStartPositionUs(200_203L)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(clippingConfiguration.startPositionMs).isEqualTo(200L);
|
||||||
|
assertThat(clippingConfiguration.startPositionUs).isEqualTo(200_203L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createClippingConfigurationInstance_setsEndPositionInMsAndUs_fieldsAreConsistent() {
|
||||||
|
// Creates instance by setting some non-default values
|
||||||
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
|
new MediaItem.ClippingConfiguration.Builder()
|
||||||
|
.setEndPositionUs(1000L)
|
||||||
|
.setEndPositionMs(C.TIME_END_OF_SOURCE)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(clippingConfiguration.endPositionMs).isEqualTo(C.TIME_END_OF_SOURCE);
|
||||||
|
assertThat(clippingConfiguration.endPositionMs).isEqualTo(C.TIME_END_OF_SOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clippingConfigurationBuilder_throwsOnInvalidValues() {
|
public void clippingConfigurationBuilder_throwsOnInvalidValues() {
|
||||||
MediaItem.ClippingConfiguration.Builder clippingConfigurationBuilder =
|
MediaItem.ClippingConfiguration.Builder clippingConfigurationBuilder =
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkArgument;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.common.util.Util.usToMs;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -154,16 +155,17 @@ public final class ConcatenatingMediaSource2 extends CompositeMediaSource<Intege
|
|||||||
@CanIgnoreReturnValue
|
@CanIgnoreReturnValue
|
||||||
public Builder add(MediaItem mediaItem, long initialPlaceholderDurationMs) {
|
public Builder add(MediaItem mediaItem, long initialPlaceholderDurationMs) {
|
||||||
checkNotNull(mediaItem);
|
checkNotNull(mediaItem);
|
||||||
checkStateNotNull(
|
|
||||||
mediaSourceFactory,
|
|
||||||
"Must use useDefaultMediaSourceFactory or setMediaSourceFactory first.");
|
|
||||||
if (initialPlaceholderDurationMs == C.TIME_UNSET
|
if (initialPlaceholderDurationMs == C.TIME_UNSET
|
||||||
&& mediaItem.clippingConfiguration.endPositionMs != C.TIME_END_OF_SOURCE) {
|
&& mediaItem.clippingConfiguration.endPositionMs != C.TIME_END_OF_SOURCE) {
|
||||||
// If the item is going to be clipped, we can provide a placeholder duration automatically.
|
// If the item is going to be clipped, we can provide a placeholder duration automatically.
|
||||||
initialPlaceholderDurationMs =
|
initialPlaceholderDurationMs =
|
||||||
mediaItem.clippingConfiguration.endPositionMs
|
usToMs(
|
||||||
- mediaItem.clippingConfiguration.startPositionMs;
|
mediaItem.clippingConfiguration.endPositionUs
|
||||||
|
- mediaItem.clippingConfiguration.startPositionUs);
|
||||||
}
|
}
|
||||||
|
checkStateNotNull(
|
||||||
|
mediaSourceFactory,
|
||||||
|
"Must use useDefaultMediaSourceFactory or setMediaSourceFactory first.");
|
||||||
return add(mediaSourceFactory.createMediaSource(mediaItem), initialPlaceholderDurationMs);
|
return add(mediaSourceFactory.createMediaSource(mediaItem), initialPlaceholderDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +366,7 @@ public final class ConcatenatingMediaSource2 extends CompositeMediaSource<Intege
|
|||||||
if (timeOffsetUs == null) {
|
if (timeOffsetUs == null) {
|
||||||
return mediaTimeMs;
|
return mediaTimeMs;
|
||||||
}
|
}
|
||||||
return mediaTimeMs + Util.usToMs(timeOffsetUs);
|
return mediaTimeMs + usToMs(timeOffsetUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleMessage(Message msg) {
|
private boolean handleMessage(Message msg) {
|
||||||
|
@ -554,15 +554,15 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||||||
// internal methods
|
// internal methods
|
||||||
|
|
||||||
private static MediaSource maybeClipMediaSource(MediaItem mediaItem, MediaSource mediaSource) {
|
private static MediaSource maybeClipMediaSource(MediaItem mediaItem, MediaSource mediaSource) {
|
||||||
if (mediaItem.clippingConfiguration.startPositionMs == 0
|
if (mediaItem.clippingConfiguration.startPositionUs == 0
|
||||||
&& mediaItem.clippingConfiguration.endPositionMs == C.TIME_END_OF_SOURCE
|
&& mediaItem.clippingConfiguration.endPositionUs == C.TIME_END_OF_SOURCE
|
||||||
&& !mediaItem.clippingConfiguration.relativeToDefaultPosition) {
|
&& !mediaItem.clippingConfiguration.relativeToDefaultPosition) {
|
||||||
return mediaSource;
|
return mediaSource;
|
||||||
}
|
}
|
||||||
return new ClippingMediaSource(
|
return new ClippingMediaSource(
|
||||||
mediaSource,
|
mediaSource,
|
||||||
msToUs(mediaItem.clippingConfiguration.startPositionMs),
|
mediaItem.clippingConfiguration.startPositionUs,
|
||||||
msToUs(mediaItem.clippingConfiguration.endPositionMs),
|
mediaItem.clippingConfiguration.endPositionUs,
|
||||||
/* enableInitialDiscontinuity= */ !mediaItem.clippingConfiguration.startsAtKeyFrame,
|
/* enableInitialDiscontinuity= */ !mediaItem.clippingConfiguration.startsAtKeyFrame,
|
||||||
/* allowDynamicClippingUpdates= */ mediaItem.clippingConfiguration.relativeToLiveWindow,
|
/* allowDynamicClippingUpdates= */ mediaItem.clippingConfiguration.relativeToLiveWindow,
|
||||||
mediaItem.clippingConfiguration.relativeToDefaultPosition);
|
mediaItem.clippingConfiguration.relativeToDefaultPosition);
|
||||||
|
@ -17,7 +17,6 @@ package androidx.media3.transformer;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Util.msToUs;
|
|
||||||
|
|
||||||
import androidx.annotation.IntRange;
|
import androidx.annotation.IntRange;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
@ -276,12 +275,12 @@ public final class EditedMediaItem {
|
|||||||
} else {
|
} else {
|
||||||
MediaItem.ClippingConfiguration clippingConfiguration = mediaItem.clippingConfiguration;
|
MediaItem.ClippingConfiguration clippingConfiguration = mediaItem.clippingConfiguration;
|
||||||
checkArgument(!clippingConfiguration.relativeToDefaultPosition);
|
checkArgument(!clippingConfiguration.relativeToDefaultPosition);
|
||||||
if (clippingConfiguration.endPositionMs == C.TIME_END_OF_SOURCE) {
|
if (clippingConfiguration.endPositionUs == C.TIME_END_OF_SOURCE) {
|
||||||
presentationDurationUs = durationUs - msToUs(clippingConfiguration.startPositionMs);
|
presentationDurationUs = durationUs - clippingConfiguration.startPositionUs;
|
||||||
} else {
|
} else {
|
||||||
checkArgument(clippingConfiguration.endPositionMs <= durationUs);
|
checkArgument(clippingConfiguration.endPositionUs <= durationUs);
|
||||||
presentationDurationUs =
|
presentationDurationUs =
|
||||||
msToUs(clippingConfiguration.endPositionMs - clippingConfiguration.startPositionMs);
|
clippingConfiguration.endPositionUs - clippingConfiguration.startPositionUs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,25 @@ public final class EditedMediaItemBuilderTest {
|
|||||||
assertThat(editedMediaItem.presentationDurationUs).isEqualTo(200_000);
|
assertThat(editedMediaItem.presentationDurationUs).isEqualTo(200_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void duration_withClippingConfigurationAndStartEndPositionInUs() {
|
||||||
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
|
new MediaItem.ClippingConfiguration.Builder()
|
||||||
|
.setStartPositionUs(300_000)
|
||||||
|
.setEndPositionUs(500_000)
|
||||||
|
.build();
|
||||||
|
MediaItem mediaItem =
|
||||||
|
new MediaItem.Builder()
|
||||||
|
.setUri("Uri")
|
||||||
|
.setClippingConfiguration(clippingConfiguration)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
EditedMediaItem editedMediaItem =
|
||||||
|
new EditedMediaItem.Builder(mediaItem).setDurationUs(1_000_000).build();
|
||||||
|
|
||||||
|
assertThat(editedMediaItem.presentationDurationUs).isEqualTo(200_000);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void duration_withClippingConfigurationAndStartPosition() {
|
public void duration_withClippingConfigurationAndStartPosition() {
|
||||||
MediaItem.ClippingConfiguration clippingConfiguration =
|
MediaItem.ClippingConfiguration clippingConfiguration =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user