Skip to content

Commit

Permalink
Add a CustomData field to the Format class
Browse files Browse the repository at this point in the history
Summary:
    This change aims to add a generic `CustomData` field to the `Format` class.

    The intent is to allow ExoPlayer customers to add extra data to the Format class without forcing
    specific data to be included, impacting customers that do not need it and would allow for the data
    to be changed without requiring changes to the `Media3` codebase.
  • Loading branch information
khouzam committed Jun 3, 2024
1 parent 387153f commit b183232
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ public static final class Builder {

private @C.CryptoType int cryptoType;

// Extra custom data added to the class.
@Nullable private Object customData;

/** Creates a new instance with default values. */
public Builder() {
labels = ImmutableList.of();
Expand All @@ -221,6 +224,10 @@ public Builder() {
tileCountVertical = NO_VALUE;
// Provided by the source.
cryptoType = C.CRYPTO_TYPE_NONE;
// CustomData optionally created
if (customDataAllocator != null) {
customData = customDataAllocator.createCustomData();
}
}

/**
Expand Down Expand Up @@ -270,6 +277,8 @@ private Builder(Format format) {
this.tileCountVertical = format.tileCountVertical;
// Provided by the source.
this.cryptoType = format.cryptoType;
// Extra custom data added to the class.
this.customData = format.customData;
}

/**
Expand Down Expand Up @@ -714,6 +723,20 @@ public Builder setCryptoType(@C.CryptoType int cryptoType) {
return this;
}

// Extra custom data added to the class.

/**
* Sets the opaque object {@link Format#customData}. The default value is null.
*
* @param customData The {@link Format#customData}.
* @return The builder.
*/
@CanIgnoreReturnValue
public Builder setCustomData(@Nullable Object customData) {
this.customData = customData;
return this;
}

// Build.

public Format build() {
Expand Down Expand Up @@ -964,6 +987,31 @@ public Format build() {
*/
@UnstableApi public final @C.CryptoType int cryptoType;

/**
* An extra opaque object that can be added to the {@link Format} to provide additional information
* that can be passed through the player.
*/
@UnstableApi @Nullable public final Object customData;

/**
* Interface to create a new @{link CustomData} object.
*/
public interface CustomDataAllocator {
Object createCustomData();
}

/**
* Set the default {@link CustomDataAllocator} to be used when creating {@link Format} instances.
*/
@UnstableApi public static void setDefaultCustomDataAllocator(@Nullable CustomDataAllocator defaultCustomDataAllocator) {
customDataAllocator = defaultCustomDataAllocator;
}

/**
* The default {@link CustomDataAllocator} to be used when creating {@link Format} instances.
*/
@UnstableApi @Nullable private static CustomDataAllocator customDataAllocator;

// Lazily initialized hashcode.
private int hashCode;

Expand Down Expand Up @@ -1038,6 +1086,8 @@ private Format(Builder builder) {
} else {
cryptoType = builder.cryptoType;
}
// Extra custom data added to the class.
customData = builder.customData;
}

/** Returns a {@link Format.Builder} initialized with the values of this instance. */
Expand Down Expand Up @@ -1212,6 +1262,8 @@ public int hashCode() {
result = 31 * result + tileCountVertical;
// Provided by the source.
result = 31 * result + cryptoType;
// Extra custom data added to the class.
result = 31 * result + (customData == null ? 0 : customData.hashCode());
hashCode = result;
}
return hashCode;
Expand Down Expand Up @@ -1262,7 +1314,8 @@ public boolean equals(@Nullable Object obj) {
&& Util.areEqual(metadata, other.metadata)
&& Util.areEqual(colorInfo, other.colorInfo)
&& Util.areEqual(drmInitData, other.drmInitData)
&& initializationDataEquals(other);
&& initializationDataEquals(other)
&& Util.areEqual(customData, other.customData);
}

/**
Expand Down Expand Up @@ -1360,6 +1413,9 @@ public static String toLogString(@Nullable Format format) {
Joiner.on(',').appendTo(builder, Util.getRoleFlagStrings(format.roleFlags));
builder.append("]");
}
if (format.customData != null) {
builder.append(", customData=").append(format.customData);
}
return builder.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.junit.Assert.assertThrows;

import android.os.Bundle;
import androidx.media3.common.util.Util;
import androidx.media3.test.utils.FakeMetadataEntry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
Expand All @@ -35,6 +36,53 @@
@RunWith(AndroidJUnit4.class)
public final class FormatTest {

public static class ExoCustomData {

public final String extraMetadata;
public final int customInt;

public ExoCustomData(String extraMetadata, int customInt) {
this.extraMetadata = extraMetadata;
this.customInt = customInt;
}

@Override
public int hashCode() {
int result = 17;
result = 31 * result + (extraMetadata == null ? 0 : extraMetadata.hashCode());
result = 31 * result + customInt;
return result;
}

@Override
public String toString() {
return "ExoCustomData = ["
+ "extraMetadata='"
+ extraMetadata
+ "', customInt="
+ customInt
+ ", hashCode="
+ hashCode()
+ "]";
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
ExoCustomData other = (ExoCustomData) obj;
return Util.areEqual(extraMetadata, other.extraMetadata) && customInt == other.customInt;
}

public static Object createCustomData() {
return new ExoCustomData("", -1);
}
}

@Test
public void buildUponFormat_createsEqualFormat() {
Format testFormat = createTestFormat();
Expand Down Expand Up @@ -115,7 +163,26 @@ public void formatBuild_withLabelAndLabelsSetButNoMatch_throwsException() {
.build());
}

private static Format createTestFormat() {
@Test
public void setDefaultCustomDataAllocator_addsCustomData() {
Format.setDefaultCustomDataAllocator(ExoCustomData::createCustomData);
Format format = new Format.Builder().build();

assertThat(format.customData).isInstanceOf(ExoCustomData.class);
assertThat(format.customData).isEqualTo(ExoCustomData.createCustomData());
}

@Test
public void copyFormat_copiesCustomData() {
Format.setDefaultCustomDataAllocator(ExoCustomData::createCustomData);
Format format = createTestFormat().buildUpon().setCustomData(new ExoCustomData("CustomData", 100)).build();

Format copy = format.buildUpon().build();
assertThat(format.customData).isEqualTo(copy.customData);
assertThat(format.customData).isEqualTo(new ExoCustomData("CustomData", 100));
}

private static Format createTestFormat() {
byte[] initData1 = new byte[] {1, 2, 3};
byte[] initData2 = new byte[] {4, 5, 6};
List<byte[]> initializationData = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ private boolean drainOutputBuffer()
.setEncoderDelay(encoderDelay)
.setEncoderPadding(encoderPadding)
.setMetadata(inputFormat.metadata)
.setCustomData(inputFormat.customData)
.setId(inputFormat.id)
.setLabel(inputFormat.label)
.setLabels(inputFormat.labels)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaF
.setEncoderDelay(format.encoderDelay)
.setEncoderPadding(format.encoderPadding)
.setMetadata(format.metadata)
.setCustomData(format.customData)
.setId(format.id)
.setLabel(format.label)
.setLabels(format.labels)
Expand Down

0 comments on commit b183232

Please sign in to comment.