Set isLive flag in CastTimeline based on MediaInfo.

Issue:#2668
PiperOrigin-RevId: 274793644
This commit is contained in:
tonihei 2019-10-15 14:44:26 +01:00 committed by Oliver Woodman
parent fc95d07a94
commit a95f0643b9
2 changed files with 52 additions and 29 deletions

View File

@ -39,9 +39,14 @@ import java.util.Arrays;
* The default start position of the item in microseconds, or {@link C#TIME_UNSET} if unknown. * The default start position of the item in microseconds, or {@link C#TIME_UNSET} if unknown.
*/ */
public final long defaultPositionUs; public final long defaultPositionUs;
/** Whether the item is live content, or {@code false} if unknown. */
public final boolean isLive;
private ItemData() { private ItemData() {
this(/* durationUs= */ C.TIME_UNSET, /* defaultPositionUs */ C.TIME_UNSET); this(
/* durationUs= */ C.TIME_UNSET, /* defaultPositionUs */
C.TIME_UNSET,
/* isLive= */ false);
} }
/** /**
@ -49,26 +54,29 @@ import java.util.Arrays;
* *
* @param durationUs See {@link #durationsUs}. * @param durationUs See {@link #durationsUs}.
* @param defaultPositionUs See {@link #defaultPositionUs}. * @param defaultPositionUs See {@link #defaultPositionUs}.
* @param isLive See {@link #isLive}.
*/ */
public ItemData(long durationUs, long defaultPositionUs) { public ItemData(long durationUs, long defaultPositionUs, boolean isLive) {
this.durationUs = durationUs; this.durationUs = durationUs;
this.defaultPositionUs = defaultPositionUs; this.defaultPositionUs = defaultPositionUs;
this.isLive = isLive;
} }
/** Returns an instance with the given {@link #durationsUs}. */ /**
public ItemData copyWithDurationUs(long durationUs) { * Returns a copy of this instance with the given values.
if (durationUs == this.durationUs) { *
* @param durationUs The duration in microseconds, or {@link C#TIME_UNSET} if unknown.
* @param defaultPositionUs The default start position in microseconds, or {@link C#TIME_UNSET}
* if unknown.
* @param isLive Whether the item is live, or {@code false} if unknown.
*/
public ItemData copyWithNewValues(long durationUs, long defaultPositionUs, boolean isLive) {
if (durationUs == this.durationUs
&& defaultPositionUs == this.defaultPositionUs
&& isLive == this.isLive) {
return this; return this;
} }
return new ItemData(durationUs, defaultPositionUs); return new ItemData(durationUs, defaultPositionUs, isLive);
}
/** Returns an instance with the given {@link #defaultPositionsUs}. */
public ItemData copyWithDefaultPositionUs(long defaultPositionUs) {
if (defaultPositionUs == this.defaultPositionUs) {
return this;
}
return new ItemData(durationUs, defaultPositionUs);
} }
} }
@ -80,6 +88,7 @@ import java.util.Arrays;
private final int[] ids; private final int[] ids;
private final long[] durationsUs; private final long[] durationsUs;
private final long[] defaultPositionsUs; private final long[] defaultPositionsUs;
private final boolean[] isLive;
/** /**
* Creates a Cast timeline from the given data. * Creates a Cast timeline from the given data.
@ -93,12 +102,14 @@ import java.util.Arrays;
ids = Arrays.copyOf(itemIds, itemCount); ids = Arrays.copyOf(itemIds, itemCount);
durationsUs = new long[itemCount]; durationsUs = new long[itemCount];
defaultPositionsUs = new long[itemCount]; defaultPositionsUs = new long[itemCount];
isLive = new boolean[itemCount];
for (int i = 0; i < ids.length; i++) { for (int i = 0; i < ids.length; i++) {
int id = ids[i]; int id = ids[i];
idsToIndex.put(id, i); idsToIndex.put(id, i);
ItemData data = itemIdToData.get(id, ItemData.EMPTY); ItemData data = itemIdToData.get(id, ItemData.EMPTY);
durationsUs[i] = data.durationUs; durationsUs[i] = data.durationUs;
defaultPositionsUs[i] = data.defaultPositionUs; defaultPositionsUs[i] = data.defaultPositionUs == C.TIME_UNSET ? 0 : data.defaultPositionUs;
isLive[i] = data.isLive;
} }
} }
@ -121,7 +132,7 @@ import java.util.Arrays;
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
/* isSeekable= */ !isDynamic, /* isSeekable= */ !isDynamic,
isDynamic, isDynamic,
/* isLive= */ isDynamic, isLive[windowIndex],
defaultPositionsUs[windowIndex], defaultPositionsUs[windowIndex],
durationUs, durationUs,
/* firstPeriodIndex= */ windowIndex, /* firstPeriodIndex= */ windowIndex,
@ -162,7 +173,8 @@ import java.util.Arrays;
CastTimeline that = (CastTimeline) other; CastTimeline that = (CastTimeline) other;
return Arrays.equals(ids, that.ids) return Arrays.equals(ids, that.ids)
&& Arrays.equals(durationsUs, that.durationsUs) && Arrays.equals(durationsUs, that.durationsUs)
&& Arrays.equals(defaultPositionsUs, that.defaultPositionsUs); && Arrays.equals(defaultPositionsUs, that.defaultPositionsUs)
&& Arrays.equals(isLive, that.isLive);
} }
@Override @Override
@ -170,6 +182,7 @@ import java.util.Arrays;
int result = Arrays.hashCode(ids); int result = Arrays.hashCode(ids);
result = 31 * result + Arrays.hashCode(durationsUs); result = 31 * result + Arrays.hashCode(durationsUs);
result = 31 * result + Arrays.hashCode(defaultPositionsUs); result = 31 * result + Arrays.hashCode(defaultPositionsUs);
result = 31 * result + Arrays.hashCode(isLive);
return result; return result;
} }

View File

@ -16,7 +16,9 @@
package com.google.android.exoplayer2.ext.cast; package com.google.android.exoplayer2.ext.cast;
import android.util.SparseArray; import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaQueueItem; import com.google.android.gms.cast.MediaQueueItem;
import com.google.android.gms.cast.MediaStatus; import com.google.android.gms.cast.MediaStatus;
import com.google.android.gms.cast.framework.media.RemoteMediaClient; import com.google.android.gms.cast.framework.media.RemoteMediaClient;
@ -61,25 +63,33 @@ import java.util.HashSet;
} }
int currentItemId = mediaStatus.getCurrentItemId(); int currentItemId = mediaStatus.getCurrentItemId();
long durationUs = CastUtils.getStreamDurationUs(mediaStatus.getMediaInfo()); updateItemData(
itemIdToData.put( currentItemId, mediaStatus.getMediaInfo(), /* defaultPositionUs= */ C.TIME_UNSET);
currentItemId,
itemIdToData
.get(currentItemId, CastTimeline.ItemData.EMPTY)
.copyWithDurationUs(durationUs));
for (MediaQueueItem item : mediaStatus.getQueueItems()) { for (MediaQueueItem item : mediaStatus.getQueueItems()) {
int itemId = item.getItemId(); long defaultPositionUs = (long) (item.getStartTime() * C.MICROS_PER_SECOND);
itemIdToData.put( updateItemData(item.getItemId(), item.getMedia(), defaultPositionUs);
itemId,
itemIdToData
.get(itemId, CastTimeline.ItemData.EMPTY)
.copyWithDefaultPositionUs((long) (item.getStartTime() * C.MICROS_PER_SECOND)));
} }
return new CastTimeline(itemIds, itemIdToData); return new CastTimeline(itemIds, itemIdToData);
} }
private void updateItemData(int itemId, @Nullable MediaInfo mediaInfo, long defaultPositionUs) {
CastTimeline.ItemData previousData = itemIdToData.get(itemId, CastTimeline.ItemData.EMPTY);
long durationUs = CastUtils.getStreamDurationUs(mediaInfo);
if (durationUs == C.TIME_UNSET) {
durationUs = previousData.durationUs;
}
boolean isLive =
mediaInfo == null
? previousData.isLive
: mediaInfo.getStreamType() == MediaInfo.STREAM_TYPE_LIVE;
if (defaultPositionUs == C.TIME_UNSET) {
defaultPositionUs = previousData.defaultPositionUs;
}
itemIdToData.put(itemId, previousData.copyWithNewValues(durationUs, defaultPositionUs, isLive));
}
private void removeUnusedItemDataEntries(int[] itemIds) { private void removeUnusedItemDataEntries(int[] itemIds) {
HashSet<Integer> scratchItemIds = new HashSet<>(/* initialCapacity= */ itemIds.length * 2); HashSet<Integer> scratchItemIds = new HashSet<>(/* initialCapacity= */ itemIds.length * 2);
for (int id : itemIds) { for (int id : itemIds) {