Commit 42d4afe7 by olly Committed by Oliver Woodman

Make Format.Builder, peakBitrate and averageBitrate public

- Deprecate old Format.createXXX methods
- Deprecate most Format.copyXXX methods
- Stop using deprecated Format.copyXXX methods in the library

Note: Replacing library usages of Format.createXXX method
will be done in follow up CLs. These changes aren't purely
mechanical because we need to decide which out of peakBitrate
and averageBitrate to set in each case where currently a
single bitrate is provided.

Issue: #2863
PiperOrigin-RevId: 296450935
parent 4c05201a
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
* Add a sample count parameter to `MediaCodecRenderer.processOutputBuffer` * Add a sample count parameter to `MediaCodecRenderer.processOutputBuffer`
and `AudioSink.handleBuffer` to allow batching multiple encoded frames and `AudioSink.handleBuffer` to allow batching multiple encoded frames
in one buffer. in one buffer.
* Add a `Format.Builder` and deprecate all `Format.create*` methods and most
`Format.copyWith*` methods.
* Split `Format.bitrate` into `Format.averageBitrate` and `Format.peakBitrate`
([#2863](https://github.com/google/ExoPlayer/issues/2863)).
* Text: * Text:
* Parse `<ruby>` and `<rt>` tags in WebVTT subtitles (rendering is coming * Parse `<ruby>` and `<rt>` tags in WebVTT subtitles (rendering is coming
later). later).
......
...@@ -32,7 +32,11 @@ import java.util.Map; ...@@ -32,7 +32,11 @@ import java.util.Map;
*/ */
public final class DataSpec { public final class DataSpec {
/** Builds {@link DataSpec} instances. */ /**
* Builds {@link DataSpec} instances.
*
* <p>Use DataSpec#buildUpon() to obtain a builder representing an existing {@link DataSpec}.
*/
public static final class Builder { public static final class Builder {
@Nullable private Uri uri; @Nullable private Uri uri;
......
...@@ -699,7 +699,8 @@ public final class PlaybackStatsListener ...@@ -699,7 +699,8 @@ public final class PlaybackStatsListener
*/ */
public void onVideoSizeChanged(EventTime eventTime, int width, int height) { public void onVideoSizeChanged(EventTime eventTime, int width, int height) {
if (currentVideoFormat != null && currentVideoFormat.height == Format.NO_VALUE) { if (currentVideoFormat != null && currentVideoFormat.height == Format.NO_VALUE) {
Format formatWithHeight = currentVideoFormat.copyWithVideoSize(width, height); Format formatWithHeight =
currentVideoFormat.buildUpon().setWidth(width).setHeight(height).build();
maybeUpdateVideoFormat(eventTime, formatWithHeight); maybeUpdateVideoFormat(eventTime, formatWithHeight);
} }
} }
......
...@@ -317,7 +317,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -317,7 +317,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
// Clear gapless playback metadata if the start/end points don't match the media. // Clear gapless playback metadata if the start/end points don't match the media.
int encoderDelay = startUs != 0 ? 0 : format.encoderDelay; int encoderDelay = startUs != 0 ? 0 : format.encoderDelay;
int encoderPadding = endUs != C.TIME_END_OF_SOURCE ? 0 : format.encoderPadding; int encoderPadding = endUs != C.TIME_END_OF_SOURCE ? 0 : format.encoderPadding;
formatHolder.format = format.copyWithGaplessInfo(encoderDelay, encoderPadding); formatHolder.format =
format
.buildUpon()
.setEncoderDelay(encoderDelay)
.setEncoderPadding(encoderPadding)
.build();
} }
return C.RESULT_FORMAT_READ; return C.RESULT_FORMAT_READ;
} }
......
...@@ -734,10 +734,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -734,10 +734,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
? new Metadata(icyHeaders) ? new Metadata(icyHeaders)
: metadata.copyWithAppendedEntries(icyHeaders)); : metadata.copyWithAppendedEntries(icyHeaders));
} }
// Update the track format with the bitrate from the ICY header only if it declares neither
// an average or peak bitrate of its own.
if (isAudio if (isAudio
&& trackFormat.bitrate == Format.NO_VALUE && trackFormat.averageBitrate == Format.NO_VALUE
&& trackFormat.peakBitrate == Format.NO_VALUE
&& icyHeaders.bitrate != Format.NO_VALUE) { && icyHeaders.bitrate != Format.NO_VALUE) {
trackFormat = trackFormat.copyWithBitrate(icyHeaders.bitrate); trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build();
} }
} }
trackArray[i] = new TrackGroup(trackFormat); trackArray[i] = new TrackGroup(trackFormat);
......
...@@ -197,8 +197,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput { ...@@ -197,8 +197,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
@Override @Override
public void format(Format format) { public void format(Format format) {
sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat) sampleFormat =
: format; manifestFormat != null ? format.withManifestFormatInfo(manifestFormat) : format;
castNonNull(trackOutput).format(sampleFormat); castNonNull(trackOutput).format(sampleFormat);
} }
......
...@@ -98,7 +98,7 @@ public final class DashUtil { ...@@ -98,7 +98,7 @@ public final class DashUtil {
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation); Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
return sampleFormat == null return sampleFormat == null
? manifestFormat.drmInitData ? manifestFormat.drmInitData
: sampleFormat.copyWithManifestFormatInfo(manifestFormat).drmInitData; : sampleFormat.withManifestFormatInfo(manifestFormat).drmInitData;
} }
/** /**
......
...@@ -284,25 +284,22 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -284,25 +284,22 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private MetadataUtil() {} private MetadataUtil() {}
/** /** Updates a {@link Format.Builder} to include metadata from the provided sources. */
* Returns a {@link Format} that is the same as the input format but includes information from the public static void setFormatMetadata(
* specified sources of metadata.
*/
public static Format getFormatWithMetadata(
int trackType, int trackType,
Format format,
@Nullable Metadata udtaMetadata, @Nullable Metadata udtaMetadata,
@Nullable Metadata mdtaMetadata, @Nullable Metadata mdtaMetadata,
GaplessInfoHolder gaplessInfoHolder) { GaplessInfoHolder gaplessInfoHolder,
Format.Builder formatBuilder) {
if (trackType == C.TRACK_TYPE_AUDIO) { if (trackType == C.TRACK_TYPE_AUDIO) {
if (gaplessInfoHolder.hasGaplessInfo()) { if (gaplessInfoHolder.hasGaplessInfo()) {
format = formatBuilder
format.copyWithGaplessInfo( .setEncoderDelay(gaplessInfoHolder.encoderDelay)
gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding); .setEncoderPadding(gaplessInfoHolder.encoderPadding);
} }
// We assume all udta metadata is associated with the audio track. // We assume all udta metadata is associated with the audio track.
if (udtaMetadata != null) { if (udtaMetadata != null) {
format = format.copyWithMetadata(udtaMetadata); formatBuilder.setMetadata(udtaMetadata);
} }
} else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) { } else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) {
// Populate only metadata keys that are known to be specific to video. // Populate only metadata keys that are known to be specific to video.
...@@ -311,12 +308,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -311,12 +308,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
if (entry instanceof MdtaMetadataEntry) { if (entry instanceof MdtaMetadataEntry) {
MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry; MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)) { if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)) {
format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry)); formatBuilder.setMetadata(new Metadata(mdtaMetadataEntry));
} }
} }
} }
} }
return format;
} }
/** /**
......
...@@ -423,17 +423,17 @@ public final class Mp4Extractor implements Extractor, SeekMap { ...@@ -423,17 +423,17 @@ public final class Mp4Extractor implements Extractor, SeekMap {
// Each sample has up to three bytes of overhead for the start code that replaces its length. // Each sample has up to three bytes of overhead for the start code that replaces its length.
// Allow ten source samples per output sample, like the platform extractor. // Allow ten source samples per output sample, like the platform extractor.
int maxInputSize = trackSampleTable.maximumSize + 3 * 10; int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
Format format = track.format.copyWithMaxInputSize(maxInputSize); Format.Builder formatBuilder = track.format.buildUpon();
formatBuilder.setMaxInputSize(maxInputSize);
if (track.type == C.TRACK_TYPE_VIDEO if (track.type == C.TRACK_TYPE_VIDEO
&& trackDurationUs > 0 && trackDurationUs > 0
&& trackSampleTable.sampleCount > 1) { && trackSampleTable.sampleCount > 1) {
float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f); float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f);
format = format.copyWithFrameRate(frameRate); formatBuilder.setFrameRate(frameRate);
} }
format = MetadataUtil.setFormatMetadata(
MetadataUtil.getFormatWithMetadata( track.type, udtaMetadata, mdtaMetadata, gaplessInfoHolder, formatBuilder);
track.type, format, udtaMetadata, mdtaMetadata, gaplessInfoHolder); mp4Track.trackOutput.format(formatBuilder.build());
mp4Track.trackOutput.format(format);
if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) { if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) {
firstVideoTrackIndex = tracks.size(); firstVideoTrackIndex = tracks.size();
......
...@@ -568,7 +568,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -568,7 +568,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
chunkIndex < mediaChunks.size() chunkIndex < mediaChunks.size()
? mediaChunks.get(chunkIndex).trackFormat ? mediaChunks.get(chunkIndex).trackFormat
: Assertions.checkNotNull(upstreamTrackFormat); : Assertions.checkNotNull(upstreamTrackFormat);
format = format.copyWithManifestFormatInfo(trackFormat); format = format.withManifestFormatInfo(trackFormat);
} }
formatHolder.format = format; formatHolder.format = format;
} }
...@@ -1160,7 +1160,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1160,7 +1160,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
if (i == primaryExtractorTrackIndex) { if (i == primaryExtractorTrackIndex) {
Format[] formats = new Format[chunkSourceTrackCount]; Format[] formats = new Format[chunkSourceTrackCount];
if (chunkSourceTrackCount == 1) { if (chunkSourceTrackCount == 1) {
formats[0] = sampleFormat.copyWithManifestFormatInfo(chunkSourceTrackGroup.getFormat(0)); formats[0] = sampleFormat.withManifestFormatInfo(chunkSourceTrackGroup.getFormat(0));
} else { } else {
for (int j = 0; j < chunkSourceTrackCount; j++) { for (int j = 0; j < chunkSourceTrackCount; j++) {
formats[j] = deriveFormat(chunkSourceTrackGroup.getFormat(j), sampleFormat, true); formats[j] = deriveFormat(chunkSourceTrackGroup.getFormat(j), sampleFormat, true);
...@@ -1346,6 +1346,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1346,6 +1346,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
invalidateUpstreamFormatAdjustment(); invalidateUpstreamFormatAdjustment();
} }
@SuppressWarnings("ReferenceEquality")
@Override @Override
public Format getAdjustedUpstreamFormat(Format format) { public Format getAdjustedUpstreamFormat(Format format) {
@Nullable @Nullable
...@@ -1357,8 +1358,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1357,8 +1358,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
drmInitData = overridingDrmInitData; drmInitData = overridingDrmInitData;
} }
} }
return super.getAdjustedUpstreamFormat( @Nullable Metadata metadata = getAdjustedMetadata(format.metadata);
format.copyWithAdjustments(drmInitData, getAdjustedMetadata(format.metadata))); if (drmInitData != format.drmInitData || metadata != format.metadata) {
format = format.buildUpon().setDrmInitData(drmInitData).setMetadata(metadata).build();
}
return super.getAdjustedUpstreamFormat(format);
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment