Skip to content

Commit

Permalink
Merge pull request #40 from DiceTechnology/impr/DORIS-1085-label-miss…
Browse files Browse the repository at this point in the history
…-for-muxed-audio-only

chore: Polish the track group generate logic of multiple muxed audio tracks
  • Loading branch information
Guoen Yong authored Nov 18, 2021
2 parents c509688 + e5e58e8 commit 2d32da4
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -620,19 +620,22 @@ private void buildAndPrepareMainSampleStreamWrapper(
numberOfAudioCodecs <= 1
&& numberOfVideoCodecs <= 1
&& numberOfAudioCodecs + numberOfVideoCodecs > 0;
@Nullable List<Format> muxedAudioFormats = getMuxedAudioFormats(masterPlaylist);
HlsSampleStreamWrapper sampleStreamWrapper =
buildSampleStreamWrapper(
C.TRACK_TYPE_DEFAULT,
selectedPlaylistUrls,
selectedPlaylistFormats,
masterPlaylist.muxedAudioFormat,
muxedAudioFormats,
masterPlaylist.muxedCaptionFormats,
overridingDrmInitData,
positionUs);
sampleStreamWrappers.add(sampleStreamWrapper);
manifestUrlIndicesPerWrapper.add(selectedVariantIndices);
if (allowChunklessPreparation && codecsStringAllowsChunklessPreparation) {
List<TrackGroup> muxedTrackGroups = new ArrayList<>();
int muxedAudioFormatCount = (muxedAudioFormats == null ? 0 : muxedAudioFormats.size());
Format firstMuxedAudioFormat = (muxedAudioFormatCount > 0 ? muxedAudioFormats.get(0) : null);
if (numberOfVideoCodecs > 0) {
Format[] videoFormats = new Format[selectedVariantsCount];
for (int i = 0; i < videoFormats.length; i++) {
Expand All @@ -641,13 +644,14 @@ private void buildAndPrepareMainSampleStreamWrapper(
muxedTrackGroups.add(new TrackGroup(videoFormats));

if (numberOfAudioCodecs > 0
&& (masterPlaylist.muxedAudioFormat != null || masterPlaylist.audios.isEmpty())) {
muxedTrackGroups.add(
new TrackGroup(
deriveAudioFormat(
selectedPlaylistFormats[0],
masterPlaylist.muxedAudioFormat,
/* isPrimaryTrackInVariant= */ false)));
&& (muxedAudioFormats != null || masterPlaylist.audios.isEmpty())) {
Format variantFormat = selectedPlaylistFormats[0];
Format[] formats = new Format[muxedAudioFormatCount > 0 ? muxedAudioFormatCount : 1];
for (int i = 0; i < formats.length; i++) {
Format mediaTagFormat = (i < muxedAudioFormatCount ? muxedAudioFormats.get(i) : firstMuxedAudioFormat);
formats[i] = deriveAudioFormat(variantFormat, mediaTagFormat, false);
}
muxedTrackGroups.add(new TrackGroup(formats));
}
List<Format> ccFormats = masterPlaylist.muxedCaptionFormats;
if (ccFormats != null) {
Expand All @@ -659,10 +663,14 @@ private void buildAndPrepareMainSampleStreamWrapper(
// Variants only contain audio.
Format[] audioFormats = new Format[selectedVariantsCount];
for (int i = 0; i < audioFormats.length; i++) {
// TODO: We should change to find the matched muxedAudioFormat via audio group of
// variantFormat, But the format have not the group information, we will polish it here
// when supporting audio group feature later.
Format mediaTagFormat = (i < muxedAudioFormatCount ? muxedAudioFormats.get(i) : firstMuxedAudioFormat);
audioFormats[i] =
deriveAudioFormat(
/* variantFormat= */ selectedPlaylistFormats[i],
masterPlaylist.muxedAudioFormat,
mediaTagFormat,
/* isPrimaryTrackInVariant= */ true);
}
muxedTrackGroups.add(new TrackGroup(audioFormats));
Expand Down Expand Up @@ -700,8 +708,9 @@ private void buildAndPrepareAudioSampleStreamWrappers(
renditionByNameIndex < audioRenditions.size();
renditionByNameIndex++) {
String name = audioRenditions.get(renditionByNameIndex).name;
if (!alreadyGroupedNames.add(name)) {
// This name already has a corresponding group.
Uri url = audioRenditions.get(renditionByNameIndex).url;
if (!alreadyGroupedNames.add(name) || url == null) {
// This name already has a corresponding group. Or it is one muxed audio rendition.
continue;
}

Expand Down Expand Up @@ -745,7 +754,7 @@ private HlsSampleStreamWrapper buildSampleStreamWrapper(
int trackType,
Uri[] playlistUrls,
Format[] playlistFormats,
@Nullable Format muxedAudioFormat,
@Nullable List<Format> muxedAudioFormats,
@Nullable List<Format> muxedCaptionFormats,
Map<String, DrmInitData> overridingDrmInitData,
long positionUs) {
Expand All @@ -766,14 +775,50 @@ private HlsSampleStreamWrapper buildSampleStreamWrapper(
overridingDrmInitData,
allocator,
positionUs,
muxedAudioFormat,
muxedAudioFormats,
drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy,
eventDispatcher,
metadataType);
}

@Nullable
private static List<Format> getMuxedAudioFormats(HlsMasterPlaylist masterPlaylist) {
List<Format> muxedAudioFormats = new ArrayList<>();
for (int i = 0; i < masterPlaylist.variants.size(); i++) {
Format muxedAudioFormat = getMuxedAudioFormat(masterPlaylist.audios, masterPlaylist.variants.get(i));
if (muxedAudioFormat == null) {
continue;
}
boolean exist = false;
for (int j = 0; j < muxedAudioFormats.size(); j++) {
if (muxedAudioFormats.get(j) == muxedAudioFormat) {
exist = true;
break;
}
}
if (!exist) {
muxedAudioFormats.add(muxedAudioFormat);
}
}
return muxedAudioFormats.size() > 0 ? muxedAudioFormats : null;
}

@Nullable
private static Format getMuxedAudioFormat(List<HlsMasterPlaylist.Rendition> audioRenditions, HlsMasterPlaylist.Variant variant) {
if (variant.audioGroupId == null) {
return null;
}
for (int i = 0; i < audioRenditions.size(); i++) {
HlsMasterPlaylist.Rendition audio = audioRenditions.get(i);
if (audio.url == null && variant.audioGroupId.equals(audio.groupId)) {
return audio.format;
}
}
return null;
}

private static Map<String, DrmInitData> deriveOverridingDrmInitData(
List<DrmInitData> sessionKeyDrmInitData) {
ArrayList<DrmInitData> mutableSessionKeyDrmInitData = new ArrayList<>(sessionKeyDrmInitData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public interface Callback extends SequenceableLoader.Callback<HlsSampleStreamWra
private final Callback callback;
private final HlsChunkSource chunkSource;
private final Allocator allocator;
@Nullable private final Format muxedAudioFormat;
@Nullable private final List<Format> muxedAudioFormats;
private final DrmSessionManager drmSessionManager;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
Expand Down Expand Up @@ -189,7 +189,7 @@ public interface Callback extends SequenceableLoader.Callback<HlsSampleStreamWra
* stream's {@link DrmInitData} will be overridden.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations.
* @param positionUs The position from which to start loading media.
* @param muxedAudioFormat Optional muxed audio {@link Format} as defined by the master playlist.
* @param muxedAudioFormats Optional list of muxed audio {@link Format}.
* @param drmSessionManager The {@link DrmSessionManager} to acquire {@link DrmSession
* DrmSessions} with.
* @param drmEventDispatcher A dispatcher to notify of {@link DrmSessionEventListener} events.
Expand All @@ -204,7 +204,7 @@ public HlsSampleStreamWrapper(
Map<String, DrmInitData> overridingDrmInitData,
Allocator allocator,
long positionUs,
@Nullable Format muxedAudioFormat,
@Nullable List<Format> muxedAudioFormats,
DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy,
Expand All @@ -215,7 +215,7 @@ public HlsSampleStreamWrapper(
this.chunkSource = chunkSource;
this.overridingDrmInitData = overridingDrmInitData;
this.allocator = allocator;
this.muxedAudioFormat = muxedAudioFormat;
this.muxedAudioFormats = muxedAudioFormats;
this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
Expand Down Expand Up @@ -1343,16 +1343,6 @@ private void buildTracksFromSampleStreams() {
TrackGroup chunkSourceTrackGroup = chunkSource.getTrackGroup();
int chunkSourceTrackCount = chunkSourceTrackGroup.length;

// Workaround for audio-only stream, https://github.com/google/ExoPlayer/issues/9608
if (primaryExtractorTrackType == C.TRACK_TYPE_AUDIO && chunkSourceTrackCount > 0) {
Format trackFormat = chunkSourceTrackGroup.getFormat(0);
boolean isAudioOnlyChunk = (trackFormat.bitrate > 0);
if (isAudioOnlyChunk) {
primaryExtractorTrackType = C.TRACK_TYPE_VIDEO;
primaryExtractorTrackIndex = C.INDEX_UNSET;
}
}

// Instantiate the necessary internal data-structures.
primaryTrackGroupIndex = C.INDEX_UNSET;
trackGroupToSampleQueueIndex = new int[extractorTrackCount];
Expand All @@ -1365,24 +1355,46 @@ private void buildTracksFromSampleStreams() {
for (int i = 0; i < extractorTrackCount; i++) {
Format sampleFormat = Assertions.checkStateNotNull(sampleQueues[i].getUpstreamFormat());
if (i == primaryExtractorTrackIndex) {
@Nullable List<Format> muxedAudioFormats = this.muxedAudioFormats;
int muxedAudioFormatCount = (muxedAudioFormats == null ? 0 : muxedAudioFormats.size());
Format firstMuxedAudioFormat = (muxedAudioFormatCount > 0 ? muxedAudioFormats.get(0) : null);
Format[] formats = new Format[chunkSourceTrackCount];
if (chunkSourceTrackCount == 1) {
formats[0] = sampleFormat.withManifestFormatInfo(chunkSourceTrackGroup.getFormat(0));
} else {
for (int j = 0; j < chunkSourceTrackCount; j++) {
formats[j] = deriveFormat(chunkSourceTrackGroup.getFormat(j), sampleFormat, true);
for (int j = 0; j < chunkSourceTrackCount; j++) {
Format playlistFormat = chunkSourceTrackGroup.getFormat(j);
if (primaryExtractorTrackType == C.TRACK_TYPE_AUDIO && muxedAudioFormatCount > 0) {
// TODO: We should change to find the matched muxedAudioFormat via audio group of
// variantFormat, But the format have not the group information, we will polish it here
// when supporting audio group feature later.
Format muxedAudioFormat = (j < muxedAudioFormatCount ? muxedAudioFormats.get(j) : firstMuxedAudioFormat);
// The format.language may be miss if use playlistFormat.withManifestFormatInfo(muxedAudioFormat)
// because of the playlistFormat.sampleMimeType is null.
playlistFormat = muxedAudioFormat;
}
// If there's only a single variant (chunkSourceTrackCount == 1) then we can safely
// retain all fields from sampleFormat. Else we need to use deriveFormat to retain only
// the fields that will be the same for all variants.
formats[j] =
chunkSourceTrackCount == 1
? sampleFormat.withManifestFormatInfo(playlistFormat)
: deriveFormat(playlistFormat, sampleFormat, /* propagateBitrates= */ true);
}
trackGroups[i] = new TrackGroup(formats);
primaryTrackGroupIndex = i;
} else {
@Nullable
Format trackFormat =
List<Format> muxedAudioFormats =
primaryExtractorTrackType == C.TRACK_TYPE_VIDEO
&& MimeTypes.isAudio(sampleFormat.sampleMimeType)
? muxedAudioFormat
? this.muxedAudioFormats
: null;
trackGroups[i] = new TrackGroup(deriveFormat(trackFormat, sampleFormat, false));
int muxedAudioFormatCount = (muxedAudioFormats == null ? 0 : muxedAudioFormats.size());
Format firstMuxedAudioFormat = (muxedAudioFormatCount > 0 ? muxedAudioFormats.get(0) : null);
Format[] formats = new Format[muxedAudioFormatCount > 0 ? muxedAudioFormatCount : 1];
for (int j = 0; j < formats.length; j++) {
Format playlistFormat = (j < muxedAudioFormatCount ? muxedAudioFormats.get(j) : firstMuxedAudioFormat);
formats[j] = deriveFormat(playlistFormat, sampleFormat, false);
}
trackGroups[i] = new TrackGroup(formats);
}
}
this.trackGroups = createTrackGroupArrayWithDrmInfo(trackGroups);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,13 +511,9 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri
}
}
formatBuilder.setSampleMimeType(sampleMimeType);
if (uri != null) {
formatBuilder.setMetadata(metadata);
audios.add(new Rendition(uri, formatBuilder.build(), groupId, name));
} else if (variant != null) {
// TODO: Remove muxedAudioFormat and add a Rendition with a null uri to audios.
muxedAudioFormat = formatBuilder.build();
}
// Remove muxedAudioFormat and add a Rendition with a null uri to audios.
formatBuilder.setMetadata(metadata);
audios.add(new Rendition(uri, formatBuilder.build(), groupId, name));
break;
case TYPE_SUBTITLES:
sampleMimeType = null;
Expand Down

0 comments on commit 2d32da4

Please sign in to comment.