Merge "media: hook up OnFrameRenderedListener events to framework events" into mnc-dev
This commit is contained in:
@@ -1455,15 +1455,6 @@ final public class MediaCodec {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface BufferFlag {}
|
||||
|
||||
private static class FrameRenderedInfo {
|
||||
public long mPresentationTimeUs;
|
||||
public long mNanoTime;
|
||||
public FrameRenderedInfo(long presentationTimeUs, long nanoTime) {
|
||||
mPresentationTimeUs = presentationTimeUs;
|
||||
mNanoTime = nanoTime;
|
||||
}
|
||||
}
|
||||
|
||||
private EventHandler mEventHandler;
|
||||
private EventHandler mOnFrameRenderedHandler;
|
||||
private EventHandler mCallbackHandler;
|
||||
@@ -1503,10 +1494,16 @@ final public class MediaCodec {
|
||||
}
|
||||
case EVENT_FRAME_RENDERED:
|
||||
synchronized (mListenerLock) {
|
||||
FrameRenderedInfo info = (FrameRenderedInfo)msg.obj;
|
||||
if (mOnFrameRenderedListener != null) {
|
||||
Map<String, Object> map = (Map<String, Object>)msg.obj;
|
||||
for (int i = 0; ; ++i) {
|
||||
Object mediaTimeUs = map.get(i + "-media-time-us");
|
||||
Object systemNano = map.get(i + "-system-nano");
|
||||
if (mediaTimeUs == null || systemNano == null
|
||||
|| mOnFrameRenderedListener == null) {
|
||||
break;
|
||||
}
|
||||
mOnFrameRenderedListener.onFrameRendered(
|
||||
mCodec, info.mPresentationTimeUs, info.mNanoTime);
|
||||
mCodec, (long)mediaTimeUs, (long)systemNano);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2362,26 +2359,9 @@ final public class MediaCodec {
|
||||
info = mDequeuedOutputInfos.remove(index);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// until codec and libgui supports callback, assume frame is rendered within 50 ms
|
||||
postRenderedCallback(render, info, 50 /* delayMs */);
|
||||
releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */);
|
||||
}
|
||||
|
||||
private void postRenderedCallback(boolean render, @Nullable BufferInfo info, long delayMs) {
|
||||
if (render && info != null) {
|
||||
synchronized (mListenerLock) {
|
||||
if (mOnFrameRenderedListener != null) {
|
||||
FrameRenderedInfo obj = new FrameRenderedInfo(
|
||||
info.presentationTimeUs, System.nanoTime() + delayMs * 1000000);
|
||||
Message msg = mOnFrameRenderedHandler.obtainMessage(
|
||||
EVENT_FRAME_RENDERED, obj);
|
||||
mOnFrameRenderedHandler.sendMessageDelayed(msg, delayMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If you are done with a buffer, use this call to update its surface timestamp
|
||||
* and return it to the codec to render it on the output surface. If you
|
||||
@@ -2440,12 +2420,6 @@ final public class MediaCodec {
|
||||
info = mDequeuedOutputInfos.remove(index);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// until codec and libgui supports callback, assume frame is rendered at the
|
||||
// render time or 16 ms from now, whichever is later.
|
||||
postRenderedCallback(
|
||||
true /* render */, info,
|
||||
Math.max(renderTimestampNs - System.nanoTime(), 16666666) / 1000000);
|
||||
releaseOutputBuffer(
|
||||
index, true /* render */, true /* updatePTS */, renderTimestampNs);
|
||||
}
|
||||
@@ -3049,9 +3023,12 @@ final public class MediaCodec {
|
||||
} else if (mOnFrameRenderedHandler != null) {
|
||||
mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED);
|
||||
}
|
||||
native_enableOnFrameRenderedListener(listener != null);
|
||||
}
|
||||
}
|
||||
|
||||
private native void native_enableOnFrameRenderedListener(boolean enable);
|
||||
|
||||
private EventHandler getEventHandlerOn(
|
||||
@Nullable Handler handler, @NonNull EventHandler lastHandler) {
|
||||
if (handler == null) {
|
||||
|
||||
@@ -56,6 +56,7 @@ enum {
|
||||
enum {
|
||||
EVENT_CALLBACK = 1,
|
||||
EVENT_SET_CALLBACK = 2,
|
||||
EVENT_FRAME_RENDERED = 3,
|
||||
};
|
||||
|
||||
static struct CryptoErrorCodes {
|
||||
@@ -226,6 +227,18 @@ void JMediaCodec::deleteJavaObjects(JNIEnv *env) {
|
||||
mByteBufferLimitMethodID = NULL;
|
||||
}
|
||||
|
||||
status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
|
||||
if (enable) {
|
||||
if (mOnFrameRenderedNotification == NULL) {
|
||||
mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this);
|
||||
}
|
||||
} else {
|
||||
mOnFrameRenderedNotification.clear();
|
||||
}
|
||||
|
||||
return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification);
|
||||
}
|
||||
|
||||
status_t JMediaCodec::setCallback(jobject cb) {
|
||||
if (cb != NULL) {
|
||||
if (mCallbackNotification == NULL) {
|
||||
@@ -728,6 +741,27 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
|
||||
env->DeleteLocalRef(obj);
|
||||
}
|
||||
|
||||
void JMediaCodec::handleFrameRenderedNotification(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_FRAME_RENDERED, arg1, arg2, obj);
|
||||
|
||||
env->DeleteLocalRef(obj);
|
||||
}
|
||||
|
||||
void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
|
||||
switch (msg->what()) {
|
||||
case kWhatCallbackNotify:
|
||||
@@ -735,6 +769,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
|
||||
handleCallback(msg);
|
||||
break;
|
||||
}
|
||||
case kWhatFrameRendered:
|
||||
{
|
||||
handleFrameRenderedNotification(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
TRESPASS();
|
||||
}
|
||||
@@ -848,6 +887,22 @@ static jint throwExceptionAsNecessary(
|
||||
}
|
||||
}
|
||||
|
||||
static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
jboolean enabled) {
|
||||
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
|
||||
|
||||
if (codec == NULL) {
|
||||
throwExceptionAsNecessary(env, INVALID_OPERATION);
|
||||
return;
|
||||
}
|
||||
|
||||
status_t err = codec->enableOnFrameRenderedListener(enabled);
|
||||
|
||||
throwExceptionAsNecessary(env, err);
|
||||
}
|
||||
|
||||
static void android_media_MediaCodec_native_setCallback(
|
||||
JNIEnv *env,
|
||||
jobject thiz,
|
||||
@@ -1744,6 +1799,9 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "native_setInputSurface", "(Landroid/view/Surface;)V",
|
||||
(void *)android_media_MediaCodec_setInputSurface },
|
||||
|
||||
{ "native_enableOnFrameRenderedListener", "(Z)V",
|
||||
(void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
|
||||
|
||||
{ "native_setCallback",
|
||||
"(Landroid/media/MediaCodec$Callback;)V",
|
||||
(void *)android_media_MediaCodec_native_setCallback },
|
||||
|
||||
@@ -46,6 +46,8 @@ struct JMediaCodec : public AHandler {
|
||||
void registerSelf();
|
||||
void release();
|
||||
|
||||
status_t enableOnFrameRenderedListener(jboolean enable);
|
||||
|
||||
status_t setCallback(jobject cb);
|
||||
|
||||
status_t configure(
|
||||
@@ -116,11 +118,11 @@ protected:
|
||||
virtual ~JMediaCodec();
|
||||
|
||||
virtual void onMessageReceived(const sp<AMessage> &msg);
|
||||
void handleCallback(const sp<AMessage> &msg);
|
||||
|
||||
private:
|
||||
enum {
|
||||
kWhatCallbackNotify,
|
||||
kWhatFrameRendered,
|
||||
};
|
||||
|
||||
jclass mClass;
|
||||
@@ -139,6 +141,7 @@ private:
|
||||
sp<MediaCodec> mCodec;
|
||||
|
||||
sp<AMessage> mCallbackNotification;
|
||||
sp<AMessage> mOnFrameRenderedNotification;
|
||||
|
||||
status_t mInitStatus;
|
||||
|
||||
@@ -148,6 +151,8 @@ private:
|
||||
|
||||
void cacheJavaObjects(JNIEnv *env);
|
||||
void deleteJavaObjects(JNIEnv *env);
|
||||
void handleCallback(const sp<AMessage> &msg);
|
||||
void handleFrameRenderedNotification(const sp<AMessage> &msg);
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user