Remove data capturing logic from ShadowMediaCodecConfig
We're now using CapturingRenderersFactory everywhere PiperOrigin-RevId: 348018988
This commit is contained in:
parent
0d1dac93c4
commit
466826e673
@ -22,10 +22,8 @@ import com.google.android.exoplayer2.metadata.Metadata;
|
|||||||
import com.google.android.exoplayer2.testutil.CapturingRenderersFactory;
|
import com.google.android.exoplayer2.testutil.CapturingRenderersFactory;
|
||||||
import com.google.android.exoplayer2.testutil.Dumper;
|
import com.google.android.exoplayer2.testutil.Dumper;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -39,17 +37,13 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class PlaybackOutput implements Dumper.Dumpable {
|
public final class PlaybackOutput implements Dumper.Dumpable {
|
||||||
|
|
||||||
@Nullable private final ShadowMediaCodecConfig codecConfig;
|
private final CapturingRenderersFactory capturingRenderersFactory;
|
||||||
@Nullable private final CapturingRenderersFactory capturingRenderersFactory;
|
|
||||||
|
|
||||||
private final List<Metadata> metadatas;
|
private final List<Metadata> metadatas;
|
||||||
private final List<List<Cue>> subtitles;
|
private final List<List<Cue>> subtitles;
|
||||||
|
|
||||||
private PlaybackOutput(
|
private PlaybackOutput(
|
||||||
SimpleExoPlayer player,
|
SimpleExoPlayer player, CapturingRenderersFactory capturingRenderersFactory) {
|
||||||
@Nullable ShadowMediaCodecConfig codecConfig,
|
|
||||||
@Nullable CapturingRenderersFactory capturingRenderersFactory) {
|
|
||||||
this.codecConfig = codecConfig;
|
|
||||||
this.capturingRenderersFactory = capturingRenderersFactory;
|
this.capturingRenderersFactory = capturingRenderersFactory;
|
||||||
|
|
||||||
metadatas = Collections.synchronizedList(new ArrayList<>());
|
metadatas = Collections.synchronizedList(new ArrayList<>());
|
||||||
@ -75,27 +69,12 @@ public final class PlaybackOutput implements Dumper.Dumpable {
|
|||||||
*/
|
*/
|
||||||
public static PlaybackOutput register(
|
public static PlaybackOutput register(
|
||||||
SimpleExoPlayer player, CapturingRenderersFactory capturingRenderersFactory) {
|
SimpleExoPlayer player, CapturingRenderersFactory capturingRenderersFactory) {
|
||||||
return new PlaybackOutput(player, /* codecConfig= */ null, capturingRenderersFactory);
|
return new PlaybackOutput(player, capturingRenderersFactory);
|
||||||
}
|
|
||||||
|
|
||||||
/** @deprecated Use {@link #register(SimpleExoPlayer, CapturingRenderersFactory)}. */
|
|
||||||
@Deprecated
|
|
||||||
public static PlaybackOutput register(
|
|
||||||
SimpleExoPlayer player, ShadowMediaCodecConfig mediaCodecConfig) {
|
|
||||||
return new PlaybackOutput(player, mediaCodecConfig, /* capturingRenderersFactory= */ null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(Dumper dumper) {
|
public void dump(Dumper dumper) {
|
||||||
if (codecConfig != null) {
|
capturingRenderersFactory.dump(dumper);
|
||||||
ImmutableMap<String, TeeCodec> codecs = codecConfig.getCodecs();
|
|
||||||
ImmutableList<String> mimeTypes = ImmutableList.sortedCopyOf(codecs.keySet());
|
|
||||||
for (String mimeType : mimeTypes) {
|
|
||||||
dumper.add(Assertions.checkNotNull(codecs.get(mimeType)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Assertions.checkNotNull(capturingRenderersFactory).dump(dumper);
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpMetadata(dumper);
|
dumpMetadata(dumper);
|
||||||
dumpSubtitles(dumper);
|
dumpSubtitles(dumper);
|
||||||
|
@ -15,17 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.robolectric;
|
package com.google.android.exoplayer2.robolectric;
|
||||||
|
|
||||||
import android.media.MediaCodec;
|
|
||||||
import android.media.MediaCodecInfo;
|
import android.media.MediaCodecInfo;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import com.google.android.exoplayer2.testutil.CapturingRenderersFactory;
|
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import java.util.HashMap;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import org.junit.rules.ExternalResource;
|
import org.junit.rules.ExternalResource;
|
||||||
import org.robolectric.shadows.MediaCodecInfoBuilder;
|
import org.robolectric.shadows.MediaCodecInfoBuilder;
|
||||||
import org.robolectric.shadows.ShadowMediaCodec;
|
import org.robolectric.shadows.ShadowMediaCodec;
|
||||||
@ -35,30 +31,14 @@ import org.robolectric.shadows.ShadowMediaCodecList;
|
|||||||
* A JUnit @Rule to configure Roboelectric's {@link ShadowMediaCodec}.
|
* A JUnit @Rule to configure Roboelectric's {@link ShadowMediaCodec}.
|
||||||
*
|
*
|
||||||
* <p>Registers a {@link org.robolectric.shadows.ShadowMediaCodec.CodecConfig} for each audio/video
|
* <p>Registers a {@link org.robolectric.shadows.ShadowMediaCodec.CodecConfig} for each audio/video
|
||||||
* MIME type known by ExoPlayer, and provides access to the bytes passed to these via {@link
|
* MIME type known by ExoPlayer.
|
||||||
* TeeCodec}.
|
|
||||||
*/
|
*/
|
||||||
public final class ShadowMediaCodecConfig extends ExternalResource {
|
public final class ShadowMediaCodecConfig extends ExternalResource {
|
||||||
|
|
||||||
private final Map<String, TeeCodec> codecsByMimeType;
|
|
||||||
|
|
||||||
private ShadowMediaCodecConfig() {
|
|
||||||
this.codecsByMimeType = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ShadowMediaCodecConfig forAllSupportedMimeTypes() {
|
public static ShadowMediaCodecConfig forAllSupportedMimeTypes() {
|
||||||
return new ShadowMediaCodecConfig();
|
return new ShadowMediaCodecConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link CapturingRenderersFactory} to access {@link MediaCodec} interactions
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public ImmutableMap<String, TeeCodec> getCodecs() {
|
|
||||||
return ImmutableMap.copyOf(codecsByMimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void before() throws Throwable {
|
protected void before() throws Throwable {
|
||||||
// Video codecs
|
// Video codecs
|
||||||
@ -101,7 +81,6 @@ public final class ShadowMediaCodecConfig extends ExternalResource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void after() {
|
protected void after() {
|
||||||
codecsByMimeType.clear();
|
|
||||||
ShadowMediaCodecList.reset();
|
ShadowMediaCodecList.reset();
|
||||||
ShadowMediaCodec.clearCodecs();
|
ShadowMediaCodec.clearCodecs();
|
||||||
}
|
}
|
||||||
@ -136,12 +115,11 @@ public final class ShadowMediaCodecConfig extends ExternalResource {
|
|||||||
.build());
|
.build());
|
||||||
// TODO: Update ShadowMediaCodec to consider the MediaFormat.KEY_MAX_INPUT_SIZE value passed
|
// TODO: Update ShadowMediaCodec to consider the MediaFormat.KEY_MAX_INPUT_SIZE value passed
|
||||||
// to configure() so we don't have to specify large buffers here.
|
// to configure() so we don't have to specify large buffers here.
|
||||||
TeeCodec codec = new TeeCodec(mimeType);
|
CodecImpl codec = new CodecImpl(mimeType);
|
||||||
ShadowMediaCodec.addDecoder(
|
ShadowMediaCodec.addDecoder(
|
||||||
codecName,
|
codecName,
|
||||||
new ShadowMediaCodec.CodecConfig(
|
new ShadowMediaCodec.CodecConfig(
|
||||||
/* inputBufferSize= */ 100_000, /* outputBufferSize= */ 100_000, codec));
|
/* inputBufferSize= */ 100_000, /* outputBufferSize= */ 100_000, codec));
|
||||||
codecsByMimeType.put(mimeType, codec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaCodecInfo.CodecProfileLevel createProfileLevel(int profile, int level) {
|
private static MediaCodecInfo.CodecProfileLevel createProfileLevel(int profile, int level) {
|
||||||
@ -150,4 +128,30 @@ public final class ShadowMediaCodecConfig extends ExternalResource {
|
|||||||
profileLevel.level = level;
|
profileLevel.level = level;
|
||||||
return profileLevel;
|
return profileLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ShadowMediaCodec.CodecConfig.Codec} that passes data through without modifying it.
|
||||||
|
*
|
||||||
|
* <p>Note: This currently drops all audio data - removing this restriction is tracked in
|
||||||
|
* [internal b/174737370].
|
||||||
|
*/
|
||||||
|
private static final class CodecImpl implements ShadowMediaCodec.CodecConfig.Codec {
|
||||||
|
|
||||||
|
private final String mimeType;
|
||||||
|
|
||||||
|
public CodecImpl(String mimeType) {
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(ByteBuffer in, ByteBuffer out) {
|
||||||
|
byte[] bytes = new byte[in.remaining()];
|
||||||
|
in.get(bytes);
|
||||||
|
|
||||||
|
// TODO(internal b/174737370): Output audio bytes as well.
|
||||||
|
if (!MimeTypes.isAudio(mimeType)) {
|
||||||
|
out.put(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 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.exoplayer2.robolectric;
|
|
||||||
|
|
||||||
import android.media.MediaCodec;
|
|
||||||
import com.google.android.exoplayer2.testutil.CapturingRenderersFactory;
|
|
||||||
import com.google.android.exoplayer2.testutil.Dumper;
|
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import org.robolectric.shadows.ShadowMediaCodec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link CapturingRenderersFactory} to access {@link MediaCodec} interactions
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public final class TeeCodec implements ShadowMediaCodec.CodecConfig.Codec, Dumper.Dumpable {
|
|
||||||
|
|
||||||
private final String mimeType;
|
|
||||||
private final List<byte[]> receivedBuffers;
|
|
||||||
|
|
||||||
public TeeCodec(String mimeType) {
|
|
||||||
this.mimeType = mimeType;
|
|
||||||
this.receivedBuffers = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(ByteBuffer in, ByteBuffer out) {
|
|
||||||
byte[] bytes = new byte[in.remaining()];
|
|
||||||
in.get(bytes);
|
|
||||||
receivedBuffers.add(bytes);
|
|
||||||
|
|
||||||
if (!MimeTypes.isAudio(mimeType)) {
|
|
||||||
// Don't output audio bytes, because ShadowAudioTrack doesn't advance the playback position so
|
|
||||||
// playback never completes.
|
|
||||||
// TODO: Update ShadowAudioTrack to advance the playback position in a realistic way.
|
|
||||||
out.put(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dump(Dumper dumper) {
|
|
||||||
if (receivedBuffers.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dumper.startBlock("MediaCodec (" + mimeType + ")");
|
|
||||||
dumper.add("buffers.length", receivedBuffers.size());
|
|
||||||
for (int i = 0; i < receivedBuffers.size(); i++) {
|
|
||||||
dumper.add("buffers[" + i + "]", receivedBuffers.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
dumper.endBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the buffers received by this codec.
|
|
||||||
*
|
|
||||||
* <p>The list is sorted in the order the buffers were passed to {@link #process(ByteBuffer,
|
|
||||||
* ByteBuffer)}.
|
|
||||||
*/
|
|
||||||
public ImmutableList<byte[]> getReceivedBuffers() {
|
|
||||||
return ImmutableList.copyOf(receivedBuffers);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user