Merge pull request #3634 from jinminghe/bugfix/format

Set KEY_OPERATING_RATE for MediaCodecVideoRenderer.
This commit is contained in:
ojw28 2018-07-20 16:12:04 +01:00 committed by GitHub
commit f4219b55e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 95 additions and 12 deletions

View File

@ -136,6 +136,11 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
onPositionReset(positionUs, false);
}
@Override
public final void setOperatingRate(float operatingRate) {
onOperatingRateChanged(operatingRate);
}
@Override
public final void stop() throws ExoPlaybackException {
Assertions.checkState(state == STATE_STARTED);
@ -216,6 +221,17 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
// Do nothing.
}
/**
* Called when the operating rate is changed.
* <p>
* The default implementation is a no-op.
*
* @param operatingRate The new operating rate.
*/
protected void onOperatingRateChanged(float operatingRate) {
// Do nothing.
}
/**
* Called when the renderer is started.
* <p>

View File

@ -277,6 +277,7 @@ import java.util.Collections;
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
eventHandler.obtainMessage(MSG_PLAYBACK_PARAMETERS_CHANGED, playbackParameters).sendToTarget();
updateTrackSelectionPlaybackSpeed(playbackParameters.speed);
updateRendererOperatingRate(playbackParameters.speed);
}
// Handler.Callback implementation.
@ -1099,6 +1100,14 @@ import java.util.Collections;
}
}
private void updateRendererOperatingRate(float operatingRate) {
for (Renderer renderer : renderers) {
if (renderer != null) {
renderer.setOperatingRate(operatingRate);
}
}
}
private boolean shouldTransitionToReadyState(boolean renderersReadyOrEnded) {
if (enabledRenderers.length == 0) {
// If there are no enabled renderers, determine whether we're ready based on the timeline.

View File

@ -192,6 +192,13 @@ public interface Renderer extends PlayerMessage.Target {
*/
void resetPosition(long positionUs) throws ExoPlaybackException;
/**
* Sets the operating rate of this renderer.
*
* @param operatingRate The renderer operating rate.
*/
void setOperatingRate(float operatingRate);
/**
* Incrementally renders the {@link SampleStream}.
* <p>

View File

@ -317,12 +317,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
MediaCrypto crypto) {
MediaCrypto crypto, float codecOperatingRate) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
passthroughEnabled = codecInfo.passthrough;
String codecMimeType = codecInfo.mimeType == null ? MimeTypes.AUDIO_RAW : codecInfo.mimeType;
MediaFormat mediaFormat = getMediaFormat(format, codecMimeType, codecMaxInputSize);
MediaFormat mediaFormat = getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
if (passthroughEnabled) {
// Store the input MIME type if we're using the passthrough codec.
@ -633,10 +633,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
* @param format The format of the media.
* @param codecMimeType The MIME type handled by the codec.
* @param codecMaxInputSize The maximum input size supported by the codec.
* @param codecOperatingRate
* @return The framework media format.
*/
@SuppressLint("InlinedApi")
protected MediaFormat getMediaFormat(Format format, String codecMimeType, int codecMaxInputSize) {
protected MediaFormat getMediaFormat(Format format, String codecMimeType, int codecMaxInputSize,
float codecOperatingRate) {
MediaFormat mediaFormat = new MediaFormat();
// Set format parameters that should always be set.
mediaFormat.setString(MediaFormat.KEY_MIME, codecMimeType);
@ -648,6 +650,10 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
// Set codec configuration values.
if (Util.SDK_INT >= 23) {
mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
if (format.sampleRate != Format.NO_VALUE) {
mediaFormat.setFloat(
MediaFormat.KEY_OPERATING_RATE, codecOperatingRate * format.sampleRate);
}
}
return mediaFormat;
}

View File

@ -274,6 +274,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private DrmSession<FrameworkMediaCrypto> drmSession;
private DrmSession<FrameworkMediaCrypto> pendingDrmSession;
private MediaCodec codec;
private float codecOperatingRate = 1.0f;
private @Nullable ArrayDeque<MediaCodecInfo> availableCodecInfos;
private @Nullable DecoderInitializationException preferredDecoderInitializationException;
private @Nullable MediaCodecInfo codecInfo;
@ -385,10 +386,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* @param codec The {@link MediaCodec} to configure.
* @param format The format for which the codec is being configured.
* @param crypto For drm protected playbacks, a {@link MediaCrypto} to use for decryption.
* @param codecOperatingRate The {@link MediaFormat#KEY_OPERATING_RATE} to use for configuration.
* @throws DecoderQueryException If an error occurs querying {@code codecInfo}.
*/
protected abstract void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
MediaCrypto crypto) throws DecoderQueryException;
protected abstract void configureCodec(MediaCodecInfo codecInfo,
MediaCodec codec, Format format,
MediaCrypto crypto,
float codecOperatingRate) throws DecoderQueryException;
protected final void maybeInitCodec() throws ExoPlaybackException {
if (codec != null || format == null) {
@ -479,6 +483,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
@Override
protected void onOperatingRateChanged(float operatingRate) {
codecOperatingRate = operatingRate;
if (format != null) {
updateCodecOperatingRate(codec, format, operatingRate);
}
}
@Override
protected void onDisabled() {
format = null;
@ -723,7 +735,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codec = MediaCodec.createByCodecName(name);
TraceUtil.endSection();
TraceUtil.beginSection("configureCodec");
configureCodec(codecInfo, codec, format, crypto);
configureCodec(codecInfo, codec, format, crypto, codecOperatingRate);
TraceUtil.endSection();
TraceUtil.beginSection("startCodec");
codec.start();
@ -1025,8 +1037,21 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
releaseCodec();
maybeInitCodec();
}
} else {
if (Util.SDK_INT >= 23) {
updateCodecOperatingRate(codec, format, codecOperatingRate);
}
}
}
/**
* Updates the {@link MediaCodec} operating rate.
* <p>
* The default implementation is a no-op.
*/
protected void updateCodecOperatingRate(MediaCodec codec, Format format, float codecOperatingRate) {
// Do nothing.
}
/**
* Called when the output format of the {@link MediaCodec} changes.

View File

@ -23,6 +23,7 @@ import android.media.MediaCodec;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.CallSuper;
@ -445,11 +446,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
MediaCrypto crypto) throws DecoderQueryException {
protected void configureCodec(MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
MediaCrypto crypto,
float codecOperatingRate) throws DecoderQueryException {
codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
MediaFormat mediaFormat = getMediaFormat(format, codecMaxValues, deviceNeedsAutoFrcWorkaround,
tunnelingAudioSessionId);
tunnelingAudioSessionId, codecOperatingRate);
if (surface == null) {
Assertions.checkState(shouldUseDummySurface(codecInfo));
if (dummySurface == null) {
@ -501,6 +505,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
buffersInCodecCount = 0;
}
@TargetApi(23)
@Override
protected void updateCodecOperatingRate(MediaCodec codec, Format format, float codecOperatingRate) {
if (format.frameRate == Format.NO_VALUE) {
return;
}
Bundle codecParameters = new Bundle();
codecParameters.putFloat(MediaFormat.KEY_OPERATING_RATE, format.frameRate * codecOperatingRate);
codec.setParameters(codecParameters);
}
@Override
protected void onCodecInitialized(String name, long initializedTimestampMs,
long initializationDurationMs) {
@ -940,6 +955,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* logic that negatively impacts ExoPlayer.
* @param tunnelingAudioSessionId The audio session id to use for tunneling, or {@link
* C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
* @param codecOperatingRate
* @return The framework {@link MediaFormat} that should be used to configure the decoder.
*/
@SuppressLint("InlinedApi")
@ -947,7 +963,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
Format format,
CodecMaxValues codecMaxValues,
boolean deviceNeedsAutoFrcWorkaround,
int tunnelingAudioSessionId) {
int tunnelingAudioSessionId,
float codecOperatingRate) {
MediaFormat mediaFormat = new MediaFormat();
// Set format parameters that should always be set.
mediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
@ -966,6 +983,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// Set codec configuration values.
if (Util.SDK_INT >= 23) {
mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
if (format.frameRate != Format.NO_VALUE) {
mediaFormat.setFloat(MediaFormat.KEY_OPERATING_RATE, codecOperatingRate * format.frameRate);
}
}
if (deviceNeedsAutoFrcWorkaround) {
mediaFormat.setInteger("auto-frc", 0);

View File

@ -82,14 +82,14 @@ public class DebugRenderersFactory extends DefaultRenderersFactory {
@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
MediaCrypto crypto) throws DecoderQueryException {
MediaCrypto crypto, float codecOperatingRate) throws DecoderQueryException {
// If the codec is being initialized whilst the renderer is started, default behavior is to
// render the first frame (i.e. the keyframe before the current position), then drop frames up
// to the current playback position. For test runs that place a maximum limit on the number of
// dropped frames allowed, this is not desired behavior. Hence we skip (rather than drop)
// frames up to the current playback position [Internal: b/66494991].
skipToPositionBeforeRenderingFirstFrame = getState() == Renderer.STATE_STARTED;
super.configureCodec(codecInfo, codec, format, crypto);
super.configureCodec(codecInfo, codec, format, crypto, codecOperatingRate);
}
@Override