Loading core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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); } media/java/android/media/MediaCodec.java +103 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1923,6 +1936,7 @@ final public class MediaCodec implements PlaybackComponent { mEventHandler = null; } mCallbackHandler = mEventHandler; mOnFirstTunnelFrameReadyHandler = mEventHandler; mOnFrameRenderedHandler = mEventHandler; mBufferLock = new Object(); Loading Loading @@ -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); } Loading Loading @@ -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. Loading Loading @@ -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 * Loading Loading @@ -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; } Loading media/jni/android_media_MediaCodec.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -1100,6 +1134,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { } break; } case kWhatFirstTunnelFrameReady: { handleFirstTunnelFrameReadyNotification(msg); break; } default: TRESPASS(); } Loading Loading @@ -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, Loading Loading @@ -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 }, Loading media/jni/android_media_MediaCodec.h +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -176,6 +178,7 @@ private: kWhatCallbackNotify, kWhatFrameRendered, kWhatAsyncReleaseComplete, kWhatFirstTunnelFrameReady, }; jclass mClass; Loading @@ -191,6 +194,7 @@ private: std::once_flag mAsyncReleaseFlag; sp<AMessage> mCallbackNotification; sp<AMessage> mOnFirstTunnelFrameReadyNotification; sp<AMessage> mOnFrameRenderedNotification; status_t mInitStatus; Loading @@ -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); Loading Loading
core/api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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); }
media/java/android/media/MediaCodec.java +103 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1923,6 +1936,7 @@ final public class MediaCodec implements PlaybackComponent { mEventHandler = null; } mCallbackHandler = mEventHandler; mOnFirstTunnelFrameReadyHandler = mEventHandler; mOnFrameRenderedHandler = mEventHandler; mBufferLock = new Object(); Loading Loading @@ -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); } Loading Loading @@ -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. Loading Loading @@ -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 * Loading Loading @@ -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; } Loading
media/jni/android_media_MediaCodec.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -1100,6 +1134,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { } break; } case kWhatFirstTunnelFrameReady: { handleFirstTunnelFrameReadyNotification(msg); break; } default: TRESPASS(); } Loading Loading @@ -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, Loading Loading @@ -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 }, Loading
media/jni/android_media_MediaCodec.h +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -176,6 +178,7 @@ private: kWhatCallbackNotify, kWhatFrameRendered, kWhatAsyncReleaseComplete, kWhatFirstTunnelFrameReady, }; jclass mClass; Loading @@ -191,6 +194,7 @@ private: std::once_flag mAsyncReleaseFlag; sp<AMessage> mCallbackNotification; sp<AMessage> mOnFirstTunnelFrameReadyNotification; sp<AMessage> mOnFrameRenderedNotification; status_t mInitStatus; Loading @@ -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); Loading