mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +00:00
Allow changing of video scaling mode
Issue #2016 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=139803888
This commit is contained in:
parent
4846146827
commit
9d7d8adc9c
5 changed files with 132 additions and 64 deletions
|
|
@ -222,6 +222,29 @@ public final class C {
|
|||
*/
|
||||
public static final int BUFFER_FLAG_DECODE_ONLY = 0x80000000;
|
||||
|
||||
/**
|
||||
* Video scaling modes for {@link MediaCodec}-based {@link Renderer}s.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {VIDEO_SCALING_MODE_SCALE_TO_FIT, VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING})
|
||||
public @interface VideoScalingMode {}
|
||||
/**
|
||||
* @see MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT =
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT;
|
||||
/**
|
||||
* @see MediaCodec#VIDEO_SCALING_MODE_SCALE_TO_FIT
|
||||
*/
|
||||
@SuppressWarnings("InlinedApi")
|
||||
public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING =
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING;
|
||||
/**
|
||||
* A default video scaling mode for {@link MediaCodec}-based {@link Renderer}s.
|
||||
*/
|
||||
public static final int VIDEO_SCALING_MODE_DEFAULT = VIDEO_SCALING_MODE_SCALE_TO_FIT;
|
||||
|
||||
/**
|
||||
* Track selection flags.
|
||||
*/
|
||||
|
|
@ -463,6 +486,16 @@ public final class C {
|
|||
*/
|
||||
public static final int MSG_SET_STREAM_TYPE = 4;
|
||||
|
||||
/**
|
||||
* The type of a message that can be passed to a {@link MediaCodec}-based video {@link Renderer}
|
||||
* via {@link ExoPlayer#sendMessages} or {@link ExoPlayer#blockingSendMessages}. The message
|
||||
* object should be one of the integer scaling modes in {@link C.VideoScalingMode}.
|
||||
* <p>
|
||||
* Note that the scaling mode only applies if the {@link Surface} targeted by the renderer is
|
||||
* owned by a {@link android.view.SurfaceView}.
|
||||
*/
|
||||
public static final int MSG_SET_SCALING_MODE = 5;
|
||||
|
||||
/**
|
||||
* Applications or extensions may define custom {@code MSG_*} constants greater than or equal to
|
||||
* this value.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
|
||||
private Surface surface;
|
||||
private boolean ownsSurface;
|
||||
@C.VideoScalingMode
|
||||
private int videoScalingMode;
|
||||
private SurfaceHolder surfaceHolder;
|
||||
private TextureView textureView;
|
||||
private TextRenderer.Output textOutput;
|
||||
|
|
@ -115,7 +117,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
private int audioSessionId;
|
||||
@C.StreamType
|
||||
private int audioStreamType;
|
||||
private float volume;
|
||||
private float audioVolume;
|
||||
private PlaybackParamsHolder playbackParamsHolder;
|
||||
|
||||
/* package */ SimpleExoPlayer(Context context, TrackSelector trackSelector,
|
||||
|
|
@ -152,14 +154,43 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
this.audioRendererCount = audioRendererCount;
|
||||
|
||||
// Set initial values.
|
||||
audioVolume = 1;
|
||||
audioSessionId = AudioTrack.SESSION_ID_NOT_SET;
|
||||
audioStreamType = C.STREAM_TYPE_DEFAULT;
|
||||
volume = 1;
|
||||
videoScalingMode = C.VIDEO_SCALING_MODE_DEFAULT;
|
||||
|
||||
// Build the player and associated objects.
|
||||
player = new ExoPlayerImpl(renderers, trackSelector, loadControl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the video scaling mode.
|
||||
* <p>
|
||||
* Note that the scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is
|
||||
* enabled and if the output surface is owned by a {@link android.view.SurfaceView}.
|
||||
*
|
||||
* @param videoScalingMode The video scaling mode.
|
||||
*/
|
||||
public void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) {
|
||||
this.videoScalingMode = videoScalingMode;
|
||||
ExoPlayerMessage[] messages = new ExoPlayerMessage[videoRendererCount];
|
||||
int count = 0;
|
||||
for (Renderer renderer : renderers) {
|
||||
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
|
||||
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_SCALING_MODE,
|
||||
videoScalingMode);
|
||||
}
|
||||
}
|
||||
player.sendMessages(messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the video scaling mode.
|
||||
*/
|
||||
public @C.VideoScalingMode int getVideoScalingMode() {
|
||||
return videoScalingMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
|
||||
* currently set on the player.
|
||||
|
|
@ -267,15 +298,15 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
/**
|
||||
* Sets the audio volume, with 0 being silence and 1 being unity gain.
|
||||
*
|
||||
* @param volume The volume.
|
||||
* @param audioVolume The audio volume.
|
||||
*/
|
||||
public void setVolume(float volume) {
|
||||
this.volume = volume;
|
||||
public void setVolume(float audioVolume) {
|
||||
this.audioVolume = audioVolume;
|
||||
ExoPlayerMessage[] messages = new ExoPlayerMessage[audioRendererCount];
|
||||
int count = 0;
|
||||
for (Renderer renderer : renderers) {
|
||||
if (renderer.getTrackType() == C.TRACK_TYPE_AUDIO) {
|
||||
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_VOLUME, volume);
|
||||
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_VOLUME, audioVolume);
|
||||
}
|
||||
}
|
||||
player.sendMessages(messages);
|
||||
|
|
@ -285,7 +316,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
* Returns the audio volume, with 0 being silence and 1 being unity gain.
|
||||
*/
|
||||
public float getVolume() {
|
||||
return volume;
|
||||
return audioVolume;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -568,9 +599,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, ArrayList<Renderer> renderersList,
|
||||
long allowedVideoJoiningTimeMs) {
|
||||
MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer(context,
|
||||
MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT,
|
||||
allowedVideoJoiningTimeMs, drmSessionManager, false, mainHandler, componentListener,
|
||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||
MediaCodecSelector.DEFAULT, allowedVideoJoiningTimeMs, drmSessionManager, false,
|
||||
mainHandler, componentListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||
renderersList.add(videoRenderer);
|
||||
|
||||
Renderer audioRenderer = new MediaCodecAudioRenderer(MediaCodecSelector.DEFAULT,
|
||||
|
|
|
|||
|
|
@ -375,6 +375,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||
return codec == null && format != null;
|
||||
}
|
||||
|
||||
protected final MediaCodec getCodec() {
|
||||
return codec;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEnabled(boolean joining) throws ExoPlaybackException {
|
||||
decoderCounters = new DecoderCounters();
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
private final VideoFrameReleaseTimeHelper frameReleaseTimeHelper;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final long allowedJoiningTimeMs;
|
||||
private final int videoScalingMode;
|
||||
private final int maxDroppedFramesToNotify;
|
||||
private final boolean deviceNeedsAutoFrcWorkaround;
|
||||
|
||||
|
|
@ -65,6 +64,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
private CodecMaxValues codecMaxValues;
|
||||
|
||||
private Surface surface;
|
||||
@C.VideoScalingMode
|
||||
private int scalingMode;
|
||||
private boolean renderedFirstFrame;
|
||||
private long joiningDeadlineMs;
|
||||
private long droppedFrameAccumulationStartTimeMs;
|
||||
|
|
@ -85,32 +86,25 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param videoScalingMode The scaling mode to pass to
|
||||
* {@link MediaCodec#setVideoScalingMode(int)}.
|
||||
*/
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
|
||||
int videoScalingMode) {
|
||||
this(context, mediaCodecSelector, videoScalingMode, 0);
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
|
||||
this(context, mediaCodecSelector, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param videoScalingMode The scaling mode to pass to
|
||||
* {@link MediaCodec#setVideoScalingMode(int)}.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
*/
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
|
||||
int videoScalingMode, long allowedJoiningTimeMs) {
|
||||
this(context, mediaCodecSelector, videoScalingMode, allowedJoiningTimeMs, null, null, -1);
|
||||
long allowedJoiningTimeMs) {
|
||||
this(context, mediaCodecSelector, allowedJoiningTimeMs, null, null, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param videoScalingMode The scaling mode to pass to
|
||||
* {@link MediaCodec#setVideoScalingMode(int)}.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
|
|
@ -120,17 +114,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
*/
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
|
||||
int videoScalingMode, long allowedJoiningTimeMs, Handler eventHandler,
|
||||
VideoRendererEventListener eventListener, int maxDroppedFrameCountToNotify) {
|
||||
this(context, mediaCodecSelector, videoScalingMode, allowedJoiningTimeMs, null, false,
|
||||
eventHandler, eventListener, maxDroppedFrameCountToNotify);
|
||||
long allowedJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener,
|
||||
int maxDroppedFrameCountToNotify) {
|
||||
this(context, mediaCodecSelector, allowedJoiningTimeMs, null, false, eventHandler,
|
||||
eventListener, maxDroppedFrameCountToNotify);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param videoScalingMode The scaling mode to pass to
|
||||
* {@link MediaCodec#setVideoScalingMode(int)}.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param drmSessionManager For use with encrypted content. May be null if support for encrypted
|
||||
|
|
@ -147,12 +139,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
*/
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
|
||||
int videoScalingMode, long allowedJoiningTimeMs,
|
||||
DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
|
||||
long allowedJoiningTimeMs, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
|
||||
boolean playClearSamplesWithoutKeys, Handler eventHandler,
|
||||
VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) {
|
||||
super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys);
|
||||
this.videoScalingMode = videoScalingMode;
|
||||
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
|
||||
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
|
||||
frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context);
|
||||
|
|
@ -163,6 +153,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
currentHeight = Format.NO_VALUE;
|
||||
currentPixelWidthHeightRatio = Format.NO_VALUE;
|
||||
pendingPixelWidthHeightRatio = Format.NO_VALUE;
|
||||
scalingMode = C.VIDEO_SCALING_MODE_DEFAULT;
|
||||
clearLastReportedVideoSize();
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +275,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
|
||||
if (messageType == C.MSG_SET_SURFACE) {
|
||||
setSurface((Surface) message);
|
||||
} else if (messageType == C.MSG_SET_SCALING_MODE) {
|
||||
scalingMode = (Integer) message;
|
||||
MediaCodec codec = getCodec();
|
||||
if (codec != null) {
|
||||
setVideoScalingMode(codec, scalingMode);
|
||||
}
|
||||
} else {
|
||||
super.handleMessage(messageType, message);
|
||||
}
|
||||
|
|
@ -358,7 +355,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
currentUnappliedRotationDegrees = pendingRotationDegrees;
|
||||
}
|
||||
// Must be applied each time the output format changes.
|
||||
codec.setVideoScalingMode(videoScalingMode);
|
||||
setVideoScalingMode(codec, scalingMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -488,6 +485,36 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
private void clearLastReportedVideoSize() {
|
||||
lastReportedWidth = Format.NO_VALUE;
|
||||
lastReportedHeight = Format.NO_VALUE;
|
||||
lastReportedPixelWidthHeightRatio = Format.NO_VALUE;
|
||||
lastReportedUnappliedRotationDegrees = Format.NO_VALUE;
|
||||
}
|
||||
|
||||
private void maybeNotifyVideoSizeChanged() {
|
||||
if (lastReportedWidth != currentWidth || lastReportedHeight != currentHeight
|
||||
|| lastReportedUnappliedRotationDegrees != currentUnappliedRotationDegrees
|
||||
|| lastReportedPixelWidthHeightRatio != currentPixelWidthHeightRatio) {
|
||||
eventDispatcher.videoSizeChanged(currentWidth, currentHeight, currentUnappliedRotationDegrees,
|
||||
currentPixelWidthHeightRatio);
|
||||
lastReportedWidth = currentWidth;
|
||||
lastReportedHeight = currentHeight;
|
||||
lastReportedUnappliedRotationDegrees = currentUnappliedRotationDegrees;
|
||||
lastReportedPixelWidthHeightRatio = currentPixelWidthHeightRatio;
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeNotifyDroppedFrames() {
|
||||
if (droppedFrames > 0) {
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
long elapsedMs = now - droppedFrameAccumulationStartTimeMs;
|
||||
eventDispatcher.droppedFrames(droppedFrames, elapsedMs);
|
||||
droppedFrames = 0;
|
||||
droppedFrameAccumulationStartTimeMs = now;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private static MediaFormat getMediaFormat(Format format, CodecMaxValues codecMaxValues,
|
||||
boolean deviceNeedsAutoFrcWorkaround) {
|
||||
|
|
@ -583,34 +610,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||
return (maxPixels * 3) / (2 * minCompressionRatio);
|
||||
}
|
||||
|
||||
private void clearLastReportedVideoSize() {
|
||||
lastReportedWidth = Format.NO_VALUE;
|
||||
lastReportedHeight = Format.NO_VALUE;
|
||||
lastReportedPixelWidthHeightRatio = Format.NO_VALUE;
|
||||
lastReportedUnappliedRotationDegrees = Format.NO_VALUE;
|
||||
}
|
||||
|
||||
private void maybeNotifyVideoSizeChanged() {
|
||||
if (lastReportedWidth != currentWidth || lastReportedHeight != currentHeight
|
||||
|| lastReportedUnappliedRotationDegrees != currentUnappliedRotationDegrees
|
||||
|| lastReportedPixelWidthHeightRatio != currentPixelWidthHeightRatio) {
|
||||
eventDispatcher.videoSizeChanged(currentWidth, currentHeight, currentUnappliedRotationDegrees,
|
||||
currentPixelWidthHeightRatio);
|
||||
lastReportedWidth = currentWidth;
|
||||
lastReportedHeight = currentHeight;
|
||||
lastReportedUnappliedRotationDegrees = currentUnappliedRotationDegrees;
|
||||
lastReportedPixelWidthHeightRatio = currentPixelWidthHeightRatio;
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeNotifyDroppedFrames() {
|
||||
if (droppedFrames > 0) {
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
long elapsedMs = now - droppedFrameAccumulationStartTimeMs;
|
||||
eventDispatcher.droppedFrames(droppedFrames, elapsedMs);
|
||||
droppedFrames = 0;
|
||||
droppedFrameAccumulationStartTimeMs = now;
|
||||
}
|
||||
private static void setVideoScalingMode(MediaCodec codec, int scalingMode) {
|
||||
codec.setVideoScalingMode(scalingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ public class DebugMediaCodecVideoRenderer extends MediaCodecVideoRenderer {
|
|||
private int bufferCount;
|
||||
|
||||
public DebugMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
|
||||
int videoScalingMode, long allowedJoiningTimeMs, Handler eventHandler,
|
||||
VideoRendererEventListener eventListener, int maxDroppedFrameCountToNotify) {
|
||||
super(context, mediaCodecSelector, videoScalingMode, allowedJoiningTimeMs, null, false,
|
||||
eventHandler, eventListener, maxDroppedFrameCountToNotify);
|
||||
long allowedJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener,
|
||||
int maxDroppedFrameCountToNotify) {
|
||||
super(context, mediaCodecSelector, allowedJoiningTimeMs, null, false, eventHandler,
|
||||
eventListener, maxDroppedFrameCountToNotify);
|
||||
startIndex = 0;
|
||||
queueSize = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue