ArrayList<Renderer> out) { out.add( new MediaCodecAudioRenderer( context, MediaCodecSelector.DEFAULT,
@Override protected List<MediaCodecInfo> getDecoderInfos( MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder) throws DecoderQueryException { if (allowPassthrough(format.channelCount, format.sampleMimeType)) { MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo(); if (passthroughDecoderInfo != null) { return Collections.singletonList(passthroughDecoderInfo); } } return super.getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder); }
@Override protected void configureCodec( MediaCodecInfo codecInfo, MediaCodec codec, Format format, MediaCrypto crypto, float codecOperatingRate) { codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats()); codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name); codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name); passthroughEnabled = codecInfo.passthrough; String codecMimeType = codecInfo.mimeType == null ? MimeTypes.AUDIO_RAW : codecInfo.mimeType; MediaFormat mediaFormat = getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate); codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0); if (passthroughEnabled) { // Store the input MIME type if we're using the passthrough codec. passthroughMediaFormat = mediaFormat; passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType); } else { passthroughMediaFormat = null; } }
boolean supportsFormatDrm = supportsFormatDrm(drmSessionManager, format.drmInitData); if (supportsFormatDrm && allowPassthrough(format.channelCount, mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) { return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | FORMAT_HANDLED;
@Override protected void renderToEndOfStream() throws ExoPlaybackException { try { audioSink.playToEndOfStream(); } catch (AudioSink.WriteException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } }
/** * Returns a maximum input size suitable for configuring a codec for {@code format} in a way that * will allow possible adaptation to other compatible formats in {@code streamFormats}. * * @param codecInfo A {@link MediaCodecInfo} describing the decoder. * @param format The format for which the codec is being configured. * @param streamFormats The possible stream formats. * @return A suitable maximum input size. */ protected int getCodecMaxInputSize( MediaCodecInfo codecInfo, Format format, Format[] streamFormats) { int maxInputSize = getCodecMaxInputSize(codecInfo, format); if (streamFormats.length == 1) { // The single entry in streamFormats must correspond to the format for which the codec is // being configured. return maxInputSize; } for (Format streamFormat : streamFormats) { if (codecInfo.isSeamlessAdaptationSupported( format, streamFormat, /* isNewFormatComplete= */ false)) { maxInputSize = Math.max(maxInputSize, getCodecMaxInputSize(codecInfo, streamFormat)); } } return maxInputSize; }
@Override protected void onEnabled(boolean joining) throws ExoPlaybackException { super.onEnabled(joining); eventDispatcher.enabled(decoderCounters); int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId; if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) { audioSink.enableTunnelingV21(tunnelingAudioSessionId); } else { audioSink.disableTunneling(); } }
@Override protected void onOutputFormatChanged(MediaCodec codec, MediaFormat outputFormat) throws ExoPlaybackException { @C.Encoding int encoding; MediaFormat format; if (passthroughMediaFormat != null) { encoding = MimeTypes.getEncoding(passthroughMediaFormat.getString(MediaFormat.KEY_MIME)); format = passthroughMediaFormat; } else { encoding = pcmEncoding; format = outputFormat; } int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT); int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE); int[] channelMap; if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && this.channelCount < 6) { channelMap = new int[this.channelCount]; for (int i = 0; i < this.channelCount; i++) { channelMap[i] = i; } } else { channelMap = null; } try { audioSink.configure(encoding, channelCount, sampleRate, 0, channelMap, encoderDelay, encoderPadding); } catch (AudioSink.ConfigurationException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } }
@Override protected @KeepCodecResult int canKeepCodec( MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) { if (getCodecMaxInputSize(codecInfo, newFormat) <= codecMaxInputSize && codecInfo.isSeamlessAdaptationSupported( oldFormat, newFormat, /* isNewFormatComplete= */ true) && oldFormat.encoderDelay == 0 && oldFormat.encoderPadding == 0 && newFormat.encoderDelay == 0 && newFormat.encoderPadding == 0) { return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION; } else { return KEEP_CODEC_RESULT_NO; } }
@NonNull protected List<Renderer> buildAudioRenderers() { List<Renderer> renderers = new ArrayList<>(); renderers.add(new MediaCodecAudioRenderer(context, MediaCodecSelector.DEFAULT, drmSessionManager, true, handler, audioRendererEventListener, AudioCapabilities.getCapabilities(context))); // Adds any registered classes List<String> classNames = ExoMedia.Data.registeredRendererClasses.get(ExoMedia.RendererType.AUDIO); if (classNames != null) { for (String className: classNames) { try { Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getConstructor(Handler.class, AudioRendererEventListener.class); Renderer renderer = (Renderer) constructor.newInstance(handler, audioRendererEventListener); renderers.add(renderer); } catch (Exception e) { // Purposefully left blank } } } return renderers; }
throw ExoPlaybackException.createForRenderer(e, getIndex());
@ExtensionRendererMode int extensionRendererMode, List<Renderer> outRenderers) { MediaCodecAudioRenderer mediaCodecAudioRenderer = new MediaCodecAudioRenderer( context, mediaCodecSelector,
out.add(new MediaCodecAudioRenderer(mediaCodecSelector, drmSessionManager, true, eventHandler, eventListener, audioCapabilities));