Search in sources :

Example 6 with Events

use of androidx.media3.common.Player.Events in project media by androidx.

the class DashManifestParser method parseEventStream.

/**
 * Parses a single EventStream node in the manifest.
 *
 * @param xpp The current xml parser.
 * @return The {@link EventStream} parsed from this EventStream node.
 * @throws XmlPullParserException If there is any error parsing this node.
 * @throws IOException If there is any error reading from the underlying input stream.
 */
protected EventStream parseEventStream(XmlPullParser xpp) throws XmlPullParserException, IOException {
    String schemeIdUri = parseString(xpp, "schemeIdUri", "");
    String value = parseString(xpp, "value", "");
    long timescale = parseLong(xpp, "timescale", 1);
    List<Pair<Long, EventMessage>> eventMessages = new ArrayList<>();
    ByteArrayOutputStream scratchOutputStream = new ByteArrayOutputStream(512);
    do {
        xpp.next();
        if (XmlPullParserUtil.isStartTag(xpp, "Event")) {
            Pair<Long, EventMessage> event = parseEvent(xpp, schemeIdUri, value, timescale, scratchOutputStream);
            eventMessages.add(event);
        } else {
            maybeSkipTag(xpp);
        }
    } while (!XmlPullParserUtil.isEndTag(xpp, "EventStream"));
    long[] presentationTimesUs = new long[eventMessages.size()];
    EventMessage[] events = new EventMessage[eventMessages.size()];
    for (int i = 0; i < eventMessages.size(); i++) {
        Pair<Long, EventMessage> event = eventMessages.get(i);
        presentationTimesUs[i] = event.first;
        events[i] = event.second;
    }
    return buildEventStream(schemeIdUri, value, timescale, presentationTimesUs, events);
}
Also used : EventMessage(androidx.media3.extractor.metadata.emsg.EventMessage) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Pair(android.util.Pair)

Example 7 with Events

use of androidx.media3.common.Player.Events in project media by androidx.

the class AdTagLoader method loadAdInternal.

private void loadAdInternal(AdMediaInfo adMediaInfo, AdPodInfo adPodInfo) {
    if (adsManager == null) {
        // Drop events after release.
        if (configuration.debugModeEnabled) {
            Log.d(TAG, "loadAd after release " + getAdMediaInfoString(adMediaInfo) + ", ad pod " + adPodInfo);
        }
        return;
    }
    int adGroupIndex = getAdGroupIndexForAdPod(adPodInfo);
    int adIndexInAdGroup = adPodInfo.getAdPosition() - 1;
    AdInfo adInfo = new AdInfo(adGroupIndex, adIndexInAdGroup);
    // The ad URI may already be known, so force put to update it if needed.
    adInfoByAdMediaInfo.forcePut(adMediaInfo, adInfo);
    if (configuration.debugModeEnabled) {
        Log.d(TAG, "loadAd " + getAdMediaInfoString(adMediaInfo));
    }
    if (adPlaybackState.isAdInErrorState(adGroupIndex, adIndexInAdGroup)) {
        // timeout after its media load timeout.
        return;
    }
    // The ad count may increase on successive loads of ads in the same ad pod, for example, due to
    // separate requests for ad tags with multiple ads within the ad pod completing after an earlier
    // ad has loaded. See also https://github.com/google/ExoPlayer/issues/7477.
    AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex);
    adPlaybackState = adPlaybackState.withAdCount(adInfo.adGroupIndex, max(adPodInfo.getTotalAds(), adGroup.states.length));
    adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex);
    for (int i = 0; i < adIndexInAdGroup; i++) {
        // Any preceding ads that haven't loaded are not going to load.
        if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
            adPlaybackState = adPlaybackState.withAdLoadError(adGroupIndex, /* adIndexInAdGroup= */
            i);
        }
    }
    Uri adUri = Uri.parse(adMediaInfo.getUrl());
    adPlaybackState = adPlaybackState.withAdUri(adInfo.adGroupIndex, adInfo.adIndexInAdGroup, adUri);
    updateAdPlaybackState();
}
Also used : AdPlaybackState(androidx.media3.common.AdPlaybackState) Uri(android.net.Uri)

Example 8 with Events

use of androidx.media3.common.Player.Events in project media by androidx.

the class AdTagLoader method addListenerWithAdView.

/**
 * Starts passing events from this instance (including any pending ad playback state) and
 * registers obstructions.
 */
public void addListenerWithAdView(EventListener eventListener, AdViewProvider adViewProvider) {
    boolean isStarted = !eventListeners.isEmpty();
    eventListeners.add(eventListener);
    if (isStarted) {
        if (!AdPlaybackState.NONE.equals(adPlaybackState)) {
            // Pass the existing ad playback state to the new listener.
            eventListener.onAdPlaybackState(adPlaybackState);
        }
        return;
    }
    lastVolumePercent = 0;
    lastAdProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
    lastContentProgress = VideoProgressUpdate.VIDEO_TIME_NOT_READY;
    maybeNotifyPendingAdLoadError();
    if (!AdPlaybackState.NONE.equals(adPlaybackState)) {
        // Pass the ad playback state to the player, and resume ads if necessary.
        eventListener.onAdPlaybackState(adPlaybackState);
    } else if (adsManager != null) {
        adPlaybackState = new AdPlaybackState(adsId, getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
        updateAdPlaybackState();
    }
    for (AdOverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
        adDisplayContainer.registerFriendlyObstruction(imaFactory.createFriendlyObstruction(overlayInfo.view, ImaUtil.getFriendlyObstructionPurpose(overlayInfo.purpose), overlayInfo.reasonDetail));
    }
}
Also used : AdOverlayInfo(androidx.media3.common.AdOverlayInfo) AdPlaybackState(androidx.media3.common.AdPlaybackState)

Example 9 with Events

use of androidx.media3.common.Player.Events in project media by androidx.

the class MediaSessionService method onStartCommand.

/**
 * Called when a component calls {@link android.content.Context#startService(Intent)}.
 *
 * <p>The default implementation handles the incoming media button events. In this case, the
 * intent will have the action {@link Intent#ACTION_MEDIA_BUTTON}. Override this method if this
 * service also needs to handle actions other than {@link Intent#ACTION_MEDIA_BUTTON}.
 */
@CallSuper
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    if (intent == null) {
        return START_STICKY;
    }
    DefaultActionFactory actionFactory;
    synchronized (lock) {
        actionFactory = checkStateNotNull(this.actionFactory);
    }
    @Nullable Uri uri = intent.getData();
    @Nullable MediaSession session = uri != null ? MediaSession.getSession(uri) : null;
    if (actionFactory.isMediaAction(intent)) {
        if (session == null) {
            ControllerInfo controllerInfo = ControllerInfo.createLegacyControllerInfo();
            session = onGetSession(controllerInfo);
            if (session == null) {
                return START_STICKY;
            }
            addSession(session);
        }
        @Nullable KeyEvent keyEvent = actionFactory.getKeyEvent(intent);
        if (keyEvent != null) {
            session.getSessionCompat().getController().dispatchMediaButtonEvent(keyEvent);
        }
    } else if (actionFactory.isCustomAction(intent)) {
        @Nullable String customAction = actionFactory.getCustomAction(intent);
        if (session != null && customAction != null) {
            Bundle customExtras = actionFactory.getCustomActionExtras(intent);
            getMediaNotificationManager().onCustomAction(session, customAction, customExtras);
        }
    }
    return START_STICKY;
}
Also used : KeyEvent(android.view.KeyEvent) Bundle(android.os.Bundle) Uri(android.net.Uri) Nullable(androidx.annotation.Nullable) ControllerInfo(androidx.media3.session.MediaSession.ControllerInfo) CallSuper(androidx.annotation.CallSuper)

Example 10 with Events

use of androidx.media3.common.Player.Events in project media by androidx.

the class MediaControllerListenerTest method onEvents_whenNewCommandIsCalledInsideOnEvents_isCalledFromNewLooperIterationSet.

@Test
public void onEvents_whenNewCommandIsCalledInsideOnEvents_isCalledFromNewLooperIterationSet() throws Exception {
    Player.Events firstLooperIterationSetTestEvents = new Player.Events(new FlagSet.Builder().add(EVENT_REPEAT_MODE_CHANGED).build());
    Player.Events secondLooperIterationSetTestEvents = new Player.Events(new FlagSet.Builder().add(EVENT_SHUFFLE_MODE_ENABLED_CHANGED).build());
    List<Integer> listenerEventCodes = new ArrayList<>();
    MediaController controller = controllerTestRule.createController(remoteSession.getToken());
    CountDownLatch latch = new CountDownLatch(4);
    AtomicReference<Player.Events> firstLooperIterationSetEventsRef = new AtomicReference<>();
    AtomicReference<Player.Events> secondLooperIterationSetEventsRef = new AtomicReference<>();
    Player.Listener listener = new Player.Listener() {

        @Override
        public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
            listenerEventCodes.add(EVENT_REPEAT_MODE_CHANGED);
            latch.countDown();
        }

        @Override
        public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
            listenerEventCodes.add(EVENT_SHUFFLE_MODE_ENABLED_CHANGED);
            latch.countDown();
        }

        @Override
        public void onEvents(Player player, Player.Events events) {
            listenerEventCodes.add(EVENT_ON_EVENTS);
            if (!controller.getShuffleModeEnabled()) {
                controller.setShuffleModeEnabled(true);
                firstLooperIterationSetEventsRef.set(events);
            } else {
                secondLooperIterationSetEventsRef.set(events);
            }
            latch.countDown();
        }
    };
    controller.addListener(listener);
    remoteSession.getMockPlayer().setRepeatMode(REPEAT_MODE_ONE);
    remoteSession.getMockPlayer().notifyRepeatModeChanged();
    assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
    assertThat(listenerEventCodes).containsExactly(EVENT_REPEAT_MODE_CHANGED, EVENT_ON_EVENTS, EVENT_SHUFFLE_MODE_ENABLED_CHANGED, EVENT_ON_EVENTS);
    assertThat(firstLooperIterationSetEventsRef.get()).isEqualTo(firstLooperIterationSetTestEvents);
    assertThat(secondLooperIterationSetEventsRef.get()).isEqualTo(secondLooperIterationSetTestEvents);
}
Also used : RemoteMockPlayer(androidx.media3.session.RemoteMediaSession.RemoteMockPlayer) Player(androidx.media3.common.Player) RepeatMode(androidx.media3.common.Player.RepeatMode) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) FlagSet(androidx.media3.common.FlagSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LargeTest(androidx.test.filters.LargeTest) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)65 Player (androidx.media3.common.Player)64 CountDownLatch (java.util.concurrent.CountDownLatch)58 AtomicReference (java.util.concurrent.atomic.AtomicReference)56 LargeTest (androidx.test.filters.LargeTest)52 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)46 Bundle (android.os.Bundle)34 Timeline (androidx.media3.common.Timeline)31 FlagSet (androidx.media3.common.FlagSet)24 MediaItem (androidx.media3.common.MediaItem)24 Events (androidx.media3.common.Player.Events)20 PositionInfo (androidx.media3.common.Player.PositionInfo)19 Nullable (androidx.annotation.Nullable)17 MediaTestUtils.createTimeline (androidx.media3.session.MediaTestUtils.createTimeline)17 ArrayList (java.util.ArrayList)17 AtomicLong (java.util.concurrent.atomic.AtomicLong)15 QueueItem (android.support.v4.media.session.MediaSessionCompat.QueueItem)12 Window (androidx.media3.common.Timeline.Window)8 PlaybackStateCompat (android.support.v4.media.session.PlaybackStateCompat)6 MediaMetadata (androidx.media3.common.MediaMetadata)6