Search in sources :

Example 6 with MediaCodecSelector

use of com.google.android.exoplayer2.mediacodec.MediaCodecSelector in project ExoPlayer by google.

the class DefaultRenderersFactory method buildAudioRenderers.

/**
 * Builds audio renderers for use by the player.
 *
 * @param context The {@link Context} associated with the player.
 * @param extensionRendererMode The extension renderer mode.
 * @param mediaCodecSelector A decoder selector.
 * @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
 *     initialization fails. This may result in using a decoder that is slower/less efficient than
 *     the primary decoder.
 * @param audioSink A sink to which the renderers will output.
 * @param eventHandler A handler to use when invoking event listeners and outputs.
 * @param eventListener An event listener.
 * @param out An array to which the built renderers should be appended.
 */
protected void buildAudioRenderers(Context context, @ExtensionRendererMode int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, AudioSink audioSink, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
    MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer(context, getCodecAdapterFactory(), mediaCodecSelector, enableDecoderFallback, eventHandler, eventListener, audioSink);
    out.add(audioRenderer);
    if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) {
        return;
    }
    int extensionRendererIndex = out.size();
    if (extensionRendererMode == EXTENSION_RENDERER_MODE_PREFER) {
        extensionRendererIndex--;
    }
    try {
        // Full class names used for constructor args so the LINT rule triggers if any of them move.
        Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.opus.LibopusAudioRenderer");
        Constructor<?> constructor = clazz.getConstructor(android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class);
        Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);
        out.add(extensionRendererIndex++, renderer);
        Log.i(TAG, "Loaded LibopusAudioRenderer.");
    } catch (ClassNotFoundException e) {
    // Expected if the app was built without the extension.
    } catch (Exception e) {
        // The extension is present, but instantiation failed.
        throw new RuntimeException("Error instantiating Opus extension", e);
    }
    try {
        // Full class names used for constructor args so the LINT rule triggers if any of them move.
        Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer");
        Constructor<?> constructor = clazz.getConstructor(android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class);
        Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);
        out.add(extensionRendererIndex++, renderer);
        Log.i(TAG, "Loaded LibflacAudioRenderer.");
    } catch (ClassNotFoundException e) {
    // Expected if the app was built without the extension.
    } catch (Exception e) {
        // The extension is present, but instantiation failed.
        throw new RuntimeException("Error instantiating FLAC extension", e);
    }
    try {
        // Full class names used for constructor args so the LINT rule triggers if any of them move.
        Class<?> clazz = Class.forName("com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer");
        Constructor<?> constructor = clazz.getConstructor(android.os.Handler.class, com.google.android.exoplayer2.audio.AudioRendererEventListener.class, com.google.android.exoplayer2.audio.AudioSink.class);
        Renderer renderer = (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);
        out.add(extensionRendererIndex++, renderer);
        Log.i(TAG, "Loaded FfmpegAudioRenderer.");
    } catch (ClassNotFoundException e) {
    // Expected if the app was built without the extension.
    } catch (Exception e) {
        // The extension is present, but instantiation failed.
        throw new RuntimeException("Error instantiating FFmpeg extension", e);
    }
}
Also used : MediaCodecAudioRenderer(com.google.android.exoplayer2.audio.MediaCodecAudioRenderer) CameraMotionRenderer(com.google.android.exoplayer2.video.spherical.CameraMotionRenderer) MediaCodecAudioRenderer(com.google.android.exoplayer2.audio.MediaCodecAudioRenderer) MetadataRenderer(com.google.android.exoplayer2.metadata.MetadataRenderer) MediaCodecVideoRenderer(com.google.android.exoplayer2.video.MediaCodecVideoRenderer) TextRenderer(com.google.android.exoplayer2.text.TextRenderer)

Example 7 with MediaCodecSelector

use of com.google.android.exoplayer2.mediacodec.MediaCodecSelector in project ExoPlayer by google.

the class MediaCodecAudioRendererTest method setUp.

@Before
public void setUp() throws Exception {
    // audioSink isEnded can always be true because the MediaCodecAudioRenderer isEnded =
    // super.isEnded && audioSink.isEnded.
    when(audioSink.isEnded()).thenReturn(true);
    when(audioSink.handleBuffer(any(), anyLong(), anyInt())).thenReturn(true);
    when(audioSink.supportsFormat(any())).thenAnswer(invocation -> {
        Format format = invocation.getArgument(/* index= */
        0, Format.class);
        return MimeTypes.AUDIO_RAW.equals(format.sampleMimeType) && format.pcmEncoding == C.ENCODING_PCM_16BIT;
    });
    mediaCodecSelector = (mimeType, requiresSecureDecoder, requiresTunnelingDecoder) -> Collections.singletonList(MediaCodecInfo.newInstance(/* name= */
    "name", /* mimeType= */
    mimeType, /* codecMimeType= */
    mimeType, /* capabilities= */
    null, /* hardwareAccelerated= */
    false, /* softwareOnly= */
    true, /* vendor= */
    false, /* forceDisableAdaptive= */
    false, /* forceSecure= */
    false));
    Handler eventHandler = new Handler(Looper.getMainLooper());
    mediaCodecAudioRenderer = new MediaCodecAudioRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* enableDecoderFallback= */
    false, eventHandler, audioRendererEventListener, audioSink);
    mediaCodecAudioRenderer.init(/* index= */
    0, PlayerId.UNSET);
}
Also used : MediaFormat(android.media.MediaFormat) Format(com.google.android.exoplayer2.Format) Handler(android.os.Handler) Before(org.junit.Before)

Example 8 with MediaCodecSelector

use of com.google.android.exoplayer2.mediacodec.MediaCodecSelector in project ExoPlayer by google.

the class MediaCodecAudioRendererTest method render_throwsExoPlaybackExceptionJustOnce_whenSet.

@Test
public void render_throwsExoPlaybackExceptionJustOnce_whenSet() throws Exception {
    MediaCodecAudioRenderer exceptionThrowingRenderer = new MediaCodecAudioRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* eventHandler= */
    null, /* eventListener= */
    null) {

        @Override
        protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaFormat) throws ExoPlaybackException {
            super.onOutputFormatChanged(format, mediaFormat);
            if (!format.equals(AUDIO_AAC)) {
                setPendingPlaybackException(ExoPlaybackException.createForRenderer(new AudioSink.ConfigurationException("Test", format), "rendererName", /* rendererIndex= */
                0, format, C.FORMAT_HANDLED, /* isRecoverable= */
                false, PlaybackException.ERROR_CODE_UNSPECIFIED));
            }
        }
    };
    Format changedFormat = AUDIO_AAC.buildUpon().setSampleRate(32_000).build();
    FakeSampleStream fakeSampleStream = new FakeSampleStream(new DefaultAllocator(/* trimOnReset= */
    true, /* individualAllocationSize= */
    1024), /* mediaSourceEventDispatcher= */
    null, DrmSessionManager.DRM_UNSUPPORTED, new DrmSessionEventListener.EventDispatcher(), /* initialFormat= */
    AUDIO_AAC, ImmutableList.of(oneByteSample(/* timeUs= */
    0, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM));
    fakeSampleStream.writeData(/* startPositionUs= */
    0);
    exceptionThrowingRenderer.init(/* index= */
    0, PlayerId.UNSET);
    exceptionThrowingRenderer.enable(RendererConfiguration.DEFAULT, new Format[] { AUDIO_AAC, changedFormat }, fakeSampleStream, /* positionUs= */
    0, /* joining= */
    false, /* mayRenderStartOfStream= */
    false, /* startPositionUs= */
    0, /* offsetUs */
    0);
    exceptionThrowingRenderer.start();
    exceptionThrowingRenderer.render(/* positionUs= */
    0, SystemClock.elapsedRealtime() * 1000);
    exceptionThrowingRenderer.render(/* positionUs= */
    250, SystemClock.elapsedRealtime() * 1000);
    MediaFormat mediaFormat = new MediaFormat();
    mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
    mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 32_000);
    // Simulating the exception being thrown when not traceable back to render.
    exceptionThrowingRenderer.onOutputFormatChanged(changedFormat, mediaFormat);
    assertThrows(ExoPlaybackException.class, () -> exceptionThrowingRenderer.render(/* positionUs= */
    500, SystemClock.elapsedRealtime() * 1000));
    // Doesn't throw an exception because it's cleared after being thrown in the previous call to
    // render.
    exceptionThrowingRenderer.render(/* positionUs= */
    750, SystemClock.elapsedRealtime() * 1000);
}
Also used : MediaFormat(android.media.MediaFormat) FakeSampleStream(com.google.android.exoplayer2.testutil.FakeSampleStream) MediaFormat(android.media.MediaFormat) Format(com.google.android.exoplayer2.Format) DefaultAllocator(com.google.android.exoplayer2.upstream.DefaultAllocator) DrmSessionEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener) Nullable(androidx.annotation.Nullable) Test(org.junit.Test)

Example 9 with MediaCodecSelector

use of com.google.android.exoplayer2.mediacodec.MediaCodecSelector in project ExoPlayer by google.

the class MediaCodecAudioRendererTest method supportsFormat_withEac3JocMediaAndEac3Decoder_returnsTrue.

@Test
public void supportsFormat_withEac3JocMediaAndEac3Decoder_returnsTrue() throws Exception {
    Format mediaFormat = new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_E_AC3_JOC).setCodecs(MimeTypes.CODEC_E_AC3_JOC).build();
    MediaCodecSelector mediaCodecSelector = (mimeType, requiresSecureDecoder, requiresTunnelingDecoder) -> !mimeType.equals(MimeTypes.AUDIO_E_AC3) ? ImmutableList.of() : ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
    "eac3-codec", /* mimeType= */
    mimeType, /* codecMimeType= */
    mimeType, /* capabilities= */
    null, /* hardwareAccelerated= */
    false, /* softwareOnly= */
    true, /* vendor= */
    false, /* forceDisableAdaptive= */
    false, /* forceSecure= */
    false));
    MediaCodecAudioRenderer renderer = new MediaCodecAudioRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* enableDecoderFallback= */
    false, /* eventHandler= */
    new Handler(Looper.getMainLooper()), audioRendererEventListener, audioSink);
    renderer.init(/* index= */
    0, PlayerId.UNSET);
    @Capabilities int capabilities = renderer.supportsFormat(mediaFormat);
    assertThat(RendererCapabilities.getFormatSupport(capabilities)).isEqualTo(C.FORMAT_HANDLED);
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) ExoPlaybackException(com.google.android.exoplayer2.ExoPlaybackException) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) MediaFormat(android.media.MediaFormat) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Mock(org.mockito.Mock) Assert.assertThrows(org.junit.Assert.assertThrows) RunWith(org.junit.runner.RunWith) SystemClock(android.os.SystemClock) AndroidJUnit4(androidx.test.ext.junit.runners.AndroidJUnit4) Shadows.shadowOf(org.robolectric.Shadows.shadowOf) ApplicationProvider(androidx.test.core.app.ApplicationProvider) Format(com.google.android.exoplayer2.Format) PlayerId(com.google.android.exoplayer2.analytics.PlayerId) MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo) ArgumentCaptor(org.mockito.ArgumentCaptor) DrmSessionEventListener(com.google.android.exoplayer2.drm.DrmSessionEventListener) MimeTypes(com.google.android.exoplayer2.util.MimeTypes) ImmutableList(com.google.common.collect.ImmutableList) Handler(android.os.Handler) Looper(android.os.Looper) MockitoJUnit(org.mockito.junit.MockitoJUnit) ArgumentMatchers.anyInt(org.mockito.ArgumentMatchers.anyInt) FakeSampleStream(com.google.android.exoplayer2.testutil.FakeSampleStream) DefaultAllocator(com.google.android.exoplayer2.upstream.DefaultAllocator) C(com.google.android.exoplayer2.C) Before(org.junit.Before) FakeSampleStreamItem.format(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) END_OF_STREAM_ITEM(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) FakeSampleStreamItem.oneByteSample(com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample) Nullable(androidx.annotation.Nullable) Rule(org.junit.Rule) RendererConfiguration(com.google.android.exoplayer2.RendererConfiguration) MediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector) PlaybackException(com.google.android.exoplayer2.PlaybackException) DrmSessionManager(com.google.android.exoplayer2.drm.DrmSessionManager) MockitoRule(org.mockito.junit.MockitoRule) Collections(java.util.Collections) MediaCodecSelector(com.google.android.exoplayer2.mediacodec.MediaCodecSelector) MediaFormat(android.media.MediaFormat) Format(com.google.android.exoplayer2.Format) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Capabilities(com.google.android.exoplayer2.RendererCapabilities.Capabilities) Handler(android.os.Handler) Test(org.junit.Test)

Example 10 with MediaCodecSelector

use of com.google.android.exoplayer2.mediacodec.MediaCodecSelector in project ExoPlayer by google.

the class MediaCodecAudioRenderer method getDecoderInfos.

/**
 * Returns a list of decoders that can decode media in the specified format, in the priority order
 * specified by the {@link MediaCodecSelector}. Note that since the {@link MediaCodecSelector}
 * only has access to {@link Format#sampleMimeType}, the list is not ordered to account for
 * whether each decoder supports the details of the format (e.g., taking into account the format's
 * profile, level, channel count and so on). {@link
 * MediaCodecUtil#getDecoderInfosSortedByFormatSupport} can be used to further sort the list into
 * an order where decoders that fully support the format come first.
 *
 * @param mediaCodecSelector The decoder selector.
 * @param format The {@link Format} for which a decoder is required.
 * @param requiresSecureDecoder Whether a secure decoder is required.
 * @param audioSink The {@link AudioSink} to which audio will be output.
 * @return A list of {@link MediaCodecInfo}s corresponding to decoders. May be empty.
 * @throws DecoderQueryException Thrown if there was an error querying decoders.
 */
private static List<MediaCodecInfo> getDecoderInfos(MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder, AudioSink audioSink) throws DecoderQueryException {
    @Nullable String mimeType = format.sampleMimeType;
    if (mimeType == null) {
        return ImmutableList.of();
    }
    if (audioSink.supportsFormat(format)) {
        // The format is supported directly, so a codec is only needed for decryption.
        @Nullable MediaCodecInfo codecInfo = MediaCodecUtil.getDecryptOnlyDecoderInfo();
        if (codecInfo != null) {
            return ImmutableList.of(codecInfo);
        }
    }
    List<MediaCodecInfo> decoderInfos = mediaCodecSelector.getDecoderInfos(mimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */
    false);
    @Nullable String alternativeMimeType = MediaCodecUtil.getAlternativeCodecMimeType(format);
    if (alternativeMimeType == null) {
        return ImmutableList.copyOf(decoderInfos);
    }
    List<MediaCodecInfo> alternativeDecoderInfos = mediaCodecSelector.getDecoderInfos(alternativeMimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */
    false);
    return ImmutableList.<MediaCodecInfo>builder().addAll(decoderInfos).addAll(alternativeDecoderInfos).build();
}
Also used : MediaCodecInfo(com.google.android.exoplayer2.mediacodec.MediaCodecInfo) Nullable(androidx.annotation.Nullable)

Aggregations

Nullable (androidx.annotation.Nullable)7 MediaCodecInfo (com.google.android.exoplayer2.mediacodec.MediaCodecInfo)6 MediaFormat (android.media.MediaFormat)5 Format (com.google.android.exoplayer2.Format)5 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)5 Handler (android.os.Handler)4 DrmSessionEventListener (com.google.android.exoplayer2.drm.DrmSessionEventListener)4 FakeSampleStream (com.google.android.exoplayer2.testutil.FakeSampleStream)4 DefaultAllocator (com.google.android.exoplayer2.upstream.DefaultAllocator)4 Before (org.junit.Before)4 Test (org.junit.Test)4 CodecCapabilities (android.media.MediaCodecInfo.CodecCapabilities)3 Looper (android.os.Looper)3 SystemClock (android.os.SystemClock)3 ApplicationProvider (androidx.test.core.app.ApplicationProvider)3 AndroidJUnit4 (androidx.test.ext.junit.runners.AndroidJUnit4)3 C (com.google.android.exoplayer2.C)3 Capabilities (com.google.android.exoplayer2.RendererCapabilities.Capabilities)3 RendererConfiguration (com.google.android.exoplayer2.RendererConfiguration)3 PlayerId (com.google.android.exoplayer2.analytics.PlayerId)3