Merge "Add tunnel mode video peek related APIs" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4f576188b4
@@ -21341,6 +21341,7 @@ package android.media {
|
||||
method public void setCallback(@Nullable android.media.MediaCodec.Callback, @Nullable android.os.Handler);
|
||||
method public void setCallback(@Nullable android.media.MediaCodec.Callback);
|
||||
method public void setInputSurface(@NonNull android.view.Surface);
|
||||
method public void setOnFirstTunnelFrameReadyListener(@Nullable android.os.Handler, @Nullable android.media.MediaCodec.OnFirstTunnelFrameReadyListener);
|
||||
method public void setOnFrameRenderedListener(@Nullable android.media.MediaCodec.OnFrameRenderedListener, @Nullable android.os.Handler);
|
||||
method public void setOutputSurface(@NonNull android.view.Surface);
|
||||
method public void setParameters(@Nullable android.os.Bundle);
|
||||
@@ -21368,6 +21369,7 @@ package android.media {
|
||||
field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
|
||||
field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames";
|
||||
field public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us";
|
||||
field public static final String PARAMETER_KEY_TUNNEL_PEEK = "tunnel-peek";
|
||||
field public static final String PARAMETER_KEY_VIDEO_BITRATE = "video-bitrate";
|
||||
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
|
||||
@@ -21458,6 +21460,10 @@ package android.media {
|
||||
field public static final String WIDTH = "android.media.mediacodec.width";
|
||||
}
|
||||
|
||||
public static interface MediaCodec.OnFirstTunnelFrameReadyListener {
|
||||
method public void onFirstTunnelFrameReady(@NonNull android.media.MediaCodec);
|
||||
}
|
||||
|
||||
public static interface MediaCodec.OnFrameRenderedListener {
|
||||
method public void onFrameRendered(@NonNull android.media.MediaCodec, long, long);
|
||||
}
|
||||
|
||||
@@ -1674,9 +1674,11 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
public @interface BufferFlag {}
|
||||
|
||||
private EventHandler mEventHandler;
|
||||
private EventHandler mOnFirstTunnelFrameReadyHandler;
|
||||
private EventHandler mOnFrameRenderedHandler;
|
||||
private EventHandler mCallbackHandler;
|
||||
private Callback mCallback;
|
||||
private OnFirstTunnelFrameReadyListener mOnFirstTunnelFrameReadyListener;
|
||||
private OnFrameRenderedListener mOnFrameRenderedListener;
|
||||
private final Object mListenerLock = new Object();
|
||||
private MediaCodecInfo mCodecInfo;
|
||||
@@ -1687,6 +1689,7 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
private static final int EVENT_CALLBACK = 1;
|
||||
private static final int EVENT_SET_CALLBACK = 2;
|
||||
private static final int EVENT_FRAME_RENDERED = 3;
|
||||
private static final int EVENT_FIRST_TUNNEL_FRAME_READY = 4;
|
||||
|
||||
private static final int CB_INPUT_AVAILABLE = 1;
|
||||
private static final int CB_OUTPUT_AVAILABLE = 2;
|
||||
@@ -1748,6 +1751,16 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
mCodec, (long)mediaTimeUs, (long)systemNano);
|
||||
}
|
||||
break;
|
||||
case EVENT_FIRST_TUNNEL_FRAME_READY:
|
||||
OnFirstTunnelFrameReadyListener onFirstTunnelFrameReadyListener;
|
||||
synchronized (mListenerLock) {
|
||||
onFirstTunnelFrameReadyListener = mOnFirstTunnelFrameReadyListener;
|
||||
}
|
||||
if (onFirstTunnelFrameReadyListener == null) {
|
||||
break;
|
||||
}
|
||||
onFirstTunnelFrameReadyListener.onFirstTunnelFrameReady(mCodec);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -1923,6 +1936,7 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
mEventHandler = null;
|
||||
}
|
||||
mCallbackHandler = mEventHandler;
|
||||
mOnFirstTunnelFrameReadyHandler = mEventHandler;
|
||||
mOnFrameRenderedHandler = mEventHandler;
|
||||
|
||||
mBufferLock = new Object();
|
||||
@@ -2277,6 +2291,9 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
mCallbackHandler.removeMessages(EVENT_SET_CALLBACK);
|
||||
mCallbackHandler.removeMessages(EVENT_CALLBACK);
|
||||
}
|
||||
if (mOnFirstTunnelFrameReadyHandler != null) {
|
||||
mOnFirstTunnelFrameReadyHandler.removeMessages(EVENT_FIRST_TUNNEL_FRAME_READY);
|
||||
}
|
||||
if (mOnFrameRenderedHandler != null) {
|
||||
mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED);
|
||||
}
|
||||
@@ -4446,6 +4463,41 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
public static final String PARAMETER_KEY_LOW_LATENCY =
|
||||
MediaFormat.KEY_LOW_LATENCY;
|
||||
|
||||
/**
|
||||
* Control video peek of the first frame when a codec is configured for tunnel mode with
|
||||
* {@link MediaFormat#KEY_AUDIO_SESSION_ID} while the {@link AudioTrack} is paused.
|
||||
*<p>
|
||||
* When disabled (1) after a {@link #flush} or {@link #start}, (2) while the corresponding
|
||||
* {@link AudioTrack} is paused and (3) before any buffers are queued, the first frame is not to
|
||||
* be rendered until either this parameter is enabled or the corresponding {@link AudioTrack}
|
||||
* has begun playback. Once the frame is decoded and ready to be rendered,
|
||||
* {@link OnFirstTunnelFrameReadyListener#onFirstTunnelFrameReady} is called but the frame is
|
||||
* not rendered. The surface continues to show the previously-rendered content, or black if the
|
||||
* surface is new. A subsequent call to {@link AudioTrack#play} renders this frame and triggers
|
||||
* a callback to {@link OnFrameRenderedListener#onFrameRendered}, and video playback begins.
|
||||
*<p>
|
||||
* <b>Note</b>: To clear any previously rendered content and show black, configure the
|
||||
* MediaCodec with {@code KEY_PUSH_BLANK_BUFFERS_ON_STOP(1)}, and call {@link #stop} before
|
||||
* pushing new video frames to the codec.
|
||||
*<p>
|
||||
* When enabled (1) after a {@link #flush} or {@link #start} and (2) while the corresponding
|
||||
* {@link AudioTrack} is paused, the first frame is rendered as soon as it is decoded, or
|
||||
* immediately, if it has already been decoded. If not already decoded, when the frame is
|
||||
* decoded and ready to be rendered,
|
||||
* {@link OnFirstTunnelFrameReadyListener#onFirstTunnelFrameReady} is called. The frame is then
|
||||
* immediately rendered and {@link OnFrameRenderedListener#onFrameRendered} is subsequently
|
||||
* called.
|
||||
*<p>
|
||||
* The value is an Integer object containing the value 1 to enable or the value 0 to disable.
|
||||
*<p>
|
||||
* The default for this parameter is <b>enabled</b>. Once a frame has been rendered, changing
|
||||
* this parameter has no effect until a subsequent {@link #flush} or
|
||||
* {@link #stop}/{@link #start}.
|
||||
*
|
||||
* @see #setParameters(Bundle)
|
||||
*/
|
||||
public static final String PARAMETER_KEY_TUNNEL_PEEK = "tunnel-peek";
|
||||
|
||||
/**
|
||||
* Communicate additional parameter changes to the component instance.
|
||||
* <b>Note:</b> Some of these parameter changes may silently fail to apply.
|
||||
@@ -4544,6 +4596,55 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
setCallback(cb, null /* handler */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener to be called when the first output frame has been decoded
|
||||
* and is ready to be rendered for a codec configured for tunnel mode with
|
||||
* {@code KEY_AUDIO_SESSION_ID}.
|
||||
*
|
||||
* @see MediaCodec#setOnFirstTunnelFrameReadyListener
|
||||
*/
|
||||
public interface OnFirstTunnelFrameReadyListener {
|
||||
|
||||
/**
|
||||
* Called when the first output frame has been decoded and is ready to be
|
||||
* rendered.
|
||||
*/
|
||||
void onFirstTunnelFrameReady(@NonNull MediaCodec codec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback to be invoked when the first output frame has been decoded
|
||||
* and is ready to be rendered on a codec configured for tunnel mode with {@code
|
||||
* KEY_AUDIO_SESSION_ID}.
|
||||
*
|
||||
* @param handler the callback will be run on the handler's thread. If {@code
|
||||
* null}, the callback will be run on the default thread, which is the looper from
|
||||
* which the codec was created, or a new thread if there was none.
|
||||
*
|
||||
* @param listener the callback that will be run. If {@code null}, clears any registered
|
||||
* listener.
|
||||
*/
|
||||
public void setOnFirstTunnelFrameReadyListener(
|
||||
@Nullable Handler handler, @Nullable OnFirstTunnelFrameReadyListener listener) {
|
||||
synchronized (mListenerLock) {
|
||||
mOnFirstTunnelFrameReadyListener = listener;
|
||||
if (listener != null) {
|
||||
EventHandler newHandler = getEventHandlerOn(
|
||||
handler,
|
||||
mOnFirstTunnelFrameReadyHandler);
|
||||
if (newHandler != mOnFirstTunnelFrameReadyHandler) {
|
||||
mOnFirstTunnelFrameReadyHandler.removeMessages(EVENT_FIRST_TUNNEL_FRAME_READY);
|
||||
}
|
||||
mOnFirstTunnelFrameReadyHandler = newHandler;
|
||||
} else if (mOnFirstTunnelFrameReadyHandler != null) {
|
||||
mOnFirstTunnelFrameReadyHandler.removeMessages(EVENT_FIRST_TUNNEL_FRAME_READY);
|
||||
}
|
||||
native_enableOnFirstTunnelFrameReadyListener(listener != null);
|
||||
}
|
||||
}
|
||||
|
||||
private native void native_enableOnFirstTunnelFrameReadyListener(boolean enable);
|
||||
|
||||
/**
|
||||
* Listener to be called when an output frame has rendered on the output surface
|
||||
*
|
||||
@@ -4667,6 +4768,8 @@ final public class MediaCodec implements PlaybackComponent {
|
||||
EventHandler handler = mEventHandler;
|
||||
if (what == EVENT_CALLBACK) {
|
||||
handler = mCallbackHandler;
|
||||
} else if (what == EVENT_FIRST_TUNNEL_FRAME_READY) {
|
||||
handler = mOnFirstTunnelFrameReadyHandler;
|
||||
} else if (what == EVENT_FRAME_RENDERED) {
|
||||
handler = mOnFrameRenderedHandler;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ enum {
|
||||
EVENT_CALLBACK = 1,
|
||||
EVENT_SET_CALLBACK = 2,
|
||||
EVENT_FRAME_RENDERED = 3,
|
||||
EVENT_FIRST_TUNNEL_FRAME_READY = 4,
|
||||
};
|
||||
|
||||
static struct CryptoErrorCodes {
|
||||
@@ -269,6 +270,18 @@ JMediaCodec::~JMediaCodec() {
|
||||
mClass = NULL;
|
||||
}
|
||||
|
||||
status_t JMediaCodec::enableOnFirstTunnelFrameReadyListener(jboolean enable) {
|
||||
if (enable) {
|
||||
if (mOnFirstTunnelFrameReadyNotification == NULL) {
|
||||
mOnFirstTunnelFrameReadyNotification = new AMessage(kWhatFirstTunnelFrameReady, this);
|
||||
}
|
||||
} else {
|
||||
mOnFirstTunnelFrameReadyNotification.clear();
|
||||
}
|
||||
|
||||
return mCodec->setOnFirstTunnelFrameReadyNotification(mOnFirstTunnelFrameReadyNotification);
|
||||
}
|
||||
|
||||
status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
|
||||
if (enable) {
|
||||
if (mOnFrameRenderedNotification == NULL) {
|
||||
@@ -1058,6 +1071,27 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
|
||||
env->DeleteLocalRef(obj);
|
||||
}
|
||||
|
||||
void JMediaCodec::handleFirstTunnelFrameReadyNotification(const sp<AMessage> &msg) {
|
||||
int32_t arg1 = 0, arg2 = 0;
|
||||
jobject obj = NULL;
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
sp<AMessage> data;
|
||||
CHECK(msg->findMessage("data", &data));
|
||||
|
||||
status_t err = ConvertMessageToMap(env, data, &obj);
|
||||
if (err != OK) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
env->CallVoidMethod(
|
||||
mObject, gFields.postEventFromNativeID,
|
||||
EVENT_FIRST_TUNNEL_FRAME_READY, arg1, arg2, obj);
|
||||
|
||||
env->DeleteLocalRef(obj);
|
||||
}
|
||||
|
||||
void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
|
||||
int32_t arg1 = 0, arg2 = 0;
|
||||
jobject obj = NULL;
|
||||
@@ -1100,6 +1134,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kWhatFirstTunnelFrameReady:
|
||||
{
|
||||
handleFirstTunnelFrameReadyNotification(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TRESPASS();
|
||||
}
|
||||
@@ -1256,6 +1295,22 @@ static jint throwExceptionAsNecessary(
|
||||
}
|
||||
}
|
||||
|
||||
static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
jboolean enabled) {
|
||||
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
|
||||
|
||||
if (codec == NULL || codec->initCheck() != OK) {
|
||||
throwExceptionAsNecessary(env, INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
status_t err = codec->enableOnFirstTunnelFrameReadyListener(enabled);
|
||||
|
||||
throwExceptionAsNecessary(env, err);
|
||||
}
|
||||
|
||||
static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
@@ -3138,6 +3193,9 @@ static const JNINativeMethod gMethods[] = {
|
||||
{ "native_setInputSurface", "(Landroid/view/Surface;)V",
|
||||
(void *)android_media_MediaCodec_setInputSurface },
|
||||
|
||||
{ "native_enableOnFirstTunnelFrameReadyListener", "(Z)V",
|
||||
(void *)android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener },
|
||||
|
||||
{ "native_enableOnFrameRenderedListener", "(Z)V",
|
||||
(void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@ struct JMediaCodec : public AHandler {
|
||||
void release();
|
||||
void releaseAsync();
|
||||
|
||||
status_t enableOnFirstTunnelFrameReadyListener(jboolean enable);
|
||||
|
||||
status_t enableOnFrameRenderedListener(jboolean enable);
|
||||
|
||||
status_t setCallback(jobject cb);
|
||||
@@ -176,6 +178,7 @@ private:
|
||||
kWhatCallbackNotify,
|
||||
kWhatFrameRendered,
|
||||
kWhatAsyncReleaseComplete,
|
||||
kWhatFirstTunnelFrameReady,
|
||||
};
|
||||
|
||||
jclass mClass;
|
||||
@@ -191,6 +194,7 @@ private:
|
||||
std::once_flag mAsyncReleaseFlag;
|
||||
|
||||
sp<AMessage> mCallbackNotification;
|
||||
sp<AMessage> mOnFirstTunnelFrameReadyNotification;
|
||||
sp<AMessage> mOnFrameRenderedNotification;
|
||||
|
||||
status_t mInitStatus;
|
||||
@@ -203,6 +207,7 @@ private:
|
||||
jobject *buf) const;
|
||||
|
||||
void handleCallback(const sp<AMessage> &msg);
|
||||
void handleFirstTunnelFrameReadyNotification(const sp<AMessage> &msg);
|
||||
void handleFrameRenderedNotification(const sp<AMessage> &msg);
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);
|
||||
|
||||
Reference in New Issue
Block a user