Set assumedVideoMinimumCodecOperatingRate for all playbacks

PiperOrigin-RevId: 405736227
This commit is contained in:
olly 2021-10-26 22:30:30 +01:00 committed by Andrew Lewis
parent 933e207b3e
commit aff15ae9ee
4 changed files with 112 additions and 19 deletions

View File

@ -208,7 +208,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
/* enableDecoderFallback= */ false,
eventHandler,
eventListener,
maxDroppedFramesToNotify);
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
}
/**
@ -241,12 +242,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
enableDecoderFallback,
eventHandler,
eventListener,
maxDroppedFramesToNotify);
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
}
/**
* Creates a new instance.
*
* @param context A context.
* @param codecAdapterFactory The {@link MediaCodecAdapter.Factory} used to create {@link
* MediaCodecAdapter} instances.
@ -271,12 +271,56 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) {
this(
context,
codecAdapterFactory,
mediaCodecSelector,
allowedJoiningTimeMs,
enableDecoderFallback,
eventHandler,
eventListener,
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
}
/**
* Creates a new instance.
*
* @param context A context.
* @param codecAdapterFactory The {@link MediaCodecAdapter.Factory} used to create {@link
* MediaCodecAdapter} instances.
* @param mediaCodecSelector A decoder selector.
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
* can attempt to seamlessly join an ongoing playback.
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
* initialization fails. This may result in using a decoder that is slower/less efficient than
* the primary decoder.
* @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 maxDroppedFramesToNotify The maximum number of frames that can be dropped between
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
* @param assumedMinimumCodecOperatingRate A codec operating rate that all codecs instantiated by
* this renderer are assumed to meet implicitly (i.e. without the operating rate being set
* explicitly using {@link MediaFormat#KEY_OPERATING_RATE}).
*/
public MediaCodecVideoRenderer(
Context context,
MediaCodecAdapter.Factory codecAdapterFactory,
MediaCodecSelector mediaCodecSelector,
long allowedJoiningTimeMs,
boolean enableDecoderFallback,
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify,
float assumedMinimumCodecOperatingRate) {
super(
C.TRACK_TYPE_VIDEO,
codecAdapterFactory,
mediaCodecSelector,
enableDecoderFallback,
/* assumedMinimumCodecOperatingRate= */ 30);
assumedMinimumCodecOperatingRate);
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.context = context.getApplicationContext();

View File

@ -1435,7 +1435,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
int esdsAtomPosition =
childAtomType == Atom.TYPE_esds
? childPosition
: findEsdsPosition(parent, childPosition, childAtomSize);
: findBoxPosition(parent, Atom.TYPE_esds, childPosition, childAtomSize);
if (esdsAtomPosition != C.POSITION_UNSET) {
Pair<@NullableType String, byte @NullableType []> mimeTypeAndInitializationData =
parseEsdsFromParent(parent, esdsAtomPosition);
@ -1537,18 +1537,28 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
/**
* Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds
* box is found
* Returns the position of the first box with the given {@code boxType} within {@code parent}, or
* {@link C#POSITION_UNSET} if no such box is found.
*
* @param parent The {@link ParsableByteArray} to search. The search will start from the {@link
* ParsableByteArray#getPosition() current position}.
* @param boxType The box type to search for.
* @param parentBoxPosition The position in {@code parent} of the box we are searching.
* @param parentBoxSize The size of the parent box we are searching in bytes.
* @return The position of the first box with the given {@code boxType} within {@code parent}, or
* {@link C#POSITION_UNSET} if no such box is found.
*/
private static int findEsdsPosition(ParsableByteArray parent, int position, int size)
private static int findBoxPosition(
ParsableByteArray parent, int boxType, int parentBoxPosition, int parentBoxSize)
throws ParserException {
int childAtomPosition = parent.getPosition();
while (childAtomPosition - position < size) {
ExtractorUtil.checkContainerInput(childAtomPosition >= parentBoxPosition, /* message= */ null);
while (childAtomPosition - parentBoxPosition < parentBoxSize) {
parent.setPosition(childAtomPosition);
int childAtomSize = parent.readInt();
ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childType = parent.readInt();
if (childType == Atom.TYPE_esds) {
if (childType == boxType) {
return childAtomPosition;
}
childAtomPosition += childAtomSize;

View File

@ -102,6 +102,7 @@ public final class TranscodingTransformer {
private boolean flattenForSlowMotion;
private String outputMimeType;
@Nullable private String audioMimeType;
@Nullable private String videoMimeType;
private TranscodingTransformer.Listener listener;
private Looper looper;
private Clock clock;
@ -125,6 +126,7 @@ public final class TranscodingTransformer {
this.flattenForSlowMotion = transcodingTransformer.transformation.flattenForSlowMotion;
this.outputMimeType = transcodingTransformer.transformation.outputMimeType;
this.audioMimeType = transcodingTransformer.transformation.audioMimeType;
this.videoMimeType = transcodingTransformer.transformation.videoMimeType;
this.listener = transcodingTransformer.listener;
this.looper = transcodingTransformer.looper;
this.clock = transcodingTransformer.clock;
@ -231,6 +233,33 @@ public final class TranscodingTransformer {
return this;
}
/**
* Sets the video MIME type of the output. The default value is to use the same MIME type as the
* input. Supported values are:
*
* <ul>
* <li>when the container MIME type is {@link MimeTypes#VIDEO_MP4}:
* <ul>
* <li>{@link MimeTypes#VIDEO_H263}
* <li>{@link MimeTypes#VIDEO_H264}
* <li>{@link MimeTypes#VIDEO_H265} from API level 24
* <li>{@link MimeTypes#VIDEO_MP4V}
* </ul>
* <li>when the container MIME type is {@link MimeTypes#VIDEO_WEBM}:
* <ul>
* <li>{@link MimeTypes#VIDEO_VP8}
* <li>{@link MimeTypes#VIDEO_VP9} from API level 24
* </ul>
* </ul>
*
* @param videoMimeType The MIME type of the video samples in the output.
* @return This builder.
*/
public Builder setVideoMimeType(String videoMimeType) {
this.videoMimeType = videoMimeType;
return this;
}
/**
* Sets the audio MIME type of the output. The default value is to use the same MIME type as the
* input. Supported values are:
@ -331,12 +360,10 @@ public final class TranscodingTransformer {
muxerFactory.supportsOutputMimeType(outputMimeType),
"Unsupported output MIME type: " + outputMimeType);
if (audioMimeType != null) {
checkState(
muxerFactory.supportsSampleMimeType(audioMimeType, outputMimeType),
"Unsupported sample MIME type "
+ audioMimeType
+ " for container MIME type "
+ outputMimeType);
checkSampleMimeType(audioMimeType);
}
if (videoMimeType != null) {
checkSampleMimeType(videoMimeType);
}
Transformation transformation =
new Transformation(
@ -345,10 +372,19 @@ public final class TranscodingTransformer {
flattenForSlowMotion,
outputMimeType,
audioMimeType,
/* videoMimeType= */ null);
videoMimeType);
return new TranscodingTransformer(
context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock);
}
private void checkSampleMimeType(String sampleMimeType) {
checkState(
muxerFactory.supportsSampleMimeType(sampleMimeType, outputMimeType),
"Unsupported sample MIME type "
+ sampleMimeType
+ " for container MIME type "
+ outputMimeType);
}
}
/** A listener for the transformation events. */

View File

@ -58,7 +58,10 @@ import androidx.media3.exoplayer.RendererCapabilities;
? sampleMimeType
: transformation.audioMimeType))
|| (MimeTypes.isVideo(sampleMimeType)
&& muxerWrapper.supportsSampleMimeType(sampleMimeType))) {
&& muxerWrapper.supportsSampleMimeType(
transformation.videoMimeType == null
? sampleMimeType
: transformation.videoMimeType))) {
return RendererCapabilities.create(C.FORMAT_HANDLED);
} else {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);