summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MediaCodec.cpp
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2015-05-02 02:23:06 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-02 02:23:07 +0000
commit8651c6f5069cca40ef805b800a9730617ff7f9b8 (patch)
tree129d2b9634ed11d920253265e86b171033887b39 /media/libstagefright/MediaCodec.cpp
parente2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049 (diff)
parent1dcdfead2971c1fa7c02f24ba86f706890c9f99e (diff)
downloadframeworks_av-8651c6f5069cca40ef805b800a9730617ff7f9b8.zip
frameworks_av-8651c6f5069cca40ef805b800a9730617ff7f9b8.tar.gz
frameworks_av-8651c6f5069cca40ef805b800a9730617ff7f9b8.tar.bz2
Merge "stagefright: add support for dynamically setting MediaCodec output surface" into mnc-dev
Diffstat (limited to 'media/libstagefright/MediaCodec.cpp')
-rw-r--r--media/libstagefright/MediaCodec.cpp115
1 files changed, 93 insertions, 22 deletions
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index ace7826..ed4f682 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -556,6 +556,14 @@ status_t MediaCodec::usePersistentInputSurface(
return PostAndAwaitResponse(msg, &response);
}
+status_t MediaCodec::setSurface(const sp<Surface> &surface) {
+ sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
+ msg->setObject("surface", surface);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
status_t MediaCodec::createInputSurface(
sp<IGraphicBufferProducer>* bufferProducer) {
sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
@@ -1249,7 +1257,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
{
// response to initiateCreateInputSurface()
status_t err = NO_ERROR;
- sp<AMessage> response = new AMessage();
+ sp<AMessage> response = new AMessage;
if (!msg->findInt32("err", &err)) {
sp<RefBase> obj;
msg->findObject("input-surface", &obj);
@@ -1280,7 +1288,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
case CodecBase::kWhatSignaledInputEOS:
{
// response to signalEndOfInputStream()
- sp<AMessage> response = new AMessage();
+ sp<AMessage> response = new AMessage;
status_t err;
if (msg->findInt32("err", &err)) {
response->setInt32("err", err);
@@ -1686,6 +1694,61 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatSetSurface:
+ {
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ status_t err = OK;
+ sp<Surface> surface;
+
+ switch (mState) {
+ case CONFIGURED:
+ case STARTED:
+ case FLUSHED:
+ {
+ sp<RefBase> obj;
+ (void)msg->findObject("surface", &obj);
+ sp<Surface> surface = static_cast<Surface *>(obj.get());
+ if (mSurface == NULL) {
+ // do not support setting surface if it was not set
+ err = INVALID_OPERATION;
+ } else if (obj == NULL) {
+ // do not support unsetting surface
+ err = BAD_VALUE;
+ } else {
+ err = connectToSurface(surface);
+ if (err == BAD_VALUE) {
+ // assuming reconnecting to same surface
+ // TODO: check if it is the same surface
+ err = OK;
+ } else {
+ if (err == OK) {
+ if (mFlags & kFlagUsesSoftwareRenderer) {
+ mSoftRenderer = new SoftwareRenderer(surface);
+ // TODO: check if this was successful
+ } else {
+ err = mCodec->setSurface(surface);
+ }
+ }
+ if (err == OK) {
+ (void)disconnectFromSurface();
+ mSurface = surface;
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ err = INVALID_OPERATION;
+ break;
+ }
+
+ PostReplyWithError(replyID, err);
+ break;
+ }
+
case kWhatCreateInputSurface:
case kWhatUsePersistentInputSurface:
{
@@ -2456,36 +2519,44 @@ ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
return index;
}
-status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
- status_t err;
+status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
+ status_t err = OK;
+ if (surface != NULL) {
+ err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+ if (err == BAD_VALUE) {
+ ALOGI("native window already connected. Assuming no change of surface");
+ } else if (err != OK) {
+ ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
+ }
+ }
+ return err;
+}
+status_t MediaCodec::disconnectFromSurface() {
+ status_t err = OK;
if (mSurface != NULL) {
- err = native_window_api_disconnect(
- mSurface.get(), NATIVE_WINDOW_API_MEDIA);
-
+ err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
if (err != OK) {
- ALOGW("native_window_api_disconnect returned an error: %s (%d)",
- strerror(-err), err);
+ ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
}
-
+ // assume disconnected even on error
mSurface.clear();
}
+ return err;
+}
+status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
+ status_t err = OK;
+ if (mSurface != NULL) {
+ (void)disconnectFromSurface();
+ }
if (surface != NULL) {
- err = native_window_api_connect(
- surface.get(), NATIVE_WINDOW_API_MEDIA);
-
- if (err != OK) {
- ALOGE("native_window_api_connect returned an error: %s (%d)",
- strerror(-err), err);
-
- return err;
+ err = connectToSurface(surface);
+ if (err == OK) {
+ mSurface = surface;
}
-
- mSurface = surface;
}
-
- return OK;
+ return err;
}
void MediaCodec::onInputBufferAvailable() {