Skip to content

Commit 1b44e0a

Browse files
committed
exoplayer: upd sabr classes
1 parent 6e8fddc commit 1b44e0a

File tree

14 files changed

+142
-66
lines changed

14 files changed

+142
-66
lines changed

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/DefaultSabrChunkSource.java

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,12 @@
3030
import com.google.android.exoplayer2.source.sabr.parser.models.CaptionSelector;
3131
import com.google.android.exoplayer2.source.sabr.parser.models.VideoSelector;
3232
import com.google.android.exoplayer2.source.sabr.parser.misc.Utils;
33-
import com.google.android.exoplayer2.source.sabr.protos.misc.FormatId;
3433
import com.google.android.exoplayer2.trackselection.TrackSelection;
3534
import com.google.android.exoplayer2.upstream.DataSource;
3635
import com.google.android.exoplayer2.upstream.DataSpec;
3736
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
3837
import com.google.android.exoplayer2.upstream.TransferListener;
3938
import com.google.android.exoplayer2.util.MimeTypes;
40-
import com.liskovsoft.sharedutils.helpers.Helpers;
4139

4240
import java.io.IOException;
4341
import java.util.ArrayList;
@@ -635,7 +633,7 @@ private static AudioSelector createAudioSelection(int trackType, TrackSelection
635633

636634
Format selectedFormat = trackSelection.getSelectedFormat();
637635

638-
return new AudioSelector(Helpers.firstNonNull(selectedFormat.label, "selected_audio"), false, createFormatId(selectedFormat));
636+
return new AudioSelector("selected_audio", false, selectedFormat);
639637
}
640638

641639
private static VideoSelector createVideoSelection(int trackType, TrackSelection trackSelection) {
@@ -645,7 +643,7 @@ private static VideoSelector createVideoSelection(int trackType, TrackSelection
645643

646644
Format selectedFormat = trackSelection.getSelectedFormat();
647645

648-
return new VideoSelector(Helpers.firstNonNull(selectedFormat.label, "selected_video"), false, createFormatId(selectedFormat));
646+
return new VideoSelector("selected_video", false, selectedFormat);
649647
}
650648

651649
private static CaptionSelector createCaptionSelection(int trackType, TrackSelection trackSelection) {
@@ -655,15 +653,7 @@ private static CaptionSelector createCaptionSelection(int trackType, TrackSelect
655653

656654
Format selectedFormat = trackSelection.getSelectedFormat();
657655

658-
return new CaptionSelector(Helpers.firstNonNull(selectedFormat.label, "selected_caption"), false, createFormatId(selectedFormat));
659-
}
660-
661-
private static FormatId createFormatId(Format format) {
662-
FormatId formatId = FormatId.newBuilder()
663-
.setItag(Helpers.parseInt(format.id))
664-
.setLastModified(format.lastModified)
665-
.build();
666-
return formatId;
656+
return new CaptionSelector("selected_caption", false, selectedFormat);
667657
}
668658

669659
/** {@link MediaChunkIterator} wrapping a {@link RepresentationHolder}. */

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/SabrProcessor.java

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import androidx.annotation.NonNull;
77

88
import com.google.android.exoplayer2.C;
9+
import com.google.android.exoplayer2.Format;
910
import com.google.android.exoplayer2.extractor.ExtractorInput;
1011
import com.google.android.exoplayer2.source.sabr.parser.exceptions.SabrStreamError;
12+
import com.google.android.exoplayer2.source.sabr.parser.misc.EnabledTrackTypes;
1113
import com.google.android.exoplayer2.source.sabr.parser.models.AudioSelector;
1214
import com.google.android.exoplayer2.source.sabr.parser.models.CaptionSelector;
1315
import com.google.android.exoplayer2.source.sabr.parser.models.ConsumedRange;
@@ -87,6 +89,7 @@ public class SabrProcessor {
8789
private List<FormatId> selectedAudioFormatIds;
8890
private List<FormatId> selectedVideoFormatIds;
8991
private List<FormatId> selectedCaptionFormatIds;
92+
private final Map<Integer, MediaHeader> initializedFormats;
9093

9194
public SabrProcessor(
9295
@NonNull String videoPlaybackUstreamerConfig,
@@ -131,6 +134,7 @@ public SabrProcessor(
131134
totalDurationMs = NO_VALUE;
132135
sabrContextsToSend = new HashSet<>();
133136
sabrContextUpdates = new HashMap<>();
137+
initializedFormats = new HashMap<>();
134138
initializeClientAbrState();
135139
}
136140

@@ -244,6 +248,7 @@ public ProcessMediaHeaderResult processMediaHeader(MediaHeader mediaHeader) {
244248
}
245249

246250
Segment segment = new Segment(
251+
mediaHeader,
247252
mediaHeader.getFormatId(),
248253
isInitSegment,
249254
durationMs,
@@ -329,6 +334,8 @@ public ProcessMediaEndResult processMediaEnd(long headerId) {
329334
throw new SabrStreamError(String.format("Header ID %s not found in partial segments", headerId));
330335
}
331336

337+
initializedFormats.put(segment.mediaHeader.getItag(), segment.mediaHeader);
338+
332339
Log.d(TAG, "MediaEnd for %s (sequence %s, data length = %s)",
333340
segment.formatId, segment.sequenceNumber, segment.receivedDataLength);
334341

@@ -478,12 +485,12 @@ public ProcessFormatInitializationMetadataResult processFormatInitializationMeta
478485
}
479486
}
480487

481-
int durationMs = Utils.ticksToMs(
482-
formatInitMetadata.hasDurationTicks() ? formatInitMetadata.getDurationTicks() : -1,
488+
long durationMs = Utils.ticksToMs(
489+
formatInitMetadata.hasDurationUnits() ? formatInitMetadata.getDurationUnits() : -1,
483490
formatInitMetadata.hasDurationTimescale() ? formatInitMetadata.getDurationTimescale() : -1
484491
);
485492

486-
int totalSegments = formatInitMetadata.hasTotalSegments() ? formatInitMetadata.getTotalSegments() : -1;
493+
long totalSegments = formatInitMetadata.hasEndSegmentNumber() ? formatInitMetadata.getEndSegmentNumber() : -1;
487494

488495
if (totalSegments == -1 && liveMetadata != null && liveMetadata.hasHeadSequenceNumber()) {
489496
totalSegments = liveMetadata.getHeadSequenceNumber();
@@ -558,7 +565,7 @@ public ProcessLiveMetadataResult processLiveMetadata(LiveMetadata liveMetadata)
558565
// If the current player time is less than the min dvr time, simulate a server seek to the min dvr time.
559566
// The server SHOULD send us a SABR_SEEK part in this case, but it does not always happen (e.g. ANDROID_VR)
560567
// The server SHOULD NOT send us segments before the min dvr time, so we should assume that the player time is correct.
561-
int minSeekableTimeMs = Utils.ticksToMs(liveMetadata.hasMinSeekableTimeTicks() ? liveMetadata.getMinSeekableTimeTicks() : -1,
568+
long minSeekableTimeMs = Utils.ticksToMs(liveMetadata.hasMinSeekableTimeTicks() ? liveMetadata.getMinSeekableTimeTicks() : -1,
562569
liveMetadata.hasMinSeekableTimescale() ? liveMetadata.getMinSeekableTimescale() : -1);
563570
if (minSeekableTimeMs != -1 && clientAbrState.hasPlayerTimeMs() && clientAbrState.getPlayerTimeMs() < minSeekableTimeMs) {
564571
Log.d(TAG, "Player time %s is less than min seekable time %s, simulating server seek",
@@ -693,19 +700,34 @@ public int getLiveSegmentTargetDurationSec() {
693700
//}
694701

695702
public VideoPlaybackAbrRequest buildVideoPlaybackAbrRequest(int trackType, boolean isInit) {
696-
int resolution = trackType == C.TRACK_TYPE_VIDEO && videoFormatSelector != null ? Utils.parseHeight(videoFormatSelector.displayName) : 0;
697-
int bandwidthEstimate = 1350000; // ???
698-
699-
ClientAbrState clientAbrStateTest = ClientAbrState.newBuilder()
700-
.setLastManualSelectedResolution(resolution)
701-
.setStickyResolution(resolution)
703+
Format selectedVideoFormat = getSelectedFormat(videoFormatSelector);
704+
Format selectedAudioFormat = getSelectedFormat(audioFormatSelector);
705+
int height = trackType == C.TRACK_TYPE_VIDEO && selectedVideoFormat != null
706+
? selectedVideoFormat.height : -1;
707+
int bandwidthEstimate = trackType == C.TRACK_TYPE_VIDEO && selectedVideoFormat != null
708+
? selectedVideoFormat.bitrate : selectedAudioFormat != null ? selectedAudioFormat.bitrate : -1;
709+
710+
ClientAbrState.Builder clientAbrStateBuilder = getClientAbrState().toBuilder()
711+
.setSabrForceMaxNetworkInterruptionDurationMs(0)
712+
.setPlaybackRate(1) // TODO: ???
713+
.setPlayerTimeMs(0) // TODO: ???
714+
.setClientViewportIsFlexible(false)
702715
.setBandwidthEstimate(bandwidthEstimate)
703-
.setEnabledTrackTypesBitfield(getAllSelectedTracksBitfield(trackType))
704716
.setDrcEnabled(false)
705-
.setSabrForceMaxNetworkInterruptionDurationMs(0)
706-
.build();
717+
.setEnabledTrackTypesBitfield(height != -1 ? EnabledTrackTypes.VIDEO_ONLY : EnabledTrackTypes.AUDIO_ONLY);
718+
719+
if (height != -1) {
720+
clientAbrStateBuilder
721+
.setStickyResolution(height)
722+
.setLastManualSelectedResolution(height);
723+
} else {
724+
//clientAbrStateBuilder
725+
// .setAudioTrackId("0");
726+
}
727+
728+
ClientAbrState clientAbrStateMod = clientAbrStateBuilder.build();
707729

708-
Pair<List<BufferedRange>, FormatId> bufferRanges = createBufferedRangesAndDiscardFormat(trackType);
730+
Pair<List<BufferedRange>, FormatId> bufferRanges = addBufferingInfoToAbrRequest(trackType);
709731

710732
List<FormatId> selectedFormats = getSelectedFormatIds(trackType);
711733

@@ -718,7 +740,7 @@ public VideoPlaybackAbrRequest buildVideoPlaybackAbrRequest(int trackType, boole
718740
}
719741

720742
return VideoPlaybackAbrRequest.newBuilder()
721-
.setClientAbrState(clientAbrStateTest)
743+
.setClientAbrState(clientAbrStateMod)
722744
.addAllPreferredVideoFormatIds(videoFormatSelector.formatIds)
723745
.addAllPreferredAudioFormatIds(audioFormatSelector.formatIds)
724746
.addAllPreferredSubtitleFormatIds(captionFormatSelector.formatIds)
@@ -733,6 +755,10 @@ public VideoPlaybackAbrRequest buildVideoPlaybackAbrRequest(int trackType, boole
733755
.build();
734756
}
735757

758+
private static Format getSelectedFormat(FormatSelector formatSelector) {
759+
return formatSelector != null && !formatSelector.selectedFormats.isEmpty() ? formatSelector.selectedFormats.get(0) : null;
760+
}
761+
736762
private List<FormatId> getSelectedFormatIds() {
737763
List<FormatId> result = new ArrayList<>();
738764

@@ -743,18 +769,6 @@ private List<FormatId> getSelectedFormatIds() {
743769
return result;
744770
}
745771

746-
private int getAllSelectedTracksBitfield(int trackType) {
747-
if (!videoFormatSelector.formatIds.isEmpty() && trackType == C.TRACK_TYPE_VIDEO) {
748-
return 1;
749-
} else if (!audioFormatSelector.formatIds.isEmpty() && trackType == C.TRACK_TYPE_AUDIO) {
750-
return 2;
751-
} else if (!captionFormatSelector.formatIds.isEmpty() && trackType == C.TRACK_TYPE_TEXT) {
752-
return 3;
753-
}
754-
755-
return 0;
756-
}
757-
758772
private List<FormatId> getSelectedFormatIds(int trackType) {
759773
List<FormatId> result = new ArrayList<>();
760774

@@ -885,23 +899,24 @@ public void setCaptionFormatSelector(CaptionSelector captionFormatSelector) {
885899
*
886900
* @return The format to discard (if any) - typically formats that are active but not currently requested.
887901
*/
888-
private Pair<List<BufferedRange>, FormatId> createBufferedRangesAndDiscardFormat(int trackType) {
902+
private Pair<List<BufferedRange>, FormatId> addBufferingInfoToAbrRequest(int trackType) {
889903
FormatId audioFormat = audioFormatSelector.formatIds.isEmpty() ? null : audioFormatSelector.formatIds.get(0);
890904
FormatId videoFormat = videoFormatSelector.formatIds.isEmpty() ? null : videoFormatSelector.formatIds.get(0);
891905

892906
FormatId formatToDiscard = null;
893907
List<BufferedRange> bufferedRanges = new ArrayList<>();
894908

895909
FormatId currentFormat = trackType == C.TRACK_TYPE_VIDEO ? videoFormat : audioFormat;
896-
int currentFormatITag = currentFormat != null ? currentFormat.getItag() : -1;
910+
int currentFormatKey = currentFormat != null ? currentFormat.getItag() : -1;
897911

898912
for (FormatId activeFormat : new FormatId[]{videoFormat, audioFormat}) {
899913
if (activeFormat == null) {
900914
continue;
901915
}
902916

903-
boolean shouldDiscard = currentFormatITag != activeFormat.getItag();
904-
SelectedFormat initializedFormat = null; // TODO: not implemented
917+
int activeFormatKey = activeFormat.getItag();
918+
boolean shouldDiscard = currentFormatKey != activeFormatKey;
919+
MediaHeader initializedFormat = initializedFormats.get(activeFormatKey);
905920

906921
BufferedRange bufferedRange = shouldDiscard ? createFullBufferRange(activeFormat) : createPartialBufferRange(initializedFormat);
907922

@@ -943,11 +958,30 @@ private BufferedRange createFullBufferRange(@NonNull FormatId format) {
943958
* @param initializedFormat - The format with initialization data.
944959
* @return A BufferedRange object with segment information, or null if no metadata is available.
945960
*/
946-
private BufferedRange createPartialBufferRange(SelectedFormat initializedFormat) {
961+
private BufferedRange createPartialBufferRange(MediaHeader initializedFormat) {
947962
if (initializedFormat == null) {
948963
return null;
949964
}
950965

951-
return null;
966+
int sequenceNumber = initializedFormat.hasSequenceNumber() ? initializedFormat.getSequenceNumber() : 1;
967+
TimeRange timeRange = initializedFormat.hasTimeRange() ? initializedFormat.getTimeRange() : null;
968+
int timeScale = timeRange != null && timeRange.hasTimescale() ? timeRange.getTimescale() : 1_000;
969+
long durationMs = initializedFormat.hasDurationMs() ? initializedFormat.getDurationMs() : 0;
970+
return BufferedRange.newBuilder()
971+
.setFormatId(initializedFormat.getFormatId())
972+
.setStartSegmentIndex(sequenceNumber)
973+
.setDurationMs(durationMs)
974+
.setStartTimeMs(0)
975+
.setEndSegmentIndex(sequenceNumber)
976+
.setTimeRange(TimeRange.newBuilder()
977+
.setTimescale(timeScale)
978+
.setStartTicks(0)
979+
.setDurationTicks(durationMs)
980+
.build())
981+
.build();
982+
}
983+
984+
public void handleResponse() {
985+
952986
}
953987
}

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/SabrStream.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ private UMPPart nextKnownUMPPart(@NonNull ExtractorInput extractorInput) {
494494

495495
if (part == null) {
496496
Log.d(TAG, "The UMP stream is ended.");
497+
processor.handleResponse();
497498
break;
498499
}
499500

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.google.android.exoplayer2.source.sabr.parser.misc;
2+
3+
public class EnabledTrackTypes {
4+
public static final int VIDEO_AND_AUDIO = 0;
5+
public static final int AUDIO_ONLY = 1;
6+
public static final int VIDEO_ONLY = 2;
7+
}

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/misc/Utils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
import java.io.IOException;
88

99
public class Utils {
10-
public static int ticksToMs(long timeTicks, int timescale) {
10+
public static long ticksToMs(long timeTicks, long timescale) {
1111
if (timeTicks == -1 || timescale == -1) {
1212
return -1;
1313
}
1414

15-
return (int) Math.ceil(((double) timeTicks / timescale) * 1_000);
15+
return (long) Math.ceil(((double) timeTicks / timescale) * 1_000);
1616
}
1717

1818
public static byte[] readAllBytes(ByteArrayInputStream is) {

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/models/AudioSelector.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.google.android.exoplayer2.source.sabr.parser.models;
22

3+
import com.google.android.exoplayer2.Format;
34
import com.google.android.exoplayer2.source.sabr.protos.misc.FormatId;
45

56
public class AudioSelector extends FormatSelector {
@@ -11,6 +12,10 @@ public AudioSelector(String displayName, boolean discardMedia, FormatId... forma
1112
super(displayName, discardMedia, formatIds);
1213
}
1314

15+
public AudioSelector(String displayName, boolean discardMedia, Format... selectedFormats) {
16+
super(displayName, discardMedia, selectedFormats);
17+
}
18+
1419
@Override
1520
public String getMimePrefix() {
1621
return "audio";

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/models/CaptionSelector.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.google.android.exoplayer2.source.sabr.parser.models;
22

3+
import com.google.android.exoplayer2.Format;
34
import com.google.android.exoplayer2.source.sabr.protos.misc.FormatId;
45

6+
import java.util.List;
7+
58
public class CaptionSelector extends FormatSelector {
69
public CaptionSelector(String displayName, boolean discardMedia) {
710
super(displayName, discardMedia);
@@ -11,6 +14,10 @@ public CaptionSelector(String displayName, boolean discardMedia, FormatId... for
1114
super(displayName, discardMedia, formatIds);
1215
}
1316

17+
public CaptionSelector(String displayName, boolean discardMedia, Format... selectedFormats) {
18+
super(displayName, discardMedia, selectedFormats);
19+
}
20+
1421
@Override
1522
public String getMimePrefix() {
1623
return "text";

exoplayer-amzn-2.10.6/library/sabr/src/main/java/com/google/android/exoplayer2/source/sabr/parser/models/FormatSelector.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.google.android.exoplayer2.source.sabr.parser.models;
22

3+
import com.google.android.exoplayer2.Format;
34
import com.google.android.exoplayer2.source.sabr.protos.misc.FormatId;
45
import com.liskovsoft.sharedutils.helpers.Helpers;
56

@@ -10,6 +11,7 @@
1011
public class FormatSelector {
1112
public final String displayName;
1213
public final List<FormatId> formatIds = new ArrayList<>();
14+
public final List<Format> selectedFormats = new ArrayList<>();
1315
public final boolean discardMedia;
1416

1517
public FormatSelector(String displayName, boolean discardMedia) {
@@ -25,6 +27,18 @@ public FormatSelector(String displayName, boolean discardMedia, FormatId... form
2527
}
2628
}
2729

30+
public FormatSelector(String displayName, boolean discardMedia, Format... selectedFormats) {
31+
this.displayName = displayName;
32+
this.discardMedia = discardMedia;
33+
34+
if (selectedFormats != null) {
35+
for (Format format : selectedFormats) {
36+
this.formatIds.add(createFormatId(format));
37+
}
38+
this.selectedFormats.addAll(Arrays.asList(selectedFormats));
39+
}
40+
}
41+
2842
public String getMimePrefix() {
2943
return null;
3044
}
@@ -38,4 +52,12 @@ public boolean match(FormatId formatId, String mimeType) {
3852
public boolean isDiscardMedia() {
3953
return discardMedia;
4054
}
55+
56+
private static FormatId createFormatId(Format format) {
57+
FormatId formatId = FormatId.newBuilder()
58+
.setItag(Helpers.parseInt(format.id))
59+
.setLastModified(format.lastModified)
60+
.build();
61+
return formatId;
62+
}
4163
}

0 commit comments

Comments
 (0)