/** * Creates a VP9 decoder. * * @param numInputBuffers The number of input buffers. * @param numOutputBuffers The number of output buffers. * @param initialInputBufferSize The initial size of each input buffer. * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * content. Maybe null and can be ignored if decoder does not handle encrypted content. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. */ public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, ExoMediaCrypto exoMediaCrypto) throws VpxDecoderException { super(new DecoderInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]); if (!VpxLibrary.isAvailable()) { throw new VpxDecoderException("Failed to load decoder native libraries."); } this.exoMediaCrypto = exoMediaCrypto; if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { throw new VpxDecoderException("Vpx decoder does not support secure decode."); } vpxDecContext = vpxInit(); if (vpxDecContext == 0) { throw new VpxDecoderException("Failed to initialize decoder"); } setInitialInputBufferSize(initialInputBufferSize); }
/** * @param scaleToFit Whether video frames should be scaled to fit when rendering. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. */ public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFramesToNotify, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(C.TRACK_TYPE_VIDEO); this.scaleToFit = scaleToFit; this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; joiningDeadlineMs = C.TIME_UNSET; clearReportedVideoSize(); formatHolder = new FormatHolder(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); eventDispatcher = new EventDispatcher(eventHandler, eventListener); outputMode = VpxDecoder.OUTPUT_MODE_NONE; decoderReinitializationState = REINITIALIZATION_STATE_NONE; }
/** * Creates a VP9 decoder. * * @param numInputBuffers The number of input buffers. * @param numOutputBuffers The number of output buffers. * @param initialInputBufferSize The initial size of each input buffer. * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * content. Maybe null and can be ignored if decoder does not handle encrypted content. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. */ public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, ExoMediaCrypto exoMediaCrypto) throws VpxDecoderException { super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]); if (!VpxLibrary.isAvailable()) { throw new VpxDecoderException("Failed to load decoder native libraries."); } this.exoMediaCrypto = exoMediaCrypto; if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { throw new VpxDecoderException("Vpx decoder does not support secure decode."); } vpxDecContext = vpxInit(); if (vpxDecContext == 0) { throw new VpxDecoderException("Failed to initialize decoder"); } setInitialInputBufferSize(initialInputBufferSize); }
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); audioRenderer = new SimpleDecoderAudioRenderer(null, null, null, false, mockAudioSink) { @Override protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager, Format format) { return FORMAT_HANDLED; } @Override protected SimpleDecoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends AudioDecoderException> createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws AudioDecoderException { return new FakeDecoder(); } }; }
private void maybeInitDecoder() throws ExoPlaybackException { if (decoder != null) { return; } drmSession = pendingDrmSession; ExoMediaCrypto mediaCrypto = null; if (drmSession != null) { @DrmSession.State int drmSessionState = drmSession.getState(); if (drmSessionState == DrmSession.STATE_ERROR) { throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); } else if (drmSessionState == DrmSession.STATE_OPENED || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) { mediaCrypto = drmSession.getMediaCrypto(); } else { // The drm session isn't open yet. return; } } try { long codecInitializingTimestamp = SystemClock.elapsedRealtime(); TraceUtil.beginSection("createAudioDecoder"); decoder = createDecoder(inputFormat, mediaCrypto); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); decoderCounters.decoderInitCount++; } catch (AudioDecoderException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } }
@Override protected FfmpegDecoder createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws FfmpegDecoderException { decoder = new FfmpegDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, format.sampleMimeType, format.initializationData); return decoder; }
private void maybeInitDecoder() throws ExoPlaybackException { if (decoder != null) { return; } drmSession = pendingDrmSession; ExoMediaCrypto mediaCrypto = null; if (drmSession != null) { mediaCrypto = drmSession.getMediaCrypto(); if (mediaCrypto == null) { DrmSessionException drmError = drmSession.getError(); if (drmError != null) { throw ExoPlaybackException.createForRenderer(drmError, getIndex()); } // The drm session isn't open yet. return; } } try { long codecInitializingTimestamp = SystemClock.elapsedRealtime(); TraceUtil.beginSection("createVpxDecoder"); decoder = new VpxDecoder(NUM_INPUT_BUFFERS, NUM_OUTPUT_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto); decoder.setOutputMode(outputMode); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); decoderCounters.decoderInitCount++; } catch (VpxDecoderException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } }
@Override protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager, Format format) { if (!OpusLibrary.isAvailable() || !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) { return FORMAT_UNSUPPORTED_TYPE; } else if (!supportsOutputEncoding(C.ENCODING_PCM_16BIT)) { return FORMAT_UNSUPPORTED_SUBTYPE; } else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) { return FORMAT_UNSUPPORTED_DRM; } else { return FORMAT_HANDLED; } }
@Override protected OpusDecoder createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws OpusDecoderException { decoder = new OpusDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, format.initializationData, mediaCrypto); return decoder; }
@Override protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager, Format format) { if (!FlacLibrary.isAvailable() || !MimeTypes.AUDIO_FLAC.equalsIgnoreCase(format.sampleMimeType)) { return FORMAT_UNSUPPORTED_TYPE; } else if (!supportsOutputEncoding(C.ENCODING_PCM_16BIT)) { return FORMAT_UNSUPPORTED_SUBTYPE; } else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) { return FORMAT_UNSUPPORTED_DRM; } else { return FORMAT_HANDLED; } }
@Override protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager, Format format) { String sampleMimeType = format.sampleMimeType; if (!FfmpegLibrary.isAvailable() || !MimeTypes.isAudio(sampleMimeType)) { return FORMAT_UNSUPPORTED_TYPE; } else if (!FfmpegLibrary.supportsFormat(sampleMimeType) || !isOutputSupported(format)) { return FORMAT_UNSUPPORTED_SUBTYPE; } else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) { return FORMAT_UNSUPPORTED_DRM; } else { return FORMAT_HANDLED; } }
@Override protected FfmpegDecoder createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws FfmpegDecoderException { decoder = new FfmpegDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, format.sampleMimeType, format.initializationData, shouldUseFloatOutput(format)); return decoder; }
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param audioSink The sink to which audio will be output. */ public SimpleDecoderAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, AudioSink audioSink) { super(C.TRACK_TYPE_AUDIO); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; eventDispatcher = new EventDispatcher(eventHandler, eventListener); this.audioSink = audioSink; audioSink.setListener(new AudioSinkListener()); formatHolder = new FormatHolder(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); decoderReinitializationState = REINITIALIZATION_STATE_NONE; audioTrackNeedsConfigure = true; }
private void maybeInitDecoder() throws ExoPlaybackException { if (decoder != null) { return; } drmSession = pendingDrmSession; ExoMediaCrypto mediaCrypto = null; if (drmSession != null) { mediaCrypto = drmSession.getMediaCrypto(); if (mediaCrypto == null) { DrmSessionException drmError = drmSession.getError(); if (drmError != null) { throw ExoPlaybackException.createForRenderer(drmError, getIndex()); } // The drm session isn't open yet. return; } } try { long codecInitializingTimestamp = SystemClock.elapsedRealtime(); TraceUtil.beginSection("createAudioDecoder"); decoder = createDecoder(inputFormat, mediaCrypto); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); decoderCounters.decoderInitCount++; } catch (AudioDecoderException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } }
/** * @param scaleToFit Whether video frames should be scaled to fit when rendering. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. */ public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFramesToNotify, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(C.TRACK_TYPE_VIDEO); this.scaleToFit = scaleToFit; this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; joiningDeadlineMs = -1; clearLastReportedVideoSize(); formatHolder = new FormatHolder(); eventDispatcher = new EventDispatcher(eventHandler, eventListener); outputMode = VpxDecoder.OUTPUT_MODE_NONE; }
@Override public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { if (outputStreamEnded) { return; } // Try and read a format if we don't have one already. if (format == null && !readFormat()) { // We can't make progress without one. return; } if (isRendererAvailable()) { drmSession = pendingDrmSession; ExoMediaCrypto mediaCrypto = null; if (drmSession != null) { int drmSessionState = drmSession.getState(); if (drmSessionState == DrmSession.STATE_ERROR) { throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); } else if (drmSessionState == DrmSession.STATE_OPENED || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) { mediaCrypto = drmSession.getMediaCrypto(); } else { // The drm session isn't open yet. return; } } try { if (decoder == null) { // If we don't have a decoder yet, we need to instantiate one. long codecInitializingTimestamp = SystemClock.elapsedRealtime(); TraceUtil.beginSection("createVpxDecoder"); decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto); decoder.setOutputMode(outputMode); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp); decoderCounters.decoderInitCount++; } TraceUtil.beginSection("drainAndFeed"); while (drainOutputBuffer(positionUs)) {} while (feedInputBuffer()) {} TraceUtil.endSection(); } catch (VpxDecoderException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } } else { skipToKeyframeBefore(positionUs); } decoderCounters.ensureUpdated(); }
private native long vpxSecureDecode(long context, ByteBuffer encoded, int length, ExoMediaCrypto wvCrypto, int inputMode, byte[] key, byte[] iv, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData);
/** * Creates an Opus decoder. * * @param numInputBuffers The number of input buffers. * @param numOutputBuffers The number of output buffers. * @param initialInputBufferSize The initial size of each input buffer. * @param initializationData Codec-specific initialization data. The first element must contain an * opus header. Optionally, the list may contain two additional buffers, which must contain * the encoder delay and seek pre roll values in nanoseconds, encoded as longs. * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * content. Maybe null and can be ignored if decoder does not handle encrypted content. * @throws OpusDecoderException Thrown if an exception occurs when initializing the decoder. */ public OpusDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, List<byte[]> initializationData, ExoMediaCrypto exoMediaCrypto) throws OpusDecoderException { super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]); if (!OpusLibrary.isAvailable()) { throw new OpusDecoderException("Failed to load decoder native libraries."); } this.exoMediaCrypto = exoMediaCrypto; if (exoMediaCrypto != null && !OpusLibrary.opusIsSecureDecodeSupported()) { throw new OpusDecoderException("Opus decoder does not support secure decode."); } byte[] headerBytes = initializationData.get(0); if (headerBytes.length < 19) { throw new OpusDecoderException("Header size is too small."); } channelCount = headerBytes[9] & 0xFF; if (channelCount > 8) { throw new OpusDecoderException("Invalid channel count: " + channelCount); } int preskip = readLittleEndian16(headerBytes, 10); int gain = readLittleEndian16(headerBytes, 16); byte[] streamMap = new byte[8]; int numStreams; int numCoupled; if (headerBytes[18] == 0) { // Channel mapping // If there is no channel mapping, use the defaults. if (channelCount > 2) { // Maximum channel count with default layout. throw new OpusDecoderException("Invalid Header, missing stream map."); } numStreams = 1; numCoupled = (channelCount == 2) ? 1 : 0; streamMap[0] = 0; streamMap[1] = 1; } else { if (headerBytes.length < 21 + channelCount) { throw new OpusDecoderException("Header size is too small."); } // Read the channel mapping. numStreams = headerBytes[19] & 0xFF; numCoupled = headerBytes[20] & 0xFF; System.arraycopy(headerBytes, 21, streamMap, 0, channelCount); } if (initializationData.size() == 3) { if (initializationData.get(1).length != 8 || initializationData.get(2).length != 8) { throw new OpusDecoderException("Invalid Codec Delay or Seek Preroll"); } long codecDelayNs = ByteBuffer.wrap(initializationData.get(1)).order(ByteOrder.nativeOrder()).getLong(); long seekPreRollNs = ByteBuffer.wrap(initializationData.get(2)).order(ByteOrder.nativeOrder()).getLong(); headerSkipSamples = nsToSamples(codecDelayNs); headerSeekPreRollSamples = nsToSamples(seekPreRollNs); } else { headerSkipSamples = preskip; headerSeekPreRollSamples = DEFAULT_SEEK_PRE_ROLL_SAMPLES; } nativeDecoderContext = opusInit(SAMPLE_RATE, channelCount, numStreams, numCoupled, gain, streamMap); if (nativeDecoderContext == 0) { throw new OpusDecoderException("Failed to initialize decoder"); } setInitialInputBufferSize(initialInputBufferSize); }
private native int opusSecureDecode(long decoder, long timeUs, ByteBuffer inputBuffer, int inputSize, SimpleOutputBuffer outputBuffer, int sampleRate, ExoMediaCrypto wvCrypto, int inputMode, byte[] key, byte[] iv, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData);
@Override protected OpusDecoder createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws OpusDecoderException { return new OpusDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, format.initializationData, mediaCrypto); }
@Override protected FlacDecoder createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws FlacDecoderException { return new FlacDecoder(NUM_BUFFERS, NUM_BUFFERS, format.initializationData); }
private native long vpxSecureDecode(long context, ByteBuffer encoded, int length, ExoMediaCrypto mediaCrypto, int inputMode, byte[] key, byte[] iv, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData);
private native int opusSecureDecode(long decoder, long timeUs, ByteBuffer inputBuffer, int inputSize, SimpleOutputBuffer outputBuffer, int sampleRate, ExoMediaCrypto mediaCrypto, int inputMode, byte[] key, byte[] iv, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData);
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param audioCapabilities The audio capabilities for playback on this device. May be null if the * default capabilities (no encoded audio passthrough support) should be assumed. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output. */ public SimpleDecoderAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, AudioProcessor... audioProcessors) { super(C.TRACK_TYPE_AUDIO); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; eventDispatcher = new EventDispatcher(eventHandler, eventListener); audioTrack = new AudioTrack(audioCapabilities, audioProcessors, new AudioTrackListener()); formatHolder = new FormatHolder(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); decoderReinitializationState = REINITIALIZATION_STATE_NONE; audioTrackNeedsConfigure = true; }
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param audioCapabilities The audio capabilities for playback on this device. May be null if the * default capabilities (no encoded audio passthrough support) should be assumed. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output. */ public SimpleDecoderAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, AudioProcessor... audioProcessors) { super(C.TRACK_TYPE_AUDIO); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; eventDispatcher = new EventDispatcher(eventHandler, eventListener); audioTrack = new AudioTrack(audioCapabilities, audioProcessors, new AudioTrackListener()); formatHolder = new FormatHolder(); flagsOnlyBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); decoderReinitializationState = REINITIALIZATION_STATE_NONE; audioTrackNeedsConfigure = true; }
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param audioCapabilities The audio capabilities for playback on this device. May be null if the * default capabilities (no encoded audio passthrough support) should be assumed. */ public LibopusAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(eventHandler, eventListener, audioCapabilities, drmSessionManager, playClearSamplesWithoutKeys); }
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output. */ public LibopusAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, AudioProcessor... audioProcessors) { super(eventHandler, eventListener, null, drmSessionManager, playClearSamplesWithoutKeys, audioProcessors); }
/** * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param audioCapabilities The audio capabilities for playback on this device. May be null if the * default capabilities (no encoded audio passthrough support) should be assumed. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output. */ public SimpleDecoderAudioRenderer(Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities, DrmSessionManager<ExoMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, AudioProcessor... audioProcessors) { this(eventHandler, eventListener, drmSessionManager, playClearSamplesWithoutKeys, new DefaultAudioSink(audioCapabilities, audioProcessors)); }
/** * Creates a decoder for the given format. * * @param format The format for which a decoder is required. * @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. * Maybe null and can be ignored if decoder does not handle encrypted content. * @return The decoder. * @throws AudioDecoderException If an error occurred creating a suitable decoder. */ protected abstract SimpleDecoder<DecoderInputBuffer, ? extends SimpleOutputBuffer, ? extends AudioDecoderException> createDecoder(Format format, ExoMediaCrypto mediaCrypto) throws AudioDecoderException;
/** * Returns the {@link #FORMAT_SUPPORT_MASK} component of the return value for * {@link #supportsFormat(Format)}. * * @param drmSessionManager The renderer's {@link DrmSessionManager}. * @param format The format. * @return The extent to which the renderer supports the format itself. */ protected abstract int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager, Format format);