From 3a01a71dcbb467d06cc5da4a72a82bb588648cfc Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Fri, 30 Jan 2015 19:30:05 -0800 Subject: stagefright: add fallback for native flex-YUV support Use software renderer if codec cannot support flex-YUV on a surface Bug: 17906609 Change-Id: I3d0e3ff5fee7d7b3e2416892968fa18f6139598a --- include/media/stagefright/MediaCodec.h | 2 +- media/libstagefright/ACodec.cpp | 90 ++++++++++++++++++++++++++++------ media/libstagefright/MediaCodec.cpp | 11 +++-- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index 54a4e8b..d448097 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -194,7 +194,7 @@ private: }; enum { - kFlagIsSoftwareCodec = 1, + kFlagUsesSoftwareRenderer = 1, kFlagOutputFormatChanged = 2, kFlagOutputBuffersChanged = 4, kFlagStickyError = 8, diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 11043f8..72518a9 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1258,9 +1258,10 @@ status_t ACodec::configureCodec( } } + // NOTE: we only use native window for video decoders sp obj; bool haveNativeWindow = msg->findObject("native-window", &obj) - && obj != NULL; + && obj != NULL && video && !encoder; mStoreMetaDataInOutputBuffers = false; if (video && !encoder) { inputFormat->setInt32("adaptive-playback", false); @@ -1275,7 +1276,7 @@ status_t ACodec::configureCodec( mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; } } - if (!encoder && video && haveNativeWindow) { + if (haveNativeWindow) { sp windowWrapper( static_cast(obj.get())); sp nativeWindow = windowWrapper->getNativeWindow(); @@ -1324,6 +1325,8 @@ status_t ACodec::configureCodec( if (err != OK) { ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d", mComponentName.c_str(), err); + // allow failure + err = OK; } else { inputFormat->setInt32("max-width", maxWidth); inputFormat->setInt32("max-height", maxHeight); @@ -1417,11 +1420,80 @@ status_t ACodec::configureCodec( } if (video) { + // determine need for software renderer + bool usingSwRenderer = false; + if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) { + usingSwRenderer = true; + haveNativeWindow = false; + } + if (encoder) { err = setupVideoEncoder(mime, msg); } else { err = setupVideoDecoder(mime, msg, haveNativeWindow); } + + if (err != OK) { + return err; + } + + if (haveNativeWindow) { + sp nativeWindow( + static_cast(obj.get())); + CHECK(nativeWindow != NULL); + mNativeWindow = nativeWindow->getNativeWindow(); + + native_window_set_scaling_mode( + mNativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + } + + // initialize native window now to get actual output format + // TODO: this is needed for some encoders even though they don't use native window + CHECK_EQ((status_t)OK, initNativeWindow()); + + // fallback for devices that do not handle flex-YUV for native buffers + if (haveNativeWindow) { + int32_t requestedColorFormat = OMX_COLOR_FormatUnused; + if (msg->findInt32("color-format", &requestedColorFormat) && + requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) { + CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK); + int32_t colorFormat = OMX_COLOR_FormatUnused; + OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused; + CHECK(outputFormat->findInt32("color-format", &colorFormat)); + ALOGD("[%s] Requested output format %#x and got %#x.", + mComponentName.c_str(), requestedColorFormat, colorFormat); + if (!isFlexibleColorFormat( + mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent) + || flexibleEquivalent != (OMX_U32)requestedColorFormat) { + // device did not handle flex-YUV request for native window, fall back + // to SW renderer + ALOGI("[%s] Falling back to software renderer", mComponentName.c_str()); + mNativeWindow.clear(); + haveNativeWindow = false; + usingSwRenderer = true; + if (mStoreMetaDataInOutputBuffers) { + err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_FALSE); + mStoreMetaDataInOutputBuffers = false; + // TODO: implement adaptive-playback support for bytebuffer mode. + // This is done by SW codecs, but most HW codecs don't support it. + inputFormat->setInt32("adaptive-playback", false); + } + if (err == OK) { + err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE); + } + if (mFlags & kFlagIsGrallocUsageProtected) { + // fallback is not supported for protected playback + err = PERMISSION_DENIED; + } else if (err == OK) { + err = setupVideoDecoder(mime, msg, false); + } + } + } + } + + if (usingSwRenderer) { + outputFormat->setInt32("using-sw-renderer", 1); + } } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { int32_t numChannels, sampleRate; if (!msg->findInt32("channel-count", &numChannels) @@ -4922,20 +4994,6 @@ bool ACodec::LoadedState::onConfigureComponent( return false; } - sp obj; - if (msg->findObject("native-window", &obj) - && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) { - sp nativeWindow( - static_cast(obj.get())); - CHECK(nativeWindow != NULL); - mCodec->mNativeWindow = nativeWindow->getNativeWindow(); - - native_window_set_scaling_mode( - mCodec->mNativeWindow.get(), - NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - } - CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); - { sp notify = mCodec->mNotify->dup(); notify->setInt32("what", CodecBase::kWhatComponentConfigured); diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index c2381b4..a9c3a04 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -869,9 +869,9 @@ void MediaCodec::onMessageReceived(const sp &msg) { CHECK(msg->findString("componentName", &mComponentName)); if (mComponentName.startsWith("OMX.google.")) { - mFlags |= kFlagIsSoftwareCodec; + mFlags |= kFlagUsesSoftwareRenderer; } else { - mFlags &= ~kFlagIsSoftwareCodec; + mFlags &= ~kFlagUsesSoftwareRenderer; } if (mComponentName.endsWith(".secure")) { @@ -894,6 +894,11 @@ void MediaCodec::onMessageReceived(const sp &msg) { CHECK(msg->findMessage("input-format", &mInputFormat)); CHECK(msg->findMessage("output-format", &mOutputFormat)); + int32_t usingSwRenderer; + if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer) + && usingSwRenderer) { + mFlags |= kFlagUsesSoftwareRenderer; + } setState(CONFIGURED); (new AMessage)->postReply(mReplyID); break; @@ -989,7 +994,7 @@ void MediaCodec::onMessageReceived(const sp &msg) { if (mSoftRenderer == NULL && mNativeWindow != NULL && - (mFlags & kFlagIsSoftwareCodec)) { + (mFlags & kFlagUsesSoftwareRenderer)) { AString mime; CHECK(msg->findString("mime", &mime)); -- cgit v1.1