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
This commit is contained in:
parent
300dc05e85
commit
03fe503f1c
@ -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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
// Stale event.
|
// Stale event.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
maybeNotifyRenderedFirstFrame();
|
onProcessedTunneledBuffer(presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user