Commit 5a3340d6 by Oliver Woodman

Add initial AC3 passthrough support.

parent 81bf68b1
...@@ -17,6 +17,8 @@ package com.google.android.exoplayer.demo.full; ...@@ -17,6 +17,8 @@ package com.google.android.exoplayer.demo.full;
import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.ExoPlayer;
import com.google.android.exoplayer.VideoSurfaceView; import com.google.android.exoplayer.VideoSurfaceView;
import com.google.android.exoplayer.audio.AudioCapabilities;
import com.google.android.exoplayer.audio.AudioCapabilitiesReceiver;
import com.google.android.exoplayer.demo.DemoUtil; import com.google.android.exoplayer.demo.DemoUtil;
import com.google.android.exoplayer.demo.R; import com.google.android.exoplayer.demo.R;
import com.google.android.exoplayer.demo.full.player.DashRendererBuilder; import com.google.android.exoplayer.demo.full.player.DashRendererBuilder;
...@@ -59,7 +61,7 @@ import android.widget.Toast; ...@@ -59,7 +61,7 @@ import android.widget.Toast;
* An activity that plays media using {@link DemoPlayer}. * An activity that plays media using {@link DemoPlayer}.
*/ */
public class FullPlayerActivity extends Activity implements SurfaceHolder.Callback, OnClickListener, public class FullPlayerActivity extends Activity implements SurfaceHolder.Callback, OnClickListener,
DemoPlayer.Listener, DemoPlayer.TextListener { DemoPlayer.Listener, DemoPlayer.TextListener, AudioCapabilitiesReceiver.Listener {
private static final float CAPTION_LINE_HEIGHT_RATIO = 0.0533f; private static final float CAPTION_LINE_HEIGHT_RATIO = 0.0533f;
private static final int MENU_GROUP_TRACKS = 1; private static final int MENU_GROUP_TRACKS = 1;
...@@ -89,6 +91,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -89,6 +91,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
private int contentType; private int contentType;
private String contentId; private String contentId;
private AudioCapabilitiesReceiver audioCapabilitiesReceiver;
private AudioCapabilities audioCapabilities;
// Activity lifecycle // Activity lifecycle
@Override @Override
...@@ -112,6 +117,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -112,6 +117,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
} }
}); });
audioCapabilitiesReceiver = new AudioCapabilitiesReceiver(getApplicationContext(), this);
shutterView = findViewById(R.id.shutter); shutterView = findViewById(R.id.shutter);
debugRootView = findViewById(R.id.controls_root); debugRootView = findViewById(R.id.controls_root);
...@@ -137,7 +144,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -137,7 +144,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
configureSubtitleView(); configureSubtitleView();
preparePlayer();
// The player will be prepared on receiving audio capabilities.
audioCapabilitiesReceiver.register();
} }
@Override @Override
...@@ -148,6 +157,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -148,6 +157,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
} else { } else {
player.blockingClearSurface(); player.blockingClearSurface();
} }
audioCapabilitiesReceiver.unregister();
} }
@Override @Override
...@@ -166,6 +177,17 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -166,6 +177,17 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
} }
} }
// AudioCapabilitiesReceiver.Listener methods
@Override
public void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities) {
this.audioCapabilities = audioCapabilities;
releasePlayer();
autoPlay = true;
preparePlayer();
}
// Internal methods // Internal methods
private RendererBuilder getRendererBuilder() { private RendererBuilder getRendererBuilder() {
...@@ -176,7 +198,7 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba ...@@ -176,7 +198,7 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
new SmoothStreamingTestMediaDrmCallback(), debugTextView); new SmoothStreamingTestMediaDrmCallback(), debugTextView);
case DemoUtil.TYPE_DASH: case DemoUtil.TYPE_DASH:
return new DashRendererBuilder(userAgent, contentUri.toString(), contentId, return new DashRendererBuilder(userAgent, contentUri.toString(), contentId,
new WidevineTestMediaDrmCallback(contentId), debugTextView); new WidevineTestMediaDrmCallback(contentId), debugTextView, audioCapabilities);
default: default:
return new DefaultRendererBuilder(this, contentUri, debugTextView); return new DefaultRendererBuilder(this, contentUri, debugTextView);
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer.demo.full.player; package com.google.android.exoplayer.demo.full.player;
import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer;
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;
...@@ -22,6 +23,7 @@ import com.google.android.exoplayer.MediaCodecUtil; ...@@ -22,6 +23,7 @@ import com.google.android.exoplayer.MediaCodecUtil;
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer; import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.audio.AudioCapabilities;
import com.google.android.exoplayer.chunk.ChunkSampleSource; import com.google.android.exoplayer.chunk.ChunkSampleSource;
import com.google.android.exoplayer.chunk.ChunkSource; import com.google.android.exoplayer.chunk.ChunkSource;
import com.google.android.exoplayer.chunk.Format; import com.google.android.exoplayer.chunk.Format;
...@@ -84,18 +86,20 @@ public class DashRendererBuilder implements RendererBuilder, ...@@ -84,18 +86,20 @@ public class DashRendererBuilder implements RendererBuilder,
private final String contentId; private final String contentId;
private final MediaDrmCallback drmCallback; private final MediaDrmCallback drmCallback;
private final TextView debugTextView; private final TextView debugTextView;
private final AudioCapabilities audioCapabilities;
private DemoPlayer player; private DemoPlayer player;
private RendererBuilderCallback callback; private RendererBuilderCallback callback;
private ManifestFetcher<MediaPresentationDescription> manifestFetcher; private ManifestFetcher<MediaPresentationDescription> manifestFetcher;
public DashRendererBuilder(String userAgent, String url, String contentId, public DashRendererBuilder(String userAgent, String url, String contentId,
MediaDrmCallback drmCallback, TextView debugTextView) { MediaDrmCallback drmCallback, TextView debugTextView, AudioCapabilities audioCapabilities) {
this.userAgent = userAgent; this.userAgent = userAgent;
this.url = url; this.url = url;
this.contentId = contentId; this.contentId = contentId;
this.drmCallback = drmCallback; this.drmCallback = drmCallback;
this.debugTextView = debugTextView; this.debugTextView = debugTextView;
this.audioCapabilities = audioCapabilities;
} }
@Override @Override
...@@ -208,6 +212,7 @@ public class DashRendererBuilder implements RendererBuilder, ...@@ -208,6 +212,7 @@ public class DashRendererBuilder implements RendererBuilder,
} }
// Build the audio chunk sources. // Build the audio chunk sources.
boolean haveAc3Tracks = false;
List<ChunkSource> audioChunkSourceList = new ArrayList<ChunkSource>(); List<ChunkSource> audioChunkSourceList = new ArrayList<ChunkSource>();
List<String> audioTrackNameList = new ArrayList<String>(); List<String> audioTrackNameList = new ArrayList<String>();
if (audioAdaptationSet != null) { if (audioAdaptationSet != null) {
...@@ -220,6 +225,19 @@ public class DashRendererBuilder implements RendererBuilder, ...@@ -220,6 +225,19 @@ public class DashRendererBuilder implements RendererBuilder,
format.audioSamplingRate + "Hz)"); format.audioSamplingRate + "Hz)");
audioChunkSourceList.add(new DashChunkSource(manifestFetcher, audioAdaptationSetIndex, audioChunkSourceList.add(new DashChunkSource(manifestFetcher, audioAdaptationSetIndex,
new int[] {i}, audioDataSource, audioEvaluator, LIVE_EDGE_LATENCY_MS)); new int[] {i}, audioDataSource, audioEvaluator, LIVE_EDGE_LATENCY_MS));
haveAc3Tracks |= format.mimeType.equals(MimeTypes.AUDIO_AC3)
|| format.mimeType.equals(MimeTypes.AUDIO_EC3);
}
// Filter out non-AC-3 tracks if there is an AC-3 track, to avoid having to switch renderers.
if (haveAc3Tracks) {
for (int i = audioRepresentations.size() - 1; i >= 0; i--) {
Format format = audioRepresentations.get(i).format;
if (!format.mimeType.equals(MimeTypes.AUDIO_AC3)
&& !format.mimeType.equals(MimeTypes.AUDIO_EC3)) {
audioTrackNameList.remove(i);
audioChunkSourceList.remove(i);
}
}
} }
} }
...@@ -238,8 +256,16 @@ public class DashRendererBuilder implements RendererBuilder, ...@@ -238,8 +256,16 @@ public class DashRendererBuilder implements RendererBuilder,
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl, SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, mainHandler, player, AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, mainHandler, player,
DemoPlayer.TYPE_AUDIO); DemoPlayer.TYPE_AUDIO);
audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true, // TODO: There needs to be some logic to filter out non-AC3 tracks when selecting to use AC3.
mainHandler, player); 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);
}
} }
// Build the text chunk sources. // Build the text chunk sources.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer.demo.full.player; package com.google.android.exoplayer.demo.full.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;
...@@ -45,8 +46,8 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -45,8 +46,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/ */
public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener, public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener,
DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener, DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener,
MediaCodecAudioTrackRenderer.EventListener, TextTrackRenderer.TextRenderer, MediaCodecAudioTrackRenderer.EventListener, Ac3PassthroughAudioTrackRenderer.EventListener,
StreamingDrmSessionManager.EventListener { TextTrackRenderer.TextRenderer, StreamingDrmSessionManager.EventListener {
/** /**
* Builds renderers for the player. * Builds renderers for the player.
......
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