Loading api/current.txt +9 −0 Original line number Diff line number Diff line Loading @@ -14292,6 +14292,7 @@ package android.media { method public final void release(); method public final void releaseOutputBuffer(int, boolean); method public final void releaseOutputBuffer(int, long); method public void setCallback(android.media.MediaCodec.Callback); method public final void setParameters(android.os.Bundle); method public final void setVideoScalingMode(int); method public final void signalEndOfInputStream(); Loading Loading @@ -14322,6 +14323,14 @@ package android.media { field public int size; } public static abstract class MediaCodec.Callback { ctor public MediaCodec.Callback(); method public abstract void onError(android.media.MediaCodec, int, int); method public abstract void onInputBufferAvailable(android.media.MediaCodec, int); method public abstract void onOutputBufferAvailable(android.media.MediaCodec, int, android.media.MediaCodec.BufferInfo); method public abstract void onOutputFormatChanged(android.media.MediaCodec, android.media.MediaFormat); } public static final class MediaCodec.CodecException extends java.lang.IllegalStateException { ctor public MediaCodec.CodecException(int, int, java.lang.String); method public int getErrorCode(); media/java/android/media/MediaCodec.java +116 −31 Original line number Diff line number Diff line Loading @@ -205,9 +205,15 @@ final public class MediaCodec { public static final int BUFFER_FLAG_END_OF_STREAM = 4; private EventHandler mEventHandler; private volatile NotificationCallback mNotificationCallback; private Callback mCallback; static final int EVENT_NOTIFY = 1; private static final int EVENT_CALLBACK = 1; private static final int EVENT_SET_CALLBACK = 2; private static final int CB_INPUT_AVAILABLE = 1; private static final int CB_OUTPUT_AVAILABLE = 2; private static final int CB_ERROR = 3; private static final int CB_OUTPUT_FORMAT_CHANGE = 4; private class EventHandler extends Handler { private MediaCodec mCodec; Loading @@ -220,12 +226,60 @@ final public class MediaCodec { @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_NOTIFY: case EVENT_CALLBACK: { handleCallback(msg); break; } case EVENT_SET_CALLBACK: { mCallback = (MediaCodec.Callback) msg.obj; break; } default: { break; } } } private void handleCallback(Message msg) { if (mCallback == null) { return; } switch (msg.arg1) { case CB_INPUT_AVAILABLE: { mCallback.onInputBufferAvailable(mCodec, msg.arg2 /* index */); break; } case CB_OUTPUT_AVAILABLE: { mCallback.onOutputBufferAvailable( mCodec, msg.arg2 /* index */, (MediaCodec.BufferInfo) msg.obj); break; } case CB_ERROR: { NotificationCallback cb = mNotificationCallback; if (cb != null) { cb.onCodecNotify(mCodec); mCallback.onError(mCodec, msg.arg2 /* error */, (Integer) msg.obj /* actionCode */); break; } case CB_OUTPUT_FORMAT_CHANGE: { mCallback.onOutputFormatChanged(mCodec, new MediaFormat((Map<String, Object>) msg.obj)); break; } default: { break; } } Loading Loading @@ -360,6 +414,8 @@ final public class MediaCodec { native_configure(keys, values, surface, crypto, flags); } private native final void native_setCallback(Callback cb); private native final void native_configure( String[] keys, Object[] values, Surface surface, MediaCrypto crypto, int flags); Loading Loading @@ -398,7 +454,8 @@ final public class MediaCodec { native_stop(); if (mEventHandler != null) { mEventHandler.removeMessages(EVENT_NOTIFY); mEventHandler.removeMessages(EVENT_CALLBACK); mEventHandler.removeMessages(EVENT_SET_CALLBACK); } } Loading Loading @@ -855,44 +912,72 @@ final public class MediaCodec { } /** * Sets the codec listener for actionable MediaCodec events. * <p>Call this method with a null listener to stop receiving event notifications. * Sets an asynchronous callback for actionable MediaCodec events. * * If the client intends to use the component in asynchronous mode, * a valid callback should be provided before {@link #configure} is called. * * @param cb The listener that will run. * When asynchronous callback is enabled, the client should not call * {@link #dequeueInputBuffer(long)} or {@link #dequeueOutputBuffer(BufferInfo, long)} * * @hide * @param cb The callback that will run. */ public void setNotificationCallback(NotificationCallback cb) { mNotificationCallback = cb; public void setCallback(/* MediaCodec. */ Callback cb) { if (mEventHandler != null) { // set java callback on handler Message msg = mEventHandler.obtainMessage(EVENT_SET_CALLBACK, 0, 0, cb); mEventHandler.sendMessage(msg); // set native handler here, don't post to handler because // it may cause the callback to be delayed and set in a wrong state, // and MediaCodec is already doing it on looper. native_setCallback(cb); } } /** * MediaCodec callback interface. Used to notify the user asynchronously * of various MediaCodec events. */ public static abstract class Callback { /** * Called when an input buffer becomes available. * * @param codec The MediaCodec object. * @param index The index of the available input buffer. */ public abstract void onInputBufferAvailable(MediaCodec codec, int index); /** * MediaCodec listener interface. Used to notify the user of MediaCodec * when there are available input and/or output buffers, a change in * configuration or when a codec error happened. * Called when an output buffer becomes available. * * @hide * @param codec The MediaCodec object. * @param index The index of the available output buffer. * @param info Info regarding the available output buffer {@link MediaCodec.BufferInfo}. */ public static abstract class NotificationCallback { public abstract void onOutputBufferAvailable(MediaCodec codec, int index, BufferInfo info); /** * Called on the listener to notify that there is an actionable * MediaCodec event. The application should call {@link #dequeueOutputBuffer} * to receive the configuration change event, codec error or an * available output buffer. It should also call {@link #dequeueInputBuffer} * to receive any available input buffer. For best performance, it * is recommended to exhaust both available input and output buffers in * the handling of a single callback, by calling the dequeue methods * repeatedly with a zero timeout until {@link #INFO_TRY_AGAIN_LATER} is returned. * Called when the MediaCodec encountered an error * * @param codec the MediaCodec instance that has an actionable event. * @param codec The MediaCodec object. * @param error a device specific error code. * @param actionCode a value for use in {@link MediaCodec.CodecException}. */ public abstract void onError(MediaCodec codec, int error, int actionCode); /** * Called when the output format has changed * * @param codec The MediaCodec object. * @param format The new output format. */ public abstract void onCodecNotify(MediaCodec codec); public abstract void onOutputFormatChanged(MediaCodec codec, MediaFormat format); } private void postEventFromNative( int what, int arg1, int arg2, Object obj) { if (mEventHandler != null && mNotificationCallback != null) { if (mEventHandler != null) { Message msg = mEventHandler.obtainMessage(what, arg1, arg2, obj); mEventHandler.sendMessage(msg); } Loading media/jni/android_media_MediaCodec.cpp +121 −66 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ enum { }; enum { EVENT_NOTIFY = 1, EVENT_CALLBACK = 1, EVENT_SET_CALLBACK = 2, }; struct CryptoErrorCodes { Loading Loading @@ -82,9 +83,7 @@ JMediaCodec::JMediaCodec( JNIEnv *env, jobject thiz, const char *name, bool nameIsType, bool encoder) : mClass(NULL), mObject(NULL), mGeneration(1), mRequestedActivityNotification(false) { mObject(NULL) { jclass clazz = env->GetObjectClass(thiz); CHECK(clazz != NULL); Loading Loading @@ -151,6 +150,18 @@ JMediaCodec::~JMediaCodec() { mClass = NULL; } status_t JMediaCodec::setCallback(jobject cb) { if (cb != NULL) { if (mCallbackNotification == NULL) { mCallbackNotification = new AMessage(kWhatCallbackNotify, id()); } } else { mCallbackNotification.clear(); } return mCodec->setCallback(mCallbackNotification); } status_t JMediaCodec::configure( const sp<AMessage> &format, const sp<IGraphicBufferProducer> &bufferProducer, Loading @@ -173,32 +184,13 @@ status_t JMediaCodec::createInputSurface( } status_t JMediaCodec::start() { status_t err = mCodec->start(); if (err != OK) { return err; } mActivityNotification = new AMessage(kWhatActivityNotify, id()); mActivityNotification->setInt32("generation", mGeneration); requestActivityNotification(); return err; return mCodec->start(); } status_t JMediaCodec::stop() { mSurfaceTextureClient.clear(); status_t err = mCodec->stop(); sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, id()); sp<AMessage> response; msg->postAndAwaitResponse(&response); mActivityNotification.clear(); return err; return mCodec->stop(); } status_t JMediaCodec::flush() { Loading Loading @@ -230,11 +222,7 @@ status_t JMediaCodec::queueSecureInputBuffer( } status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { status_t err = mCodec->dequeueInputBuffer(index, timeoutUs); requestActivityNotification(); return err; return mCodec->dequeueInputBuffer(index, timeoutUs); } status_t JMediaCodec::dequeueOutputBuffer( Loading @@ -245,8 +233,6 @@ status_t JMediaCodec::dequeueOutputBuffer( status_t err = mCodec->dequeueOutputBuffer( index, &offset, &size, &timeUs, &flags, timeoutUs); requestActivityNotification(); if (err != OK) { return err; } Loading Loading @@ -387,67 +373,116 @@ void JMediaCodec::setVideoScalingMode(int mode) { } } void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatRequestActivityNotifications: void JMediaCodec::handleCallback(const sp<AMessage> &msg) { int32_t arg1, arg2 = 0; jobject obj = NULL; CHECK(msg->findInt32("callbackID", &arg1)); JNIEnv *env = AndroidRuntime::getJNIEnv(); switch (arg1) { case MediaCodec::CB_INPUT_AVAILABLE: { if (mRequestedActivityNotification) { CHECK(msg->findInt32("index", &arg2)); break; } mCodec->requestActivityNotification(mActivityNotification); mRequestedActivityNotification = true; case MediaCodec::CB_OUTPUT_AVAILABLE: { CHECK(msg->findInt32("index", &arg2)); size_t size, offset; int64_t timeUs; uint32_t flags; CHECK(msg->findSize("size", &size)); CHECK(msg->findSize("offset", &offset)); CHECK(msg->findInt64("timeUs", &timeUs)); CHECK(msg->findInt32("flags", (int32_t *)&flags)); ScopedLocalRef<jclass> clazz( env, env->FindClass("android/media/MediaCodec$BufferInfo")); jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V"); jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V"); obj = env->NewObject(clazz.get(), ctor); if (obj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create MediaCodec.BufferInfo."); env->ExceptionClear(); } jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags); break; } case kWhatActivityNotify: case MediaCodec::CB_ERROR: { CHECK(msg->findInt32("err", &arg2)); int32_t actionCode; CHECK(msg->findInt32("actionCode", &actionCode)); // use Integer object to pass the action code ScopedLocalRef<jclass> clazz( env, env->FindClass("java/lang/Integer")); jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(I)V"); obj = env->NewObject(clazz.get(), ctor, actionCode); if (obj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create Integer object for actionCode."); env->ExceptionClear(); } jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } break; } case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: { int32_t generation; CHECK(msg->findInt32("generation", &generation)); sp<AMessage> format; CHECK(msg->findMessage("format", &format)); if (OK != ConvertMessageToMap(env, format, &obj)) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } if (generation != mGeneration) { // stale break; } mRequestedActivityNotification = false; default: TRESPASS(); } JNIEnv *env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod( mObject, gFields.postEventFromNativeID, EVENT_NOTIFY, 0 /* arg1 */, 0 /* arg2 */, NULL /* obj */); EVENT_CALLBACK, arg1, arg2, obj); break; env->DeleteLocalRef(obj); } case kWhatStopActivityNotifications: void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatCallbackNotify: { uint32_t replyID; CHECK(msg->senderAwaitsResponse(&replyID)); ++mGeneration; mRequestedActivityNotification = false; sp<AMessage> response = new AMessage; response->postReply(replyID); handleCallback(msg); break; } default: TRESPASS(); } } void JMediaCodec::requestActivityNotification() { (new AMessage(kWhatRequestActivityNotifications, id()))->post(); } } // namespace android //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -551,6 +586,22 @@ static jint throwExceptionAsNecessary( return 0; } static void android_media_MediaCodec_native_setCallback( JNIEnv *env, jobject thiz, jobject cb) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } status_t err = codec->setCallback(cb); throwExceptionAsNecessary(env, err); } static void android_media_MediaCodec_native_configure( JNIEnv *env, jobject thiz, Loading Loading @@ -1119,6 +1170,10 @@ static void android_media_MediaCodec_native_finalize( static JNINativeMethod gMethods[] = { { "release", "()V", (void *)android_media_MediaCodec_release }, { "native_setCallback", "(Landroid/media/MediaCodec$Callback;)V", (void *)android_media_MediaCodec_native_setCallback }, { "native_configure", "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;" "Landroid/media/MediaCrypto;I)V", Loading media/jni/android_media_MediaCodec.h +5 −8 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct JMediaCodec : public AHandler { void registerSelf(); void release(); status_t setCallback(jobject cb); status_t configure( const sp<AMessage> &format, const sp<IGraphicBufferProducer> &bufferProducer, Loading Loading @@ -99,12 +101,11 @@ protected: virtual ~JMediaCodec(); virtual void onMessageReceived(const sp<AMessage> &msg); void handleCallback(const sp<AMessage> &msg); private: enum { kWhatActivityNotify, kWhatRequestActivityNotifications, kWhatStopActivityNotifications, kWhatCallbackNotify, }; jclass mClass; Loading @@ -114,11 +115,7 @@ private: sp<ALooper> mLooper; sp<MediaCodec> mCodec; sp<AMessage> mActivityNotification; int32_t mGeneration; bool mRequestedActivityNotification; void requestActivityNotification(); sp<AMessage> mCallbackNotification; DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec); }; Loading Loading
api/current.txt +9 −0 Original line number Diff line number Diff line Loading @@ -14292,6 +14292,7 @@ package android.media { method public final void release(); method public final void releaseOutputBuffer(int, boolean); method public final void releaseOutputBuffer(int, long); method public void setCallback(android.media.MediaCodec.Callback); method public final void setParameters(android.os.Bundle); method public final void setVideoScalingMode(int); method public final void signalEndOfInputStream(); Loading Loading @@ -14322,6 +14323,14 @@ package android.media { field public int size; } public static abstract class MediaCodec.Callback { ctor public MediaCodec.Callback(); method public abstract void onError(android.media.MediaCodec, int, int); method public abstract void onInputBufferAvailable(android.media.MediaCodec, int); method public abstract void onOutputBufferAvailable(android.media.MediaCodec, int, android.media.MediaCodec.BufferInfo); method public abstract void onOutputFormatChanged(android.media.MediaCodec, android.media.MediaFormat); } public static final class MediaCodec.CodecException extends java.lang.IllegalStateException { ctor public MediaCodec.CodecException(int, int, java.lang.String); method public int getErrorCode();
media/java/android/media/MediaCodec.java +116 −31 Original line number Diff line number Diff line Loading @@ -205,9 +205,15 @@ final public class MediaCodec { public static final int BUFFER_FLAG_END_OF_STREAM = 4; private EventHandler mEventHandler; private volatile NotificationCallback mNotificationCallback; private Callback mCallback; static final int EVENT_NOTIFY = 1; private static final int EVENT_CALLBACK = 1; private static final int EVENT_SET_CALLBACK = 2; private static final int CB_INPUT_AVAILABLE = 1; private static final int CB_OUTPUT_AVAILABLE = 2; private static final int CB_ERROR = 3; private static final int CB_OUTPUT_FORMAT_CHANGE = 4; private class EventHandler extends Handler { private MediaCodec mCodec; Loading @@ -220,12 +226,60 @@ final public class MediaCodec { @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_NOTIFY: case EVENT_CALLBACK: { handleCallback(msg); break; } case EVENT_SET_CALLBACK: { mCallback = (MediaCodec.Callback) msg.obj; break; } default: { break; } } } private void handleCallback(Message msg) { if (mCallback == null) { return; } switch (msg.arg1) { case CB_INPUT_AVAILABLE: { mCallback.onInputBufferAvailable(mCodec, msg.arg2 /* index */); break; } case CB_OUTPUT_AVAILABLE: { mCallback.onOutputBufferAvailable( mCodec, msg.arg2 /* index */, (MediaCodec.BufferInfo) msg.obj); break; } case CB_ERROR: { NotificationCallback cb = mNotificationCallback; if (cb != null) { cb.onCodecNotify(mCodec); mCallback.onError(mCodec, msg.arg2 /* error */, (Integer) msg.obj /* actionCode */); break; } case CB_OUTPUT_FORMAT_CHANGE: { mCallback.onOutputFormatChanged(mCodec, new MediaFormat((Map<String, Object>) msg.obj)); break; } default: { break; } } Loading Loading @@ -360,6 +414,8 @@ final public class MediaCodec { native_configure(keys, values, surface, crypto, flags); } private native final void native_setCallback(Callback cb); private native final void native_configure( String[] keys, Object[] values, Surface surface, MediaCrypto crypto, int flags); Loading Loading @@ -398,7 +454,8 @@ final public class MediaCodec { native_stop(); if (mEventHandler != null) { mEventHandler.removeMessages(EVENT_NOTIFY); mEventHandler.removeMessages(EVENT_CALLBACK); mEventHandler.removeMessages(EVENT_SET_CALLBACK); } } Loading Loading @@ -855,44 +912,72 @@ final public class MediaCodec { } /** * Sets the codec listener for actionable MediaCodec events. * <p>Call this method with a null listener to stop receiving event notifications. * Sets an asynchronous callback for actionable MediaCodec events. * * If the client intends to use the component in asynchronous mode, * a valid callback should be provided before {@link #configure} is called. * * @param cb The listener that will run. * When asynchronous callback is enabled, the client should not call * {@link #dequeueInputBuffer(long)} or {@link #dequeueOutputBuffer(BufferInfo, long)} * * @hide * @param cb The callback that will run. */ public void setNotificationCallback(NotificationCallback cb) { mNotificationCallback = cb; public void setCallback(/* MediaCodec. */ Callback cb) { if (mEventHandler != null) { // set java callback on handler Message msg = mEventHandler.obtainMessage(EVENT_SET_CALLBACK, 0, 0, cb); mEventHandler.sendMessage(msg); // set native handler here, don't post to handler because // it may cause the callback to be delayed and set in a wrong state, // and MediaCodec is already doing it on looper. native_setCallback(cb); } } /** * MediaCodec callback interface. Used to notify the user asynchronously * of various MediaCodec events. */ public static abstract class Callback { /** * Called when an input buffer becomes available. * * @param codec The MediaCodec object. * @param index The index of the available input buffer. */ public abstract void onInputBufferAvailable(MediaCodec codec, int index); /** * MediaCodec listener interface. Used to notify the user of MediaCodec * when there are available input and/or output buffers, a change in * configuration or when a codec error happened. * Called when an output buffer becomes available. * * @hide * @param codec The MediaCodec object. * @param index The index of the available output buffer. * @param info Info regarding the available output buffer {@link MediaCodec.BufferInfo}. */ public static abstract class NotificationCallback { public abstract void onOutputBufferAvailable(MediaCodec codec, int index, BufferInfo info); /** * Called on the listener to notify that there is an actionable * MediaCodec event. The application should call {@link #dequeueOutputBuffer} * to receive the configuration change event, codec error or an * available output buffer. It should also call {@link #dequeueInputBuffer} * to receive any available input buffer. For best performance, it * is recommended to exhaust both available input and output buffers in * the handling of a single callback, by calling the dequeue methods * repeatedly with a zero timeout until {@link #INFO_TRY_AGAIN_LATER} is returned. * Called when the MediaCodec encountered an error * * @param codec the MediaCodec instance that has an actionable event. * @param codec The MediaCodec object. * @param error a device specific error code. * @param actionCode a value for use in {@link MediaCodec.CodecException}. */ public abstract void onError(MediaCodec codec, int error, int actionCode); /** * Called when the output format has changed * * @param codec The MediaCodec object. * @param format The new output format. */ public abstract void onCodecNotify(MediaCodec codec); public abstract void onOutputFormatChanged(MediaCodec codec, MediaFormat format); } private void postEventFromNative( int what, int arg1, int arg2, Object obj) { if (mEventHandler != null && mNotificationCallback != null) { if (mEventHandler != null) { Message msg = mEventHandler.obtainMessage(what, arg1, arg2, obj); mEventHandler.sendMessage(msg); } Loading
media/jni/android_media_MediaCodec.cpp +121 −66 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ enum { }; enum { EVENT_NOTIFY = 1, EVENT_CALLBACK = 1, EVENT_SET_CALLBACK = 2, }; struct CryptoErrorCodes { Loading Loading @@ -82,9 +83,7 @@ JMediaCodec::JMediaCodec( JNIEnv *env, jobject thiz, const char *name, bool nameIsType, bool encoder) : mClass(NULL), mObject(NULL), mGeneration(1), mRequestedActivityNotification(false) { mObject(NULL) { jclass clazz = env->GetObjectClass(thiz); CHECK(clazz != NULL); Loading Loading @@ -151,6 +150,18 @@ JMediaCodec::~JMediaCodec() { mClass = NULL; } status_t JMediaCodec::setCallback(jobject cb) { if (cb != NULL) { if (mCallbackNotification == NULL) { mCallbackNotification = new AMessage(kWhatCallbackNotify, id()); } } else { mCallbackNotification.clear(); } return mCodec->setCallback(mCallbackNotification); } status_t JMediaCodec::configure( const sp<AMessage> &format, const sp<IGraphicBufferProducer> &bufferProducer, Loading @@ -173,32 +184,13 @@ status_t JMediaCodec::createInputSurface( } status_t JMediaCodec::start() { status_t err = mCodec->start(); if (err != OK) { return err; } mActivityNotification = new AMessage(kWhatActivityNotify, id()); mActivityNotification->setInt32("generation", mGeneration); requestActivityNotification(); return err; return mCodec->start(); } status_t JMediaCodec::stop() { mSurfaceTextureClient.clear(); status_t err = mCodec->stop(); sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, id()); sp<AMessage> response; msg->postAndAwaitResponse(&response); mActivityNotification.clear(); return err; return mCodec->stop(); } status_t JMediaCodec::flush() { Loading Loading @@ -230,11 +222,7 @@ status_t JMediaCodec::queueSecureInputBuffer( } status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { status_t err = mCodec->dequeueInputBuffer(index, timeoutUs); requestActivityNotification(); return err; return mCodec->dequeueInputBuffer(index, timeoutUs); } status_t JMediaCodec::dequeueOutputBuffer( Loading @@ -245,8 +233,6 @@ status_t JMediaCodec::dequeueOutputBuffer( status_t err = mCodec->dequeueOutputBuffer( index, &offset, &size, &timeUs, &flags, timeoutUs); requestActivityNotification(); if (err != OK) { return err; } Loading Loading @@ -387,67 +373,116 @@ void JMediaCodec::setVideoScalingMode(int mode) { } } void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatRequestActivityNotifications: void JMediaCodec::handleCallback(const sp<AMessage> &msg) { int32_t arg1, arg2 = 0; jobject obj = NULL; CHECK(msg->findInt32("callbackID", &arg1)); JNIEnv *env = AndroidRuntime::getJNIEnv(); switch (arg1) { case MediaCodec::CB_INPUT_AVAILABLE: { if (mRequestedActivityNotification) { CHECK(msg->findInt32("index", &arg2)); break; } mCodec->requestActivityNotification(mActivityNotification); mRequestedActivityNotification = true; case MediaCodec::CB_OUTPUT_AVAILABLE: { CHECK(msg->findInt32("index", &arg2)); size_t size, offset; int64_t timeUs; uint32_t flags; CHECK(msg->findSize("size", &size)); CHECK(msg->findSize("offset", &offset)); CHECK(msg->findInt64("timeUs", &timeUs)); CHECK(msg->findInt32("flags", (int32_t *)&flags)); ScopedLocalRef<jclass> clazz( env, env->FindClass("android/media/MediaCodec$BufferInfo")); jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V"); jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V"); obj = env->NewObject(clazz.get(), ctor); if (obj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create MediaCodec.BufferInfo."); env->ExceptionClear(); } jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags); break; } case kWhatActivityNotify: case MediaCodec::CB_ERROR: { CHECK(msg->findInt32("err", &arg2)); int32_t actionCode; CHECK(msg->findInt32("actionCode", &actionCode)); // use Integer object to pass the action code ScopedLocalRef<jclass> clazz( env, env->FindClass("java/lang/Integer")); jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(I)V"); obj = env->NewObject(clazz.get(), ctor, actionCode); if (obj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create Integer object for actionCode."); env->ExceptionClear(); } jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } break; } case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: { int32_t generation; CHECK(msg->findInt32("generation", &generation)); sp<AMessage> format; CHECK(msg->findMessage("format", &format)); if (OK != ConvertMessageToMap(env, format, &obj)) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } if (generation != mGeneration) { // stale break; } mRequestedActivityNotification = false; default: TRESPASS(); } JNIEnv *env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod( mObject, gFields.postEventFromNativeID, EVENT_NOTIFY, 0 /* arg1 */, 0 /* arg2 */, NULL /* obj */); EVENT_CALLBACK, arg1, arg2, obj); break; env->DeleteLocalRef(obj); } case kWhatStopActivityNotifications: void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatCallbackNotify: { uint32_t replyID; CHECK(msg->senderAwaitsResponse(&replyID)); ++mGeneration; mRequestedActivityNotification = false; sp<AMessage> response = new AMessage; response->postReply(replyID); handleCallback(msg); break; } default: TRESPASS(); } } void JMediaCodec::requestActivityNotification() { (new AMessage(kWhatRequestActivityNotifications, id()))->post(); } } // namespace android //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -551,6 +586,22 @@ static jint throwExceptionAsNecessary( return 0; } static void android_media_MediaCodec_native_setCallback( JNIEnv *env, jobject thiz, jobject cb) { sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } status_t err = codec->setCallback(cb); throwExceptionAsNecessary(env, err); } static void android_media_MediaCodec_native_configure( JNIEnv *env, jobject thiz, Loading Loading @@ -1119,6 +1170,10 @@ static void android_media_MediaCodec_native_finalize( static JNINativeMethod gMethods[] = { { "release", "()V", (void *)android_media_MediaCodec_release }, { "native_setCallback", "(Landroid/media/MediaCodec$Callback;)V", (void *)android_media_MediaCodec_native_setCallback }, { "native_configure", "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;" "Landroid/media/MediaCrypto;I)V", Loading
media/jni/android_media_MediaCodec.h +5 −8 Original line number Diff line number Diff line Loading @@ -44,6 +44,8 @@ struct JMediaCodec : public AHandler { void registerSelf(); void release(); status_t setCallback(jobject cb); status_t configure( const sp<AMessage> &format, const sp<IGraphicBufferProducer> &bufferProducer, Loading Loading @@ -99,12 +101,11 @@ protected: virtual ~JMediaCodec(); virtual void onMessageReceived(const sp<AMessage> &msg); void handleCallback(const sp<AMessage> &msg); private: enum { kWhatActivityNotify, kWhatRequestActivityNotifications, kWhatStopActivityNotifications, kWhatCallbackNotify, }; jclass mClass; Loading @@ -114,11 +115,7 @@ private: sp<ALooper> mLooper; sp<MediaCodec> mCodec; sp<AMessage> mActivityNotification; int32_t mGeneration; bool mRequestedActivityNotification; void requestActivityNotification(); sp<AMessage> mCallbackNotification; DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec); }; Loading