diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java index c01929bc13..746a3138f0 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/DashRendererBuilder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer.demo.player; -import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer; +import com.google.android.exoplayer.C; import com.google.android.exoplayer.DefaultLoadControl; import com.google.android.exoplayer.LoadControl; import com.google.android.exoplayer.MediaCodecAudioTrackRenderer; @@ -61,6 +61,7 @@ import com.google.android.exoplayer.util.MimeTypes; import com.google.android.exoplayer.util.Util; import android.annotation.TargetApi; +import android.media.AudioFormat; import android.media.MediaCodec; import android.media.UnsupportedSchemeException; import android.os.Handler; @@ -298,13 +299,8 @@ public class DashRendererBuilder implements RendererBuilder, // TODO: There needs to be some logic to filter out non-AC3 tracks when selecting to use AC3. boolean useAc3Passthrough = haveAc3Tracks && audioCapabilities != null && (audioCapabilities.supportsAc3() || audioCapabilities.supportsEAc3()); - if (useAc3Passthrough) { - audioRenderer = - new Ac3PassthroughAudioTrackRenderer(audioSampleSource, mainHandler, player); - } else { - audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true, - mainHandler, player); - } + audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true, + mainHandler, player, useAc3Passthrough ? C.ENCODING_AC3 : AudioFormat.ENCODING_DEFAULT); } // Build the text chunk sources. diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java index 0dc625344b..8136cdc979 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer.demo.player; -import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer; import com.google.android.exoplayer.DummyTrackRenderer; import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlayer; @@ -51,8 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener, HlsSampleSource.EventListener, DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener, MediaCodecAudioTrackRenderer.EventListener, - Ac3PassthroughAudioTrackRenderer.EventListener, StreamingDrmSessionManager.EventListener, - TextRenderer { + StreamingDrmSessionManager.EventListener, TextRenderer { /** * Builds renderers for the player. diff --git a/library/src/main/java/com/google/android/exoplayer/Ac3PassthroughAudioTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/Ac3PassthroughAudioTrackRenderer.java deleted file mode 100644 index 1c8c967963..0000000000 --- a/library/src/main/java/com/google/android/exoplayer/Ac3PassthroughAudioTrackRenderer.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer; - -import com.google.android.exoplayer.audio.AudioCapabilitiesReceiver; -import com.google.android.exoplayer.audio.AudioTrack; -import com.google.android.exoplayer.util.Assertions; -import com.google.android.exoplayer.util.MimeTypes; - -import android.annotation.TargetApi; -import android.media.AudioFormat; -import android.os.Handler; - -import java.io.IOException; - -/** - * Renders encoded AC-3/enhanced AC-3 data to an {@link AudioTrack} for decoding on the playback - * device. - * - *

To determine whether the playback device supports passthrough, receive an audio configuration - * using {@link AudioCapabilitiesReceiver} and check whether the audio capabilities include - * AC-3/enhanced AC-3 passthrough. - */ -@TargetApi(21) -public final class Ac3PassthroughAudioTrackRenderer extends TrackRenderer { - - /** - * Interface definition for a callback to be notified of {@link Ac3PassthroughAudioTrackRenderer} - * events. - */ - public interface EventListener { - - /** - * Invoked when an {@link AudioTrack} fails to initialize. - * - * @param e The corresponding exception. - */ - void onAudioTrackInitializationError(AudioTrack.InitializationException e); - - /** - * Invoked when an {@link AudioTrack} write fails. - * - * @param e The corresponding exception. - */ - void onAudioTrackWriteError(AudioTrack.WriteException e); - - } - - /** - * The type of a message that can be passed to an instance of this class via - * {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object - * should be a {@link Float} with 0 being silence and 1 being unity gain. - */ - public static final int MSG_SET_VOLUME = 1; - - private static final int SOURCE_STATE_NOT_READY = 0; - private static final int SOURCE_STATE_READY = 1; - - /** Default buffer size for AC-3 packets from the sample source */ - private static final int DEFAULT_BUFFER_SIZE = 16384 * 2; - - private final Handler eventHandler; - private final EventListener eventListener; - - private final SampleSource source; - private final SampleHolder sampleHolder; - private final MediaFormatHolder formatHolder; - - private int trackIndex; - private MediaFormat format; - - private int sourceState; - private boolean inputStreamEnded; - private boolean shouldReadInputBuffer; - - private long currentPositionUs; - - private AudioTrack audioTrack; - private int audioSessionId; - - /** - * Constructs a new track renderer that passes AC-3 samples directly to an audio track. - * - * @param source The upstream source from which the renderer obtains samples. - * @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. - */ - public Ac3PassthroughAudioTrackRenderer(SampleSource source, Handler eventHandler, - EventListener eventListener) { - this.source = Assertions.checkNotNull(source); - this.eventHandler = eventHandler; - this.eventListener = eventListener; - sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT); - sampleHolder.replaceBuffer(DEFAULT_BUFFER_SIZE); - formatHolder = new MediaFormatHolder(); - audioTrack = new AudioTrack(); - shouldReadInputBuffer = true; - } - - @Override - protected boolean isTimeSource() { - return true; - } - - @Override - protected int doPrepare() throws ExoPlaybackException { - try { - boolean sourcePrepared = source.prepare(); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - - for (int i = 0; i < source.getTrackCount(); i++) { - // TODO(andrewlewis): Choose best format here after checking playout formats from HDMI config. - if (handlesMimeType(source.getTrackInfo(i).mimeType)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - - return TrackRenderer.STATE_IGNORE; - } - - private static boolean handlesMimeType(String mimeType) { - return MimeTypes.AUDIO_MP4.equals(mimeType); - } - - @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); - sourceState = SOURCE_STATE_NOT_READY; - inputStreamEnded = false; - currentPositionUs = positionUs; - } - - @Override - protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { - try { - sourceState = source.continueBuffering(positionUs) - ? (sourceState == SOURCE_STATE_NOT_READY ? SOURCE_STATE_READY : sourceState) - : SOURCE_STATE_NOT_READY; - - if (format == null) { - readFormat(); - } else { - // Initialize and start the audio track now. - if (!audioTrack.isInitialized()) { - int oldAudioSessionId = audioSessionId; - try { - audioSessionId = audioTrack.initialize(oldAudioSessionId); - } catch (AudioTrack.InitializationException e) { - notifyAudioTrackInitializationError(e); - throw new ExoPlaybackException(e); - } - - if (getState() == TrackRenderer.STATE_STARTED) { - audioTrack.play(); - } - } - - feedInputBuffer(); - } - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - } - - private void readFormat() throws IOException { - int result = source.readData(trackIndex, currentPositionUs, formatHolder, sampleHolder, false); - if (result == SampleSource.FORMAT_READ) { - format = formatHolder.format; - // TODO: For E-AC-3 input, reconfigure with AudioFormat.ENCODING_E_AC3. - audioTrack.reconfigure(format.getFrameworkMediaFormatV16(), AudioFormat.ENCODING_AC3, 0); - } - } - - private void feedInputBuffer() throws IOException, ExoPlaybackException { - if (!audioTrack.isInitialized() || inputStreamEnded) { - return; - } - - // Get more data if we have run out. - if (shouldReadInputBuffer) { - sampleHolder.clearData(); - int result = - source.readData(trackIndex, currentPositionUs, formatHolder, sampleHolder, false); - if (result == SampleSource.FORMAT_READ) { - format = formatHolder.format; - audioTrack.reconfigure(format.getFrameworkMediaFormatV16(), AudioFormat.ENCODING_AC3, 0); - } - if (result == SampleSource.END_OF_STREAM) { - inputStreamEnded = true; - } - if (result != SampleSource.SAMPLE_READ) { - return; - } - shouldReadInputBuffer = false; - } - - int handleBufferResult; - try { - handleBufferResult = - audioTrack.handleBuffer(sampleHolder.data, 0, sampleHolder.size, sampleHolder.timeUs); - } catch (AudioTrack.WriteException e) { - notifyAudioTrackWriteError(e); - throw new ExoPlaybackException(e); - } - - // If we are out of sync, allow currentPositionUs to jump backwards. - if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) { - currentPositionUs = Long.MIN_VALUE; - } - - // Get another input buffer if this one was consumed. - shouldReadInputBuffer = (handleBufferResult & AudioTrack.RESULT_BUFFER_CONSUMED) != 0; - } - - @Override - protected void onStarted() { - audioTrack.play(); - } - - @Override - protected void onStopped() { - audioTrack.pause(); - } - - @Override - protected boolean isEnded() { - // We've exhausted the input stream, and the AudioTrack has either played all of the data - // submitted, or has been fed insufficient data to begin playback. - return inputStreamEnded && (!audioTrack.hasPendingData() - || !audioTrack.hasEnoughDataToBeginPlayback()); - } - - @Override - protected boolean isReady() { - return audioTrack.hasPendingData() || (format != null && sourceState != SOURCE_STATE_NOT_READY); - } - - @Override - protected long getCurrentPositionUs() { - long audioTrackCurrentPositionUs = audioTrack.getCurrentPositionUs(isEnded()); - if (audioTrackCurrentPositionUs != AudioTrack.CURRENT_POSITION_NOT_SET) { - // Make sure we don't ever report time moving backwards. - currentPositionUs = Math.max(currentPositionUs, audioTrackCurrentPositionUs); - } - return currentPositionUs; - } - - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; - } - - @Override - protected long getBufferedPositionUs() { - long sourceBufferedPosition = source.getBufferedPositionUs(); - return sourceBufferedPosition == UNKNOWN_TIME_US || sourceBufferedPosition == END_OF_TRACK_US - ? sourceBufferedPosition : Math.max(sourceBufferedPosition, getCurrentPositionUs()); - } - - @Override - protected void onDisabled() { - audioSessionId = AudioTrack.SESSION_ID_NOT_SET; - shouldReadInputBuffer = true; - audioTrack.release(); - } - - @Override - protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); - sourceState = SOURCE_STATE_NOT_READY; - inputStreamEnded = false; - shouldReadInputBuffer = true; - - // TODO: Try and re-use the same AudioTrack instance once [Internal: b/7941810] is fixed. - audioTrack.reset(); - currentPositionUs = Long.MIN_VALUE; - } - - @Override - public void handleMessage(int messageType, Object message) throws ExoPlaybackException { - if (messageType == MSG_SET_VOLUME) { - audioTrack.setVolume((Float) message); - } else { - super.handleMessage(messageType, message); - } - } - - private void notifyAudioTrackInitializationError(final AudioTrack.InitializationException e) { - if (eventHandler != null && eventListener != null) { - eventHandler.post(new Runnable() { - @Override - public void run() { - eventListener.onAudioTrackInitializationError(e); - } - }); - } - } - - private void notifyAudioTrackWriteError(final AudioTrack.WriteException e) { - if (eventHandler != null && eventListener != null) { - eventHandler.post(new Runnable() { - @Override - public void run() { - eventListener.onAudioTrackWriteError(e); - } - }); - } - } - -} diff --git a/library/src/main/java/com/google/android/exoplayer/C.java b/library/src/main/java/com/google/android/exoplayer/C.java index 0c43fd50d0..9b75afdbbb 100644 --- a/library/src/main/java/com/google/android/exoplayer/C.java +++ b/library/src/main/java/com/google/android/exoplayer/C.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer; +import android.media.AudioFormat; import android.media.MediaCodec; import android.media.MediaExtractor; @@ -49,6 +50,12 @@ public final class C { @SuppressWarnings("InlinedApi") public static final int CRYPTO_MODE_AES_CTR = MediaCodec.CRYPTO_MODE_AES_CTR; + /** + * @see AudioFormat#ENCODING_AC3 + */ + @SuppressWarnings("InlinedApi") + public static final int ENCODING_AC3 = AudioFormat.ENCODING_AC3; + /** * @see MediaExtractor#SAMPLE_FLAG_SYNC */ diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java index 34b76d1a76..f23510f1dc 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java @@ -15,11 +15,13 @@ */ package com.google.android.exoplayer; +import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer.audio.AudioTrack; import com.google.android.exoplayer.drm.DrmSessionManager; import com.google.android.exoplayer.util.MimeTypes; import android.annotation.TargetApi; +import android.media.AudioFormat; import android.media.MediaCodec; import android.media.MediaFormat; import android.media.audiofx.Virtualizer; @@ -62,8 +64,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { */ public static final int MSG_SET_VOLUME = 1; + /** + * The name for the raw (passthrough) decoder OMX component. + */ + private static final String RAW_DECODER_NAME = "OMX.google.raw.decoder"; + private final EventListener eventListener; private final AudioTrack audioTrack; + private final int encoding; private int audioSessionId; private long currentPositionUs; @@ -116,10 +124,56 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { */ public MediaCodecAudioTrackRenderer(SampleSource source, DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, EventListener eventListener) { + this(source, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, eventListener, + AudioFormat.ENCODING_DEFAULT); + } + + /** + * @param source The upstream source from which the renderer obtains samples. + * @param drmSessionManager For use with encrypted content. May be null if support for encrypted + * content 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 acquisision. 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 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 encoding One of the {@code AudioFormat.ENCODING_*} constants specifying the audio + * encoding. + */ + public MediaCodecAudioTrackRenderer(SampleSource source, DrmSessionManager drmSessionManager, + boolean playClearSamplesWithoutKeys, Handler eventHandler, EventListener eventListener, + int encoding) { super(source, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, eventListener); this.eventListener = eventListener; this.audioSessionId = AudioTrack.SESSION_ID_NOT_SET; this.audioTrack = new AudioTrack(); + this.encoding = encoding; + } + + @Override + protected DecoderInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder) + throws DecoderQueryException { + if (encoding == AudioFormat.ENCODING_AC3 || encoding == AudioFormat.ENCODING_E_AC3) { + return new DecoderInfo(RAW_DECODER_NAME, true); + } + return super.getDecoderInfo(mimeType, requiresSecureDecoder); + } + + @Override + protected void configureCodec(MediaCodec codec, String codecName, MediaFormat format, + android.media.MediaCrypto crypto) { + if (RAW_DECODER_NAME.equals(codecName)) { + // Override the MIME type used to configure the codec if we are using a passthrough decoder. + String mimeType = format.getString(MediaFormat.KEY_MIME); + format.setString(android.media.MediaFormat.KEY_MIME, MimeTypes.AUDIO_RAW); + codec.configure(format, null, crypto, 0); + format.setString(android.media.MediaFormat.KEY_MIME, mimeType); + } else { + codec.configure(format, null, crypto, 0); + } } @Override @@ -140,7 +194,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { @Override protected void onOutputFormatChanged(MediaFormat format) { - audioTrack.reconfigure(format); + audioTrack.reconfigure(format, encoding, 0); } /** diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java index c7f3406582..854aa2c929 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java @@ -289,12 +289,25 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } /** - * Configures a newly created {@link MediaCodec}. Sub-classes should - * override this method if they wish to configure the codec with a - * non-null surface. - **/ - protected void configureCodec(MediaCodec codec, android.media.MediaFormat x, MediaCrypto crypto) { - codec.configure(x, null, crypto, 0); + * Returns a {@link DecoderInfo} for decoding media in the specified MIME type. + * + * @param mimeType The type of media to decode. + * @param requiresSecureDecoder Whether a secure decoder is needed for decoding {@code mimeType}. + * @return {@link DecoderInfo} for decoding media in the specified MIME type, or {@code null} if + * no suitable decoder is available. + */ + protected DecoderInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder) + throws DecoderQueryException { + return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder); + } + + /** + * Configures a newly created {@link MediaCodec}. Sub-classes should override this method if they + * wish to configure the codec with a non-null surface. + */ + protected void configureCodec(MediaCodec codec, String codecName, + android.media.MediaFormat format, MediaCrypto crypto) { + codec.configure(format, null, crypto, 0); } @SuppressWarnings("deprecation") @@ -329,7 +342,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { DecoderInfo decoderInfo = null; try { - decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder); + decoderInfo = getDecoderInfo(mimeType, requiresSecureDecoder); } catch (DecoderQueryException e) { notifyAndThrowDecoderInitError(new DecoderInitializationException(format, e, DecoderInitializationException.DECODER_QUERY_ERROR)); @@ -345,7 +358,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { try { long codecInitializingTimestamp = SystemClock.elapsedRealtime(); codec = MediaCodec.createByCodecName(decoderName); - configureCodec(codec, format.getFrameworkMediaFormatV16(), mediaCrypto); + configureCodec(codec, decoderName, format.getFrameworkMediaFormatV16(), mediaCrypto); codec.start(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); notifyDecoderInitialized(decoderName, codecInitializedTimestamp, diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java index fbf3e1500c..b843901543 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java @@ -358,8 +358,8 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { // Override configureCodec to provide the surface. @Override - protected void configureCodec(MediaCodec codec, android.media.MediaFormat format, - MediaCrypto crypto) { + protected void configureCodec(MediaCodec codec, String codecName, + android.media.MediaFormat format, MediaCrypto crypto) { codec.configure(format, surface, crypto, 0); codec.setVideoScalingMode(videoScalingMode); } diff --git a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java index c589b813d3..39e3ff8d23 100644 --- a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java +++ b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java @@ -313,10 +313,10 @@ public final class AudioTrack { /** * Reconfigures the audio track to play back media in {@code format}. The encoding is assumed to - * be {@link AudioFormat#ENCODING_PCM_16BIT}. + * be {@link AudioFormat#ENCODING_DEFAULT}. */ public void reconfigure(MediaFormat format) { - reconfigure(format, AudioFormat.ENCODING_PCM_16BIT, 0); + reconfigure(format, AudioFormat.ENCODING_DEFAULT, 0); } /** diff --git a/library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java b/library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java index 9dcc1638ee..43473b7af2 100644 --- a/library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java +++ b/library/src/main/java/com/google/android/exoplayer/util/MimeTypes.java @@ -33,13 +33,15 @@ public class MimeTypes { public static final String AUDIO_MP4 = BASE_TYPE_AUDIO + "/mp4"; public static final String AUDIO_AAC = BASE_TYPE_AUDIO + "/mp4a-latm"; - public static final String AUDIO_AC3 = BASE_TYPE_AUDIO + "/ac3"; - public static final String AUDIO_EC3 = BASE_TYPE_AUDIO + "/eac3"; public static final String AUDIO_WEBM = BASE_TYPE_AUDIO + "/webm"; public static final String AUDIO_MPEG = BASE_TYPE_AUDIO + "/mpeg"; public static final String AUDIO_MPEG_L1 = BASE_TYPE_AUDIO + "/mpeg-L1"; public static final String AUDIO_MPEG_L2 = BASE_TYPE_AUDIO + "/mpeg-L2"; + public static final String AUDIO_RAW = BASE_TYPE_AUDIO + "/raw"; + public static final String AUDIO_AC3 = BASE_TYPE_AUDIO + "/ac3"; + public static final String AUDIO_EC3 = BASE_TYPE_AUDIO + "/eac3"; + public static final String AUDIO_VORBIS = BASE_TYPE_AUDIO + "/vorbis"; public static final String AUDIO_OPUS = BASE_TYPE_AUDIO + "/opus";