Search in sources :

Example 41 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class EventLogger method onTracksChanged.

@Override
public void onTracksChanged(TrackGroupArray ignored, TrackSelectionArray trackSelections) {
    MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
    if (mappedTrackInfo == null) {
        Log.d(TAG, "Tracks []");
        return;
    }
    Log.d(TAG, "Tracks [");
    // Log tracks associated to renderers.
    for (int rendererIndex = 0; rendererIndex < mappedTrackInfo.length; rendererIndex++) {
        TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
        TrackSelection trackSelection = trackSelections.get(rendererIndex);
        if (rendererTrackGroups.length > 0) {
            Log.d(TAG, "  Renderer:" + rendererIndex + " [");
            for (int groupIndex = 0; groupIndex < rendererTrackGroups.length; groupIndex++) {
                TrackGroup trackGroup = rendererTrackGroups.get(groupIndex);
                String adaptiveSupport = getAdaptiveSupportString(trackGroup.length, mappedTrackInfo.getAdaptiveSupport(rendererIndex, groupIndex, false));
                Log.d(TAG, "    Group:" + groupIndex + ", adaptive_supported=" + adaptiveSupport + " [");
                for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
                    String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
                    String formatSupport = getFormatSupportString(mappedTrackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex));
                    Log.d(TAG, "      " + status + " Track:" + trackIndex + ", " + Format.toLogString(trackGroup.getFormat(trackIndex)) + ", supported=" + formatSupport);
                }
                Log.d(TAG, "    ]");
            }
            // Log metadata for at most one of the tracks selected for the renderer.
            if (trackSelection != null) {
                for (int selectionIndex = 0; selectionIndex < trackSelection.length(); selectionIndex++) {
                    Metadata metadata = trackSelection.getFormat(selectionIndex).metadata;
                    if (metadata != null) {
                        Log.d(TAG, "    Metadata [");
                        printMetadata(metadata, "      ");
                        Log.d(TAG, "    ]");
                        break;
                    }
                }
            }
            Log.d(TAG, "  ]");
        }
    }
    // Log tracks not associated with a renderer.
    TrackGroupArray unassociatedTrackGroups = mappedTrackInfo.getUnassociatedTrackGroups();
    if (unassociatedTrackGroups.length > 0) {
        Log.d(TAG, "  Renderer:None [");
        for (int groupIndex = 0; groupIndex < unassociatedTrackGroups.length; groupIndex++) {
            Log.d(TAG, "    Group:" + groupIndex + " [");
            TrackGroup trackGroup = unassociatedTrackGroups.get(groupIndex);
            for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
                String status = getTrackStatusString(false);
                String formatSupport = getFormatSupportString(RendererCapabilities.FORMAT_UNSUPPORTED_TYPE);
                Log.d(TAG, "      " + status + " Track:" + trackIndex + ", " + Format.toLogString(trackGroup.getFormat(trackIndex)) + ", supported=" + formatSupport);
            }
            Log.d(TAG, "    ]");
        }
        Log.d(TAG, "  ]");
    }
    Log.d(TAG, "]");
}
Also used : TrackGroup(com.google.android.exoplayer2.source.TrackGroup) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) Metadata(com.google.android.exoplayer2.metadata.Metadata) MappedTrackInfo(com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo) TrackSelection(com.google.android.exoplayer2.trackselection.TrackSelection)

Example 42 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class MappingTrackSelector method maybeConfigureRenderersForTunneling.

/**
   * Determines whether tunneling should be enabled, replacing {@link RendererConfiguration}s in
   * {@code rendererConfigurations} with configurations that enable tunneling on the appropriate
   * renderers if so.
   *
   * @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which
   *     {@link TrackSelection}s are to be generated.
   * @param rendererTrackGroupArrays An array of {@link TrackGroupArray}s where each entry
   *     corresponds to the renderer of equal index in {@code renderers}.
   * @param rendererFormatSupports Maps every available track to a specific level of support as
   *     defined by the renderer {@code FORMAT_*} constants.
   * @param rendererConfigurations The renderer configurations. Configurations may be replaced with
   *     ones that enable tunneling as a result of this call.
   * @param trackSelections The renderer track selections.
   * @param tunnelingAudioSessionId The audio session id to use when tunneling, or
   *     {@link C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
   */
private static void maybeConfigureRenderersForTunneling(RendererCapabilities[] rendererCapabilities, TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports, RendererConfiguration[] rendererConfigurations, TrackSelection[] trackSelections, int tunnelingAudioSessionId) {
    if (tunnelingAudioSessionId == C.AUDIO_SESSION_ID_UNSET) {
        return;
    }
    // Check whether we can enable tunneling. To enable tunneling we require exactly one audio and
    // one video renderer to support tunneling and have a selection.
    int tunnelingAudioRendererIndex = -1;
    int tunnelingVideoRendererIndex = -1;
    boolean enableTunneling = true;
    for (int i = 0; i < rendererCapabilities.length; i++) {
        int rendererType = rendererCapabilities[i].getTrackType();
        TrackSelection trackSelection = trackSelections[i];
        if ((rendererType == C.TRACK_TYPE_AUDIO || rendererType == C.TRACK_TYPE_VIDEO) && trackSelection != null) {
            if (rendererSupportsTunneling(rendererFormatSupports[i], rendererTrackGroupArrays[i], trackSelection)) {
                if (rendererType == C.TRACK_TYPE_AUDIO) {
                    if (tunnelingAudioRendererIndex != -1) {
                        enableTunneling = false;
                        break;
                    } else {
                        tunnelingAudioRendererIndex = i;
                    }
                } else {
                    if (tunnelingVideoRendererIndex != -1) {
                        enableTunneling = false;
                        break;
                    } else {
                        tunnelingVideoRendererIndex = i;
                    }
                }
            }
        }
    }
    enableTunneling &= tunnelingAudioRendererIndex != -1 && tunnelingVideoRendererIndex != -1;
    if (enableTunneling) {
        RendererConfiguration tunnelingRendererConfiguration = new RendererConfiguration(tunnelingAudioSessionId);
        rendererConfigurations[tunnelingAudioRendererIndex] = tunnelingRendererConfiguration;
        rendererConfigurations[tunnelingVideoRendererIndex] = tunnelingRendererConfiguration;
    }
}
Also used : RendererConfiguration(com.google.android.exoplayer2.RendererConfiguration)

Example 43 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class MappingTrackSelector method selectTracks.

// TrackSelector implementation.
@Override
public final TrackSelectorResult selectTracks(RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups) throws ExoPlaybackException {
    // Structures into which data will be written during the selection. The extra item at the end
    // of each array is to store data associated with track groups that cannot be associated with
    // any renderer.
    int[] rendererTrackGroupCounts = new int[rendererCapabilities.length + 1];
    TrackGroup[][] rendererTrackGroups = new TrackGroup[rendererCapabilities.length + 1][];
    int[][][] rendererFormatSupports = new int[rendererCapabilities.length + 1][][];
    for (int i = 0; i < rendererTrackGroups.length; i++) {
        rendererTrackGroups[i] = new TrackGroup[trackGroups.length];
        rendererFormatSupports[i] = new int[trackGroups.length][];
    }
    // Determine the extent to which each renderer supports mixed mimeType adaptation.
    int[] mixedMimeTypeAdaptationSupport = getMixedMimeTypeAdaptationSupport(rendererCapabilities);
    // renderer provides for each track in the group.
    for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
        TrackGroup group = trackGroups.get(groupIndex);
        // Associate the group to a preferred renderer.
        int rendererIndex = findRenderer(rendererCapabilities, group);
        // Evaluate the support that the renderer provides for each track in the group.
        int[] rendererFormatSupport = rendererIndex == rendererCapabilities.length ? new int[group.length] : getFormatSupport(rendererCapabilities[rendererIndex], group);
        // Stash the results.
        int rendererTrackGroupCount = rendererTrackGroupCounts[rendererIndex];
        rendererTrackGroups[rendererIndex][rendererTrackGroupCount] = group;
        rendererFormatSupports[rendererIndex][rendererTrackGroupCount] = rendererFormatSupport;
        rendererTrackGroupCounts[rendererIndex]++;
    }
    // Create a track group array for each renderer, and trim each rendererFormatSupports entry.
    TrackGroupArray[] rendererTrackGroupArrays = new TrackGroupArray[rendererCapabilities.length];
    int[] rendererTrackTypes = new int[rendererCapabilities.length];
    for (int i = 0; i < rendererCapabilities.length; i++) {
        int rendererTrackGroupCount = rendererTrackGroupCounts[i];
        rendererTrackGroupArrays[i] = new TrackGroupArray(Arrays.copyOf(rendererTrackGroups[i], rendererTrackGroupCount));
        rendererFormatSupports[i] = Arrays.copyOf(rendererFormatSupports[i], rendererTrackGroupCount);
        rendererTrackTypes[i] = rendererCapabilities[i].getTrackType();
    }
    // Create a track group array for track groups not associated with a renderer.
    int unassociatedTrackGroupCount = rendererTrackGroupCounts[rendererCapabilities.length];
    TrackGroupArray unassociatedTrackGroupArray = new TrackGroupArray(Arrays.copyOf(rendererTrackGroups[rendererCapabilities.length], unassociatedTrackGroupCount));
    TrackSelection[] trackSelections = selectTracks(rendererCapabilities, rendererTrackGroupArrays, rendererFormatSupports);
    // Apply track disabling and overriding.
    for (int i = 0; i < rendererCapabilities.length; i++) {
        if (rendererDisabledFlags.get(i)) {
            trackSelections[i] = null;
        } else {
            TrackGroupArray rendererTrackGroup = rendererTrackGroupArrays[i];
            Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(i);
            SelectionOverride override = overrides == null ? null : overrides.get(rendererTrackGroup);
            if (override != null) {
                trackSelections[i] = override.createTrackSelection(rendererTrackGroup);
            }
        }
    }
    // Package up the track information and selections.
    MappedTrackInfo mappedTrackInfo = new MappedTrackInfo(rendererTrackTypes, rendererTrackGroupArrays, mixedMimeTypeAdaptationSupport, rendererFormatSupports, unassociatedTrackGroupArray);
    // Initialize the renderer configurations to the default configuration for all renderers with
    // selections, and null otherwise.
    RendererConfiguration[] rendererConfigurations = new RendererConfiguration[rendererCapabilities.length];
    for (int i = 0; i < rendererCapabilities.length; i++) {
        rendererConfigurations[i] = trackSelections[i] != null ? RendererConfiguration.DEFAULT : null;
    }
    // Configure audio and video renderers to use tunneling if appropriate.
    maybeConfigureRenderersForTunneling(rendererCapabilities, rendererTrackGroupArrays, rendererFormatSupports, rendererConfigurations, trackSelections, tunnelingAudioSessionId);
    return new TrackSelectorResult(trackGroups, new TrackSelectionArray(trackSelections), mappedTrackInfo, rendererConfigurations);
}
Also used : TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) TrackGroup(com.google.android.exoplayer2.source.TrackGroup) RendererConfiguration(com.google.android.exoplayer2.RendererConfiguration)

Example 44 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class MappingTrackSelector method findRenderer.

/**
   * Finds the renderer to which the provided {@link TrackGroup} should be associated.
   * <p>
   * A {@link TrackGroup} is associated to a renderer that reports
   * {@link RendererCapabilities#FORMAT_HANDLED} support for one or more of the tracks in the group,
   * or {@link RendererCapabilities#FORMAT_EXCEEDS_CAPABILITIES} if no such renderer exists, or
   * {@link RendererCapabilities#FORMAT_UNSUPPORTED_SUBTYPE} if again no such renderer exists. In
   * the case that two or more renderers report the same level of support, the renderer with the
   * lowest index is associated.
   * <p>
   * If all renderers report {@link RendererCapabilities#FORMAT_UNSUPPORTED_TYPE} for all of the
   * tracks in the group, then {@code renderers.length} is returned to indicate that no association
   * was made.
   *
   * @param rendererCapabilities The {@link RendererCapabilities} of the renderers.
   * @param group The {@link TrackGroup} whose associated renderer is to be found.
   * @return The index of the associated renderer, or {@code renderers.length} if no
   *     association was made.
   * @throws ExoPlaybackException If an error occurs finding a renderer.
   */
private static int findRenderer(RendererCapabilities[] rendererCapabilities, TrackGroup group) throws ExoPlaybackException {
    int bestRendererIndex = rendererCapabilities.length;
    int bestFormatSupportLevel = RendererCapabilities.FORMAT_UNSUPPORTED_TYPE;
    for (int rendererIndex = 0; rendererIndex < rendererCapabilities.length; rendererIndex++) {
        RendererCapabilities rendererCapability = rendererCapabilities[rendererIndex];
        for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
            int formatSupportLevel = rendererCapability.supportsFormat(group.getFormat(trackIndex)) & RendererCapabilities.FORMAT_SUPPORT_MASK;
            if (formatSupportLevel > bestFormatSupportLevel) {
                bestRendererIndex = rendererIndex;
                bestFormatSupportLevel = formatSupportLevel;
                if (bestFormatSupportLevel == RendererCapabilities.FORMAT_HANDLED) {
                    // We can't do better.
                    return bestRendererIndex;
                }
            }
        }
    }
    return bestRendererIndex;
}
Also used : RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities)

Example 45 with Renderer

use of com.google.android.exoplayer2.Renderer in project ExoPlayer by google.

the class ExoPlayerTest method testPlayMultiPeriodTimeline.

/**
   * Tests playback of a source that exposes three periods.
   */
public void testPlayMultiPeriodTimeline() throws Exception {
    PlayerWrapper playerWrapper = new PlayerWrapper();
    Timeline timeline = new FakeTimeline(new TimelineWindowDefinition(false, false, 0), new TimelineWindowDefinition(false, false, 0), new TimelineWindowDefinition(false, false, 0));
    MediaSource mediaSource = new FakeMediaSource(timeline, null, TEST_VIDEO_FORMAT);
    FakeRenderer renderer = new FakeRenderer(TEST_VIDEO_FORMAT);
    playerWrapper.setup(mediaSource, renderer);
    playerWrapper.blockUntilEnded(TIMEOUT_MS);
    assertEquals(2, playerWrapper.positionDiscontinuityCount);
    assertEquals(3, renderer.formatReadCount);
    assertEquals(1, renderer.bufferReadCount);
    assertTrue(renderer.isEnded);
    assertEquals(timeline, playerWrapper.timeline);
    assertNull(playerWrapper.manifest);
}
Also used : MediaSource(com.google.android.exoplayer2.source.MediaSource)

Aggregations

Test (org.junit.Test)36 FakeRenderer (com.google.android.exoplayer2.testutil.FakeRenderer)27 Nullable (androidx.annotation.Nullable)25 FakeMediaSource (com.google.android.exoplayer2.testutil.FakeMediaSource)25 FakeTimeline (com.google.android.exoplayer2.testutil.FakeTimeline)25 TestExoPlayerBuilder (com.google.android.exoplayer2.testutil.TestExoPlayerBuilder)24 TextRenderer (com.google.android.exoplayer2.text.TextRenderer)21 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)19 ArrayList (java.util.ArrayList)18 SinglePeriodTimeline (com.google.android.exoplayer2.source.SinglePeriodTimeline)17 NoUidTimeline (com.google.android.exoplayer2.testutil.NoUidTimeline)17 MediaSource (com.google.android.exoplayer2.source.MediaSource)16 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)16 ActionSchedule (com.google.android.exoplayer2.testutil.ActionSchedule)16 Format (com.google.android.exoplayer2.Format)15 Listener (com.google.android.exoplayer2.Player.Listener)15 ExoPlayerTestRunner (com.google.android.exoplayer2.testutil.ExoPlayerTestRunner)15 TimelineWindowDefinition (com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition)14 InOrder (org.mockito.InOrder)14 ConcatenatingMediaSource (com.google.android.exoplayer2.source.ConcatenatingMediaSource)13