From 1dcdfead2971c1fa7c02f24ba86f706890c9f99e Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 30 Apr 2015 13:59:10 -0700 Subject: stagefright: add support for dynamically setting MediaCodec output surface Bug: 11990461 Change-Id: I2aee89ef504234dc66eb5fcf6e62e1706088f758 --- media/libstagefright/MediaCodec.cpp | 115 +++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 22 deletions(-) (limited to 'media/libstagefright/MediaCodec.cpp') diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 9906a10..cf69418 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -523,6 +523,14 @@ status_t MediaCodec::configure( return err; } +status_t MediaCodec::setSurface(const sp &surface) { + sp msg = new AMessage(kWhatSetSurface, this); + msg->setObject("surface", surface); + + sp response; + return PostAndAwaitResponse(msg, &response); +} + status_t MediaCodec::createInputSurface( sp* bufferProducer) { sp msg = new AMessage(kWhatCreateInputSurface, this); @@ -1216,7 +1224,7 @@ void MediaCodec::onMessageReceived(const sp &msg) { { // response to initiateCreateInputSurface() status_t err = NO_ERROR; - sp response = new AMessage(); + sp response = new AMessage; if (!msg->findInt32("err", &err)) { sp obj; msg->findObject("input-surface", &obj); @@ -1233,7 +1241,7 @@ void MediaCodec::onMessageReceived(const sp &msg) { case CodecBase::kWhatSignaledInputEOS: { // response to signalEndOfInputStream() - sp response = new AMessage(); + sp response = new AMessage; status_t err; if (msg->findInt32("err", &err)) { response->setInt32("err", err); @@ -1639,6 +1647,61 @@ void MediaCodec::onMessageReceived(const sp &msg) { break; } + case kWhatSetSurface: + { + sp replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + status_t err = OK; + sp surface; + + switch (mState) { + case CONFIGURED: + case STARTED: + case FLUSHED: + { + sp obj; + (void)msg->findObject("surface", &obj); + sp surface = static_cast(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: { sp replyID; @@ -2401,36 +2464,44 @@ ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { return index; } -status_t MediaCodec::handleSetSurface(const sp &surface) { - status_t err; +status_t MediaCodec::connectToSurface(const sp &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) { + 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() { -- cgit v1.1