Android: Remove use of EGLContexts in PeerConnectionFactory
Since the legacy video codecs seem to be around for some time more, we need to make them injectable and provide a migration path for clients that still use them so that we can clean up PeerConnectionFactory. This CL moves the creation of EglContexts into the legacy codec factories. Clients can then migrate to setEGLContext() instead of using setVideoHwAccelerationOptions(). Bug: webrtc:9502 Change-Id: I608607b32db73ce3df7704a061e66d9d53946af5 Reviewed-on: https://webrtc-review.googlesource.com/87941 Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23934}
This commit is contained in:
committed by
Commit Bot
parent
2234121cfb
commit
0f0e7a6f18
@ -278,7 +278,6 @@ generate_jni("generated_video_jni") {
|
|||||||
"api/org/webrtc/VideoSource.java",
|
"api/org/webrtc/VideoSource.java",
|
||||||
"api/org/webrtc/VideoTrack.java",
|
"api/org/webrtc/VideoTrack.java",
|
||||||
"api/org/webrtc/YuvHelper.java",
|
"api/org/webrtc/YuvHelper.java",
|
||||||
"src/java/org/webrtc/EglBase14.java",
|
|
||||||
"src/java/org/webrtc/NV12Buffer.java",
|
"src/java/org/webrtc/NV12Buffer.java",
|
||||||
"src/java/org/webrtc/NV21Buffer.java",
|
"src/java/org/webrtc/NV21Buffer.java",
|
||||||
"src/java/org/webrtc/NativeCapturerObserver.java",
|
"src/java/org/webrtc/NativeCapturerObserver.java",
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import org.webrtc.VideoFrame;
|
|||||||
// Java-side of peerconnection.cc:MediaCodecVideoDecoder.
|
// Java-side of peerconnection.cc:MediaCodecVideoDecoder.
|
||||||
// This class is an implementation detail of the Java PeerConnection API.
|
// This class is an implementation detail of the Java PeerConnection API.
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public class MediaCodecVideoDecoder {
|
public class MediaCodecVideoDecoder {
|
||||||
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
||||||
// so the class and its methods have non-public visibility. The API this
|
// so the class and its methods have non-public visibility. The API this
|
||||||
@ -79,6 +80,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
private static int codecErrors = 0;
|
private static int codecErrors = 0;
|
||||||
// List of disabled codec types - can be set from application.
|
// List of disabled codec types - can be set from application.
|
||||||
private static Set<String> hwDecoderDisabledTypes = new HashSet<String>();
|
private static Set<String> hwDecoderDisabledTypes = new HashSet<String>();
|
||||||
|
@Nullable private static EglBase eglBase;
|
||||||
|
|
||||||
@Nullable private Thread mediaCodecThread;
|
@Nullable private Thread mediaCodecThread;
|
||||||
@Nullable private MediaCodec mediaCodec;
|
@Nullable private MediaCodec mediaCodec;
|
||||||
@ -141,7 +143,6 @@ public class MediaCodecVideoDecoder {
|
|||||||
private int sliceHeight;
|
private int sliceHeight;
|
||||||
private boolean hasDecodedFirstFrame;
|
private boolean hasDecodedFirstFrame;
|
||||||
private final Queue<TimeStamps> decodeStartTimeMs = new ArrayDeque<TimeStamps>();
|
private final Queue<TimeStamps> decodeStartTimeMs = new ArrayDeque<TimeStamps>();
|
||||||
private boolean useSurface;
|
|
||||||
|
|
||||||
// The below variables are only used when decoding to a Surface.
|
// The below variables are only used when decoding to a Surface.
|
||||||
@Nullable private TextureListener textureListener;
|
@Nullable private TextureListener textureListener;
|
||||||
@ -157,6 +158,28 @@ public class MediaCodecVideoDecoder {
|
|||||||
void onMediaCodecVideoDecoderCriticalError(int codecErrors);
|
void onMediaCodecVideoDecoderCriticalError(int codecErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set EGL context used by HW decoding. The EGL context must be shared with the remote render. */
|
||||||
|
public static void setEglContext(EglBase.Context eglContext) {
|
||||||
|
if (eglBase != null) {
|
||||||
|
Logging.w(TAG, "Egl context already set.");
|
||||||
|
eglBase.release();
|
||||||
|
}
|
||||||
|
eglBase = EglBase.create(eglContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dispose the EGL context used by HW decoding. */
|
||||||
|
public static void disposeEglContext() {
|
||||||
|
if (eglBase != null) {
|
||||||
|
eglBase.release();
|
||||||
|
eglBase = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CalledByNative
|
||||||
|
static boolean useSurface() {
|
||||||
|
return eglBase != null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void setErrorCallback(MediaCodecVideoDecoderErrorCallback errorCallback) {
|
public static void setErrorCallback(MediaCodecVideoDecoderErrorCallback errorCallback) {
|
||||||
Logging.d(TAG, "Set error callback");
|
Logging.d(TAG, "Set error callback");
|
||||||
MediaCodecVideoDecoder.errorCallback = errorCallback;
|
MediaCodecVideoDecoder.errorCallback = errorCallback;
|
||||||
@ -323,16 +346,13 @@ public class MediaCodecVideoDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass null in |eglContext| to configure the codec for ByteBuffer output.
|
|
||||||
@CalledByNativeUnchecked
|
@CalledByNativeUnchecked
|
||||||
private boolean initDecode(
|
private boolean initDecode(VideoCodecType type, int width, int height) {
|
||||||
VideoCodecType type, int width, int height, @Nullable EglBase.Context eglContext) {
|
|
||||||
if (mediaCodecThread != null) {
|
if (mediaCodecThread != null) {
|
||||||
throw new RuntimeException("initDecode: Forgot to release()?");
|
throw new RuntimeException("initDecode: Forgot to release()?");
|
||||||
}
|
}
|
||||||
|
|
||||||
String mime = null;
|
String mime = null;
|
||||||
useSurface = (eglContext != null);
|
|
||||||
String[] supportedCodecPrefixes = null;
|
String[] supportedCodecPrefixes = null;
|
||||||
if (type == VideoCodecType.VIDEO_CODEC_VP8) {
|
if (type == VideoCodecType.VIDEO_CODEC_VP8) {
|
||||||
mime = VP8_MIME_TYPE;
|
mime = VP8_MIME_TYPE;
|
||||||
@ -351,8 +371,9 @@ public class MediaCodecVideoDecoder {
|
|||||||
throw new RuntimeException("Cannot find HW decoder for " + type);
|
throw new RuntimeException("Cannot find HW decoder for " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.d(TAG, "Java initDecode: " + type + " : " + width + " x " + height + ". Color: 0x"
|
Logging.d(TAG,
|
||||||
+ Integer.toHexString(properties.colorFormat) + ". Use Surface: " + useSurface);
|
"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.
|
runningInstance = this; // Decoder is now running and can be queried for stack traces.
|
||||||
mediaCodecThread = Thread.currentThread();
|
mediaCodecThread = Thread.currentThread();
|
||||||
@ -362,10 +383,10 @@ public class MediaCodecVideoDecoder {
|
|||||||
stride = width;
|
stride = width;
|
||||||
sliceHeight = height;
|
sliceHeight = height;
|
||||||
|
|
||||||
if (useSurface) {
|
if (useSurface()) {
|
||||||
@Nullable
|
@Nullable
|
||||||
final SurfaceTextureHelper surfaceTextureHelper =
|
final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
|
||||||
SurfaceTextureHelper.create("Decoder SurfaceTextureHelper", eglContext);
|
"Decoder SurfaceTextureHelper", eglBase.getEglBaseContext());
|
||||||
if (surfaceTextureHelper != null) {
|
if (surfaceTextureHelper != null) {
|
||||||
textureListener = new TextureListener(surfaceTextureHelper);
|
textureListener = new TextureListener(surfaceTextureHelper);
|
||||||
textureListener.setSize(width, height);
|
textureListener.setSize(width, height);
|
||||||
@ -374,7 +395,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
|
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
|
||||||
if (!useSurface) {
|
if (!useSurface()) {
|
||||||
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
|
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
|
||||||
}
|
}
|
||||||
Logging.d(TAG, " Format: " + format);
|
Logging.d(TAG, " Format: " + format);
|
||||||
@ -461,7 +482,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
mediaCodec = null;
|
mediaCodec = null;
|
||||||
mediaCodecThread = null;
|
mediaCodecThread = null;
|
||||||
runningInstance = null;
|
runningInstance = null;
|
||||||
if (useSurface) {
|
if (useSurface()) {
|
||||||
surface.release();
|
surface.release();
|
||||||
surface = null;
|
surface = null;
|
||||||
textureListener.release();
|
textureListener.release();
|
||||||
@ -773,7 +794,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
textureListener.setSize(width, height);
|
textureListener.setSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
|
if (!useSurface() && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
|
||||||
colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
|
colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
|
||||||
Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
|
Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
|
||||||
if (!supportedColorList.contains(colorFormat)) {
|
if (!supportedColorList.contains(colorFormat)) {
|
||||||
@ -817,7 +838,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
@CalledByNativeUnchecked
|
@CalledByNativeUnchecked
|
||||||
private @Nullable DecodedTextureBuffer dequeueTextureBuffer(int dequeueTimeoutMs) {
|
private @Nullable DecodedTextureBuffer dequeueTextureBuffer(int dequeueTimeoutMs) {
|
||||||
checkOnMediaCodecThread();
|
checkOnMediaCodecThread();
|
||||||
if (!useSurface) {
|
if (!useSurface()) {
|
||||||
throw new IllegalStateException("dequeueTexture() called for byte buffer decoding.");
|
throw new IllegalStateException("dequeueTexture() called for byte buffer decoding.");
|
||||||
}
|
}
|
||||||
DecodedOutputBuffer outputBuffer = dequeueOutputBuffer(dequeueTimeoutMs);
|
DecodedOutputBuffer outputBuffer = dequeueOutputBuffer(dequeueTimeoutMs);
|
||||||
@ -881,7 +902,7 @@ public class MediaCodecVideoDecoder {
|
|||||||
private void returnDecodedOutputBuffer(int index)
|
private void returnDecodedOutputBuffer(int index)
|
||||||
throws IllegalStateException, MediaCodec.CodecException {
|
throws IllegalStateException, MediaCodec.CodecException {
|
||||||
checkOnMediaCodecThread();
|
checkOnMediaCodecThread();
|
||||||
if (useSurface) {
|
if (useSurface()) {
|
||||||
throw new IllegalStateException("returnDecodedOutputBuffer() called for surface decoding.");
|
throw new IllegalStateException("returnDecodedOutputBuffer() called for surface decoding.");
|
||||||
}
|
}
|
||||||
mediaCodec.releaseOutputBuffer(index, false /* render */);
|
mediaCodec.releaseOutputBuffer(index, false /* render */);
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import org.webrtc.EglBase;
|
||||||
import org.webrtc.EglBase14;
|
import org.webrtc.EglBase14;
|
||||||
import org.webrtc.VideoFrame;
|
import org.webrtc.VideoFrame;
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ import org.webrtc.VideoFrame;
|
|||||||
// This class is an implementation detail of the Java PeerConnection API.
|
// This class is an implementation detail of the Java PeerConnection API.
|
||||||
@TargetApi(19)
|
@TargetApi(19)
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public class MediaCodecVideoEncoder {
|
public class MediaCodecVideoEncoder {
|
||||||
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
||||||
// so the class and its methods have non-public visibility. The API this
|
// so the class and its methods have non-public visibility. The API this
|
||||||
@ -79,6 +81,7 @@ public class MediaCodecVideoEncoder {
|
|||||||
private static int codecErrors = 0;
|
private static int codecErrors = 0;
|
||||||
// List of disabled codec types - can be set from application.
|
// List of disabled codec types - can be set from application.
|
||||||
private static Set<String> hwEncoderDisabledTypes = new HashSet<String>();
|
private static Set<String> hwEncoderDisabledTypes = new HashSet<String>();
|
||||||
|
@Nullable private static EglBase staticEglBase;
|
||||||
|
|
||||||
@Nullable private Thread mediaCodecThread;
|
@Nullable private Thread mediaCodecThread;
|
||||||
@Nullable private MediaCodec mediaCodec;
|
@Nullable private MediaCodec mediaCodec;
|
||||||
@ -147,6 +150,36 @@ public class MediaCodecVideoEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set EGL context used by HW encoding. The EGL context must be shared with the video capturer
|
||||||
|
* and any local render.
|
||||||
|
*/
|
||||||
|
public static void setEglContext(EglBase.Context eglContext) {
|
||||||
|
if (staticEglBase != null) {
|
||||||
|
Logging.w(TAG, "Egl context already set.");
|
||||||
|
staticEglBase.release();
|
||||||
|
}
|
||||||
|
staticEglBase = EglBase.create(eglContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dispose the EGL context used by HW encoding. */
|
||||||
|
public static void disposeEglContext() {
|
||||||
|
if (staticEglBase != null) {
|
||||||
|
staticEglBase.release();
|
||||||
|
staticEglBase = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static EglBase.Context getEglContext() {
|
||||||
|
return staticEglBase == null ? null : staticEglBase.getEglBaseContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CalledByNative
|
||||||
|
static boolean hasEgl14Context() {
|
||||||
|
return staticEglBase instanceof EglBase14;
|
||||||
|
}
|
||||||
|
|
||||||
// List of supported HW VP8 encoders.
|
// List of supported HW VP8 encoders.
|
||||||
private static final MediaCodecProperties qcomVp8HwProperties = new MediaCodecProperties(
|
private static final MediaCodecProperties qcomVp8HwProperties = new MediaCodecProperties(
|
||||||
"OMX.qcom.", Build.VERSION_CODES.KITKAT, BitrateAdjustmentType.NO_ADJUSTMENT);
|
"OMX.qcom.", Build.VERSION_CODES.KITKAT, BitrateAdjustmentType.NO_ADJUSTMENT);
|
||||||
@ -446,8 +479,7 @@ public class MediaCodecVideoEncoder {
|
|||||||
|
|
||||||
@CalledByNativeUnchecked
|
@CalledByNativeUnchecked
|
||||||
boolean initEncode(VideoCodecType type, int profile, int width, int height, int kbps, int fps,
|
boolean initEncode(VideoCodecType type, int profile, int width, int height, int kbps, int fps,
|
||||||
@Nullable EglBase14.Context sharedContext) {
|
boolean useSurface) {
|
||||||
final boolean useSurface = sharedContext != null;
|
|
||||||
Logging.d(TAG,
|
Logging.d(TAG,
|
||||||
"Java initEncode: " + type + ". Profile: " + profile + " : " + width + " x " + height
|
"Java initEncode: " + type + ". Profile: " + profile + " : " + width + " x " + height
|
||||||
+ ". @ " + kbps + " kbps. Fps: " + fps + ". Encode from texture : " + useSurface);
|
+ ". @ " + kbps + " kbps. Fps: " + fps + ". Encode from texture : " + useSurface);
|
||||||
@ -548,7 +580,7 @@ public class MediaCodecVideoEncoder {
|
|||||||
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
|
||||||
|
|
||||||
if (useSurface) {
|
if (useSurface) {
|
||||||
eglBase = new EglBase14(sharedContext, EglBase.CONFIG_RECORDABLE);
|
eglBase = new EglBase14((EglBase14.Context) getEglContext(), EglBase.CONFIG_RECORDABLE);
|
||||||
// Create an input surface and keep a reference since we must release the surface when done.
|
// Create an input surface and keep a reference since we must release the surface when done.
|
||||||
inputSurface = mediaCodec.createInputSurface();
|
inputSurface = mediaCodec.createInputSurface();
|
||||||
eglBase.createSurface(inputSurface);
|
eglBase.createSurface(inputSurface);
|
||||||
|
|||||||
@ -33,8 +33,6 @@ public class PeerConnectionFactory {
|
|||||||
@Nullable private static Thread networkThread;
|
@Nullable private static Thread networkThread;
|
||||||
@Nullable private static Thread workerThread;
|
@Nullable private static Thread workerThread;
|
||||||
@Nullable private static Thread signalingThread;
|
@Nullable private static Thread signalingThread;
|
||||||
private EglBase localEglbase;
|
|
||||||
private EglBase remoteEglbase;
|
|
||||||
|
|
||||||
public static class InitializationOptions {
|
public static class InitializationOptions {
|
||||||
final Context applicationContext;
|
final Context applicationContext;
|
||||||
@ -88,6 +86,8 @@ public class PeerConnectionFactory {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated, this method only affects the deprecated HW codecs and not the new ones.
|
||||||
|
@Deprecated
|
||||||
public Builder setEnableVideoHwAcceleration(boolean enableVideoHwAcceleration) {
|
public Builder setEnableVideoHwAcceleration(boolean enableVideoHwAcceleration) {
|
||||||
this.enableVideoHwAcceleration = enableVideoHwAcceleration;
|
this.enableVideoHwAcceleration = enableVideoHwAcceleration;
|
||||||
return this;
|
return this;
|
||||||
@ -365,10 +365,8 @@ public class PeerConnectionFactory {
|
|||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public VideoSource createVideoSource(VideoCapturer capturer) {
|
public VideoSource createVideoSource(VideoCapturer capturer) {
|
||||||
final EglBase.Context eglContext =
|
final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
|
||||||
localEglbase == null ? null : localEglbase.getEglBaseContext();
|
VIDEO_CAPTURER_THREAD_NAME, MediaCodecVideoEncoder.getEglContext());
|
||||||
final SurfaceTextureHelper surfaceTextureHelper =
|
|
||||||
SurfaceTextureHelper.create(VIDEO_CAPTURER_THREAD_NAME, eglContext);
|
|
||||||
final VideoSource videoSource = new VideoSource(
|
final VideoSource videoSource = new VideoSource(
|
||||||
nativeCreateVideoSource(nativeFactory, capturer.isScreencast()), surfaceTextureHelper);
|
nativeCreateVideoSource(nativeFactory, capturer.isScreencast()), surfaceTextureHelper);
|
||||||
capturer.initialize(surfaceTextureHelper, ContextUtils.getApplicationContext(),
|
capturer.initialize(surfaceTextureHelper, ContextUtils.getApplicationContext(),
|
||||||
@ -401,26 +399,20 @@ public class PeerConnectionFactory {
|
|||||||
nativeStopAecDump(nativeFactory);
|
nativeStopAecDump(nativeFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the EGL context used by HW Video encoding and decoding.
|
/**
|
||||||
|
* Set the EGL context used by HW Video encoding and decoding.
|
||||||
*
|
*
|
||||||
* @param localEglContext Must be the same as used by VideoCapturerAndroid and any local video
|
* @param localEglContext Must be the same as used by VideoCapturerAndroid and any local video
|
||||||
* renderer.
|
* renderer.
|
||||||
* @param remoteEglContext Must be the same as used by any remote video renderer.
|
* @param remoteEglContext Must be the same as used by any remote video renderer.
|
||||||
|
* @deprecated Use new HW video encoded/decoder instead, and use createVideoSource(boolean
|
||||||
|
* isScreencast) instead of createVideoSource(VideoCapturer).
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setVideoHwAccelerationOptions(
|
public void setVideoHwAccelerationOptions(
|
||||||
EglBase.Context localEglContext, EglBase.Context remoteEglContext) {
|
EglBase.Context localEglContext, EglBase.Context remoteEglContext) {
|
||||||
if (localEglbase != null) {
|
MediaCodecVideoEncoder.setEglContext(localEglContext);
|
||||||
Logging.w(TAG, "Egl context already set.");
|
MediaCodecVideoDecoder.setEglContext(remoteEglContext);
|
||||||
localEglbase.release();
|
|
||||||
}
|
|
||||||
if (remoteEglbase != null) {
|
|
||||||
Logging.w(TAG, "Egl context already set.");
|
|
||||||
remoteEglbase.release();
|
|
||||||
}
|
|
||||||
localEglbase = EglBase.create(localEglContext);
|
|
||||||
remoteEglbase = EglBase.create(remoteEglContext);
|
|
||||||
nativeSetVideoHwAccelerationOptions(
|
|
||||||
nativeFactory, localEglbase.getEglBaseContext(), remoteEglbase.getEglBaseContext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
@ -428,10 +420,8 @@ public class PeerConnectionFactory {
|
|||||||
networkThread = null;
|
networkThread = null;
|
||||||
workerThread = null;
|
workerThread = null;
|
||||||
signalingThread = null;
|
signalingThread = null;
|
||||||
if (localEglbase != null)
|
MediaCodecVideoEncoder.disposeEglContext();
|
||||||
localEglbase.release();
|
MediaCodecVideoDecoder.disposeEglContext();
|
||||||
if (remoteEglbase != null)
|
|
||||||
remoteEglbase.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void threadsCallbacks() {
|
public void threadsCallbacks() {
|
||||||
@ -510,8 +500,6 @@ public class PeerConnectionFactory {
|
|||||||
private static native boolean nativeStartAecDump(
|
private static native boolean nativeStartAecDump(
|
||||||
long factory, int file_descriptor, int filesize_limit_bytes);
|
long factory, int file_descriptor, int filesize_limit_bytes);
|
||||||
private static native void nativeStopAecDump(long factory);
|
private static native void nativeStopAecDump(long factory);
|
||||||
private static native void nativeSetVideoHwAccelerationOptions(
|
|
||||||
long factory, Object localEGLContext, Object remoteEGLContext);
|
|
||||||
private static native void nativeInvokeThreadsCallbacks(long factory);
|
private static native void nativeInvokeThreadsCallbacks(long factory);
|
||||||
private static native void nativeFreeFactory(long factory);
|
private static native void nativeFreeFactory(long factory);
|
||||||
private static native long nativeGetNativePeerConnectionFactory(long factory);
|
private static native long nativeGetNativePeerConnectionFactory(long factory);
|
||||||
|
|||||||
@ -40,8 +40,8 @@ public class MediaCodecVideoEncoderTest {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
||||||
assertTrue(encoder.initEncode(
|
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
||||||
MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile, 640, 480, 300, 30, null));
|
640, 480, 300, 30, /* useSurface= */ false));
|
||||||
encoder.release();
|
encoder.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,10 +53,12 @@ public class MediaCodecVideoEncoderTest {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
|
EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
|
||||||
|
MediaCodecVideoEncoder.setEglContext(eglBase.getEglBaseContext());
|
||||||
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
||||||
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
||||||
640, 480, 300, 30, eglBase.getEglBaseContext()));
|
640, 480, 300, 30, /* useSurface= */ true));
|
||||||
encoder.release();
|
encoder.release();
|
||||||
|
MediaCodecVideoEncoder.disposeEglContext();
|
||||||
eglBase.release();
|
eglBase.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,13 +70,15 @@ public class MediaCodecVideoEncoderTest {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
||||||
assertTrue(encoder.initEncode(
|
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
||||||
MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile, 640, 480, 300, 30, null));
|
640, 480, 300, 30, /* useSurface= */ false));
|
||||||
encoder.release();
|
encoder.release();
|
||||||
EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
|
EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
|
||||||
|
MediaCodecVideoEncoder.setEglContext(eglBase.getEglBaseContext());
|
||||||
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
||||||
640, 480, 300, 30, eglBase.getEglBaseContext()));
|
640, 480, 300, 30, /* useSurface= */ true));
|
||||||
encoder.release();
|
encoder.release();
|
||||||
|
MediaCodecVideoEncoder.disposeEglContext();
|
||||||
eglBase.release();
|
eglBase.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ public class MediaCodecVideoEncoderTest {
|
|||||||
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
|
||||||
|
|
||||||
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
assertTrue(encoder.initEncode(MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, profile,
|
||||||
width, height, 300, 30, null));
|
width, height, 300, 30, /* useSurface= */ false));
|
||||||
ByteBuffer[] inputBuffers = encoder.getInputBuffers();
|
ByteBuffer[] inputBuffers = encoder.getInputBuffers();
|
||||||
assertNotNull(inputBuffers);
|
assertNotNull(inputBuffers);
|
||||||
assertTrue(min_size <= inputBuffers[0].capacity());
|
assertTrue(min_size <= inputBuffers[0].capacity());
|
||||||
|
|||||||
@ -61,11 +61,6 @@ class EglBase14 implements EglBase {
|
|||||||
public Context(android.opengl.EGLContext eglContext) {
|
public Context(android.opengl.EGLContext eglContext) {
|
||||||
this.egl14Context = eglContext;
|
this.egl14Context = eglContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@CalledByNative("Context")
|
|
||||||
static boolean isEgl14Context(EglBase.Context context) {
|
|
||||||
return context instanceof EglBase14.Context;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new context with the specified config type, sharing data with sharedContext.
|
// Create a new context with the specified config type, sharing data with sharedContext.
|
||||||
|
|||||||
@ -64,7 +64,7 @@ class MediaCodecVideoDecoder : public VideoDecoder, public rtc::MessageHandler {
|
|||||||
public:
|
public:
|
||||||
explicit MediaCodecVideoDecoder(JNIEnv* jni,
|
explicit MediaCodecVideoDecoder(JNIEnv* jni,
|
||||||
VideoCodecType codecType,
|
VideoCodecType codecType,
|
||||||
jobject render_egl_context);
|
bool use_surface);
|
||||||
~MediaCodecVideoDecoder() override;
|
~MediaCodecVideoDecoder() override;
|
||||||
|
|
||||||
int32_t InitDecode(const VideoCodec* codecSettings,
|
int32_t InitDecode(const VideoCodec* codecSettings,
|
||||||
@ -105,14 +105,10 @@ class MediaCodecVideoDecoder : public VideoDecoder, public rtc::MessageHandler {
|
|||||||
// Type of video codec.
|
// Type of video codec.
|
||||||
VideoCodecType codecType_;
|
VideoCodecType codecType_;
|
||||||
|
|
||||||
// Render EGL context - owned by factory, should not be allocated/destroyed
|
|
||||||
// by VideoDecoder.
|
|
||||||
jobject render_egl_context_;
|
|
||||||
|
|
||||||
bool key_frame_required_;
|
bool key_frame_required_;
|
||||||
bool inited_;
|
bool inited_;
|
||||||
bool sw_fallback_required_;
|
bool sw_fallback_required_;
|
||||||
bool use_surface_;
|
const bool use_surface_;
|
||||||
VideoCodec codec_;
|
VideoCodec codec_;
|
||||||
I420BufferPool decoded_frame_pool_;
|
I420BufferPool decoded_frame_pool_;
|
||||||
DecodedImageCallback* callback_;
|
DecodedImageCallback* callback_;
|
||||||
@ -141,12 +137,12 @@ class MediaCodecVideoDecoder : public VideoDecoder, public rtc::MessageHandler {
|
|||||||
|
|
||||||
MediaCodecVideoDecoder::MediaCodecVideoDecoder(JNIEnv* jni,
|
MediaCodecVideoDecoder::MediaCodecVideoDecoder(JNIEnv* jni,
|
||||||
VideoCodecType codecType,
|
VideoCodecType codecType,
|
||||||
jobject render_egl_context)
|
bool use_surface)
|
||||||
: codecType_(codecType),
|
: codecType_(codecType),
|
||||||
render_egl_context_(render_egl_context),
|
|
||||||
key_frame_required_(true),
|
key_frame_required_(true),
|
||||||
inited_(false),
|
inited_(false),
|
||||||
sw_fallback_required_(false),
|
sw_fallback_required_(false),
|
||||||
|
use_surface_(use_surface),
|
||||||
codec_thread_(Thread::Create()),
|
codec_thread_(Thread::Create()),
|
||||||
j_media_codec_video_decoder_(
|
j_media_codec_video_decoder_(
|
||||||
jni,
|
jni,
|
||||||
@ -154,7 +150,6 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(JNIEnv* jni,
|
|||||||
codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
|
codec_thread_->SetName("MediaCodecVideoDecoder", NULL);
|
||||||
RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder";
|
RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoDecoder";
|
||||||
|
|
||||||
use_surface_ = (render_egl_context_ != NULL);
|
|
||||||
ALOGD << "MediaCodecVideoDecoder ctor. Use surface: " << use_surface_;
|
ALOGD << "MediaCodecVideoDecoder ctor. Use surface: " << use_surface_;
|
||||||
memset(&codec_, 0, sizeof(codec_));
|
memset(&codec_, 0, sizeof(codec_));
|
||||||
AllowBlockingCalls();
|
AllowBlockingCalls();
|
||||||
@ -228,10 +223,9 @@ int32_t MediaCodecVideoDecoder::InitDecodeOnCodecThread() {
|
|||||||
|
|
||||||
ScopedJavaLocalRef<jobject> j_video_codec_enum =
|
ScopedJavaLocalRef<jobject> j_video_codec_enum =
|
||||||
Java_VideoCodecType_fromNativeIndex(jni, codecType_);
|
Java_VideoCodecType_fromNativeIndex(jni, codecType_);
|
||||||
jobject j_egl_context = use_surface_ ? render_egl_context_ : nullptr;
|
|
||||||
bool success = Java_MediaCodecVideoDecoder_initDecode(
|
bool success = Java_MediaCodecVideoDecoder_initDecode(
|
||||||
jni, j_media_codec_video_decoder_, j_video_codec_enum, codec_.width,
|
jni, j_media_codec_video_decoder_, j_video_codec_enum, codec_.width,
|
||||||
codec_.height, JavaParamRef<jobject>(j_egl_context));
|
codec_.height);
|
||||||
|
|
||||||
if (CheckException(jni) || !success) {
|
if (CheckException(jni) || !success) {
|
||||||
ALOGE << "Codec initialization error - fallback to SW codec.";
|
ALOGE << "Codec initialization error - fallback to SW codec.";
|
||||||
@ -779,8 +773,7 @@ void MediaCodecVideoDecoder::OnMessage(rtc::Message* msg) {
|
|||||||
codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
|
codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory()
|
MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() {
|
||||||
: egl_context_(nullptr) {
|
|
||||||
ALOGD << "MediaCodecVideoDecoderFactory ctor";
|
ALOGD << "MediaCodecVideoDecoderFactory ctor";
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
@ -807,23 +800,6 @@ MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory()
|
|||||||
|
|
||||||
MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {
|
MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() {
|
||||||
ALOGD << "MediaCodecVideoDecoderFactory dtor";
|
ALOGD << "MediaCodecVideoDecoderFactory dtor";
|
||||||
if (egl_context_) {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
jni->DeleteGlobalRef(egl_context_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MediaCodecVideoDecoderFactory::SetEGLContext(JNIEnv* jni,
|
|
||||||
jobject egl_context) {
|
|
||||||
ALOGD << "MediaCodecVideoDecoderFactory::SetEGLContext";
|
|
||||||
if (egl_context_) {
|
|
||||||
jni->DeleteGlobalRef(egl_context_);
|
|
||||||
egl_context_ = nullptr;
|
|
||||||
}
|
|
||||||
egl_context_ = jni->NewGlobalRef(egl_context);
|
|
||||||
if (CheckException(jni)) {
|
|
||||||
ALOGE << "error calling NewGlobalRef for EGL Context.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SdpVideoFormat> MediaCodecVideoDecoderFactory::GetSupportedFormats()
|
std::vector<SdpVideoFormat> MediaCodecVideoDecoderFactory::GetSupportedFormats()
|
||||||
@ -843,7 +819,8 @@ std::unique_ptr<VideoDecoder> MediaCodecVideoDecoderFactory::CreateVideoDecoder(
|
|||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
return rtc::MakeUnique<MediaCodecVideoDecoder>(
|
return rtc::MakeUnique<MediaCodecVideoDecoder>(
|
||||||
jni, PayloadStringToCodecType(format.name), egl_context_);
|
jni, PayloadStringToCodecType(format.name),
|
||||||
|
Java_MediaCodecVideoDecoder_useSurface(jni));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ALOGW << "Can not find HW video decoder for type " << format.name;
|
ALOGW << "Can not find HW video decoder for type " << format.name;
|
||||||
|
|||||||
@ -25,8 +25,6 @@ class MediaCodecVideoDecoderFactory : public VideoDecoderFactory {
|
|||||||
MediaCodecVideoDecoderFactory();
|
MediaCodecVideoDecoderFactory();
|
||||||
~MediaCodecVideoDecoderFactory() override;
|
~MediaCodecVideoDecoderFactory() override;
|
||||||
|
|
||||||
void SetEGLContext(JNIEnv* jni, jobject render_egl_context);
|
|
||||||
|
|
||||||
// VideoDecoderFactory implementation.
|
// VideoDecoderFactory implementation.
|
||||||
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
|
std::vector<SdpVideoFormat> GetSupportedFormats() const override;
|
||||||
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
|
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
|
||||||
@ -35,7 +33,6 @@ class MediaCodecVideoDecoderFactory : public VideoDecoderFactory {
|
|||||||
static bool IsH264HighProfileSupported(JNIEnv* env);
|
static bool IsH264HighProfileSupported(JNIEnv* env);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
jobject egl_context_;
|
|
||||||
std::vector<SdpVideoFormat> supported_formats_;
|
std::vector<SdpVideoFormat> supported_formats_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -98,7 +98,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
|||||||
~MediaCodecVideoEncoder() override;
|
~MediaCodecVideoEncoder() override;
|
||||||
MediaCodecVideoEncoder(JNIEnv* jni,
|
MediaCodecVideoEncoder(JNIEnv* jni,
|
||||||
const SdpVideoFormat& format,
|
const SdpVideoFormat& format,
|
||||||
jobject egl_context);
|
bool has_egl_context);
|
||||||
|
|
||||||
// VideoEncoder implementation.
|
// VideoEncoder implementation.
|
||||||
int32_t InitEncode(const VideoCodec* codec_settings,
|
int32_t InitEncode(const VideoCodec* codec_settings,
|
||||||
@ -115,7 +115,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
|||||||
int32_t SetRateAllocation(const VideoBitrateAllocation& rate_allocation,
|
int32_t SetRateAllocation(const VideoBitrateAllocation& rate_allocation,
|
||||||
uint32_t frame_rate) override;
|
uint32_t frame_rate) override;
|
||||||
|
|
||||||
bool SupportsNativeHandle() const override { return egl_context_ != nullptr; }
|
bool SupportsNativeHandle() const override { return has_egl_context_; }
|
||||||
const char* ImplementationName() const override;
|
const char* ImplementationName() const override;
|
||||||
|
|
||||||
// Fills the input buffer with data from the buffers passed as parameters.
|
// Fills the input buffer with data from the buffers passed as parameters.
|
||||||
@ -275,9 +275,7 @@ class MediaCodecVideoEncoder : public VideoEncoder {
|
|||||||
// non-flexible VP9 mode.
|
// non-flexible VP9 mode.
|
||||||
size_t gof_idx_;
|
size_t gof_idx_;
|
||||||
|
|
||||||
// EGL context - owned by factory, should not be allocated/destroyed
|
const bool has_egl_context_;
|
||||||
// by MediaCodecVideoEncoder.
|
|
||||||
jobject egl_context_;
|
|
||||||
|
|
||||||
// Temporary fix for VP8.
|
// Temporary fix for VP8.
|
||||||
// Sends a key frame if frames are largely spaced apart (possibly
|
// Sends a key frame if frames are largely spaced apart (possibly
|
||||||
@ -302,7 +300,7 @@ MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
|
|||||||
|
|
||||||
MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni,
|
MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni,
|
||||||
const SdpVideoFormat& format,
|
const SdpVideoFormat& format,
|
||||||
jobject egl_context)
|
bool has_egl_context)
|
||||||
: format_(format),
|
: format_(format),
|
||||||
callback_(NULL),
|
callback_(NULL),
|
||||||
j_media_codec_video_encoder_(
|
j_media_codec_video_encoder_(
|
||||||
@ -310,7 +308,7 @@ MediaCodecVideoEncoder::MediaCodecVideoEncoder(JNIEnv* jni,
|
|||||||
Java_MediaCodecVideoEncoder_Constructor(jni)),
|
Java_MediaCodecVideoEncoder_Constructor(jni)),
|
||||||
inited_(false),
|
inited_(false),
|
||||||
use_surface_(false),
|
use_surface_(false),
|
||||||
egl_context_(egl_context),
|
has_egl_context_(has_egl_context),
|
||||||
sw_fallback_required_(false) {
|
sw_fallback_required_(false) {
|
||||||
encoder_queue_checker_.Detach();
|
encoder_queue_checker_.Detach();
|
||||||
}
|
}
|
||||||
@ -361,7 +359,7 @@ int32_t MediaCodecVideoEncoder::InitEncode(const VideoCodec* codec_settings,
|
|||||||
return InitEncodeInternal(
|
return InitEncodeInternal(
|
||||||
init_width, init_height, codec_settings->startBitrate,
|
init_width, init_height, codec_settings->startBitrate,
|
||||||
codec_settings->maxFramerate,
|
codec_settings->maxFramerate,
|
||||||
codec_settings->expect_encode_from_texture && (egl_context_ != nullptr));
|
codec_settings->expect_encode_from_texture && has_egl_context_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */,
|
int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */,
|
||||||
@ -475,7 +473,7 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
|||||||
if (sw_fallback_required_) {
|
if (sw_fallback_required_) {
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return WEBRTC_VIDEO_CODEC_OK;
|
||||||
}
|
}
|
||||||
RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set.";
|
RTC_CHECK(!use_surface || has_egl_context_) << "EGL context not set.";
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
|
|
||||||
@ -522,8 +520,8 @@ int32_t MediaCodecVideoEncoder::InitEncodeInternal(int width,
|
|||||||
Java_VideoCodecType_fromNativeIndex(jni, codec_type);
|
Java_VideoCodecType_fromNativeIndex(jni, codec_type);
|
||||||
const bool encode_status = Java_MediaCodecVideoEncoder_initEncode(
|
const bool encode_status = Java_MediaCodecVideoEncoder_initEncode(
|
||||||
jni, j_media_codec_video_encoder_, j_video_codec_enum, profile_, width,
|
jni, j_media_codec_video_encoder_, j_video_codec_enum, profile_, width,
|
||||||
height, kbps, fps,
|
height, kbps, fps, use_surface);
|
||||||
JavaParamRef<jobject>(use_surface ? egl_context_ : nullptr));
|
|
||||||
if (!encode_status) {
|
if (!encode_status) {
|
||||||
ALOGE << "Failed to configure encoder.";
|
ALOGE << "Failed to configure encoder.";
|
||||||
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
ProcessHWError(false /* reset_if_fallback_unavailable */);
|
||||||
@ -1212,8 +1210,7 @@ const char* MediaCodecVideoEncoder::ImplementationName() const {
|
|||||||
return "MediaCodec";
|
return "MediaCodec";
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory()
|
MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() {
|
||||||
: egl_context_(nullptr) {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
supported_formats_.clear();
|
supported_formats_.clear();
|
||||||
@ -1270,23 +1267,6 @@ MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory()
|
|||||||
|
|
||||||
MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() {
|
MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() {
|
||||||
ALOGD << "MediaCodecVideoEncoderFactory dtor";
|
ALOGD << "MediaCodecVideoEncoderFactory dtor";
|
||||||
if (egl_context_) {
|
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
|
||||||
jni->DeleteGlobalRef(egl_context_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MediaCodecVideoEncoderFactory::SetEGLContext(JNIEnv* jni,
|
|
||||||
jobject egl_context) {
|
|
||||||
ALOGD << "MediaCodecVideoEncoderFactory::SetEGLContext";
|
|
||||||
if (egl_context_) {
|
|
||||||
jni->DeleteGlobalRef(egl_context_);
|
|
||||||
egl_context_ = nullptr;
|
|
||||||
}
|
|
||||||
egl_context_ = jni->NewGlobalRef(egl_context);
|
|
||||||
if (CheckException(jni)) {
|
|
||||||
ALOGE << "error calling NewGlobalRef for EGL Context.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<VideoEncoder> MediaCodecVideoEncoderFactory::CreateVideoEncoder(
|
std::unique_ptr<VideoEncoder> MediaCodecVideoEncoderFactory::CreateVideoEncoder(
|
||||||
@ -1299,7 +1279,8 @@ std::unique_ptr<VideoEncoder> MediaCodecVideoEncoderFactory::CreateVideoEncoder(
|
|||||||
ALOGD << "Create HW video encoder for " << format.name;
|
ALOGD << "Create HW video encoder for " << format.name;
|
||||||
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
||||||
ScopedLocalRefFrame local_ref_frame(jni);
|
ScopedLocalRefFrame local_ref_frame(jni);
|
||||||
return rtc::MakeUnique<MediaCodecVideoEncoder>(jni, format, egl_context_);
|
return rtc::MakeUnique<MediaCodecVideoEncoder>(
|
||||||
|
jni, format, Java_MediaCodecVideoEncoder_hasEgl14Context(jni));
|
||||||
}
|
}
|
||||||
ALOGW << "Can not find HW video encoder for type " << format.name;
|
ALOGW << "Can not find HW video encoder for type " << format.name;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@ -28,13 +28,6 @@ VideoDecoderFactory* CreateVideoDecoderFactory(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoEncoderFactory* encoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context) {}
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoDecoderFactory* decoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context) {}
|
|
||||||
|
|
||||||
void* CreateVideoSource(JNIEnv* env,
|
void* CreateVideoSource(JNIEnv* env,
|
||||||
rtc::Thread* signaling_thread,
|
rtc::Thread* signaling_thread,
|
||||||
rtc::Thread* worker_thread,
|
rtc::Thread* worker_thread,
|
||||||
|
|||||||
@ -36,15 +36,11 @@ class OwnedFactoryAndThreads {
|
|||||||
OwnedFactoryAndThreads(std::unique_ptr<Thread> network_thread,
|
OwnedFactoryAndThreads(std::unique_ptr<Thread> network_thread,
|
||||||
std::unique_ptr<Thread> worker_thread,
|
std::unique_ptr<Thread> worker_thread,
|
||||||
std::unique_ptr<Thread> signaling_thread,
|
std::unique_ptr<Thread> signaling_thread,
|
||||||
VideoEncoderFactory* legacy_encoder_factory,
|
|
||||||
VideoDecoderFactory* legacy_decoder_factory,
|
|
||||||
rtc::NetworkMonitorFactory* network_monitor_factory,
|
rtc::NetworkMonitorFactory* network_monitor_factory,
|
||||||
PeerConnectionFactoryInterface* factory)
|
PeerConnectionFactoryInterface* factory)
|
||||||
: network_thread_(std::move(network_thread)),
|
: network_thread_(std::move(network_thread)),
|
||||||
worker_thread_(std::move(worker_thread)),
|
worker_thread_(std::move(worker_thread)),
|
||||||
signaling_thread_(std::move(signaling_thread)),
|
signaling_thread_(std::move(signaling_thread)),
|
||||||
legacy_encoder_factory_(legacy_encoder_factory),
|
|
||||||
legacy_decoder_factory_(legacy_decoder_factory),
|
|
||||||
network_monitor_factory_(network_monitor_factory),
|
network_monitor_factory_(network_monitor_factory),
|
||||||
factory_(factory) {}
|
factory_(factory) {}
|
||||||
|
|
||||||
@ -54,12 +50,6 @@ class OwnedFactoryAndThreads {
|
|||||||
Thread* network_thread() { return network_thread_.get(); }
|
Thread* network_thread() { return network_thread_.get(); }
|
||||||
Thread* signaling_thread() { return signaling_thread_.get(); }
|
Thread* signaling_thread() { return signaling_thread_.get(); }
|
||||||
Thread* worker_thread() { return worker_thread_.get(); }
|
Thread* worker_thread() { return worker_thread_.get(); }
|
||||||
VideoEncoderFactory* legacy_encoder_factory() {
|
|
||||||
return legacy_encoder_factory_;
|
|
||||||
}
|
|
||||||
VideoDecoderFactory* legacy_decoder_factory() {
|
|
||||||
return legacy_decoder_factory_;
|
|
||||||
}
|
|
||||||
rtc::NetworkMonitorFactory* network_monitor_factory() {
|
rtc::NetworkMonitorFactory* network_monitor_factory() {
|
||||||
return network_monitor_factory_;
|
return network_monitor_factory_;
|
||||||
}
|
}
|
||||||
@ -70,8 +60,6 @@ class OwnedFactoryAndThreads {
|
|||||||
const std::unique_ptr<Thread> network_thread_;
|
const std::unique_ptr<Thread> network_thread_;
|
||||||
const std::unique_ptr<Thread> worker_thread_;
|
const std::unique_ptr<Thread> worker_thread_;
|
||||||
const std::unique_ptr<Thread> signaling_thread_;
|
const std::unique_ptr<Thread> signaling_thread_;
|
||||||
VideoEncoderFactory* legacy_encoder_factory_;
|
|
||||||
VideoDecoderFactory* legacy_decoder_factory_;
|
|
||||||
rtc::NetworkMonitorFactory* network_monitor_factory_;
|
rtc::NetworkMonitorFactory* network_monitor_factory_;
|
||||||
PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
|
PeerConnectionFactoryInterface* factory_; // Const after ctor except dtor.
|
||||||
};
|
};
|
||||||
|
|||||||
@ -112,9 +112,7 @@ jobject NativeToJavaPeerConnectionFactory(
|
|||||||
rtc::NetworkMonitorFactory* network_monitor_factory) {
|
rtc::NetworkMonitorFactory* network_monitor_factory) {
|
||||||
jni::OwnedFactoryAndThreads* owned_factory = new jni::OwnedFactoryAndThreads(
|
jni::OwnedFactoryAndThreads* owned_factory = new jni::OwnedFactoryAndThreads(
|
||||||
std::move(network_thread), std::move(worker_thread),
|
std::move(network_thread), std::move(worker_thread),
|
||||||
std::move(signaling_thread), nullptr /* legacy_encoder_factory */,
|
std::move(signaling_thread), network_monitor_factory, pcf.release());
|
||||||
nullptr /* legacy_decoder_factory */, network_monitor_factory,
|
|
||||||
pcf.release());
|
|
||||||
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
|
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
|
||||||
|
|
||||||
return Java_PeerConnectionFactory_Constructor(
|
return Java_PeerConnectionFactory_Constructor(
|
||||||
@ -241,8 +239,6 @@ jlong CreatePeerConnectionFactoryForJava(
|
|||||||
std::unique_ptr<RtcEventLogFactoryInterface> rtc_event_log_factory(
|
std::unique_ptr<RtcEventLogFactoryInterface> rtc_event_log_factory(
|
||||||
CreateRtcEventLogFactory());
|
CreateRtcEventLogFactory());
|
||||||
|
|
||||||
VideoEncoderFactory* legacy_video_encoder_factory = nullptr;
|
|
||||||
VideoDecoderFactory* legacy_video_decoder_factory = nullptr;
|
|
||||||
std::unique_ptr<VideoEncoderFactory> video_encoder_factory;
|
std::unique_ptr<VideoEncoderFactory> video_encoder_factory;
|
||||||
std::unique_ptr<VideoDecoderFactory> video_decoder_factory;
|
std::unique_ptr<VideoDecoderFactory> video_decoder_factory;
|
||||||
std::unique_ptr<cricket::MediaEngineInterface> media_engine;
|
std::unique_ptr<cricket::MediaEngineInterface> media_engine;
|
||||||
@ -261,11 +257,8 @@ jlong CreatePeerConnectionFactoryForJava(
|
|||||||
if (jencoder_factory.is_null()) {
|
if (jencoder_factory.is_null()) {
|
||||||
// TODO(bugs.webrtc.org/7925): When all clients switched to injectable
|
// TODO(bugs.webrtc.org/7925): When all clients switched to injectable
|
||||||
// factories, remove the legacy codec factories
|
// factories, remove the legacy codec factories
|
||||||
std::unique_ptr<VideoEncoderFactory> legacy_factory =
|
|
||||||
CreateLegacyVideoEncoderFactory();
|
|
||||||
legacy_video_encoder_factory = legacy_factory.get();
|
|
||||||
video_encoder_factory =
|
video_encoder_factory =
|
||||||
WrapLegacyVideoEncoderFactory(std::move(legacy_factory));
|
WrapLegacyVideoEncoderFactory(CreateLegacyVideoEncoderFactory());
|
||||||
} else {
|
} else {
|
||||||
video_encoder_factory = std::unique_ptr<VideoEncoderFactory>(
|
video_encoder_factory = std::unique_ptr<VideoEncoderFactory>(
|
||||||
CreateVideoEncoderFactory(jni, jencoder_factory));
|
CreateVideoEncoderFactory(jni, jencoder_factory));
|
||||||
@ -274,11 +267,8 @@ jlong CreatePeerConnectionFactoryForJava(
|
|||||||
if (jdecoder_factory.is_null()) {
|
if (jdecoder_factory.is_null()) {
|
||||||
// TODO(bugs.webrtc.org/7925): When all clients switched to injectable
|
// TODO(bugs.webrtc.org/7925): When all clients switched to injectable
|
||||||
// factories, remove the legacy codec factories
|
// factories, remove the legacy codec factories
|
||||||
std::unique_ptr<VideoDecoderFactory> legacy_factory =
|
|
||||||
CreateLegacyVideoDecoderFactory();
|
|
||||||
legacy_video_decoder_factory = legacy_factory.get();
|
|
||||||
video_decoder_factory =
|
video_decoder_factory =
|
||||||
WrapLegacyVideoDecoderFactory(std::move(legacy_factory));
|
WrapLegacyVideoDecoderFactory(CreateLegacyVideoDecoderFactory());
|
||||||
} else {
|
} else {
|
||||||
video_decoder_factory = std::unique_ptr<VideoDecoderFactory>(
|
video_decoder_factory = std::unique_ptr<VideoDecoderFactory>(
|
||||||
CreateVideoDecoderFactory(jni, jdecoder_factory));
|
CreateVideoDecoderFactory(jni, jdecoder_factory));
|
||||||
@ -303,8 +293,7 @@ jlong CreatePeerConnectionFactoryForJava(
|
|||||||
}
|
}
|
||||||
OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
|
OwnedFactoryAndThreads* owned_factory = new OwnedFactoryAndThreads(
|
||||||
std::move(network_thread), std::move(worker_thread),
|
std::move(network_thread), std::move(worker_thread),
|
||||||
std::move(signaling_thread), legacy_video_encoder_factory,
|
std::move(signaling_thread), network_monitor_factory, factory.release());
|
||||||
legacy_video_decoder_factory, network_monitor_factory, factory.release());
|
|
||||||
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
|
owned_factory->InvokeJavaCallbacksOnFactoryThreads();
|
||||||
return jlongFromPointer(owned_factory);
|
return jlongFromPointer(owned_factory);
|
||||||
}
|
}
|
||||||
@ -478,20 +467,6 @@ static jlong JNI_PeerConnectionFactory_CreateVideoTrack(
|
|||||||
return jlongFromPointer(track.release());
|
return jlongFromPointer(track.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void JNI_PeerConnectionFactory_SetVideoHwAccelerationOptions(
|
|
||||||
JNIEnv* jni,
|
|
||||||
const JavaParamRef<jclass>&,
|
|
||||||
jlong native_factory,
|
|
||||||
const JavaParamRef<jobject>& local_egl_context,
|
|
||||||
const JavaParamRef<jobject>& remote_egl_context) {
|
|
||||||
OwnedFactoryAndThreads* owned_factory =
|
|
||||||
reinterpret_cast<OwnedFactoryAndThreads*>(native_factory);
|
|
||||||
SetEglContext(jni, owned_factory->legacy_encoder_factory(),
|
|
||||||
local_egl_context);
|
|
||||||
SetEglContext(jni, owned_factory->legacy_decoder_factory(),
|
|
||||||
remote_egl_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong JNI_PeerConnectionFactory_GetNativePeerConnectionFactory(
|
static jlong JNI_PeerConnectionFactory_GetNativePeerConnectionFactory(
|
||||||
JNIEnv* jni,
|
JNIEnv* jni,
|
||||||
const JavaParamRef<jclass>&,
|
const JavaParamRef<jclass>&,
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include "media/engine/convert_legacy_video_factory.h"
|
#include "media/engine/convert_legacy_video_factory.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/ptr_util.h"
|
#include "rtc_base/ptr_util.h"
|
||||||
#include "sdk/android/generated_video_jni/jni/EglBase14_jni.h"
|
|
||||||
#include "sdk/android/src/jni/androidmediadecoder_jni.h"
|
#include "sdk/android/src/jni/androidmediadecoder_jni.h"
|
||||||
#include "sdk/android/src/jni/androidmediaencoder_jni.h"
|
#include "sdk/android/src/jni/androidmediaencoder_jni.h"
|
||||||
#include "sdk/android/src/jni/androidvideotracksource.h"
|
#include "sdk/android/src/jni/androidvideotracksource.h"
|
||||||
@ -43,32 +42,6 @@ VideoDecoderFactory* CreateVideoDecoderFactory(
|
|||||||
return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
|
return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoEncoderFactory* encoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context) {
|
|
||||||
if (encoder_factory) {
|
|
||||||
MediaCodecVideoEncoderFactory* media_codec_factory =
|
|
||||||
static_cast<MediaCodecVideoEncoderFactory*>(encoder_factory);
|
|
||||||
if (media_codec_factory && Java_Context_isEgl14Context(env, egl_context)) {
|
|
||||||
RTC_LOG(LS_INFO) << "Set EGL context for HW encoding.";
|
|
||||||
media_codec_factory->SetEGLContext(env, egl_context.obj());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoDecoderFactory* decoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context) {
|
|
||||||
if (decoder_factory) {
|
|
||||||
MediaCodecVideoDecoderFactory* media_codec_factory =
|
|
||||||
static_cast<MediaCodecVideoDecoderFactory*>(decoder_factory);
|
|
||||||
if (media_codec_factory) {
|
|
||||||
RTC_LOG(LS_INFO) << "Set EGL context for HW decoding.";
|
|
||||||
media_codec_factory->SetEGLContext(env, egl_context.obj());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* CreateVideoSource(JNIEnv* env,
|
void* CreateVideoSource(JNIEnv* env,
|
||||||
rtc::Thread* signaling_thread,
|
rtc::Thread* signaling_thread,
|
||||||
rtc::Thread* worker_thread,
|
rtc::Thread* worker_thread,
|
||||||
|
|||||||
@ -33,13 +33,6 @@ VideoDecoderFactory* CreateVideoDecoderFactory(
|
|||||||
JNIEnv* jni,
|
JNIEnv* jni,
|
||||||
const JavaRef<jobject>& j_decoder_factory);
|
const JavaRef<jobject>& j_decoder_factory);
|
||||||
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoEncoderFactory* encoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context);
|
|
||||||
void SetEglContext(JNIEnv* env,
|
|
||||||
VideoDecoderFactory* decoder_factory,
|
|
||||||
const JavaRef<jobject>& egl_context);
|
|
||||||
|
|
||||||
void* CreateVideoSource(JNIEnv* env,
|
void* CreateVideoSource(JNIEnv* env,
|
||||||
rtc::Thread* signaling_thread,
|
rtc::Thread* signaling_thread,
|
||||||
rtc::Thread* worker_thread,
|
rtc::Thread* worker_thread,
|
||||||
|
|||||||
Reference in New Issue
Block a user