Expose MediaCodec.setParameters API to
- change video target bitrate on the fly
- request sync frames
- temporarily suspend feeding input buffers to the encoder
Change-Id: If5cf1162b2eeb28ac08288ecfa9f0e9823dd972e
diff --git a/api/current.txt b/api/current.txt
index 6026cc5..bf95a71 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12046,6 +12046,7 @@
method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
method public final void release();
method public final void releaseOutputBuffer(int, boolean);
+ method public final void setParameters(java.util.Map<java.lang.String, java.lang.Object>);
method public final void setVideoScalingMode(int);
method public final void signalEndOfInputStream();
method public final void start();
@@ -12059,6 +12060,9 @@
field public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
field public static final int INFO_OUTPUT_FORMAT_CHANGED = -2; // 0xfffffffe
field public static final int INFO_TRY_AGAIN_LATER = -1; // 0xffffffff
+ field public static final java.lang.String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
+ field public static final java.lang.String PARAMETER_KEY_SUSPEND = "drop-input-frames";
+ field public static final java.lang.String PARAMETER_KEY_VIDEO_BITRATE = "videoBitrate";
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 703eb27..f4e867e 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -564,6 +564,52 @@
public native final String getName();
/**
+ * Change a video encoder's target bitrate on the fly. The value is an
+ * Integer object containing the new bitrate in bps.
+ */
+ public static final String PARAMETER_KEY_VIDEO_BITRATE = "videoBitrate";
+
+ /**
+ * Temporarily suspend/resume encoding of input data. While suspended
+ * input data is effectively discarded instead of being fed into the
+ * encoder. This parameter really only makes sense to use with an encoder
+ * in "surface-input" mode, as the client code has no control over the
+ * input-side of the encoder in that case.
+ * The value is an Integer object containing the value 1 to suspend
+ * or the value 0 to resume.
+ */
+ public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames";
+
+ /**
+ * Request that the encoder produce a sync frame "soon".
+ * Provide an Integer with the value 0.
+ */
+ public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
+
+ /**
+ * Communicate additional parameter changes to the component instance.
+ */
+ public final void setParameters(Map<String, Object> params) {
+ if (params == null) {
+ return;
+ }
+
+ String[] keys = new String[params.size()];
+ Object[] values = new Object[params.size()];
+
+ int i = 0;
+ for (Map.Entry<String, Object> entry: params.entrySet()) {
+ keys[i] = entry.getKey();
+ values[i] = entry.getValue();
+ ++i;
+ }
+
+ setParameters(keys, values);
+ }
+
+ private native final void setParameters(String[] keys, Object[] values);
+
+ /**
* Get the codec info. If the codec was created by createDecoderByType
* or createEncoderByType, what component is chosen is not known beforehand,
* and thus the caller does not have the MediaCodecInfo.
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index ae1db87..a859506 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -310,6 +310,10 @@
return OK;
}
+status_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
+ return mCodec->setParameters(msg);
+}
+
void JMediaCodec::setVideoScalingMode(int mode) {
if (mSurfaceTextureClient != NULL) {
native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
@@ -837,6 +841,27 @@
return NULL;
}
+static void android_media_MediaCodec_setParameters(
+ JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
+ ALOGV("android_media_MediaCodec_setParameters");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ sp<AMessage> params;
+ status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, ¶ms);
+
+ if (err == OK) {
+ err = codec->setParameters(params);
+ }
+
+ throwExceptionAsNecessary(env, err);
+}
+
static void android_media_MediaCodec_setVideoScalingMode(
JNIEnv *env, jobject thiz, jint mode) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -986,6 +1011,9 @@
{ "getName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },
+ { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
+ (void *)android_media_MediaCodec_setParameters },
+
{ "setVideoScalingMode", "(I)V",
(void *)android_media_MediaCodec_setVideoScalingMode },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 282d2c5..2fbbd72 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -87,6 +87,8 @@
status_t getName(JNIEnv *env, jstring *name) const;
+ status_t setParameters(const sp<AMessage> ¶ms);
+
void setVideoScalingMode(int mode);
protected: