| Index: webrtc/api/android/java/src/org/webrtc/MediaCodecVideoDecoder.java
|
| diff --git a/webrtc/api/android/java/src/org/webrtc/MediaCodecVideoDecoder.java b/webrtc/api/android/java/src/org/webrtc/MediaCodecVideoDecoder.java
|
| index 053780b9495171295ee6fae11b90c5e93a1f13e0..44572cb1284bd3f99face8a5011566f4dae5c254 100644
|
| --- a/webrtc/api/android/java/src/org/webrtc/MediaCodecVideoDecoder.java
|
| +++ b/webrtc/api/android/java/src/org/webrtc/MediaCodecVideoDecoder.java
|
| @@ -42,11 +42,7 @@ public class MediaCodecVideoDecoder {
|
| private static final long MAX_DECODE_TIME_MS = 200;
|
|
|
| // Tracks webrtc::VideoCodecType.
|
| - public enum VideoCodecType {
|
| - VIDEO_CODEC_VP8,
|
| - VIDEO_CODEC_VP9,
|
| - VIDEO_CODEC_H264
|
| - }
|
| + public enum VideoCodecType { VIDEO_CODEC_VP8, VIDEO_CODEC_VP9, VIDEO_CODEC_H264 }
|
|
|
| // Timeout for input buffer dequeue.
|
| private static final int DEQUEUE_INPUT_TIMEOUT = 500000;
|
| @@ -70,14 +66,13 @@ public class MediaCodecVideoDecoder {
|
| private static final String VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
|
| private static final String H264_MIME_TYPE = "video/avc";
|
| // List of supported HW VP8 decoders.
|
| - private static final String[] supportedVp8HwCodecPrefixes =
|
| - {"OMX.qcom.", "OMX.Nvidia.", "OMX.Exynos.", "OMX.Intel." };
|
| + private static final String[] supportedVp8HwCodecPrefixes = {
|
| + "OMX.qcom.", "OMX.Nvidia.", "OMX.Exynos.", "OMX.Intel."};
|
| // List of supported HW VP9 decoders.
|
| - private static final String[] supportedVp9HwCodecPrefixes =
|
| - {"OMX.qcom.", "OMX.Exynos." };
|
| + private static final String[] supportedVp9HwCodecPrefixes = {"OMX.qcom.", "OMX.Exynos."};
|
| // List of supported HW H.264 decoders.
|
| - private static final String[] supportedH264HwCodecPrefixes =
|
| - {"OMX.qcom.", "OMX.Intel.", "OMX.Exynos." };
|
| + private static final String[] supportedH264HwCodecPrefixes = {
|
| + "OMX.qcom.", "OMX.Intel.", "OMX.Exynos."};
|
|
|
| // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
|
| // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
|
| @@ -87,13 +82,11 @@ public class MediaCodecVideoDecoder {
|
| private static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04;
|
| // Allowable color formats supported by codec - in order of preference.
|
| private static final List<Integer> supportedColorList = Arrays.asList(
|
| - CodecCapabilities.COLOR_FormatYUV420Planar,
|
| - CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
|
| - CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
|
| - COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka,
|
| - COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka,
|
| - COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka,
|
| - COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m);
|
| + CodecCapabilities.COLOR_FormatYUV420Planar, CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
|
| + CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
|
| + COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka, COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka,
|
| + COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka,
|
| + COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m);
|
|
|
| private int colorFormat;
|
| private int width;
|
| @@ -108,8 +101,8 @@ public class MediaCodecVideoDecoder {
|
| private TextureListener textureListener;
|
| private int droppedFrames;
|
| private Surface surface = null;
|
| - private final Queue<DecodedOutputBuffer>
|
| - dequeuedSurfaceOutputBuffers = new LinkedList<DecodedOutputBuffer>();
|
| + private final Queue<DecodedOutputBuffer> dequeuedSurfaceOutputBuffers =
|
| + new LinkedList<DecodedOutputBuffer>();
|
|
|
| // MediaCodec error handler - invoked when critical error happens which may prevent
|
| // further use of media codec API. Now it means that one of media codec instances
|
| @@ -142,18 +135,18 @@ public class MediaCodecVideoDecoder {
|
|
|
| // Functions to query if HW decoding is supported.
|
| public static boolean isVp8HwSupported() {
|
| - return !hwDecoderDisabledTypes.contains(VP8_MIME_TYPE) &&
|
| - (findDecoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes) != null);
|
| + return !hwDecoderDisabledTypes.contains(VP8_MIME_TYPE)
|
| + && (findDecoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes) != null);
|
| }
|
|
|
| public static boolean isVp9HwSupported() {
|
| - return !hwDecoderDisabledTypes.contains(VP9_MIME_TYPE) &&
|
| - (findDecoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes) != null);
|
| + return !hwDecoderDisabledTypes.contains(VP9_MIME_TYPE)
|
| + && (findDecoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes) != null);
|
| }
|
|
|
| public static boolean isH264HwSupported() {
|
| - return !hwDecoderDisabledTypes.contains(H264_MIME_TYPE) &&
|
| - (findDecoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes) != null);
|
| + return !hwDecoderDisabledTypes.contains(H264_MIME_TYPE)
|
| + && (findDecoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes) != null);
|
| }
|
|
|
| public static void printStackTrace() {
|
| @@ -175,11 +168,10 @@ public class MediaCodecVideoDecoder {
|
| this.colorFormat = colorFormat;
|
| }
|
| public final String codecName; // OpenMax component name for VP8 codec.
|
| - public final int colorFormat; // Color format supported by codec.
|
| + public final int colorFormat; // Color format supported by codec.
|
| }
|
|
|
| - private static DecoderProperties findDecoder(
|
| - String mime, String[] supportedCodecPrefixes) {
|
| + private static DecoderProperties findDecoder(String mime, String[] supportedCodecPrefixes) {
|
| if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
| return null; // MediaCodec.setParameters is missing.
|
| }
|
| @@ -189,7 +181,7 @@ public class MediaCodecVideoDecoder {
|
| try {
|
| info = MediaCodecList.getCodecInfoAt(i);
|
| } catch (IllegalArgumentException e) {
|
| - Logging.e(TAG, "Cannot retrieve decoder codec info", e);
|
| + Logging.e(TAG, "Cannot retrieve decoder codec info", e);
|
| }
|
| if (info == null || info.isEncoder()) {
|
| continue;
|
| @@ -202,7 +194,7 @@ public class MediaCodecVideoDecoder {
|
| }
|
| }
|
| if (name == null) {
|
| - continue; // No HW support in this codec; try the next one.
|
| + continue; // No HW support in this codec; try the next one.
|
| }
|
| Logging.d(TAG, "Found candidate decoder " + name);
|
|
|
| @@ -223,7 +215,7 @@ public class MediaCodecVideoDecoder {
|
| try {
|
| capabilities = info.getCapabilitiesForType(mime);
|
| } catch (IllegalArgumentException e) {
|
| - Logging.e(TAG, "Cannot retrieve decoder capabilities", e);
|
| + Logging.e(TAG, "Cannot retrieve decoder capabilities", e);
|
| continue;
|
| }
|
| for (int colorFormat : capabilities.colorFormats) {
|
| @@ -233,29 +225,27 @@ public class MediaCodecVideoDecoder {
|
| for (int codecColorFormat : capabilities.colorFormats) {
|
| if (codecColorFormat == supportedColorFormat) {
|
| // Found supported HW decoder.
|
| - Logging.d(TAG, "Found target decoder " + name +
|
| - ". Color: 0x" + Integer.toHexString(codecColorFormat));
|
| + Logging.d(TAG, "Found target decoder " + name + ". Color: 0x"
|
| + + Integer.toHexString(codecColorFormat));
|
| return new DecoderProperties(name, codecColorFormat);
|
| }
|
| }
|
| }
|
| }
|
| Logging.d(TAG, "No HW decoder found for mime " + mime);
|
| - return null; // No HW decoder.
|
| + return null; // No HW decoder.
|
| }
|
|
|
| private void checkOnMediaCodecThread() throws IllegalStateException {
|
| if (mediaCodecThread.getId() != Thread.currentThread().getId()) {
|
| - throw new IllegalStateException(
|
| - "MediaCodecVideoDecoder previously operated on " + mediaCodecThread +
|
| - " but is now called on " + Thread.currentThread());
|
| + throw new IllegalStateException("MediaCodecVideoDecoder previously operated on "
|
| + + mediaCodecThread + " but is now called on " + Thread.currentThread());
|
| }
|
| }
|
|
|
| // Pass null in |surfaceTextureHelper| to configure the codec for ByteBuffer output.
|
| private boolean initDecode(
|
| - VideoCodecType type, int width, int height,
|
| - SurfaceTextureHelper surfaceTextureHelper) {
|
| + VideoCodecType type, int width, int height, SurfaceTextureHelper surfaceTextureHelper) {
|
| if (mediaCodecThread != null) {
|
| throw new RuntimeException("initDecode: Forgot to release()?");
|
| }
|
| @@ -280,9 +270,8 @@ public class MediaCodecVideoDecoder {
|
| throw new RuntimeException("Cannot find HW decoder for " + type);
|
| }
|
|
|
| - Logging.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height +
|
| - ". Color: 0x" + Integer.toHexString(properties.colorFormat) +
|
| - ". Use Surface: " + useSurface);
|
| + Logging.d(TAG, "Java initDecode: " + type + " : " + width + " x " + height + ". Color: 0x"
|
| + + Integer.toHexString(properties.colorFormat) + ". Use Surface: " + useSurface);
|
|
|
| runningInstance = this; // Decoder is now running and can be queried for stack traces.
|
| mediaCodecThread = Thread.currentThread();
|
| @@ -317,8 +306,8 @@ public class MediaCodecVideoDecoder {
|
| hasDecodedFirstFrame = false;
|
| dequeuedSurfaceOutputBuffers.clear();
|
| droppedFrames = 0;
|
| - Logging.d(TAG, "Input buffers: " + inputBuffers.length +
|
| - ". Output buffers: " + outputBuffers.length);
|
| + Logging.d(TAG,
|
| + "Input buffers: " + inputBuffers.length + ". Output buffers: " + outputBuffers.length);
|
| return true;
|
| } catch (IllegalStateException e) {
|
| Logging.e(TAG, "initDecode failed", e);
|
| @@ -406,12 +395,11 @@ public class MediaCodecVideoDecoder {
|
| try {
|
| inputBuffers[inputBufferIndex].position(0);
|
| inputBuffers[inputBufferIndex].limit(size);
|
| - decodeStartTimeMs.add(new TimeStamps(SystemClock.elapsedRealtime(), timeStampMs,
|
| - ntpTimeStamp));
|
| + decodeStartTimeMs.add(
|
| + new TimeStamps(SystemClock.elapsedRealtime(), timeStampMs, ntpTimeStamp));
|
| mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, presentationTimeStamUs, 0);
|
| return true;
|
| - }
|
| - catch (IllegalStateException e) {
|
| + } catch (IllegalStateException e) {
|
| Logging.e(TAG, "decode failed", e);
|
| return false;
|
| }
|
| @@ -511,8 +499,7 @@ public class MediaCodecVideoDecoder {
|
|
|
| public void addBufferToRender(DecodedOutputBuffer buffer) {
|
| if (bufferToRender != null) {
|
| - Logging.e(TAG,
|
| - "Unexpected addBufferToRender() called while waiting for a texture.");
|
| + Logging.e(TAG, "Unexpected addBufferToRender() called while waiting for a texture.");
|
| throw new IllegalStateException("Waiting for a texture.");
|
| }
|
| bufferToRender = buffer;
|
| @@ -530,8 +517,8 @@ public class MediaCodecVideoDecoder {
|
| int oesTextureId, float[] transformMatrix, long timestampNs) {
|
| synchronized (newFrameLock) {
|
| if (renderedBuffer != null) {
|
| - Logging.e(TAG,
|
| - "Unexpected onTextureFrameAvailable() called while already holding a texture.");
|
| + Logging.e(
|
| + TAG, "Unexpected onTextureFrameAvailable() called while already holding a texture.");
|
| throw new IllegalStateException("Already holding a texture.");
|
| }
|
| // |timestampNs| is always zero on some Android versions.
|
| @@ -550,7 +537,7 @@ public class MediaCodecVideoDecoder {
|
| if (renderedBuffer == null && timeoutMs > 0 && isWaitingForTexture()) {
|
| try {
|
| newFrameLock.wait(timeoutMs);
|
| - } catch(InterruptedException e) {
|
| + } catch (InterruptedException e) {
|
| // Restore the interrupted status by reinterrupting the thread.
|
| Thread.currentThread().interrupt();
|
| }
|
| @@ -588,8 +575,8 @@ public class MediaCodecVideoDecoder {
|
| // MediaCodec.INFO_TRY_AGAIN_LATER.
|
| final MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
|
| while (true) {
|
| - final int result = mediaCodec.dequeueOutputBuffer(
|
| - info, TimeUnit.MILLISECONDS.toMicros(dequeueTimeoutMs));
|
| + final int result =
|
| + mediaCodec.dequeueOutputBuffer(info, TimeUnit.MILLISECONDS.toMicros(dequeueTimeoutMs));
|
| switch (result) {
|
| case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
|
| outputBuffers = mediaCodec.getOutputBuffers();
|
| @@ -604,8 +591,8 @@ public class MediaCodecVideoDecoder {
|
| int new_width = format.getInteger(MediaFormat.KEY_WIDTH);
|
| int new_height = format.getInteger(MediaFormat.KEY_HEIGHT);
|
| if (hasDecodedFirstFrame && (new_width != width || new_height != height)) {
|
| - throw new RuntimeException("Unexpected size change. Configured " + width + "*" +
|
| - height + ". New " + new_width + "*" + new_height);
|
| + throw new RuntimeException("Unexpected size change. Configured " + width + "*" + height
|
| + + ". New " + new_width + "*" + new_height);
|
| }
|
| width = format.getInteger(MediaFormat.KEY_WIDTH);
|
| height = format.getInteger(MediaFormat.KEY_HEIGHT);
|
| @@ -635,19 +622,14 @@ public class MediaCodecVideoDecoder {
|
| long decodeTimeMs = SystemClock.elapsedRealtime() - timeStamps.decodeStartTimeMs;
|
| if (decodeTimeMs > MAX_DECODE_TIME_MS) {
|
| Logging.e(TAG, "Very high decode time: " + decodeTimeMs + "ms"
|
| - + ". Q size: " + decodeStartTimeMs.size()
|
| - + ". Might be caused by resuming H264 decoding after a pause.");
|
| + + ". Q size: " + decodeStartTimeMs.size()
|
| + + ". Might be caused by resuming H264 decoding after a pause.");
|
| decodeTimeMs = MAX_DECODE_TIME_MS;
|
| }
|
| - return new DecodedOutputBuffer(result,
|
| - info.offset,
|
| - info.size,
|
| - TimeUnit.MICROSECONDS.toMillis(info.presentationTimeUs),
|
| - timeStamps.timeStampMs,
|
| - timeStamps.ntpTimeStampMs,
|
| - decodeTimeMs,
|
| - SystemClock.elapsedRealtime());
|
| - }
|
| + return new DecodedOutputBuffer(result, info.offset, info.size,
|
| + TimeUnit.MICROSECONDS.toMillis(info.presentationTimeUs), timeStamps.timeStampMs,
|
| + timeStamps.ntpTimeStampMs, decodeTimeMs, SystemClock.elapsedRealtime());
|
| + }
|
| }
|
| }
|
|
|
| @@ -675,8 +657,8 @@ public class MediaCodecVideoDecoder {
|
| }
|
|
|
| if ((dequeuedSurfaceOutputBuffers.size()
|
| - >= Math.min(MAX_QUEUED_OUTPUTBUFFERS, outputBuffers.length)
|
| - || (dequeueTimeoutMs > 0 && !dequeuedSurfaceOutputBuffers.isEmpty()))) {
|
| + >= Math.min(MAX_QUEUED_OUTPUTBUFFERS, outputBuffers.length)
|
| + || (dequeueTimeoutMs > 0 && !dequeuedSurfaceOutputBuffers.isEmpty()))) {
|
| ++droppedFrames;
|
| // Drop the oldest frame still in dequeuedSurfaceOutputBuffers.
|
| // The oldest frame is owned by |textureListener| and can't be dropped since
|
| @@ -686,18 +668,17 @@ public class MediaCodecVideoDecoder {
|
| // TODO(perkj): Re-add the below log when VideoRenderGUI has been removed or fixed to
|
| // return the one and only texture even if it does not render.
|
| Logging.w(TAG, "Draining decoder. Dropping frame with TS: "
|
| - + droppedFrame.presentationTimeStampMs +
|
| - ". Total number of dropped frames: " + droppedFrames);
|
| + + droppedFrame.presentationTimeStampMs + ". Total number of dropped frames: "
|
| + + droppedFrames);
|
| } else {
|
| - Logging.w(TAG, "Too many output buffers " + dequeuedSurfaceOutputBuffers.size() +
|
| - ". Dropping frame with TS: " + droppedFrame.presentationTimeStampMs +
|
| - ". Total number of dropped frames: " + droppedFrames);
|
| + Logging.w(TAG, "Too many output buffers " + dequeuedSurfaceOutputBuffers.size()
|
| + + ". Dropping frame with TS: " + droppedFrame.presentationTimeStampMs
|
| + + ". Total number of dropped frames: " + droppedFrames);
|
| }
|
|
|
| mediaCodec.releaseOutputBuffer(droppedFrame.index, false /* render */);
|
| - return new DecodedTextureBuffer(0, null,
|
| - droppedFrame.presentationTimeStampMs, droppedFrame.timeStampMs,
|
| - droppedFrame.ntpTimeStampMs, droppedFrame.decodeTimeMs,
|
| + return new DecodedTextureBuffer(0, null, droppedFrame.presentationTimeStampMs,
|
| + droppedFrame.timeStampMs, droppedFrame.ntpTimeStampMs, droppedFrame.decodeTimeMs,
|
| SystemClock.elapsedRealtime() - droppedFrame.endDecodeTimeMs);
|
| }
|
| return null;
|
|
|