mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Refactor frame rate notification to release control
Frame rate change is currently notified to the release control when the video frame processor input frame rate changes, but it should be when the video frame processor output frame rate changes. PiperOrigin-RevId: 688512300
This commit is contained in:
parent
31ece8cbd2
commit
8260bb3d2e
@ -157,6 +157,14 @@ public interface VideoFrameProcessor {
|
|||||||
*/
|
*/
|
||||||
default void onOutputSizeChanged(int width, int height) {}
|
default void onOutputSizeChanged(int width, int height) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the output frame rate changes.
|
||||||
|
*
|
||||||
|
* @param frameRate The output frame rate in frames per second, or {@link Format#NO_VALUE} if
|
||||||
|
* unknown.
|
||||||
|
*/
|
||||||
|
default void onOutputFrameRateChanged(float frameRate) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an output frame with the given {@code presentationTimeUs} becomes available for
|
* Called when an output frame with the given {@code presentationTimeUs} becomes available for
|
||||||
* rendering.
|
* rendering.
|
||||||
|
@ -35,6 +35,14 @@ public interface VideoGraph {
|
|||||||
*/
|
*/
|
||||||
default void onOutputSizeChanged(int width, int height) {}
|
default void onOutputSizeChanged(int width, int height) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the output frame rate changes.
|
||||||
|
*
|
||||||
|
* @param frameRate The output frame rate in frames per second, or {@link Format#NO_VALUE} if
|
||||||
|
* unknown.
|
||||||
|
*/
|
||||||
|
default void onOutputFrameRateChanged(float frameRate) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an output frame with the given {@code framePresentationTimeUs} becomes available
|
* Called when an output frame with the given {@code framePresentationTimeUs} becomes available
|
||||||
* for rendering.
|
* for rendering.
|
||||||
|
@ -457,6 +457,8 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
private final List<GlShaderProgram> intermediateGlShaderPrograms;
|
private final List<GlShaderProgram> intermediateGlShaderPrograms;
|
||||||
private final ConditionVariable inputStreamRegisteredCondition;
|
private final ConditionVariable inputStreamRegisteredCondition;
|
||||||
|
|
||||||
|
private @MonotonicNonNull InputStreamInfo currentInputStreamInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The input stream that is {@linkplain #registerInputStream registered}, but the pipeline has not
|
* The input stream that is {@linkplain #registerInputStream registered}, but the pipeline has not
|
||||||
* adapted to processing it.
|
* adapted to processing it.
|
||||||
@ -515,7 +517,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
if (pendingInputStreamInfo != null) {
|
if (pendingInputStreamInfo != null) {
|
||||||
InputStreamInfo pendingInputStreamInfo = this.pendingInputStreamInfo;
|
InputStreamInfo pendingInputStreamInfo = this.pendingInputStreamInfo;
|
||||||
videoFrameProcessingTaskExecutor.submit(
|
videoFrameProcessingTaskExecutor.submit(
|
||||||
() -> configureEffects(pendingInputStreamInfo, /* forceReconfigure= */ false));
|
() -> configure(pendingInputStreamInfo, /* forceReconfigure= */ false));
|
||||||
this.pendingInputStreamInfo = null;
|
this.pendingInputStreamInfo = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -659,7 +661,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
registeredFirstInputStream = true;
|
registeredFirstInputStream = true;
|
||||||
inputStreamRegisteredCondition.close();
|
inputStreamRegisteredCondition.close();
|
||||||
videoFrameProcessingTaskExecutor.submit(
|
videoFrameProcessingTaskExecutor.submit(
|
||||||
() -> configureEffects(pendingInputStreamInfo, /* forceReconfigure= */ true));
|
() -> configure(pendingInputStreamInfo, /* forceReconfigure= */ true));
|
||||||
} else {
|
} else {
|
||||||
// Rejects further inputs after signaling EOS and before the next input stream is fully
|
// Rejects further inputs after signaling EOS and before the next input stream is fully
|
||||||
// configured.
|
// configured.
|
||||||
@ -988,16 +990,17 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link GlShaderProgram} instances for {@code effects}.
|
* Configures for a new input stream.
|
||||||
*
|
*
|
||||||
* <p>The pipeline will only re-configure if the {@link InputStreamInfo#effects new effects}
|
* <p>The effect pipeline will only re-configure if the {@link InputStreamInfo#effects new
|
||||||
* doesn't match the {@link #activeEffects}, or when {@code forceReconfigure} is set to {@code
|
* effects} don't match the {@link #activeEffects}, or when {@code forceReconfigure} is set to
|
||||||
* true}.
|
* {@code true}.
|
||||||
*/
|
*/
|
||||||
private void configureEffects(InputStreamInfo inputStreamInfo, boolean forceReconfigure)
|
private void configure(InputStreamInfo inputStreamInfo, boolean forceReconfigure)
|
||||||
throws VideoFrameProcessingException {
|
throws VideoFrameProcessingException {
|
||||||
checkColors(
|
checkColors(
|
||||||
/* inputColorInfo= */ checkNotNull(inputStreamInfo.format.colorInfo), outputColorInfo);
|
/* inputColorInfo= */ checkNotNull(inputStreamInfo.format.colorInfo), outputColorInfo);
|
||||||
|
|
||||||
if (forceReconfigure || !activeEffects.equals(inputStreamInfo.effects)) {
|
if (forceReconfigure || !activeEffects.equals(inputStreamInfo.effects)) {
|
||||||
if (!intermediateGlShaderPrograms.isEmpty()) {
|
if (!intermediateGlShaderPrograms.isEmpty()) {
|
||||||
for (int i = 0; i < intermediateGlShaderPrograms.size(); i++) {
|
for (int i = 0; i < intermediateGlShaderPrograms.size(); i++) {
|
||||||
@ -1035,10 +1038,17 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
onInputSurfaceReadyListener = null;
|
onInputSurfaceReadyListener = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listenerExecutor.execute(
|
listenerExecutor.execute(
|
||||||
() ->
|
() ->
|
||||||
listener.onInputStreamRegistered(
|
listener.onInputStreamRegistered(
|
||||||
inputStreamInfo.inputType, inputStreamInfo.format, inputStreamInfo.effects));
|
inputStreamInfo.inputType, inputStreamInfo.format, inputStreamInfo.effects));
|
||||||
|
if (currentInputStreamInfo == null
|
||||||
|
|| inputStreamInfo.format.frameRate != currentInputStreamInfo.format.frameRate) {
|
||||||
|
listenerExecutor.execute(
|
||||||
|
() -> listener.onOutputFrameRateChanged(inputStreamInfo.format.frameRate));
|
||||||
|
}
|
||||||
|
this.currentInputStreamInfo = inputStreamInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks that color configuration is valid for {@link DefaultVideoFrameProcessor}. */
|
/** Checks that color configuration is valid for {@link DefaultVideoFrameProcessor}. */
|
||||||
|
@ -176,6 +176,11 @@ public abstract class MultipleInputVideoGraph implements VideoGraph {
|
|||||||
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
|
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOutputFrameRateChanged(float frameRate) {
|
||||||
|
listenerExecutor.execute(() -> listener.onOutputFrameRateChanged(frameRate));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailableForRendering(long presentationTimeUs) {
|
public void onOutputFrameAvailableForRendering(long presentationTimeUs) {
|
||||||
if (presentationTimeUs == 0) {
|
if (presentationTimeUs == 0) {
|
||||||
|
@ -114,6 +114,11 @@ public abstract class SingleInputVideoGraph implements VideoGraph {
|
|||||||
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
|
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOutputFrameRateChanged(float frameRate) {
|
||||||
|
listenerExecutor.execute(() -> listener.onOutputFrameRateChanged(frameRate));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailableForRendering(long presentationTimeUs) {
|
public void onOutputFrameAvailableForRendering(long presentationTimeUs) {
|
||||||
if (isEnded) {
|
if (isEnded) {
|
||||||
|
@ -339,6 +339,11 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
defaultVideoSink.onInputStreamChanged(INPUT_TYPE_SURFACE, format);
|
defaultVideoSink.onInputStreamChanged(INPUT_TYPE_SURFACE, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOutputFrameRateChanged(float frameRate) {
|
||||||
|
videoFrameReleaseControl.setFrameRate(frameRate);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOutputFrameAvailableForRendering(long framePresentationTimeUs) {
|
public void onOutputFrameAvailableForRendering(long framePresentationTimeUs) {
|
||||||
if (pendingFlushCount > 0) {
|
if (pendingFlushCount > 0) {
|
||||||
@ -596,7 +601,6 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unsupported input type " + inputType);
|
throw new UnsupportedOperationException("Unsupported input type " + inputType);
|
||||||
}
|
}
|
||||||
videoFrameReleaseControl.setFrameRate(format.frameRate);
|
|
||||||
this.inputType = inputType;
|
this.inputType = inputType;
|
||||||
this.inputFormat = format;
|
this.inputFormat = format;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user