status_t requestIDRFrame();
+ // Notification will be posted once there "is something to do", i.e.
+ // an input/output buffer has become available, a format change is
+ // pending, an error is pending.
+ void requestActivityNotification(const sp<AMessage> ¬ify);
+
protected:
virtual ~MediaCodec();
virtual void onMessageReceived(const sp<AMessage> &msg);
};
enum {
- kWhatInit = 'init',
- kWhatConfigure = 'conf',
- kWhatStart = 'strt',
- kWhatStop = 'stop',
- kWhatRelease = 'rele',
- kWhatDequeueInputBuffer = 'deqI',
- kWhatQueueInputBuffer = 'queI',
- kWhatDequeueOutputBuffer = 'deqO',
- kWhatReleaseOutputBuffer = 'relO',
- kWhatGetBuffers = 'getB',
- kWhatFlush = 'flus',
- kWhatGetOutputFormat = 'getO',
- kWhatDequeueInputTimedOut = 'dITO',
- kWhatDequeueOutputTimedOut = 'dOTO',
- kWhatCodecNotify = 'codc',
- kWhatRequestIDRFrame = 'ridr',
+ kWhatInit = 'init',
+ kWhatConfigure = 'conf',
+ kWhatStart = 'strt',
+ kWhatStop = 'stop',
+ kWhatRelease = 'rele',
+ kWhatDequeueInputBuffer = 'deqI',
+ kWhatQueueInputBuffer = 'queI',
+ kWhatDequeueOutputBuffer = 'deqO',
+ kWhatReleaseOutputBuffer = 'relO',
+ kWhatGetBuffers = 'getB',
+ kWhatFlush = 'flus',
+ kWhatGetOutputFormat = 'getO',
+ kWhatDequeueInputTimedOut = 'dITO',
+ kWhatDequeueOutputTimedOut = 'dOTO',
+ kWhatCodecNotify = 'codc',
+ kWhatRequestIDRFrame = 'ridr',
+ kWhatRequestActivityNotification = 'racN',
};
enum {
List<sp<ABuffer> > mCSD;
+ sp<AMessage> mActivityNotify;
+
MediaCodec(const sp<ALooper> &looper);
static status_t PostAndAwaitResponse(
status_t setNativeWindow(
const sp<SurfaceTextureClient> &surfaceTextureClient);
+ void postActivityNotificationIfPossible();
+
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
return OK;
}
+void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) {
+ sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
+ msg->setMessage("notify", notify);
+ msg->post();
+}
+
////////////////////////////////////////////////////////////////////////////////
void MediaCodec::cancelPendingDequeueOperations() {
sendErrorReponse = false;
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
cancelPendingDequeueOperations();
break;
sendErrorReponse = false;
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
break;
}
}
(new AMessage)->postReply(mReplyID);
} else {
mFlags |= kFlagOutputBuffersChanged;
+ postActivityNotificationIfPossible();
}
}
break;
mOutputFormat = msg;
mFlags |= kFlagOutputFormatChanged;
+ postActivityNotificationIfPossible();
break;
}
err);
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
+
cancelPendingDequeueOperations();
}
break;
++mDequeueInputTimeoutGeneration;
mFlags &= ~kFlagDequeueInputPending;
mDequeueInputReplyID = 0;
+ } else {
+ postActivityNotificationIfPossible();
}
break;
}
++mDequeueOutputTimeoutGeneration;
mFlags &= ~kFlagDequeueOutputPending;
mDequeueOutputReplyID = 0;
+ } else {
+ postActivityNotificationIfPossible();
}
+
break;
}
break;
}
+ case kWhatRequestActivityNotification:
+ {
+ CHECK(mActivityNotify == NULL);
+ CHECK(msg->findMessage("notify", &mActivityNotify));
+
+ postActivityNotificationIfPossible();
+ break;
+ }
+
default:
TRESPASS();
}
mFlags &= ~kFlagOutputFormatChanged;
mFlags &= ~kFlagOutputBuffersChanged;
mFlags &= ~kFlagStickyError;
+
+ mActivityNotify.clear();
}
mState = newState;
return OK;
}
+void MediaCodec::postActivityNotificationIfPossible() {
+ if (mActivityNotify == NULL) {
+ return;
+ }
+
+ if ((mFlags & (kFlagStickyError
+ | kFlagOutputBuffersChanged
+ | kFlagOutputFormatChanged))
+ || !mAvailPortBuffers[kPortIndexInput].empty()
+ || !mAvailPortBuffers[kPortIndexOutput].empty()) {
+ mActivityNotify->post();
+ mActivityNotify.clear();
+ }
+}
+
} // namespace android
break;
}
- case kWhatDoMoreWork:
+ case kWhatEncoderActivity:
{
+#if 0
+ int64_t whenUs;
+ if (msg->findInt64("whenUs", &whenUs)) {
+ int64_t nowUs = ALooper::GetNowUs();
+ ALOGI("[%s] kWhatEncoderActivity after %lld us",
+ mIsVideo ? "video" : "audio", nowUs - whenUs);
+ }
+#endif
+
mDoMoreWorkPending = false;
if (mEncoder == NULL) {
}
mDoMoreWorkPending = true;
- (new AMessage(kWhatDoMoreWork, id()))->post(1000ll);
+
+#if 1
+ if (mEncoderActivityNotify == NULL) {
+ mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, id());
+ }
+ mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
+#else
+ sp<AMessage> notify = new AMessage(kWhatEncoderActivity, id());
+ notify->setInt64("whenUs", ALooper::GetNowUs());
+ mEncoder->requestActivityNotification(notify);
+#endif
}
status_t Converter::feedEncoderInputBuffers() {
}
status_t Converter::doMoreWork() {
- size_t bufferIndex;
- status_t err = mEncoder->dequeueInputBuffer(&bufferIndex);
+ status_t err;
+
+ for (;;) {
+ size_t bufferIndex;
+ err = mEncoder->dequeueInputBuffer(&bufferIndex);
+
+ if (err != OK) {
+ break;
+ }
- if (err == OK) {
mAvailEncoderInputIndices.push_back(bufferIndex);
- feedEncoderInputBuffers();
}
+ feedEncoderInputBuffers();
+
for (;;) {
+ size_t bufferIndex;
size_t offset;
size_t size;
int64_t timeUs;
kWhatRequestIDRFrame,
kWhatShutdown,
kWhatMediaPullerNotify,
+ kWhatEncoderActivity,
};
void shutdownAsync();
sp<AMessage> mOutputFormat;
sp<MediaCodec> mEncoder;
+ sp<AMessage> mEncoderActivityNotify;
Vector<sp<ABuffer> > mEncoderInputBuffers;
Vector<sp<ABuffer> > mEncoderOutputBuffers;