Add option to disable particular HW video codec from app.
Plus minor clean up / adding comments. BUG=b/26695339 R=jiayl@webrtc.org Review URL: https://codereview.webrtc.org/1644253003 . Cr-Commit-Position: refs/heads/master@{#11431}
This commit is contained in:
parent
9dfed79f3f
commit
eee86a6aa3
@ -27,7 +27,6 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
@ -41,8 +40,10 @@ import org.webrtc.Logging;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -65,13 +66,19 @@ public class MediaCodecVideoDecoder {
|
||||
VIDEO_CODEC_H264
|
||||
}
|
||||
|
||||
private static final int DEQUEUE_INPUT_TIMEOUT = 500000; // 500 ms timeout.
|
||||
private static final int MEDIA_CODEC_RELEASE_TIMEOUT_MS = 5000; // Timeout for codec releasing.
|
||||
// Timeout for input buffer dequeue.
|
||||
private static final int DEQUEUE_INPUT_TIMEOUT = 500000;
|
||||
// Timeout for codec releasing.
|
||||
private static final int MEDIA_CODEC_RELEASE_TIMEOUT_MS = 5000;
|
||||
// Max number of output buffers queued before starting to drop decoded frames.
|
||||
private static final int MAX_QUEUED_OUTPUTBUFFERS = 3;
|
||||
// Active running decoder instance. Set in initDecode() (called from native code)
|
||||
// and reset to null in release() call.
|
||||
private static MediaCodecVideoDecoder runningInstance = null;
|
||||
private static MediaCodecVideoDecoderErrorCallback errorCallback = null;
|
||||
private static int codecErrors = 0;
|
||||
// List of disabled codec types - can be set from application.
|
||||
private static Set<String> hwDecoderDisabledTypes = new HashSet<String>();
|
||||
|
||||
private Thread mediaCodecThread;
|
||||
private MediaCodec mediaCodec;
|
||||
@ -110,8 +117,6 @@ public class MediaCodecVideoDecoder {
|
||||
|
||||
// The below variables are only used when decoding to a Surface.
|
||||
private TextureListener textureListener;
|
||||
// Max number of output buffers queued before starting to drop decoded frames.
|
||||
private static final int MAX_QUEUED_OUTPUTBUFFERS = 3;
|
||||
private int droppedFrames;
|
||||
private Surface surface = null;
|
||||
private final Queue<DecodedOutputBuffer>
|
||||
@ -129,7 +134,52 @@ public class MediaCodecVideoDecoder {
|
||||
MediaCodecVideoDecoder.errorCallback = errorCallback;
|
||||
}
|
||||
|
||||
// Helper struct for findVp8Decoder() below.
|
||||
// Functions to disable HW decoding - can be called from applications for platforms
|
||||
// which have known HW decoding problems.
|
||||
public static void disableVp8HwCodec() {
|
||||
Logging.w(TAG, "VP8 decoding is disabled by application.");
|
||||
hwDecoderDisabledTypes.add(VP8_MIME_TYPE);
|
||||
}
|
||||
|
||||
public static void disableVp9HwCodec() {
|
||||
Logging.w(TAG, "VP9 decoding is disabled by application.");
|
||||
hwDecoderDisabledTypes.add(VP9_MIME_TYPE);
|
||||
}
|
||||
|
||||
public static void disableH264HwCodec() {
|
||||
Logging.w(TAG, "H.264 decoding is disabled by application.");
|
||||
hwDecoderDisabledTypes.add(H264_MIME_TYPE);
|
||||
}
|
||||
|
||||
// Functions to query if HW decoding is supported.
|
||||
public static boolean isVp8HwSupported() {
|
||||
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);
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupported() {
|
||||
return !hwDecoderDisabledTypes.contains(H264_MIME_TYPE) &&
|
||||
(findDecoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes) != null);
|
||||
}
|
||||
|
||||
public static void printStackTrace() {
|
||||
if (runningInstance != null && runningInstance.mediaCodecThread != null) {
|
||||
StackTraceElement[] mediaCodecStackTraces = runningInstance.mediaCodecThread.getStackTrace();
|
||||
if (mediaCodecStackTraces.length > 0) {
|
||||
Logging.d(TAG, "MediaCodecVideoDecoder stacks trace:");
|
||||
for (StackTraceElement stackTrace : mediaCodecStackTraces) {
|
||||
Logging.d(TAG, stackTrace.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper struct for findDecoder() below.
|
||||
private static class DecoderProperties {
|
||||
public DecoderProperties(String codecName, int colorFormat) {
|
||||
this.codecName = codecName;
|
||||
@ -195,30 +245,6 @@ public class MediaCodecVideoDecoder {
|
||||
return null; // No HW decoder.
|
||||
}
|
||||
|
||||
public static boolean isVp8HwSupported() {
|
||||
return findDecoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes) != null;
|
||||
}
|
||||
|
||||
public static boolean isVp9HwSupported() {
|
||||
return findDecoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes) != null;
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupported() {
|
||||
return findDecoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes) != null;
|
||||
}
|
||||
|
||||
public static void printStackTrace() {
|
||||
if (runningInstance != null && runningInstance.mediaCodecThread != null) {
|
||||
StackTraceElement[] mediaCodecStackTraces = runningInstance.mediaCodecThread.getStackTrace();
|
||||
if (mediaCodecStackTraces.length > 0) {
|
||||
Logging.d(TAG, "MediaCodecVideoDecoder stacks trace:");
|
||||
for (StackTraceElement stackTrace : mediaCodecStackTraces) {
|
||||
Logging.d(TAG, stackTrace.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOnMediaCodecThread() throws IllegalStateException {
|
||||
if (mediaCodecThread.getId() != Thread.currentThread().getId()) {
|
||||
throw new IllegalStateException(
|
||||
@ -376,9 +402,12 @@ public class MediaCodecVideoDecoder {
|
||||
this.timeStampMs = timeStampMs;
|
||||
this.ntpTimeStampMs = ntpTimeStampMs;
|
||||
}
|
||||
private final long decodeStartTimeMs; // Time when this frame was queued for decoding.
|
||||
private final long timeStampMs; // Only used for bookkeeping in Java. Used in C++;
|
||||
private final long ntpTimeStampMs; // Only used for bookkeeping in Java. Used in C++;
|
||||
// Time when this frame was queued for decoding.
|
||||
private final long decodeStartTimeMs;
|
||||
// Only used for bookkeeping in Java. Stores C++ inputImage._timeStamp value for input frame.
|
||||
private final long timeStampMs;
|
||||
// Only used for bookkeeping in Java. Stores C++ inputImage.ntp_time_ms_ value for input frame.
|
||||
private final long ntpTimeStampMs;
|
||||
}
|
||||
|
||||
// Helper struct for dequeueOutputBuffer() below.
|
||||
@ -397,11 +426,13 @@ public class MediaCodecVideoDecoder {
|
||||
private final int index;
|
||||
private final int offset;
|
||||
private final int size;
|
||||
// C++ inputImage._timeStamp value for output frame.
|
||||
private final long timeStampMs;
|
||||
// C++ inputImage.ntp_time_ms_ value for output frame.
|
||||
private final long ntpTimeStampMs;
|
||||
// Number of ms it took to decode this frame.
|
||||
private final long decodeTimeMs;
|
||||
// System time when this frame finished decoding.
|
||||
// System time when this frame decoding finished.
|
||||
private final long endDecodeTimeMs;
|
||||
}
|
||||
|
||||
@ -409,8 +440,11 @@ public class MediaCodecVideoDecoder {
|
||||
private static class DecodedTextureBuffer {
|
||||
private final int textureID;
|
||||
private final float[] transformMatrix;
|
||||
// C++ inputImage._timeStamp value for output frame.
|
||||
private final long timeStampMs;
|
||||
// C++ inputImage.ntp_time_ms_ value for output frame.
|
||||
private final long ntpTimeStampMs;
|
||||
// Number of ms it took to decode this frame.
|
||||
private final long decodeTimeMs;
|
||||
// Interval from when the frame finished decoding until this buffer has been created.
|
||||
// Since there is only one texture, this interval depend on the time from when
|
||||
@ -614,8 +648,9 @@ public class MediaCodecVideoDecoder {
|
||||
// Logging.w(TAG, "Draining decoder. Dropping frame with TS: "
|
||||
// + droppedFrame.timeStampMs + ". Total number of dropped frames: " + droppedFrames);
|
||||
} else {
|
||||
Logging.w(TAG, "Too many output buffers. Dropping frame with TS: "
|
||||
+ droppedFrame.timeStampMs + ". Total number of dropped frames: " + droppedFrames);
|
||||
Logging.w(TAG, "Too many output buffers " + dequeuedSurfaceOutputBuffers.size() +
|
||||
". Dropping frame with TS: " + droppedFrame.timeStampMs +
|
||||
". Total number of dropped frames: " + droppedFrames);
|
||||
}
|
||||
|
||||
mediaCodec.releaseOutputBuffer(droppedFrame.index, false /* render */);
|
||||
|
||||
@ -42,7 +42,9 @@ import org.webrtc.Logging;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -72,6 +74,8 @@ public class MediaCodecVideoEncoder {
|
||||
private static MediaCodecVideoEncoder runningInstance = null;
|
||||
private static MediaCodecVideoEncoderErrorCallback errorCallback = null;
|
||||
private static int codecErrors = 0;
|
||||
// List of disabled codec types - can be set from application.
|
||||
private static Set<String> hwEncoderDisabledTypes = new HashSet<String>();
|
||||
|
||||
private Thread mediaCodecThread;
|
||||
private MediaCodec mediaCodec;
|
||||
@ -104,7 +108,6 @@ public class MediaCodecVideoEncoder {
|
||||
|
||||
// Bitrate modes - should be in sync with OMX_VIDEO_CONTROLRATETYPE defined
|
||||
// in OMX_Video.h
|
||||
private static final int VIDEO_ControlRateVariable = 1;
|
||||
private static final int VIDEO_ControlRateConstant = 2;
|
||||
// NV12 color format supported by QCOM codec, but not declared in MediaCodec -
|
||||
// see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
|
||||
@ -138,6 +141,54 @@ public class MediaCodecVideoEncoder {
|
||||
MediaCodecVideoEncoder.errorCallback = errorCallback;
|
||||
}
|
||||
|
||||
// Functions to disable HW encoding - can be called from applications for platforms
|
||||
// which have known HW decoding problems.
|
||||
public static void disableVp8HwCodec() {
|
||||
Logging.w(TAG, "VP8 encoding is disabled by application.");
|
||||
hwEncoderDisabledTypes.add(VP8_MIME_TYPE);
|
||||
}
|
||||
|
||||
public static void disableVp9HwCodec() {
|
||||
Logging.w(TAG, "VP9 encoding is disabled by application.");
|
||||
hwEncoderDisabledTypes.add(VP9_MIME_TYPE);
|
||||
}
|
||||
|
||||
public static void disableH264HwCodec() {
|
||||
Logging.w(TAG, "H.264 encoding is disabled by application.");
|
||||
hwEncoderDisabledTypes.add(H264_MIME_TYPE);
|
||||
}
|
||||
|
||||
// Functions to query if HW encoding is supported.
|
||||
public static boolean isVp8HwSupported() {
|
||||
return !hwEncoderDisabledTypes.contains(VP8_MIME_TYPE) &&
|
||||
(findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, supportedColorList) != null);
|
||||
}
|
||||
|
||||
public static boolean isVp9HwSupported() {
|
||||
return !hwEncoderDisabledTypes.contains(VP9_MIME_TYPE) &&
|
||||
(findHwEncoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes, supportedColorList) != null);
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupported() {
|
||||
return !hwEncoderDisabledTypes.contains(H264_MIME_TYPE) &&
|
||||
(findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes, supportedColorList) != null);
|
||||
}
|
||||
|
||||
public static boolean isVp8HwSupportedUsingTextures() {
|
||||
return !hwEncoderDisabledTypes.contains(VP8_MIME_TYPE) && (findHwEncoder(
|
||||
VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, supportedSurfaceColorList) != null);
|
||||
}
|
||||
|
||||
public static boolean isVp9HwSupportedUsingTextures() {
|
||||
return !hwEncoderDisabledTypes.contains(VP9_MIME_TYPE) && (findHwEncoder(
|
||||
VP9_MIME_TYPE, supportedVp9HwCodecPrefixes, supportedSurfaceColorList) != null);
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupportedUsingTextures() {
|
||||
return !hwEncoderDisabledTypes.contains(H264_MIME_TYPE) && (findHwEncoder(
|
||||
H264_MIME_TYPE, supportedH264HwCodecPrefixes, supportedSurfaceColorList) != null);
|
||||
}
|
||||
|
||||
// Helper struct for findHwEncoder() below.
|
||||
private static class EncoderProperties {
|
||||
public EncoderProperties(String codecName, int colorFormat) {
|
||||
@ -213,33 +264,6 @@ public class MediaCodecVideoEncoder {
|
||||
return null; // No HW encoder.
|
||||
}
|
||||
|
||||
public static boolean isVp8HwSupported() {
|
||||
return findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, supportedColorList) != null;
|
||||
}
|
||||
|
||||
public static boolean isVp9HwSupported() {
|
||||
return findHwEncoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes, supportedColorList) != null;
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupported() {
|
||||
return findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes, supportedColorList) != null;
|
||||
}
|
||||
|
||||
public static boolean isVp8HwSupportedUsingTextures() {
|
||||
return findHwEncoder(
|
||||
VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, supportedSurfaceColorList) != null;
|
||||
}
|
||||
|
||||
public static boolean isVp9HwSupportedUsingTextures() {
|
||||
return findHwEncoder(
|
||||
VP9_MIME_TYPE, supportedVp9HwCodecPrefixes, supportedSurfaceColorList) != null;
|
||||
}
|
||||
|
||||
public static boolean isH264HwSupportedUsingTextures() {
|
||||
return findHwEncoder(
|
||||
H264_MIME_TYPE, supportedH264HwCodecPrefixes, supportedSurfaceColorList) != null;
|
||||
}
|
||||
|
||||
private void checkOnMediaCodecThread() {
|
||||
if (mediaCodecThread.getId() != Thread.currentThread().getId()) {
|
||||
throw new RuntimeException(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user