Commit d9b3582b by Oliver Woodman

Use OMX.google.raw.decoder for passthrough playback.

The OMX component needs to be configured with a format that has a
MIME type of audio/raw. Remove Ac3PassthroughAudioTrackRenderer,
which is no longer used.
parent ed1dbddc
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
*/ */
package com.google.android.exoplayer.demo.player; 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.DefaultLoadControl;
import com.google.android.exoplayer.LoadControl; import com.google.android.exoplayer.LoadControl;
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer; import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
...@@ -61,6 +61,7 @@ import com.google.android.exoplayer.util.MimeTypes; ...@@ -61,6 +61,7 @@ import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.AudioFormat;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.UnsupportedSchemeException; import android.media.UnsupportedSchemeException;
import android.os.Handler; import android.os.Handler;
...@@ -298,13 +299,8 @@ public class DashRendererBuilder implements RendererBuilder, ...@@ -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. // TODO: There needs to be some logic to filter out non-AC3 tracks when selecting to use AC3.
boolean useAc3Passthrough = haveAc3Tracks && audioCapabilities != null boolean useAc3Passthrough = haveAc3Tracks && audioCapabilities != null
&& (audioCapabilities.supportsAc3() || audioCapabilities.supportsEAc3()); && (audioCapabilities.supportsAc3() || audioCapabilities.supportsEAc3());
if (useAc3Passthrough) { audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true,
audioRenderer = mainHandler, player, useAc3Passthrough ? C.ENCODING_AC3 : AudioFormat.ENCODING_DEFAULT);
new Ac3PassthroughAudioTrackRenderer(audioSampleSource, mainHandler, player);
} else {
audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true,
mainHandler, player);
}
} }
// Build the text chunk sources. // Build the text chunk sources.
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
package com.google.android.exoplayer.demo.player; package com.google.android.exoplayer.demo.player;
import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer;
import com.google.android.exoplayer.DummyTrackRenderer; import com.google.android.exoplayer.DummyTrackRenderer;
import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
...@@ -51,8 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -51,8 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener, public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener,
HlsSampleSource.EventListener, DefaultBandwidthMeter.EventListener, HlsSampleSource.EventListener, DefaultBandwidthMeter.EventListener,
MediaCodecVideoTrackRenderer.EventListener, MediaCodecAudioTrackRenderer.EventListener, MediaCodecVideoTrackRenderer.EventListener, MediaCodecAudioTrackRenderer.EventListener,
Ac3PassthroughAudioTrackRenderer.EventListener, StreamingDrmSessionManager.EventListener, StreamingDrmSessionManager.EventListener, TextRenderer {
TextRenderer {
/** /**
* Builds renderers for the player. * Builds renderers for the player.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer; package com.google.android.exoplayer;
import android.media.AudioFormat;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaExtractor; import android.media.MediaExtractor;
...@@ -50,6 +51,12 @@ public final class C { ...@@ -50,6 +51,12 @@ public final class C {
public static final int CRYPTO_MODE_AES_CTR = MediaCodec.CRYPTO_MODE_AES_CTR; 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 * @see MediaExtractor#SAMPLE_FLAG_SYNC
*/ */
@SuppressWarnings("InlinedApi") @SuppressWarnings("InlinedApi")
......
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
*/ */
package com.google.android.exoplayer; package com.google.android.exoplayer;
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer.audio.AudioTrack; import com.google.android.exoplayer.audio.AudioTrack;
import com.google.android.exoplayer.drm.DrmSessionManager; import com.google.android.exoplayer.drm.DrmSessionManager;
import com.google.android.exoplayer.util.MimeTypes; import com.google.android.exoplayer.util.MimeTypes;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.AudioFormat;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.media.audiofx.Virtualizer; import android.media.audiofx.Virtualizer;
...@@ -62,8 +64,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { ...@@ -62,8 +64,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
*/ */
public static final int MSG_SET_VOLUME = 1; 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 EventListener eventListener;
private final AudioTrack audioTrack; private final AudioTrack audioTrack;
private final int encoding;
private int audioSessionId; private int audioSessionId;
private long currentPositionUs; private long currentPositionUs;
...@@ -116,10 +124,56 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { ...@@ -116,10 +124,56 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
*/ */
public MediaCodecAudioTrackRenderer(SampleSource source, DrmSessionManager drmSessionManager, public MediaCodecAudioTrackRenderer(SampleSource source, DrmSessionManager drmSessionManager,
boolean playClearSamplesWithoutKeys, Handler eventHandler, EventListener eventListener) { 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); super(source, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, eventListener);
this.eventListener = eventListener; this.eventListener = eventListener;
this.audioSessionId = AudioTrack.SESSION_ID_NOT_SET; this.audioSessionId = AudioTrack.SESSION_ID_NOT_SET;
this.audioTrack = new AudioTrack(); 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 @Override
...@@ -140,7 +194,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer { ...@@ -140,7 +194,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
@Override @Override
protected void onOutputFormatChanged(MediaFormat format) { protected void onOutputFormatChanged(MediaFormat format) {
audioTrack.reconfigure(format); audioTrack.reconfigure(format, encoding, 0);
} }
/** /**
......
...@@ -289,12 +289,25 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -289,12 +289,25 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
} }
/** /**
* Configures a newly created {@link MediaCodec}. Sub-classes should * Returns a {@link DecoderInfo} for decoding media in the specified MIME type.
* override this method if they wish to configure the codec with a *
* non-null surface. * @param mimeType The type of media to decode.
**/ * @param requiresSecureDecoder Whether a secure decoder is needed for decoding {@code mimeType}.
protected void configureCodec(MediaCodec codec, android.media.MediaFormat x, MediaCrypto crypto) { * @return {@link DecoderInfo} for decoding media in the specified MIME type, or {@code null} if
codec.configure(x, null, crypto, 0); * 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") @SuppressWarnings("deprecation")
...@@ -329,7 +342,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -329,7 +342,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
DecoderInfo decoderInfo = null; DecoderInfo decoderInfo = null;
try { try {
decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder); decoderInfo = getDecoderInfo(mimeType, requiresSecureDecoder);
} catch (DecoderQueryException e) { } catch (DecoderQueryException e) {
notifyAndThrowDecoderInitError(new DecoderInitializationException(format, e, notifyAndThrowDecoderInitError(new DecoderInitializationException(format, e,
DecoderInitializationException.DECODER_QUERY_ERROR)); DecoderInitializationException.DECODER_QUERY_ERROR));
...@@ -345,7 +358,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -345,7 +358,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
try { try {
long codecInitializingTimestamp = SystemClock.elapsedRealtime(); long codecInitializingTimestamp = SystemClock.elapsedRealtime();
codec = MediaCodec.createByCodecName(decoderName); codec = MediaCodec.createByCodecName(decoderName);
configureCodec(codec, format.getFrameworkMediaFormatV16(), mediaCrypto); configureCodec(codec, decoderName, format.getFrameworkMediaFormatV16(), mediaCrypto);
codec.start(); codec.start();
long codecInitializedTimestamp = SystemClock.elapsedRealtime(); long codecInitializedTimestamp = SystemClock.elapsedRealtime();
notifyDecoderInitialized(decoderName, codecInitializedTimestamp, notifyDecoderInitialized(decoderName, codecInitializedTimestamp,
......
...@@ -358,8 +358,8 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { ...@@ -358,8 +358,8 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
// Override configureCodec to provide the surface. // Override configureCodec to provide the surface.
@Override @Override
protected void configureCodec(MediaCodec codec, android.media.MediaFormat format, protected void configureCodec(MediaCodec codec, String codecName,
MediaCrypto crypto) { android.media.MediaFormat format, MediaCrypto crypto) {
codec.configure(format, surface, crypto, 0); codec.configure(format, surface, crypto, 0);
codec.setVideoScalingMode(videoScalingMode); codec.setVideoScalingMode(videoScalingMode);
} }
......
...@@ -313,10 +313,10 @@ public final class AudioTrack { ...@@ -313,10 +313,10 @@ public final class AudioTrack {
/** /**
* Reconfigures the audio track to play back media in {@code format}. The encoding is assumed to * 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) { public void reconfigure(MediaFormat format) {
reconfigure(format, AudioFormat.ENCODING_PCM_16BIT, 0); reconfigure(format, AudioFormat.ENCODING_DEFAULT, 0);
} }
/** /**
......
...@@ -33,13 +33,15 @@ public class MimeTypes { ...@@ -33,13 +33,15 @@ public class MimeTypes {
public static final String AUDIO_MP4 = BASE_TYPE_AUDIO + "/mp4"; 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_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_WEBM = BASE_TYPE_AUDIO + "/webm";
public static final String AUDIO_MPEG = BASE_TYPE_AUDIO + "/mpeg"; 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_L1 = BASE_TYPE_AUDIO + "/mpeg-L1";
public static final String AUDIO_MPEG_L2 = BASE_TYPE_AUDIO + "/mpeg-L2"; 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_VORBIS = BASE_TYPE_AUDIO + "/vorbis";
public static final String AUDIO_OPUS = BASE_TYPE_AUDIO + "/opus"; public static final String AUDIO_OPUS = BASE_TYPE_AUDIO + "/opus";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment