Commit 5a3340d6 by Oliver Woodman

Add initial AC3 passthrough support.

parent 81bf68b1
......@@ -17,6 +17,8 @@ package com.google.android.exoplayer.demo.full;
import com.google.android.exoplayer.ExoPlayer;
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.R;
import com.google.android.exoplayer.demo.full.player.DashRendererBuilder;
......@@ -59,7 +61,7 @@ import android.widget.Toast;
* An activity that plays media using {@link DemoPlayer}.
*/
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 int MENU_GROUP_TRACKS = 1;
......@@ -89,6 +91,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
private int contentType;
private String contentId;
private AudioCapabilitiesReceiver audioCapabilitiesReceiver;
private AudioCapabilities audioCapabilities;
// Activity lifecycle
@Override
......@@ -112,6 +117,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
}
});
audioCapabilitiesReceiver = new AudioCapabilitiesReceiver(getApplicationContext(), this);
shutterView = findViewById(R.id.shutter);
debugRootView = findViewById(R.id.controls_root);
......@@ -137,7 +144,9 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
public void onResume() {
super.onResume();
configureSubtitleView();
preparePlayer();
// The player will be prepared on receiving audio capabilities.
audioCapabilitiesReceiver.register();
}
@Override
......@@ -148,6 +157,8 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
} else {
player.blockingClearSurface();
}
audioCapabilitiesReceiver.unregister();
}
@Override
......@@ -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
private RendererBuilder getRendererBuilder() {
......@@ -176,7 +198,7 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
new SmoothStreamingTestMediaDrmCallback(), debugTextView);
case DemoUtil.TYPE_DASH:
return new DashRendererBuilder(userAgent, contentUri.toString(), contentId,
new WidevineTestMediaDrmCallback(contentId), debugTextView);
new WidevineTestMediaDrmCallback(contentId), debugTextView, audioCapabilities);
default:
return new DefaultRendererBuilder(this, contentUri, debugTextView);
}
......
......@@ -15,6 +15,7 @@
*/
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.LoadControl;
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
......@@ -22,6 +23,7 @@ import com.google.android.exoplayer.MediaCodecUtil;
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
import com.google.android.exoplayer.SampleSource;
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.ChunkSource;
import com.google.android.exoplayer.chunk.Format;
......@@ -84,18 +86,20 @@ public class DashRendererBuilder implements RendererBuilder,
private final String contentId;
private final MediaDrmCallback drmCallback;
private final TextView debugTextView;
private final AudioCapabilities audioCapabilities;
private DemoPlayer player;
private RendererBuilderCallback callback;
private ManifestFetcher<MediaPresentationDescription> manifestFetcher;
public DashRendererBuilder(String userAgent, String url, String contentId,
MediaDrmCallback drmCallback, TextView debugTextView) {
MediaDrmCallback drmCallback, TextView debugTextView, AudioCapabilities audioCapabilities) {
this.userAgent = userAgent;
this.url = url;
this.contentId = contentId;
this.drmCallback = drmCallback;
this.debugTextView = debugTextView;
this.audioCapabilities = audioCapabilities;
}
@Override
......@@ -208,6 +212,7 @@ public class DashRendererBuilder implements RendererBuilder,
}
// Build the audio chunk sources.
boolean haveAc3Tracks = false;
List<ChunkSource> audioChunkSourceList = new ArrayList<ChunkSource>();
List<String> audioTrackNameList = new ArrayList<String>();
if (audioAdaptationSet != null) {
......@@ -220,6 +225,19 @@ public class DashRendererBuilder implements RendererBuilder,
format.audioSamplingRate + "Hz)");
audioChunkSourceList.add(new DashChunkSource(manifestFetcher, audioAdaptationSetIndex,
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,
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true, mainHandler, player,
DemoPlayer.TYPE_AUDIO);
audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, drmSessionManager, true,
mainHandler, player);
// 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);
}
}
// Build the text chunk sources.
......
......@@ -15,6 +15,7 @@
*/
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.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer;
......@@ -45,8 +46,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventListener,
DefaultBandwidthMeter.EventListener, MediaCodecVideoTrackRenderer.EventListener,
MediaCodecAudioTrackRenderer.EventListener, TextTrackRenderer.TextRenderer,
StreamingDrmSessionManager.EventListener {
MediaCodecAudioTrackRenderer.EventListener, Ac3PassthroughAudioTrackRenderer.EventListener,
TextTrackRenderer.TextRenderer, StreamingDrmSessionManager.EventListener {
/**
* 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