Commit b79156c3 by andrewlewis Committed by Oliver Woodman

Propagate output format in tunneling mode

From API 23 this uses the timed format queue. Before API 23 the
format is notified as soon as the buffer is queued.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=213830729
parent b58daf8d
...@@ -497,6 +497,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -497,6 +497,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return false; return false;
} }
/**
* Polls the pending output format queue for a given buffer timestamp. If a format is present, it
* is removed and returned. Otherwise returns {@code null}. Subclasses should only call this
* method if they are taking over responsibility for output format propagation (e.g., when using
* video tunneling).
*/
protected final @Nullable Format updateOutputFormatForTime(long presentationTimeUs) {
Format format = formatQueue.pollFloor(presentationTimeUs);
if (format != null) {
outputFormat = format;
}
return format;
}
protected final MediaCodec getCodec() { protected final MediaCodec getCodec() {
return codec; return codec;
} }
...@@ -1297,10 +1311,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1297,10 +1311,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size); outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
} }
shouldSkipOutputBuffer = shouldSkipOutputBuffer(outputBufferInfo.presentationTimeUs); shouldSkipOutputBuffer = shouldSkipOutputBuffer(outputBufferInfo.presentationTimeUs);
Format format = formatQueue.pollFloor(outputBufferInfo.presentationTimeUs); updateOutputFormatForTime(outputBufferInfo.presentationTimeUs);
if (format != null) {
outputFormat = format;
}
} }
boolean processedOutputBuffer; boolean processedOutputBuffer;
......
...@@ -566,7 +566,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -566,7 +566,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
buffersInCodecCount++; buffersInCodecCount++;
lastInputTimeUs = Math.max(buffer.timeUs, lastInputTimeUs); lastInputTimeUs = Math.max(buffer.timeUs, lastInputTimeUs);
if (Util.SDK_INT < 23 && tunneling) { if (Util.SDK_INT < 23 && tunneling) {
maybeNotifyRenderedFirstFrame(); // In tunneled mode before API 23 we don't have a way to know when the buffer is output, so
// treat it as if it were output immediately.
onProcessedTunneledBuffer(buffer.timeUs);
} }
} }
...@@ -575,29 +577,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -575,29 +577,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
boolean hasCrop = outputFormat.containsKey(KEY_CROP_RIGHT) boolean hasCrop = outputFormat.containsKey(KEY_CROP_RIGHT)
&& outputFormat.containsKey(KEY_CROP_LEFT) && outputFormat.containsKey(KEY_CROP_BOTTOM) && outputFormat.containsKey(KEY_CROP_LEFT) && outputFormat.containsKey(KEY_CROP_BOTTOM)
&& outputFormat.containsKey(KEY_CROP_TOP); && outputFormat.containsKey(KEY_CROP_TOP);
currentWidth = hasCrop int width =
? outputFormat.getInteger(KEY_CROP_RIGHT) - outputFormat.getInteger(KEY_CROP_LEFT) + 1 hasCrop
: outputFormat.getInteger(MediaFormat.KEY_WIDTH); ? outputFormat.getInteger(KEY_CROP_RIGHT) - outputFormat.getInteger(KEY_CROP_LEFT) + 1
currentHeight = hasCrop : outputFormat.getInteger(MediaFormat.KEY_WIDTH);
? outputFormat.getInteger(KEY_CROP_BOTTOM) - outputFormat.getInteger(KEY_CROP_TOP) + 1 int height =
: outputFormat.getInteger(MediaFormat.KEY_HEIGHT); hasCrop
currentPixelWidthHeightRatio = pendingPixelWidthHeightRatio; ? outputFormat.getInteger(KEY_CROP_BOTTOM) - outputFormat.getInteger(KEY_CROP_TOP) + 1
if (Util.SDK_INT >= 21) { : outputFormat.getInteger(MediaFormat.KEY_HEIGHT);
// On API level 21 and above the decoder applies the rotation when rendering to the surface. processOutputFormat(codec, width, height);
// Hence currentUnappliedRotation should always be 0. For 90 and 270 degree rotations, we need
// to flip the width, height and pixel aspect ratio to reflect the rotation that was applied.
if (pendingRotationDegrees == 90 || pendingRotationDegrees == 270) {
int rotatedHeight = currentWidth;
currentWidth = currentHeight;
currentHeight = rotatedHeight;
currentPixelWidthHeightRatio = 1 / currentPixelWidthHeightRatio;
}
} else {
// On API level 20 and below the decoder does not apply the rotation.
currentUnappliedRotationDegrees = pendingRotationDegrees;
}
// Must be applied each time the output format changes.
codec.setVideoScalingMode(scalingMode);
} }
@Override @Override
...@@ -705,6 +693,28 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -705,6 +693,28 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return false; return false;
} }
private void processOutputFormat(MediaCodec codec, int width, int height) {
currentWidth = width;
currentHeight = height;
currentPixelWidthHeightRatio = pendingPixelWidthHeightRatio;
if (Util.SDK_INT >= 21) {
// On API level 21 and above the decoder applies the rotation when rendering to the surface.
// Hence currentUnappliedRotation should always be 0. For 90 and 270 degree rotations, we need
// to flip the width, height and pixel aspect ratio to reflect the rotation that was applied.
if (pendingRotationDegrees == 90 || pendingRotationDegrees == 270) {
int rotatedHeight = currentWidth;
currentWidth = currentHeight;
currentHeight = rotatedHeight;
currentPixelWidthHeightRatio = 1 / currentPixelWidthHeightRatio;
}
} else {
// On API level 20 and below the decoder does not apply the rotation.
currentUnappliedRotationDegrees = pendingRotationDegrees;
}
// Must be applied each time the output format changes.
codec.setVideoScalingMode(scalingMode);
}
private void notifyFrameMetadataListener( private void notifyFrameMetadataListener(
long presentationTimeUs, long releaseTimeNs, Format format) { long presentationTimeUs, long releaseTimeNs, Format format) {
if (frameMetadataListener != null) { if (frameMetadataListener != null) {
...@@ -722,6 +732,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -722,6 +732,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return outputStreamOffsetUs; return outputStreamOffsetUs;
} }
/** Called when a buffer was processed in tunneling mode. */
protected void onProcessedTunneledBuffer(long presentationTimeUs) {
@Nullable Format format = updateOutputFormatForTime(presentationTimeUs);
if (format != null) {
processOutputFormat(getCodec(), format.width, format.height);
}
maybeNotifyVideoSizeChanged();
maybeNotifyRenderedFirstFrame();
onProcessedOutputBuffer(presentationTimeUs);
}
/** /**
* Called when an output buffer is successfully processed. * Called when an output buffer is successfully processed.
* *
...@@ -1463,7 +1484,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1463,7 +1484,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// Stale event. // Stale event.
return; return;
} }
maybeNotifyRenderedFirstFrame(); onProcessedTunneledBuffer(presentationTimeUs);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment