Commit 6fc5e6b9 by olly Committed by Oliver Woodman

Migrate HLS to Format.Builder

Issue: #2863
PiperOrigin-RevId: 296482726
parent f342df20
......@@ -1347,39 +1347,6 @@ public final class Format implements Parcelable {
return buildUpon().setLabel(label).build();
}
// TODO: Inline into HlsSampleStreamWrapper and remove.
public Format copyWithContainerInfo(
@Nullable String id,
@Nullable String label,
@Nullable String sampleMimeType,
@Nullable String codecs,
@Nullable Metadata metadata,
int bitrate,
int width,
int height,
int channelCount,
@C.SelectionFlags int selectionFlags,
@Nullable String language) {
if (this.metadata != null) {
metadata = this.metadata.copyWithAppendedEntriesFrom(metadata);
}
return buildUpon()
.setId(id)
.setLabel(label)
.setLanguage(language)
.setSelectionFlags(selectionFlags)
.setAverageBitrate(bitrate)
.setPeakBitrate(bitrate)
.setMetadata(metadata)
.setCodecs(codecs)
.setSampleMimeType(sampleMimeType)
.setWidth(width)
.setHeight(height)
.setChannelCount(channelCount)
.build();
}
/** @deprecated Use {@link #withManifestFormatInfo(Format)}. */
@Deprecated
public Format copyWithManifestFormatInfo(Format manifestFormat) {
......
......@@ -235,15 +235,11 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
// closed caption track on channel 0.
muxedCaptionFormats =
Collections.singletonList(
Format.createTextSampleFormat(
/* id= */ null,
MimeTypes.APPLICATION_CEA608,
/* selectionFlags= */ 0,
/* language= */ null));
new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_CEA608).build());
} else {
muxedCaptionFormats = Collections.emptyList();
}
String codecs = format.codecs;
@Nullable String codecs = format.codecs;
if (!TextUtils.isEmpty(codecs)) {
// Sometimes AAC and H264 streams are declared in TS chunks even though they don't really
// exist. If we know from the codec attribute that they don't exist, then we can
......
......@@ -659,7 +659,11 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
}
TrackGroup id3TrackGroup =
new TrackGroup(Format.createSampleFormat(/* id= */ "ID3", MimeTypes.APPLICATION_ID3));
new TrackGroup(
new Format.Builder()
.setId("ID3")
.setSampleMimeType(MimeTypes.APPLICATION_ID3)
.build());
muxedTrackGroups.add(id3TrackGroup);
sampleStreamWrapper.prepareWithMasterPlaylistInfo(
......@@ -785,33 +789,34 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
}
private static Format deriveVideoFormat(Format variantFormat) {
String codecs = Util.getCodecsOfType(variantFormat.codecs, C.TRACK_TYPE_VIDEO);
String sampleMimeType = MimeTypes.getMediaMimeType(codecs);
return Format.createVideoContainerFormat(
variantFormat.id,
variantFormat.label,
variantFormat.containerMimeType,
sampleMimeType,
codecs,
variantFormat.metadata,
variantFormat.bitrate,
variantFormat.width,
variantFormat.height,
variantFormat.frameRate,
/* initializationData= */ null,
variantFormat.selectionFlags,
variantFormat.roleFlags);
@Nullable String codecs = Util.getCodecsOfType(variantFormat.codecs, C.TRACK_TYPE_VIDEO);
@Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs);
return new Format.Builder()
.setId(variantFormat.id)
.setLabel(variantFormat.label)
.setContainerMimeType(variantFormat.containerMimeType)
.setSampleMimeType(sampleMimeType)
.setCodecs(codecs)
.setMetadata(variantFormat.metadata)
.setAverageBitrate(variantFormat.averageBitrate)
.setPeakBitrate(variantFormat.peakBitrate)
.setWidth(variantFormat.width)
.setHeight(variantFormat.height)
.setFrameRate(variantFormat.frameRate)
.setSelectionFlags(variantFormat.selectionFlags)
.setRoleFlags(variantFormat.roleFlags)
.build();
}
private static Format deriveAudioFormat(
Format variantFormat, @Nullable Format mediaTagFormat, boolean isPrimaryTrackInVariant) {
String codecs;
Metadata metadata;
@Nullable String codecs;
@Nullable Metadata metadata;
int channelCount = Format.NO_VALUE;
int selectionFlags = 0;
int roleFlags = 0;
String language = null;
String label = null;
@Nullable String language = null;
@Nullable String label = null;
if (mediaTagFormat != null) {
codecs = mediaTagFormat.codecs;
metadata = mediaTagFormat.metadata;
......@@ -831,22 +836,23 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
label = variantFormat.label;
}
}
String sampleMimeType = MimeTypes.getMediaMimeType(codecs);
int bitrate = isPrimaryTrackInVariant ? variantFormat.bitrate : Format.NO_VALUE;
return Format.createAudioContainerFormat(
variantFormat.id,
label,
variantFormat.containerMimeType,
sampleMimeType,
codecs,
metadata,
bitrate,
channelCount,
/* sampleRate= */ Format.NO_VALUE,
/* initializationData= */ null,
selectionFlags,
roleFlags,
language);
@Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs);
int averageBitrate = isPrimaryTrackInVariant ? variantFormat.averageBitrate : Format.NO_VALUE;
int peakBitrate = isPrimaryTrackInVariant ? variantFormat.peakBitrate : Format.NO_VALUE;
return new Format.Builder()
.setId(variantFormat.id)
.setLabel(label)
.setContainerMimeType(variantFormat.containerMimeType)
.setSampleMimeType(sampleMimeType)
.setCodecs(codecs)
.setMetadata(metadata)
.setAverageBitrate(averageBitrate)
.setPeakBitrate(peakBitrate)
.setChannelCount(channelCount)
.setSelectionFlags(selectionFlags)
.setRoleFlags(roleFlags)
.setLanguage(language)
.build();
}
}
......@@ -1269,38 +1269,50 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
*
* @param playlistFormat The format information obtained from the master playlist.
* @param sampleFormat The format information obtained from the samples.
* @param propagateBitrate Whether the bitrate from the playlist format should be included in the
* derived format.
* @param propagateBitrates Whether the bitrates from the playlist format should be included in
* the derived format.
* @return The derived track format.
*/
private static Format deriveFormat(
@Nullable Format playlistFormat, Format sampleFormat, boolean propagateBitrate) {
@Nullable Format playlistFormat, Format sampleFormat, boolean propagateBitrates) {
if (playlistFormat == null) {
return sampleFormat;
}
int bitrate = propagateBitrate ? playlistFormat.bitrate : Format.NO_VALUE;
int channelCount =
playlistFormat.channelCount != Format.NO_VALUE
? playlistFormat.channelCount
: sampleFormat.channelCount;
int sampleTrackType = MimeTypes.getTrackType(sampleFormat.sampleMimeType);
@Nullable String codecs = Util.getCodecsOfType(playlistFormat.codecs, sampleTrackType);
@Nullable String mimeType = MimeTypes.getMediaMimeType(codecs);
if (mimeType == null) {
mimeType = sampleFormat.sampleMimeType;
}
return sampleFormat.copyWithContainerInfo(
playlistFormat.id,
playlistFormat.label,
mimeType,
codecs,
playlistFormat.metadata,
bitrate,
playlistFormat.width,
playlistFormat.height,
channelCount,
playlistFormat.selectionFlags,
playlistFormat.language);
@Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs);
Format.Builder formatBuilder =
sampleFormat
.buildUpon()
.setId(playlistFormat.id)
.setLabel(playlistFormat.label)
.setLanguage(playlistFormat.language)
.setSelectionFlags(playlistFormat.selectionFlags)
.setAverageBitrate(propagateBitrates ? playlistFormat.averageBitrate : Format.NO_VALUE)
.setPeakBitrate(propagateBitrates ? playlistFormat.peakBitrate : Format.NO_VALUE)
.setCodecs(codecs)
.setWidth(playlistFormat.width)
.setHeight(playlistFormat.height);
if (sampleMimeType != null) {
formatBuilder.setSampleMimeType(sampleMimeType);
}
if (playlistFormat.channelCount != Format.NO_VALUE) {
formatBuilder.setChannelCount(playlistFormat.channelCount);
}
if (playlistFormat.metadata != null) {
Metadata metadata = playlistFormat.metadata;
if (sampleFormat.metadata != null) {
metadata = sampleFormat.metadata.copyWithAppendedEntriesFrom(metadata);
}
formatBuilder.setMetadata(metadata);
}
return formatBuilder.build();
}
private static boolean isMediaChunk(Chunk chunk) {
......@@ -1409,9 +1421,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
// TODO(ibaker): Create a Formats util class with common constants like this.
private static final Format ID3_FORMAT =
Format.createSampleFormat(/* id= */ null, MimeTypes.APPLICATION_ID3);
new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_ID3).build();
private static final Format EMSG_FORMAT =
Format.createSampleFormat(/* id= */ null, MimeTypes.APPLICATION_EMSG);
new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_EMSG).build();
private final EventMessageDecoder emsgDecoder;
private final TrackOutput delegate;
......
......@@ -187,9 +187,11 @@ public final class WebvttExtractor implements Extractor {
private TrackOutput buildTrackOutput(long subsampleOffsetUs) {
TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_TEXT);
trackOutput.format(
Format.createTextSampleFormat(
/* id= */ null, MimeTypes.TEXT_VTT, /* selectionFlags= */ 0, language)
.copyWithSubsampleOffsetUs(subsampleOffsetUs));
new Format.Builder()
.setSampleMimeType(MimeTypes.TEXT_VTT)
.setLanguage(language)
.setSubsampleOffsetUs(subsampleOffsetUs)
.build());
output.endTracks();
return trackOutput;
}
......
......@@ -102,16 +102,7 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
*/
public static Variant createMediaPlaylistVariantUrl(Uri url) {
Format format =
Format.createContainerFormat(
"0",
/* label= */ null,
MimeTypes.APPLICATION_M3U8,
/* sampleMimeType= */ null,
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
/* selectionFlags= */ 0,
/* roleFlags= */ 0,
/* language= */ null);
new Format.Builder().setId("0").setContainerMimeType(MimeTypes.APPLICATION_M3U8).build();
return new Variant(
url,
format,
......
......@@ -55,11 +55,11 @@ public final class HlsMediaPeriodTest {
HlsMasterPlaylist testMasterPlaylist =
createMasterPlaylist(
/* variants= */ Arrays.asList(
createAudioOnlyVariant(/* bitrate= */ 10000),
createMuxedVideoAudioVariant(/* bitrate= */ 200000),
createAudioOnlyVariant(/* bitrate= */ 300000),
createMuxedVideoAudioVariant(/* bitrate= */ 400000),
createMuxedVideoAudioVariant(/* bitrate= */ 600000)),
createAudioOnlyVariant(/* peakBitrate= */ 10000),
createMuxedVideoAudioVariant(/* peakBitrate= */ 200000),
createAudioOnlyVariant(/* peakBitrate= */ 300000),
createMuxedVideoAudioVariant(/* peakBitrate= */ 400000),
createMuxedVideoAudioVariant(/* peakBitrate= */ 600000)),
/* audios= */ Arrays.asList(
createAudioRendition(/* language= */ "spa"),
createAudioRendition(/* language= */ "ger"),
......@@ -121,40 +121,22 @@ public final class HlsMediaPeriodTest {
/* sessionKeyDrmInitData= */ Collections.emptyList());
}
private static Variant createMuxedVideoAudioVariant(int bitrate) {
private static Variant createMuxedVideoAudioVariant(int peakBitrate) {
return createVariant(
Format.createVideoContainerFormat(
/* id= */ null,
/* label= */ null,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
/* sampleMimeType= */ null,
/* codecs= */ "avc1.100.41,mp4a.40.2",
/* metadata= */ null,
bitrate,
/* width= */ Format.NO_VALUE,
/* height= */ Format.NO_VALUE,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* selectionFlags= */ 0,
/* roleFlags= */ 0));
new Format.Builder()
.setContainerMimeType(MimeTypes.APPLICATION_M3U8)
.setCodecs("avc1.100.41,mp4a.40.2")
.setPeakBitrate(peakBitrate)
.build());
}
private static Variant createAudioOnlyVariant(int bitrate) {
private static Variant createAudioOnlyVariant(int peakBitrate) {
return createVariant(
Format.createVideoContainerFormat(
/* id= */ null,
/* label= */ null,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
/* sampleMimeType= */ null,
/* codecs= */ "mp4a.40.2",
/* metadata= */ null,
bitrate,
/* width= */ Format.NO_VALUE,
/* height= */ Format.NO_VALUE,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* selectionFlags= */ 0,
/* roleFlags= */ 0));
new Format.Builder()
.setContainerMimeType(MimeTypes.APPLICATION_M3U8)
.setCodecs("mp4a.40.2")
.setPeakBitrate(peakBitrate)
.build());
}
private static Rendition createAudioRendition(String language) {
......@@ -174,32 +156,19 @@ public final class HlsMediaPeriodTest {
}
private static Format createAudioFormat(String language) {
return Format.createAudioContainerFormat(
/* id= */ null,
/* label= */ null,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
MimeTypes.getMediaMimeType("mp4a.40.2"),
/* codecs= */ "mp4a.40.2",
/* metadata= */ null,
/* bitrate= */ Format.NO_VALUE,
/* channelCount= */ Format.NO_VALUE,
/* sampleRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* selectionFlags= */ 0,
/* roleFlags= */ 0,
language);
return new Format.Builder()
.setContainerMimeType(MimeTypes.APPLICATION_M3U8)
.setSampleMimeType(MimeTypes.getMediaMimeType("mp4a.40.2"))
.setCodecs("mp4a.40.2")
.setLanguage(language)
.build();
}
private static Format createSubtitleFormat(String language) {
return Format.createTextContainerFormat(
/* id= */ null,
/* label= */ null,
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
/* sampleMimeType= */ MimeTypes.TEXT_VTT,
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
/* selectionFlags= */ 0,
/* roleFlags= */ 0,
language);
return new Format.Builder()
.setContainerMimeType(MimeTypes.APPLICATION_M3U8)
.setSampleMimeType(MimeTypes.TEXT_VTT)
.setLanguage(language)
.build();
}
}
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