Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1025)

Unified Diff: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java

Issue 1403713002: MediaCodecVideoEncoder add support to encode from textures (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java
diff --git a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java
index 6a218fd56834f649a05e9972f0550fc999ead744..04d94076124dda854e883495c31eaff0c388d5bf 100644
--- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java
+++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java
@@ -33,8 +33,11 @@ import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
+import android.opengl.EGLContext;
+import android.opengl.GLES20;
import android.os.Build;
import android.os.Bundle;
+import android.view.Surface;
import org.webrtc.Logging;
@@ -65,6 +68,9 @@ public class MediaCodecVideoEncoder {
private Thread mediaCodecThread;
private MediaCodec mediaCodec;
private ByteBuffer[] outputBuffers;
+ private EglBase eglBase;
+ private Surface inputSurface;
+ private GlRectDrawer drawer;
private static final String VP8_MIME_TYPE = "video/x-vnd.on2.vp8";
private static final String H264_MIME_TYPE = "video/avc";
// List of supported HW VP8 codecs.
@@ -117,7 +123,7 @@ public class MediaCodecVideoEncoder {
}
private static EncoderProperties findHwEncoder(
- String mime, String[] supportedHwCodecPrefixes) {
+ String mime, String[] supportedHwCodecPrefixes, boolean useSurface) {
// MediaCodec.setParameters is missing for JB and below, so bitrate
// can not be adjusted dynamically.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
@@ -168,6 +174,18 @@ public class MediaCodecVideoEncoder {
Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
}
+ if (useSurface) {
+ for (int codecColorFormat : capabilities.colorFormats) {
+ if (codecColorFormat == CodecCapabilities.COLOR_FormatSurface) {
+ // Found supported HW encoder.
+ Logging.d(TAG, "Found target encoder for mime " + mime + " : " + name +
+ ". Using Surface as input");
+ return new EncoderProperties(name, codecColorFormat);
+ }
+ }
+ return null;
+ }
+
// Check if codec supports either yuv420 or nv12.
for (int supportedColorFormat : supportedColorList) {
for (int codecColorFormat : capabilities.colorFormats) {
@@ -184,11 +202,19 @@ public class MediaCodecVideoEncoder {
}
public static boolean isVp8HwSupported() {
- return findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes) != null;
+ return findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, false) != null;
}
public static boolean isH264HwSupported() {
- return findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes) != null;
+ return findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes, false) != null;
+ }
+
+ public static boolean isVp8HwSupportedUsingTextures() {
AlexG 2015/10/14 23:48:27 Are these 2 functions called from native code or f
perkj_webrtc 2015/11/16 13:08:51 they are here so that an app can ask if the hw cod
+ return findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, true) != null;
+ }
+
+ public static boolean isH264HwSupportedUsingTextures() {
+ return findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes, true) != null;
}
private void checkOnMediaCodecThread() {
@@ -209,10 +235,12 @@ public class MediaCodecVideoEncoder {
}
}
- // Returns false if the hardware encoder currently can't be used.
- boolean initEncode(VideoCodecType type, int width, int height, int kbps, int fps) {
+ boolean initEncode(VideoCodecType type, int width, int height, int kbps, int fps,
+ EGLContext sharedContext) {
+ final boolean useSurface = sharedContext != null;
Logging.d(TAG, "Java initEncode: " + type + " : " + width + " x " + height +
- ". @ " + kbps + " kbps. Fps: " + fps + ".");
+ ". @ " + kbps + " kbps. Fps: " + fps + ". Encode from texture : " +
+ (useSurface ? "True" : "False"));
if (mediaCodecThread != null) {
throw new RuntimeException("Forgot to release()?");
@@ -222,11 +250,11 @@ public class MediaCodecVideoEncoder {
int keyFrameIntervalSec = 0;
if (type == VideoCodecType.VIDEO_CODEC_VP8) {
mime = VP8_MIME_TYPE;
- properties = findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes);
+ properties = findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes, useSurface);
keyFrameIntervalSec = 100;
} else if (type == VideoCodecType.VIDEO_CODEC_H264) {
mime = H264_MIME_TYPE;
- properties = findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes);
+ properties = findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes, useSurface);
keyFrameIntervalSec = 20;
}
if (properties == null) {
@@ -250,6 +278,13 @@ public class MediaCodecVideoEncoder {
mediaCodec.configure(
format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+ if (useSurface) {
+ eglBase = new EglBase(sharedContext, EglBase.ConfigType.RECORDABLE);
+ // Create an input surface and keep a reference since we must release the surface when done.
+ inputSurface = mediaCodec.createInputSurface();
+ eglBase.createSurface(inputSurface);
+ drawer = new GlRectDrawer();
+ }
mediaCodec.start();
outputBuffers = mediaCodec.getOutputBuffers();
@@ -291,6 +326,27 @@ public class MediaCodecVideoEncoder {
}
}
+ boolean encodeTexture(boolean isKeyframe, int oesTextureId, float[] transformationMatrix,
+ long presentationTimestampUs) {
+ checkOnMediaCodecThread();
+ try {
+ if (isKeyframe) {
+ Logging.d(TAG, "Sync frame request");
+ Bundle b = new Bundle();
+ b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
+ mediaCodec.setParameters(b);
+ }
+ eglBase.makeCurrent();
+ drawer.drawOes(oesTextureId, transformationMatrix);
+ eglBase.swapBuffers(presentationTimestampUs * 1000);
+ return true;
+ }
+ catch (RuntimeException e) {
+ Logging.e(TAG, "encodeTexture failed", e);
+ return false;
+ }
+ }
+
void release() {
Logging.d(TAG, "Java releaseEncoder");
checkOnMediaCodecThread();
@@ -302,6 +358,15 @@ public class MediaCodecVideoEncoder {
}
mediaCodec = null;
mediaCodecThread = null;
+ if (drawer != null) {
+ drawer.release();
AlexG 2015/10/14 23:48:27 nit: drawer = null and same for 2 checks below?
perkj_webrtc 2015/11/16 13:08:51 Done.
+ }
+ if (eglBase != null) {
+ eglBase.release();
+ }
+ if (inputSurface != null) {
+ inputSurface.release();
+ }
}
private boolean setRates(int kbps, int frameRateIgnored) {

Powered by Google App Engine
This is Rietveld 408576698