From 5a446aafff3020d607ad6fb14cc7ae76dd8f7947 Mon Sep 17 00:00:00 2001 From: Rachad Date: Tue, 29 Jul 2014 16:47:56 -0700 Subject: Added Tunneled video playback support to ACodec Bug:16132368 Change-Id: I88d2d66b8548fc203f4a2c4797196af15e56ff38 --- media/libmedia/IOMX.cpp | 38 ++++++ media/libstagefright/ACodec.cpp | 157 ++++++++++++++++--------- media/libstagefright/OMXClient.cpp | 11 ++ media/libstagefright/include/OMX.h | 4 + media/libstagefright/include/OMXNodeInstance.h | 4 + media/libstagefright/omx/OMX.cpp | 7 ++ media/libstagefright/omx/OMXNodeInstance.cpp | 43 +++++++ 7 files changed, 207 insertions(+), 57 deletions(-) (limited to 'media') diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp index 5df232f..c583d32 100644 --- a/media/libmedia/IOMX.cpp +++ b/media/libmedia/IOMX.cpp @@ -54,6 +54,7 @@ enum { GET_GRAPHIC_BUFFER_USAGE, SET_INTERNAL_OPTION, UPDATE_GRAPHIC_BUFFER_IN_META, + CONFIGURE_VIDEO_TUNNEL_MODE, }; class BpOMX : public BpInterface { @@ -368,6 +369,25 @@ public: return err; } + virtual status_t configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle ) { + Parcel data, reply; + data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); + data.writeInt32((int32_t)node); + data.writeInt32(portIndex); + data.writeInt32((int32_t)tunneled); + data.writeInt32(audioHwSync); + remote()->transact(CONFIGURE_VIDEO_TUNNEL_MODE, data, &reply); + + status_t err = reply.readInt32(); + if (sidebandHandle) { + *sidebandHandle = (native_handle_t *)reply.readNativeHandle(); + } + return err; + } + + virtual status_t allocateBuffer( node_id node, OMX_U32 port_index, size_t size, buffer_id *buffer, void **buffer_data) { @@ -804,6 +824,24 @@ status_t BnOMX::onTransact( return NO_ERROR; } + case CONFIGURE_VIDEO_TUNNEL_MODE: + { + CHECK_OMX_INTERFACE(IOMX, data, reply); + + node_id node = (node_id)data.readInt32(); + OMX_U32 port_index = data.readInt32(); + OMX_BOOL tunneled = (OMX_BOOL)data.readInt32(); + OMX_U32 audio_hw_sync = data.readInt32(); + + native_handle_t *sideband_handle; + status_t err = configureVideoTunnelMode( + node, port_index, tunneled, audio_hw_sync, &sideband_handle); + reply->writeInt32(err); + reply->writeNativeHandle(sideband_handle); + + return NO_ERROR; + } + case ALLOC_BUFFER: { CHECK_OMX_INTERFACE(IOMX, data, reply); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 503ce81..ac80da2 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1224,77 +1224,99 @@ status_t ACodec::configureCodec( } } - // Always try to enable dynamic output buffers on native surface sp obj; int32_t haveNativeWindow = msg->findObject("native-window", &obj) && - obj != NULL; + obj != NULL; mStoreMetaDataInOutputBuffers = false; if (video && !encoder) { inputFormat->setInt32("adaptive-playback", false); } if (!encoder && video && haveNativeWindow) { - err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_TRUE); - if (err != OK) { - ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", - mComponentName.c_str(), err); - - // if adaptive playback has been requested, try JB fallback - // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS - // LARGE MEMORY REQUIREMENT - - // we will not do adaptive playback on software accessed - // surfaces as they never had to respond to changes in the - // crop window, and we don't trust that they will be able to. - int usageBits = 0; - bool canDoAdaptivePlayback; - - sp windowWrapper( - static_cast(obj.get())); - sp nativeWindow = windowWrapper->getNativeWindow(); - - if (nativeWindow->query( - nativeWindow.get(), - NATIVE_WINDOW_CONSUMER_USAGE_BITS, - &usageBits) != OK) { - canDoAdaptivePlayback = false; - } else { - canDoAdaptivePlayback = - (usageBits & - (GRALLOC_USAGE_SW_READ_MASK | - GRALLOC_USAGE_SW_WRITE_MASK)) == 0; + sp windowWrapper( + static_cast(obj.get())); + sp nativeWindow = windowWrapper->getNativeWindow(); + + int32_t tunneled; + if (msg->findInt32("feature-tunneled-playback", &tunneled) && + tunneled != 0) { + ALOGI("Configuring TUNNELED video playback."); + + int64_t audioHwSync = 0; + if (!msg->findInt64("audio-hw-sync", &audioHwSync)) { + ALOGW("No Audio HW Sync provided for video tunnel"); + } + err = configureTunneledVideoPlayback(audioHwSync, nativeWindow); + if (err != OK) { + ALOGE("configureTunneledVideoPlayback(%" PRId64 ",%p) failed!", + audioHwSync, nativeWindow.get()); + return err; } - int32_t maxWidth = 0, maxHeight = 0; - if (canDoAdaptivePlayback && - msg->findInt32("max-width", &maxWidth) && - msg->findInt32("max-height", &maxHeight)) { - ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", - mComponentName.c_str(), maxWidth, maxHeight); - - err = mOMX->prepareForAdaptivePlayback( - mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight); - ALOGW_IF(err != OK, - "[%s] prepareForAdaptivePlayback failed w/ err %d", + inputFormat->setInt32("adaptive-playback", true); + } else { + // Always try to enable dynamic output buffers on native surface + err = mOMX->storeMetaDataInBuffers( + mNode, kPortIndexOutput, OMX_TRUE); + if (err != OK) { + ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d", mComponentName.c_str(), err); - if (err == OK) { - inputFormat->setInt32("max-width", maxWidth); - inputFormat->setInt32("max-height", maxHeight); - inputFormat->setInt32("adaptive-playback", true); + // if adaptive playback has been requested, try JB fallback + // NOTE: THIS FALLBACK MECHANISM WILL BE REMOVED DUE TO ITS + // LARGE MEMORY REQUIREMENT + + // we will not do adaptive playback on software accessed + // surfaces as they never had to respond to changes in the + // crop window, and we don't trust that they will be able to. + int usageBits = 0; + bool canDoAdaptivePlayback; + + if (nativeWindow->query( + nativeWindow.get(), + NATIVE_WINDOW_CONSUMER_USAGE_BITS, + &usageBits) != OK) { + canDoAdaptivePlayback = false; + } else { + canDoAdaptivePlayback = + (usageBits & + (GRALLOC_USAGE_SW_READ_MASK | + GRALLOC_USAGE_SW_WRITE_MASK)) == 0; + } + + int32_t maxWidth = 0, maxHeight = 0; + if (canDoAdaptivePlayback && + msg->findInt32("max-width", &maxWidth) && + msg->findInt32("max-height", &maxHeight)) { + ALOGV("[%s] prepareForAdaptivePlayback(%dx%d)", + mComponentName.c_str(), maxWidth, maxHeight); + + err = mOMX->prepareForAdaptivePlayback( + mNode, kPortIndexOutput, OMX_TRUE, maxWidth, + maxHeight); + ALOGW_IF(err != OK, + "[%s] prepareForAdaptivePlayback failed w/ err %d", + mComponentName.c_str(), err); + + if (err == OK) { + inputFormat->setInt32("max-width", maxWidth); + inputFormat->setInt32("max-height", maxHeight); + inputFormat->setInt32("adaptive-playback", true); + } } + // allow failure + err = OK; + } else { + ALOGV("[%s] storeMetaDataInBuffers succeeded", + mComponentName.c_str()); + mStoreMetaDataInOutputBuffers = true; + inputFormat->setInt32("adaptive-playback", true); } - // allow failure - err = OK; - } else { - ALOGV("[%s] storeMetaDataInBuffers succeeded", mComponentName.c_str()); - mStoreMetaDataInOutputBuffers = true; - inputFormat->setInt32("adaptive-playback", true); - } - int32_t push; - if (msg->findInt32("push-blank-buffers-on-shutdown", &push) - && push != 0) { - mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; + int32_t push; + if (msg->findInt32("push-blank-buffers-on-shutdown", &push) + && push != 0) { + mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown; + } } int32_t rotationDegrees; @@ -1869,6 +1891,27 @@ status_t ACodec::setupRawAudioFormat( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); } +status_t ACodec::configureTunneledVideoPlayback( + int64_t audioHwSync, const sp &nativeWindow) { + native_handle_t* sidebandHandle; + + status_t err = mOMX->configureVideoTunnelMode( + mNode, kPortIndexOutput, OMX_TRUE, audioHwSync, &sidebandHandle); + if (err != OK) { + ALOGE("configureVideoTunnelMode failed! (err %d).", err); + return err; + } + + err = native_window_set_sideband_stream(nativeWindow.get(), sidebandHandle); + if (err != OK) { + ALOGE("native_window_set_sideband_stream(%p) failed! (err %d).", + sidebandHandle, err); + return err; + } + + return OK; +} + status_t ACodec::setVideoPortFormatType( OMX_U32 portIndex, OMX_VIDEO_CODINGTYPE compressionFormat, diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp index aca21cf..ca031aa 100644 --- a/media/libstagefright/OMXClient.cpp +++ b/media/libstagefright/OMXClient.cpp @@ -78,6 +78,10 @@ struct MuxOMX : public IOMX { node_id node, OMX_U32 port_index, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight); + virtual status_t configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle); + virtual status_t enableGraphicBuffers( node_id node, OMX_U32 port_index, OMX_BOOL enable); @@ -291,6 +295,13 @@ status_t MuxOMX::prepareForAdaptivePlayback( node, port_index, enable, maxFrameWidth, maxFrameHeight); } +status_t MuxOMX::configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL enable, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { + return getOMX(node)->configureVideoTunnelMode( + node, portIndex, enable, audioHwSync, sidebandHandle); +} + status_t MuxOMX::enableGraphicBuffers( node_id node, OMX_U32 port_index, OMX_BOOL enable) { return getOMX(node)->enableGraphicBuffers(node, port_index, enable); diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h index cd51bbf..e8c4970 100644 --- a/media/libstagefright/include/OMX.h +++ b/media/libstagefright/include/OMX.h @@ -75,6 +75,10 @@ public: node_id node, OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 max_frame_width, OMX_U32 max_frame_height); + virtual status_t configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle); + virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, buffer_id *buffer); diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h index 3967dc6..dc6d410 100644 --- a/media/libstagefright/include/OMXNodeInstance.h +++ b/media/libstagefright/include/OMXNodeInstance.h @@ -62,6 +62,10 @@ struct OMXNodeInstance { OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight); + status_t configureVideoTunnelMode( + OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle); + status_t useBuffer( OMX_U32 portIndex, const sp ¶ms, OMX::buffer_id *buffer); diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp index cc4770a..41407e4 100644 --- a/media/libstagefright/omx/OMX.cpp +++ b/media/libstagefright/omx/OMX.cpp @@ -342,6 +342,13 @@ status_t OMX::prepareForAdaptivePlayback( portIndex, enable, maxFrameWidth, maxFrameHeight); } +status_t OMX::configureVideoTunnelMode( + node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, + OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { + return findInstance(node)->configureVideoTunnelMode( + portIndex, tunneled, audioHwSync, sidebandHandle); +} + status_t OMX::useBuffer( node_id node, OMX_U32 port_index, const sp ¶ms, buffer_id *buffer) { diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index d6ab109..efb27f5 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -460,6 +460,49 @@ status_t OMXNodeInstance::prepareForAdaptivePlayback( return err; } +status_t OMXNodeInstance::configureVideoTunnelMode( + OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, + native_handle_t **sidebandHandle) { + Mutex::Autolock autolock(mLock); + + OMX_INDEXTYPE index; + OMX_STRING name = const_cast( + "OMX.google.android.index.configureVideoTunnelMode"); + + OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index); + if (err != OMX_ErrorNone) { + ALOGE("configureVideoTunnelMode extension is missing!"); + return StatusFromOMXError(err); + } + + ConfigureVideoTunnelModeParams tunnelParams; + tunnelParams.nSize = sizeof(tunnelParams); + tunnelParams.nVersion.s.nVersionMajor = 1; + tunnelParams.nVersion.s.nVersionMinor = 0; + tunnelParams.nVersion.s.nRevision = 0; + tunnelParams.nVersion.s.nStep = 0; + + tunnelParams.nPortIndex = portIndex; + tunnelParams.bTunneled = tunneled; + tunnelParams.nAudioHwSync = audioHwSync; + err = OMX_SetParameter(mHandle, index, &tunnelParams); + if (err != OMX_ErrorNone) { + ALOGE("configureVideoTunnelMode failed! (err %d).", err); + return UNKNOWN_ERROR; + } + + err = OMX_GetParameter(mHandle, index, &tunnelParams); + if (err != OMX_ErrorNone) { + ALOGE("GetVideoTunnelWindow failed! (err %d).", err); + return UNKNOWN_ERROR; + } + if (sidebandHandle) { + *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow; + } + + return err; +} + status_t OMXNodeInstance::useBuffer( OMX_U32 portIndex, const sp ¶ms, OMX::buffer_id *buffer) { -- cgit v1.1