Fix two ad insertion related bugs in DefaultPlaybackSessionManager.
1. A content session after an ad has been played was not re-marked as active, leading to new ad session being marked as active too early. 2. Switching from content to post-roll ended the content session because the return value of getAdGroupTimeUs of C.TIME_END_OF_SOURCE was not handled. Using the nextAdGroupIndex instead. PiperOrigin-RevId: 246977327
This commit is contained in:
parent
2a0ead1b29
commit
7d5558881d
@ -63,7 +63,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.annotation:annotation:1.0.2'
|
||||
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
|
||||
implementation 'com.android.support:support-core-ui:' + supportLibraryVersion
|
||||
implementation 'androidx.fragment:fragment:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation project(modulePrefix + 'library-core')
|
||||
|
@ -25,7 +25,7 @@ import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import androidx.appcompat.app.AppCompatDialog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -19,7 +19,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/track_selection_dialog_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
@ -32,7 +32,7 @@
|
||||
app:tabGravity="fill"
|
||||
app:tabMode="fixed"/>
|
||||
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
</android.support.v4.view.ViewPager>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
|
@ -396,7 +396,8 @@ public abstract class Timeline {
|
||||
* microseconds.
|
||||
*
|
||||
* @param adGroupIndex The ad group index.
|
||||
* @return The time of the ad group at the index, in microseconds.
|
||||
* @return The time of the ad group at the index, in microseconds, or {@link
|
||||
* C#TIME_END_OF_SOURCE} for a post-roll ad group.
|
||||
*/
|
||||
public long getAdGroupTimeUs(int adGroupIndex) {
|
||||
return adPlaybackState.adGroupTimesUs[adGroupIndex];
|
||||
|
@ -202,10 +202,12 @@ public final class DefaultPlaybackSessionManager implements PlaybackSessionManag
|
||||
@RequiresNonNull("listener")
|
||||
private void updateActiveSession(EventTime eventTime, SessionDescriptor sessionDescriptor) {
|
||||
currentMediaPeriodId = eventTime.mediaPeriodId;
|
||||
if (sessionDescriptor.isCreated && !sessionDescriptor.isActive) {
|
||||
sessionDescriptor.isActive = true;
|
||||
if (sessionDescriptor.isCreated) {
|
||||
activeSessionId = sessionDescriptor.sessionId;
|
||||
listener.onSessionActive(eventTime, sessionDescriptor.sessionId);
|
||||
if (!sessionDescriptor.isActive) {
|
||||
sessionDescriptor.isActive = true;
|
||||
listener.onSessionActive(eventTime, sessionDescriptor.sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,13 +328,9 @@ public final class DefaultPlaybackSessionManager implements PlaybackSessionManag
|
||||
|| (eventAdGroup == adMediaPeriodId.adGroupIndex
|
||||
&& eventAdIndex > adMediaPeriodId.adIndexInAdGroup);
|
||||
} else {
|
||||
eventTime.timeline.getPeriod(adPeriodIndex, period);
|
||||
long adGroupTimeMs =
|
||||
adMediaPeriodId.adGroupIndex < period.getAdGroupCount()
|
||||
? C.usToMs(period.getAdGroupTimeUs(adMediaPeriodId.adGroupIndex))
|
||||
: 0;
|
||||
// Finished if the event is for content after this ad.
|
||||
return adGroupTimeMs <= eventTime.currentPlaybackPositionMs;
|
||||
return eventTime.mediaPeriodId.nextAdGroupIndex == C.INDEX_UNSET
|
||||
|| eventTime.mediaPeriodId.nextAdGroupIndex > adMediaPeriodId.adGroupIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -598,6 +598,43 @@ public final class DefaultPlaybackSessionManagerTest {
|
||||
assertThat(updatedSessionId300).isEqualTo(sessionId300);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timelineUpdate_withContent_doesNotFinishFuturePostrollAd() {
|
||||
Timeline adTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 0,
|
||||
/* isSeekable= */ true,
|
||||
/* isDynamic= */ false,
|
||||
/* durationUs =*/ 10 * C.MICROS_PER_SECOND,
|
||||
new AdPlaybackState(/* adGroupTimesUs= */ C.TIME_END_OF_SOURCE)
|
||||
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)));
|
||||
EventTime adEventTime =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* adGroupIndex= */ 0,
|
||||
/* adIndexInAdGroup= */ 0,
|
||||
/* windowSequenceNumber= */ 0));
|
||||
EventTime contentEventTime =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* windowSequenceNumber= */ 0,
|
||||
/* nextAdGroupIndex= */ 0));
|
||||
sessionManager.updateSessions(contentEventTime);
|
||||
sessionManager.updateSessions(adEventTime);
|
||||
|
||||
sessionManager.handleTimelineUpdate(contentEventTime);
|
||||
|
||||
verify(mockListener, never()).onSessionFinished(any(), anyString(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void positionDiscontinuity_withinWindow_doesNotFinishSession() {
|
||||
Timeline timeline =
|
||||
@ -943,6 +980,70 @@ public final class DefaultPlaybackSessionManagerTest {
|
||||
verifyNoMoreInteractions(mockListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
updateSessions_withNewAd_afterDiscontinuitiesFromContentToAdAndBack_doesNotActivateNewAd() {
|
||||
Timeline adTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 0,
|
||||
/* isSeekable= */ true,
|
||||
/* isDynamic= */ false,
|
||||
/* durationUs =*/ 10 * C.MICROS_PER_SECOND,
|
||||
new AdPlaybackState(
|
||||
/* adGroupTimesUs= */ 2 * C.MICROS_PER_SECOND, 5 * C.MICROS_PER_SECOND)
|
||||
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
|
||||
.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1)));
|
||||
EventTime adEventTime1 =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* adGroupIndex= */ 0,
|
||||
/* adIndexInAdGroup= */ 0,
|
||||
/* windowSequenceNumber= */ 0));
|
||||
EventTime adEventTime2 =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* adGroupIndex= */ 1,
|
||||
/* adIndexInAdGroup= */ 0,
|
||||
/* windowSequenceNumber= */ 0));
|
||||
EventTime contentEventTime1 =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* windowSequenceNumber= */ 0,
|
||||
/* nextAdGroupIndex= */ 0));
|
||||
EventTime contentEventTime2 =
|
||||
createEventTime(
|
||||
adTimeline,
|
||||
/* windowIndex= */ 0,
|
||||
new MediaPeriodId(
|
||||
adTimeline.getUidOfPeriod(/* periodIndex= */ 0),
|
||||
/* windowSequenceNumber= */ 0,
|
||||
/* nextAdGroupIndex= */ 1));
|
||||
sessionManager.handleTimelineUpdate(contentEventTime1);
|
||||
sessionManager.updateSessions(contentEventTime1);
|
||||
sessionManager.updateSessions(adEventTime1);
|
||||
sessionManager.handlePositionDiscontinuity(
|
||||
adEventTime1, Player.DISCONTINUITY_REASON_AD_INSERTION);
|
||||
sessionManager.handlePositionDiscontinuity(
|
||||
contentEventTime2, Player.DISCONTINUITY_REASON_AD_INSERTION);
|
||||
String adSessionId2 =
|
||||
sessionManager.getSessionForMediaPeriodId(adTimeline, adEventTime2.mediaPeriodId);
|
||||
|
||||
sessionManager.updateSessions(adEventTime2);
|
||||
|
||||
verify(mockListener, never()).onSessionActive(any(), eq(adSessionId2));
|
||||
}
|
||||
|
||||
private static EventTime createEventTime(
|
||||
Timeline timeline, int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||
return new EventTime(
|
||||
|
Loading…
x
Reference in New Issue
Block a user